openapi: 3.0.3
info:
  title: SKU.io API
  description: 'SKU.io is an inventory management platform for multichannel ecommerce
    brands.


    ## Authentication


    SKU.io uses **Personal Access Tokens (PATs)** for API authentication.


    1. Log in to your SKU.io account

    2. Go to **Settings → Developer → Personal Access Tokens**

    3. Create a named token with the scopes you need

    4. Use it as a Bearer token in the `Authorization` header


    ```

    Authorization: Bearer <your-token>

    ```'
  version: 1.0.0
  contact:
    name: SKU.io Support
    url: https://sku.io
servers:
- url: https://{tenant}.sku.io
  description: Production
  variables:
    tenant:
      default: app
      description: Your SKU.io subdomain
components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: Personal Access Token from Settings → Developer → Personal Access
        Tokens
security:
- bearerAuth: []
tags:
- name: 17TRACK
- name: Accounting
- name: Financials
- name: Bills
- name: Amortization Schedules
- name: Financial Line Types
- name: Cost Categories
- name: Payment Terms
- name: Ledger (Accounting v2)
- name: Configuration
- name: Authentication
- name: Users
- name: Roles & Permissions
- name: Feature Flags
- name: Alerts
- name: Jobs & Logs
- name: Integration Instances
- name: Misc
- name: FIFO Layers
- name: Data Imports
- name: Customers
- name: Settings
- name: Tracked Job Logs
- name: Suppliers
- name: Warehouses
- name: Reference Data (Read-Only)
- name: Inventory Adjustments
- name: Inventory Movements
- name: Listings
- name: Sales Credits
- name: Reporting
- name: Product Listings (V2)
- name: Dashboard
- name: Tags
- name: Subscriptions
- name: PDF Templates
- name: UI Utilities
- name: Horizon
- name: Workflows
- name: Workflow Actions
- name: Workflow Executions
- name: Workflow Node Types
- name: Workflow Templates
- name: Workflow Credentials
- name: BigCommerce
- name: Card on File
- name: Stores
- name: Sales Channels
- name: Channel Partners
- name: Store Email Templates
- name: Sales Channel Product Templates
- name: Sales Channel Listing Profiles
- name: Sub Sales Channels
- name: Sales Reps
- name: Custom Report Builder
- name: eBay
- name: Faire
- name: Gift Cards
- name: House Accounts
- name: Export
- name: Data Feeds
- name: Inventory Intelligence
- name: Inventory Expiry & Shelf-Life
- name: Amazon
- name: Shopify
- name: WooCommerce
- name: Walmart
- name: Magento
- name: TikTok Shop
- name: Temu
- name: Square
- name: Magento 1
- name: Shipfusion
- name: ShipHero
- name: ShipStation
- name: Veracore
- name: 3PL
- name: Trackstar
- name: Starshipit
- name: API Shipping Provider
- name: Shippit
- name: Odoo 3PL
- name: QuickBooks Online
- name: Xero
- name: Stripe
- name: Google Calendar
- name: Google Sheets
- name: Airtable
- name: Products
- name: Organization
- name: Pricing
- name: Custom Fields
- name: CSV Templates
- name: Product Listings
- name: Inventory
- name: Adjustments & Transfers
- name: Stock Takes
- name: Assemblies
- name: Initial Inventory
- name: Costing
- name: Product Pro Forma
- name: Merchandise Planning
- name: Serial Numbers
- name: Landed Cost Breakdown
- name: Loyalty
- name: OAuth
- name: Connection
- name: Transactions
- name: Orders
- name: Shipments
- name: Inventory Sources (MSI)
- name: Warehouse Mappings
- name: Shipping Method Mappings
- name: Payment Method Mappings
- name: BOMs
- name: Manufacturing Orders
- name: MO Operations
- name: Outsourced Production
- name: Simple Assembly
- name: Work Centers
- name: Contractors
- name: Units of Measure
- name: Scheduler
- name: Demand Suggestions
- name: Lots
- name: Lot Genealogy
- name: MRP Planning
- name: Sales Orders
- name: Sales Order Lines
- name: Fulfillments
- name: Merged Shipments
- name: Channel Refunds
- name: Returns & RMAs
- name: Discount Codes
- name: Purchase Orders
- name: Purchase Invoices
- name: Vendor Returns
- name: Purchase Receipts
- name: Purchase Order Shipments
- name: Inbound Shipments
- name: Sales Order OCR
- name: Purchase Invoice OCR
- name: Landed Cost Invoice OCR
- name: Document Inbox
- name: Documents
- name: Fulfillment Orders
- name: Line Decorations
- name: Decoration Orders
- name: Artwork
- name: Decoration Cost Rules
- name: Decoration Methods
- name: Decoration Placements
- name: Quotes
- name: POS / Register
- name: Pick Lists
- name: Report Templates
- name: Movement Composer
- name: Product Import
- name: Vendor Credits
- name: Vendor Deposits
- name: Webhooks
paths:
  /api/integrations/17track/test:
    post:
      tags:
      - 17TRACK
      summary: Test Connection
      description: 'Validate a 17TRACK API key WITHOUT persisting an instance — powers
        the connect-modal `Test Connection` button.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Under the hood the supplied key is sent to 17TRACK''s `/getquota` endpoint;
        the response reports the quota so the UI can warn before connecting.


        **Required Fields:**

        - `api_key` — 17TRACK API key (string, 8–255 chars)


        **Responses:**

        - `200 OK` — key is valid, returns the live quota

        - `422 Unprocessable Entity` with `code: invalid_key` — 17TRACK rejected the
        key (auth error)

        - `422 Unprocessable Entity` with `code: api_error` — 17TRACK API returned
        a non-auth error (rate-limited, upstream failure, etc.)'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                api_key:
                  type: string
              example:
                api_key: sk_17track_live_xxxxxxxxxxxxxxxxxxxx
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      quota:
                        type: object
                        properties:
                          used:
                            type: integer
                          total:
                            type: integer
                          remaining:
                            type: integer
                  message:
                    type: string
                example:
                  data:
                    quota:
                      used: 142
                      total: 1000
                      remaining: 858
                  message: Connection successful
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 422 Invalid API Key
                  value:
                    message: Invalid API key
                    code: invalid_key
                example-1:
                  summary: 422 Validation Error
                  value:
                    message: The api key field must be at least 8 characters.
                    errors:
                      api_key:
                      - The api key field must be at least 8 characters.
        '429': &id001
          description: Rate limited — platform limit is 1,000 requests/min; individual
            tokens may carry lower limits. Honor the `Retry-After` header before retrying.
            See the [Rate Limits guide](https://developer.sku.io/docs/guides/rate-limits).
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  retry_after_seconds:
                    type: integer
                example:
                  message: Token rate limit exceeded.
                  retry_after_seconds: 42
        '401': &id002
          description: Unauthenticated — the bearer token is missing, revoked, expired,
            or malformed. Never retry automatically; fix the credential. See the [Errors
            guide](https://developer.sku.io/docs/guides/errors).
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Unauthenticated.
        '403': &id003
          description: Forbidden — the token lacks a required scope, the endpoint
            is not available to API tokens, or the user behind the token lacks the
            permission. A human must adjust the token scopes or user permissions;
            do not retry.
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  required_scope:
                    type: string
                example:
                  message: 'Token is missing the required scope: orders:write'
                  required_scope: orders:write
      operationId: post-api-integrations-17track-test
  /api/integrations/17track/instances:
    post:
      tags:
      - 17TRACK
      summary: Create 17TRACK Instance
      description: "Persist the singleton 17TRACK instance for this tenant. The `WebhookRoutable`\
        \ trait mints a unique `wh_*` token as part of the create flow — the resulting\
        \ webhook URL is returned in the response so it can be copied into the tenant's\
        \ 17TRACK dashboard.\n\n:::info[Authorization]\nAny valid API token can call\
        \ this endpoint — no specific scope required. [Manage tokens](https://app.sku.io/settings/api).\n\
        :::\n\n**Required Fields:**\n- `name` — Display name (string, max 255 chars)\n\
        - `api_key` — 17TRACK API key (string, 8–255 chars)\n\n**Optional Fields:**\n\
        - `auto_track` — Per-entity auto-track flags (object). When omitted or partial,\
        \ every missing key defaults to `true` (\"all on\" happy path):\n  - `auto_track.sales_order_fulfillments`\
        \ (boolean)\n  - `auto_track.inbound_shipments` (boolean)\n  - `auto_track.warehouse_transfer_shipments`\
        \ (boolean)\n  - `auto_track.rmas` (boolean)\n  - `auto_track.vendor_credit_shipments`\
        \ (boolean)\n\n**Responses:**\n- `201 Created` — Instance persisted; payload\
        \ includes the freshly minted `webhook_url`.\n- `422 Unprocessable Entity`\
        \ — Validation failure OR a 17TRACK instance already exists for this tenant\
        \ (the integration is a singleton).\n\n**Sales-channel scoping (`auto_track_channels`)**\
        \ — optional. `default` is `all` (track everything not explicitly disabled)\
        \ or `none` (track nothing until explicitly enabled). `channels` is an optional\
        \ object keyed by sales-channel id; each entry may carry a boolean `enabled`\
        \ flag and/or a `sub_channels` object keyed by sub-channel id (booleans).\
        \ Resolution is most-specific-first: a `sub_channels` override wins, then\
        \ the channel `enabled` flag, then `default`. Fulfillment type is modeled\
        \ as a sub-channel (e.g. Amazon FBA vs merchant-fulfilled, or Shopify Web\
        \ vs POS), so excluding high-volume marketplace-fulfilled shipments is just\
        \ disabling that sub-channel. Only sales order fulfillments are scoped; other\
        \ shipment types are unaffected. Validation: `default` must be `all` or `none`\
        \ (422 otherwise)."
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                api_key:
                  type: string
                auto_track:
                  type: object
                  properties:
                    sales_order_fulfillments:
                      type: boolean
                    inbound_shipments:
                      type: boolean
                    warehouse_transfer_shipments:
                      type: boolean
                    rmas:
                      type: boolean
                    vendor_credit_shipments:
                      type: boolean
                auto_track_channels:
                  type: object
                  properties:
                    default:
                      type: string
                    channels:
                      type: object
                      properties: {}
              example:
                name: 17TRACK Production
                api_key: sk_17track_live_xxxxxxxxxxxxxxxxxxxx
                auto_track:
                  sales_order_fulfillments: true
                  inbound_shipments: true
                  warehouse_transfer_shipments: true
                  rmas: true
                  vendor_credit_shipments: true
                auto_track_channels:
                  default: all
                  channels: {}
      parameters: []
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      is_automatic_sync_enabled:
                        type: boolean
                      auto_track:
                        type: object
                        properties:
                          sales_order_fulfillments:
                            type: boolean
                          inbound_shipments:
                            type: boolean
                          warehouse_transfer_shipments:
                            type: boolean
                          rmas:
                            type: boolean
                          vendor_credit_shipments:
                            type: boolean
                      auto_track_channels:
                        type: object
                        properties:
                          default:
                            type: string
                          channels:
                            type: object
                            properties: {}
                      webhook_url:
                        type: string
                      quota:
                        type: string
                        nullable: true
                      status_counts:
                        type: string
                        nullable: true
                      last_webhook_at:
                        type: string
                        nullable: true
                      last_event_at:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 1
                    name: 17TRACK Production
                    is_automatic_sync_enabled: true
                    auto_track:
                      sales_order_fulfillments: true
                      inbound_shipments: true
                      warehouse_transfer_shipments: true
                      rmas: true
                      vendor_credit_shipments: true
                    auto_track_channels:
                      default: all
                      channels: {}
                    webhook_url: https://acme.sku.io/webhooks/seventeentrack/wh_aB3cD4eF5gH6iJ7kL8mN9oP
                    quota: null
                    status_counts: null
                    last_webhook_at: null
                    last_event_at: null
                    created_at: '2026-06-18T14:32:00+00:00'
                    updated_at: '2026-06-18T14:32:00+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
        '422': &id005
          description: Validation failed — the body is a field → messages map (Laravel
            shape) or the platform envelope with a stable machine-readable `code`.
            Fix the payload and resubmit.
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      field_name:
                        type: array
                        items:
                          type: string
                example:
                  message: The given data was invalid.
                  errors:
                    field_name:
                    - The field name is required.
      operationId: post-api-integrations-17track-instances
  /api/integrations/17track/instances/{instance}:
    get:
      tags:
      - 17TRACK
      summary: Get 17TRACK Instance
      description: 'Return the 17TRACK instance enriched with the LIVE dashboard summary
        — quota, per-status counts, the webhook URL, and the most recent webhook +
        event timestamps. This is the payload that powers the connect dashboard.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Route-model binding resolves the integer ID against `SeventeenTrackIntegrationInstance`;
        its global scope guarantees only 17TRACK rows resolve here.


        **Response includes:**

        - Instance config (name, auto-sync flag, per-entity auto-track flags, timestamps)

        - `webhook_url` — the unique URL to paste into the 17TRACK dashboard

        - `quota` — live quota from 17TRACK''s `/getquota`

        - `status_counts` — zero-filled map of EVERY `DeliveryStatusEnum` value to
        count (10 buckets)

        - `last_webhook_at` — ISO timestamp of the most recent webhook ingest

        - `last_event_at` — ISO timestamp of the most recent carrier event across
        all rows


        **Responses:**

        - `200 OK` — instance + dashboard summary

        - `404 Not Found` — instance ID does not exist


        **Sales-channel scoping (`auto_track_channels`)** — optional. `default` is
        `all` (track everything not explicitly disabled) or `none` (track nothing
        until explicitly enabled). `channels` is an optional object keyed by sales-channel
        id; each entry may carry a boolean `enabled` flag and/or a `sub_channels`
        object keyed by sub-channel id (booleans). Resolution is most-specific-first:
        a `sub_channels` override wins, then the channel `enabled` flag, then `default`.
        Fulfillment type is modeled as a sub-channel (e.g. Amazon FBA vs merchant-fulfilled,
        or Shopify Web vs POS), so excluding high-volume marketplace-fulfilled shipments
        is just disabling that sub-channel. Only sales order fulfillments are scoped;
        other shipment types are unaffected. Validation: `default` must be `all` or
        `none` (422 otherwise).'
      parameters:
      - name: instance
        in: path
        schema:
          type: integer
        required: true
        description: ID of the 17TRACK integration instance.
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      is_automatic_sync_enabled:
                        type: boolean
                      auto_track:
                        type: object
                        properties:
                          sales_order_fulfillments:
                            type: boolean
                          inbound_shipments:
                            type: boolean
                          warehouse_transfer_shipments:
                            type: boolean
                          rmas:
                            type: boolean
                          vendor_credit_shipments:
                            type: boolean
                      auto_track_channels:
                        type: object
                        properties:
                          default:
                            type: string
                          channels:
                            type: object
                            properties: {}
                      webhook_url:
                        type: string
                      quota:
                        type: object
                        properties:
                          used:
                            type: integer
                          total:
                            type: integer
                          remaining:
                            type: integer
                      status_counts:
                        type: object
                        properties:
                          pending:
                            type: integer
                          info_received:
                            type: integer
                          in_transit:
                            type: integer
                          available_for_pickup:
                            type: integer
                          out_for_delivery:
                            type: integer
                          delivered:
                            type: integer
                          delivery_failure:
                            type: integer
                          exception:
                            type: integer
                          expired:
                            type: integer
                          not_found:
                            type: integer
                      pending_registration_count:
                        type: integer
                      registration_errors:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            count:
                              type: integer
                            last_failed_at:
                              type: string
                      last_webhook_at:
                        type: string
                      last_event_at:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 1
                    name: 17TRACK Production
                    is_automatic_sync_enabled: true
                    auto_track:
                      sales_order_fulfillments: true
                      inbound_shipments: true
                      warehouse_transfer_shipments: true
                      rmas: true
                      vendor_credit_shipments: true
                    auto_track_channels:
                      default: all
                      channels: {}
                    webhook_url: https://acme.sku.io/webhooks/seventeentrack/wh_aB3cD4eF5gH6iJ7kL8mN9oP
                    quota:
                      used: 412
                      total: 1000
                      remaining: 588
                    status_counts:
                      pending: 12
                      info_received: 31
                      in_transit: 184
                      available_for_pickup: 7
                      out_for_delivery: 22
                      delivered: 1043
                      delivery_failure: 4
                      exception: 9
                      expired: 3
                      not_found: 1
                    pending_registration_count: 14
                    registration_errors:
                    - message: Sorry, but due to the policy of carrier 'USPS' (code
                        '21051'), registration is temporarily unavailable. Please
                        complete the quota purchase and configure the 'Special Carriers'
                        before proceeding.
                      count: 14
                      last_failed_at: '2026-06-27T08:55:16+00:00'
                    last_webhook_at: '2026-06-18T14:28:11+00:00'
                    last_event_at: '2026-06-18T14:27:55+00:00'
                    created_at: '2026-06-01T09:00:00+00:00'
                    updated_at: '2026-06-18T14:28:11+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': &id004
          description: Not found — no record with the given identifier (or the route
            does not exist). Verify the ID before retrying.
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: object
                    properties:
                      url:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: array
                  status:
                    type: string
                  message:
                    type: string
                example:
                  errors:
                    url:
                    - message: Not found
                      code: NotFound
                      data: []
                  status: failure
                  message: Not found
      operationId: get-api-integrations-17track-instances-instance
    patch:
      tags:
      - 17TRACK
      summary: Update 17TRACK Instance
      description: 'Patch any combination of `name`, `api_key`, per-entity `auto_track`
        toggles, or the `is_automatic_sync_enabled` flag on the singleton instance.
        All fields are optional; only the keys present in the request body are applied.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Used by the dashboard''s per-entity toggles, the rename action, key rotation,
        and the automatic-sync flip.


        **Optional Fields:**

        - `name` — string, max 255 chars

        - `api_key` — string, 8–255 chars (key rotation)

        - `auto_track.sales_order_fulfillments` — boolean

        - `auto_track.inbound_shipments` — boolean

        - `auto_track.warehouse_transfer_shipments` — boolean

        - `auto_track.rmas` — boolean

        - `auto_track.vendor_credit_shipments` — boolean

        - `is_automatic_sync_enabled` — boolean (global polling/sync kill switch)


        **Responses:**

        - `200 OK` — returns the updated instance (without the live dashboard summary;
        call `GET` to re-hydrate it)

        - `422 Unprocessable Entity` — validation failure


        **Alert & side-effect settings (all optional):**

        - `side_effects.vendor_credit_shipment_auto_delivered` (boolean, default true)
        — auto-set the vendor credit shipment''s status to Delivered when the carrier
        confirms delivery

        - `side_effects.inbound_shipment_arrival_alert` (boolean, default true) —
        in-app admin alert "package delivered — ready to receive" for inbound shipments

        - `side_effects.rma_arrival_alert` (boolean, default true) — in-app admin
        alert "package delivered — ready to inspect" for RMAs

        - `quota_alert_threshold` (integer 1–99, default 80) — quota usage % at which
        admins get a warning alert; a second high-priority alert always fires at 100%
        (exhausted). Changing the threshold re-arms the alert state machine.


        The instance resource now also returns `side_effects`, `quota_alert_threshold`,
        and a `transit` analytics block (avg days in transit + on-time-vs-ETA rate
        for rows delivered in the last 90 days, overall and per carrier).


        **Sales-channel scoping (`auto_track_channels`)** — optional. `default` is
        `all` (track everything not explicitly disabled) or `none` (track nothing
        until explicitly enabled). `channels` is an optional object keyed by sales-channel
        id; each entry may carry a boolean `enabled` flag and/or a `sub_channels`
        object keyed by sub-channel id (booleans). Resolution is most-specific-first:
        a `sub_channels` override wins, then the channel `enabled` flag, then `default`.
        Fulfillment type is modeled as a sub-channel (e.g. Amazon FBA vs merchant-fulfilled,
        or Shopify Web vs POS), so excluding high-volume marketplace-fulfilled shipments
        is just disabling that sub-channel. Only sales order fulfillments are scoped;
        other shipment types are unaffected. Validation: `default` must be `all` or
        `none` (422 otherwise).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                api_key:
                  type: string
                is_automatic_sync_enabled:
                  type: boolean
                auto_track:
                  type: object
                  properties:
                    sales_order_fulfillments:
                      type: boolean
                    inbound_shipments:
                      type: boolean
                    warehouse_transfer_shipments:
                      type: boolean
                    rmas:
                      type: boolean
                    vendor_credit_shipments:
                      type: boolean
                auto_track_channels:
                  type: object
                  properties:
                    default:
                      type: string
                    channels:
                      type: object
                      properties:
                        '3':
                          type: object
                          properties:
                            sub_channels:
                              type: object
                              properties:
                                '31':
                                  type: boolean
                                '32':
                                  type: boolean
                        '5':
                          type: object
                          properties:
                            enabled:
                              type: boolean
                side_effects:
                  type: object
                  properties:
                    vendor_credit_shipment_auto_delivered:
                      type: boolean
                    inbound_shipment_arrival_alert:
                      type: boolean
                    rma_arrival_alert:
                      type: boolean
                quota_alert_threshold:
                  type: integer
              example:
                name: My 17TRACK
                api_key: ABCDEF1234567890
                is_automatic_sync_enabled: true
                auto_track:
                  sales_order_fulfillments: true
                  inbound_shipments: true
                  warehouse_transfer_shipments: true
                  rmas: true
                  vendor_credit_shipments: true
                auto_track_channels:
                  default: none
                  channels:
                    '3':
                      sub_channels:
                        '31': false
                        '32': true
                    '5':
                      enabled: true
                side_effects:
                  vendor_credit_shipment_auto_delivered: true
                  inbound_shipment_arrival_alert: true
                  rma_arrival_alert: true
                quota_alert_threshold: 80
      parameters:
      - name: instance
        in: path
        schema:
          type: integer
        required: true
        description: ID of the 17TRACK integration instance.
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      is_automatic_sync_enabled:
                        type: boolean
                      auto_track:
                        type: object
                        properties:
                          sales_order_fulfillments:
                            type: boolean
                          inbound_shipments:
                            type: boolean
                          warehouse_transfer_shipments:
                            type: boolean
                          rmas:
                            type: boolean
                          vendor_credit_shipments:
                            type: boolean
                      auto_track_channels:
                        type: object
                        properties:
                          default:
                            type: string
                          channels:
                            type: object
                            properties:
                              '3':
                                type: object
                                properties:
                                  sub_channels:
                                    type: object
                                    properties:
                                      '31':
                                        type: boolean
                                      '32':
                                        type: boolean
                              '5':
                                type: object
                                properties:
                                  enabled:
                                    type: boolean
                      webhook_url:
                        type: string
                        nullable: true
                      quota:
                        type: string
                        nullable: true
                      status_counts:
                        type: string
                        nullable: true
                      last_webhook_at:
                        type: string
                        nullable: true
                      last_event_at:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 1
                    name: 17TRACK Production (Updated)
                    is_automatic_sync_enabled: true
                    auto_track:
                      sales_order_fulfillments: true
                      inbound_shipments: false
                      warehouse_transfer_shipments: true
                      rmas: true
                      vendor_credit_shipments: true
                    auto_track_channels:
                      default: none
                      channels:
                        '3':
                          sub_channels:
                            '31': false
                            '32': true
                        '5':
                          enabled: true
                    webhook_url: null
                    quota: null
                    status_counts: null
                    last_webhook_at: null
                    last_event_at: null
                    created_at: '2026-06-01T09:00:00+00:00'
                    updated_at: '2026-06-18T14:35:42+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: patch-api-integrations-17track-instances-instance
    delete:
      tags:
      - 17TRACK
      summary: Disconnect 17TRACK Instance
      description: 'Disconnect 17TRACK. Per the PRD edge-case spec:

        - Historical tracking rows are retained (read-only history is preserved).

        - Currently-active rows are stamped `stopped_at = now()` so polling stops.

        - The webhook token row in the central registry is removed.

        - The integration instance itself is deleted.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Returns `204 No Content` on success.'
      parameters:
      - name: instance
        in: path
        schema:
          type: integer
        required: true
        description: ID of the 17TRACK integration instance.
        example: '1'
      responses:
        '204':
          description: No Content
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties: {}
                example: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-integrations-17track-instances-instance
  /api/integrations/17track/instances/{instance}/trackable-channels:
    get:
      tags:
      - 17TRACK
      summary: Get Trackable Channels
      description: 'List every connected sales channel together with its sub-channels.
        17TRACK auto-tracking is scoped per (sales channel, sub-channel) pair — fulfillment
        type (e.g. Amazon FBA vs merchant-fulfilled, or Shopify Web vs POS) is represented
        as a sub-channel. Channels with no sub-channels are tracked at the channel
        level and return an empty `sub_channels` array.


        Requires a Bearer token.'
      parameters:
      - name: instance
        in: path
        schema:
          type: integer
        required: true
        description: ID of the 17TRACK integration instance.
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        platform:
                          type: string
                        icon_url:
                          type: string
                        sub_channels:
                          type: array
                          items:
                            type: object
                            properties:
                              id:
                                type: integer
                              name:
                                type: string
                              external_identifier:
                                type: string
                example:
                  data:
                  - id: 3
                    name: Amazon US
                    platform: Amazon
                    icon_url: /images/integrations/icons/amazon.svg
                    sub_channels:
                    - id: 31
                      name: FBA
                      external_identifier: FBA
                    - id: 32
                      name: MFN
                      external_identifier: MFN
                  - id: 5
                    name: Shopify Main Store
                    platform: Shopify
                    icon_url: /images/integrations/icons/shopify.svg
                    sub_channels:
                    - id: 40
                      name: Web
                      external_identifier: web
                    - id: 41
                      name: Pos
                      external_identifier: pos
                  - id: 7
                    name: eBay Store
                    platform: Ebay
                    icon_url: /images/integrations/icons/ebay.svg
                    sub_channels: []
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-integrations-17track-instances-instance-trackable-channels
  /api/integrations/17track/instances/{instance}/trackings:
    get:
      tags:
      - 17TRACK
      summary: List Instance Trackings
      description: 'Paginated list of shipment_trackings rows scoped to a single 17TRACK
        integration instance. Powers the "Trackings" sub-page of the 17TRACK integration
        UI.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Filters / sorts / `per_page` are read directly from the request via Spatie
        QueryBuilder.


        **Supported filters:**

        - `filter[search]` — substring match on tracking_number

        - `filter[delivery_status]` — comma-separated DeliveryStatusEnum values

        - `filter[carrier_code]` — comma-separated 17TRACK numeric carrier codes

        - `filter[trackable_type]` — comma-separated trackable type slugs OR FQCNs

        - `filter[date_from]`, `filter[date_to]` — m/d/Y, applied to created_at


        **Allowed sorts:** `created_at`, `last_event_at`, `delivered_at` (default:
        `-created_at`).


        **Responses:**

        - `200 OK` — paginated tracking rows

        - `401 Unauthorized` — missing/invalid bearer token

        - `404 Not Found` — instance id does not exist'
      parameters:
      - name: instance
        in: path
        schema:
          type: integer
        required: true
        description: ID of the 17TRACK integration instance.
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        trackable_type:
                          type: string
                        trackable_id:
                          type: integer
                        trackable_label:
                          type: string
                        trackable_url:
                          type: string
                        tracking_number:
                          type: string
                        carrier_code:
                          type: integer
                        carrier_name:
                          type: string
                        delivery_status:
                          type: string
                        delivery_status_label:
                          type: string
                        delivery_status_color:
                          type: string
                        sub_status:
                          type: string
                        latest_event_description:
                          type: string
                        latest_event_location:
                          type: string
                        last_event_at:
                          type: string
                        estimated_delivery_at:
                          type: string
                        delivered_at:
                          type: string
                          nullable: true
                        picked_up_at:
                          type: string
                        registered_at:
                          type: string
                        registration_error:
                          type: string
                          nullable: true
                        stopped_at:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                  links:
                    type: object
                    properties:
                      first:
                        type: string
                      last:
                        type: string
                      prev:
                        type: string
                        nullable: true
                      next:
                        type: string
                  meta:
                    type: object
                    properties:
                      current_page:
                        type: integer
                      from:
                        type: integer
                      last_page:
                        type: integer
                      per_page:
                        type: integer
                      to:
                        type: integer
                      total:
                        type: integer
                      path:
                        type: string
                example:
                  data:
                  - id: 42
                    trackable_type: sales_order_fulfillment
                    trackable_id: 1801
                    trackable_label: SO-1234 / FUL-1801
                    trackable_url: /v2/orders/sales-orders/1234
                    tracking_number: 1Z999AA10123456784
                    carrier_code: 100002
                    carrier_name: UPS
                    delivery_status: in_transit
                    delivery_status_label: In Transit
                    delivery_status_color: blue
                    sub_status: InTransit_CustomsProcessing
                    latest_event_description: Departed UPS facility
                    latest_event_location: Memphis, TN
                    last_event_at: '2026-06-09T13:14:00+00:00'
                    estimated_delivery_at: '2026-06-11T00:00:00+00:00'
                    delivered_at: null
                    picked_up_at: '2026-06-08T20:30:00+00:00'
                    registered_at: '2026-06-08T19:55:00+00:00'
                    registration_error: null
                    stopped_at: null
                    created_at: '2026-06-08T19:55:00+00:00'
                  - id: 43
                    trackable_type: sales_order_fulfillment
                    trackable_id: 1802
                    trackable_label: SO-1235 / FUL-1802
                    trackable_url: /v2/orders/sales-orders/1235
                    tracking_number: '9405550105799029763087'
                    carrier_code: null
                    carrier_name: null
                    delivery_status: pending
                    delivery_status_label: Pending
                    delivery_status_color: grey
                    sub_status: null
                    latest_event_description: null
                    latest_event_location: null
                    last_event_at: null
                    estimated_delivery_at: null
                    delivered_at: null
                    picked_up_at: null
                    registered_at: null
                    registration_error: Sorry, but due to the policy of carrier 'USPS'
                      (code '21051'), registration is temporarily unavailable. Please
                      complete the quota purchase and configure the 'Special Carriers'
                      before proceeding.
                    stopped_at: null
                    created_at: '2026-06-25T15:18:32+00:00'
                  links:
                    first: https://example.test/api/integrations/17track/instances/1/trackings?page=1
                    last: https://example.test/api/integrations/17track/instances/1/trackings?page=10
                    prev: null
                    next: https://example.test/api/integrations/17track/instances/1/trackings?page=2
                  meta:
                    current_page: 1
                    from: 1
                    last_page: 10
                    per_page: 15
                    to: 15
                    total: 150
                    path: https://example.test/api/integrations/17track/instances/1/trackings
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-integrations-17track-instances-instance-trackings
  /api/integrations/17track/instances/{instance}/webhooks:
    get:
      tags:
      - 17TRACK
      summary: List Instance Webhook Events
      description: 'Paginated audit log of every 17TRACK webhook received for this
        integration instance. One row per inbound webhook, persisted by a background
        job BEFORE processing.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Powers the "Webhooks" sub-page of the 17TRACK integration UI.


        **Supported filters:**

        - `filter[event_type]` — comma-separated 17TRACK event types

        - `filter[result]` — comma-separated outcomes (processed, failed, ignored)

        - `filter[tracking_number]` — substring match on tracking_number

        - `filter[date_from]`, `filter[date_to]` — m/d/Y, applied to received_at


        **Allowed sorts:** `received_at`, `created_at`, `event_type`, `result` (default:
        `-received_at`).


        **Each row includes a precomputed `summary` string** like "In Transit → Delivered".


        **Responses:**

        - `200 OK` — paginated webhook event rows

        - `401 Unauthorized` — missing/invalid bearer token

        - `404 Not Found` — instance id does not exist'
      parameters:
      - name: instance
        in: path
        schema:
          type: integer
        required: true
        description: ID of the 17TRACK integration instance.
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        received_at:
                          type: string
                        event_type:
                          type: string
                        tracking_number:
                          type: string
                        status_from:
                          type: string
                        status_to:
                          type: string
                        summary:
                          type: string
                        payload:
                          type: object
                          properties:
                            event:
                              type: string
                            data:
                              type: object
                              properties:
                                number:
                                  type: string
                                carrier:
                                  type: integer
                                track_info:
                                  type: object
                                  properties:
                                    latest_status:
                                      type: object
                                      properties:
                                        status:
                                          type: string
                                        sub_status:
                                          type: string
                        result:
                          type: string
                        error_message:
                          type: string
                          nullable: true
                        processing_duration_ms:
                          type: integer
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  links:
                    type: object
                    properties:
                      first:
                        type: string
                      last:
                        type: string
                      prev:
                        type: string
                        nullable: true
                      next:
                        type: string
                  meta:
                    type: object
                    properties:
                      current_page:
                        type: integer
                      from:
                        type: integer
                      last_page:
                        type: integer
                      per_page:
                        type: integer
                      to:
                        type: integer
                      total:
                        type: integer
                      path:
                        type: string
                example:
                  data:
                  - id: 99
                    integration_instance_id: 1
                    received_at: '2026-06-18T15:42:00+00:00'
                    event_type: TRACKING_UPDATED
                    tracking_number: 1Z999AA10123456784
                    status_from: In Transit
                    status_to: Delivered
                    summary: In Transit → Delivered
                    payload:
                      event: TRACKING_UPDATED
                      data:
                        number: 1Z999AA10123456784
                        carrier: 100002
                        track_info:
                          latest_status:
                            status: Delivered
                            sub_status: Delivered_001
                    result: processed
                    error_message: null
                    processing_duration_ms: 42
                    created_at: '2026-06-18T15:42:00+00:00'
                    updated_at: '2026-06-18T15:42:00+00:00'
                  links:
                    first: https://example.test/api/integrations/17track/instances/1/webhooks?page=1
                    last: https://example.test/api/integrations/17track/instances/1/webhooks?page=5
                    prev: null
                    next: https://example.test/api/integrations/17track/instances/1/webhooks?page=2
                  meta:
                    current_page: 1
                    from: 1
                    last_page: 5
                    per_page: 15
                    to: 15
                    total: 75
                    path: https://example.test/api/integrations/17track/instances/1/webhooks
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-integrations-17track-instances-instance-webhooks
  /api/integrations/17track/instances/{instance}/activity:
    get:
      tags:
      - 17TRACK
      summary: List Instance Activity Log
      description: 'Paginated activity log entries scoped to a single 17TRACK integration
        instance. Surfaces both (1) rows where the instance itself is the activity
        subject (connect / settings update / disconnect) and (2) rows where `properties.integration_instance_id`
        matches (webhook ingest, backfill, quota threshold).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Powers the "Activity" sub-page of the 17TRACK integration UI.


        **Supported filters:**

        - `filter[event_type]` — comma-separated activity event names (Spatie `event`
        column)

        - `filter[causer_id]` — comma-separated user IDs

        - `filter[search]` — substring match on description

        - `filter[date_from]`, `filter[date_to]` — m/d/Y, applied to created_at


        **Allowed sorts:** `created_at`, `event`, `id` (default: `-created_at, -id`).


        **Common event values emitted by the 17TRACK module:**

        - `connected` — Integration connected (causer = user)

        - `updated` — Settings updated (properties.changed_keys)

        - `disconnected` — Integration disconnected

        - `webhook_processed` / `webhook_failed` — per webhook ingest

        - `backfill_started` / `backfill_completed` — historical backfill job

        - `quota_exceeded` — quota threshold reached (no causer)


        **Responses:**

        - `200 OK` — paginated activity rows

        - `401 Unauthorized` — missing/invalid bearer token

        - `404 Not Found` — instance id does not exist'
      parameters:
      - name: instance
        in: path
        schema:
          type: integer
        required: true
        description: ID of the 17TRACK integration instance.
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        event:
                          type: string
                        description:
                          type: string
                        causer:
                          type: string
                          nullable: true
                        properties:
                          type: object
                          properties:
                            integration_instance_id:
                              type: integer
                            event_type:
                              type: string
                            tracking_number:
                              type: string
                            updated:
                              type: integer
                            status_from:
                              type: string
                            status_to:
                              type: string
                        created_at:
                          type: string
                        occurred_at_human:
                          type: string
                  links:
                    type: object
                    properties:
                      first:
                        type: string
                      last:
                        type: string
                      prev:
                        type: string
                        nullable: true
                      next:
                        type: string
                  meta:
                    type: object
                    properties:
                      current_page:
                        type: integer
                      from:
                        type: integer
                      last_page:
                        type: integer
                      per_page:
                        type: integer
                      to:
                        type: integer
                      total:
                        type: integer
                      path:
                        type: string
                example:
                  data:
                  - id: 512
                    event: webhook_processed
                    description: Webhook processed
                    causer: null
                    properties:
                      integration_instance_id: 1
                      event_type: TRACKING_UPDATED
                      tracking_number: 1Z999AA10123456784
                      updated: 1
                      status_from: In Transit
                      status_to: Delivered
                    created_at: '2026-06-18T15:42:00+00:00'
                    occurred_at_human: 2 minutes ago
                  - id: 511
                    event: updated
                    description: Settings updated
                    causer:
                      id: 5
                      name: Operations Lead
                      email: ops@example.com
                    properties:
                      integration_instance_id: 1
                      changed_keys:
                      - auto_track
                      - name
                    created_at: '2026-06-18T14:10:00+00:00'
                    occurred_at_human: 1 hour ago
                  links:
                    first: https://example.test/api/integrations/17track/instances/1/activity?page=1
                    last: https://example.test/api/integrations/17track/instances/1/activity?page=20
                    prev: null
                    next: https://example.test/api/integrations/17track/instances/1/activity?page=2
                  meta:
                    current_page: 1
                    from: 1
                    last_page: 20
                    per_page: 15
                    to: 15
                    total: 300
                    path: https://example.test/api/integrations/17track/instances/1/activity
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-integrations-17track-instances-instance-activity
  /api/shipment-trackings:
    get:
      tags:
      - 17TRACK
      summary: List Shipment Trackings
      description: 'Paginated cross-entity listing of shipment tracking rows. Powers
        the Delivery Exceptions view, the global Trackings table, and per-entity filtered
        subsets.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Filters / sorts / `per_page` are read directly from the request by the repository
        per the Spatie QueryBuilder pagination idiom.


        **Allowed filters (`filter[...]`):**

        - `delivery_status` — comma-separated `DeliveryStatusEnum` values

        - `trackable_type` — comma-separated friendly slugs (see query param description
        for the full alias list)

        - `search` — substring match on `tracking_number`

        - `date_from` / `date_to` — `m/d/Y` bounds on `last_event_at` (app timezone)

        - `stalled` — `1` for `in_transit` rows whose last event is >7 days old

        - `integration_instance_id` — exact match


        **Allowed sorts:** `id`, `created_at`, `last_event_at`, `delivery_status`.
        Prefix with `-` for DESC.


        **The canonical Delivery Exceptions query:**

        ```

        ?filter[delivery_status]=exception,delivery_failure,expired&filter[stalled]=1

        ```

        These statuses are the ones flagged by `DeliveryStatusEnum::isException`;
        `stalled=1` adds in_transit rows that have stopped moving.


        **Response shape:** Standard Laravel `LengthAwarePaginator` JSON with `data[]`,
        `current_page`, `last_page`, `per_page`, `total`, `from`, `to`, `*_page_url`,
        `path`, `links`. Each row in `data[]` is shaped as a shipment tracking object.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        trackable_type:
                          type: string
                        trackable_id:
                          type: integer
                        trackable_label:
                          type: string
                        trackable_url:
                          type: string
                        tracking_number:
                          type: string
                        carrier_code:
                          type: integer
                        carrier_name:
                          type: string
                        delivery_status:
                          type: string
                        delivery_status_label:
                          type: string
                        delivery_status_color:
                          type: string
                        sub_status:
                          type: string
                        latest_event_description:
                          type: string
                        latest_event_location:
                          type: string
                        last_event_at:
                          type: string
                        estimated_delivery_at:
                          type: string
                          nullable: true
                        delivered_at:
                          type: string
                          nullable: true
                        registered_at:
                          type: string
                        stopped_at:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                  first_page_url:
                    type: string
                  last_page_url:
                    type: string
                  next_page_url:
                    type: string
                    nullable: true
                  prev_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  links:
                    type: array
                    items:
                      type: object
                      properties:
                        url:
                          type: string
                          nullable: true
                        label:
                          type: string
                        active:
                          type: boolean
                example:
                  data:
                  - id: 4821
                    trackable_type: sales_order_fulfillment
                    trackable_id: 9132
                    trackable_label: SO-7411 / FUL-9132
                    trackable_url: /v2/orders/sales-orders/7411
                    tracking_number: 1Z999AA10123456784
                    carrier_code: 100002
                    carrier_name: UPS
                    delivery_status: exception
                    delivery_status_label: Exception
                    delivery_status_color: error
                    sub_status: Exception_Other
                    latest_event_description: Customs clearance delayed — documentation
                      required
                    latest_event_location: Cincinnati, OH, US
                    last_event_at: '2026-06-15T08:12:00+00:00'
                    estimated_delivery_at: null
                    delivered_at: null
                    registered_at: '2026-06-12T16:04:21+00:00'
                    stopped_at: null
                    created_at: '2026-06-12T15:58:00+00:00'
                  - id: 4819
                    trackable_type: inbound_shipment
                    trackable_id: 312
                    trackable_label: INB-2026-0312
                    trackable_url: /v2/inbound-shipments/312
                    tracking_number: '9400111899223345678901'
                    carrier_code: 21051
                    carrier_name: USPS
                    delivery_status: delivery_failure
                    delivery_status_label: Delivery Failure
                    delivery_status_color: orange
                    sub_status: DeliveryFailure_NoBody
                    latest_event_description: Delivery attempted — no one available
                      to sign
                    latest_event_location: San Francisco, CA, US
                    last_event_at: '2026-06-17T19:44:00+00:00'
                    estimated_delivery_at: '2026-06-18T00:00:00+00:00'
                    delivered_at: null
                    registered_at: '2026-06-10T11:02:00+00:00'
                    stopped_at: null
                    created_at: '2026-06-10T11:00:00+00:00'
                  - id: 4775
                    trackable_type: sales_order_fulfillment
                    trackable_id: 9001
                    trackable_label: SO-7388 / FUL-9001
                    trackable_url: /v2/orders/sales-orders/7388
                    tracking_number: LX123456789CN
                    carrier_code: 3011
                    carrier_name: China Post
                    delivery_status: expired
                    delivery_status_label: Expired
                    delivery_status_color: grey-darken-2
                    sub_status: null
                    latest_event_description: No tracking events in 60+ days — tracking
                      expired
                    latest_event_location: null
                    last_event_at: '2026-04-10T03:21:00+00:00'
                    estimated_delivery_at: null
                    delivered_at: null
                    registered_at: '2026-04-08T09:14:00+00:00'
                    stopped_at: '2026-06-09T03:21:00+00:00'
                    created_at: '2026-04-08T09:12:00+00:00'
                  current_page: 1
                  last_page: 1
                  per_page: 15
                  total: 3
                  from: 1
                  to: 3
                  first_page_url: https://acme.sku.io/api/shipment-trackings?page=1
                  last_page_url: https://acme.sku.io/api/shipment-trackings?page=1
                  next_page_url: null
                  prev_page_url: null
                  path: https://acme.sku.io/api/shipment-trackings
                  links:
                  - url: null
                    label: '&laquo; Previous'
                    active: false
                  - url: https://acme.sku.io/api/shipment-trackings?page=1
                    label: '1'
                    active: true
                  - url: null
                    label: Next &raquo;
                    active: false
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-shipment-trackings
  /api/shipment-trackings/{tracking}:
    get:
      tags:
      - 17TRACK
      summary: Get Shipment Tracking
      description: 'Single tracking row with the FULL event timeline + integration
        instance descriptor. Powers the per-row timeline detail view in the Delivery
        Exceptions view and on entity detail pages.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Response adds the following on top of the listing shape:

        - `events` — ordered array of carrier events (`events_payload` JSON column)

        - `registration_error` — last registration error string from 17TRACK if any

        - `integration_instance` — the parent instance `{ id, name }`


        **Responses:**

        - `200 OK` — detail payload

        - `404 Not Found` — tracking ID does not exist'
      parameters:
      - name: tracking
        in: path
        schema:
          type: integer
        required: true
        description: ID of the shipment tracking row.
        example: '4821'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      trackable_type:
                        type: string
                      trackable_id:
                        type: integer
                      trackable_label:
                        type: string
                      trackable_url:
                        type: string
                      tracking_number:
                        type: string
                      carrier_code:
                        type: integer
                      carrier_name:
                        type: string
                      delivery_status:
                        type: string
                      delivery_status_label:
                        type: string
                      delivery_status_color:
                        type: string
                      sub_status:
                        type: string
                      latest_event_description:
                        type: string
                      latest_event_location:
                        type: string
                      last_event_at:
                        type: string
                      estimated_delivery_at:
                        type: string
                        nullable: true
                      delivered_at:
                        type: string
                        nullable: true
                      registered_at:
                        type: string
                      stopped_at:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      events:
                        type: array
                        items:
                          type: object
                          properties:
                            time_iso:
                              type: string
                            location:
                              type: string
                            description:
                              type: string
                            stage:
                              type: string
                            sub_status:
                              type: string
                      registration_error:
                        type: string
                        nullable: true
                      integration_instance:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                example:
                  data:
                    id: 4821
                    trackable_type: sales_order_fulfillment
                    trackable_id: 9132
                    trackable_label: SO-7411 / FUL-9132
                    trackable_url: /v2/orders/sales-orders/7411
                    tracking_number: 1Z999AA10123456784
                    carrier_code: 100002
                    carrier_name: UPS
                    delivery_status: exception
                    delivery_status_label: Exception
                    delivery_status_color: error
                    sub_status: Exception_Other
                    latest_event_description: Customs clearance delayed — documentation
                      required
                    latest_event_location: Cincinnati, OH, US
                    last_event_at: '2026-06-15T08:12:00+00:00'
                    estimated_delivery_at: null
                    delivered_at: null
                    registered_at: '2026-06-12T16:04:21+00:00'
                    stopped_at: null
                    created_at: '2026-06-12T15:58:00+00:00'
                    events:
                    - time_iso: '2026-06-15T08:12:00+00:00'
                      location: Cincinnati, OH, US
                      description: Customs clearance delayed — documentation required
                      stage: Exception
                      sub_status: Exception_Other
                    - time_iso: '2026-06-14T22:05:00+00:00'
                      location: Louisville, KY, US
                      description: Arrived at facility
                      stage: InTransit
                      sub_status: null
                    - time_iso: '2026-06-13T09:30:00+00:00'
                      location: Cincinnati, OH, US
                      description: Departed origin facility
                      stage: InTransit
                      sub_status: null
                    - time_iso: '2026-06-12T16:08:00+00:00'
                      location: null
                      description: Shipper created label
                      stage: InfoReceived
                      sub_status: null
                    registration_error: null
                    integration_instance:
                      id: 1
                      name: 17TRACK Production
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shipment-trackings-tracking
  /api/shipment-trackings/{tracking}/refresh:
    post:
      tags:
      - 17TRACK
      summary: Refresh Shipment Tracking
      description: 'On-demand refresh — hits 17TRACK''s `/gettrackinfo` synchronously
        and re-hydrates the local row (events, status, sub_status, estimated_delivery_at,
        etc.). Returns the same shape as `GET /shipment-trackings/{id}` so the timeline
        detail view can swap the payload in-place.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Responses:**

        - `200 OK` — refreshed detail payload (same shape as GET)

        - `422 Unprocessable Entity` with `code: refresh_failed` — 17TRACK API rejected
        the request (quota exceeded, rate-limited, connector failure). The timeline
        detail view surfaces this as a friendly error toast.

        - `404 Not Found` — tracking ID does not exist'
      requestBody:
        content: {}
      parameters:
      - name: tracking
        in: path
        schema:
          type: integer
        required: true
        description: ID of the shipment tracking row to refresh.
        example: '4821'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      trackable_type:
                        type: string
                      trackable_id:
                        type: integer
                      trackable_label:
                        type: string
                      trackable_url:
                        type: string
                      tracking_number:
                        type: string
                      carrier_code:
                        type: integer
                      carrier_name:
                        type: string
                      delivery_status:
                        type: string
                      delivery_status_label:
                        type: string
                      delivery_status_color:
                        type: string
                      sub_status:
                        type: string
                        nullable: true
                      latest_event_description:
                        type: string
                      latest_event_location:
                        type: string
                      last_event_at:
                        type: string
                      estimated_delivery_at:
                        type: string
                      delivered_at:
                        type: string
                        nullable: true
                      registered_at:
                        type: string
                      stopped_at:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      events:
                        type: array
                        items:
                          type: object
                          properties:
                            time_iso:
                              type: string
                            location:
                              type: string
                            description:
                              type: string
                            stage:
                              type: string
                            sub_status:
                              type: string
                              nullable: true
                      registration_error:
                        type: string
                        nullable: true
                      integration_instance:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                example:
                  data:
                    id: 4821
                    trackable_type: sales_order_fulfillment
                    trackable_id: 9132
                    trackable_label: SO-7411 / FUL-9132
                    trackable_url: /v2/orders/sales-orders/7411
                    tracking_number: 1Z999AA10123456784
                    carrier_code: 100002
                    carrier_name: UPS
                    delivery_status: in_transit
                    delivery_status_label: In Transit
                    delivery_status_color: blue
                    sub_status: null
                    latest_event_description: Departed customs facility — documentation
                      accepted
                    latest_event_location: Cincinnati, OH, US
                    last_event_at: '2026-06-18T11:02:00+00:00'
                    estimated_delivery_at: '2026-06-20T00:00:00+00:00'
                    delivered_at: null
                    registered_at: '2026-06-12T16:04:21+00:00'
                    stopped_at: null
                    created_at: '2026-06-12T15:58:00+00:00'
                    events:
                    - time_iso: '2026-06-18T11:02:00+00:00'
                      location: Cincinnati, OH, US
                      description: Departed customs facility — documentation accepted
                      stage: InTransit
                      sub_status: null
                    - time_iso: '2026-06-15T08:12:00+00:00'
                      location: Cincinnati, OH, US
                      description: Customs clearance delayed — documentation required
                      stage: Exception
                      sub_status: Exception_Other
                    registration_error: null
                    integration_instance:
                      id: 1
                      name: 17TRACK Production
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  code:
                    type: string
                example:
                  message: '17TRACK returned an error: quota exceeded.'
                  code: refresh_failed
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-shipment-trackings-tracking-refresh
  /api/shipment-trackings/register:
    post:
      tags:
      - 17TRACK
      summary: Register Shipment Tracking
      description: 'Manual `Track this shipment` trigger from an entity detail page.
        Resolves the entity, creates a pending `shipment_trackings` row via the manager,
        and kicks off a background job so the row gets pushed to 17TRACK promptly.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Required Fields:**

        - `trackable_type` — friendly slug. One of: `sales_order_fulfillment`, `inbound_shipment`,
        `warehouse_transfer_shipment`, `rma`, `vendor_credit_shipment`

        - `trackable_id` — integer, min 1. The PK of the trackable entity.


        **Responses:**

        - `201 Created` — pending tracking row created (carrier event data not yet
        hydrated; the register job will fill it on the next tick)

        - `404 Not Found` — trackable entity does not exist

        - `422 Unprocessable Entity` with `code: not_connected` — no active 17TRACK
        instance

        - `422 Unprocessable Entity` with `code: register_skipped` — entity has an
        empty tracking number, OR auto-track is disabled for this entity type


        This manual action bypasses the `auto_track_channels` sales-channel scoping
        — an explicit request to track one shipment always registers it, even if its
        channel is excluded from automatic tracking.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                trackable_type:
                  type: string
                trackable_id:
                  type: integer
              example:
                trackable_type: sales_order_fulfillment
                trackable_id: 9132
      parameters: []
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      trackable_type:
                        type: string
                      trackable_id:
                        type: integer
                      trackable_label:
                        type: string
                      trackable_url:
                        type: string
                      tracking_number:
                        type: string
                      carrier_code:
                        type: string
                        nullable: true
                      carrier_name:
                        type: string
                        nullable: true
                      delivery_status:
                        type: string
                      delivery_status_label:
                        type: string
                      delivery_status_color:
                        type: string
                      sub_status:
                        type: string
                        nullable: true
                      latest_event_description:
                        type: string
                        nullable: true
                      latest_event_location:
                        type: string
                        nullable: true
                      last_event_at:
                        type: string
                        nullable: true
                      estimated_delivery_at:
                        type: string
                        nullable: true
                      delivered_at:
                        type: string
                        nullable: true
                      registered_at:
                        type: string
                        nullable: true
                      stopped_at:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                example:
                  data:
                    id: 4822
                    trackable_type: sales_order_fulfillment
                    trackable_id: 9132
                    trackable_label: SO-7411 / FUL-9132
                    trackable_url: /v2/orders/sales-orders/7411
                    tracking_number: 1Z999AA10123456999
                    carrier_code: null
                    carrier_name: null
                    delivery_status: pending
                    delivery_status_label: Pending
                    delivery_status_color: grey
                    sub_status: null
                    latest_event_description: null
                    latest_event_location: null
                    last_event_at: null
                    estimated_delivery_at: null
                    delivered_at: null
                    registered_at: null
                    stopped_at: null
                    created_at: '2026-06-18T14:40:00+00:00'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 422 Not Connected
                  value:
                    message: 17TRACK is not connected.
                    code: not_connected
                example-1:
                  summary: 422 Register Skipped
                  value:
                    message: Could not register — tracking number is empty or auto-track
                      is disabled for this entity type.
                    code: register_skipped
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-shipment-trackings-register
  /api/shipment-trackings/backfill:
    post:
      tags:
      - 17TRACK
      summary: Backfill Shipment Trackings
      description: 'Kick off a background job that scans recent rows of the selected
        entity types and registers any that have a `tracking_number` but no `shipment_trackings`
        row yet.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Returns the `tracked_job_log_id` which can be polled for progress via the
        tracked job log endpoints.


        **Optional Fields:**

        - `entity_types` — array of strings. Defaults to all five. Each value must
        be one of: `sales_order_fulfillments`, `inbound_shipments`, `warehouse_transfer_shipments`,
        `rmas`, `vendor_credit_shipments`.

        - `since_days` — integer, 1–365. Defaults to 30. Look-back window in days.


        **Responses:**

        - `200 OK` — backfill dispatched; payload contains `tracked_job_log_id`

        - `422 Unprocessable Entity` with `code: not_connected` — no active 17TRACK
        instance'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                entity_types:
                  type: array
                  items:
                    type: string
                since_days:
                  type: integer
              example:
                entity_types:
                - sales_order_fulfillments
                - inbound_shipments
                - warehouse_transfer_shipments
                - rmas
                - vendor_credit_shipments
                since_days: 30
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 81244
                  message: Backfill started — track progress in the job tray.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  code:
                    type: string
                example:
                  message: 17TRACK is not connected.
                  code: not_connected
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-shipment-trackings-backfill
  /api/shipment-trackings/{tracking}/retrack:
    post:
      tags:
      - 17TRACK
      summary: Re-track Shipment Tracking
      description: 'Re-activate tracking for an expired or stopped number via 17TRACK''s
        `/retrack` endpoint. 17TRACK auto-stops tracking ~30 idle days after the last
        event; this asks it to resume pushing updates.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Only accepted for numbers 17TRACK has stopped following — an actively-tracked
        number is rejected. Each number can be re-tracked ONCE (17TRACK limit -18019905).


        On success the local row''s `stopped_at` is cleared, `delivery_status` resets
        to `pending` (re-entering the polling set), and the row is immediately re-hydrated
        via `/gettrackinfo`.


        **Responses:**

        - `200 OK` — re-hydrated detail payload (same shape as `GET /shipment-trackings/{id}`)

        - `422 Unprocessable Entity` with `code: retrack_failed` — 17TRACK rejected
        the retrack (number still active, retrack already used once, connector failure)

        - `404 Not Found` — tracking ID does not exist'
      requestBody:
        content: {}
      parameters:
      - name: tracking
        in: path
        schema:
          type: integer
        required: true
        description: ID of the expired / stopped shipment tracking row to re-activate.
        example: '4821'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      trackable_type:
                        type: string
                      trackable_id:
                        type: integer
                      trackable_label:
                        type: string
                      trackable_url:
                        type: string
                      tracking_number:
                        type: string
                      carrier_code:
                        type: integer
                      carrier_name:
                        type: string
                      delivery_status:
                        type: string
                      delivery_status_label:
                        type: string
                      delivery_status_color:
                        type: string
                      sub_status:
                        type: string
                        nullable: true
                      latest_event_description:
                        type: string
                      latest_event_location:
                        type: string
                      last_event_at:
                        type: string
                      estimated_delivery_at:
                        type: string
                      delivered_at:
                        type: string
                        nullable: true
                      registered_at:
                        type: string
                      registration_error:
                        type: string
                        nullable: true
                      stopped_at:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      events:
                        type: array
                      integration_instance:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                  message:
                    type: string
                example:
                  data:
                    id: 4821
                    trackable_type: sales_order_fulfillment
                    trackable_id: 9132
                    trackable_label: SO-7411 / FUL-9132
                    trackable_url: /v2/orders/sales-orders/7411
                    tracking_number: 1Z999AA10123456784
                    carrier_code: 100002
                    carrier_name: UPS
                    delivery_status: pending
                    delivery_status_label: Pending
                    delivery_status_color: grey
                    sub_status: null
                    latest_event_description: Departed UPS facility
                    latest_event_location: Memphis, TN
                    last_event_at: '2026-06-09T13:14:00+00:00'
                    estimated_delivery_at: '2026-06-11T00:00:00+00:00'
                    delivered_at: null
                    registered_at: '2026-05-12T16:04:21+00:00'
                    registration_error: null
                    stopped_at: null
                    created_at: '2026-05-12T15:58:00+00:00'
                    events: []
                    integration_instance:
                      id: 3
                      name: 17TRACK
                  message: Re-tracking started — 17TRACK will resume pushing updates
                    for this number.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  code:
                    type: string
                example:
                  message: '17TRACK rejected the re-track request: Retrack is not
                    allowed. You can only retrack stopped number.'
                  code: retrack_failed
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-shipment-trackings-tracking-retrack
  /api/shipment-trackings/{tracking}/change-carrier:
    post:
      tags:
      - 17TRACK
      summary: Change Shipment Tracking Carrier
      description: 'Correct a mis-detected carrier via 17TRACK''s `/changecarrier`
        endpoint and re-hydrate the row under the new carrier. 17TRACK auto-detects
        the carrier from the number format when registering and sometimes picks wrong
        — this fixes it without stopping/re-registering.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        17TRACK caps carrier changes at 5 per number (error -18019807).


        **Request body:**

        - `carrier_code` (integer, required) — 17TRACK numeric carrier key the shipment
        actually ships with. Carriers configured in SKU.io (Settings → Shipping Carriers)
        can carry a `seventeen_track_carrier_code`; the full directory is at https://res.17track.net/asset/carrier/info/apicarrier.all.json.


        On success the local row''s `carrier_code` is updated, `carrier_name` clears
        (re-hydrated on the next `/gettrackinfo`), and the tracking history reloads
        under the new carrier.


        **Responses:**

        - `200 OK` — re-hydrated detail payload

        - `422 Unprocessable Entity` with `code: change_carrier_failed` — 17TRACK
        rejected the change, or validation failed (missing/invalid `carrier_code`)

        - `404 Not Found` — tracking ID does not exist'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                carrier_code:
                  type: integer
              example:
                carrier_code: 21051
      parameters:
      - name: tracking
        in: path
        schema:
          type: integer
        required: true
        description: ID of the shipment tracking row whose carrier was mis-detected.
        example: '4821'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      trackable_type:
                        type: string
                      trackable_id:
                        type: integer
                      trackable_label:
                        type: string
                      trackable_url:
                        type: string
                      tracking_number:
                        type: string
                      carrier_code:
                        type: integer
                      carrier_name:
                        type: string
                      delivery_status:
                        type: string
                      delivery_status_label:
                        type: string
                      delivery_status_color:
                        type: string
                      sub_status:
                        type: string
                        nullable: true
                      latest_event_description:
                        type: string
                      latest_event_location:
                        type: string
                      last_event_at:
                        type: string
                      estimated_delivery_at:
                        type: string
                      delivered_at:
                        type: string
                        nullable: true
                      registered_at:
                        type: string
                      registration_error:
                        type: string
                        nullable: true
                      stopped_at:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      events:
                        type: array
                      integration_instance:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                  message:
                    type: string
                example:
                  data:
                    id: 4821
                    trackable_type: sales_order_fulfillment
                    trackable_id: 9132
                    trackable_label: SO-7411 / FUL-9132
                    trackable_url: /v2/orders/sales-orders/7411
                    tracking_number: 1Z999AA10123456784
                    carrier_code: 100002
                    carrier_name: UPS
                    delivery_status: pending
                    delivery_status_label: Pending
                    delivery_status_color: grey
                    sub_status: null
                    latest_event_description: Departed UPS facility
                    latest_event_location: Memphis, TN
                    last_event_at: '2026-06-09T13:14:00+00:00'
                    estimated_delivery_at: '2026-06-11T00:00:00+00:00'
                    delivered_at: null
                    registered_at: '2026-05-12T16:04:21+00:00'
                    registration_error: null
                    stopped_at: null
                    created_at: '2026-05-12T15:58:00+00:00'
                    events: []
                    integration_instance:
                      id: 3
                      name: 17TRACK
                  message: Re-tracking started — 17TRACK will resume pushing updates
                    for this number.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      carrier_code:
                        type: array
                        items:
                          type: string
                example:
                  message: Select the carrier this shipment actually ships with.
                  errors:
                    carrier_code:
                    - Select the carrier this shipment actually ships with.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-shipment-trackings-tracking-change-carrier
  /api/shipment-trackings/register-parcels:
    post:
      tags:
      - 17TRACK
      summary: Register Parcel Trackings (Multi-Parcel)
      description: 'Register additional parcel tracking numbers against ONE entity
        — the multi-parcel path for shipments split across several cartons (each with
        its own carrier number). The entity''s primary `tracking_number` is registered
        by the save observer; this endpoint covers the remaining boxes so every carton
        tracks independently.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Request body:**

        - `trackable_type` (string, required) — one of `sales_order_fulfillment`,
        `inbound_shipment`, `warehouse_transfer_shipment`, `rma`, `vendor_credit_shipment`

        - `trackable_id` (integer, required) — ID of the entity

        - `tracking_numbers` (string[], required, 1–40 items) — parcel tracking numbers
        to register


        Numbers already tracked for the entity are skipped; garbage values (`n/a`,
        `local pickup`, …) are dropped; new rows are created `pending` and pushed
        via the debounced batch register job. Respects the per-entity auto-track toggle.


        **Responses:**

        - `201 Created` — array of the queued tracking rows

        - `422 Unprocessable Entity` with `code: register_skipped` — every number
        was already tracked / dropped, or auto-track is disabled for this entity type

        - `422 Unprocessable Entity` with `code: not_connected` — 17TRACK is not connected

        - `404 Not Found` — trackable entity does not exist


        This manual action bypasses the `auto_track_channels` sales-channel scoping
        — an explicit request to track one shipment always registers it, even if its
        channel is excluded from automatic tracking.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                trackable_type:
                  type: string
                trackable_id:
                  type: integer
                tracking_numbers:
                  type: array
                  items:
                    type: string
              example:
                trackable_type: sales_order_fulfillment
                trackable_id: 9132
                tracking_numbers:
                - 1Z999AA10123456791
                - 1Z999AA10123456806
      parameters: []
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        trackable_type:
                          type: string
                        trackable_id:
                          type: integer
                        trackable_label:
                          type: string
                        trackable_url:
                          type: string
                        tracking_number:
                          type: string
                        carrier_code:
                          type: string
                          nullable: true
                        carrier_name:
                          type: string
                          nullable: true
                        delivery_status:
                          type: string
                        delivery_status_label:
                          type: string
                        delivery_status_color:
                          type: string
                        sub_status:
                          type: string
                          nullable: true
                        registered_at:
                          type: string
                          nullable: true
                        registration_error:
                          type: string
                          nullable: true
                        stopped_at:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                  message:
                    type: string
                example:
                  data:
                  - id: 4899
                    trackable_type: sales_order_fulfillment
                    trackable_id: 9132
                    trackable_label: SO-7411 / FUL-9132
                    trackable_url: /v2/orders/sales-orders/7411
                    tracking_number: 1Z999AA10123456791
                    carrier_code: null
                    carrier_name: null
                    delivery_status: pending
                    delivery_status_label: Pending
                    delivery_status_color: grey
                    sub_status: null
                    registered_at: null
                    registration_error: null
                    stopped_at: null
                    created_at: '2026-07-03T15:40:00+00:00'
                  message: 2 parcel(s) queued for tracking.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  code:
                    type: string
                example:
                  message: No new parcels to track — every number is already tracked
                    for this entity, or auto-track is disabled for this entity type.
                  code: register_skipped
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-shipment-trackings-register-parcels
  /webhooks/seventeentrack/{webhook_token}:
    post:
      tags:
      - 17TRACK
      summary: 17TRACK Webhook (TRACKING_UPDATED)
      description: "**This endpoint is INCOMING — it is called by 17TRACK, not by\
        \ SKU.io clients. Documented here for reference only.**\n\nFull URL shape:\
        \ `POST /webhooks/seventeentrack/{webhook_token}`. The token in the URL identifies\
        \ the tenant + instance; the `sign` field at the top of the JSON body is an\
        \ HMAC-SHA256 over the request body computed with the instance's API key as\
        \ the HMAC secret — verified by `VerifySeventeenTrackWebhook` middleware before\
        \ the controller runs.\n\n**Envelope (v2.4):**\n```\n{\n  \"event\": \"TRACKING_UPDATED\"\
        \ | \"TRACKING_STOPPED\",\n  \"data\": { ... carrier-event payload ... },\n\
        \  \"sign\": \"<sha256-hex>\"\n}\n```\n\n**Behavior:**\n- Empty body → `200\
        \ { status: 'acknowledged' }` (avoids 17TRACK retry storm).\n- Missing `event`\
        \ key → `200 { status: 'ignored' }`.\n- Valid payload → `200 { status: 'success'\
        \ }` and a background job is dispatched for async ingest. Out-of-order events\
        \ (older `last_event_at` than what's already stored) are dropped inside the\
        \ repository.\n\n**Why always 200?** 17TRACK retries non-2xx responses for\
        \ several hours. Any non-actionable scenario still acks with 200 to avoid\
        \ bogus retry storms."
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                event:
                  type: string
                data:
                  type: object
                  properties:
                    number:
                      type: string
                    carrier:
                      type: integer
                    track_info:
                      type: object
                      properties:
                        latest_status:
                          type: object
                          properties:
                            status:
                              type: string
                            sub_status:
                              type: string
                            sub_status_descr:
                              type: string
                              nullable: true
                        latest_event:
                          type: object
                          properties:
                            time_iso:
                              type: string
                            description:
                              type: string
                            location:
                              type: string
                            stage:
                              type: string
                            sub_status:
                              type: string
                              nullable: true
                        time_metrics:
                          type: object
                          properties:
                            estimated_delivery_date:
                              type: object
                              properties:
                                source:
                                  type: string
                                from:
                                  type: string
                                to:
                                  type: string
                        tracking:
                          type: object
                          properties:
                            providers:
                              type: array
                              items:
                                type: object
                                properties:
                                  events:
                                    type: array
                                    items:
                                      type: object
                                      properties:
                                        time_iso:
                                          type: string
                                        location:
                                          type: string
                                        description:
                                          type: string
                                        stage:
                                          type: string
                sign:
                  type: string
              example:
                event: TRACKING_UPDATED
                data:
                  number: 1Z999AA10123456784
                  carrier: 100002
                  track_info:
                    latest_status:
                      status: InTransit
                      sub_status: InTransit_Other
                      sub_status_descr: null
                    latest_event:
                      time_iso: '2026-06-18T11:02:00+00:00'
                      description: Departed customs facility — documentation accepted
                      location: Cincinnati, OH, US
                      stage: InTransit
                      sub_status: null
                    time_metrics:
                      estimated_delivery_date:
                        source: Carrier
                        from: '2026-06-19'
                        to: '2026-06-20'
                    tracking:
                      providers:
                      - events:
                        - time_iso: '2026-06-18T11:02:00+00:00'
                          location: Cincinnati, OH, US
                          description: Departed customs facility — documentation accepted
                          stage: InTransit
                        - time_iso: '2026-06-15T08:12:00+00:00'
                          location: Cincinnati, OH, US
                          description: Customs clearance delayed — documentation required
                          stage: Exception
                sign: 7a3f1c9b4e2d8f0a6c5e9b1d4f7a2c0e8b5d3f1a9c7e4b2d6f0a8c3e5b1d4f7a
      parameters:
      - name: webhook_token
        in: path
        schema:
          type: string
        required: true
        description: 'Opaque per-instance token minted by the `WebhookRoutable` trait.
          Globally unique across all tenants. Pattern: `wh_[A-Za-z0-9]+`.'
        example: wh_aB3cD4eF5gH6iJ7kL8mN9oP
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 Success
                  value:
                    status: success
                example-1:
                  summary: 200 Ignored (no event)
                  value:
                    status: ignored
                example-2:
                  summary: 200 Acknowledged (no instance)
                  value:
                    status: acknowledged
        '429': *id001
        '404': *id004
        '422': *id005
      security: []
      operationId: post-webhooks-seventeentrack-webhook-token
  /api/accounting/sync-settings:
    get:
      tags:
      - Accounting
      summary: Get Sync Settings
      description: 'Returns the accounting sync settings for the configured integration,
        including per-type sync enable/disable controls and sync start dates.


        :::info[Required scope: `accounting:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      integration_instance_id:
                        type: integer
                      integration_name:
                        type: string
                      sync_controls_by_type:
                        type: object
                        properties:
                          sales_order_invoice:
                            type: object
                            properties:
                              enabled:
                                type: boolean
                              sync_start_date:
                                type: string
                              label:
                                type: string
                          purchase_order_invoice:
                            type: object
                            properties:
                              enabled:
                                type: boolean
                              sync_start_date:
                                type: string
                                nullable: true
                              label:
                                type: string
                          credit_note:
                            type: object
                            properties:
                              enabled:
                                type: boolean
                              sync_start_date:
                                type: string
                                nullable: true
                              label:
                                type: string
                example:
                  data:
                    integration_instance_id: 5
                    integration_name: Xero
                    sync_controls_by_type:
                      sales_order_invoice:
                        enabled: true
                        sync_start_date: '2024-01-01'
                        label: Sales Order Invoice
                      purchase_order_invoice:
                        enabled: true
                        sync_start_date: null
                        label: Purchase Order Invoice
                      credit_note:
                        enabled: false
                        sync_start_date: null
                        label: Credit Note
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: accounting:read
      operationId: get-api-accounting-sync-settings
    put:
      tags:
      - Accounting
      summary: Update Sync Settings
      description: 'Updates the accounting sync settings. Unsubmitted types are preserved
        (partial updates supported).


        :::info[Required scope: `accounting:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token


        sync_controls_by_type keys must be valid AccountingTransactionTypeEnum values.

        Each type: enabled (required boolean) + sync_start_date (nullable date)'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                sync_controls_by_type:
                  type: object
                  properties:
                    sales_order_invoice:
                      type: object
                      properties:
                        enabled:
                          type: boolean
                        sync_start_date:
                          type: string
                    credit_note:
                      type: object
                      properties:
                        enabled:
                          type: boolean
                        sync_start_date:
                          type: string
                          nullable: true
              example:
                sync_controls_by_type:
                  sales_order_invoice:
                    enabled: true
                    sync_start_date: '2024-01-01'
                  credit_note:
                    enabled: false
                    sync_start_date: null
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      integration_instance_id:
                        type: integer
                      integration_name:
                        type: string
                      sync_controls_by_type:
                        type: object
                        properties:
                          sales_order_invoice:
                            type: object
                            properties:
                              enabled:
                                type: boolean
                              sync_start_date:
                                type: string
                              label:
                                type: string
                  message:
                    type: string
                example:
                  data:
                    integration_instance_id: 5
                    integration_name: Xero
                    sync_controls_by_type:
                      sales_order_invoice:
                        enabled: true
                        sync_start_date: '2024-01-01'
                        label: Sales Order Invoice
                  message: Sync settings updated successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: accounting:write
      operationId: put-api-accounting-sync-settings
  /api/accounting/sync-settings/types:
    get:
      tags:
      - Accounting
      summary: Get Transaction Types
      description: 'Returns all available accounting transaction types with their
        human-readable labels.


        :::info[Required scope: `accounting:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        value:
                          type: string
                        label:
                          type: string
                example:
                  data:
                  - value: sales_order_invoice
                    label: Sales Order Invoice
                  - value: purchase_order_invoice
                    label: Purchase Order Invoice
                  - value: credit_note
                    label: Credit Note
                  - value: payment
                    label: Payment
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: accounting:read
      operationId: get-api-accounting-sync-settings-types
  /api/accounting/integration:
    get:
      tags:
      - Accounting
      summary: Get Accounting Integration
      description: 'Returns the currently configured accounting integration instance
        (QBO or Xero).


        :::info[Required scope: `accounting:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: integer
                  integration_id:
                    type: integer
                  name:
                    type: string
                  is_active:
                    type: boolean
                  created_at:
                    type: string
                example:
                  id: 5
                  integration_id: 3
                  name: My Xero
                  is_active: true
                  created_at: '2023-01-01T00:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: accounting:read
      operationId: get-api-accounting-integration
  /api/financials/daily-financials/recalculate:
    post:
      tags:
      - Financials
      summary: Recalculate Daily Financials
      description: 'Triggers recalculation of the specified daily financial summary
        records. For large datasets (using filters), processing is dispatched as a
        background job.


        :::info[Required scope: `reports:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token (Power User access required)


        Request body:

        - ids (array, optional): Array of daily financial summary IDs to recalculate

        - filters (string, optional): Filter string to select records for recalculation
        (triggers background job)'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1500
                - 1501
                - 1502
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 Success - Synchronous
                  value:
                    message: Recalculation successful
                example-1:
                  summary: 200 Success - Background Job
                  value:
                    message: Recalculations processing in the background
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: reports:write
      operationId: post-api-financials-daily-financials-recalculate
  /api/financials/daily-summary/{daily_summary}:
    get:
      tags:
      - Financials
      summary: Get Daily Financial Summary
      description: 'Returns the details of a single daily financial summary record.


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token (Power User access required)'
      parameters:
      - name: daily_summary
        in: path
        schema:
          type: integer
        required: true
        description: Daily financial summary record ID
        example: '1500'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      date:
                        type: string
                      reportable:
                        type: object
                        properties:
                          id:
                            type: integer
                          type:
                            type: string
                          product:
                            type: object
                            properties:
                              id:
                                type: integer
                              sku:
                                type: string
                              brand:
                                type: string
                      quantity:
                        type: integer
                      quantity_returned:
                        type: integer
                      num_orders:
                        type: integer
                      revenue:
                        type: number
                      total_revenue:
                        type: number
                      cost:
                        type: number
                      total_cost:
                        type: number
                      profit:
                        type: number
                      profit_margin:
                        type: number
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 1500
                    date: '2024-01-14'
                    reportable:
                      id: 100
                      type: App\Models\Product
                      product:
                        id: 100
                        sku: SKU-001
                        brand: ACME
                    quantity: 25
                    quantity_returned: 2
                    num_orders: 10
                    revenue: 1250.0
                    total_revenue: 1175.0
                    cost: 500.0
                    total_cost: 460.0
                    profit: 715.0
                    profit_margin: 60.85
                    created_at: '2024-01-14T23:59:59.000000Z'
                    updated_at: '2024-01-15T01:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: reports:read
      operationId: get-api-financials-daily-summary-daily-summary
    put:
      tags:
      - Financials
      summary: Update Daily Financial Summary
      description: 'Updates the specified daily financial summary record.


        :::info[Required scope: `reports:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token (Power User access required)'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties: {}
              example: {}
      parameters:
      - name: daily_summary
        in: path
        schema:
          type: integer
        required: true
        description: Daily financial summary record ID
        example: '1500'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    id: 1500
                  message: Updated successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: reports:write
      operationId: put-api-financials-daily-summary-daily-summary
    delete:
      tags:
      - Financials
      summary: Delete Daily Financial Summary
      description: 'Deletes the specified daily financial summary record.


        :::info[Required scope: `reports:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token (Power User access required)'
      parameters:
      - name: daily_summary
        in: path
        schema:
          type: integer
        required: true
        description: Daily financial summary record ID
        example: '1500'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Deleted successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: reports:write
      operationId: delete-api-financials-daily-summary-daily-summary
  /api/financials/daily-summary:
    post:
      tags:
      - Financials
      summary: Create Daily Financial Summary
      description: 'Creates a new daily financial summary record.


        :::info[Required scope: `reports:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token (Power User access required)'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties: {}
              example: {}
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    id: 1501
                  message: Created successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: reports:write
      operationId: post-api-financials-daily-summary
  /api/financials/summary-by-period:
    get:
      tags:
      - Financials
      summary: Get Financial Summary by Period
      description: 'Returns aggregated financial data (revenue, cost, profit) grouped
        by the specified time period. Used for financial trend charts and reporting
        dashboards.


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token (Power User access required)


        Response: Array of period summaries with:

        - period: The period label (e.g. ''2024-01'', ''Q1 2024'')

        - revenue, cost, profit: Aggregated financial totals

        - num_orders: Total order count for the period'
      parameters:
      - name: period
        in: query
        schema:
          type: string
        description: 'Period grouping (required). Values: daily, weekly, monthly,
          quarterly, yearly'
        example: monthly
      - name: trailing_days
        in: query
        schema:
          type: integer
        description: Number of trailing days to include in the report (optional).
          If omitted, uses all available data.
        example: '90'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        period:
                          type: string
                        revenue:
                          type: number
                        cost:
                          type: number
                        profit:
                          type: number
                        num_orders:
                          type: integer
                  status:
                    type: string
                example:
                  data:
                  - period: 2024-01
                    revenue: 45250.0
                    cost: 18100.0
                    profit: 27150.0
                    num_orders: 182
                  - period: 2023-12
                    revenue: 38900.0
                    cost: 15560.0
                    profit: 23340.0
                    num_orders: 156
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:read
      operationId: get-api-financials-summary-by-period
  /api/financials/products/{product_id}/summary-by-period:
    get:
      tags:
      - Financials
      summary: Get Product Financial Summary by Period
      description: 'Returns financial summary data for a specific product, grouped
        by the specified time period. Used for product-level financial analytics.


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token (Power User access required)


        Response: Array of period summaries with revenue, cost, profit broken down
        for the specific product.'
      parameters:
      - name: period
        in: query
        schema:
          type: string
        description: 'Period grouping (required). Values: daily, weekly, monthly,
          quarterly, yearly'
        example: monthly
      - name: trailing_days
        in: query
        schema:
          type: integer
        description: Number of trailing days to include (optional)
        example: '180'
      - name: product_id
        in: path
        schema:
          type: integer
        required: true
        description: Product ID
        example: '100'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        period:
                          type: string
                        revenue:
                          type: number
                        cost:
                          type: number
                        profit:
                          type: number
                        num_orders:
                          type: integer
                        quantity:
                          type: integer
                  status:
                    type: string
                example:
                  data:
                  - period: 2024-01
                    revenue: 1250.0
                    cost: 500.0
                    profit: 750.0
                    num_orders: 10
                    quantity: 25
                  - period: 2023-12
                    revenue: 980.0
                    cost: 392.0
                    profit: 588.0
                    num_orders: 8
                    quantity: 20
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: reports:read
      operationId: get-api-financials-products-product-id-summary-by-period
  /api/financials/top-products:
    get:
      tags:
      - Financials
      summary: List Top Products by Financial Metric
      description: 'Returns the top-performing products ranked by the specified financial
        metric. Used for dashboard widgets and financial analysis.


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token (Power User access required)


        Response fields per product:

        - product.id, product.name, product.sku, product.image_url

        - product.brand: {id, name} (when available)

        - quantity_sold: Total units sold

        - revenue: Total revenue generated

        - costs: Total cost of goods sold

        - profit: Total profit (revenue - costs)

        - num_orders: Total number of orders'
      parameters:
      - name: metric
        in: query
        schema:
          type: string
        description: 'Metric to rank products by (required). Values: ''revenue'',
          ''profit'''
        example: revenue
      - name: limit
        in: query
        schema:
          type: integer
        description: 'Number of top products to return (optional, default: 10)'
        example: '10'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        product:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            sku:
                              type: string
                            image_url:
                              type: string
                            brand:
                              type: object
                              properties:
                                id:
                                  type: integer
                                name:
                                  type: string
                        quantity_sold:
                          type: integer
                        revenue:
                          type: number
                        costs:
                          type: number
                        profit:
                          type: number
                        num_orders:
                          type: integer
                  status:
                    type: string
                example:
                  data:
                  - product:
                      id: 100
                      name: Widget A
                      sku: SKU-001
                      image_url: https://cdn.example.com/products/sku-001.jpg
                      brand:
                        id: 5
                        name: ACME Brand
                    quantity_sold: 250
                    revenue: 12500.0
                    costs: 5000.0
                    profit: 7500.0
                    num_orders: 100
                  - product:
                      id: 101
                      name: Widget B
                      sku: SKU-002
                      image_url: null
                      brand: null
                    quantity_sold: 180
                    revenue: 9000.0
                    costs: 3600.0
                    profit: 5400.0
                    num_orders: 72
                  status: success
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      metric:
                        type: array
                        items:
                          type: string
                example:
                  message: The selected metric is invalid.
                  errors:
                    metric:
                    - The selected metric is invalid.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:read
      operationId: get-api-financials-top-products
  /api/financials/sales-order-line-financials/recalculate-lines:
    post:
      tags:
      - Financials
      summary: Recalculate Sales Order Line Financials
      description: 'Triggers recalculation of financial data for the specified sales
        order lines. For large datasets (using filters), processing is chunked and
        dispatched as background jobs (10,000 records per chunk).


        :::info[Required scope: `reports:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token (Power User access required)


        Request body:

        - ids (array, optional): Array of sales order line IDs to recalculate

        - filters (string, optional): Filter string to select records for recalculation
        (triggers chunked background jobs)'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 8001
                - 8002
                - 8003
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 Success - Synchronous
                  value:
                    message: Recalculation successful
                example-1:
                  summary: 200 Success - Background Job
                  value:
                    message: Recalculations processing in the background
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: reports:write
      operationId: post-api-financials-sales-order-line-financials-recalculate-lines
  /api/v2/financials/sales-order-lines/export:
    get:
      tags:
      - Financials
      summary: Export Sales Order Line Financials
      description: 'Exports sales order line financials. The endpoint picks one of
        two response modes based on dataset size:


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        1. SYNC (≤ 1,000 rows or scope=current_page) — streams the file inline as
        the response body. Content-Type is text/csv or application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.


        2. QUEUED (> 1,000 rows) — dispatches a background job and returns a JSON
        envelope with the tracked_job_log_id. The frontend should poll the tracked
        job log endpoints; when the job completes the resulting file is fetched via
        the export/download endpoint.


        Authentication: Requires Bearer token (Power User access required).


        Filters and sorts mirror the List Sales Order Line Financials endpoint.


        Exported columns now include an ''Allocation'' column (after ''Revenue Allocated'')
        — ''Cost-corrected'' when the line''s revenue was re-allocated in proportion
        to bundle-group COGS, otherwise ''Document''.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: text/csv
            Content-Disposition:
              schema:
                type: string
                example: attachment; filename="sales-order-financials.csv"
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 Success - Sync (binary blob)
                  value: <binary file — CSV or XLSX>
                example-1:
                  summary: 200 Success - Queued (background job)
                  value:
                    data:
                      tracked_job_log_id: 12345
                      queued: true
                    message: Export started — track progress in the job tray
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:read
      operationId: get-api-v2-financials-sales-order-lines-export
  /api/v2/financials/sales-order-lines/export/download:
    get:
      tags:
      - Financials
      summary: Download Sales Order Line Financials Export
      description: 'Downloads a completed background export produced by Export Sales
        Order Line Financials (queued path). The filename is the one reported in the
        tracked job log''s results.file field.


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token (Power User access required).


        Response is the binary file (CSV or XLSX) with an attachment Content-Disposition
        header. Returns 404 if the file param is empty or the file no longer exists
        on the model-exports disk.'
      parameters:
      - name: file
        in: query
        schema:
          type: string
        description: Filename returned in the completed tracked job's results.file.
          The server basenames this value and serves from the model-exports disk;
          unknown filenames yield 404.
        example: sales-order-financials-2026-05-22-13-00-00.xlsx
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
            Content-Disposition:
              schema:
                type: string
                example: attachment; filename="sales-order-financials-2026-05-22-13-00-00.xlsx"
          content:
            text/plain:
              schema:
                type: string
                example: <binary file>
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Not Found
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:read
      operationId: get-api-v2-financials-sales-order-lines-export-download
  /api/bills/list:
    get:
      tags:
      - Bills
      summary: List Bills
      description: "Paginated landed cost bills listing for the list view (`/v2/purchases/bills`).\
        \ Lists every bill across all three link types (Purchase Order, Warehouse\
        \ Transfer, Inbound Shipment) with computed totals, allocation status, and\
        \ source (OCR vs manual).\n\n:::info[Required scope: `purchase-orders:read`]\n\
        Grant this scope to your token under [Settings → Developer → Personal Access\
        \ Tokens](https://app.sku.io/settings/api).\n:::\n\nUses Spatie QueryBuilder\
        \ with grouped-filter (tree) support.\n\nAuthentication: Requires Bearer token.\
        \ Scope: `purchase-orders` (read/write).\n\n## Pagination\n- `page` — page\
        \ number (default 1)\n- `per_page` — items per page (default 10)\n\n## Sorting\n\
        `sort` — prefix with `-` for descending. Default: `-created_at`.\nAllowed\
        \ sorts: `id`, `invoice_number`, `invoice_date`, `supplier_name`, `supplier_id`,\
        \ `link_type`, `link_reference`, `proration_strategy`, `currency_code`, `currency_rate`,\
        \ `line_count`, `subtotal`, `tax_total`, `grand_total`, `allocated_amount`,\
        \ `unallocated_amount`, `allocation_status`, `created_at`, `updated_at`\n\n\
        ## Search\n`filter[search]` — searches Invoice Number (partial), Bill ID (exact),\
        \ Supplier name, Bill line descriptions, and the linked document reference\
        \ (PO number / transfer reference / shipment reference).\n\n## Advanced filters\n\
        Advanced filters use the `filter[{column}.{operator}]=value` syntax. A bare\
        \ `filter[{column}]=value` acts as an implicit `is`.\n\n**Text columns** (operators:\
        \ contains, does_not_contain, is, is_not, is_one_of, starts_with, does_not_start_with,\
        \ ends_with, does_not_end_with, is_empty, is_not_empty):\n- `invoice_number`,\
        \ `proration_strategy`, `link_reference`, `currency_code`\n- `link_type` —\
        \ values: `purchase_order`, `warehouse_transfer`, `inbound_shipment`\n- `source`\
        \ — values: `ocr`, `manual`\n- `allocation_status` — values: `empty`, `unallocated`,\
        \ `partial`, `allocated`\n- `supplier_name`, `line_description`, `line_nominal_code`,\
        \ `cost_category` (related-table text filters)\n- `supplier_id`, `cost_category_id`\
        \ (ID-select filters, text-typed)\n\n**Numeric columns** (operators: is, is_not,\
        \ is_one_of, greater_than, less_than, greater_than_or_equal, less_than_or_equal,\
        \ between, is_empty, is_not_empty):\n- `id`, `currency_rate`, `subtotal`,\
        \ `tax_total`, `total`, `grand_total`, `allocated_amount`, `unallocated_amount`,\
        \ `line_count`, `line_quantity`, `line_amount`\n- `between` takes two comma-separated\
        \ values, e.g. `filter[grand_total.between]=100,500`\n\n**Date columns** (operators:\
        \ is, is_not, before, after, on_or_before, on_or_after, between, is_empty,\
        \ is_not_empty, today, yesterday, tomorrow, past_week, past_month, past_year,\
        \ next_week, next_month, next_year, days_ago, days_from_now, past_days, next_days):\n\
        - `invoice_date`, `created_at`, `updated_at`\n- Dates use `YYYY-MM-DD`; `between`\
        \ takes two comma-separated dates\n\n**Boolean filters:**\n- `filter[has_accounting_transaction]=true|false`\
        \ — whether an accounting transaction has been generated for the bill\n\n\
        ## Grouped filters (filter_groups)\n`filter_groups` — base64-encoded JSON\
        \ tree supporting AND/OR conjunctions and nested groups. Takes precedence\
        \ over flat `filter[...]` params when present.\n\nJSON structure before encoding:\n\
        ```json\n{\n  \"conjunction\": \"and\",\n  \"children\": [\n    {\"type\"\
        : \"condition\", \"condition\": {\"column\": \"allocation_status.is\", \"\
        operator\": \"is\", \"value\": \"partial\"}},\n    {\"type\": \"group\", \"\
        group\": {\"conjunction\": \"or\", \"children\": [...]}}\n  ]\n}\n```\n\n\
        ## Response extras\nOn top of Laravel's standard paginator JSON, the response\
        \ includes:\n- `unfiltered_total` — total bill count with all filters cleared\
        \ (for the export modal's \"All records\" label)\n- `summary` — tenant-currency\
        \ stat card totals across the **filtered** result set: `total_billed_tenant`,\
        \ `total_allocated_tenant`, `total_unallocated_tenant`, `bill_count`\n\nEach\
        \ bill includes `documents_count` (number of attached source documents) and\
        \ `document_filenames` (their file names). Sortable by `documents_count`.\
        \ Filter with `filter[documents_count]` (e.g. `filter[documents_count.is]=0`\
        \ for bills with no source document) or `filter[document_filename]` to match\
        \ a source document's file name."
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        description: Page number (default 1)
        example: '1'
      - name: per_page
        in: query
        schema:
          type: integer
        description: Items per page (default 10)
        example: '10'
      - name: sort
        in: query
        schema:
          type: string
        description: 'Sort field; prefix with - for descending. Allowed: id, invoice_number,
          invoice_date, supplier_name, supplier_id, link_type, link_reference, proration_strategy,
          currency_code, currency_rate, line_count, subtotal, tax_total, grand_total,
          allocated_amount, unallocated_amount, allocation_status, documents_count,
          created_at, updated_at. Default: -created_at'
        example: -created_at
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        invoice_number:
                          type: string
                        invoice_date:
                          type: string
                        due_date:
                          type: string
                        payment_status:
                          type: string
                        payment_due_status:
                          type: string
                        days_until_due:
                          type: integer
                        supplier_id:
                          type: integer
                        supplier_name:
                          type: string
                        supplier_type:
                          type: string
                        link_type:
                          type: string
                        link_id:
                          type: integer
                        link_reference:
                          type: string
                        link_url_path:
                          type: string
                        proration_strategy:
                          type: string
                        currency_code:
                          type: string
                        currency_rate:
                          type: number
                        tenant_currency_code:
                          type: string
                        line_count:
                          type: integer
                        subtotal:
                          type: number
                        tax_total:
                          type: number
                        grand_total:
                          type: number
                        subtotal_tenant:
                          type: number
                        allocated_amount:
                          type: number
                        allocated_amount_tenant:
                          type: number
                        unallocated_amount:
                          type: number
                        allocation_status:
                          type: string
                        cost_categories:
                          type: array
                          items:
                            type: object
                            properties:
                              id:
                                type: integer
                              name:
                                type: string
                        has_accounting_transaction:
                          type: boolean
                        source:
                          type: string
                        ocr_extraction_id:
                          type: integer
                        settlement_reference_count:
                          type: integer
                        documents_count:
                          type: integer
                        document_filenames:
                          type: array
                          items:
                            type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                  next_page_url:
                    type: string
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                  unfiltered_total:
                    type: integer
                  summary:
                    type: object
                    properties:
                      total_billed_tenant:
                        type: number
                      total_allocated_tenant:
                        type: number
                      total_unallocated_tenant:
                        type: number
                      bill_count:
                        type: integer
                example:
                  current_page: 1
                  data:
                  - id: 12
                    invoice_number: INV-2026-0042
                    invoice_date: '2026-05-28'
                    due_date: '2026-06-27'
                    payment_status: unpaid
                    payment_due_status: not_due
                    days_until_due: 30
                    supplier_id: 3
                    supplier_name: Global Freight Co
                    supplier_type: service
                    link_type: purchase_order
                    link_id: 42
                    link_reference: PO-00042
                    link_url_path: /orders/purchase-orders/42
                    proration_strategy: cost_based
                    currency_code: USD
                    currency_rate: 1.0
                    tenant_currency_code: USD
                    line_count: 2
                    subtotal: 750.0
                    tax_total: 0.0
                    grand_total: 750.0
                    subtotal_tenant: 750.0
                    allocated_amount: 500.0
                    allocated_amount_tenant: 500.0
                    unallocated_amount: 250.0
                    allocation_status: partial
                    cost_categories:
                    - id: 1
                      name: Freight
                    - id: 2
                      name: Duty
                    has_accounting_transaction: true
                    source: ocr
                    ocr_extraction_id: 7
                    settlement_reference_count: 0
                    documents_count: 2
                    document_filenames:
                    - proforma.pdf
                    - freight-invoice.pdf
                    created_at: '2026-05-28T14:22:10.000000Z'
                    updated_at: '2026-06-02T09:15:44.000000Z'
                  first_page_url: '{{protocol}}{{domain}}/api/bills/list?page=1'
                  from: 1
                  last_page: 5
                  last_page_url: '{{protocol}}{{domain}}/api/bills/list?page=5'
                  links: []
                  next_page_url: '{{protocol}}{{domain}}/api/bills/list?page=2'
                  path: '{{protocol}}{{domain}}/api/bills/list'
                  per_page: 10
                  prev_page_url: null
                  to: 10
                  total: 47
                  unfiltered_total: 143
                  summary:
                    total_billed_tenant: 38450.25
                    total_allocated_tenant: 31200.1
                    total_unallocated_tenant: 7250.15
                    bill_count: 47
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Requested filter(s) `bogus_column` are not allowed. Allowed
                    filter(s) are `search, has_accounting_transaction, invoice_number,
                    ...`.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: purchase-orders:read
      operationId: get-api-bills-list
  /api/bills/list/export:
    get:
      tags:
      - Bills
      summary: Export Bills
      description: "Export landed cost bills as XLSX or CSV. The response is a binary\
        \ file download, not JSON.\n\n:::info[Required scope: `purchase-orders:read`]\n\
        Grant this scope to your token under [Settings → Developer → Personal Access\
        \ Tokens](https://app.sku.io/settings/api).\n:::\n\nAuthentication: Requires\
        \ Bearer token. Scope: `purchase-orders` (read/write).\n\n## Parameters\n\
        - `format` — `xlsx` (default) or `csv`\n- `content_mode` — `summary` (one\
        \ row per bill, default) or `line_items` (one row per bill line; bill columns\
        \ repeat per line, line-item columns are appended)\n- `scope` — which bills\
        \ to export:\n  - `all` — every bill, ignoring active filters\n  - `filtered`\
        \ — bills matching the current `filter[...]` / `filter_groups` params (default)\n\
        \  - `current_page` — only the current page (honors `page` / `per_page` /\
        \ `sort`)\n  - `selected` — only the bills in `ids`\n- `columns` — comma-separated\
        \ bill column keys to include (preserves order). Omit for all columns. Available\
        \ keys: `id`, `invoice_number`, `invoice_date`, `supplier_name`, `link_type`,\
        \ `link_reference`, `proration_strategy`, `currency_code`, `currency_rate`,\
        \ `line_count`, `subtotal`, `tax_total`, `grand_total`, `allocated_amount`,\
        \ `unallocated_amount`, `allocation_status`, `cost_categories`, `has_accounting_transaction`,\
        \ `source`, `settlement_reference_count`, `created_at`, `updated_at`\n- `ids`\
        \ — comma-separated bill IDs (required when `scope=selected`)\n\nAll `filter[...]`,\
        \ `filter_groups`, and `sort` params from the List Bills endpoint also apply\
        \ when `scope=filtered`.\n\nIn `line_items` mode these line columns are always\
        \ appended: Line Description, Line Cost Category, Line Qty, Line Amount, Line\
        \ Extended, Line Tax Rate.\n\n## Response\nBinary file download:\n- XLSX:\
        \ `Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet`\n\
        - CSV: `Content-Type: text/csv`\n- Filename: `landed-cost-bills-{timestamp}.{ext}`\
        \ (summary) or `landed-cost-bills-detail-{timestamp}.{ext}` (line_items)"
      parameters:
      - name: format
        in: query
        schema:
          type: string
        description: 'File format: xlsx (default) or csv'
        example: xlsx
      - name: content_mode
        in: query
        schema:
          type: string
        description: summary (one row per bill, default) or line_items (one row per
          bill line)
        example: summary
      - name: scope
        in: query
        schema:
          type: string
        description: all | filtered (default) | current_page | selected
        example: filtered
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
            Content-Disposition:
              schema:
                type: string
                example: attachment; filename=landed-cost-bills-20260611-153000.xlsx
          content:
            text/plain:
              schema:
                type: string
                example: (binary XLSX/CSV file)
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: purchase-orders:read
      operationId: get-api-bills-list-export
  /api/bills/{id}:
    get:
      tags:
      - Bills
      summary: Get Bill
      description: 'Returns a bill with its supplier, lines, allocations, and related
        purchase order / warehouse transfer data.


        :::info[Required scope: `purchase-orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      supplier_id:
                        type: integer
                      supplier_name:
                        type: string
                      supplier_type:
                        type: string
                      invoice_number:
                        type: string
                      invoice_date:
                        type: string
                      due_date:
                        type: string
                      due_date_source:
                        type: string
                      payment_due_status:
                        type: string
                      days_until_due:
                        type: integer
                      link_type:
                        type: string
                      link_id:
                        type: integer
                      currency_id:
                        type: integer
                      currency_code:
                        type: string
                      currency_rate:
                        type: number
                      proration_strategy:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            description:
                              type: string
                            quantity:
                              type: integer
                            amount:
                              type: number
                            extended_amount:
                              type: number
                            nominal_code_id:
                              type: integer
                            tax_rate_id:
                              type: string
                              nullable: true
                            created_at:
                              type: string
                            updated_at:
                              type: string
                      descriptions:
                        type: array
                        items:
                          type: string
                      total_amount:
                        type: number
                      totals:
                        type: object
                        properties:
                          line_count:
                            type: integer
                          amount:
                            type: number
                          tax:
                            type: number
                          grand_total:
                            type: number
                      allocations:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            allocation_amount:
                              type: number
                            allocation_percentage:
                              type: number
                            proration_strategy:
                              type: string
                            purchase_order_line_id:
                              type: integer
                            warehouse_transfer_line_id:
                              type: string
                              nullable: true
                            purchase_order_line:
                              type: object
                              properties:
                                id:
                                  type: integer
                                description:
                                  type: string
                                quantity:
                                  type: integer
                                product:
                                  type: object
                                  properties:
                                    id:
                                      type: integer
                                    name:
                                      type: string
                                    sku:
                                      type: string
                            warehouse_transfer_line:
                              type: string
                              nullable: true
                      ledger:
                        type: object
                        properties:
                          enabled:
                            type: boolean
                          entries:
                            type: array
                            items:
                              type: object
                              properties:
                                id:
                                  type: integer
                                status:
                                  type: string
                                reference:
                                  type: string
                                total:
                                  type: number
                                posted_at:
                                  type: string
                                  nullable: true
                                effective_at:
                                  type: string
                example:
                  data:
                    id: 1
                    supplier_id: 3
                    supplier_name: Acme Supplier Ltd
                    supplier_type: service
                    invoice_number: INV-2024-001
                    invoice_date: '2024-01-15'
                    due_date: '2024-02-14'
                    due_date_source: derived
                    payment_due_status: not_due
                    days_until_due: 30
                    link_type: purchase_order
                    link_id: 42
                    currency_id: 1
                    currency_code: USD
                    currency_rate: 1.0
                    proration_strategy: cost_based
                    created_at: '2024-01-15T10:00:00.000000Z'
                    updated_at: '2024-01-15T10:00:00.000000Z'
                    lines:
                    - id: 1
                      description: Product A - Qty 100
                      quantity: 100
                      amount: 5.5
                      extended_amount: 550.0
                      nominal_code_id: 10
                      tax_rate_id: null
                      created_at: '2024-01-15T10:00:00.000000Z'
                      updated_at: '2024-01-15T10:00:00.000000Z'
                    descriptions:
                    - Product A - Qty 100
                    total_amount: 550.0
                    totals:
                      line_count: 1
                      amount: 550.0
                      tax: 0.0
                      grand_total: 550.0
                    allocations:
                    - id: 1
                      allocation_amount: 550.0
                      allocation_percentage: 100.0
                      proration_strategy: cost_based
                      purchase_order_line_id: 55
                      warehouse_transfer_line_id: null
                      purchase_order_line:
                        id: 55
                        description: Product A
                        quantity: 100
                        product:
                          id: 10
                          name: Product A
                          sku: PROD-A-001
                      warehouse_transfer_line: null
                    ledger:
                      enabled: true
                      entries:
                      - id: 9954
                        status: draft
                        reference: BILL-319
                        total: 250.0
                        posted_at: null
                        effective_at: '2026-03-30T00:00:00+00:00'
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No query results for model [App\Models\Bill] 999
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: purchase-orders:read
      operationId: get-api-bills-id
    put:
      tags:
      - Bills
      summary: Update Bill
      description: 'Updates an existing bill''s header data and allocations.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Fields:

        - invoice_number (required): Updated invoice number

        - invoice_date (required): Updated invoice date (YYYY-MM-DD)

        - supplier_id (required): Supplier ID — must be a service-type supplier

        - currency_id (optional): Currency ID

        - currency_rate (optional): Exchange rate

        - proration_strategy (optional): One of cost_based, quantity_based, manual

        - allocations (optional): Updated allocations array (replaces existing)'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                invoice_number:
                  type: string
                invoice_date:
                  type: string
                supplier_id:
                  type: integer
                currency_id:
                  type: integer
                currency_rate:
                  type: integer
                proration_strategy:
                  type: string
                allocations:
                  type: array
                  items:
                    type: object
                    properties:
                      purchase_order_line_id:
                        type: integer
                      allocation_amount:
                        type: integer
              example:
                invoice_number: INV-2024-001-REVISED
                invoice_date: '2024-01-20'
                supplier_id: 3
                currency_id: 1
                currency_rate: 1
                proration_strategy: cost_based
                allocations:
                - purchase_order_line_id: 55
                  allocation_amount: 550
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      supplier_id:
                        type: integer
                      supplier_name:
                        type: string
                      supplier_type:
                        type: string
                      invoice_number:
                        type: string
                      invoice_date:
                        type: string
                      link_type:
                        type: string
                      link_id:
                        type: integer
                      total_amount:
                        type: number
                example:
                  data:
                    id: 1
                    supplier_id: 3
                    supplier_name: Acme Supplier Ltd
                    supplier_type: service
                    invoice_number: INV-2024-001-REVISED
                    invoice_date: '2024-01-20'
                    link_type: purchase_order
                    link_id: 42
                    total_amount: 550.0
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: purchase-orders:write
      operationId: put-api-bills-id
    delete:
      tags:
      - Bills
      summary: Delete Bill
      description: 'Deletes a bill.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Bill deleted successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:write
      operationId: delete-api-bills-id
  /api/bills/{id}/line-items:
    get:
      tags:
      - Bills
      summary: Get Bill Line Items
      description: 'Lean lines + allocations payload for the expandable row in the
        landed cost bills list view.


        :::info[Required scope: `purchase-orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Returns the bill''s lines (with tax rate and cost category), its allocations
        (with the target PO/WT line, parent document ID, and product), and aggregate
        totals.


        `target_type` is `purchase_order_line` or `warehouse_transfer_line`; `target_document_id`
        is the parent purchase order / warehouse transfer ID.


        Authentication: Requires Bearer token. Scope: `purchase-orders` (read/write).'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            description:
                              type: string
                            quantity:
                              type: number
                            amount:
                              type: number
                            extended_amount:
                              type: number
                            tax_rate_id:
                              type: string
                              nullable: true
                            tax_rate_name:
                              type: string
                              nullable: true
                            tax_rate:
                              type: string
                              nullable: true
                            cost_category:
                              type: object
                              properties:
                                id:
                                  type: integer
                                name:
                                  type: string
                      allocations:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            purchase_order_line_id:
                              type: integer
                            warehouse_transfer_line_id:
                              type: string
                              nullable: true
                            target_type:
                              type: string
                            target_document_id:
                              type: integer
                            product_id:
                              type: integer
                            product_sku:
                              type: string
                            product_name:
                              type: string
                            description:
                              type: string
                            allocation_amount:
                              type: number
                            allocation_amount_tenant:
                              type: number
                            proration_strategy:
                              type: string
                      totals:
                        type: object
                        properties:
                          subtotal:
                            type: number
                          allocated:
                            type: number
                          allocated_tenant:
                            type: number
                example:
                  data:
                    id: 12
                    lines:
                    - id: 31
                      description: Ocean freight — container MSKU1234567
                      quantity: 1.0
                      amount: 500.0
                      extended_amount: 500.0
                      tax_rate_id: null
                      tax_rate_name: null
                      tax_rate: null
                      cost_category:
                        id: 1
                        name: Freight
                    - id: 32
                      description: Import duty
                      quantity: 1.0
                      amount: 250.0
                      extended_amount: 250.0
                      tax_rate_id: 2
                      tax_rate_name: GST 10%
                      tax_rate: 10.0
                      cost_category:
                        id: 2
                        name: Duty
                    allocations:
                    - id: 55
                      purchase_order_line_id: 101
                      warehouse_transfer_line_id: null
                      target_type: purchase_order_line
                      target_document_id: 42
                      product_id: 10
                      product_sku: PROD-A-001
                      product_name: Product A
                      description: Product A
                      allocation_amount: 500.0
                      allocation_amount_tenant: 500.0
                      proration_strategy: cost_based
                    totals:
                      subtotal: 750.0
                      allocated: 500.0
                      allocated_tenant: 500.0
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No query results for model [App\Models\Bill] 999
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: purchase-orders:read
      operationId: get-api-bills-id-line-items
  /api/bills/payees:
    get:
      tags:
      - Bills
      summary: Get Bill Payees
      description: 'Lists the distinct suppliers actually referenced by existing bills,
        ordered by name (may include grandfathered goods suppliers on migrated bills).
        Backs the Supplier filter on the bills list page.


        :::info[Required scope: `purchase-orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        For the payee picker on landed-cost / cost-entry create/edit forms, use GET
        /api/bills/eligible-payees instead.


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        company_name:
                          type: string
                        email:
                          type: string
                        type:
                          type: string
                        type_label:
                          type: string
                example:
                  data:
                  - id: 3
                    name: Freight Co.
                    company_name: Freight Co. LLC
                    email: billing@freightco.test
                    type: service
                    type_label: Service Provider
                  - id: 8
                    name: DHL Express
                    company_name: DHL
                    email: ap@dhl.test
                    type: service
                    type_label: Service Provider
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: purchase-orders:read
      operationId: get-api-bills-payees
  /api/bills/eligible-payees:
    get:
      tags:
      - Bills
      summary: Get Eligible Bill Payees
      description: 'Lists all suppliers eligible to be billed: non-archived, service-type
        suppliers, ordered by name. Backs the payee picker on the landed-cost and
        cost-entry create/edit forms (where new bills are created).


        :::info[Required scope: `purchase-orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Distinct from GET /api/bills/payees, which backs the bills-list Supplier filter
        and returns only suppliers that already appear on a bill (and may include
        grandfathered goods suppliers).


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        company_name:
                          type: string
                        email:
                          type: string
                        type:
                          type: string
                        type_label:
                          type: string
                example:
                  data:
                  - id: 3
                    name: Freight Co.
                    company_name: Freight Co. LLC
                    email: billing@freightco.test
                    type: service
                    type_label: Service Provider
                  - id: 8
                    name: DHL Express
                    company_name: DHL
                    email: ap@dhl.test
                    type: service
                    type_label: Service Provider
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: purchase-orders:read
      operationId: get-api-bills-eligible-payees
  /api/bills:
    post:
      tags:
      - Bills
      summary: Create Bill
      description: "Creates a standalone bill. Note: This endpoint is currently not\
        \ used in practice — bills are typically created via purchase order or warehouse\
        \ transfer nested routes.\n\n:::info[Required scope: `purchase-orders:write`]\n\
        Grant this scope to your token under [Settings → Developer → Personal Access\
        \ Tokens](https://app.sku.io/settings/api).\n:::\n\nAuthentication: Requires\
        \ Bearer token.\n\nFields:\n- supplier_id (required): Supplier ID — must be\
        \ a service-type supplier\n- invoice_number (required, unique): Invoice reference\
        \ number\n- invoice_date (required): Invoice date (YYYY-MM-DD)\n- link_type\
        \ (required): Type of link — 'purchase_order' or 'warehouse_transfer'\n- link_id\
        \ (required): ID of the linked record\n- currency_id (optional): Currency\
        \ ID\n- currency_rate (optional): Exchange rate\n- proration_strategy (required):\
        \ One of cost_based, quantity_based, manual\n- lines (required): Array of\
        \ bill lines\n  - lines.*.description: Line description\n  - lines.*.quantity:\
        \ Quantity\n  - lines.*.amount: Unit amount\n  - lines.*.nominal_code_id (optional,\
        \ nullable): The line's debit (expense/clearing) account that faces Accounts\
        \ Payable. Optional — omit it or send null and NO default is frozen onto the\
        \ line at save; the GL debit is resolved at posting time from the bill's link_type\
        \ (landed-cost bills linked to a purchase order / warehouse transfer / inbound\
        \ shipment capitalize to the configured inventory_control account).\n  - lines.*.tax_rate_id:\
        \ Tax rate ID (optional)\n- allocations (optional): Array of allocation objects\n\
        \  - allocations.*.purchase_order_line_id: PO line ID\n  - allocations.*.allocation_amount:\
        \ Amount to allocate"
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                supplier_id:
                  type: integer
                invoice_number:
                  type: string
                invoice_date:
                  type: string
                link_type:
                  type: string
                link_id:
                  type: integer
                currency_id:
                  type: integer
                currency_rate:
                  type: integer
                proration_strategy:
                  type: string
                lines:
                  type: array
                  items:
                    type: object
                    properties:
                      description:
                        type: string
                      quantity:
                        type: integer
                      amount:
                        type: number
                      nominal_code_id:
                        type: integer
                      tax_rate_id:
                        type: string
                        nullable: true
                allocations:
                  type: array
                  items:
                    type: object
                    properties:
                      purchase_order_line_id:
                        type: integer
                      allocation_amount:
                        type: integer
              example:
                supplier_id: 3
                invoice_number: INV-2024-001
                invoice_date: '2024-01-15'
                link_type: purchase_order
                link_id: 42
                currency_id: 1
                currency_rate: 1
                proration_strategy: cost_based
                lines:
                - description: Product A - 100 units
                  quantity: 100
                  amount: 5.5
                  nominal_code_id: 10
                  tax_rate_id: null
                allocations:
                - purchase_order_line_id: 55
                  allocation_amount: 550
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      supplier_id:
                        type: integer
                      supplier_name:
                        type: string
                      supplier_type:
                        type: string
                      invoice_number:
                        type: string
                      invoice_date:
                        type: string
                      link_type:
                        type: string
                      link_id:
                        type: integer
                      currency_code:
                        type: string
                      currency_rate:
                        type: number
                      proration_strategy:
                        type: string
                      total_amount:
                        type: number
                      totals:
                        type: object
                        properties:
                          line_count:
                            type: integer
                          amount:
                            type: number
                          tax:
                            type: number
                          grand_total:
                            type: number
                example:
                  data:
                    id: 5
                    supplier_id: 3
                    supplier_name: Acme Supplier Ltd
                    supplier_type: service
                    invoice_number: INV-2024-001
                    invoice_date: '2024-01-15'
                    link_type: purchase_order
                    link_id: 42
                    currency_code: USD
                    currency_rate: 1.0
                    proration_strategy: cost_based
                    total_amount: 550.0
                    totals:
                      line_count: 1
                      amount: 550.0
                      tax: 0.0
                      grand_total: 550.0
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: purchase-orders:write
      operationId: post-api-bills
    delete:
      tags:
      - Bills
      summary: Bulk Delete Bills
      description: 'Bulk delete landed cost bills by explicit IDs or by list filters
        ("all filtered" scope).


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Provide ONE of:

        - `ids` — array of bill IDs (each must exist)

        - `filters` — object of List Bills filter params (same keys as the `filter[...]`
        query params, plus optional `filter_groups`); the matching bill IDs are resolved
        server-side

        - `apply_to_all: true` — delete ALL bills (optionally narrowed by `filters`);
        without this flag an empty/missing `filters` object deletes nothing


        Behavior:

        - **25 bills or fewer** → deleted synchronously; response includes per-bill
        results

        - **More than 25 bills** → dispatched as a Tracked Job (`Delete Landed Cost
        Bills: N bill(s)`); response returns `tracked_job_log_id` for the tracked
        job log endpoints

        - Deleting a bill removes its lines/allocations and triggers FIFO landed-cost
        recalculation on affected layers


        Authentication: Requires Bearer token. Scope: `purchase-orders` (read/write).'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 OK (synchronous, ≤25 bills)
                  value:
                    data:
                      deleted: 3
                      failed: []
                    message: Deleted 3 bill(s)
                example-1:
                  summary: 200 OK (tracked job, >25 bills)
                  value:
                    data:
                      tracked_job_log_id: 481
                    message: Bill deletion started — track progress in the job tray
                example-2:
                  summary: 200 OK (no matches)
                  value:
                    message: No bills matched the given criteria
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      ids:
                        type: array
                        items:
                          type: string
                example:
                  message: The ids field is required when filters is not present.
                  errors:
                    ids:
                    - The ids field is required when filters is not present.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: purchase-orders:write
      operationId: delete-api-bills
  /api/bills/{id}/lines:
    patch:
      tags:
      - Bills
      summary: Update Bill Lines
      description: "Batch updates the lines of a bill. Replaces existing lines with\
        \ the provided collection.\n\n:::info[Required scope: `purchase-orders:write`]\n\
        Grant this scope to your token under [Settings → Developer → Personal Access\
        \ Tokens](https://app.sku.io/settings/api).\n:::\n\nAuthentication: Requires\
        \ Bearer token.\n\nBody:\n- lines (required): Array of bill line objects\n\
        \  - lines.*.id (optional): Existing line ID (omit for new lines)\n  - lines.*.description:\
        \ Line description\n  - lines.*.quantity: Quantity\n  - lines.*.amount: Unit\
        \ amount\n  - lines.*.nominal_code_id (optional, nullable): The line's debit\
        \ (expense/clearing) account. Send an explicit null to CLEAR the nominal code\
        \ on the line (it persists as null). OMIT the field entirely to leave an existing\
        \ line's code untouched. No inventory_control default is frozen onto the line\
        \ — when the line carries no code, the GL debit is resolved at posting time\
        \ from the bill's link_type (landed-cost bills linked to a purchase order\
        \ / warehouse transfer / inbound shipment capitalize to the configured inventory_control\
        \ account).\n  - lines.*.tax_rate_id: Tax rate ID (optional)"
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                lines:
                  type: array
                  items:
                    type: object
                    properties:
                      id:
                        type: integer
                      description:
                        type: string
                      quantity:
                        type: integer
                      amount:
                        type: integer
                      nominal_code_id:
                        type: integer
                      tax_rate_id:
                        type: string
                        nullable: true
              example:
                lines:
                - id: 1
                  description: Product A - Updated
                  quantity: 100
                  amount: 6
                  nominal_code_id: 10
                  tax_rate_id: null
                - description: New Line Item
                  quantity: 50
                  amount: 3
                  nominal_code_id: 10
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      supplier_id:
                        type: integer
                      supplier_name:
                        type: string
                      supplier_type:
                        type: string
                      invoice_number:
                        type: string
                      invoice_date:
                        type: string
                      lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            description:
                              type: string
                            quantity:
                              type: integer
                            amount:
                              type: number
                            extended_amount:
                              type: number
                      total_amount:
                        type: number
                      totals:
                        type: object
                        properties:
                          line_count:
                            type: integer
                          amount:
                            type: number
                          tax:
                            type: number
                          grand_total:
                            type: number
                example:
                  data:
                    id: 1
                    supplier_id: 3
                    supplier_name: Acme Supplier Ltd
                    supplier_type: service
                    invoice_number: INV-2024-001
                    invoice_date: '2024-01-15'
                    lines:
                    - id: 1
                      description: Product A - Updated
                      quantity: 100
                      amount: 6.0
                      extended_amount: 600.0
                    - id: 2
                      description: New Line Item
                      quantity: 50
                      amount: 3.0
                      extended_amount: 150.0
                    total_amount: 750.0
                    totals:
                      line_count: 2
                      amount: 750.0
                      tax: 0.0
                      grand_total: 750.0
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: purchase-orders:write
      operationId: patch-api-bills-id-lines
  /api/bills/{id}/available-lines:
    get:
      tags:
      - Bills
      summary: Get Available Lines for Manual Allocation
      description: 'Returns purchase order and warehouse transfer lines that are available
        for manual cost allocation to this bill. Includes pre-calculated allocation
        amounts.


        :::info[Required scope: `purchase-orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        type:
                          type: string
                        description:
                          type: string
                        quantity:
                          type: integer
                        unit_cost:
                          type: number
                        total_cost:
                          type: number
                        suggested_allocation_amount:
                          type: number
                        product:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            sku:
                              type: string
                example:
                  data:
                  - id: 55
                    type: purchase_order_line
                    description: Product A
                    quantity: 100
                    unit_cost: 5.5
                    total_cost: 550.0
                    suggested_allocation_amount: 550.0
                    product:
                      id: 10
                      name: Product A
                      sku: PROD-A-001
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:read
      operationId: get-api-bills-id-available-lines
  /api/bills/{id}/generate-accounting-transaction:
    post:
      tags:
      - Bills
      summary: Generate Accounting Transaction
      description: 'Generates (or regenerates) the accounting posting for a landed-cost
        bill. On tenants using the v2 ledger, this synchronously rebuilds the bill''s
        ledger journal entry; on legacy tenants it creates the accounting transaction.
        Safe to call repeatedly — an existing entry is superseded, not duplicated.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 OK
                  value:
                    data:
                      ledger_entries:
                      - id: 9954
                        status: draft
                        reference: BILL-319
                        total: 250.0
                        posted_at: null
                        effective_at: '2026-03-30T00:00:00+00:00'
                    message: Ledger entry generated successfully.
                example-1:
                  summary: 200 OK (ledger disabled)
                  value:
                    data: []
                    message: Ledger generation is disabled for this tenant.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: purchase-orders:write
      operationId: post-api-bills-id-generate-accounting-transaction
  /api/bills/{bill}/cost-entries:
    post:
      tags:
      - Bills
      summary: Create Cost Entries from Bill Lines
      description: "Create one cost entry per selected bill line, each tracking a\
        \ chosen amount of that line for profitability analysis. This is the `scope:\
        \ \"lines\"` mode of the endpoint; to track the whole remaining bill as a\
        \ single entry, see \"Create Cost Entry from Bill\" (same URL, `scope: \"\
        entire\"`).\n\n:::info[Required scope: `purchase-orders:write`]\nGrant this\
        \ scope to your token under [Settings → Developer → Personal Access Tokens](https://app.sku.io/settings/api).\n\
        :::\n\nEach allocation amount may be the full line total or a partial amount,\
        \ but cannot exceed what is still untracked on that line (check with the lines-availability\
        \ endpoints first). When more than one line is sent, each entry's description\
        \ is the `name` with the line's description appended. Entries inherit the\
        \ bill's supplier, currency, exchange rate, and invoice number, are dated\
        \ with the bill's invoice date, and start in `pending_allocation` status.\n\
        \nRequest fields:\n- `scope` (required) - `lines` for this mode.\n- `name`\
        \ (required, max 255) - Base description for the cost entries.\n- `cost_entry_type_id`\
        \ (optional) - ID of a cost entry type (see `GET /api/cost-entry-types`);\
        \ applies to every entry created. Omit or send null to leave them untyped.\n\
        - `notes` (optional, max 1000) - Free-form notes.\n- `line_allocations` (required\
        \ in this mode, min 1) - Array of allocations:\n  - `line_allocations[].bill_line_id`\
        \ (required, integer) - ID of a line on this bill.\n  - `line_allocations[].amount`\
        \ (required, numeric, min 0.01) - Amount of that line to track.\n\nReturns\
        \ 422 when a line does not belong to the bill or an amount exceeds the line's\
        \ untracked remainder.\n\nAuthentication: Requires Bearer token. Scope: `purchase-orders`\
        \ (read/write)."
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                scope:
                  type: string
                name:
                  type: string
                cost_entry_type_id:
                  type: integer
                notes:
                  type: string
                line_allocations:
                  type: array
                  items:
                    type: object
                    properties:
                      bill_line_id:
                        type: integer
                      amount:
                        type: integer
              example:
                scope: lines
                name: June shipment landed costs
                cost_entry_type_id: 3
                notes: Split by freight and duty lines
                line_allocations:
                - bill_line_id: 31
                  amount: 1850
                - bill_line_id: 32
                  amount: 650
      parameters:
      - name: bill
        in: path
        schema:
          type: integer
        required: true
        description: Bill ID
        example: '15'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      message:
                        type: string
                      cost_entries:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            supplier_id:
                              type: integer
                            supplier_name:
                              type: string
                            reference_number:
                              type: string
                            description:
                              type: string
                            cost_date:
                              type: string
                            amount:
                              type: number
                            amount_in_tenant_currency:
                              type: number
                            currency_id:
                              type: integer
                            currency_code:
                              type: string
                            currency_rate:
                              type: number
                            nominal_code_id:
                              type: string
                              nullable: true
                            nominal_code_name:
                              type: string
                              nullable: true
                            cost_entry_type_id:
                              type: integer
                            cost_entry_type:
                              type: object
                              properties:
                                id:
                                  type: integer
                                name:
                                  type: string
                            status:
                              type: string
                            bill_id:
                              type: integer
                            bill_line_id:
                              type: integer
                            source_type:
                              type: string
                            source_description:
                              type: string
                            source_link_type:
                              type: string
                              nullable: true
                            source_id:
                              type: string
                              nullable: true
                            source_label:
                              type: string
                              nullable: true
                            source_period:
                              type: string
                              nullable: true
                            reconciliation:
                              type: string
                              nullable: true
                            created_at:
                              type: string
                            updated_at:
                              type: string
                            totals:
                              type: object
                              properties:
                                allocated:
                                  type: number
                                unallocated:
                                  type: number
                                is_fully_allocated:
                                  type: boolean
                  status:
                    type: string
                example:
                  data:
                    message: Created 2 cost entry(s) from bill
                    cost_entries:
                    - id: 89
                      supplier_id: 12
                      supplier_name: Pacific Freight Forwarding
                      reference_number: INV-20441
                      description: June shipment landed costs - Ocean freight (container
                        MSKU1234567)
                      cost_date: '2026-06-15'
                      amount: 1850.0
                      amount_in_tenant_currency: 1850.0
                      currency_id: 1
                      currency_code: USD
                      currency_rate: 1.0
                      nominal_code_id: null
                      nominal_code_name: null
                      cost_entry_type_id: 3
                      cost_entry_type:
                        id: 3
                        name: Freight
                      status: pending_allocation
                      bill_id: 15
                      bill_line_id: 31
                      source_type: bill_line
                      source_description: 'Bill #INV-20441 - Line: Ocean freight (container
                        MSKU1234567)'
                      source_link_type: null
                      source_id: null
                      source_label: null
                      source_period: null
                      reconciliation: null
                      created_at: '2026-07-07T14:02:11.000000Z'
                      updated_at: '2026-07-07T14:02:11.000000Z'
                      totals:
                        allocated: 0.0
                        unallocated: 1850.0
                        is_fully_allocated: false
                    - id: 90
                      supplier_id: 12
                      supplier_name: Pacific Freight Forwarding
                      reference_number: INV-20441
                      description: June shipment landed costs - Import duty (HS 8516.71)
                      cost_date: '2026-06-15'
                      amount: 650.0
                      amount_in_tenant_currency: 650.0
                      currency_id: 1
                      currency_code: USD
                      currency_rate: 1.0
                      nominal_code_id: null
                      nominal_code_name: null
                      cost_entry_type_id: 3
                      cost_entry_type:
                        id: 3
                        name: Freight
                      status: pending_allocation
                      bill_id: 15
                      bill_line_id: 32
                      source_type: bill_line
                      source_description: 'Bill #INV-20441 - Line: Import duty (HS
                        8516.71)'
                      source_link_type: null
                      source_id: null
                      source_label: null
                      source_period: null
                      reconciliation: null
                      created_at: '2026-07-07T14:02:11.000000Z'
                      updated_at: '2026-07-07T14:02:11.000000Z'
                      totals:
                        allocated: 0.0
                        unallocated: 650.0
                        is_fully_allocated: false
                  status: success
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No query results for model [App\Models\Bill] 999
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 422 Unprocessable Entity - amount exceeds availability
                  value:
                    message: Amount 1900 exceeds available amount 1850 for line 'Ocean
                      freight (container MSKU1234567)'.
                    status: failure
                example-1:
                  summary: 422 Unprocessable Entity - line not on this bill
                  value:
                    message: Bill line 77 not found or doesn't belong to this bill.
                    status: failure
                example-2:
                  summary: 422 Validation Error
                  value:
                    message: The line allocations field is required when scope is
                      lines.
                    errors:
                      line_allocations:
                      - The line allocations field is required when scope is lines.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: purchase-orders:write
      operationId: post-api-bills-bill-cost-entries
  /api/bills/{bill}/profitability-summary:
    get:
      tags:
      - Bills
      summary: Get Bill Profitability Summary
      description: 'Get a profitability-tracking summary for a bill: how much of the
        bill''s total has been turned into cost entries, how much remains untracked,
        and the full list of cost entries created from the bill.


        :::info[Required scope: `purchase-orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Response fields:

        - `bill_total` - The bill''s grand total.

        - `tracked_for_profitability` - Sum of the cost entries created from this
        bill, in the account''s base currency.

        - `not_tracked` - Remainder of the bill total not yet tracked.

        - `tracking_percentage` - Tracked amount as a percentage of the bill total
        (rounded to 2 decimals).

        - `cost_entries` - Every cost entry created from this bill or its lines, including
        its allocation status and allocated/unallocated totals.


        Use this to decide whether more of the bill can still be tracked via `POST
        /api/bills/:bill/cost-entries`.


        Authentication: Requires Bearer token. Scope: `purchase-orders` (read/write).'
      parameters:
      - name: bill
        in: path
        schema:
          type: integer
        required: true
        description: Bill ID
        example: '15'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      bill_id:
                        type: integer
                      bill_total:
                        type: number
                      tracked_for_profitability:
                        type: number
                      not_tracked:
                        type: number
                      tracking_percentage:
                        type: number
                      cost_entries:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            supplier_id:
                              type: integer
                            supplier_name:
                              type: string
                            reference_number:
                              type: string
                            description:
                              type: string
                            cost_date:
                              type: string
                            amount:
                              type: number
                            amount_in_tenant_currency:
                              type: number
                            currency_id:
                              type: integer
                            currency_code:
                              type: string
                            currency_rate:
                              type: number
                            nominal_code_id:
                              type: string
                              nullable: true
                            nominal_code_name:
                              type: string
                              nullable: true
                            cost_entry_type_id:
                              type: integer
                            cost_entry_type:
                              type: object
                              properties:
                                id:
                                  type: integer
                                name:
                                  type: string
                            status:
                              type: string
                            bill_id:
                              type: integer
                            bill_line_id:
                              type: integer
                            source_type:
                              type: string
                            source_description:
                              type: string
                            source_link_type:
                              type: string
                              nullable: true
                            source_id:
                              type: string
                              nullable: true
                            source_label:
                              type: string
                              nullable: true
                            source_period:
                              type: string
                              nullable: true
                            reconciliation:
                              type: string
                              nullable: true
                            created_at:
                              type: string
                            updated_at:
                              type: string
                            totals:
                              type: object
                              properties:
                                allocated:
                                  type: number
                                unallocated:
                                  type: number
                                is_fully_allocated:
                                  type: boolean
                  status:
                    type: string
                example:
                  data:
                    bill_id: 15
                    bill_total: 2500.0
                    tracked_for_profitability: 1850.0
                    not_tracked: 650.0
                    tracking_percentage: 74.0
                    cost_entries:
                    - id: 89
                      supplier_id: 12
                      supplier_name: Pacific Freight Forwarding
                      reference_number: INV-20441
                      description: June shipment landed costs - Ocean freight (container
                        MSKU1234567)
                      cost_date: '2026-06-15'
                      amount: 1850.0
                      amount_in_tenant_currency: 1850.0
                      currency_id: 1
                      currency_code: USD
                      currency_rate: 1.0
                      nominal_code_id: null
                      nominal_code_name: null
                      cost_entry_type_id: 3
                      cost_entry_type:
                        id: 3
                        name: Freight
                      status: pending_allocation
                      bill_id: 15
                      bill_line_id: 31
                      source_type: bill_line
                      source_description: 'Bill #INV-20441 - Line: Ocean freight (container
                        MSKU1234567)'
                      source_link_type: null
                      source_id: null
                      source_label: null
                      source_period: null
                      reconciliation: null
                      created_at: '2026-07-07T14:02:11.000000Z'
                      updated_at: '2026-07-07T14:02:11.000000Z'
                      totals:
                        allocated: 0.0
                        unallocated: 1850.0
                        is_fully_allocated: false
                  status: success
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No query results for model [App\Models\Bill] 999
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: purchase-orders:read
      operationId: get-api-bills-bill-profitability-summary
  /api/bills/{bill}/lines-availability:
    get:
      tags:
      - Bills
      summary: Get Bill Lines Availability
      description: 'List every line on a bill with how much of each line has already
        been tracked as cost entries and how much is still available, plus bill-level
        totals.


        :::info[Required scope: `purchase-orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Response fields:

        - `bill_total`, `total_tracked`, `total_available` - Bill-level totals; `total_available`
        is the bill total minus the sum tracked across all lines.

        - `lines[]` - Per line: `line_total`, `already_tracked`, `available_for_tracking`,
        and `tracking_percentage` (0 for zero-total lines).


        Use this before calling `POST /api/bills/:bill/cost-entries` with `scope:
        "lines"` to choose valid allocation amounts.


        Authentication: Requires Bearer token. Scope: `purchase-orders` (read/write).'
      parameters:
      - name: bill
        in: path
        schema:
          type: integer
        required: true
        description: Bill ID
        example: '15'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      bill_id:
                        type: integer
                      bill_total:
                        type: number
                      total_tracked:
                        type: number
                      total_available:
                        type: number
                      lines:
                        type: array
                        items:
                          type: object
                          properties:
                            bill_line_id:
                              type: integer
                            description:
                              type: string
                            line_total:
                              type: number
                            already_tracked:
                              type: number
                            available_for_tracking:
                              type: number
                            tracking_percentage:
                              type: number
                  status:
                    type: string
                example:
                  data:
                    bill_id: 15
                    bill_total: 2500.0
                    total_tracked: 1850.0
                    total_available: 650.0
                    lines:
                    - bill_line_id: 31
                      description: Ocean freight (container MSKU1234567)
                      line_total: 1850.0
                      already_tracked: 1850.0
                      available_for_tracking: 0.0
                      tracking_percentage: 100.0
                    - bill_line_id: 32
                      description: Import duty (HS 8516.71)
                      line_total: 650.0
                      already_tracked: 0.0
                      available_for_tracking: 650.0
                      tracking_percentage: 0.0
                  status: success
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No query results for model [App\Models\Bill] 999
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: purchase-orders:read
      operationId: get-api-bills-bill-lines-availability
  /api/bills/{bill}/lines/{billLine}/availability:
    get:
      tags:
      - Bills
      summary: Get Bill Line Availability
      description: 'Get the tracking availability for a single bill line: its total,
        how much has already been tracked as cost entries, and how much is still available.


        :::info[Required scope: `purchase-orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Response fields:

        - `line_total` - The line''s extended total.

        - `already_tracked` - Amount of this line already covered by cost entries.

        - `available_for_tracking` - Remainder that can still be tracked.

        - `tracking_percentage` - Tracked amount as a percentage of the line total
        (0 for zero-total lines).


        Returns 404 when the line exists but does not belong to the given bill.


        Use this before calling `POST /api/bills/:bill/cost-entries` with `scope:
        "lines"` to validate a single allocation amount.


        Authentication: Requires Bearer token. Scope: `purchase-orders` (read/write).'
      parameters:
      - name: bill
        in: path
        schema:
          type: integer
        required: true
        description: Bill ID
        example: '15'
      - name: billLine
        in: path
        schema:
          type: integer
        required: true
        description: Bill line ID (must belong to the bill)
        example: '32'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      bill_line_id:
                        type: integer
                      description:
                        type: string
                      line_total:
                        type: number
                      already_tracked:
                        type: number
                      available_for_tracking:
                        type: number
                      tracking_percentage:
                        type: number
                  status:
                    type: string
                example:
                  data:
                    bill_line_id: 32
                    description: Import duty (HS 8516.71)
                    line_total: 650.0
                    already_tracked: 250.0
                    available_for_tracking: 400.0
                    tracking_percentage: 38.46
                  status: success
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 404 Not Found - line not on this bill
                  value:
                    message: Bill line does not belong to this bill
                    status: failure
                example-1:
                  summary: 404 Not Found
                  value:
                    message: No query results for model [App\Models\Bill] 999
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: purchase-orders:read
      operationId: get-api-bills-bill-lines-billline-availability
  /api/bills/{id}/payments:
    get:
      tags:
      - Bills
      summary: List Bill Payments
      description: 'Lists all payments recorded against a landed-cost bill (supplier
        payments applied to the bill). Payments two-way sync with the connected accounting
        provider.


        Authentication: Requires Bearer token.'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        amount:
                          type: number
                        cost:
                          type: integer
                        payment_date:
                          type: string
                        payment_type:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        external_reference:
                          type: string
                        type:
                          type: string
                          nullable: true
                        currency_code:
                          type: string
                        sales_credit_allocation:
                          type: string
                          nullable: true
                example:
                  data:
                  - id: 12
                    amount: 250.0
                    cost: 0
                    payment_date: '2026-07-09T00:00:00.000000Z'
                    payment_type:
                      id: 3
                      name: Bank Transfer
                    external_reference: WIRE-99182
                    type: null
                    currency_code: USD
                    sales_credit_allocation: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-bills-id-payments
    post:
      tags:
      - Bills
      summary: Add Bill Payment
      description: 'Records a payment against a landed-cost bill and recalculates
        the bill''s paid status. The payment is pushed to the connected accounting
        provider (Xero / QuickBooks Online).


        Fields:

        - payment_date (optional, date, defaults to today)

        - payment_type_id (required, an existing payment type)

        - amount (required, numeric, must be greater than 0)

        - external_reference (optional, string, max 255)

        - currency_id (optional; defaults to the bill''s currency)


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                payment_date:
                  type: string
                payment_type_id:
                  type: integer
                amount:
                  type: integer
                external_reference:
                  type: string
                currency_id:
                  type: integer
              example:
                payment_date: '2026-07-09'
                payment_type_id: 3
                amount: 250
                external_reference: WIRE-99182
                currency_id: 1
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      amount:
                        type: number
                      cost:
                        type: integer
                      payment_date:
                        type: string
                      payment_type:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      external_reference:
                        type: string
                      type:
                        type: string
                        nullable: true
                      currency_code:
                        type: string
                      sales_credit_allocation:
                        type: string
                        nullable: true
                  message:
                    type: string
                example:
                  data:
                    id: 12
                    amount: 250.0
                    cost: 0
                    payment_date: '2026-07-09T00:00:00.000000Z'
                    payment_type:
                      id: 3
                      name: Bank Transfer
                    external_reference: WIRE-99182
                    type: null
                    currency_code: USD
                    sales_credit_allocation: null
                  message: Bill payment created successfully
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      amount:
                        type: array
                        items:
                          type: string
                example:
                  message: The amount is more than the remaining balance.
                  errors:
                    amount:
                    - The amount is more than the remaining balance.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-bills-id-payments
  /api/bills/{id}/payments/{id2}:
    put:
      tags:
      - Bills
      summary: Update Bill Payment
      description: 'Updates an existing bill payment and recalculates the bill''s
        paid status. The change is re-synced to the connected accounting provider.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                payment_date:
                  type: string
                amount:
                  type: integer
                external_reference:
                  type: string
              example:
                payment_date: '2026-07-09'
                amount: 300
                external_reference: WIRE-99182
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      - name: id2
        in: path
        required: true
        schema:
          type: string
        description: The id2 identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      amount:
                        type: number
                      cost:
                        type: integer
                      payment_date:
                        type: string
                      payment_type:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      external_reference:
                        type: string
                      type:
                        type: string
                        nullable: true
                      currency_code:
                        type: string
                      sales_credit_allocation:
                        type: string
                        nullable: true
                  message:
                    type: string
                example:
                  data:
                    id: 12
                    amount: 300.0
                    cost: 0
                    payment_date: '2026-07-09T00:00:00.000000Z'
                    payment_type:
                      id: 3
                      name: Bank Transfer
                    external_reference: WIRE-99182
                    type: null
                    currency_code: USD
                    sales_credit_allocation: null
                  message: Bill payment updated successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-bills-id-payments-id2
    delete:
      tags:
      - Bills
      summary: Delete Bill Payment
      description: 'Deletes a bill payment and recalculates the bill''s paid status.
        The corresponding provider payment is voided/removed on the connected accounting
        provider.


        Authentication: Requires Bearer token.'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      - name: id2
        in: path
        required: true
        schema:
          type: string
        description: The id2 identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Bill payment deleted successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-bills-id-payments-id2
  /api/bills/{id}/activity-log:
    get:
      tags:
      - Bills
      summary: Get Bill Activity Log
      description: 'Paginated audit history for a bill — who changed what and when,
        including field-level before/after values.


        Authentication: Requires Bearer token.'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        description:
                          type: string
                        event:
                          type: string
                        subject_type:
                          type: string
                        subject_id:
                          type: integer
                        properties:
                          type: object
                          properties:
                            source:
                              type: string
                            old:
                              type: object
                              properties:
                                invoice_number:
                                  type: string
                            attributes:
                              type: object
                              properties:
                                invoice_number:
                                  type: string
                        causer_name:
                          type: string
                        created_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 481
                    description: updated
                    event: updated
                    subject_type: Bill
                    subject_id: 1
                    properties:
                      source: manual
                      old:
                        invoice_number: INV-2024-000
                      attributes:
                        invoice_number: INV-2024-001
                    causer_name: Jane Doe
                    created_at: '2026-07-09T10:00:00.000000Z'
                  current_page: 1
                  last_page: 1
                  per_page: 15
                  total: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-bills-id-activity-log
  /api/bills/{id}/notes:
    get:
      tags:
      - Bills
      summary: List Bill Notes
      description: 'Paginated notes attached to a bill, newest first.


        Authentication: Requires Bearer token.'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        note:
                          type: string
                        is_pinned:
                          type: boolean
                        link_type:
                          type: string
                        link_id:
                          type: integer
                        user:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        created_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 7
                    note: Awaiting supplier credit note.
                    is_pinned: false
                    link_type: bill
                    link_id: 1
                    user:
                      id: 2
                      name: Jane Doe
                    created_at: '2026-07-09T10:00:00.000000Z'
                  current_page: 1
                  last_page: 1
                  per_page: 15
                  total: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-bills-id-notes
    post:
      tags:
      - Bills
      summary: Add Bill Note
      description: 'Adds a note to a bill.


        Fields:

        - note (required, string)


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                note:
                  type: string
              example:
                note: Awaiting supplier credit note.
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      note:
                        type: string
                      is_pinned:
                        type: boolean
                      link_type:
                        type: string
                      link_id:
                        type: integer
                      user:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      created_at:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 7
                    note: Awaiting supplier credit note.
                    is_pinned: false
                    link_type: bill
                    link_id: 1
                    user:
                      id: 2
                      name: Jane Doe
                    created_at: '2026-07-09T10:00:00.000000Z'
                  message: Note created successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-bills-id-notes
  /api/bills/{id}/notes/{id2}/toggle-pin:
    put:
      tags:
      - Bills
      summary: Toggle Bill Note Pin
      description: 'Pins or unpins a bill note (toggles its pinned state).


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      - name: id2
        in: path
        required: true
        schema:
          type: string
        description: The id2 identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      note:
                        type: string
                      is_pinned:
                        type: boolean
                      link_type:
                        type: string
                      link_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    id: 7
                    note: Awaiting supplier credit note.
                    is_pinned: true
                    link_type: bill
                    link_id: 1
                  message: Note pinned
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-bills-id-notes-id2-toggle-pin
  /api/bills/{id}/notes/{id2}:
    delete:
      tags:
      - Bills
      summary: Delete Bill Note
      description: 'Deletes a bill note.


        Authentication: Requires Bearer token.'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      - name: id2
        in: path
        required: true
        schema:
          type: string
        description: The id2 identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Note deleted successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-bills-id-notes-id2
  /api/bills/{id}/tags:
    put:
      tags:
      - Bills
      summary: Sync Bill Tags
      description: 'Replaces the full set of tags on a bill with the provided list.


        Fields:

        - tags (required, array of strings, each max 64 chars)


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                tags:
                  type: array
                  items:
                    type: string
              example:
                tags:
                - freight
                - customs
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tags:
                        type: array
                        items:
                          type: string
                  message:
                    type: string
                example:
                  data:
                    tags:
                    - freight
                    - customs
                  message: Bill tags updated successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-bills-id-tags
  /api/bills/{id}/documents:
    get:
      tags:
      - Bills
      summary: List Bill Documents
      description: 'Lists the scanned source invoice documents linked to a bill.


        Authentication: Requires Bearer token.'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        file_name:
                          type: string
                        status:
                          type: string
                        page_count:
                          type: integer
                        created_at:
                          type: string
                example:
                  data:
                  - id: 90
                    file_name: supplier-invoice-INV-2024-001.pdf
                    status: confirmed
                    page_count: 2
                    created_at: '2026-07-09T10:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-bills-id-documents
  /api/bills/{bill}/reset-due-date:
    post:
      tags:
      - Bills
      summary: Reset Bill Due Date to Term
      description: 'Discards a manually-overridden due date on a landed-cost bill
        and re-derives it from the bill''s effective payment term (its own term, else
        the linked purchase order''s term, else the supplier default). The response''s
        `due_date_source` returns to `derived` (or `none` when no term is resolvable).


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: bill
        in: path
        schema:
          type: string
        required: true
        description: The bill ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      supplier_id:
                        type: integer
                      supplier_name:
                        type: string
                      invoice_number:
                        type: string
                      invoice_date:
                        type: string
                      due_date:
                        type: string
                      due_date_source:
                        type: string
                      payment_term_id:
                        type: integer
                      payment_term_name:
                        type: string
                      payment_term_snapshot:
                        type: object
                        properties:
                          payment_term_id:
                            type: integer
                          name:
                            type: string
                          net_days:
                            type: integer
                          due_date_type:
                            type: string
                          discount_percentage:
                            type: integer
                          discount_days:
                            type: string
                            nullable: true
                          captured_at:
                            type: string
                      term_diverges_from_po:
                        type: boolean
                      discount_due_date:
                        type: string
                        nullable: true
                      discount_amount:
                        type: string
                        nullable: true
                      discount_available:
                        type: boolean
                      payment_due_status:
                        type: string
                      days_until_due:
                        type: integer
                      link_type:
                        type: string
                      link_id:
                        type: integer
                example:
                  data:
                    id: 321
                    supplier_id: 88
                    supplier_name: DHL Forwarding
                    invoice_number: DHL-88213
                    invoice_date: '2026-07-13'
                    due_date: '2026-07-28'
                    due_date_source: derived
                    payment_term_id: 4
                    payment_term_name: Net 15
                    payment_term_snapshot:
                      payment_term_id: 4
                      name: Net 15
                      net_days: 15
                      due_date_type: from_invoice_date
                      discount_percentage: 0
                      discount_days: null
                      captured_at: '2026-07-13T12:00:00+00:00'
                    term_diverges_from_po: true
                    discount_due_date: null
                    discount_amount: null
                    discount_available: false
                    payment_due_status: not_due
                    days_until_due: 15
                    link_type: purchase_order
                    link_id: 707
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-bills-bill-reset-due-date
  /api/amortization-schedules/{amortizationSchedule}:
    get:
      tags:
      - Amortization Schedules
      summary: Get Amortization Schedule
      description: 'Get a single amortization schedule, including its full list of
        periods and the allocation configuration that is applied when each period
        is processed.


        :::info[Required scope: `purchase-orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        An amortization schedule spreads a cost entry''s unallocated amount over a
        series of periods (for example, an annual customs bond premium spread over
        four quarterly periods). Schedules are created with `POST /api/cost-entries/:costEntry/amortization-schedule`
        (documented under Cost Entries).


        Response fields:

        - `start_date` / `end_date` - The date range covered by the schedule; `end_date`
        is the last period''s end date.

        - `total_periods`, `frequency` (`daily`, `weekly`, `monthly`, `quarterly`,
        `annually`) and `method` (`straight_line`, `front_loaded`, `back_loaded`)
        - How the amount is distributed over time.

        - `total_amount` / `amount_per_period` - The amount being amortized and the
        per-period amount (the final period absorbs any rounding difference).

        - `is_fully_processed`, `pending_periods_count`, `processed_periods_count`
        - Processing progress.

        - `allocation_config` - Where each period''s amount is allocated when processed:
        `allocatable_type` is one of `product`, `brand`, `supplier`, `sales_channel`;
        `allocatable_id` is the target entity''s ID; `proration_strategy` is one of
        `revenue_based`, `cost_based`, `weight_based`, `volume_based`, `quantity_based`,
        `specific_line`, `manual`. `allocatable_name` is null on this endpoint; use
        the status endpoint to resolve the target''s display name.

        - `periods` - Every period with its number, date range, amount, and processed
        state.


        Authentication: Requires Bearer token. Scope: `purchase-orders` (read/write).'
      parameters:
      - name: amortizationSchedule
        in: path
        schema:
          type: integer
        required: true
        description: Amortization schedule ID
        example: '7'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      cost_entry_id:
                        type: integer
                      start_date:
                        type: string
                      end_date:
                        type: string
                      total_periods:
                        type: integer
                      frequency:
                        type: string
                      method:
                        type: string
                      total_amount:
                        type: number
                      amount_per_period:
                        type: number
                      is_fully_processed:
                        type: boolean
                      pending_periods_count:
                        type: integer
                      processed_periods_count:
                        type: integer
                      allocation_config:
                        type: object
                        properties:
                          allocatable_type:
                            type: string
                          allocatable_id:
                            type: integer
                          allocatable_name:
                            type: string
                            nullable: true
                          proration_strategy:
                            type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      periods:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            amortization_schedule_id:
                              type: integer
                            period_number:
                              type: integer
                            period_start:
                              type: string
                            period_end:
                              type: string
                            amount:
                              type: number
                            is_processed:
                              type: boolean
                            processed_at:
                              type: string
                            created_at:
                              type: string
                            updated_at:
                              type: string
                  status:
                    type: string
                example:
                  data:
                    id: 7
                    cost_entry_id: 42
                    start_date: '2026-01-01'
                    end_date: '2026-12-31'
                    total_periods: 4
                    frequency: quarterly
                    method: straight_line
                    total_amount: 2400.0
                    amount_per_period: 600.0
                    is_fully_processed: false
                    pending_periods_count: 2
                    processed_periods_count: 2
                    allocation_config:
                      allocatable_type: product
                      allocatable_id: 123
                      allocatable_name: null
                      proration_strategy: specific_line
                    created_at: '2026-01-05T09:30:00.000000Z'
                    updated_at: '2026-07-01T02:15:03.000000Z'
                    periods:
                    - id: 101
                      amortization_schedule_id: 7
                      period_number: 1
                      period_start: '2026-01-01'
                      period_end: '2026-03-31'
                      amount: 600.0
                      is_processed: true
                      processed_at: '2026-04-01T02:15:07.000000Z'
                      created_at: '2026-01-05T09:30:00.000000Z'
                      updated_at: '2026-04-01T02:15:07.000000Z'
                    - id: 102
                      amortization_schedule_id: 7
                      period_number: 2
                      period_start: '2026-04-01'
                      period_end: '2026-06-30'
                      amount: 600.0
                      is_processed: true
                      processed_at: '2026-07-01T02:15:03.000000Z'
                      created_at: '2026-01-05T09:30:00.000000Z'
                      updated_at: '2026-07-01T02:15:03.000000Z'
                    - id: 103
                      amortization_schedule_id: 7
                      period_number: 3
                      period_start: '2026-07-01'
                      period_end: '2026-09-30'
                      amount: 600.0
                      is_processed: false
                      processed_at: null
                      created_at: '2026-01-05T09:30:00.000000Z'
                      updated_at: '2026-01-05T09:30:00.000000Z'
                    - id: 104
                      amortization_schedule_id: 7
                      period_number: 4
                      period_start: '2026-10-01'
                      period_end: '2026-12-31'
                      amount: 600.0
                      is_processed: false
                      processed_at: null
                      created_at: '2026-01-05T09:30:00.000000Z'
                      updated_at: '2026-01-05T09:30:00.000000Z'
                  status: success
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No query results for model [App\Models\AmortizationSchedule]
                    999
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: purchase-orders:read
      operationId: get-api-amortization-schedules-amortizationschedule
    delete:
      tags:
      - Amortization Schedules
      summary: Delete Amortization Schedule
      description: 'Delete an amortization schedule together with all of its periods.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        There is no guard against deleting a schedule that has already-processed periods:
        any cost allocations that were created by processing this schedule''s periods
        are also deleted, effectively reversing those allocations. The whole operation
        runs in a single transaction, and the parent cost entry''s allocation status
        is recalculated afterwards (for example back to `pending_allocation` if nothing
        else is allocated against it).


        The cost entry itself is not deleted - a new schedule can be created for it
        afterwards with `POST /api/cost-entries/:costEntry/amortization-schedule`.


        Returns 200 with a confirmation message (not 204).


        Authentication: Requires Bearer token. Scope: `purchase-orders` (read/write).'
      parameters:
      - name: amortizationSchedule
        in: path
        schema:
          type: integer
        required: true
        description: Amortization schedule ID
        example: '7'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  status:
                    type: string
                example:
                  message: Amortization schedule deleted successfully
                  status: success
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No query results for model [App\Models\AmortizationSchedule]
                    999
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: purchase-orders:write
      operationId: delete-api-amortization-schedules-amortizationschedule
  /api/amortization-schedules/{amortizationSchedule}/status:
    get:
      tags:
      - Amortization Schedules
      summary: Get Amortization Schedule Status
      description: 'Get a compact processing-progress summary for an amortization
        schedule - useful for dashboards and polling without fetching the full period
        list.


        :::info[Required scope: `purchase-orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Response fields:

        - `total_periods`, `processed_periods`, `pending_periods`, `is_fully_processed`
        - Progress counters.

        - `total_amount` / `amount_per_period` - The amount being amortized.

        - `next_period` - The next unprocessed period (`period_number`, `period_start`,
        `period_end`, `amount`, and `is_due`, which is true once the period''s end
        date has passed). Null when every period has been processed.

        - `allocation_config` - The stored allocation target: `allocatable_type` (`product`,
        `brand`, `supplier`, `sales_channel`), `allocatable_id`, `allocatable_name`
        (the target''s name or SKU), and `proration_strategy`.


        Schedules are created with `POST /api/cost-entries/:costEntry/amortization-schedule`
        (documented under Cost Entries).


        Authentication: Requires Bearer token. Scope: `purchase-orders` (read/write).'
      parameters:
      - name: amortizationSchedule
        in: path
        schema:
          type: integer
        required: true
        description: Amortization schedule ID
        example: '7'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      cost_entry_id:
                        type: integer
                      total_periods:
                        type: integer
                      processed_periods:
                        type: integer
                      pending_periods:
                        type: integer
                      is_fully_processed:
                        type: boolean
                      total_amount:
                        type: number
                      amount_per_period:
                        type: number
                      next_period:
                        type: object
                        properties:
                          period_number:
                            type: integer
                          period_start:
                            type: string
                          period_end:
                            type: string
                          amount:
                            type: number
                          is_due:
                            type: boolean
                      allocation_config:
                        type: object
                        properties:
                          allocatable_type:
                            type: string
                          allocatable_id:
                            type: integer
                          allocatable_name:
                            type: string
                          proration_strategy:
                            type: string
                  status:
                    type: string
                example:
                  data:
                    id: 7
                    cost_entry_id: 42
                    total_periods: 4
                    processed_periods: 2
                    pending_periods: 2
                    is_fully_processed: false
                    total_amount: 2400.0
                    amount_per_period: 600.0
                    next_period:
                      period_number: 3
                      period_start: '2026-07-01'
                      period_end: '2026-09-30'
                      amount: 600.0
                      is_due: false
                    allocation_config:
                      allocatable_type: product
                      allocatable_id: 123
                      allocatable_name: Espresso Machine E61 Group Head
                      proration_strategy: specific_line
                  status: success
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No query results for model [App\Models\AmortizationSchedule]
                    999
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: purchase-orders:read
      operationId: get-api-amortization-schedules-amortizationschedule-status
  /api/amortization-schedules/{amortizationSchedule}/process:
    post:
      tags:
      - Amortization Schedules
      summary: Process Amortization Schedule Due Periods
      description: 'Process every due period on an amortization schedule. A period
        is due when it is unprocessed and its end date is on or before `as_of_date`
        (defaults to today). Processing each period creates the cost allocations defined
        by the schedule''s stored allocation configuration and updates the parent
        cost entry''s allocation status.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        This endpoint runs synchronously - allocations are created before the response
        returns, and `processed_count` reports how many periods were processed (0
        when nothing is due). A daily background task also processes due periods automatically
        for schedules that have a stored allocation configuration, so this endpoint
        is mainly for processing ahead of that run or applying a one-off target override.


        Request fields (all optional):

        - `as_of_date` - Process periods due as of this date instead of today (date,
        e.g. `2026-07-07`).

        - `allocatable_type` + `allocatable_id` - Override the stored allocation target
        for this run only. `allocatable_type` is one of `product`, `brand`, `supplier`,
        `sales_channel`; `allocatable_id` is required whenever `allocatable_type`
        is sent. When omitted, the schedule''s stored configuration is used (`used_stored_config:
        true` in the response).

        - `proration_strategy` - Only used with an override target; one of `revenue_based`,
        `cost_based`, `weight_based`, `volume_based`, `quantity_based`, `specific_line`,
        `manual` (defaults to `specific_line`).


        Returns 422 when an override target does not exist, or when no override is
        sent and the schedule has no stored allocation configuration.


        Authentication: Requires Bearer token. Scope: `purchase-orders` (read/write).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                as_of_date:
                  type: string
              example:
                as_of_date: '2026-07-07'
      parameters:
      - name: amortizationSchedule
        in: path
        schema:
          type: integer
        required: true
        description: Amortization schedule ID
        example: '7'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 OK
                  value:
                    data:
                      processed_count: 2
                      used_stored_config: true
                    message: Processed 2 periods
                    status: success
                example-1:
                  summary: 200 OK - nothing due
                  value:
                    data:
                      processed_count: 0
                      used_stored_config: true
                    message: Processed 0 periods
                    status: success
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No query results for model [App\Models\AmortizationSchedule]
                    999
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 422 Unprocessable Entity - override target not found
                  value:
                    message: 'Invalid allocatable: product with ID 999 not found'
                    status: failure
                example-1:
                  summary: 422 Validation Error
                  value:
                    message: The allocatable id field is required when allocatable
                      type is present.
                    errors:
                      allocatable_id:
                      - The allocatable id field is required when allocatable type
                        is present.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: purchase-orders:write
      operationId: post-api-amortization-schedules-amortizationschedule-process
  /api/financial-alerts:
    post:
      tags:
      - Configuration
      summary: Create Financial Alert
      description: 'Creates a new financial alert record. Typically, alerts are auto-generated
        by the process endpoint, but this allows manual creation.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                financial_alert_classification_id:
                  type: integer
                note:
                  type: string
              example:
                financial_alert_classification_id: 2
                note: Pricing error — needs review
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      financial_alert_classification_id:
                        type: integer
                      note:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 16
                    financial_alert_classification_id: 2
                    note: Pricing error — needs review
                  message: Financial alert updated successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-session-only: true
      operationId: post-api-financial-alerts
  /api/financial-alerts/{financial_alert}:
    put:
      tags:
      - Configuration
      summary: Update Financial Alert
      description: 'Updates a financial alert''s classification and/or note.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                financial_alert_classification_id:
                  type: integer
                note:
                  type: string
              example:
                financial_alert_classification_id: 3
                note: Investigated — supplier overcharge confirmed
      parameters:
      - name: financial_alert
        in: path
        schema:
          type: integer
        required: true
        example: '15'
        description: The financial alert ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      classification:
                        type: string
                      classification_id:
                        type: integer
                      note:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 15
                    classification: Supplier Issue
                    classification_id: 3
                    note: Investigated — supplier overcharge confirmed
                  message: Financial alert updated successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-session-only: true
      operationId: put-api-financial-alerts-financial-alert
    delete:
      tags:
      - Configuration
      summary: Delete Financial Alert
      description: 'Deletes a financial alert record.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: financial_alert
        in: path
        schema:
          type: integer
        required: true
        example: '15'
        description: The financial alert ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: financial alerts deleted successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-session-only: true
      operationId: delete-api-financial-alerts-financial-alert
  /api/financial-alerts/{financialAlert}/archive:
    put:
      tags:
      - Configuration
      summary: Archive Alert
      description: 'Archives (resolves) a single financial alert, recording the archiving
        user and timestamp.


        :::info[Required scope: `accounting:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: financialAlert
        in: path
        schema:
          type: integer
        required: true
        example: '15'
        description: The financial alert ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      archived_at:
                        type: string
                      archived_by_user:
                        type: string
                      is_resolved:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 15
                    archived_at: '2025-04-23T10:00:00.000000Z'
                    archived_by_user: Admin User
                    is_resolved: 'true'
                  message: Financial alert archived successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: accounting:write
      operationId: put-api-financial-alerts-financialalert-archive
  /api/financial-alerts/{financialAlert}/unarchive:
    put:
      tags:
      - Configuration
      summary: Unarchive Alert
      description: 'Unarchives (re-opens) a previously archived financial alert.


        :::info[Required scope: `accounting:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: financialAlert
        in: path
        schema:
          type: integer
        required: true
        example: '15'
        description: The financial alert ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      archived_at:
                        type: string
                        nullable: true
                      archived_by_user:
                        type: string
                        nullable: true
                      is_resolved:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 15
                    archived_at: null
                    archived_by_user: null
                    is_resolved: 'false'
                  message: Financial alert unarchived successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: accounting:write
      operationId: put-api-financial-alerts-financialalert-unarchive
  /api/financial-alerts/archive:
    put:
      tags:
      - Configuration
      summary: Bulk Archive Alerts
      description: 'Archives multiple financial alerts at once.


        :::info[Required scope: `accounting:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Fields:

        - ids (required): Array of financial alert IDs to archive'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 15
                - 16
                - 17
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: financial alerts bulk archived successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: accounting:write
      operationId: put-api-financial-alerts-archive
  /api/financial-alerts/unarchive:
    put:
      tags:
      - Configuration
      summary: Bulk Unarchive Alerts
      description: 'Unarchives multiple financial alerts at once.


        :::info[Required scope: `accounting:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Fields:

        - ids (required): Array of financial alert IDs to unarchive'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 15
                - 16
                - 17
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: financial alerts bulk unarchived successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: accounting:write
      operationId: put-api-financial-alerts-unarchive
  /api/financial-alerts/update:
    patch:
      tags:
      - Configuration
      summary: Bulk Update Alerts
      description: 'Bulk updates the classification and/or note for multiple financial
        alerts.


        :::info[Required scope: `accounting:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Fields:

        - ids (required): Array of financial alert IDs to update

        - classification (optional): Classification ID to assign

        - note (optional): Note to set on all specified alerts'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
                classification:
                  type: integer
                note:
                  type: string
              example:
                ids:
                - 15
                - 16
                - 17
                classification: 2
                note: Reviewed and classified
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: financial alerts bulk updated successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: accounting:write
      operationId: patch-api-financial-alerts-update
  /api/financial-alerts/import/preview:
    post:
      tags:
      - Configuration
      summary: Preview Import
      description: 'Previews an import file for financial alerts before committing.
        Returns a summary of what will be imported and any errors.


        :::info[Required scope: `accounting:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Content-Type: multipart/form-data


        Fields:

        - file (required): The CSV/Excel file to preview'
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                file:
                  type: string
                  description: CSV/Excel file to preview
                  format: binary
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      total_rows:
                        type: integer
                      valid_rows:
                        type: integer
                      errors:
                        type: array
                        items:
                          type: object
                          properties:
                            row:
                              type: integer
                            message:
                              type: string
                      preview:
                        type: array
                        items:
                          type: object
                          properties:
                            sku:
                              type: string
                            alert_type:
                              type: string
                            profit:
                              type: number
                example:
                  data:
                    total_rows: 50
                    valid_rows: 48
                    errors:
                    - row: 12
                      message: 'Invalid SKU: SKU-999'
                    preview:
                    - sku: WIDGET-A
                      alert_type: LOSS
                      profit: -35.0
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: accounting:write
      operationId: post-api-financial-alerts-import-preview
  /api/financial-alerts/import:
    post:
      tags:
      - Configuration
      summary: Import Alerts
      description: 'Imports financial alerts from a CSV/Excel file.


        :::info[Required scope: `accounting:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Content-Type: multipart/form-data


        Fields:

        - file (required): The CSV/Excel file to import'
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                file:
                  type: string
                  description: CSV/Excel file to import
                  format: binary
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      imported:
                        type: integer
                      skipped:
                        type: integer
                example:
                  message: Import completed successfully
                  data:
                    imported: 48
                    skipped: 2
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: accounting:write
      operationId: post-api-financial-alerts-import
  /api/financial-alerts/dashboard:
    get:
      tags:
      - Configuration
      summary: Get Dashboard Data
      description: 'Returns a summary of archived (resolved) financial alerts grouped
        by alert type. Used for the financial alerts dashboard overview.


        :::info[Required scope: `accounting:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        alert_type:
                          type: string
                        count:
                          type: integer
                example:
                  data:
                  - alert_type: LOSS
                    count: 24
                  - alert_type: LOW_MARGIN
                    count: 37
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: accounting:read
      operationId: get-api-financial-alerts-dashboard
  /api/financial-alerts/reports:
    get:
      tags:
      - Configuration
      summary: Get Report Data
      description: 'Returns reporting data for financial alerts including classification
        breakdown and resolution breakdown. Used for the reports page.


        :::info[Required scope: `accounting:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      classification_breakdown:
                        type: array
                        items:
                          type: object
                          properties:
                            count:
                              type: integer
                            classification:
                              type: string
                      resolution_breakdown:
                        type: array
                        items:
                          type: object
                          properties:
                            count:
                              type: integer
                            resolution:
                              type: string
                example:
                  data:
                    classification_breakdown:
                    - count: 15
                      classification: Pricing Error
                    - count: 9
                      classification: Supplier Issue
                    - count: 3
                      classification: null
                    resolution_breakdown:
                    - count: 42
                      resolution: Resolved
                    - count: 18
                      resolution: Unresolved
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: accounting:read
      operationId: get-api-financial-alerts-reports
  /api/financial-alerts/process:
    post:
      tags:
      - Configuration
      summary: Process Alerts
      description: 'Triggers the financial alert processing job, which scans all sales
        order lines for low margin or loss conditions and creates/deletes alerts accordingly.


        :::info[Required scope: `accounting:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Financial alerts processed successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: accounting:write
      operationId: post-api-financial-alerts-process
  /api/financial-alerts/classifications:
    get:
      tags:
      - Configuration
      summary: List Classifications
      description: 'Returns all financial alert classification categories. Classifications
        are used to tag alerts with a reason or resolution type (e.g., Pricing Error,
        Supplier Issue).


        :::info[Required scope: `accounting:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                example:
                  data:
                  - id: 1
                    name: Pricing Error
                  - id: 2
                    name: Supplier Issue
                  - id: 3
                    name: One-off Promotion
                  - id: 4
                    name: Expected Loss
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: accounting:read
      operationId: get-api-financial-alerts-classifications
    post:
      tags:
      - Configuration
      summary: Create Classification
      description: 'Creates a new financial alert classification category.


        :::info[Required scope: `accounting:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Fields:

        - name (required): Name of the classification'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
              example:
                name: Competitor Pricing
      parameters: []
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 5
                    name: Competitor Pricing
                  message: financial alert classification created successfully
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      name:
                        type: array
                        items:
                          type: string
                example:
                  message: The name field is required.
                  errors:
                    name:
                    - The name field is required.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: accounting:write
      operationId: post-api-financial-alerts-classifications
  /api/financial-alerts/classifications/{classification}:
    get:
      tags:
      - Configuration
      summary: Get Classification
      description: 'Returns a single financial alert classification by ID.


        :::info[Required scope: `accounting:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: classification
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The classification ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                example:
                  data:
                    id: 1
                    name: Pricing Error
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: accounting:read
      operationId: get-api-financial-alerts-classifications-classification
    put:
      tags:
      - Configuration
      summary: Update Classification
      description: 'Updates a financial alert classification name.


        :::info[Required scope: `accounting:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
              example:
                name: Pricing / Margin Error
      parameters:
      - name: classification
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The classification ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                example:
                  data:
                    id: 1
                    name: Pricing / Margin Error
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: accounting:write
      operationId: put-api-financial-alerts-classifications-classification
    delete:
      tags:
      - Configuration
      summary: Delete Classification
      description: 'Deletes a financial alert classification.


        :::info[Required scope: `accounting:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: classification
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The classification ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: financial alert classification deleted successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: accounting:write
      operationId: delete-api-financial-alerts-classifications-classification
  /api/financial-line-types:
    get:
      tags:
      - Financial Line Types
      summary: List Financial Line Types
      description: 'Returns all financial line types for the organization.


        :::info[Required scope: `settings:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: array
                items:
                  type: object
                  properties:
                    id:
                      type: integer
                    name:
                      type: string
                    classification:
                      type: string
                    allocate_to_products:
                      type: boolean
                    proration_strategy:
                      type: string
                    nominal_code_id:
                      type: string
                      nullable: true
                    created_at:
                      type: string
                    updated_at:
                      type: string
                example:
                - id: 1
                  name: Freight
                  classification: cost
                  allocate_to_products: true
                  proration_strategy: weight_based
                  nominal_code_id: null
                  created_at: '2024-01-01T00:00:00.000000Z'
                  updated_at: '2024-01-01T00:00:00.000000Z'
                - id: 2
                  name: Product Sales
                  classification: revenue
                  allocate_to_products: false
                  proration_strategy: revenue_based
                  nominal_code_id: 5
                  created_at: '2024-01-01T00:00:00.000000Z'
                  updated_at: '2024-02-15T10:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: settings:read
      operationId: get-api-financial-line-types
    post:
      tags:
      - Financial Line Types
      summary: Create Financial Line Type
      description: 'Creates a new financial line type.


        :::info[Required scope: `settings:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Fields:

        - name (required, string) — Name of the financial line type

        - classification (required, string) — One of: revenue, cost

        - allocate_to_products (optional, boolean) — Whether to allocate costs/revenue
        to products

        - proration_strategy (optional, string) — One of: revenue_based, cost_based,
        weight_based, volume_based, quantity_based, specific_line, manual

        - nominal_code_id (optional, integer|null) — ID of associated nominal code


        **Requires permission:** `financial_line_types.create`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                classification:
                  type: string
                allocate_to_products:
                  type: boolean
                proration_strategy:
                  type: string
                nominal_code_id:
                  type: string
                  nullable: true
              example:
                name: Freight
                classification: cost
                allocate_to_products: true
                proration_strategy: weight_based
                nominal_code_id: null
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: integer
                  name:
                    type: string
                  classification:
                    type: string
                  allocate_to_products:
                    type: boolean
                  proration_strategy:
                    type: string
                  nominal_code_id:
                    type: string
                    nullable: true
                  created_at:
                    type: string
                  updated_at:
                    type: string
                example:
                  id: 3
                  name: Freight
                  classification: cost
                  allocate_to_products: true
                  proration_strategy: weight_based
                  nominal_code_id: null
                  created_at: '2024-06-01T09:00:00.000000Z'
                  updated_at: '2024-06-01T09:00:00.000000Z'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      name:
                        type: array
                        items:
                          type: string
                      classification:
                        type: array
                        items:
                          type: string
                example:
                  message: The name field is required.
                  errors:
                    name:
                    - The name field is required.
                    classification:
                    - The selected classification is invalid.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: settings:write
      operationId: post-api-financial-line-types
    delete:
      tags:
      - Financial Line Types
      summary: Bulk Delete Financial Line Types
      description: 'Bulk deletes multiple financial line types by their IDs.


        :::info[Required scope: `settings:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Fields:

        - ids (required, array) — Array of financial line type IDs to delete


        **Requires permission:** `financial_line_types.delete`'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Records deleted successfully.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: settings:write
      operationId: delete-api-financial-line-types
  /api/financial-line-types/{financial_line_type}:
    get:
      tags:
      - Financial Line Types
      summary: Get Financial Line Type
      description: 'Returns a single financial line type by ID.


        :::info[Required scope: `settings:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: financial_line_type
        in: path
        schema:
          type: integer
        required: true
        description: Financial line type ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: integer
                  name:
                    type: string
                  classification:
                    type: string
                  allocate_to_products:
                    type: boolean
                  proration_strategy:
                    type: string
                  nominal_code_id:
                    type: string
                    nullable: true
                  created_at:
                    type: string
                  updated_at:
                    type: string
                example:
                  id: 1
                  name: Freight
                  classification: cost
                  allocate_to_products: true
                  proration_strategy: weight_based
                  nominal_code_id: null
                  created_at: '2024-01-01T00:00:00.000000Z'
                  updated_at: '2024-01-01T00:00:00.000000Z'
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No query results for model [App\Models\FinancialLineType]
                    999
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: settings:read
      operationId: get-api-financial-line-types-financial-line-type
    put:
      tags:
      - Financial Line Types
      summary: Update Financial Line Type
      description: 'Updates an existing financial line type. All fields are optional
        on update.


        :::info[Required scope: `settings:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Fields (all optional on update):

        - name (optional, string) — Name of the financial line type

        - classification (optional, string) — One of: revenue, cost

        - allocate_to_products (optional, boolean) — Whether to allocate costs/revenue
        to products

        - proration_strategy (optional, string) — One of: revenue_based, cost_based,
        weight_based, volume_based, quantity_based, specific_line, manual

        - nominal_code_id (optional, integer|null) — ID of associated nominal code


        **Requires permission:** `financial_line_types.update`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                classification:
                  type: string
                allocate_to_products:
                  type: boolean
                proration_strategy:
                  type: string
                nominal_code_id:
                  type: integer
              example:
                name: International Freight
                classification: cost
                allocate_to_products: true
                proration_strategy: volume_based
                nominal_code_id: 12
      parameters:
      - name: financial_line_type
        in: path
        schema:
          type: integer
        required: true
        description: Financial line type ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: integer
                  name:
                    type: string
                  classification:
                    type: string
                  allocate_to_products:
                    type: boolean
                  proration_strategy:
                    type: string
                  nominal_code_id:
                    type: integer
                  created_at:
                    type: string
                  updated_at:
                    type: string
                example:
                  id: 1
                  name: International Freight
                  classification: cost
                  allocate_to_products: true
                  proration_strategy: volume_based
                  nominal_code_id: 12
                  created_at: '2024-01-01T00:00:00.000000Z'
                  updated_at: '2024-06-01T10:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: settings:write
      operationId: put-api-financial-line-types-financial-line-type
    delete:
      tags:
      - Financial Line Types
      summary: Delete Financial Line Type
      description: 'Deletes a financial line type. Returns 400 if the type has associated
        financial lines.


        :::info[Required scope: `settings:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `financial_line_types.delete`'
      parameters:
      - name: financial_line_type
        in: path
        schema:
          type: integer
        required: true
        description: Financial line type ID
        example: '1'
      responses:
        '204':
          description: No Content
          content:
            text/plain:
              schema:
                type: string
                example: ''
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Cannot delete this financial line type because it has financial
                    lines associated with it.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: settings:write
      operationId: delete-api-financial-line-types-financial-line-type
  /api/nominal-codes/list:
    get:
      tags:
      - Configuration
      summary: List Nominal Codes (Dropdown)
      description: 'Returns a lightweight list of all nominal codes (id, code, name,
        type), ordered by code. Intended for dropdown/combo-box lookups.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Every nominal code record is returned independently — no deduplication. Integration
        re-syncs (e.g. QuickBooks Online) can legitimately create multiple rows sharing
        the same code + name; each appears as its own entry with its own id.


        Pass used_by_transactions=1 to restrict the list to nominal codes referenced
        by at least one accounting transaction line — used by the Accounting Transactions
        filter dropdown so unused codes don''t appear as dead filter options.


        Archived nominal codes are excluded automatically.


        The type field is the account type (Revenue, Expense, Asset, Liability, Equity,
        Bank, Current) and can be used for client-side filtering (e.g. asset-only
        dropdowns).


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        code:
                          type: string
                        name:
                          type: string
                        type:
                          type: string
                  status:
                    type: string
                example:
                  data:
                  - id: 1
                    code: '1200'
                    name: Inventory Asset
                    type: Current
                  - id: 4
                    code: '4000'
                    name: Sales Revenue
                    type: Revenue
                  - id: 2
                    code: '5000'
                    name: Cost of Goods Sold
                    type: Expense
                  - id: 3
                    code: '6000'
                    name: Shipping Expense
                    type: Expense
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: get-api-nominal-codes-list
  /api/nominal-codes/{nominal_code}:
    get:
      tags:
      - Configuration
      summary: Show Nominal Code
      description: 'Show a single nominal code.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: nominal_code
        in: path
        schema:
          type: integer
        required: true
        description: Nominal code ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      code:
                        type: string
                      name:
                        type: string
                      type:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                  status:
                    type: string
                example:
                  data:
                    id: 1
                    code: '4000'
                    name: Sales Revenue
                    type: Revenue
                    created_at: '2024-01-10T09:00:00.000000Z'
                    updated_at: '2024-02-01T11:00:00.000000Z'
                    archived_at: null
                  status: success
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No query results for model [App\Models\NominalCode] 999
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: get-api-nominal-codes-nominal-code
    put:
      tags:
      - Configuration
      summary: Update Nominal Code
      description: 'Update an existing nominal code.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.


        Request body fields (all optional on update):

        - `code` (string) — unique code; must not conflict with other records

        - `name` (string, max:255)

        - `type` — Allowed values: Revenue, Expense, Asset, Liability, Equity, Bank,
        Current, Inventory, Fixed, Directcosts, Currliab, Termliab, Sales


        **Requires permission:** `nominal_codes.update`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                code:
                  type: string
                name:
                  type: string
                type:
                  type: string
              example:
                code: '7001'
                name: Digital Marketing Expense
                type: Expense
      parameters:
      - name: nominal_code
        in: path
        schema:
          type: integer
        required: true
        description: Nominal code ID
        example: '10'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      code:
                        type: string
                      name:
                        type: string
                      type:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                  message:
                    type: string
                  status:
                    type: string
                example:
                  data:
                    id: 10
                    code: '7001'
                    name: Digital Marketing Expense
                    type: Expense
                    created_at: '2024-03-01T10:00:00.000000Z'
                    updated_at: '2024-03-05T14:00:00.000000Z'
                    archived_at: null
                  message: nominal code 7001 was updated successfully
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-session-only: true
      operationId: put-api-nominal-codes-nominal-code
    delete:
      tags:
      - Configuration
      summary: Delete Nominal Code
      description: 'Delete a nominal code. Fails if the code is used in mapping settings
        or linked to sales order lines.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `nominal_codes.delete`'
      parameters:
      - name: nominal_code
        in: path
        schema:
          type: integer
        required: true
        description: Nominal code ID
        example: '10'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  status:
                    type: string
                example:
                  message: nominal code Digital Marketing Expense was deleted successfully
                  status: success
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: array
                    items:
                      type: object
                      properties:
                        code:
                          type: string
                        field:
                          type: string
                        meta:
                          type: object
                          properties:
                            nominal_code_id:
                              type: integer
                  status:
                    type: string
                example:
                  message: Failed to delete nominal code Sales Revenue
                  errors:
                  - code: SalesOrderLineRESOURCE_LINKED
                    field: salesOrderLines
                    meta:
                      nominal_code_id: 1
                  status: error
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-session-only: true
      operationId: delete-api-nominal-codes-nominal-code
  /api/nominal-codes:
    post:
      tags:
      - Configuration
      summary: Create Nominal Code
      description: 'Create a new nominal code.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.


        Request body fields:

        - `code` (required, string) — unique identifier code for the nominal code

        - `name` (required, string, max:255) — display name

        - `type` (required) — account type. Allowed values: Revenue, Expense, Asset,
        Liability, Equity, Bank, Current, Inventory, Fixed, Directcosts, Currliab,
        Termliab, Sales


        **Requires permission:** `nominal_codes.create`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                code:
                  type: string
                name:
                  type: string
                type:
                  type: string
              example:
                code: '7000'
                name: Marketing Expense
                type: Expense
      parameters: []
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      code:
                        type: string
                      name:
                        type: string
                      type:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                  message:
                    type: string
                  status:
                    type: string
                example:
                  data:
                    id: 10
                    code: '7000'
                    name: Marketing Expense
                    type: Expense
                    created_at: '2024-03-01T10:00:00.000000Z'
                    updated_at: '2024-03-01T10:00:00.000000Z'
                    archived_at: null
                  message: nominal code was created successfully
                  status: success
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      code:
                        type: array
                        items:
                          type: string
                      type:
                        type: array
                        items:
                          type: string
                example:
                  message: The given data was invalid.
                  errors:
                    code:
                    - The code has already been taken.
                    type:
                    - The selected type is invalid.
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: post-api-nominal-codes
    delete:
      tags:
      - Configuration
      summary: Bulk Delete Nominal Codes
      description: 'Bulk delete multiple nominal codes by ID.


        :::info[Required scope: `accounting:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Request body:

        - `ids` (required) — array of nominal code IDs to delete


        **Requires permission:** `nominal_codes.delete`'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  status:
                    type: string
                example:
                  message: 2 nominal codes deleted successfully
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: accounting:write
      operationId: delete-api-nominal-codes
  /api/nominal-codes/{nominalCode}/archive:
    put:
      tags:
      - Configuration
      summary: Archive Nominal Code
      description: 'Archive a single nominal code.


        :::info[Required scope: `accounting:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `nominal_codes.archive`'
      requestBody:
        content: {}
      parameters:
      - name: nominalCode
        in: path
        schema:
          type: integer
        required: true
        description: Nominal code ID
        example: '10'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      code:
                        type: string
                      name:
                        type: string
                      type:
                        type: string
                      archived_at:
                        type: string
                  message:
                    type: string
                  status:
                    type: string
                example:
                  data:
                    id: 10
                    code: '7001'
                    name: Digital Marketing Expense
                    type: Expense
                    archived_at: '2024-03-10T11:00:00.000000Z'
                  message: nominal code 7001 was archived successfully
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: accounting:write
      operationId: put-api-nominal-codes-nominalcode-archive
  /api/nominal-codes/{nominalCode}/unarchived:
    put:
      tags:
      - Configuration
      summary: Unarchive Nominal Code
      description: 'Unarchive a single nominal code.


        :::info[Required scope: `accounting:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `nominal_codes.archive`'
      requestBody:
        content: {}
      parameters:
      - name: nominalCode
        in: path
        schema:
          type: integer
        required: true
        description: Nominal code ID
        example: '10'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      code:
                        type: string
                      name:
                        type: string
                      type:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                  message:
                    type: string
                  status:
                    type: string
                example:
                  data:
                    id: 10
                    code: '7001'
                    name: Digital Marketing Expense
                    type: Expense
                    archived_at: null
                  message: nominal code 7001 was unarchived successfully
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: accounting:write
      operationId: put-api-nominal-codes-nominalcode-unarchived
  /api/nominal-codes/archive:
    put:
      tags:
      - Configuration
      summary: Bulk Archive Nominal Codes
      description: 'Bulk archive multiple nominal codes by ID.


        :::info[Required scope: `accounting:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Request body:

        - `ids` (required) — array of nominal code IDs to archive


        **Requires permission:** `nominal_codes.archive`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 8
                - 9
                - 10
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  status:
                    type: string
                example:
                  message: 3 nominal codes archived successfully
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: accounting:write
      operationId: put-api-nominal-codes-archive
  /api/nominal-codes/unarchive:
    put:
      tags:
      - Configuration
      summary: Bulk Unarchive Nominal Codes
      description: 'Bulk unarchive multiple nominal codes by ID.


        :::info[Required scope: `accounting:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Request body:

        - `ids` (required) — array of nominal code IDs to unarchive


        **Requires permission:** `nominal_codes.archive`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 8
                - 9
                - 10
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  status:
                    type: string
                example:
                  message: 3 nominal codes unarchived successfully
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: accounting:write
      operationId: put-api-nominal-codes-unarchive
  /api/nominal-codes/deletable:
    post:
      tags:
      - Configuration
      summary: Check Deletable
      description: 'Check which nominal codes can be deleted. A code cannot be deleted
        if it is linked to sales order lines or used in nominal code mapping settings.


        :::info[Required scope: `accounting:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Request body:

        - `ids` (required, array) — nominal code IDs to check; must exist in nominal_codes
        table


        **Requires permission:** `nominal_codes.delete`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1
                - 2
                - 10
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        code:
                          type: string
                        name:
                          type: string
                        deletable:
                          type: boolean
                        reason:
                          type: object
                          properties:
                            mappingNominalCodes:
                              type: string
                  status:
                    type: string
                example:
                  data:
                  - id: 1
                    code: '4000'
                    name: Sales Revenue
                    deletable: false
                    reason:
                      mappingNominalCodes: Nominal code 'Sales Revenue' is used in
                        accounting mapping settings.
                  - id: 2
                    code: '5000'
                    name: Cost of Goods Sold
                    deletable: false
                    reason:
                      salesOrderLines: 1 sales order line is currently using nominal
                        code(Cost of Goods Sold).
                  - id: 10
                    code: '7001'
                    name: Digital Marketing Expense
                    deletable: true
                    reason: null
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: accounting:write
      operationId: post-api-nominal-codes-deletable
  /api/nominal-codes/archivable:
    post:
      tags:
      - Configuration
      summary: Check Archivable
      description: 'Check which nominal codes can be archived. A code cannot be archived
        if it is currently used in the nominal code mapping settings.


        :::info[Required scope: `accounting:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Request body:

        - `ids` (required, array) — nominal code IDs to check; must exist in nominal_codes
        table


        **Requires permission:** `nominal_codes.archive`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1
                - 10
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        code:
                          type: string
                        name:
                          type: string
                        archivable:
                          type: boolean
                        reason:
                          type: object
                          properties:
                            mappingNominalCodes:
                              type: string
                  status:
                    type: string
                example:
                  data:
                  - id: 1
                    code: '4000'
                    name: Sales Revenue
                    archivable: false
                    reason:
                      mappingNominalCodes: Nominal code 'Sales Revenue' is currently
                        used in a mapping.
                  - id: 10
                    code: '7001'
                    name: Digital Marketing Expense
                    archivable: true
                    reason: null
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: accounting:write
      operationId: post-api-nominal-codes-archivable
  /api/nominal-codes/import/preview:
    post:
      tags:
      - Configuration
      summary: Preview Import
      description: 'Preview a nominal code import file before committing. Returns
        parsed rows and any validation errors.


        :::info[Required scope: `accounting:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Content-Type: multipart/form-data

        - `file` (required) — CSV or Excel file


        **Requires permission:** `nominal_codes.import`'
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                file:
                  type: string
                  description: CSV or Excel file with nominal code data
                  format: binary
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      rows:
                        type: array
                        items:
                          type: object
                          properties:
                            code:
                              type: string
                            name:
                              type: string
                            type:
                              type: string
                            valid:
                              type: boolean
                            errors:
                              type: array
                      total:
                        type: integer
                      valid:
                        type: integer
                      invalid:
                        type: integer
                  status:
                    type: string
                example:
                  data:
                    rows:
                    - code: '8000'
                      name: Other Income
                      type: Revenue
                      valid: true
                      errors: []
                    total: 1
                    valid: 1
                    invalid: 0
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: accounting:write
      operationId: post-api-nominal-codes-import-preview
  /api/nominal-codes/import:
    post:
      tags:
      - Configuration
      summary: Import Nominal Codes
      description: 'Import nominal codes from a CSV or Excel file.


        :::info[Required scope: `accounting:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Content-Type: multipart/form-data

        - `file` (required) — CSV or Excel file


        **Requires permission:** `nominal_codes.import`'
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                file:
                  type: string
                  description: CSV or Excel file with nominal code data
                  format: binary
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      imported:
                        type: integer
                      skipped:
                        type: integer
                      errors:
                        type: array
                  message:
                    type: string
                  status:
                    type: string
                example:
                  data:
                    imported: 3
                    skipped: 0
                    errors: []
                  message: Import completed successfully
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: accounting:write
      operationId: post-api-nominal-codes-import
  /api/cost-categories:
    get:
      tags:
      - Cost Categories
      summary: List Cost Categories
      description: 'List all cost categories, ordered by name.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Each category includes its `default_nominal_code_id` and, when set, an embedded
        `default_nominal_code` object ({id, code, name}). The default nominal code
        is the account a landed-cost bill line assigned to this category posts its
        debit to by default (an explicit nominal code on the line still wins; if the
        category has no default, posting falls back to the nominal code mapping settings).


        Query parameters:

        - `selectable` (boolean) — exclude system categories

        - `is_active` (boolean) — filter by active/archived

        - `with_usage_counts` (boolean) — include usage counts


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 OK
                  value:
                    data:
                    - id: 1
                      name: Accrued Purchases
                      is_system: true
                      is_active: true
                      default_nominal_code_id: null
                      default_nominal_code: null
                      created_at: '2024-01-10T09:00:00.000000Z'
                      updated_at: '2024-01-10T09:00:00.000000Z'
                    - id: 5
                      name: Freight
                      is_system: false
                      is_active: true
                      default_nominal_code_id: 3
                      default_nominal_code:
                        id: 3
                        code: '6000'
                        name: Shipping Expense
                      created_at: '2024-03-01T10:00:00.000000Z'
                      updated_at: '2024-03-05T14:00:00.000000Z'
                    status: success
                example-1:
                  summary: 200 OK (with_usage_counts)
                  value:
                    data:
                    - id: 5
                      name: Freight
                      is_system: false
                      is_active: true
                      default_nominal_code_id: 3
                      default_nominal_code:
                        id: 3
                        code: '6000'
                        name: Shipping Expense
                      usage_counts:
                        bill_lines: 12
                        breakdown_items: 3
                        financial_line_types: 1
                        total: 16
                      created_at: '2024-03-01T10:00:00.000000Z'
                      updated_at: '2024-03-05T14:00:00.000000Z'
                    status: success
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: get-api-cost-categories
    post:
      tags:
      - Cost Categories
      summary: Create Cost Category
      description: 'Create a new cost category.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.


        Request body fields:

        - `name` (required, string, max:255) — unique category name

        - `default_nominal_code_id` (optional, integer, nullable) — the nominal code
        a landed-cost bill line assigned to this category posts its debit to by default.
        Must exist in `nominal_codes`. Leave null to fall back to the nominal code
        mapping settings at posting time.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                default_nominal_code_id:
                  type: integer
              example:
                name: Freight
                default_nominal_code_id: 3
      parameters: []
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      is_system:
                        type: boolean
                      is_active:
                        type: boolean
                      default_nominal_code_id:
                        type: integer
                      default_nominal_code:
                        type: object
                        properties:
                          id:
                            type: integer
                          code:
                            type: string
                          name:
                            type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                  message:
                    type: string
                  status:
                    type: string
                example:
                  data:
                    id: 5
                    name: Freight
                    is_system: false
                    is_active: true
                    default_nominal_code_id: 3
                    default_nominal_code:
                      id: 3
                      code: '6000'
                      name: Shipping Expense
                    created_at: '2024-03-01T10:00:00.000000Z'
                    updated_at: '2024-03-05T14:00:00.000000Z'
                  message: cost category was created successfully
                  status: success
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      name:
                        type: array
                        items:
                          type: string
                      default_nominal_code_id:
                        type: array
                        items:
                          type: string
                example:
                  message: The given data was invalid.
                  errors:
                    name:
                    - A cost category with this name already exists.
                    default_nominal_code_id:
                    - The selected default nominal code id is invalid.
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: post-api-cost-categories
  /api/cost-categories/list:
    get:
      tags:
      - Cost Categories
      summary: List Cost Categories (Paginated)
      description: 'Paginated, server-side-filtered list of cost categories. Supports
        search (name / id / keyword aliases), active/system/selectable filters, and
        sorting, returning a standard paginated envelope. Each item includes usage
        counts and, when set, the embedded default nominal code.


        Use this endpoint when building a browsable, filterable table of cost categories.
        For a full unpaginated list (e.g. to populate a dropdown) use `GET /api/cost-categories`
        instead.


        Query parameters:

        - `filter[search]` — search term (partial match on name; scope with search_columns)

        - `search_columns` — restrict search to: name, id, keyword

        - `filter[is_active]` — 1 active / 0 archived

        - `filter[is_system]` — 1 system / 0 user-defined

        - `filter[selectable]` — 1 to exclude system categories

        - `sort` — id, name, is_system, is_active, created_at, updated_at (prefix
        - for DESC)

        - `page`, `per_page` — pagination (per_page default 10)


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        is_system:
                          type: boolean
                        is_active:
                          type: boolean
                        default_nominal_code_id:
                          type: integer
                        default_nominal_code:
                          type: object
                          properties:
                            id:
                              type: integer
                            code:
                              type: string
                            name:
                              type: string
                        usage_counts:
                          type: object
                          properties:
                            bill_lines:
                              type: integer
                            breakdown_items:
                              type: integer
                            financial_line_types:
                              type: integer
                            total:
                              type: integer
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                  first_page_url:
                    type: string
                  last_page_url:
                    type: string
                  next_page_url:
                    type: string
                    nullable: true
                  prev_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                example:
                  data:
                  - id: 12
                    name: Freight
                    is_system: true
                    is_active: true
                    default_nominal_code_id: 5
                    default_nominal_code:
                      id: 5
                      code: '5000'
                      name: Cost of Goods Sold
                    usage_counts:
                      bill_lines: 8
                      breakdown_items: 2
                      financial_line_types: 1
                      total: 11
                    created_at: '2024-01-10T09:00:00.000000Z'
                    updated_at: '2024-03-02T14:20:00.000000Z'
                  current_page: 1
                  last_page: 1
                  per_page: 10
                  total: 8
                  from: 1
                  to: 8
                  first_page_url: '{{protocol}}{{domain}}/api/cost-categories/list?page=1'
                  last_page_url: '{{protocol}}{{domain}}/api/cost-categories/list?page=1'
                  next_page_url: null
                  prev_page_url: null
                  path: '{{protocol}}{{domain}}/api/cost-categories/list'
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-cost-categories-list
  /api/cost-categories/{cost_category}:
    get:
      tags:
      - Cost Categories
      summary: Get Cost Category
      description: 'Show a single cost category with usage counts and its embedded
        `default_nominal_code` (when set).


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: cost_category
        in: path
        schema:
          type: integer
        required: true
        description: Cost category ID
        example: '5'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      is_system:
                        type: boolean
                      is_active:
                        type: boolean
                      default_nominal_code_id:
                        type: integer
                      default_nominal_code:
                        type: object
                        properties:
                          id:
                            type: integer
                          code:
                            type: string
                          name:
                            type: string
                      usage_counts:
                        type: object
                        properties:
                          bill_lines:
                            type: integer
                          breakdown_items:
                            type: integer
                          financial_line_types:
                            type: integer
                          total:
                            type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                  status:
                    type: string
                example:
                  data:
                    id: 5
                    name: Freight
                    is_system: false
                    is_active: true
                    default_nominal_code_id: 3
                    default_nominal_code:
                      id: 3
                      code: '6000'
                      name: Shipping Expense
                    usage_counts:
                      bill_lines: 12
                      breakdown_items: 3
                      financial_line_types: 1
                      total: 16
                    created_at: '2024-03-01T10:00:00.000000Z'
                    updated_at: '2024-03-05T14:00:00.000000Z'
                  status: success
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No query results for model [App\Models\CostCategory] 999
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: get-api-cost-categories-cost-category
    put:
      tags:
      - Cost Categories
      summary: Update Cost Category
      description: 'Update an existing cost category.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.


        Request body fields:

        - `name` (required, string, max:255) — unique category name (ignores this
        record for the uniqueness check)

        - `default_nominal_code_id` (optional, integer, nullable) — default posting
        nominal code; must exist in `nominal_codes`. Send null to clear it and fall
        back to the nominal code mapping settings.


        Note: the name of a **system** cost category cannot be changed (returns 422).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                default_nominal_code_id:
                  type: integer
              example:
                name: Freight & Handling
                default_nominal_code_id: 3
      parameters:
      - name: cost_category
        in: path
        schema:
          type: integer
        required: true
        description: Cost category ID
        example: '5'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      is_system:
                        type: boolean
                      is_active:
                        type: boolean
                      default_nominal_code_id:
                        type: integer
                      default_nominal_code:
                        type: object
                        properties:
                          id:
                            type: integer
                          code:
                            type: string
                          name:
                            type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                  message:
                    type: string
                  status:
                    type: string
                example:
                  data:
                    id: 5
                    name: Freight
                    is_system: false
                    is_active: true
                    default_nominal_code_id: 3
                    default_nominal_code:
                      id: 3
                      code: '6000'
                      name: Shipping Expense
                    created_at: '2024-03-01T10:00:00.000000Z'
                    updated_at: '2024-03-05T14:00:00.000000Z'
                  message: cost category was updated successfully
                  status: success
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: System cost categories cannot be renamed.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-session-only: true
      operationId: put-api-cost-categories-cost-category
    delete:
      tags:
      - Cost Categories
      summary: Delete Cost Category
      description: 'Delete a cost category. Fails if the category is a system category,
        or if it is in use (bill lines / breakdown items / financial line types) unless
        `?force=true` is passed.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: cost_category
        in: path
        schema:
          type: integer
        required: true
        description: Cost category ID
        example: '5'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  status:
                    type: string
                example:
                  message: Cost category deleted.
                  status: success
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: This cost category is in use and cannot be deleted.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-session-only: true
      operationId: delete-api-cost-categories-cost-category
  /api/cost-categories/{cost_category}/archive:
    post:
      tags:
      - Cost Categories
      summary: Archive Cost Category
      description: 'Archive a cost category (soft-archive via is_active=false). System
        categories cannot be archived (returns 422).


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: cost_category
        in: path
        schema:
          type: integer
        required: true
        description: Cost category ID
        example: '5'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      is_system:
                        type: boolean
                      is_active:
                        type: boolean
                      default_nominal_code_id:
                        type: integer
                      default_nominal_code:
                        type: object
                        properties:
                          id:
                            type: integer
                          code:
                            type: string
                          name:
                            type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                  status:
                    type: string
                example:
                  data:
                    id: 5
                    name: Freight
                    is_system: false
                    is_active: false
                    default_nominal_code_id: 3
                    default_nominal_code:
                      id: 3
                      code: '6000'
                      name: Shipping Expense
                    created_at: '2024-03-01T10:00:00.000000Z'
                    updated_at: '2024-03-05T14:00:00.000000Z'
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-session-only: true
      operationId: post-api-cost-categories-cost-category-archive
  /api/cost-categories/{cost_category}/unarchive:
    post:
      tags:
      - Cost Categories
      summary: Unarchive Cost Category
      description: 'Unarchive a cost category (is_active=true).


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: cost_category
        in: path
        schema:
          type: integer
        required: true
        description: Cost category ID
        example: '5'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      is_system:
                        type: boolean
                      is_active:
                        type: boolean
                      default_nominal_code_id:
                        type: integer
                      default_nominal_code:
                        type: object
                        properties:
                          id:
                            type: integer
                          code:
                            type: string
                          name:
                            type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                  status:
                    type: string
                example:
                  data:
                    id: 5
                    name: Freight
                    is_system: false
                    is_active: true
                    default_nominal_code_id: 3
                    default_nominal_code:
                      id: 3
                      code: '6000'
                      name: Shipping Expense
                    created_at: '2024-03-01T10:00:00.000000Z'
                    updated_at: '2024-03-05T14:00:00.000000Z'
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-session-only: true
      operationId: post-api-cost-categories-cost-category-unarchive
  /api/cost-categories/{cost_category}/merge:
    post:
      tags:
      - Cost Categories
      summary: Merge Cost Category
      description: 'Merge a cost category into a target. Re-points all references
        (bill lines, breakdown items, financial line types) from the source to the
        target, then deletes the source. Returns the target category.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.


        Request body fields:

        - `target_id` (required, integer) — the cost category to merge into; must
        exist and differ from the source.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                target_id:
                  type: integer
              example:
                target_id: 6
      parameters:
      - name: cost_category
        in: path
        schema:
          type: integer
        required: true
        description: Source cost category ID (merged away and deleted)
        example: '5'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      is_system:
                        type: boolean
                      is_active:
                        type: boolean
                      default_nominal_code_id:
                        type: integer
                      default_nominal_code:
                        type: object
                        properties:
                          id:
                            type: integer
                          code:
                            type: string
                          name:
                            type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                  status:
                    type: string
                example:
                  data:
                    id: 5
                    name: Freight
                    is_system: false
                    is_active: true
                    default_nominal_code_id: 3
                    default_nominal_code:
                      id: 3
                      code: '6000'
                      name: Shipping Expense
                    created_at: '2024-03-01T10:00:00.000000Z'
                    updated_at: '2024-03-05T14:00:00.000000Z'
                  status: success
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: A cost category cannot be merged into itself.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-session-only: true
      operationId: post-api-cost-categories-cost-category-merge
  /api/cost-categories/fuzzy-match:
    get:
      tags:
      - Cost Categories
      summary: Fuzzy Match Cost Category
      description: 'Suggest a fuzzy-matched category for the given name — used by
        the create form to warn "Did you mean Freight?" before a near-duplicate is
        created. Returns null in `data` when no close match is found.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: name
        in: query
        schema:
          type: string
        description: Required. The name to fuzzy-match against existing categories.
          Returns the closest match, or null if none is close enough.
        example: Freght
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 OK (match)
                  value:
                    data:
                      id: 5
                      name: Freight
                      is_system: false
                      is_active: true
                      default_nominal_code_id: 3
                      default_nominal_code:
                        id: 3
                        code: '6000'
                        name: Shipping Expense
                      created_at: '2024-03-01T10:00:00.000000Z'
                      updated_at: '2024-03-05T14:00:00.000000Z'
                    status: success
                example-1:
                  summary: 200 OK (no match)
                  value:
                    data: null
                    status: success
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: get-api-cost-categories-fuzzy-match
  /api/payment-types:
    get:
      tags:
      - Configuration
      summary: List Payment Types
      description: 'List all payment types. Returns a flat collection (not paginated).


        :::info[Required scope: `settings:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Query parameters:

        - archived: 0 for active types, 1 for archived types. Default: 0


        Note: The Amazon and Shopify payment types are system-managed and cannot be
        deleted.'
      parameters:
      - name: archived
        in: query
        schema:
          type: integer
        description: 'Filter by archived status: 0 (active) or 1 (archived). Default:
          0'
        example: '0'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        accounting_integration_id:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                        updated_at:
                          type: string
                        archived_at:
                          type: string
                          nullable: true
                example:
                  data:
                  - id: 1
                    name: Credit Card
                    accounting_integration_id: null
                    created_at: '2024-01-01T00:00:00Z'
                    updated_at: '2024-01-01T00:00:00Z'
                    archived_at: null
                  - id: 2
                    name: Amazon
                    accounting_integration_id: null
                    created_at: '2024-01-01T00:00:00Z'
                    updated_at: '2024-01-01T00:00:00Z'
                    archived_at: null
                  - id: 3
                    name: Shopify
                    accounting_integration_id: null
                    created_at: '2024-01-01T00:00:00Z'
                    updated_at: '2024-01-01T00:00:00Z'
                    archived_at: null
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: settings:read
      operationId: get-api-payment-types
    post:
      tags:
      - Configuration
      summary: Create Payment Type
      description: 'Create a new payment type.


        :::info[Required scope: `settings:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Fields:

        - name (required): Unique payment type name, max 255 characters


        **Requires permission:** `payment_types.create`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
              example:
                name: Wire Transfer
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      accounting_integration_id:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                example:
                  message: payment type has been successfully created
                  data:
                    id: 10
                    name: Wire Transfer
                    accounting_integration_id: null
                    created_at: '2024-03-15T14:30:00Z'
                    updated_at: '2024-03-15T14:30:00Z'
                    archived_at: null
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      name:
                        type: array
                        items:
                          type: string
                example:
                  message: The given data was invalid.
                  errors:
                    name:
                    - The name has already been taken.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: settings:write
      operationId: post-api-payment-types
    delete:
      tags:
      - Configuration
      summary: Bulk Delete Payment Types
      description: 'Bulk delete multiple payment types by ID.


        :::info[Required scope: `settings:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `payment_types.delete`'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 2 payment types deleted successfully
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: settings:write
      operationId: delete-api-payment-types
  /api/payment-types/{payment_type}:
    get:
      tags:
      - Configuration
      summary: Get Payment Type
      description: 'Retrieve a single payment type by ID.


        :::info[Required scope: `settings:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: payment_type
        in: path
        schema:
          type: integer
        required: true
        description: Payment type ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      accounting_integration_id:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                example:
                  data:
                    id: 1
                    name: Credit Card
                    accounting_integration_id: null
                    created_at: '2024-01-01T00:00:00Z'
                    updated_at: '2024-01-01T00:00:00Z'
                    archived_at: null
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No query results for model [App\Models\PaymentType] 9999
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: settings:read
      operationId: get-api-payment-types-payment-type
    put:
      tags:
      - Configuration
      summary: Update Payment Type
      description: 'Update an existing payment type.


        :::info[Required scope: `settings:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Fields:

        - name (optional): New payment type name, must be unique, max 255 characters


        **Requires permission:** `payment_types.update`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
              example:
                name: Bank Wire Transfer
      parameters:
      - name: payment_type
        in: path
        schema:
          type: integer
        required: true
        description: Payment type ID
        example: '10'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      accounting_integration_id:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                example:
                  message: payment type Bank Wire Transfer has been successfully updated
                  data:
                    id: 10
                    name: Bank Wire Transfer
                    accounting_integration_id: null
                    created_at: '2024-03-15T14:30:00Z'
                    updated_at: '2024-03-15T15:00:00Z'
                    archived_at: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: settings:write
      operationId: put-api-payment-types-payment-type
    delete:
      tags:
      - Configuration
      summary: Delete Payment Type
      description: 'Delete a payment type. Amazon and Shopify payment types cannot
        be deleted (system-managed).


        :::info[Required scope: `settings:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `payment_types.delete`'
      parameters:
      - name: payment_type
        in: path
        schema:
          type: integer
        required: true
        description: Payment type ID
        example: '10'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: payment type Bank Wire Transfer has been successfully deleted
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: array
                    items:
                      type: object
                      properties:
                        message:
                          type: string
                        code:
                          type: string
                        field:
                          type: string
                example:
                  message: Failed to delete payment type Amazon
                  errors:
                  - message: payment type(Amazon) is not deletable. It is an internal
                      payment type.
                    code: PaymentTypeLinked
                    field: payment_type
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: settings:write
      operationId: delete-api-payment-types-payment-type
  /api/payment-types/deletable:
    post:
      tags:
      - Configuration
      summary: Check Deletable
      description: 'Check which payment types can be deleted. Returns deletability
        status per ID.


        :::info[Required scope: `settings:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Body:

        - ids (required): Array of integer payment type IDs to check


        **Requires permission:** `payment_types.delete`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1
                - 2
                - 10
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        deletable:
                          type: boolean
                        reason:
                          type: string
                          nullable: true
                example:
                  data:
                  - id: 1
                    name: Credit Card
                    deletable: true
                    reason: null
                  - id: 2
                    name: Amazon
                    deletable: false
                    reason: In use by 150 payments
                  - id: 10
                    name: Wire Transfer
                    deletable: true
                    reason: null
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: settings:write
      operationId: post-api-payment-types-deletable
  /api/payment-types/accounting-mapping:
    post:
      tags:
      - Configuration
      summary: Update Accounting Mapping
      description: 'Bulk update accounting integration mappings for payment types.
        Maps each payment type to an external accounting system account.


        :::info[Required scope: `settings:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Body:

        - payment_types (required): Array of payment type mapping objects

        - payment_types[].id (required): Payment type ID

        - payment_types[].accounting_integration_id (required): External accounting
        account ID

        - payment_types[].accounting_integration_type (required): Accounting integration
        type (e.g., QuickBooks)


        **Requires permission:** `payment_types.update`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                payment_types:
                  type: array
                  items:
                    type: object
                    properties:
                      id:
                        type: integer
                      accounting_integration_id:
                        type: string
                      accounting_integration_type:
                        type: string
              example:
                payment_types:
                - id: 1
                  accounting_integration_id: acc_123
                  accounting_integration_type: QuickBooks
                - id: 2
                  accounting_integration_id: acc_456
                  accounting_integration_type: QuickBooks
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                example:
                  success: true
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: settings:write
      operationId: post-api-payment-types-accounting-mapping
  /api/payment-types/{paymentType}/archive:
    put:
      tags:
      - Configuration
      summary: Archive Payment Type
      description: 'Archive a single payment type.


        :::info[Required scope: `settings:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `payment_types.archive`'
      requestBody:
        content: {}
      parameters:
      - name: paymentType
        in: path
        schema:
          type: integer
        required: true
        description: Payment type ID
        example: '10'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      archived_at:
                        type: string
                example:
                  message: payment type Wire Transfer has been archived
                  data:
                    id: 10
                    name: Wire Transfer
                    archived_at: '2024-03-16T10:00:00Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: settings:write
      operationId: put-api-payment-types-paymenttype-archive
  /api/payment-types/{paymentType}/unarchived:
    put:
      tags:
      - Configuration
      summary: Unarchive Payment Type
      description: 'Unarchive a single payment type.


        :::info[Required scope: `settings:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `payment_types.archive`'
      requestBody:
        content: {}
      parameters:
      - name: paymentType
        in: path
        schema:
          type: integer
        required: true
        description: Payment type ID
        example: '10'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                example:
                  message: payment type Wire Transfer has been unarchived
                  data:
                    id: 10
                    name: Wire Transfer
                    archived_at: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: settings:write
      operationId: put-api-payment-types-paymenttype-unarchived
  /api/payment-types/archive:
    put:
      tags:
      - Configuration
      summary: Bulk Archive Payment Types
      description: 'Bulk archive multiple payment types.


        :::info[Required scope: `settings:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `payment_types.archive`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 10
                - 11
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 2 payment types archived successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: settings:write
      operationId: put-api-payment-types-archive
  /api/payment-types/unarchive:
    put:
      tags:
      - Configuration
      summary: Bulk Unarchive Payment Types
      description: 'Bulk unarchive multiple payment types.


        :::info[Required scope: `settings:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `payment_types.archive`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 10
                - 11
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 2 payment types unarchived successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: settings:write
      operationId: put-api-payment-types-unarchive
  /api/payment-terms:
    get:
      tags:
      - Payment Terms
      summary: List Payment Terms
      description: 'Returns a paginated list of payment terms.


        :::info[Required scope: `settings:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Sort fields: id, name, net_days, discount_percentage, discount_days, due_date_type,
        is_default, created_at, updated_at (default: name).


        By default only active (non-archived) terms are returned. Use filter[archived]=all
        or filter[archived]=only to include archived records.'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        description: 'Page number (default: 1)'
        example: '1'
      - name: per_page
        in: query
        schema:
          type: integer
        description: 'Items per page (default: 10)'
        example: '10'
      - name: sort
        in: query
        schema:
          type: string
        description: 'Sort field. Prefix with - for descending. Allowed: id, name,
          net_days, discount_percentage, discount_days, due_date_type, is_default,
          created_at, updated_at'
        example: name
      - name: filter[due_date_type]
        in: query
        schema:
          type: string
        description: 'Exact match. Values: immediate, from_invoice_date, end_of_month,
          end_of_next_month, day_of_month'
        example: from_invoice_date
      - name: filter[is_default]
        in: query
        schema:
          type: boolean
        description: Exact match. Filter by default payment term flag (true/false)
        example: 'false'
      - name: filter[archived]
        in: query
        schema:
          type: string
        description: 'Archive filter. Values: only (archived only), all (include archived),
          omit for active only'
        example: all
      - name: filter[search]
        in: query
        schema:
          type: string
        description: Search across id, name, description fields
        example: net30
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        net_days:
                          type: integer
                        discount_percentage:
                          type: number
                        discount_days:
                          type: integer
                        due_date_type:
                          type: string
                        due_date_type_label:
                          type: string
                        description:
                          type: string
                        is_default:
                          type: boolean
                        is_consignment:
                          type: boolean
                        consignment_settlement_frequency:
                          type: string
                          nullable: true
                        treat_as_purchase:
                          type: boolean
                        has_discount:
                          type: boolean
                        generated_description:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                        archived_at:
                          type: string
                          nullable: true
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 1
                    name: Net 30
                    net_days: 30
                    discount_percentage: 2.0
                    discount_days: 10
                    due_date_type: from_invoice_date
                    due_date_type_label: Days After Invoice Date
                    description: 2% discount if paid within 10 days, net due in 30
                      days
                    is_default: true
                    is_consignment: false
                    consignment_settlement_frequency: null
                    treat_as_purchase: false
                    has_discount: true
                    generated_description: 2/10 Net 30
                    created_at: '2024-01-15T10:00:00.000000Z'
                    updated_at: '2024-01-15T10:00:00.000000Z'
                    archived_at: null
                  - id: 2
                    name: Net 60
                    net_days: 60
                    discount_percentage: 0.0
                    discount_days: null
                    due_date_type: from_invoice_date
                    due_date_type_label: Days After Invoice Date
                    description: null
                    is_default: false
                    is_consignment: false
                    consignment_settlement_frequency: null
                    treat_as_purchase: false
                    has_discount: false
                    generated_description: Net 60
                    created_at: '2024-01-16T09:30:00.000000Z'
                    updated_at: '2024-01-16T09:30:00.000000Z'
                    archived_at: null
                  first_page_url: https://sku2.test/api/payment-terms?page=1
                  from: 1
                  last_page: 1
                  last_page_url: https://sku2.test/api/payment-terms?page=1
                  links: []
                  next_page_url: null
                  path: https://sku2.test/api/payment-terms
                  per_page: 10
                  prev_page_url: null
                  to: 2
                  total: 2
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: settings:read
      operationId: get-api-payment-terms
    post:
      tags:
      - Payment Terms
      summary: Create Payment Term
      description: 'Creates a new payment term.


        :::info[Required scope: `settings:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Fields:

        - name (required, string, max:255, unique)

        - net_days (required, integer, 0-365)

        - discount_percentage (optional, numeric, 0-100)

        - discount_days (optional, integer >= 0; must be less than net_days for types:
        from_invoice_date, end_of_month, day_of_month)

        - due_date_type (required): immediate | from_invoice_date | end_of_month |
        end_of_next_month | day_of_month

        - description (optional, string, max:500)

        - is_default (optional, boolean)


        Vendor Deposit Schedule (optional, array):

        - vendor_deposit_schedule.*.label (optional, string)

        - vendor_deposit_schedule.*.amount_mode (optional): percent | fixed

        - vendor_deposit_schedule.*.percentage (numeric, 0-100)

        - vendor_deposit_schedule.*.fixed_amount (optional, numeric)

        - vendor_deposit_schedule.*.settlement_type (optional): vendor_deposit | final_invoice_balance

        - vendor_deposit_schedule.*.trigger_event (required): one of the supported
        trigger events including logistics_tracking_field

        - vendor_deposit_schedule.*.offset_days (optional, integer, nullable)

        - vendor_deposit_schedule.*.per_shipment (optional, boolean)

        - vendor_deposit_schedule.*.shipment_date_basis (optional): dispatched | planned_etd
        | actual_dispatched | received_at

        - vendor_deposit_schedule.*.is_ownership_transfer (optional, boolean) — only
        one line per schedule may be true

        - vendor_deposit_schedule.*.logistics_tracking_field_id (optional, integer,
        exists:logistics_tracking_fields,id) — REQUIRED when trigger_event is logistics_tracking_field


        **Requires permission:** `payment_terms.create`


        Consignment fields: set is_consignment to true to mark the term as consignment
        (supplier-owned stock billed as it sells). consignment_settlement_frequency
        controls how often consigned sales are settled (on_demand, weekly, biweekly,
        monthly, quarterly). treat_as_purchase overrides consignment so goods received
        on this term are capitalized as owned inventory immediately at receipt (substance-over-form).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                net_days:
                  type: integer
                discount_percentage:
                  type: number
                discount_days:
                  type: integer
                due_date_type:
                  type: string
                description:
                  type: string
                is_default:
                  type: boolean
                is_consignment:
                  type: boolean
                consignment_settlement_frequency:
                  type: string
                  nullable: true
                treat_as_purchase:
                  type: boolean
              example:
                name: Net 45
                net_days: 45
                discount_percentage: 1.5
                discount_days: 10
                due_date_type: from_invoice_date
                description: 1.5% discount if paid within 10 days, net due in 45 days
                is_default: false
                is_consignment: false
                consignment_settlement_frequency: null
                treat_as_purchase: false
      parameters: []
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      net_days:
                        type: integer
                      discount_percentage:
                        type: number
                      discount_days:
                        type: integer
                      due_date_type:
                        type: string
                      due_date_type_label:
                        type: string
                      description:
                        type: string
                      is_default:
                        type: boolean
                      is_consignment:
                        type: boolean
                      consignment_settlement_frequency:
                        type: string
                        nullable: true
                      treat_as_purchase:
                        type: boolean
                      has_discount:
                        type: boolean
                      generated_description:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                  message:
                    type: string
                example:
                  data:
                    id: 3
                    name: Net 45
                    net_days: 45
                    discount_percentage: 1.5
                    discount_days: 10
                    due_date_type: from_invoice_date
                    due_date_type_label: Days After Invoice Date
                    description: 1.5% discount if paid within 10 days, net due in
                      45 days
                    is_default: false
                    is_consignment: false
                    consignment_settlement_frequency: null
                    treat_as_purchase: false
                    has_discount: true
                    generated_description: 1.5/10 Net 45
                    created_at: '2024-03-01T12:00:00.000000Z'
                    updated_at: '2024-03-01T12:00:00.000000Z'
                    archived_at: null
                  message: payment term created successfully
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      name:
                        type: array
                        items:
                          type: string
                      net_days:
                        type: array
                        items:
                          type: string
                      due_date_type:
                        type: array
                        items:
                          type: string
                example:
                  message: The given data was invalid.
                  errors:
                    name:
                    - The name has already been taken.
                    net_days:
                    - The net days field is required.
                    due_date_type:
                    - The selected due date type is invalid.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: settings:write
      operationId: post-api-payment-terms
    delete:
      tags:
      - Payment Terms
      summary: Bulk Delete Payment Terms
      description: 'Bulk deletes multiple payment terms by IDs.


        :::info[Required scope: `settings:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `payment_terms.delete`'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 2 payment terms deleted successfully
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: settings:write
      operationId: delete-api-payment-terms
  /api/payment-terms/{id}:
    get:
      tags:
      - Payment Terms
      summary: Get Payment Term
      description: 'Returns a single payment term by ID. Includes due_date_type_options
        in the response for form use.


        :::info[Required scope: `settings:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      net_days:
                        type: integer
                      discount_percentage:
                        type: number
                      discount_days:
                        type: integer
                      due_date_type:
                        type: string
                      due_date_type_label:
                        type: string
                      description:
                        type: string
                      is_default:
                        type: boolean
                      is_consignment:
                        type: boolean
                      consignment_settlement_frequency:
                        type: string
                        nullable: true
                      treat_as_purchase:
                        type: boolean
                      has_discount:
                        type: boolean
                      generated_description:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                      due_date_type_options:
                        type: array
                        items:
                          type: object
                          properties:
                            value:
                              type: string
                            label:
                              type: string
                            description:
                              type: string
                            netDaysLabel:
                              type: string
                            usesNetDays:
                              type: boolean
                example:
                  data:
                    id: 1
                    name: Net 30
                    net_days: 30
                    discount_percentage: 2.0
                    discount_days: 10
                    due_date_type: from_invoice_date
                    due_date_type_label: Days After Invoice Date
                    description: 2% discount if paid within 10 days, net due in 30
                      days
                    is_default: true
                    is_consignment: false
                    consignment_settlement_frequency: null
                    treat_as_purchase: false
                    has_discount: true
                    generated_description: 2/10 Net 30
                    created_at: '2024-01-15T10:00:00.000000Z'
                    updated_at: '2024-01-15T10:00:00.000000Z'
                    archived_at: null
                    due_date_type_options:
                    - value: immediate
                      label: Due Immediately
                      description: Payment is due immediately upon receipt of invoice.
                      netDaysLabel: Net Days (not used)
                      usesNetDays: false
                    - value: from_invoice_date
                      label: Days After Invoice Date
                      description: Due date = Invoice Date + Net Days.
                      netDaysLabel: Net Days
                      usesNetDays: true
                    - value: end_of_month
                      label: End of Invoice Month + Days
                      description: Due date = End of invoice month + Net Days.
                      netDaysLabel: Additional Days After Month End
                      usesNetDays: true
                    - value: end_of_next_month
                      label: End of Next Month
                      description: Due at the end of the month following the invoice
                        date.
                      netDaysLabel: Net Days (not used)
                      usesNetDays: false
                    - value: day_of_month
                      label: Specific Day of Month
                      description: Due on a specific day of the next month.
                      netDaysLabel: Day of Month (1-31)
                      usesNetDays: true
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No query results for model [App\Models\PaymentTerm] 999
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: settings:read
      operationId: get-api-payment-terms-id
    put:
      tags:
      - Payment Terms
      summary: Update Payment Term
      description: 'Updates an existing payment term by ID.


        :::info[Required scope: `settings:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        All fields same as Create, including the optional vendor_deposit_schedule
        array (with per-line logistics_tracking_field_id required when trigger_event
        is logistics_tracking_field). Name uniqueness ignores the current record.


        Consignment fields: set is_consignment to true to mark the term as consignment
        (supplier-owned stock billed as it sells). consignment_settlement_frequency
        controls how often consigned sales are settled (on_demand, weekly, biweekly,
        monthly, quarterly). treat_as_purchase overrides consignment so goods received
        on this term are capitalized as owned inventory immediately at receipt (substance-over-form).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                net_days:
                  type: integer
                discount_percentage:
                  type: integer
                discount_days:
                  type: integer
                due_date_type:
                  type: string
                description:
                  type: string
                is_default:
                  type: boolean
                is_consignment:
                  type: boolean
                consignment_settlement_frequency:
                  type: string
                  nullable: true
                treat_as_purchase:
                  type: boolean
              example:
                name: Net 45 Updated
                net_days: 45
                discount_percentage: 2
                discount_days: 15
                due_date_type: from_invoice_date
                description: Updated payment terms
                is_default: false
                is_consignment: false
                consignment_settlement_frequency: null
                treat_as_purchase: false
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      net_days:
                        type: integer
                      discount_percentage:
                        type: number
                      discount_days:
                        type: integer
                      due_date_type:
                        type: string
                      due_date_type_label:
                        type: string
                      description:
                        type: string
                      is_default:
                        type: boolean
                      is_consignment:
                        type: boolean
                      consignment_settlement_frequency:
                        type: string
                        nullable: true
                      treat_as_purchase:
                        type: boolean
                      has_discount:
                        type: boolean
                      generated_description:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                  message:
                    type: string
                example:
                  data:
                    id: 3
                    name: Net 45 Updated
                    net_days: 45
                    discount_percentage: 2.0
                    discount_days: 15
                    due_date_type: from_invoice_date
                    due_date_type_label: Days After Invoice Date
                    description: Updated payment terms
                    is_default: false
                    is_consignment: false
                    consignment_settlement_frequency: null
                    treat_as_purchase: false
                    has_discount: true
                    generated_description: 2/15 Net 45
                    created_at: '2024-03-01T12:00:00.000000Z'
                    updated_at: '2024-03-01T14:00:00.000000Z'
                    archived_at: null
                  message: payment term Net 45 Updated updated successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: settings:write
      operationId: put-api-payment-terms-id
    delete:
      tags:
      - Payment Terms
      summary: Delete Payment Term
      description: 'Deletes a payment term by ID. Returns an error if the term is
        linked to purchase orders or suppliers.


        :::info[Required scope: `settings:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Net 45 Updated deleted successfully
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: array
                    items:
                      type: object
                      properties:
                        message:
                          type: string
                        code:
                          type: string
                        field:
                          type: string
                  message:
                    type: string
                example:
                  errors:
                  - message: This payment term is currently used by 3 purchase orders.
                    code: PurchaseOrderRESOURCE_LINKED
                    field: purchase_orders
                  message: Net 30 could not be deleted
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: settings:write
      operationId: delete-api-payment-terms-id
  /api/payment-terms/{id}/archive:
    put:
      tags:
      - Payment Terms
      summary: Archive Payment Term
      description: 'Archives a payment term. Returns a warning if already archived.


        :::info[Required scope: `settings:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      archived_at:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 1
                    name: Net 30
                    archived_at: '2024-03-01T15:00:00.000000Z'
                  message: payment term Net 30 archived successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: settings:write
      operationId: put-api-payment-terms-id-archive
  /api/payment-terms/{id}/unarchived:
    put:
      tags:
      - Payment Terms
      summary: Unarchive Payment Term
      description: 'Unarchives a payment term. Returns a warning if not currently
        archived.


        :::info[Required scope: `settings:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                  message:
                    type: string
                example:
                  data:
                    id: 1
                    name: Net 30
                    archived_at: null
                  message: payment term Net 30 unarchived successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: settings:write
      operationId: put-api-payment-terms-id-unarchived
  /api/payment-terms/archive:
    put:
      tags:
      - Payment Terms
      summary: Bulk Archive Payment Terms
      description: 'Bulk archives multiple payment terms by IDs.


        :::info[Required scope: `settings:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `payment_terms.archive`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1
                - 2
                - 3
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 3 payment terms archived successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: settings:write
      operationId: put-api-payment-terms-archive
  /api/payment-terms/unarchive:
    put:
      tags:
      - Payment Terms
      summary: Bulk Unarchive Payment Terms
      description: 'Bulk unarchives multiple payment terms by IDs.


        :::info[Required scope: `settings:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `payment_terms.archive`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1
                - 2
                - 3
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 3 payment terms unarchived successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: settings:write
      operationId: put-api-payment-terms-unarchive
  /api/payment-terms/deletable:
    post:
      tags:
      - Payment Terms
      summary: Check Payment Terms Deletable
      description: 'Checks which payment terms can be deleted (not linked to any purchase
        orders or suppliers).


        :::info[Required scope: `settings:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `payment_terms.delete`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1
                - 2
                - 3
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        deletable:
                          type: boolean
                        reason:
                          type: object
                          properties:
                            purchase_orders:
                              type: string
                example:
                  data:
                  - id: 1
                    name: Net 30
                    deletable: false
                    reason:
                      purchase_orders: This payment term is currently used by 5 purchase
                        orders.
                  - id: 2
                    name: Net 60
                    deletable: true
                    reason: null
                  - id: 3
                    name: Net 45
                    deletable: true
                    reason: null
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: settings:write
      operationId: post-api-payment-terms-deletable
  /api/incoterms:
    post:
      tags:
      - Configuration
      summary: Create Incoterm
      description: 'Manage the Incoterms 2020 reference table. Standard ICC rows carry
        structured trade-term metadata used to drive buyer/seller responsibility panels
        on purchase and sales orders.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Fields:

        - `code` (required, string, max 10, unique) — e.g. `DAP`, `FOB`. Locked for
        standard ICC rows.

        - `name` (string) — human label, e.g. `Delivered at Place`.

        - `description` (string)

        - `transport_mode` (enum) — `any` | `sea_inland`.

        - `family` (enum) — `E` | `F` | `C` | `D` (ICC term family).

        - `seller_pays_main_carriage` (boolean)

        - `export_cleared_by` (enum) — `seller` | `buyer`.

        - `import_cleared_by` (enum) — `seller` | `buyer`.

        - `seller_insurance` (enum) — `none` | `clause_a` | `clause_c`.

        - `risk_transfer_point` (string) — plain-English point where risk passes.

        - `sort_order` (integer)

        - `is_deprecated` (boolean) — flags retired rules (e.g. DAT).


        `is_standard` is server-maintained and NOT accepted in the request body.


        Authentication: Requires Bearer token. Permission: `incoterms.create` / `incoterms.update`.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                code:
                  type: string
                name:
                  type: string
                description:
                  type: string
                transport_mode:
                  type: string
                family:
                  type: string
                seller_pays_main_carriage:
                  type: boolean
                export_cleared_by:
                  type: string
                import_cleared_by:
                  type: string
                seller_insurance:
                  type: string
                risk_transfer_point:
                  type: string
                sort_order:
                  type: integer
                is_deprecated:
                  type: boolean
              example:
                code: DAP
                name: Delivered at Place
                description: Seller delivers goods to the named destination. Buyer
                  handles import customs clearance and duties.
                transport_mode: any
                family: D
                seller_pays_main_carriage: true
                export_cleared_by: seller
                import_cleared_by: buyer
                seller_insurance: none
                risk_transfer_point: At the named place of destination, when goods
                  are ready for unloading.
                sort_order: 12
                is_deprecated: false
      parameters: []
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      code:
                        type: string
                      id:
                        type: integer
                      name:
                        type: string
                      description:
                        type: string
                      transport_mode:
                        type: string
                      family:
                        type: string
                      seller_pays_main_carriage:
                        type: boolean
                      export_cleared_by:
                        type: string
                      import_cleared_by:
                        type: string
                      seller_insurance:
                        type: string
                      risk_transfer_point:
                        type: string
                      is_standard:
                        type: boolean
                      is_deprecated:
                        type: boolean
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                      sort_order:
                        type: integer
                example:
                  message: incoterm created successfully.
                  data:
                    code: DAP
                    id: 12
                    name: Delivered at Place
                    description: Seller delivers goods to the named destination. Buyer
                      handles import customs clearance and duties.
                    transport_mode: any
                    family: D
                    seller_pays_main_carriage: true
                    export_cleared_by: seller
                    import_cleared_by: buyer
                    seller_insurance: none
                    risk_transfer_point: At the named place of destination, when goods
                      are ready for unloading.
                    is_standard: true
                    is_deprecated: false
                    created_at: '2026-07-13T10:30:00.000000Z'
                    updated_at: '2026-07-13T10:30:00.000000Z'
                    archived_at: null
                    sort_order: 4
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      code:
                        type: array
                        items:
                          type: string
                example:
                  message: The code has already been taken.
                  errors:
                    code:
                    - The code has already been taken.
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: post-api-incoterms
    delete:
      tags:
      - Configuration
      summary: Bulk Delete Incoterms
      description: 'Deletes multiple incoterms in a single request.


        :::info[Required scope: `settings:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token


        Request body:

        - ids (array, required): Array of incoterm IDs to delete


        **Requires permission:** `incoterms.delete`'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 2 incoterms deleted successfully.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: settings:write
      operationId: delete-api-incoterms
  /api/incoterms/{incoterm}:
    get:
      tags:
      - Configuration
      summary: Get Incoterm
      description: 'Returns the details of a single incoterm.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token'
      parameters:
      - name: incoterm
        in: path
        schema:
          type: integer
        required: true
        description: Incoterm ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      code:
                        type: string
                      id:
                        type: integer
                      name:
                        type: string
                      description:
                        type: string
                      transport_mode:
                        type: string
                      family:
                        type: string
                      seller_pays_main_carriage:
                        type: boolean
                      export_cleared_by:
                        type: string
                      import_cleared_by:
                        type: string
                      seller_insurance:
                        type: string
                      risk_transfer_point:
                        type: string
                      is_standard:
                        type: boolean
                      is_deprecated:
                        type: boolean
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                      sort_order:
                        type: integer
                example:
                  data:
                    code: EXW
                    id: 1
                    name: Ex Works
                    description: Ex Works — seller makes goods available at their
                      premises.
                    transport_mode: any
                    family: E
                    seller_pays_main_carriage: true
                    export_cleared_by: seller
                    import_cleared_by: buyer
                    seller_insurance: none
                    risk_transfer_point: At the named place of destination, when goods
                      are ready for unloading.
                    is_standard: true
                    is_deprecated: false
                    created_at: '2026-07-13T10:30:00.000000Z'
                    updated_at: '2026-07-13T10:30:00.000000Z'
                    archived_at: null
                    sort_order: 4
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No query results for model [App\Models\Incoterm] 99
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: get-api-incoterms-incoterm
    put:
      tags:
      - Configuration
      summary: Update Incoterm
      description: 'Manage the Incoterms 2020 reference table. Standard ICC rows carry
        structured trade-term metadata used to drive buyer/seller responsibility panels
        on purchase and sales orders.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Fields:

        - `code` (required, string, max 10, unique) — e.g. `DAP`, `FOB`. Locked for
        standard ICC rows.

        - `name` (string) — human label, e.g. `Delivered at Place`.

        - `description` (string)

        - `transport_mode` (enum) — `any` | `sea_inland`.

        - `family` (enum) — `E` | `F` | `C` | `D` (ICC term family).

        - `seller_pays_main_carriage` (boolean)

        - `export_cleared_by` (enum) — `seller` | `buyer`.

        - `import_cleared_by` (enum) — `seller` | `buyer`.

        - `seller_insurance` (enum) — `none` | `clause_a` | `clause_c`.

        - `risk_transfer_point` (string) — plain-English point where risk passes.

        - `sort_order` (integer)

        - `is_deprecated` (boolean) — flags retired rules (e.g. DAT).


        `is_standard` is server-maintained and NOT accepted in the request body.


        Authentication: Requires Bearer token. Permission: `incoterms.create` / `incoterms.update`.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                code:
                  type: string
                name:
                  type: string
                description:
                  type: string
                transport_mode:
                  type: string
                family:
                  type: string
                seller_pays_main_carriage:
                  type: boolean
                export_cleared_by:
                  type: string
                import_cleared_by:
                  type: string
                seller_insurance:
                  type: string
                risk_transfer_point:
                  type: string
                sort_order:
                  type: integer
                is_deprecated:
                  type: boolean
              example:
                code: EXW
                name: Ex Works
                description: Ex Works — seller makes goods available at their premises.
                transport_mode: any
                family: E
                seller_pays_main_carriage: false
                export_cleared_by: buyer
                import_cleared_by: buyer
                seller_insurance: none
                risk_transfer_point: At the seller's premises, once goods are placed
                  at the buyer's disposal.
                sort_order: 1
                is_deprecated: false
      parameters:
      - name: incoterm
        in: path
        schema:
          type: integer
        required: true
        description: Incoterm ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      code:
                        type: string
                      id:
                        type: integer
                      name:
                        type: string
                      description:
                        type: string
                      transport_mode:
                        type: string
                      family:
                        type: string
                      seller_pays_main_carriage:
                        type: boolean
                      export_cleared_by:
                        type: string
                      import_cleared_by:
                        type: string
                      seller_insurance:
                        type: string
                      risk_transfer_point:
                        type: string
                      is_standard:
                        type: boolean
                      is_deprecated:
                        type: boolean
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                      sort_order:
                        type: integer
                example:
                  message: incoterm EXW updated successfully.
                  data:
                    code: EXW
                    id: 1
                    name: Ex Works
                    description: Ex Works — seller makes goods available at their
                      premises.
                    transport_mode: any
                    family: E
                    seller_pays_main_carriage: true
                    export_cleared_by: seller
                    import_cleared_by: buyer
                    seller_insurance: none
                    risk_transfer_point: At the named place of destination, when goods
                      are ready for unloading.
                    is_standard: true
                    is_deprecated: false
                    created_at: '2026-07-13T10:30:00.000000Z'
                    updated_at: '2026-07-13T10:30:00.000000Z'
                    archived_at: null
                    sort_order: 4
        '422':
          description: Unprocessable Entity
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      code:
                        type: array
                        items:
                          type: string
                example:
                  message: Incoterm 'FOB' is a standard term and its code cannot be
                    changed.
                  errors:
                    code:
                    - Incoterm 'FOB' is a standard term and its code cannot be changed.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-session-only: true
      operationId: put-api-incoterms-incoterm
    delete:
      tags:
      - Configuration
      summary: Delete Incoterm
      description: 'Deletes the specified incoterm. Will fail if the incoterm is linked
        to existing purchase orders or other records.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token


        **Requires permission:** `incoterms.delete`'
      parameters:
      - name: incoterm
        in: path
        schema:
          type: integer
        required: true
        description: Incoterm ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: incoterm EXW deleted successfully.
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      purchase_orders:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            incoterm_id:
                              type: integer
                example:
                  message: incoterm EXW could not be deleted.
                  errors:
                    purchase_orders:
                    - message: Incoterm is linked to existing purchase orders
                      code: PurchaseOrderResourceLinked
                      incoterm_id: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-session-only: true
      operationId: delete-api-incoterms-incoterm
  /api/incoterms/{incoterm}/archive:
    put:
      tags:
      - Configuration
      summary: Archive Incoterm
      description: 'Archives the specified incoterm by setting its archived_at timestamp.


        :::info[Required scope: `settings:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token


        **Requires permission:** `incoterms.archive`'
      requestBody:
        content: {}
      parameters:
      - name: incoterm
        in: path
        schema:
          type: integer
        required: true
        description: Incoterm ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      code:
                        type: string
                      archived_at:
                        type: string
                example:
                  message: incoterm EXW archived successfully.
                  data:
                    id: 1
                    code: EXW
                    archived_at: '2024-01-15T10:30:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: settings:write
      operationId: put-api-incoterms-incoterm-archive
  /api/incoterms/{incoterm}/unarchived:
    put:
      tags:
      - Configuration
      summary: Unarchive Incoterm
      description: 'Restores (unarchives) the specified incoterm by clearing its archived_at
        timestamp.


        :::info[Required scope: `settings:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token


        **Requires permission:** `incoterms.archive`'
      requestBody:
        content: {}
      parameters:
      - name: incoterm
        in: path
        schema:
          type: integer
        required: true
        description: Incoterm ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      code:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                example:
                  message: incoterm EXW unarchived successfully.
                  data:
                    id: 1
                    code: EXW
                    archived_at: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: settings:write
      operationId: put-api-incoterms-incoterm-unarchived
  /api/incoterms/deletable:
    post:
      tags:
      - Configuration
      summary: Check Deletable
      description: 'Checks whether the specified incoterms can be deleted. Returns
        deletability status and reason if an incoterm is in use.


        :::info[Required scope: `settings:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token


        Request body:

        - ids (array, required, min:1): Array of incoterm IDs to check


        **Requires permission:** `incoterms.delete`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1
                - 2
                - 3
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        code:
                          type: string
                        deletable:
                          type: boolean
                        reason:
                          type: string
                example:
                  data:
                  - id: 1
                    code: EXW
                    deletable: false
                    reason: Linked to existing purchase orders
                  - id: 2
                    code: FOB
                    deletable: true
                    reason: null
                  - id: 3
                    code: CIF
                    deletable: true
                    reason: null
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: settings:write
      operationId: post-api-incoterms-deletable
  /api/incoterms/archive:
    put:
      tags:
      - Configuration
      summary: Bulk Archive Incoterms
      description: 'Archives multiple incoterms.


        :::info[Required scope: `settings:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token


        Request body:

        - ids (array, required): Array of incoterm IDs to archive


        **Requires permission:** `incoterms.archive`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 2
                - 3
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 2 incoterms archived successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: settings:write
      operationId: put-api-incoterms-archive
  /api/incoterms/unarchive:
    put:
      tags:
      - Configuration
      summary: Bulk Unarchive Incoterms
      description: 'Restores (unarchives) multiple incoterms.


        :::info[Required scope: `settings:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token


        Request body:

        - ids (array, required): Array of incoterm IDs to unarchive


        **Requires permission:** `incoterms.archive`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 2
                - 3
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 2 incoterms unarchived successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: settings:write
      operationId: put-api-incoterms-unarchive
  /api/ledger/dashboard:
    get:
      tags:
      - Ledger (Accounting v2)
      summary: Get Dashboard Summary
      description: 'The Accounting v2 section landing summary — the whole dashboard
        in one call. Composed from the existing managers/repositories so it never
        diverges from the tab it summarizes.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Authentication:** Requires Bearer token.


        **Sections:**

        - `generation_health` — the derived backlog signal (`state`: healthy | behind
        | failing | paused) with its label + Vuetify color, plus the raw inputs: kill-switch
        `enabled`, `environment_override`, outbox `pending`/`failed`, the drain `last_processed_at`
        heartbeat, `stale_after_minutes` (5), and the next scheduled runs. `behind`
        requires BOTH queued work AND a stale heartbeat — a large-but-draining queue
        stays healthy.

        - `kpis` — four headline counts: `pending_sync` (pending_sync + update_pending
        + syncing + retrying), `needs_attention` (needs_attention + failed + conflict
        + removed_in_provider), `synced`, and `outbox_backlog` (outbox pending + failed
        source documents not yet turned into entries).

        - `status_breakdown` — per-display-status counts in enum order, each with
        label + color (click a segment to open the All tab filtered on that `display_status`).
        Statuses with no entries are included with count 0.

        - `needs_attention` — the parked `total`, the `group_count`, and the top 5
        error-cause `groups`.

        - `connections` — the accounting connections view-model (provider, health,
        lock date, rate budget, last inbound, open ops).

        - `reconciliation` — `balance_mismatches`: current entries whose line sums
        disagree with their header totals.

        - `recent_entries` — the 5 most recent entries (same shape as the entries
        table).'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      dashboard:
                        type: object
                        properties:
                          generation_health:
                            type: object
                            properties:
                              state:
                                type: string
                              label:
                                type: string
                              color:
                                type: string
                              enabled:
                                type: boolean
                              environment_override:
                                type: boolean
                              pending:
                                type: integer
                              failed:
                                type: integer
                              last_processed_at:
                                type: string
                              stale_after_minutes:
                                type: integer
                              schedule:
                                type: object
                                properties:
                                  next_generation_run_at:
                                    type: string
                                  next_reconcile_run_at:
                                    type: string
                          kpis:
                            type: object
                            properties:
                              pending_sync:
                                type: integer
                              needs_attention:
                                type: integer
                              synced:
                                type: integer
                              outbox_backlog:
                                type: integer
                          status_breakdown:
                            type: array
                            items:
                              type: object
                              properties:
                                key:
                                  type: string
                                label:
                                  type: string
                                color:
                                  type: string
                                count:
                                  type: integer
                          needs_attention:
                            type: object
                            properties:
                              total:
                                type: integer
                              group_count:
                                type: integer
                              groups:
                                type: array
                                items:
                                  type: object
                                  properties:
                                    cause_key:
                                      type: string
                                    label:
                                      type: string
                                    error_class:
                                      type: string
                                    count:
                                      type: integer
                          connections:
                            type: array
                            items:
                              type: object
                              properties:
                                id:
                                  type: integer
                                provider:
                                  type: string
                                name:
                                  type: string
                                health:
                                  type: object
                                  properties:
                                    sync_status:
                                      type: string
                                    paused:
                                      type: boolean
                                lock_date:
                                  type: string
                                rate_budget_remaining:
                                  type: string
                                  nullable: true
                                last_inbound_event_at:
                                  type: string
                                open_operations:
                                  type: object
                                  properties:
                                    pending:
                                      type: integer
                                    queued:
                                      type: integer
                                    in_flight:
                                      type: integer
                          reconciliation:
                            type: object
                            properties:
                              balance_mismatches:
                                type: integer
                          recent_entries:
                            type: array
                            items:
                              type: object
                              properties:
                                id:
                                  type: integer
                                uuid:
                                  type: string
                                type:
                                  type: object
                                  properties:
                                    value:
                                      type: string
                                    label:
                                      type: string
                                status:
                                  type: string
                                display_status:
                                  type: object
                                  properties:
                                    key:
                                      type: string
                                    label:
                                      type: string
                                    color:
                                      type: string
                                    reason:
                                      type: string
                                      nullable: true
                                effective_at:
                                  type: string
                                posted_at:
                                  type: string
                                currency_code:
                                  type: string
                                total_debit:
                                  type: string
                                total_credit:
                                  type: string
                                reference:
                                  type: string
                                reference_suffix:
                                  type: string
                                  nullable: true
                                description:
                                  type: string
                                source:
                                  type: object
                                  properties:
                                    type:
                                      type: string
                                    id:
                                      type: integer
                                    label:
                                      type: string
                                    link_type_label:
                                      type: string
                                    link_route:
                                      type: string
                                    link_legacy_url:
                                      type: string
                                      nullable: true
                                    url:
                                      type: string
                                batch_id:
                                  type: string
                                  nullable: true
                                sync_override:
                                  type: string
                                  nullable: true
                                integrity_flag:
                                  type: string
                                  nullable: true
                                reversal_of_id:
                                  type: string
                                  nullable: true
                                replaced_by_id:
                                  type: string
                                  nullable: true
                                created_at:
                                  type: string
                                provider_link:
                                  type: string
                                  nullable: true
                  status:
                    type: string
                example:
                  data:
                    dashboard:
                      generation_health:
                        state: behind
                        label: Behind
                        color: warning
                        enabled: true
                        environment_override: false
                        pending: 42
                        failed: 0
                        last_processed_at: '2026-06-12T02:21:00+00:00'
                        stale_after_minutes: 5
                        schedule:
                          next_generation_run_at: '2026-06-12T20:21:00+00:00'
                          next_reconcile_run_at: '2026-06-13T00:00:00+00:00'
                      kpis:
                        pending_sync: 38
                        needs_attention: 14
                        synced: 1240
                        outbox_backlog: 42
                      status_breakdown:
                      - key: excluded
                        label: Excluded
                        color: grey
                        count: 12
                      - key: pending_sync
                        label: Pending sync
                        color: info
                        count: 28
                      - key: syncing
                        label: Syncing
                        color: info
                        count: 4
                      - key: synced
                        label: Synced
                        color: success
                        count: 1240
                      - key: update_pending
                        label: Update pending
                        color: warning
                        count: 5
                      - key: retrying
                        label: Retrying
                        color: warning
                        count: 1
                      - key: needs_attention
                        label: Needs attention
                        color: error
                        count: 9
                      - key: failed
                        label: Failed
                        color: error
                        count: 3
                      - key: removed_in_provider
                        label: Removed in provider
                        color: error
                        count: 1
                      - key: conflict
                        label: Conflict
                        color: error
                        count: 1
                      - key: voided
                        label: Synced, Voided
                        color: warning
                        count: 2
                      needs_attention:
                        total: 14
                        group_count: 2
                        groups:
                        - cause_key: user_action_required:d2b5c3a1e4f6a7b8c9d0e1f2a3b4c5d6
                          label: 'Account # Sales Revenue is inactive in QuickBooks
                            Online.'
                          error_class: user_action_required
                          count: 11
                        - cause_key: auth_connection:9f1c0b2a3d4e5f60718293a4b5c6d7e8
                          label: The Xero connection needs to be re-authorized.
                          error_class: auth_connection
                          count: 3
                      connections:
                      - id: 3
                        provider: qbo
                        name: QuickBooks Online
                        health:
                          sync_status: active
                          paused: false
                        lock_date: '2026-04-30'
                        rate_budget_remaining: null
                        last_inbound_event_at: '2026-06-10T18:42:11+00:00'
                        open_operations:
                          pending: 4
                          queued: 2
                          in_flight: 1
                      reconciliation:
                        balance_mismatches: 0
                      recent_entries:
                      - id: 1842
                        uuid: 9c2f1b7e-4a6d-4f0e-9b1a-2d8c5e7f3a10
                        type:
                          value: sales_order_invoice
                          label: Sales Order Invoice
                        status: posted
                        display_status:
                          key: synced
                          label: Synced
                          color: success
                          reason: null
                        effective_at: '2026-06-05T14:30:00+00:00'
                        posted_at: '2026-06-05T14:35:12+00:00'
                        currency_code: USD
                        total_debit: '249.9900'
                        total_credit: '249.9900'
                        reference: SO-10293
                        reference_suffix: null
                        description: Sales order invoice for SO-10293
                        source:
                          type: App\Models\SalesOrder
                          id: 10293
                          label: SO-10293
                          link_type_label: Sales Order
                          link_route: /orders/sales-orders/10293
                          link_legacy_url: null
                          url: /orders/sales-orders/10293
                        batch_id: null
                        sync_override: null
                        integrity_flag: null
                        reversal_of_id: null
                        replaced_by_id: null
                        created_at: '2026-06-05T14:30:02+00:00'
                        provider_link: null
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-ledger-dashboard
  /api/ledger/outbox/failures:
    get:
      tags:
      - Ledger (Accounting v2)
      summary: List Outbox Failures
      description: 'Paginated terminally-failed `ledger_outbox` rows for the dashboard
        failures drill-down, newest failure first (`processed_at` carries the failure
        timestamp for failed rows).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Authentication:** Requires Bearer token.


        **Pagination:** `per_page` (default 10, clamped to 100), `page`. Standard
        Laravel pagination envelope.


        **Each row:**

        - `source` — the source-document cross-link resolved from source_type/source_id
        (NOT hydrated — failed rows often point at since-deleted documents, so `label`/`link_route`
        may be null; `link_type_label` always renders).

        - `event` — the failed source event (created | updated | deleted) with a headline
        label.

        - `attempts` — how many drain attempts were exhausted before the row terminated.

        - `last_error` — the preserved error text (capped at 60 KB).

        - `failed_at` / `available_at` / `created_at` — ISO-8601 timestamps.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        source:
                          type: object
                          properties:
                            type:
                              type: string
                            id:
                              type: integer
                            label:
                              type: string
                              nullable: true
                            link_type_label:
                              type: string
                            link_route:
                              type: string
                              nullable: true
                            link_legacy_url:
                              type: string
                              nullable: true
                            url:
                              type: string
                              nullable: true
                        event:
                          type: object
                          properties:
                            value:
                              type: string
                            label:
                              type: string
                        attempts:
                          type: integer
                        last_error:
                          type: string
                        available_at:
                          type: string
                        failed_at:
                          type: string
                        created_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                  first_page_url:
                    type: string
                  last_page_url:
                    type: string
                  next_page_url:
                    type: string
                    nullable: true
                  prev_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  links:
                    type: array
                example:
                  data:
                  - id: 9182
                    source:
                      type: App\Models\Bill
                      id: 4412
                      label: null
                      link_type_label: Bill
                      link_route: null
                      link_legacy_url: null
                      url: null
                    event:
                      value: updated
                      label: Updated
                    attempts: 5
                    last_error: 'QuickBooks Online rejected the request: Account ''Sales
                      Revenue'' is inactive.'
                    available_at: '2026-06-12T02:18:00+00:00'
                    failed_at: '2026-06-12T02:21:00+00:00'
                    created_at: '2026-06-12T01:40:00+00:00'
                  current_page: 1
                  last_page: 1
                  per_page: 10
                  total: 1
                  from: 1
                  to: 1
                  first_page_url: '{{protocol}}{{domain}}/api/ledger/outbox/failures?page=1'
                  last_page_url: '{{protocol}}{{domain}}/api/ledger/outbox/failures?page=1'
                  next_page_url: null
                  prev_page_url: null
                  path: '{{protocol}}{{domain}}/api/ledger/outbox/failures'
                  links: []
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-ledger-outbox-failures
  /api/ledger/outbox/failures/retry:
    post:
      tags:
      - Ledger (Accounting v2)
      summary: Retry Outbox Failures
      description: 'Re-queue terminally-failed outbox rows for another drain pass:
        reset them to pending, clear the attempt counter (a fresh max-attempts budget
        — otherwise the next failure would immediately re-terminate them), make them
        claimable now, and kick the drain.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Authentication:** Requires Bearer token. Requires the `accounting.sync`
        permission.


        **Body:** `{ "ids": [9182, 9183] }` retries the given failed rows; omit `ids`
        or pass `[]` to retry EVERY terminally-failed row.


        **Response:** `data.requeued` — the number of rows re-queued (0 if there were
        no failures to retry).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 9182
                - 9183
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      requeued:
                        type: integer
                  message:
                    type: string
                  status:
                    type: string
                example:
                  data:
                    requeued: 2
                  message: 2 failed rows re-queued — generation will reprocess them
                    shortly.
                  status: success
        '422':
          description: Unprocessable Content
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      ids.0:
                        type: array
                        items:
                          type: string
                example:
                  message: The ids.0 field must be an integer.
                  errors:
                    ids.0:
                    - The ids.0 field must be an integer.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-ledger-outbox-failures-retry
  /api/ledger/entries:
    get:
      tags:
      - Ledger (Accounting v2)
      summary: List Journal Entries
      description: "Paginated journal entries listing. Discarded regeneration drafts\
        \ are excluded; reversed entries stay visible so the reversal chain is browsable.\n\
        \n:::info[Authorization]\nAny valid API token can call this endpoint — no\
        \ specific scope required. [Manage tokens](https://app.sku.io/settings/api).\n\
        :::\n\n**Authentication:** Requires Bearer token (Personal Access Token).\n\
        \n**Filters (Spatie QueryBuilder):**\n- `filter[type]` — exact entry type\
        \ (AccountingTransactionTypeEnum, ~30 values, e.g. sales_order_invoice, fba_shipments,\
        \ bill)\n- `filter[status]` — exact lifecycle status: draft, posted, reversed\n\
        - `filter[display_status]` — exact, comma-multi supported. Values: excluded,\
        \ pending_sync, syncing, synced, update_pending, retrying, needs_attention,\
        \ failed, removed_in_provider, conflict, voided\n- `filter[sync_routing]`\
        \ — Routing/cadence axis (individual | daily | monthly)\n- `filter[source_type]`\
        \ — exact source morph class\n- `filter[batch_id]` — exact batch ID\n- `filter[date_from]`\
        \ / `filter[date_to]` — m/d/Y on effective_at (invalid dates silently ignored)\n\
        - `filter[connection]` — connection ID; entries holding a sync link on that\
        \ connection\n- `filter[search]` — partial match on reference, description,\
        \ amount (total_debit), id, the resolved counterparty name and the synced\
        \ provider document id (remote_id — e.g. a Xero invoice ID); scope with `search_columns`\
        \ (e.g. `search_columns=remote_id`) and force exact match with `search_strict_columns`\n\
        \n**Sorts:** id, effective_at, reference, total_debit, created_at, type, counterparty,\
        \ due_date, display_status, sync_routing (default: -effective_at). `type`\
        \ sorts the stored entry-type enum; `counterparty` sorts the resolved supplier/customer/marketplace/provider\
        \ name across polymorphic sources; `due_date` sorts the source purchase invoice's\
        \ due date (other sources sort NULL).\n\n**Pagination:** per_page default\
        \ 10, clamped to max 100.\n\nEach row carries a `display_status` object (key/label/color/reason).\
        \ A batch member has no standalone status — its `display_status` mirrors its\
        \ batch aggregate's live status at read time (Pending Sync / Syncing / Synced\
        \ / Failed …); there is deliberately no `batched` status value. `reason` is\
        \ the chip-tooltip hint: `batch_member` for batch members, comma-joined eligibility\
        \ exclusion reasons (or `no_accounting_connection`) for excluded entries,\
        \ null otherwise. Detail-only sections (lines, sync_links, operations, reversal_chain)\
        \ are NOT included on the index — use the show endpoint.\n\n**Status is null\
        \ for historical entries:** the `display_status` and `routing` objects each\
        \ report null key/label/color when an entry has left the live books — it is\
        \ discarded (superseded by a regenerated replacement: `replaced_by_id` set\
        \ + `discarded_at`) or a reversed original (`status = reversed`). Such rows\
        \ can never sync (the batch rollup, reports and live lists all exclude them),\
        \ so a frozen `synced` status would mislead; the supersession marker carries\
        \ the why instead. A live reversal contra entry (`reversal_of_id` set, still\
        \ posted) is NOT historical and keeps its status.\n\n**Advanced filters (`filter_groups`):**\
        \ base64-encoded JSON tree of AND/OR groups, applied via GroupedFilterSupport\
        \ (same stack as Purchase Orders). Decoded shape:\n```\n{\n  \"conjunction\"\
        : \"and\",\n  \"children\": [\n    {\"type\": \"condition\", \"condition\"\
        : {\"column\": \"reference\", \"operator\": \"contains\", \"value\": \"INV\"\
        }},\n    {\"type\": \"group\", \"group\": {\"conjunction\": \"or\", \"children\"\
        : [...]}}\n  ]\n}\n```\n**Filterable columns:** `reference`, `description`,\
        \ `entry_type`, `entry_status`, `entry_display_status`, `currency_code`, `counterparty`\
        \ (text: is, is_not, contains, does_not_contain, starts_with, ends_with, is_empty,\
        \ is_not_empty, is_one_of); `id`, `total_debit`, `total_credit`, `entry_batch_id`\
        \ (numeric: is, is_not, is_one_of, greater_than, less_than, greater_than_or_equal,\
        \ less_than_or_equal, between, is_empty, is_not_empty); `nominal_code_id`\
        \ (text, relationship — matches entries posting to the nominal code on any\
        \ line); `effective_at` (date), `posted_at`, `created_at` (datetime: is, is_not,\
        \ before, after, on_or_before, on_or_after, between, today, yesterday, past_week,\
        \ past_month, …). `counterparty` has no stored column — it filters on the\
        \ resolved supplier/customer/marketplace name via the same correlated subquery\
        \ used for search and sort.\n\nUnregistered columns in the tree are rejected\
        \ with HTTP 400 (InvalidFilterQuery).\n\nEach entry includes `provider_link`\
        \ — the accounting-provider document it is synced to (the Xero/QBO column):\
        \ { provider, remote_type, remote_id, link_type_label, label, link_route (internal\
        \ detail page, or null when none exists yet), remote_url (provider deep link)\
        \ }. It is null for entries not yet synced to a provider.\n\n**Per-lens columns\
        \ (`lens` query param):** the scoped Transactions tabs (Invoices / Journals\
        \ / Purchase Orders) are thin wrappers over this one endpoint and request\
        \ extra columns via `?lens=`. The All tab, dashboard, detail and export paths\
        \ send no lens, so the response keeps the shared columns only with zero extra\
        \ queries. When a lens is present each row gains a derive-on-read block:\n\
        - `lens=invoices` adds `counterparty` ({ name, id, link_type_label, link_route\
        \ }; a CRM party has `link_type_label` \"Supplier\"/\"Customer\" + numeric\
        \ `id` + `link_route`; an AR source (sales order / sales credit) with no CRM\
        \ customer falls back to a marketplace customer — `name` \"{Integration} Customer\"\
        \ e.g. \"Amazon Customer\", `link_type_label` \"Customer\", `id` + `link_route`\
        \ null; a settlement source (Amazon financial-event group) falls back to a\
        \ bare marketplace label — `name` the integration name e.g. \"Amazon\", `link_type_label`\
        \ \"Marketplace\", `id` + `link_route` null; a ShipMyOrders provider invoice\
        \ (a 3PL fulfilment-provider bill, no CRM party) falls back to a fixed provider\
        \ label — `name` \"SMO\", `link_type_label` \"Provider\", `id` + `link_route`\
        \ null; null/absent when the source resolves no party or was deleted), `due_date`\
        \ (YYYY-MM-DD date-only, no timezone conversion; null unless the source carries\
        \ one — only purchase invoices do), and `tax_total` (scale-4 string summed\
        \ across the entry's lines, or null when no line carries tax).\n- `lens=journals`\
        \ adds `debit_account` and `credit_account` — each is either { split: false,\
        \ nominal_code_id, code, name, link_route } for a side posting to one account,\
        \ or { split: true, count } when the side fans out across several codes, or\
        \ null when the side has no lines — plus `batch` ({ id, label, status, period_start,\
        \ period_end, link_route } or null for unbatched entries).\n- `lens=purchase-orders`\
        \ adds `counterparty` (the supplier, same shape as above) and `stage` ({ ordered:\
        \ true, received: none|partial|full, invoiced: none|partial|full }) derived\
        \ from the source purchase order's receipt_status / invoice_status.\n\nEach\
        \ row carries `line_count` — the number of GL-impact journal lines on the\
        \ entry (cheap `withCount` subquery) — powering the entries table's inline\
        \ expandable \"Lines\" column. Fetch the lines themselves via **Get Journal\
        \ Entry Lines** (`/api/ledger/entries/{entry}/lines`).\n\n**`can_sync_now`**\
        \ (boolean) — whether a manual \"Sync Now\" can push this entry right now.\
        \ The per-transaction-type Sync toggle, granularity opt-out and the per-type\
        \ start date only gate *automatic/scheduled* sync; a manual push bypasses\
        \ them, so `can_sync_now` stays `true` for a benign \"Auto-off\" entry. It\
        \ is `false` only when a *structural* blocker applies (connection inactive,\
        \ entry is a batch member / open batch, internal-only, or before the accounting\
        \ provider's conversion/start date) — those block even a manual push. Drives\
        \ the UI split between a grey \"Auto-off · push anytime\" chip (`display_status=excluded`\
        \ + `can_sync_now=true`) and an amber \"Blocked\" chip (`display_status=excluded`\
        \ + `can_sync_now=false`).\n\n**provider_status** (response field) — the provider's\
        \ own transaction status on the synced document (primary sync link remote_status);\
        \ null for unsynced entries. Backs the Provider Status column + filter."
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        uuid:
                          type: string
                        type:
                          type: object
                          properties:
                            value:
                              type: string
                            label:
                              type: string
                        status:
                          type: string
                        display_status:
                          type: object
                          properties:
                            key:
                              type: string
                            label:
                              type: string
                            color:
                              type: string
                            reason:
                              type: string
                              nullable: true
                        can_sync_now:
                          type: boolean
                        locked_update_pending:
                          type: boolean
                        locked_amend_blocked:
                          type: boolean
                        routing:
                          type: object
                          properties:
                            key:
                              type: string
                            label:
                              type: string
                            color:
                              type: string
                            batch_id:
                              type: string
                              nullable: true
                            batch_route:
                              type: string
                              nullable: true
                        effective_at:
                          type: string
                        posted_at:
                          type: string
                        currency_code:
                          type: string
                        total_debit:
                          type: string
                        total_credit:
                          type: string
                        document_total:
                          type: string
                        document_number:
                          type: string
                        reference:
                          type: string
                        reference_suffix:
                          type: string
                          nullable: true
                        description:
                          type: string
                        source:
                          type: object
                          properties:
                            type:
                              type: string
                            id:
                              type: integer
                            label:
                              type: string
                            link_type_label:
                              type: string
                            link_route:
                              type: string
                            link_legacy_url:
                              type: string
                              nullable: true
                            url:
                              type: string
                        batch_id:
                          type: string
                          nullable: true
                        sync_override:
                          type: string
                          nullable: true
                        integrity_flag:
                          type: string
                          nullable: true
                        reversal_of_id:
                          type: string
                          nullable: true
                        replaced_by_id:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                        provider_link:
                          type: object
                          properties:
                            provider:
                              type: string
                            remote_type:
                              type: string
                            remote_id:
                              type: string
                            link_type_label:
                              type: string
                            label:
                              type: string
                            link_route:
                              type: string
                            remote_url:
                              type: string
                        provider_status:
                          type: string
                  current_page:
                    type: integer
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                    items:
                      type: object
                      properties:
                        url:
                          type: string
                          nullable: true
                        label:
                          type: string
                        active:
                          type: boolean
                  next_page_url:
                    type: string
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 1842
                    uuid: 9c2f1b7e-4a6d-4f0e-9b1a-2d8c5e7f3a10
                    type:
                      value: sales_order_invoice
                      label: Sales Order Invoice
                    status: posted
                    display_status:
                      key: synced
                      label: Synced
                      color: success
                      reason: null
                    can_sync_now: true
                    locked_update_pending: false
                    locked_amend_blocked: false
                    routing:
                      key: individual
                      label: Individual
                      color: grey
                      batch_id: null
                      batch_route: null
                    effective_at: '2026-06-05T14:30:00+00:00'
                    posted_at: '2026-06-05T14:35:12+00:00'
                    currency_code: USD
                    total_debit: '249.9900'
                    total_credit: '249.9900'
                    document_total: '249.9900'
                    document_number: INV-1842
                    reference: SO-10293
                    reference_suffix: null
                    description: Sales order invoice for SO-10293
                    source:
                      type: App\Models\SalesOrder
                      id: 10293
                      label: SO-10293
                      link_type_label: Sales Order
                      link_route: /orders/sales-orders/10293
                      link_legacy_url: null
                      url: /orders/sales-orders/10293
                    batch_id: null
                    sync_override: null
                    integrity_flag: null
                    reversal_of_id: null
                    replaced_by_id: null
                    created_at: '2026-06-05T14:30:02+00:00'
                    provider_link:
                      provider: Xero
                      remote_type: xero_invoice
                      remote_id: a1b2c3d4-0000-0000-0000-000000000000
                      link_type_label: Invoice
                      label: INV-1042
                      link_route: /integrations/xero/invoices/55
                      remote_url: https://go.xero.com/AccountsReceivable/View.aspx?InvoiceID=a1b2c3d4-0000-0000-0000-000000000000
                    provider_status: AUTHORISED
                  - id: 1841
                    uuid: 5e8d2c1a-9f3b-4e7d-8a60-1b4c6d9e2f55
                    type:
                      value: fba_shipments
                      label: FBA Shipments
                    status: draft
                    display_status:
                      key: pending_sync
                      label: Pending Sync
                      color: info
                      reason: batch_member
                    can_sync_now: false
                    locked_update_pending: false
                    locked_amend_blocked: false
                    routing:
                      key: daily
                      label: Daily
                      color: purple
                      batch_id: 57
                      batch_route: /ledger/batches/57
                    effective_at: '2026-06-04T09:00:00+00:00'
                    posted_at: null
                    currency_code: USD
                    total_debit: '1240.5000'
                    total_credit: '1240.5000'
                    document_total: '1240.5000'
                    document_number: JE-1841
                    reference: FBA-SHIP-2026-06-04
                    reference_suffix: null
                    description: FBA shipments for 06/04/2026
                    source:
                      type: Modules\Amazon\Entities\AmazonLedger
                      id: 88451
                      label: '#88451'
                      link_type_label: Amazon Ledger
                      link_route: null
                      link_legacy_url: null
                      url: null
                    batch_id: 57
                    sync_override: null
                    integrity_flag: null
                    reversal_of_id: null
                    replaced_by_id: null
                    created_at: '2026-06-04T09:02:41+00:00'
                    provider_link: null
                    provider_status: AUTHORISED
                  current_page: 1
                  first_page_url: https://sku-alt.test/api/ledger/entries?page=1
                  from: 1
                  last_page: 93
                  last_page_url: https://sku-alt.test/api/ledger/entries?page=93
                  links:
                  - url: null
                    label: '&laquo; Previous'
                    active: false
                  - url: https://sku-alt.test/api/ledger/entries?page=1
                    label: '1'
                    active: true
                  - url: https://sku-alt.test/api/ledger/entries?page=2
                    label: Next &raquo;
                    active: false
                  next_page_url: https://sku-alt.test/api/ledger/entries?page=2
                  path: https://sku-alt.test/api/ledger/entries
                  per_page: 10
                  prev_page_url: null
                  to: 10
                  total: 924
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-ledger-entries
  /api/ledger/entries/needs-attention:
    get:
      tags:
      - Ledger (Accounting v2)
      summary: List Needs-Attention Groups
      description: 'The needs-attention inbox feed: non-discarded entries whose display
        status needs a human (needs_attention, failed, conflict, removed_in_provider
        — capped at the latest 1000), grouped server-side by error cause so the UI
        can offer fix-once-retry-all.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Authentication:** Requires Bearer token.


        **Grouping:** each group keys on the latest sync operation''s `error_class`
        plus a normalized cause message (numeric IDs masked to `#` so per-record noise
        collapses into one cause, truncated to 160 chars). Entries with no operation
        error group under `status:<display_status>`. Groups are sorted by count descending.


        **Response shape (per group):**

        - `cause_key` — stable grouping key (error_class[:md5-of-message] or status:&lt;display_status>)

        - `label` — human-readable cause (normalized message, headline-cased error
        class, or display-status label)

        - `error_class` — retryable_transient | auth_connection | auto_remediable
        | user_action_required | terminal_internal | conflict, or null

        - `count` — total entries in the group

        - `entry_ids` — up to 25 sample entry IDs

        - `latest_error_payload` — the raw error payload of the group''s latest operation,
        or null'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      groups:
                        type: array
                        items:
                          type: object
                          properties:
                            cause_key:
                              type: string
                            label:
                              type: string
                            error_class:
                              type: string
                            count:
                              type: integer
                            entry_ids:
                              type: array
                              items:
                                type: integer
                            latest_error_payload:
                              type: object
                              properties:
                                message:
                                  type: string
                                provider_code:
                                  type: string
                example:
                  data:
                    groups:
                    - cause_key: user_action_required:d2b5c3a1e4f6a7b8c9d0e1f2a3b4c5d6
                      label: 'Account # Sales Revenue is inactive in QuickBooks Online.'
                      error_class: user_action_required
                      count: 14
                      entry_ids:
                      - 1842
                      - 1836
                      - 1831
                      - 1828
                      - 1815
                      - 1809
                      - 1804
                      - 1799
                      - 1795
                      - 1788
                      - 1781
                      - 1774
                      - 1769
                      - 1762
                      latest_error_payload:
                        message: Account 4000 Sales Revenue is inactive in QuickBooks
                          Online.
                        provider_code: '6240'
                    - cause_key: auth_connection
                      label: Auth Connection
                      error_class: auth_connection
                      count: 3
                      entry_ids:
                      - 1822
                      - 1817
                      - 1801
                      latest_error_payload:
                        error: 'Token refresh failed: invalid_grant'
                    - cause_key: status:removed_in_provider
                      label: Removed in provider
                      error_class: null
                      count: 1
                      entry_ids:
                      - 1755
                      latest_error_payload: null
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-ledger-entries-needs-attention
  /api/ledger/entries/stale-precutover:
    get:
      tags:
      - Ledger (Accounting v2)
      summary: List Stale Pre-Cutover Entries
      description: 'Imported pre-cutover journal entries whose SOURCE document was
        edited after the entry was imported. Automatic generation deliberately never
        rewrites frozen pre-cutover history, so these entries'' figures no longer
        match their documents — this feed makes that drift visible so it can be fixed
        deliberately with Rebuild Journal Entry (single) or Bulk Entry Action with
        action `rebuild`.


        **Authentication:** Requires Bearer token.


        **Response fields:**

        - `count` — total stale entries across all source types

        - `capped` — true when `entries` holds only the first 200 rows. To rebuild
        everything in one call, use Bulk Entry Action with `action: "rebuild"` and
        `scope: "all_stale"` — it targets the full stale set, not just this preview.

        - `entries` — up to 200 rows, most-recently-drifted first. Each row carries
        the entry identity (`id`, `document_number`, `reference`, `type`, `display_status`),
        its amounts (`total_debit`, `total_credit`, `currency_code`), its accounting
        date (`effective_at`), the source document link (`source`), and the drift
        facts: `source_updated_at` (when the document last changed) vs `imported_at`
        (when the entry was imported).


        Returns `count: 0` with an empty list for tenants without an accounting cutover
        (no frozen history exists).'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      count:
                        type: integer
                      capped:
                        type: boolean
                      entries:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            reference:
                              type: string
                            reference_suffix:
                              type: integer
                            document_number:
                              type: string
                            type:
                              type: object
                              properties:
                                value:
                                  type: string
                                label:
                                  type: string
                            display_status:
                              type: object
                              properties:
                                key:
                                  type: string
                                label:
                                  type: string
                                color:
                                  type: string
                            currency_code:
                              type: string
                            total_debit:
                              type: string
                            total_credit:
                              type: string
                            effective_at:
                              type: string
                            source:
                              type: object
                              properties:
                                type:
                                  type: string
                                id:
                                  type: integer
                                label:
                                  type: string
                                link_type_label:
                                  type: string
                                link_route:
                                  type: string
                                link_legacy_url:
                                  type: string
                                  nullable: true
                                url:
                                  type: string
                            source_updated_at:
                              type: string
                            imported_at:
                              type: string
                  status:
                    type: string
                example:
                  data:
                    count: 3
                    capped: false
                    entries:
                    - id: 8114
                      reference: BILL-1042
                      reference_suffix: 0
                      document_number: BILL-8114
                      type:
                        value: bill
                        label: Bill
                      display_status:
                        key: not_synced
                        label: Not Synced
                        color: grey
                      currency_code: USD
                      total_debit: '1250.0000'
                      total_credit: '1250.0000'
                      effective_at: '2025-11-14T00:00:00+00:00'
                      source:
                        type: App\Models\Bill
                        id: 1042
                        label: BILL-1042
                        link_type_label: Bill
                        link_route: /purchases/bills/1042
                        link_legacy_url: null
                        url: /purchases/bills/1042
                      source_updated_at: '2026-07-08T15:21:44+00:00'
                      imported_at: '2026-06-11T03:12:09+00:00'
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-ledger-entries-stale-precutover
  /api/ledger/entries/source-types:
    get:
      tags:
      - Ledger (Accounting v2)
      summary: List Source Types
      description: 'Distinct source-document origins present on live (non-discarded,
        non-batch-aggregate) journal entries — powers the entries-list "Source" quick
        filter so it offers only origins the tenant actually has (e.g. "Amazon Settlement",
        "Sales Order", "Bill"). Lets users isolate settlement-derived bills/invoices
        that have no batch.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Authentication:** Requires Bearer token.


        **Usage:** each `value` is the backend morph class to pass back as `filter[source_type]=<value>`
        on `GET /api/ledger/entries`; `label` is the friendly name to display. Options
        are sorted by label.


        **No query parameters.**'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      source_types:
                        type: array
                        items:
                          type: object
                          properties:
                            value:
                              type: string
                            label:
                              type: string
                example:
                  data:
                    source_types:
                    - value: Modules\Amazon\Entities\AmazonFinancialEventGroup
                      label: Amazon Settlement
                    - value: App\Models\Bill
                      label: Bill
                    - value: App\Models\PurchaseOrder
                      label: Purchase Order
                    - value: App\Models\SalesOrder
                      label: Sales Order
                    - value: App\Models\SalesOrderFulfillment
                      label: Sales Order Fulfillment
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-ledger-entries-source-types
  /api/ledger/entries/provider-statuses:
    get:
      tags:
      - Ledger (Accounting v2)
      summary: List Provider Statuses
      description: 'Distinct provider transaction statuses (sync link remote_status
        — Xero DRAFT/AUTHORISED/PAID/VOIDED, QBO Paid/Open, …) present for the tenant,
        as {value, label} options for the entries table''s Provider Status filter
        (filter[provider_status]=...). Values are provider-native raw statuses; labels
        are Title Case.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      provider_statuses:
                        type: array
                        items:
                          type: object
                          properties:
                            value:
                              type: string
                            label:
                              type: string
                example:
                  data:
                    provider_statuses:
                    - value: AUTHORISED
                      label: Authorised
                    - value: DRAFT
                      label: Draft
                    - value: PAID
                      label: Paid
                    - value: VOIDED
                      label: Voided
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-ledger-entries-provider-statuses
  /api/ledger/entries/{entry}:
    get:
      tags:
      - Ledger (Accounting v2)
      summary: Get Journal Entry
      description: 'Journal entry detail: everything from the index row plus the detail-only
        sections —


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        - `lines` — the GL impact rows (direction, amount, quantity, tax_amount, nominal_code,
        tax_rate, source_line, role)

        - `invoice_view` — Xero-style invoice document view, present only for invoice-style
        entry types (sales_order_invoice, batch_sales_order_invoice, purchase_order_invoice,
        sales_credit, vendor_credit, bill) that resolve at least one product line;
        `null` for manual journals and quantity-free entries. One row per source line
        (`item`, `description`, `quantity`, `unit_price`, `discount_amount`, `account`,
        `tax_rate`, `tax_amount`, `amount`) with a `subtotal` / `discount_total` /
        `tax_total` / `total` / `currency_code` footer. Money + quantity fields are
        4dp strings; `total` = `subtotal` + `tax_total`. Tax and quantity are read
        from the primary (revenue / COGS / expense) leg only, so they are never double-counted
        against the auto-booked control leg.


        - `sync_links` — provider links with connection identity, remote document
        type/ID, the provider deep link (`remote_url`, Xero go.xero.com / QBO web-app
        URL patterns), link_state (unlinked, linked_current, linked_stale, linked_conflict,
        remote_gone), remote_status and last_remote_seen_at

        - `operations` — the latest 20 sync operations (state, operation create|update|void|delete|link,
        direction push|pull, error_class, error_payload, attempts, connection) each
        with its append-only `transitions` audit trail

        - `reversal_chain` — summaries of the linked reversal_of / reversed_by / replaced_by
        / replaces entries


        **counterparty** — the supplier (AP) or customer (AR) the source document
        is against, as a cross-linkable reference: `{ name, id, link_type_label, link_route
        }`. Present on the detail path (and the Invoices / Purchase Orders list lenses)
        whenever the eager-loaded source resolves a party. Four shapes: (1) a linked
        CRM party — `name` + numeric `id` + `link_type_label` "Supplier"/"Customer"
        + `link_route` `/crm/suppliers/{id}` or `/crm/customers/{id}`; (2) a **marketplace-customer
        fallback** for AR sources (sales order / sales credit) with no CRM customer
        — `name` is "{Integration} Customer" (e.g. "Amazon Customer", "Shopify Customer"),
        `link_type_label` "Customer", with `id` and `link_route` `null` (no detail
        page to link to); (3) a **marketplace fallback** for a settlement source (Amazon
        financial-event group, whose sale + fee legs all net against the marketplace)
        — `name` is the bare integration name (e.g. "Amazon"), `link_type_label` "Marketplace",
        with `id` and `link_route` `null`; (4) a **provider fallback** for a ShipMyOrders
        provider invoice (a 3PL fulfilment-provider bill carrying no CRM party and
        no integration instance) — `name` is the fixed label "SMO", `link_type_label`
        "Provider", with `id` and `link_route` `null`; (5) the field is **absent entirely**
        only for sources that resolve none of the above (a manual journal with no
        source, a native SKU.io order missing its customer, a deleted source) — match
        it with `if (entry.counterparty)`.


        **Sync axes are null for historical entries:** the `sync`, `progress` and
        `routing` objects each report null key/label/color when an entry has left
        the live books — it is discarded (superseded by a regenerated replacement:
        `replaced_by_id` set + `discarded_at`) or a reversed original (`status = reversed`).
        Such rows can never sync (the batch rollup, reports and live lists all exclude
        them), so a frozen `enabled`/`synced` axis would mislead; the supersession
        marker carries the why instead. A live reversal contra entry (`reversal_of_id`
        set, still posted) is NOT historical and keeps its axes.


        **Authentication:** Requires Bearer token.


        Returns 404 when the entry does not exist (route is numeric-constrained).


        Each line also carries `role` — its economic role within a document-style
        entry (`primary` product leg, `control` A/R or A/P leg, `tax` leg, or `discount`
        leg), recovered from the mapped nominal code. The GL Impact table shows the
        invoiced quantity (and copied line description) on `primary` legs only: v2
        copies the quantity onto the control leg too, so a role-blind column would
        repeat it on Accounts Payable / Receivable and read as a double-count. `role`
        is `null` on paths that don''t load lines.


        Each line also carries `pushed_to_provider`: `false` marks the control line
        (A/R on an Invoice/Credit Note, A/P on a Bill) that the connected provider
        auto-books itself — SKU omits it from the push, so the GL Impact table dims
        it. `true` = the line is pushed. `null` when no accounting provider is connected.
        The entry''s `sync_provider` (''Xero'' / ''QuickBooks'', or `null`) names
        that provider for the hint.


        **`can_sync_now`** (boolean) — whether a manual "Sync Now" can push this entry
        right now. The per-transaction-type Sync toggle, granularity opt-out and the
        per-type start date only gate *automatic/scheduled* sync; a manual push bypasses
        them, so `can_sync_now` stays `true` for a benign "Auto-off" entry. It is
        `false` only when a *structural* blocker applies (connection inactive, entry
        is a batch member / open batch, internal-only, or before the accounting provider''s
        conversion/start date) — those block even a manual push. Drives the UI split
        between a grey "Auto-off · push anytime" chip (`display_status=excluded` +
        `can_sync_now=true`) and an amber "Blocked" chip (`display_status=excluded`
        + `can_sync_now=false`).


        **provider_payment** — for invoice-style entries (sales/purchase invoices,
        bills) linked to an accounting provider, the paid status + payment metadata:
        normalized `payment_state` (paid / partially_paid / unpaid / voided), the
        provider invoice lifecycle `provider_status` (Xero DRAFT/AUTHORISED/PAID/VOIDED),
        amounts (total/paid/due/credited), the `payments` applied, and provider-dependent
        `metadata`. Xero is fully populated; QBO is header-only and flagged `data_availability:
        limited`. `null` for non-invoice or unlinked entries.


        **`chain`** — the full reverse+replace lineage for the source document (every
        version, its reversal contras and the current head), oldest→newest, for a
        chain-of-events view. Each step: { id, document_number, reference, reference_suffix,
        status (draft|posted|reversed), role (original|reversal|replacement), is_current,
        is_viewed, reversal_of_id, replaced_by_id, effective_at, provider_link ({
        remote_type, remote_id, remote_url, link_state, remote_status, badge } or
        null) }. `[]` when the entry has never been reversed or replaced.


        Also returns `sync_override_provenance` (who/what/when set the sync override:
        `source` = `user` | `legacy_cutover` | `system`, `set_at`, `set_by`; null
        when no override) and `is_settlement_sourced` (boolean — a marketplace settlement
        posting, exempt from per-channel sync toggles).


        `provider_payment.unreflected_credit_notes` — credit notes the accounting
        provider has applied to this bill that are not yet reflected in SKU as vendor-credit
        allocations. Empty when everything reconciles. Each item carries `credit_note_id`,
        `credit_note_number`, `applied_amount` (applied at the provider), `reflected_amount`
        (covered by SKU allocations) and `shortfall` (the remaining unreflected amount).'
      parameters:
      - name: entry
        in: path
        schema:
          type: integer
        required: true
        description: Ledger journal entry ID (numeric). Route-model bound — returns
          404 if the entry does not exist.
        example: '1842'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      uuid:
                        type: string
                      type:
                        type: object
                        properties:
                          value:
                            type: string
                          label:
                            type: string
                      status:
                        type: string
                      display_status:
                        type: object
                        properties:
                          key:
                            type: string
                          label:
                            type: string
                          color:
                            type: string
                          reason:
                            type: string
                            nullable: true
                      can_sync_now:
                        type: boolean
                      locked_update_pending:
                        type: boolean
                      locked_amend_blocked:
                        type: boolean
                      sync:
                        type: object
                        properties:
                          key:
                            type: string
                          label:
                            type: string
                          color:
                            type: string
                          reason:
                            type: string
                            nullable: true
                      progress:
                        type: object
                        properties:
                          key:
                            type: string
                          label:
                            type: string
                          color:
                            type: string
                          via_batch:
                            type: boolean
                      routing:
                        type: object
                        properties:
                          key:
                            type: string
                          label:
                            type: string
                          color:
                            type: string
                          batch_id:
                            type: string
                            nullable: true
                          batch_route:
                            type: string
                            nullable: true
                      effective_at:
                        type: string
                      posted_at:
                        type: string
                      currency_code:
                        type: string
                      total_debit:
                        type: string
                      total_credit:
                        type: string
                      document_total:
                        type: string
                      document_number:
                        type: string
                      reference:
                        type: string
                      reference_suffix:
                        type: string
                        nullable: true
                      description:
                        type: string
                      source:
                        type: object
                        properties:
                          type:
                            type: string
                          id:
                            type: integer
                          label:
                            type: string
                          link_type_label:
                            type: string
                          link_route:
                            type: string
                          link_legacy_url:
                            type: string
                            nullable: true
                          url:
                            type: string
                      counterparty:
                        type: object
                        properties:
                          name:
                            type: string
                          id:
                            type: integer
                          link_type_label:
                            type: string
                          link_route:
                            type: string
                      batch_id:
                        type: string
                        nullable: true
                      sync_override:
                        type: string
                        nullable: true
                      sync_override_provenance:
                        type: object
                        properties:
                          source:
                            type: string
                          set_at:
                            type: string
                          set_by:
                            type: object
                            properties:
                              id:
                                type: integer
                              name:
                                type: string
                      is_settlement_sourced:
                        type: boolean
                      sync_provider:
                        type: string
                      integrity_flag:
                        type: string
                        nullable: true
                      reversal_of_id:
                        type: string
                        nullable: true
                      replaced_by_id:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      invoice_view:
                        type: object
                        properties:
                          lines:
                            type: array
                            items:
                              type: object
                              properties:
                                item:
                                  type: string
                                description:
                                  type: string
                                quantity:
                                  type: string
                                unit_price:
                                  type: string
                                discount_amount:
                                  type: string
                                  nullable: true
                                account:
                                  type: object
                                  properties:
                                    nominal_code_id:
                                      type: integer
                                    code:
                                      type: string
                                    name:
                                      type: string
                                    link_route:
                                      type: string
                                tax_rate:
                                  type: object
                                  properties:
                                    id:
                                      type: integer
                                    name:
                                      type: string
                                    rate:
                                      type: number
                                tax_amount:
                                  type: string
                                amount:
                                  type: string
                                source_line:
                                  type: object
                                  properties:
                                    type:
                                      type: string
                                    id:
                                      type: integer
                          subtotal:
                            type: string
                          discount_total:
                            type: string
                          tax_total:
                            type: string
                          total:
                            type: string
                          currency_code:
                            type: string
                      provider_payment:
                        type: object
                        properties:
                          provider:
                            type: string
                          provider_label:
                            type: string
                          document_type:
                            type: string
                          provider_status:
                            type: string
                          provider_status_label:
                            type: string
                          provider_status_color:
                            type: string
                          payment_state:
                            type: string
                          currency_code:
                            type: string
                          total:
                            type: string
                          amount_paid:
                            type: string
                          amount_due:
                            type: string
                          amount_credited:
                            type: string
                          sub_total:
                            type: string
                          tax_total:
                            type: string
                          due_date:
                            type: string
                          fully_paid_on:
                            type: string
                          document_date:
                            type: string
                          provider_url:
                            type: string
                          payments:
                            type: array
                            items:
                              type: object
                              properties:
                                date:
                                  type: string
                                amount:
                                  type: string
                                reference:
                                  type: string
                                type:
                                  type: string
                                status:
                                  type: string
                                is_reconciled:
                                  type: boolean
                                bank_account:
                                  type: string
                                provider_payment_id:
                                  type: string
                                provider_url:
                                  type: string
                                link_route:
                                  type: string
                                link_type_label:
                                  type: string
                                link_id:
                                  type: integer
                          metadata:
                            type: array
                            items:
                              type: object
                              properties:
                                label:
                                  type: string
                                value:
                                  type: string
                          data_availability:
                            type: string
                          availability_message:
                            type: string
                            nullable: true
                          last_synced_at:
                            type: string
                          unreflected_credit_notes:
                            type: array
                      lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            direction:
                              type: string
                            amount:
                              type: string
                            quantity:
                              type: string
                              nullable: true
                            tax_amount:
                              type: string
                            description:
                              type: string
                            nominal_code:
                              type: object
                              properties:
                                id:
                                  type: integer
                                code:
                                  type: string
                                name:
                                  type: string
                            tax_rate:
                              type: string
                              nullable: true
                            source_line:
                              type: string
                              nullable: true
                            role:
                              type: string
                            pushed_to_provider:
                              type: boolean
                      sync_links:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            provider:
                              type: string
                            connection:
                              type: object
                              properties:
                                id:
                                  type: integer
                                name:
                                  type: string
                            remote_type:
                              type: string
                            remote_id:
                              type: string
                            remote_url:
                              type: string
                            link_state:
                              type: string
                            remote_status:
                              type: string
                            last_remote_seen_at:
                              type: string
                      operations:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            state:
                              type: string
                            operation:
                              type: string
                            direction:
                              type: string
                            error_class:
                              type: string
                            retry_disposition:
                              type: string
                            error_payload:
                              type: object
                              properties:
                                message:
                                  type: string
                                user_title:
                                  type: string
                                user_message:
                                  type: string
                                provider_code:
                                  type: string
                                retry_disposition:
                                  type: string
                            attempts:
                              type: integer
                            connection:
                              type: object
                              properties:
                                id:
                                  type: integer
                                name:
                                  type: string
                            created_at:
                              type: string
                            started_at:
                              type: string
                            finished_at:
                              type: string
                            transitions:
                              type: array
                              items:
                                type: object
                                properties:
                                  from:
                                    type: string
                                    nullable: true
                                  to:
                                    type: string
                                  reason:
                                    type: string
                                  created_at:
                                    type: string
                      reversal_chain:
                        type: object
                        properties:
                          reversal_of:
                            type: string
                            nullable: true
                          reversed_by:
                            type: string
                            nullable: true
                          replaced_by:
                            type: string
                            nullable: true
                          replaces:
                            type: object
                            properties:
                              id:
                                type: integer
                              document_number:
                                type: string
                              reference:
                                type: string
                              status:
                                type: string
                      provider_link:
                        type: string
                        nullable: true
                      chain:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            document_number:
                              type: string
                            reference:
                              type: string
                            reference_suffix:
                              type: integer
                            status:
                              type: string
                            role:
                              type: string
                            is_current:
                              type: boolean
                            is_viewed:
                              type: boolean
                            reversal_of_id:
                              type: string
                              nullable: true
                            replaced_by_id:
                              type: integer
                            effective_at:
                              type: string
                            provider_link:
                              type: object
                              properties:
                                remote_type:
                                  type: string
                                remote_id:
                                  type: string
                                remote_url:
                                  type: string
                                link_state:
                                  type: string
                                remote_status:
                                  type: string
                                badge:
                                  type: string
                example:
                  data:
                    id: 1842
                    uuid: 9c2f1b7e-4a6d-4f0e-9b1a-2d8c5e7f3a10
                    type:
                      value: sales_order_invoice
                      label: Sales Order Invoice
                    status: posted
                    display_status:
                      key: needs_attention
                      label: Needs attention
                      color: error
                      reason: null
                    can_sync_now: true
                    locked_update_pending: false
                    locked_amend_blocked: false
                    sync:
                      key: enabled
                      label: Enabled
                      color: success
                      reason: null
                    progress:
                      key: needs_attention
                      label: Needs attention
                      color: error
                      via_batch: false
                    routing:
                      key: individual
                      label: Individual
                      color: grey
                      batch_id: null
                      batch_route: null
                    effective_at: '2026-06-05T14:30:00+00:00'
                    posted_at: '2026-06-05T14:35:12+00:00'
                    currency_code: USD
                    total_debit: '249.9900'
                    total_credit: '249.9900'
                    document_total: '249.9900'
                    document_number: INV-1842
                    reference: SO-10293
                    reference_suffix: null
                    description: Sales order invoice for SO-10293
                    source:
                      type: App\Models\SalesOrder
                      id: 10293
                      label: SO-10293
                      link_type_label: Sales Order
                      link_route: /orders/sales-orders/10293
                      link_legacy_url: null
                      url: /orders/sales-orders/10293
                    counterparty:
                      name: Acme Retail LLC
                      id: 5821
                      link_type_label: Customer
                      link_route: /crm/customers/5821
                    batch_id: null
                    sync_override: null
                    sync_override_provenance:
                      source: user
                      set_at: '2026-07-16T14:00:00+00:00'
                      set_by:
                        id: 12
                        name: Julia T
                    is_settlement_sourced: false
                    sync_provider: Xero
                    integrity_flag: null
                    reversal_of_id: null
                    replaced_by_id: null
                    created_at: '2026-06-05T14:30:02+00:00'
                    invoice_view:
                      lines:
                      - item: WIDGET-BLU
                        description: Blue Widget
                        quantity: '3.0000'
                        unit_price: '76.5133'
                        discount_amount: null
                        account:
                          nominal_code_id: 40
                          code: '4000'
                          name: Sales Revenue
                          link_route: /ledger/accounts/40
                        tax_rate:
                          id: 2
                          name: Tax on Sales (8.875%)
                          rate: 8.875
                        tax_amount: '20.4500'
                        amount: '229.5400'
                        source_line:
                          type: App\Models\SalesOrderLine
                          id: 30412
                      subtotal: '229.5400'
                      discount_total: '0.0000'
                      tax_total: '20.4500'
                      total: '249.9900'
                      currency_code: USD
                    provider_payment:
                      provider: xero
                      provider_label: Xero
                      document_type: invoice
                      provider_status: PAID
                      provider_status_label: Paid
                      provider_status_color: success
                      payment_state: paid
                      currency_code: USD
                      total: '100.0000'
                      amount_paid: '100.0000'
                      amount_due: '0.0000'
                      amount_credited: '0.0000'
                      sub_total: '90.0000'
                      tax_total: '10.0000'
                      due_date: '2026-01-31T00:00:00+00:00'
                      fully_paid_on: '2026-12-02T00:00:00+00:00'
                      document_date: '2026-12-01T00:00:00+00:00'
                      provider_url: https://go.xero.com/AccountsReceivable/View.aspx?InvoiceID=6b1e...INV
                      payments:
                      - date: '2026-12-02T00:00:00+00:00'
                        amount: '100.0000'
                        reference: CHK-1042
                        type: ACCRECPAYMENT
                        status: AUTHORISED
                        is_reconciled: true
                        bank_account: Business Bank Account
                        provider_payment_id: b1c2d3e4-5678-90ab-cdef-1234567890ab
                        provider_url: https://go.xero.com/Bank/ViewTransaction.aspx?bankTransactionID=b1c2d3e4-5678-90ab-cdef-1234567890ab
                        link_route: /integrations/xero/payments/42
                        link_type_label: Xero Payment
                        link_id: 42
                      metadata:
                      - label: Currency Rate
                        value: '1.000000'
                      - label: Sent To Contact
                        value: 'Yes'
                      data_availability: full
                      availability_message: null
                      last_synced_at: '2026-12-02T04:15:00+00:00'
                      unreflected_credit_notes: []
                    lines:
                    - id: 5210
                      direction: debit
                      amount: '249.9900'
                      quantity: null
                      tax_amount: '20.4500'
                      description: Accounts receivable
                      nominal_code:
                        id: 12
                        code: '1100'
                        name: Accounts Receivable
                      tax_rate: null
                      source_line: null
                      role: control
                      pushed_to_provider: false
                    - id: 5211
                      direction: credit
                      amount: '229.5400'
                      quantity: '3.0000'
                      tax_amount: null
                      description: Product sales
                      nominal_code:
                        id: 40
                        code: '4000'
                        name: Sales Revenue
                      tax_rate:
                        id: 2
                        name: Tax on Sales (8.875%)
                      source_line:
                        type: App\Models\SalesOrderLine
                        id: 30412
                      role: primary
                      pushed_to_provider: true
                    - id: 5212
                      direction: credit
                      amount: '20.4500'
                      quantity: null
                      tax_amount: null
                      description: Sales tax payable
                      nominal_code:
                        id: 45
                        code: '2200'
                        name: Sales Tax Payable
                      tax_rate:
                        id: 2
                        name: Tax on Sales (8.875%)
                      source_line: null
                      role: tax
                      pushed_to_provider: true
                    sync_links:
                    - id: 311
                      provider: qbo
                      connection:
                        id: 3
                        name: QuickBooks Online
                      remote_type: Invoice
                      remote_id: '4412'
                      remote_url: https://app.qbo.intuit.com/app/invoice?txnId=4412
                      link_state: linked_stale
                      remote_status: Open
                      last_remote_seen_at: '2026-06-08T03:12:00+00:00'
                    operations:
                    - id: 9907
                      state: needs_action
                      operation: update
                      direction: push
                      error_class: user_action_required
                      retry_disposition: needs_action
                      error_payload:
                        message: 'Duplicate Document Number Error : You must specify
                          a different number. This number has already been used.'
                        user_title: A document with this reference already exists
                          in QuickBooks
                        user_message: QuickBooks rejected this as a duplicate of a
                          document that already exists. Review whether it is the same
                          document before re-syncing.
                        provider_code: '6240'
                        retry_disposition: needs_action
                      attempts: 1
                      connection:
                        id: 3
                        name: QuickBooks Online
                      created_at: '2026-06-08T03:10:00+00:00'
                      started_at: '2026-06-08T03:10:05+00:00'
                      finished_at: '2026-06-08T03:10:06+00:00'
                      transitions:
                      - from: null
                        to: pending
                        reason: enqueued
                        created_at: '2026-06-08T03:10:00+00:00'
                      - from: pending
                        to: in_flight
                        reason: dispatched
                        created_at: '2026-06-08T03:10:05+00:00'
                      - from: in_flight
                        to: needs_action
                        reason: 'provider_validation: Account 4000 Sales Revenue is
                          inactive'
                        created_at: '2026-06-08T03:10:06+00:00'
                    reversal_chain:
                      reversal_of: null
                      reversed_by: null
                      replaced_by: null
                      replaces:
                        id: 1790
                        document_number: JE-1790
                        reference: SO-10293
                        status: reversed
                    provider_link: null
                    chain:
                    - id: 1839
                      document_number: VC-1839
                      reference: 0001668
                      reference_suffix: 0
                      status: reversed
                      role: original
                      is_current: false
                      is_viewed: true
                      reversal_of_id: null
                      replaced_by_id: 1842
                      effective_at: '2026-02-28T08:00:00+00:00'
                      provider_link:
                        remote_type: xero_credit_note
                        remote_id: 2643cbf7-ea33-460d-9d30-301fac99f609
                        remote_url: https://go.xero.com/AccountsPayable/ViewCreditNote.aspx?creditNoteID=2643cbf7-ea33-460d-9d30-301fac99f609
                        link_state: remote_gone
                        remote_status: VOIDED
                        badge: Voided
                    - id: 1841
                      document_number: VC-1841
                      reference: 0001668
                      reference_suffix: 0
                      status: posted
                      role: reversal
                      is_current: false
                      is_viewed: false
                      reversal_of_id: 1839
                      replaced_by_id: null
                      effective_at: '2026-02-28T08:00:00+00:00'
                      provider_link: null
                    - id: 1842
                      document_number: VC-1842
                      reference: 0001668/R1
                      reference_suffix: 1
                      status: draft
                      role: replacement
                      is_current: true
                      is_viewed: false
                      reversal_of_id: null
                      replaced_by_id: null
                      effective_at: '2026-02-28T08:00:00+00:00'
                      provider_link: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-ledger-entries-entry
  /api/ledger/entries/{entry}/lines:
    get:
      tags:
      - Ledger (Accounting v2)
      summary: Get Journal Entry Lines
      description: 'The entry''s GL-impact journal lines — a lightweight cousin of
        **Get Journal Entry** that returns only the `lines` array (no sync_links,
        operations or reversal_chain). Drives the entries table''s inline "Lines"
        row expansion.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Lines are ordered GL-impact-first: debits before credits, each ordered by
        nominal code.


        Each line includes:

        - `direction` — `debit` or `credit`

        - `amount` — the extended (line total) amount as a string

        - `quantity`, `tax_amount` — strings, or null

        - `nominal_code` — `{ id, code, name }` of the account the line posts to

        - `is_overridden` — true when a durable override remapped this line''s account

        - `nominal_code_original` — the account it WOULD have derived to (non-null
        only when overridden), drives the `<derived> → <override>` display

        - `tax_rate` — `{ id, name }` or null

        - `source_line` — `{ type, id }` of the originating document line, or null

        - `role` — economic role within a document-style entry: `primary` (product
        leg), `control` (A/R or A/P leg), `tax`, or `discount`, recovered from the
        mapped nominal code. The GL Impact table shows the invoiced quantity on `primary`
        legs only (v2 copies the quantity onto the control leg, so a role-blind column
        would double-count it); `null` on paths that don''t load lines

        - `pushed_to_provider` — `false` marks the control line (A/R on an Invoice/Credit
        Note, A/P on a Bill) that the connected provider auto-books itself, so SKU
        omits it from the push and the GL Impact table dims it; `true` = pushed; `null`
        when no accounting provider is connected


        **Authentication:** Requires Bearer token.


        Returns 404 when the entry does not exist (route is numeric-constrained).'
      parameters:
      - name: entry
        in: path
        schema:
          type: integer
        required: true
        description: Ledger journal entry ID (numeric). Route-model bound — returns
          404 if the entry does not exist.
        example: '1842'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        direction:
                          type: string
                        amount:
                          type: string
                        quantity:
                          type: string
                        tax_amount:
                          type: string
                        description:
                          type: string
                        nominal_code:
                          type: object
                          properties:
                            id:
                              type: integer
                            code:
                              type: string
                            name:
                              type: string
                        is_overridden:
                          type: boolean
                        nominal_code_original:
                          type: string
                          nullable: true
                        tax_rate:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        source_line:
                          type: object
                          properties:
                            type:
                              type: string
                            id:
                              type: integer
                        role:
                          type: string
                        pushed_to_provider:
                          type: boolean
                example:
                  data:
                  - id: 5501
                    direction: debit
                    amount: '1200.00'
                    quantity: '10'
                    tax_amount: '0.00'
                    description: Inventory received — Widget A
                    nominal_code:
                      id: 31
                      code: '500'
                      name: Cost of Goods Sold
                    is_overridden: false
                    nominal_code_original: null
                    tax_rate:
                      id: 4
                      name: No VAT
                    source_line:
                      type: App\Models\PurchaseInvoiceLine
                      id: 8842
                    role: primary
                    pushed_to_provider: true
                  - id: 5502
                    direction: credit
                    amount: '1200.00'
                    quantity: null
                    tax_amount: '0.00'
                    description: Accounts Payable — Acme Supplies
                    nominal_code:
                      id: 80
                      code: '800'
                      name: Accounts Payable
                    is_overridden: false
                    nominal_code_original: null
                    tax_rate: null
                    source_line: null
                    role: control
                    pushed_to_provider: false
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-ledger-entries-entry-lines
  /api/ledger/entries/{entry}/attachment-sync:
    get:
      tags:
      - Ledger (Accounting v2)
      summary: Get Journal Entry Attachment Sync
      description: 'The sync state of each source-document file attachment across
        every connection. When the entry''s source document (purchase invoice, vendor
        credit, or vendor deposit) has attachments, this returns one row per (attachment
        × connection) describing whether the file was uploaded to the matching Xero/QBO
        document.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Returns an empty `data` array when the source has no attachments, no attachment
        concept, or nothing has been attempted yet.


        Each row includes:

        - `source_attachment_id` — the SKU attachment row id

        - `file_name` — the source file''s display name

        - `connection_id`, `provider` — the accounting connection and its integration
        name (e.g. `Xero`, `QuickBooks Online`)

        - `remote_type`, `remote_id` — the provider document the file is attached
        to (e.g. `qbo_vendor_credit`)

        - `remote_attachment_id` — the Xero AttachmentID / QBO Attachable.Id (null
        while failed/pending)

        - `status` — `synced`, `failed`, or `pending`

        - `last_error` — failure reason (null on success)

        - `synced_at` — ISO-8601 UTC timestamp of the last successful upload (null
        otherwise)


        Authentication: requires a Bearer token.'
      parameters:
      - name: entry
        in: path
        schema:
          type: integer
        required: true
        description: Ledger journal entry ID (numeric). Route-model bound — returns
          404 if the entry does not exist.
        example: '1842'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        source_attachment_id:
                          type: integer
                        file_name:
                          type: string
                        connection_id:
                          type: integer
                        provider:
                          type: string
                        remote_type:
                          type: string
                        remote_id:
                          type: string
                        remote_attachment_id:
                          type: string
                        status:
                          type: string
                        last_error:
                          type: string
                          nullable: true
                        synced_at:
                          type: string
                example:
                  data:
                  - id: 5012
                    source_attachment_id: 8841
                    file_name: supplier-invoice.pdf
                    connection_id: 12
                    provider: Xero
                    remote_type: xero_bill
                    remote_id: b1f0e2c4-6fce-4330-bb3b-8306278c6fd8
                    remote_attachment_id: a77c1e90-2b1f-4d0a-9d1e-9a2b3c4d5e6f
                    status: synced
                    last_error: null
                    synced_at: '2026-07-02T14:12:05+00:00'
                  - id: 5013
                    source_attachment_id: 8842
                    file_name: delivery-note.pdf
                    connection_id: 12
                    provider: Xero
                    remote_type: xero_bill
                    remote_id: b1f0e2c4-6fce-4330-bb3b-8306278c6fd8
                    remote_attachment_id: null
                    status: failed
                    last_error: 'Skipped: file exceeds the provider attachment size
                      limit of 25MB.'
                    synced_at: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-ledger-entries-entry-attachment-sync
  /api/ledger/entries/{entry}/rebuild:
    post:
      tags:
      - Ledger (Accounting v2)
      summary: Rebuild Journal Entry
      description: 'Rebuild the entry''s SOURCE document INLINE (single-entry action):
        the user clicked Rebuild on the entry detail page and expects the regenerated
        entry to be current the instant the request returns, not after the async drain
        catches up. The rebuild writes the same `updated` outbox row a real source
        mutation rides, then processes JUST that row synchronously through the shared
        outbox processor (build → persistSet → batch-assign → sync-select) — so posted-immutability
        (reversal + replacement) holds exactly as on the async path.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Two cases fall back to the queue instead of running inline (the message says
        which):

        - **Batch-aggregate entries** (source = a LedgerBatch) ride the batch state
        machine (markDirty + a background job) — identical effect to POST /api/ledger/batches/{batch}/rebuild.

        - **Generation disabled** (the `ledger.generation_enabled` kill-switch is
        off): the `updated` row is parked for whenever the drain next runs.


        **Authentication:** Requires Bearer token.


        **Request body:** none.


        **Response:** 200 with a `message`. When the rebuild ran inline the message
        is "Entry rebuilt from its source document."; on the queued fallback it is
        "Rebuild queued — the entry will regenerate from its source document shortly."
        (App\Response normalizes every 2xx to 200.) Returns 404 when the entry does
        not exist.


        Permission: requires `accounting.sync` (granular permissions; admins bypass;
        unenforced when the tenant''s granular_permissions feature flag is off). Returns
        403 without it.'
      requestBody:
        content: {}
      parameters:
      - name: entry
        in: path
        schema:
          type: integer
        required: true
        description: Ledger journal entry ID (numeric). Route-model bound — returns
          404 if the entry does not exist.
        example: '1842'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 OK — rebuilt inline
                  value:
                    data: []
                    message: Entry rebuilt from its source document.
                example-1:
                  summary: 200 OK — rebuild queued
                  value:
                    data: []
                    message: Rebuild queued — the entry will regenerate from its source
                      document shortly.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-ledger-entries-entry-rebuild
  /api/ledger/entries/{entry}/refresh:
    post:
      tags:
      - Ledger (Accounting v2)
      summary: Refresh Journal Entry
      description: 'Refresh this entry''s amounts from its SOURCE document IN PLACE
        — the light counterpart to Rebuild. Where Rebuild corrects a posted entry
        by writing a reversal + a replacement, Refresh re-derives the entry''s lines
        and totals and writes them onto the SAME entry: its id, status and accounting-provider
        link are all kept, so a posted, already-synced entry whose local figure drifted
        is corrected WITHOUT creating a new entry and WITHOUT touching the linked
        Xero / QuickBooks document. After the rewrite the sync state is re-graded
        — a still-editable remote is offered an update, while a settled/locked or
        voided remote is left as-is (nothing is pushed).


        **Authentication:** Requires Bearer token.


        **Request body:** none.


        **Response:** 200 with `data.refresh` ({ refreshed, reason, period_locked
        }) and `data.entry` (the refreshed entry object). `refreshed` is false with
        a `reason` when there is nothing to do: `already_current` (the entry already
        matches its source), `batched` (the entry rolls into a batch aggregate — rebuild
        the batch instead), `generation_disabled`, or `source_no_longer_produces_entry`
        (the source stopped producing this entry — use Rebuild to reverse it). `period_locked`
        is reported (never enforced): true when the entry is dated in a locked accounting
        period, so the caller can warn that an in-place edit changes a closed period.
        `message` summarises the outcome.


        Permission: requires `accounting.sync` (granular permissions; admins bypass;
        unenforced when the tenant''s granular_permissions feature flag is off). Returns
        403 without it; 404 when the entry does not exist.'
      requestBody:
        content: {}
      parameters:
      - name: entry
        in: path
        schema:
          type: integer
        required: true
        description: Ledger journal entry ID (numeric). Route-model bound — returns
          404 if the entry does not exist.
        example: '1842'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 OK — refreshed in place
                  value:
                    data:
                      refresh:
                        refreshed: true
                        reason: null
                        period_locked: false
                      entry:
                        id: 1842
                        uuid: 9c2f1b7e-4a6d-4f0e-9b1a-2d8c5e7f3a10
                        type:
                          value: purchase_order_invoice
                          label: Purchase Order Invoice
                        status: posted
                        display_status:
                          key: locked
                          label: Synced, Locked
                          color: info
                          reason: null
                        can_sync_now: false
                        effective_at: '2026-06-05T14:30:00+00:00'
                        posted_at: '2026-06-05T14:35:12+00:00'
                        currency_code: USD
                        total_debit: '4631.0400'
                        total_credit: '4631.0400'
                        reference: BILL-10293
                        sync_links:
                        - id: 55
                          provider: xero
                          remote_type: xero_bill
                          remote_id: 54bccb09-ffa1-4309-8caf-4f78a09b493a
                          link_state: remote_locked
                          remote_status: PAID
                        operations: []
                    message: Refreshed from its source document — the provider link
                      was kept.
                example-1:
                  summary: 200 OK — nothing to refresh (already current)
                  value:
                    data:
                      refresh:
                        refreshed: false
                        reason: already_current
                        period_locked: false
                      entry:
                        id: 1842
                        status: posted
                        total_debit: '4631.0400'
                        total_credit: '4631.0400'
                        reference: BILL-10293
                    message: This entry already matches its source document — nothing
                      to refresh.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-ledger-entries-entry-refresh
  /api/ledger/entries/{entry}/sync:
    post:
      tags:
      - Ledger (Accounting v2)
      summary: Resync Entry to Provider
      description: 'Push this SINGLE entry to the connected accounting provider SYNCHRONOUSLY
        (InlineLedgerSyncRunner): the provider round-trip runs inline within the request,
        so the response already reflects the real Synced / Failed outcome — there
        is no interim "queued" state to poll. This powers the entry detail page''s
        "Resync Now" button and its live "talking to the provider" animation. The
        bulk equivalent — `POST /api/ledger/entries/bulk` with action `sync_now` —
        stays an async tracked job.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Authentication:** Requires Bearer token.


        **Request body:** none.


        **Locked documents:** when the provider document is paid/settled (locked),
        amounts and dates cannot be pushed. Resync instead pushes only the fields
        the provider still allows editing on a locked document (the reference/number)
        and reports `amended: true`. The entry keeps its "Synced, Locked" status;
        if the reference change covered all the local drift, the pending-update flag
        clears. To push amount or date changes, remove the payment or credit note
        on the provider document first, then Resync. **Fully-locked documents:** some
        provider document types (for example a credit note with a payment or allocation
        applied) are locked so hard that even the reference cannot be pushed. For
        those, Resync mints no operation and reports `locked_blocked: true`, and the
        entry carries a `locked_amend_blocked` flag; nothing changes on the provider
        until the payment or allocation is removed there.


        **Behaviour:** mints the entry''s manual push op (manual eligibility bypasses
        the soft per-type Sync toggle but NOT structural blockers — connection inactive,
        batch member / open batch, internal-only, or before the provider start date)
        and drives it to the provider in-process. A no-op (still reports `synced`
        when already linked-current) when the entry''s content hash matches the last
        sync, or `eligible: false` when nothing can be pushed.


        **First-push regeneration:** when the entry is imported pre-cutover history
        that has NEVER been synced (no link on any connection), it is first rebuilt
        with the current posting rules so the provider''s first copy reflects current
        logic rather than the migrated import. The rebuild may replace the entry with
        a successor — `data.sync.entry_id` is the entry the push actually ran against
        and `data.entry` is that (possibly new) entry.


        **Response:** 200 with `data.sync` ({ eligible, synced, failed, amended, locked_blocked,
        error, regenerated, entry_id }) and `data.entry` (the refreshed ledger entry
        object, which includes a `locked_amend_blocked` flag). `error` carries the
        provider rejection message when `failed` is true. `locked_blocked` is true
        when the provider document is fully locked and not even the reference could
        be pushed. `message` summarises the outcome.


        Permission: requires `accounting.sync` (granular permissions; admins bypass;
        unenforced when the tenant''s granular_permissions feature flag is off). Returns
        403 without it; 404 when the entry does not exist.'
      requestBody:
        content: {}
      parameters:
      - name: entry
        in: path
        schema:
          type: integer
        required: true
        description: Ledger journal entry ID (numeric). Route-model bound — returns
          404 if the entry does not exist.
        example: '8114'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 OK — pushed (synced)
                  value:
                    data:
                      sync:
                        eligible: true
                        synced: true
                        failed: false
                        amended: false
                        error: null
                        regenerated: false
                        entry_id: 8114
                      entry:
                        id: 8114
                        type:
                          value: bill
                          label: Bill
                        status: posted
                        display_status:
                          key: synced
                          label: Synced
                          color: success
                          reason: null
                        can_sync_now: true
                        locked_update_pending: false
                        locked_amend_blocked: false
                        counterparty_name: Amazon
                        currency_code: USD
                        total_debit: '842.6700'
                        total_credit: '842.6700'
                        document_number: BILL-8114
                        reference: 5cKTkaXNDpXqmNv0MzaOHAMppp6CsZOYXrgMbDv4UDg
                        sync_provider: Xero
                        sync_links:
                        - id: 5521
                          provider: Xero
                          remote_type: bill
                          remote_id: 57406763-6b49-4be8-98b5-16750c106f6e
                          link_state: linked_current
                          remote_status: AUTHORISED
                          last_remote_seen_at: '2026-06-30T01:41:05+00:00'
                        operations:
                        - id: 90211
                          state: succeeded
                          operation: create
                          direction: push
                          error_class: null
                          error_payload: null
                          attempts: 1
                          finished_at: '2026-06-30T01:41:05+00:00'
                    message: Pushed to the provider — this entry is up to date.
                example-1:
                  summary: 200 OK — locked document, editable fields pushed (amended)
                  value:
                    data:
                      sync:
                        eligible: true
                        synced: false
                        failed: false
                        amended: true
                        error: null
                        regenerated: false
                        entry_id: 8114
                      entry:
                        id: 8114
                        type:
                          value: bill
                          label: Bill
                        status: posted
                        display_status:
                          key: locked
                          label: Synced, Locked
                          color: warning
                          reason: null
                        can_sync_now: true
                        locked_update_pending: false
                        locked_amend_blocked: false
                        counterparty_name: Amazon
                        currency_code: USD
                        total_debit: '842.6700'
                        total_credit: '842.6700'
                        document_number: BILL-8114
                        reference: 5cKTkaXNDpXqmNv0MzaOHAMppp6CsZOYXrgMbDv4UDg
                        sync_provider: Xero
                        sync_links:
                        - id: 5521
                          provider: Xero
                          remote_type: bill
                          remote_id: 57406763-6b49-4be8-98b5-16750c106f6e
                          link_state: linked_current
                          remote_status: AUTHORISED
                          last_remote_seen_at: '2026-06-30T01:41:05+00:00'
                        operations:
                        - id: 90211
                          state: succeeded
                          operation: create
                          direction: push
                          error_class: null
                          error_payload: null
                          attempts: 1
                          finished_at: '2026-06-30T01:41:05+00:00'
                    message: Pushed to the provider — this entry is up to date.
                example-2:
                  summary: 200 OK — fully locked, reference not pushable (locked_blocked)
                  value:
                    data:
                      sync:
                        eligible: true
                        synced: false
                        failed: false
                        amended: false
                        locked_blocked: true
                        error: null
                        regenerated: false
                        entry_id: 11026
                      entry:
                        id: 11026
                        type:
                          value: vendor_credit
                          label: Vendor Credit
                        status: posted
                        display_status:
                          key: locked
                          label: Synced, Locked
                          color: warning
                          reason: null
                        can_sync_now: true
                        locked_update_pending: false
                        locked_amend_blocked: true
                        counterparty_name: Amazon
                        currency_code: USD
                        total_debit: '600.0000'
                        total_credit: '600.0000'
                        document_number: VC-9512
                        reference: VC-9512-updated
                        sync_provider: Xero
                        sync_links:
                        - id: 6033
                          provider: Xero
                          remote_type: credit_note
                          remote_id: 9f2b7c41-2d5a-4a8e-b1c0-77a2e6d51a90
                          link_state: remote_locked
                          remote_status: PAID
                          last_remote_seen_at: '2026-07-13T02:15:44+00:00'
                        operations:
                        - id: 90455
                          state: succeeded
                          operation: create
                          direction: push
                          error_class: null
                          error_payload: null
                          attempts: 1
                          finished_at: '2026-07-01T09:12:30+00:00'
                    message: This document is locked in the provider while a payment
                      is applied — its reference can't be pushed until the payment
                      is removed on the provider.
                example-3:
                  summary: 200 OK — provider rejected (failed)
                  value:
                    data:
                      sync:
                        eligible: true
                        synced: false
                        failed: true
                        amended: false
                        error: Account code 200 is not a valid code for this document.
                        regenerated: false
                        entry_id: 8114
                      entry:
                        id: 8114
                        type:
                          value: bill
                          label: Bill
                        status: posted
                        display_status:
                          key: failed
                          label: Failed
                          color: error
                          reason: Account code 200 is not a valid code for this document.
                        can_sync_now: true
                        locked_update_pending: false
                        locked_amend_blocked: false
                        counterparty_name: Amazon
                        currency_code: USD
                        document_number: BILL-8114
                        reference: 5cKTkaXNDpXqmNv0MzaOHAMppp6CsZOYXrgMbDv4UDg
                        sync_provider: Xero
                    message: The provider rejected this entry — see the sync error
                      for details.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-ledger-entries-entry-sync
  /api/ledger/entries/{entry}/settlement-preview:
    get:
      tags:
      - Ledger (Accounting v2)
      summary: Preview Bill Settlement With Vendor Credits
      description: 'Preview the plan to settle a bill (a purchase-invoice entry) using
        the vendor credits already allocated against it — the read side of the "sync
        & mark paid" flow. Reports whether the entry is a settleable bill, whether
        the bill itself is synced to the accounting provider, and the state of each
        applied vendor credit: `missing_transaction` (its accounting transaction has
        not been generated yet), `unsynced` (generated but not pushed to the provider),
        or `synced` (its credit note is pushed and its allocation applied). Use it
        to show exactly what will happen before committing.


        **Authentication:** Requires Bearer token.


        **Request body:** none.


        **Response:** 200 with `data.settlement`: `is_settleable_bill`, `bill_synced`,
        `already_settled`, `needs_action`, `credit_count`, `allocated_total`, `outstanding_balance`,
        `currency_code`, and `credits[]` (each carries `vendor_credit_id`, `allocation_id`,
        `vendor_credit_number`, `vendor_credit_route`, `allocation_amount`, `state`,
        `ledger_entry_id`, `ledger_entry_route`). When the entry is not a bill with
        allocated vendor credits, `is_settleable_bill` is false and `credits` is empty.
        Returns 404 when the entry does not exist.'
      parameters:
      - name: entry
        in: path
        schema:
          type: integer
        required: true
        description: Ledger journal entry ID (numeric) — must be a bill (purchase
          invoice) entry. Route-model bound — returns 404 if the entry does not exist.
        example: '9609'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 OK — settleable, action needed
                  value:
                    data:
                      settlement:
                        is_settleable_bill: true
                        bill_synced: true
                        already_settled: false
                        needs_action: true
                        credit_count: 4
                        allocated_total: '2084.52'
                        outstanding_balance: '2084.52'
                        currency_code: USD
                        credits:
                        - vendor_credit_id: 312
                          allocation_id: 907
                          vendor_credit_number: VC-000312
                          vendor_credit_route: /v2/vendor-credits/312
                          allocation_amount: '500.00'
                          state: unsynced
                          ledger_entry_id: 9720
                          ledger_entry_route: /ledger/entries/9720
                        - vendor_credit_id: 313
                          allocation_id: 908
                          vendor_credit_number: VC-000313
                          vendor_credit_route: /v2/vendor-credits/313
                          allocation_amount: '600.00'
                          state: missing_transaction
                          ledger_entry_id: null
                          ledger_entry_route: null
                        - vendor_credit_id: 314
                          allocation_id: 909
                          vendor_credit_number: VC-000314
                          vendor_credit_route: /v2/vendor-credits/314
                          allocation_amount: '484.52'
                          state: unsynced
                          ledger_entry_id: 9721
                          ledger_entry_route: /ledger/entries/9721
                        - vendor_credit_id: 315
                          allocation_id: 910
                          vendor_credit_number: VC-000315
                          vendor_credit_route: /v2/vendor-credits/315
                          allocation_amount: '500.00'
                          state: synced
                          ledger_entry_id: 9722
                          ledger_entry_route: /ledger/entries/9722
                    message: This bill has 4 vendor credits allocated — 3 still need
                      to be applied on the provider to mark it paid.
                example-1:
                  summary: 200 OK — not a settleable bill
                  value:
                    data:
                      settlement:
                        is_settleable_bill: false
                        bill_synced: false
                        already_settled: false
                        needs_action: false
                        credit_count: 0
                        allocated_total: '0.00'
                        outstanding_balance: '0.00'
                        currency_code: null
                        credits: []
                    message: This entry is not a bill with vendor credits allocated.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-ledger-entries-entry-settlement-preview
  /api/ledger/entries/{entry}/sync-and-settle:
    post:
      tags:
      - Ledger (Accounting v2)
      summary: Settle Bill With Vendor Credits
      description: 'Settle a bill (a purchase-invoice entry) using the vendor credits
        allocated against it so the connected accounting provider marks the bill PAID
        — the missing half of two-way sync when the allocations exist here but were
        never pushed. Dispatches a tracked background job that (1) syncs the bill
        so its remote document exists, (2) for each applied vendor credit generates
        its accounting transactions if missing, syncs its credit note, then pushes
        the allocation (Xero credit-note allocation / QuickBooks zero-dollar bill
        payment), and (3) re-reads the bill so its link re-grades to Synced, Locked
        (paid). Idempotent — re-running skips work already done, so a partial failure
        is safe to retry.


        **Authentication:** Requires Bearer token + `accounting.sync` permission (403
        without it).


        **Request body:** none.


        **Response:** 200 with `data.tracked_job_log_id` (poll for progress) and `data.settlement`
        (the pre-run snapshot, same shape as Preview Bill Settlement). When the bill
        is already settled by its credits, returns 200 with just `data.settlement`
        and no job. Returns 422 when the entry is not a bill with vendor credits allocated.
        Returns 404 when the entry does not exist.'
      requestBody:
        content: {}
      parameters:
      - name: entry
        in: path
        schema:
          type: integer
        required: true
        description: Ledger journal entry ID (numeric) — must be a bill (purchase
          invoice) entry. Route-model bound — returns 404 if the entry does not exist.
        example: '9609'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 OK — settlement started
                  value:
                    data:
                      tracked_job_log_id: 44821
                      settlement:
                        is_settleable_bill: true
                        bill_synced: true
                        already_settled: false
                        needs_action: true
                        credit_count: 4
                        allocated_total: '2084.52'
                        outstanding_balance: '2084.52'
                        currency_code: USD
                        credits:
                        - vendor_credit_id: 312
                          allocation_id: 907
                          vendor_credit_number: VC-000312
                          vendor_credit_route: /v2/vendor-credits/312
                          allocation_amount: '500.00'
                          state: unsynced
                          ledger_entry_id: 9720
                          ledger_entry_route: /ledger/entries/9720
                        - vendor_credit_id: 313
                          allocation_id: 908
                          vendor_credit_number: VC-000313
                          vendor_credit_route: /v2/vendor-credits/313
                          allocation_amount: '600.00'
                          state: missing_transaction
                          ledger_entry_id: null
                          ledger_entry_route: null
                        - vendor_credit_id: 314
                          allocation_id: 909
                          vendor_credit_number: VC-000314
                          vendor_credit_route: /v2/vendor-credits/314
                          allocation_amount: '484.52'
                          state: unsynced
                          ledger_entry_id: 9721
                          ledger_entry_route: /ledger/entries/9721
                        - vendor_credit_id: 315
                          allocation_id: 910
                          vendor_credit_number: VC-000315
                          vendor_credit_route: /v2/vendor-credits/315
                          allocation_amount: '500.00'
                          state: synced
                          ledger_entry_id: 9722
                          ledger_entry_route: /ledger/entries/9722
                    message: Settling the bill with its vendor credits — track progress
                      in the job tracker.
                example-1:
                  summary: 200 OK — already settled
                  value:
                    data:
                      settlement:
                        is_settleable_bill: true
                        bill_synced: true
                        already_settled: true
                        needs_action: false
                        credit_count: 4
                        allocated_total: '2084.52'
                        outstanding_balance: '0.00'
                        currency_code: USD
                        credits:
                        - vendor_credit_id: 312
                          allocation_id: 907
                          vendor_credit_number: VC-000312
                          vendor_credit_route: /v2/vendor-credits/312
                          allocation_amount: '500.00'
                          state: synced
                          ledger_entry_id: 9720
                          ledger_entry_route: /ledger/entries/9720
                    message: This bill is already settled by its vendor credits —
                      nothing to do.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: This entry is not a bill with vendor credits allocated,
                    so there is nothing to settle.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-ledger-entries-entry-sync-and-settle
  /api/ledger/entries/{entry}/clear-errors:
    post:
      tags:
      - Ledger (Accounting v2)
      summary: Clear Sync Errors
      description: 'Dismiss THIS single entry''s parked sync errors (needs_action
        / failed_retryable) SYNCHRONOUSLY by superseding its open sync operations
        across every connection, then return the refreshed entry so the detail page
        drops the error banner without a page refresh. This powers the entry detail
        page''s "Clear errors" button.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        It clears the error WITHOUT auto-retrying — the user runs Resync Now afterwards
        to re-attempt the push. The bulk equivalent — `POST /api/ledger/entries/bulk`
        with action `clear_errors` — stays an async tracked job for multi-entry selections.


        **Authentication:** Requires Bearer token.


        **Request body:** none.


        **Behaviour:** transitions the entry''s open operations (except InFlight)
        to `Superseded` per connection, then recomputes and refreshes the entry''s
        display status. A no-op (`cleared: false`) when the entry has no open sync
        errors.


        **Response:** 200 with `data.cleared` (bool — whether any open ops were superseded)
        and `data.entry` (the refreshed ledger entry object, whose `display_status`
        no longer reports needs_attention). `message` summarises the outcome.


        Permission: requires `accounting.sync` (granular permissions; admins bypass;
        unenforced when the tenant''s granular_permissions feature flag is off). Returns
        403 without it; 404 when the entry does not exist.'
      requestBody:
        content: {}
      parameters:
      - name: entry
        in: path
        schema:
          type: integer
        required: true
        description: Ledger journal entry ID (numeric). Route-model bound — returns
          404 if the entry does not exist.
        example: '8114'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 OK — errors cleared
                  value:
                    data:
                      cleared: true
                      entry:
                        id: 8114
                        type:
                          value: bill
                          label: Bill
                        status: posted
                        display_status:
                          key: not_synced
                          label: Not Synced
                          color: grey
                          reason: null
                        can_sync_now: true
                        locked_update_pending: false
                        locked_amend_blocked: false
                        counterparty_name: Amazon
                        currency_code: USD
                        total_debit: '842.6700'
                        total_credit: '842.6700'
                        document_number: BILL-8114
                        reference: 5cKTkaXNDpXqmNv0MzaOHAMppp6CsZOYXrgMbDv4UDg
                        sync_provider: Xero
                        operations:
                        - id: 90244
                          state: superseded
                          operation: create
                          direction: push
                          error_class: null
                          error_payload: null
                          attempts: 2
                          finished_at: '2026-06-30T01:41:05+00:00'
                    message: Sync errors cleared — run Sync now to re-attempt.
                example-1:
                  summary: 200 OK — nothing to clear (no-op)
                  value:
                    data:
                      cleared: false
                      entry:
                        id: 8114
                        type:
                          value: bill
                          label: Bill
                        status: posted
                        display_status:
                          key: synced
                          label: Synced
                          color: success
                          reason: null
                        can_sync_now: true
                        document_number: BILL-8114
                        sync_provider: Xero
                    message: No sync errors to clear on this entry.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-ledger-entries-entry-clear-errors
  /api/ledger/entries/{entry}/recreate:
    post:
      tags:
      - Ledger (Accounting v2)
      summary: Recreate Accounting Transaction
      description: '"Recreate document" for an entry whose remote document was VOIDED
        or DELETED in the accounting provider (display_status `voided` — "Synced,
        Voided" — or `removed_in_provider` — "Synced, Deleted"). Once a provider document
        is voided/deleted there is nothing left to update on it, so this reverse+replaces
        the entry into a fresh UNLINKED draft replacement and mints it from the same
        source, even though the source itself never changed.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        The dead provider link is RETAINED on the reversed original as the historical
        record; the replacement starts with NO provider link and is chained via replaced_by_id,
        so the detail view shows a "Replaces …" link. This action does NOT push and
        does NOT touch the dead document — the user syncs the fresh draft to push
        a brand-new document on demand.


        **Authentication:** Requires Bearer token.


        **Request body:** none.


        **Response:** 200 with `data.recreate` ({ recreated, status, reason, replacement_id
        }) and `data.entry` (the now-reversed original). `replacement_id` is the id
        of the fresh unlinked draft. `recreated` is false with reason `not_voided`
        (nothing voided to replace), `generation_disabled`, or `source_not_accounting_ready`
        (the source no longer produces an entry). Returns 404 when the entry does
        not exist.


        Permission: requires `accounting.sync`.'
      requestBody:
        content: {}
      parameters:
      - name: entry
        in: path
        schema:
          type: integer
        required: true
        description: Ledger journal entry ID (numeric). Route-model bound — returns
          404 if the entry does not exist.
        example: '1842'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 OK — reversed + fresh unlinked replacement
                  value:
                    data:
                      recreate:
                        recreated: true
                        status: voided
                        reason: null
                        replacement_id: 1843
                      entry:
                        id: 1842
                        uuid: 9c2f1b7e-4a6d-4f0e-9b1a-2d8c5e7f3a10
                        type:
                          value: vendor_credit
                          label: Vendor Credit
                        status: reversed
                        display_status:
                          key: voided
                          label: Synced, Voided
                          color: warning
                          reason: null
                        can_sync_now: false
                        locked_update_pending: false
                        locked_amend_blocked: false
                        effective_at: '2026-02-28T08:00:00+00:00'
                        posted_at: '2026-02-28T08:05:00+00:00'
                        currency_code: USD
                        total_debit: '600.0000'
                        total_credit: '600.0000'
                        document_number: VC-11036
                        reference: 0001668/R1
                        replaced_by_id: 1843
                        sync_links:
                        - id: 819
                          provider: xero
                          connection:
                            id: 30
                            name: Xero
                          remote_type: xero_credit_note
                          remote_id: 2643cbf7-ea33-460d-9d30-301fac99f609
                          remote_url: https://go.xero.com/AccountsPayable/ViewCreditNote.aspx?creditNoteID=2643cbf7-ea33-460d-9d30-301fac99f609
                          link_state: remote_gone
                          remote_status: VOIDED
                          last_remote_seen_at: '2026-07-13T22:40:00+00:00'
                        operations: []
                    message: Created a fresh draft that replaces this entry — the
                      voided document stays on the original for the record. Sync the
                      new draft when you are ready to push a brand-new document.
                example-1:
                  summary: 200 OK — not recreated (source no longer produces an entry)
                  value:
                    data:
                      recreate:
                        recreated: false
                        status: voided
                        reason: source_not_accounting_ready
                        replacement_id: null
                      entry:
                        id: 1842
                        uuid: 9c2f1b7e-4a6d-4f0e-9b1a-2d8c5e7f3a10
                        type:
                          value: vendor_credit
                          label: Vendor Credit
                        status: posted
                        display_status:
                          key: voided
                          label: Synced, Voided
                          color: warning
                          reason: null
                        can_sync_now: false
                        locked_update_pending: false
                        locked_amend_blocked: false
                        effective_at: '2026-02-28T08:00:00+00:00'
                        posted_at: '2026-02-28T08:05:00+00:00'
                        currency_code: USD
                        total_debit: '600.0000'
                        total_credit: '600.0000'
                        document_number: VC-11036
                        reference: 0001668/R1
                        replaced_by_id: null
                        sync_links: []
                        operations: []
                    message: No replacement was created — this entry's source no longer
                      produces an accounting entry.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-ledger-entries-entry-recreate
  /api/ledger/entries/{entry}/relink-candidates:
    get:
      tags:
      - Ledger (Accounting v2)
      summary: List Relink Candidates
      description: 'Provider documents this voided or deleted entry could be linked
        to INSTEAD of recreating one — the confidence-ranked "link to an existing
        document" picker. Use this when the accounting document was voided in the
        provider and a replacement already exists there (e.g. a bill was voided and
        re-raised): rather than minting a duplicate, adopt the document that is already
        in the provider.


        Reads the provider-document cache for the connection of the entry''s voided
        link and returns the unlinked documents of the same kind, ranked best-first.
        Each candidate carries per-signal match flags — `amount_match`, `date_match`,
        `reference_match`, and `confident` (amount AND date within tolerance) — so
        the top result is usually the correct replacement. Documents already linked
        to another entry, or themselves voided/deleted, are excluded. Documents dismissed
        on the reconcile screen are still offered — flagged `dismissed: true` and
        ranked below equally-confident undismissed candidates; linking one clears
        its dismissal. Returns an empty list when the entry has no voided/deleted
        link to recover.


        **Authentication:** Requires Bearer token.


        **Query parameters:** `search` (optional) — free-text narrowing.


        **Response:** 200 with `data` as an array of candidate documents ordered most-confident
        first.'
      parameters:
      - name: entry
        in: path
        schema:
          type: integer
        required: true
        description: Ledger journal entry ID (numeric). Route-model bound — returns
          404 if the entry does not exist.
        example: '1842'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        connection_id:
                          type: integer
                        remote_type:
                          type: string
                        remote_id:
                          type: string
                        reference:
                          type: string
                        total:
                          type: string
                        currency:
                          type: string
                        document_date:
                          type: string
                        status:
                          type: string
                        amount_match:
                          type: boolean
                        date_match:
                          type: boolean
                        reference_match:
                          type: boolean
                        confident:
                          type: boolean
                        dismissed:
                          type: boolean
                example:
                  data:
                  - connection_id: 30
                    remote_type: xero_bill
                    remote_id: 54f0b7b3-9537-447a-bda2-897f7da26e9f
                    reference: 'PO-0327: INVCBUSA-2000001.1'
                    total: '49063.4000'
                    currency: USD
                    document_date: '2025-09-22'
                    status: AUTHORISED
                    amount_match: true
                    date_match: true
                    reference_match: true
                    confident: true
                    dismissed: false
                  - connection_id: 30
                    remote_type: xero_bill
                    remote_id: 11c2a7d0-882e-4a19-9f6b-73c0d9a1e2ff
                    reference: PO-0299
                    total: '1204.0000'
                    currency: USD
                    document_date: '2025-09-03'
                    status: AUTHORISED
                    amount_match: false
                    date_match: false
                    reference_match: false
                    confident: false
                    dismissed: true
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-ledger-entries-entry-relink-candidates
  /api/ledger/entries/{entry}/link-candidates:
    get:
      tags:
      - Ledger (Accounting v2)
      summary: List Document Link Candidates
      description: 'Provider documents an unmatched ledger entry could be linked to
        for the first time — the confidence-ranked picker for pointing a never-linked
        SKU entry at the document it already corresponds to in the provider (e.g.
        a bill that was imported into the provider some other way), instead of syncing
        a duplicate. This is the sibling of List Relink Candidates, which recovers
        a voided/deleted link; this one is for an entry that has never been linked.


        Reads the provider-document cache for the tenant''s accounting connection
        and returns the unlinked documents ranked best-first. Each candidate carries
        per-signal match flags — `amount_match`, `date_match`, `reference_match`,
        and `confident` (amount AND date within tolerance). Documents already linked
        to another entry are excluded. Documents dismissed on the reconcile screen
        are still offered — flagged `dismissed: true` and ranked below equally-confident
        undismissed candidates; linking one clears its dismissal. Returns an empty
        list when the entry is already linked. Link the chosen document with POST
        /api/ledger/reconciliation/link.


        **Authentication:** Requires Bearer token.


        **Query parameters:** `search` (optional) — free-text narrowing.


        **Response:** 200 with `data` as an array of candidate documents ordered most-confident
        first.'
      parameters:
      - name: entry
        in: path
        schema:
          type: integer
        required: true
        description: Ledger journal entry ID (numeric). Route-model bound — returns
          404 if the entry does not exist.
        example: '10927'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        connection_id:
                          type: integer
                        remote_type:
                          type: string
                        remote_id:
                          type: string
                        reference:
                          type: string
                        total:
                          type: string
                        currency:
                          type: string
                        document_date:
                          type: string
                        status:
                          type: string
                        amount_match:
                          type: boolean
                        date_match:
                          type: boolean
                        reference_match:
                          type: boolean
                        confident:
                          type: boolean
                        dismissed:
                          type: boolean
                example:
                  data:
                  - connection_id: 30
                    remote_type: xero_bill
                    remote_id: 85414bb6-6f88-4c0f-8c53-53e7c1f7128c
                    reference: 'FBA181D492B4: 55641'
                    total: '3950.0000'
                    currency: USD
                    document_date: '2024-05-23'
                    status: PAID
                    amount_match: true
                    date_match: true
                    reference_match: true
                    confident: true
                    dismissed: false
                  - connection_id: 30
                    remote_type: xero_bill
                    remote_id: 11c2a7d0-882e-4a19-9f6b-73c0d9a1e2ff
                    reference: PO-0299
                    total: '1204.0000'
                    currency: USD
                    document_date: '2025-09-03'
                    status: AUTHORISED
                    amount_match: false
                    date_match: false
                    reference_match: false
                    confident: false
                    dismissed: true
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-ledger-entries-entry-link-candidates
  /api/ledger/entries/{entry}/relink:
    post:
      tags:
      - Ledger (Accounting v2)
      summary: Link Entry to Existing Document
      description: 'Re-link a voided or deleted entry to an EXISTING provider document
        — the replacement already re-created in the accounting provider — instead
        of minting a fresh one. Repoints the entry''s voided link onto the chosen
        document in place and records it so the NEXT sync pushes an update to that
        existing document, never a duplicate create.


        Use the candidate returned by `List Relink Candidates` to supply `remote_type`
        and `remote_id`. The action is guarded: the entry must still be voided/deleted,
        it must have a voided link on the given connection, and the target document
        must not already be linked to another entry.


        Linking a document also clears any reconcile-screen dismissal recorded against
        it.


        **Authentication:** Requires Bearer token.


        **Request body:**

        - `connection_id` (integer, required) — the accounting connection the document
        belongs to.

        - `remote_type` (string, required) — the document kind, e.g. `xero_bill`,
        `xero_invoice`, `qbo_bill`.

        - `remote_id` (string, required) — the provider document identifier to adopt.

        - `remote_status` (string, optional) — the document''s current provider status
        (e.g. `AUTHORISED`), recorded on the link.


        **Response:** 200 with `data.relink` ({ relinked, status, reason }) and `data.entry`
        (the refreshed entry). When `relinked` is false, `reason` is one of `not_voided`,
        `no_parked_link`, or `already_linked_elsewhere`. Returns 404 when the entry
        does not exist, 422 when the body is invalid.


        Requires the `accounting.sync` permission.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                connection_id:
                  type: integer
                remote_type:
                  type: string
                remote_id:
                  type: string
                remote_status:
                  type: string
              example:
                connection_id: 30
                remote_type: xero_bill
                remote_id: 54f0b7b3-9537-447a-bda2-897f7da26e9f
                remote_status: AUTHORISED
      parameters:
      - name: entry
        in: path
        schema:
          type: integer
        required: true
        description: Ledger journal entry ID (numeric). Route-model bound — returns
          404 if the entry does not exist.
        example: '1842'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 OK — linked
                  value:
                    data:
                      relink:
                        relinked: true
                        status: update_pending
                        reason: null
                      entry:
                        id: 1842
                        uuid: 9c2f1b7e-4a6d-4f0e-9b1a-2d8c5e7f3a10
                        type:
                          value: purchase_order_invoice
                          label: Purchase Order Invoice
                        status: posted
                        display_status:
                          key: update_pending
                          label: Synced, Pending Update
                          color: warning
                          reason: null
                        can_sync_now: true
                        currency_code: USD
                        total_debit: '49063.4000'
                        total_credit: '49063.4000'
                        document_number: BILL-1842
                        reference: 'PO-0327: INVCBUSA-2000001'
                        sync_links:
                        - remote_type: xero_bill
                          remote_id: 54f0b7b3-9537-447a-bda2-897f7da26e9f
                          link_state: linked_stale
                          remote_status: AUTHORISED
                        operations: []
                    message: Linked to the existing provider document — it will update
                      on the next sync.
                example-1:
                  summary: 200 OK — already linked to another entry
                  value:
                    data:
                      relink:
                        relinked: false
                        status: voided
                        reason: already_linked_elsewhere
                      entry:
                        id: 1842
                        display_status:
                          key: voided
                          label: Synced, Voided
                          color: warning
                          reason: null
                    message: That provider document is already linked to another entry.
                example-2:
                  summary: 200 OK — settled (Synced, Locked)
                  value:
                    data:
                      relink:
                        relinked: true
                        status: locked
                        reason: null
                      entry:
                        id: 1842
                        display_status:
                          key: locked
                          label: Synced, Locked
                          color: grey
                          reason: null
                        sync_links:
                        - remote_type: xero_bill
                          remote_id: 54f0b7b3-9537-447a-bda2-897f7da26e9f
                          link_state: remote_locked
                          remote_status: PAID
                    message: Linked to the existing provider document — it is settled
                      there, so the entry is marked Synced, Locked.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-ledger-entries-entry-relink
  /api/ledger/entries/{entry}/fetch-remote:
    post:
      tags:
      - Ledger (Accounting v2)
      summary: Fetch Latest From Provider
      description: 'The inbound mirror of "Sync Now" (— two-way sync, on demand):
        instead of PUSHING local changes out, it re-reads this entry''s remote document(s)
        FROM the accounting provider (Xero / QuickBooks) and re-grades the sync link
        RIGHT NOW. For each supported, still-linked connection it fetches the current
        remote truth via the same InboundChangeProcessor funnel the webhook + nightly
        sweep use — picking up drift (→ linked_conflict), a void/delete (→ remote_gone),
        a settled/paid lock (→ remote_locked), or a previously settled lock that has
        re-opened for edits — the paying payment / credit note was reversed at the
        provider, e.g. Xero PAID → AUTHORISED — which un-parks the link (→ linked_stale)
        so it is ready to resync — and refreshes `last_remote_seen_at`. A 404 at the
        provider degrades to a synthetic-deleted snapshot so the link still parks
        remote_gone rather than silently staying Synced.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Runs **synchronously** (the response reflects the re-read); the bulk equivalent
        is the `fetch_remote` action on POST /api/ledger/entries/bulk, which runs
        the same per-entry work as a tracked job.


        **Deferral:** if a push for this entry is in flight, the funnel writes NOTHING
        (touching the link would erase the drift signals reconciliation needs) and
        the response carries `data.fetch.deferred: true` with a "try again once the
        in-flight sync settles" message — still HTTP 200.


        **Authentication:** Requires Bearer token + `accounting.sync` permission (403
        without it).


        **Request body:** none.


        **Response:** 200 with `data.fetch` ({ checked, not_linked, deferred, primary,
        outcomes }) and `data.entry` (the refreshed ledger entry object so the new
        link state renders without a second round-trip). `data.fetch.primary` is the
        most-notable settled outcome across the re-read links by severity (`remote_gone`
        > `remote_locked` > `conflict` > `remote_reopened` > `current`), or null when
        nothing was re-read. `message` explains the outcome. Returns **502 Bad Gateway**
        when the provider read itself fails (e.g. expired auth / network) — no link
        state is changed. Returns 404 when the entry does not exist.


        When the provider has settled the bill with a credit note that SKU has not
        mirrored as a vendor-credit allocation, the response reports `data.fetch.unreflected_credit
        = true` and lists the affected notes in `data.fetch.unreflected_credit_notes`
        (each with `credit_note_number`, `applied_amount` and `shortfall`), and `message`
        explains that a matching vendor credit must be created or allocated to reconcile
        the bill.'
      requestBody:
        content: {}
      parameters:
      - name: entry
        in: path
        schema:
          type: integer
        required: true
        description: Ledger journal entry ID (numeric). Route-model bound — returns
          404 if the entry does not exist.
        example: '1842'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 OK — refreshed, up to date
                  value:
                    data:
                      fetch:
                        checked: 1
                        not_linked: false
                        deferred: false
                        primary: current
                        outcomes:
                          current: 1
                        unreflected_credit: false
                        unreflected_credit_notes: []
                      entry:
                        id: 1842
                        type:
                          value: bill
                          label: Bill
                        status: posted
                        display_status:
                          key: synced
                          label: Synced
                          reason: null
                        document_number: BILL-1842
                        reference: 5cKTkaXNDpXqmNv0MzaOHAMppp6CsZOYXrgMbDv4UDg
                        currency_code: USD
                        total_debit: '1305.86'
                        total_credit: '1305.86'
                        document_total: '842.67'
                        sync_provider: Xero
                        sync_links:
                        - connection_id: 7
                          remote_type: xero_bill
                          remote_id: 57406763-6b49-4be8-98b5-16750c106f6e
                          link_state: linked_current
                          last_remote_seen_at: '2026-06-30T01:41:05Z'
                    message: Refreshed from the provider — the entry is up to date.
                example-1:
                  summary: 200 OK — remote document deleted
                  value:
                    data:
                      fetch:
                        checked: 1
                        not_linked: false
                        deferred: false
                        primary: remote_gone
                        outcomes:
                          remote_gone: 1
                        unreflected_credit: false
                        unreflected_credit_notes: []
                      entry:
                        id: 1842
                        display_status:
                          key: removed_in_provider
                          label: Synced, Deleted
                          reason: null
                        sync_links:
                        - connection_id: 7
                          remote_type: xero_bill
                          remote_id: 57406763-6b49-4be8-98b5-16750c106f6e
                          link_state: remote_gone
                    message: The provider document was voided or deleted — the entry
                      is now marked accordingly.
                example-2:
                  summary: 200 OK — remote lock re-opened
                  value:
                    data:
                      fetch:
                        checked: 1
                        not_linked: false
                        deferred: false
                        primary: remote_reopened
                        outcomes:
                          remote_reopened: 1
                        unreflected_credit: false
                        unreflected_credit_notes: []
                      entry:
                        id: 1842
                        display_status:
                          key: update_pending
                          label: Synced, Pending Update
                          reason: null
                        sync_links:
                        - connection_id: 7
                          remote_type: xero_bill
                          remote_id: 57406763-6b49-4be8-98b5-16750c106f6e
                          link_state: linked_stale
                          remote_status: AUTHORISED
                    message: The provider document was re-opened for edits — the lock
                      has been released and the entry is ready to resync.
                example-3:
                  summary: 200 OK — credit note not reflected in SKU
                  value:
                    data:
                      fetch:
                        checked: 1
                        not_linked: false
                        deferred: false
                        primary: remote_locked
                        outcomes:
                          remote_locked: 1
                        unreflected_credit: true
                        unreflected_credit_notes:
                        - credit_note_id: 384727d6-0277-4f1a-a088-f0cb16d47dff
                          credit_note_number: '46135'
                          applied_amount: '170.9800'
                          reflected_amount: '0.0000'
                          shortfall: '170.9800'
                      entry:
                        id: 1842
                        type:
                          value: bill
                          label: Bill
                        status: posted
                        display_status:
                          key: synced
                          label: Synced
                          reason: null
                        document_number: BILL-1842
                        reference: 5cKTkaXNDpXqmNv0MzaOHAMppp6CsZOYXrgMbDv4UDg
                        currency_code: USD
                        total_debit: '1305.86'
                        total_credit: '1305.86'
                        document_total: '842.67'
                        sync_provider: Xero
                        sync_links:
                        - connection_id: 7
                          remote_type: xero_bill
                          remote_id: 57406763-6b49-4be8-98b5-16750c106f6e
                          link_state: linked_current
                          last_remote_seen_at: '2026-06-30T01:41:05Z'
                    message: Refreshed from the provider — but a credit note applied
                      there is not reflected in SKU. Create or allocate the matching
                      vendor credit to reconcile this bill.
        '502':
          description: Bad Gateway
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Could not reach the provider to fetch the latest — please
                    try again. (The access token has expired)
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-ledger-entries-entry-fetch-remote
  /api/ledger/entries/{entry}/sync-inspection:
    get:
      tags:
      - Ledger (Accounting v2)
      summary: Get Entry Sync Inspection
      description: 'Explain why a journal entry is (or is not) syncing to the accounting
        provider. Read-only — never writes.


        **Authentication:** Requires Bearer token.


        **Response fields:**

        - `eligible` (boolean) — the entry will sync automatically as it stands

        - `enableable` (boolean) — the entry won''t auto-sync, but a manual sync (or
        a `force_enabled` override) will push it: its only blockers are settings opt-outs

        - `can_sync_now` (boolean) — `eligible OR enableable`; whether a manual sync
        would succeed right now

        - `reasons` (array of strings) — why automatic sync is blocked (empty when
        eligible). Possible codes: `override_disabled`, `type_disabled`, `channel_disabled`,
        `granularity_off`, `before_type_sync_start_date`, `before_provider_sync_start_date`,
        `batch_member`, `batch_open`, `internal_only`, `connection_inactive`, `no_accounting_connection`

        - `structural_reasons` (array of strings) — the subset that blocks even a
        manual sync (empty when the entry is eligible or enableable)

        - `sync_override` (string|null) — the entry''s durable override (`force_enabled`
        / `force_disabled`), if any

        - `sync_override_provenance` (object|null) — who or what set the override:
        `source` (`user`, `legacy_cutover`, or `system`), `set_at` (ISO 8601), `set_by`
        (`{id, name}` of the user, or null)


        Notes: `channel_disabled` blocks scheduled sync only — a manual sync still
        pushes the entry. Structural codes (`connection_inactive`, `batch_member`,
        `batch_open`, `internal_only`, `before_provider_sync_start_date`) cannot be
        bypassed.


        Returns 404 when the entry does not exist.'
      parameters:
      - name: entry
        in: path
        schema:
          type: integer
        required: true
        description: Ledger journal entry ID (numeric). Route-model bound — returns
          404 if the entry does not exist.
        example: '1842'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      entry_id:
                        type: integer
                      eligible:
                        type: boolean
                      enableable:
                        type: boolean
                      can_sync_now:
                        type: boolean
                      reasons:
                        type: array
                        items:
                          type: string
                      structural_reasons:
                        type: array
                      sync_override:
                        type: string
                      sync_override_provenance:
                        type: object
                        properties:
                          source:
                            type: string
                          set_at:
                            type: string
                          set_by:
                            type: string
                            nullable: true
                  message:
                    type: string
                    nullable: true
                example:
                  data:
                    entry_id: 1842
                    eligible: false
                    enableable: true
                    can_sync_now: true
                    reasons:
                    - channel_disabled
                    - override_disabled
                    structural_reasons: []
                    sync_override: force_disabled
                    sync_override_provenance:
                      source: legacy_cutover
                      set_at: '2026-07-16T14:00:00+00:00'
                      set_by: null
                  message: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-ledger-entries-entry-sync-inspection
  /api/ledger/entries/{entry}/sync-override:
    post:
      tags:
      - Ledger (Accounting v2)
      summary: Set Sync Override
      description: "Set or clear the entry's durable sync override (Layer A). This\
        \ endpoint is THE sanctioned writer of `ledger_journal_entries.sync_override`\
        \ — the override is durable user intent, and regeneration never touches the\
        \ column, so it survives rebuilds (fixes the legacy is_sync_enabled clobber\
        \ bug).\n\n:::info[Authorization]\nAny valid API token can call this endpoint\
        \ — no specific scope required. [Manage tokens](https://app.sku.io/settings/api).\n\
        :::\n\n**Authentication:** Requires Bearer token.\n\n**Request body fields:**\n\
        - `override` (required-present, nullable) — one of:\n  - `\"force_enabled\"\
        ` — force the entry eligible for sync\n  - `\"force_disabled\"` — force the\
        \ entry excluded from sync\n  - `null` — clear the override back to derived\
        \ eligibility\n\nThe key MUST be present in the body (HTTP 422 if omitted);\
        \ send `null` to clear.\n\nAfter the write, sync work and display status are\
        \ re-evaluated. The response echoes the entry's id, the saved sync_override\
        \ and the recomputed display_status. Returns 404 when the entry does not exist.\n\
        \nPermission: requires `accounting.sync` (granular permissions; admins bypass;\
        \ unenforced when the tenant's granular_permissions feature flag is off).\
        \ Returns 403 without it.\n\nEvery write records provenance (who set the override\
        \ and when), returned as `sync_override_provenance` on the entry; clearing\
        \ the override clears the provenance with it."
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                override:
                  type: string
              example:
                override: force_disabled
      parameters:
      - name: entry
        in: path
        schema:
          type: integer
        required: true
        description: Ledger journal entry ID (numeric). Route-model bound — returns
          404 if the entry does not exist.
        example: '1842'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      sync_override:
                        type: string
                      display_status:
                        type: string
                      can_sync_now:
                        type: boolean
                      locked_update_pending:
                        type: boolean
                      locked_amend_blocked:
                        type: boolean
                  message:
                    type: string
                example:
                  data:
                    id: 1842
                    sync_override: force_disabled
                    display_status: excluded
                    can_sync_now: true
                    locked_update_pending: false
                    locked_amend_blocked: false
                  message: Sync override updated.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      override:
                        type: array
                        items:
                          type: string
                example:
                  message: The override field must be provided (use null to clear
                    the override).
                  errors:
                    override:
                    - The override field must be provided (use null to clear the override).
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-ledger-entries-entry-sync-override
  /api/ledger/entries/{entry}/reference-override:
    post:
      tags:
      - Ledger (Accounting v2)
      summary: Set Reference Override
      description: 'Set or clear the entry''s durable **reference override**. The
        override is the custom reference shown in SKU and SENT TO THE ACCOUNTING PROVIDER
        (Xero/QBO) as the reference / invoice number, in place of the auto-derived
        `reference`. Like `sync_override` it is durable user intent — carried across
        draft regeneration and posted reversal+replacement — and the original `reference`
        is always retained for traceability.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Authentication:** Requires Bearer token.


        **Request body fields:**

        - `reference` (required-present, nullable string, max 191) — the custom reference.
        Send an empty string or `null` to clear the override back to the derived reference.


        The key MUST be present (HTTP 422 if omitted). The response echoes the entry
        id, the derived `reference`, the saved `reference_override`, and `display_reference`
        (= override ?? reference, what the UI shows and what syncs). Returns 404 when
        the entry does not exist.


        Permission: requires `accounting.sync`.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                reference:
                  type: string
              example:
                reference: PO-0001.55
      parameters:
      - name: entry
        in: path
        schema:
          type: integer
        required: true
        description: Ledger journal entry ID (numeric). Route-model bound — returns
          404 if the entry does not exist.
        example: '1842'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      document_number:
                        type: string
                      reference:
                        type: string
                      reference_override:
                        type: string
                      display_reference:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 1842
                    document_number: JE-1842
                    reference: PO-0001
                    reference_override: PO-0001.55
                    display_reference: PO-0001.55
                  message: Reference updated.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-ledger-entries-entry-reference-override
  /api/ledger/entries/{entry}/nominal-overrides:
    post:
      tags:
      - Ledger (Accounting v2)
      summary: Set Nominal Override
      description: 'Pin a durable manual **nominal-code (GL account) override** on
        the entry: "when this entry would post to `from_nominal_code_id`, post to
        `to_nominal_code_id` instead." The override is keyed by the entry identity
        and **re-applied during derivation on every rebuild**, so it survives regeneration
        the way `sync_override` does — while amounts, dates and lines keep tracking
        the source document (it pins ONLY the account, NOT a whole-entry lock).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Applying it rebuilds the entry through the normal pipeline: a **draft** regenerates
        with the remapped account; a **posted** entry **reverses + re-posts** a correction
        (the accounting-correct path). Re-editing an already-overridden line keys
        off the line''s ORIGINALLY-DERIVED account, so send `from_nominal_code_id
        = nominal_code_id_original ?? nominal_code_id`.


        **Authentication:** Requires Bearer token.


        **Request body fields:**

        - `from_nominal_code_id` (required, integer, exists:nominal_codes) — the originally-derived
        account to remap.

        - `to_nominal_code_id` (required, integer, exists:nominal_codes, different
        from `from`) — the account to post to.


        To revert, use DELETE on this endpoint instead. Returns 404 when the entry
        does not exist.


        Permission: requires `accounting.sync`.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                from_nominal_code_id:
                  type: integer
                to_nominal_code_id:
                  type: integer
              example:
                from_nominal_code_id: 10
                to_nominal_code_id: 20
      parameters:
      - name: entry
        in: path
        schema:
          type: integer
        required: true
        description: Ledger journal entry ID (numeric). Route-model bound — returns
          404 if the entry does not exist.
        example: '1842'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                  message:
                    type: string
                example:
                  data: []
                  message: Account override saved — the entry will regenerate with
                    the new account shortly.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-ledger-entries-entry-nominal-overrides
    delete:
      tags:
      - Ledger (Accounting v2)
      summary: Remove Nominal Override
      description: 'Remove the nominal-code override for one originally-derived account
        (`from_nominal_code_id`) so the line reverts to its source-derived account
        on the next rebuild.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Authentication:** Requires Bearer token.


        **Request body fields:**

        - `from_nominal_code_id` (required, integer) — the derived account whose override
        is being removed.


        Returns 404 when the entry does not exist. Permission: requires `accounting.sync`.'
      parameters:
      - name: entry
        in: path
        schema:
          type: integer
        required: true
        description: Ledger journal entry ID (numeric). Route-model bound — returns
          404 if the entry does not exist.
        example: '1842'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                  message:
                    type: string
                example:
                  data: []
                  message: Override removed — the line will revert to its derived
                    account shortly.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-ledger-entries-entry-nominal-overrides
  /api/ledger/entries/bulk:
    post:
      tags:
      - Ledger (Accounting v2)
      summary: Bulk Entry Action
      description: 'Dispatch one tracked bulk action over ledger entries. Eligible/excluded
        counts are computed server-side via EligibilityResolver BEFORE dispatch, so
        the response counts are accurate. The job reports progress via the tracked
        job log endpoints.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Authentication:** Requires Bearer token + `accounting.sync` permission (403
        without it).


        **Request body fields:**

        - `action` (required) — one of: `sync_now` (queue an immediate provider push),
        `set_override` (force sync on/off — requires `override`), `rebuild` (regenerate
        from source; posted entries corrected via reversal + replacement), `unlink`
        (sever the provider sync link so SKU stops tracking the remote doc — a later
        sync CREATES a new doc), `clear_errors` (dismiss parked needs_action / failed_retryable
        operations WITHOUT retrying), `fetch_remote` (the INBOUND mirror of sync_now
        — re-read the remote document(s) and re-grade the link state: drift / void
        / settled-lock; runs as a tracked job), `delete` (HARD-delete the entry —
        permanently removes the journal entry, its GL lines, provider sync links and
        operation history, and nulls any sibling reversal pointer; IRREVERSIBLE; unlike
        the other actions it runs even when ledger generation is disabled).

        - `scope` (optional, `selected` default | `all` | `all_stale`) — `all` targets
        every entry matching the CURRENT filters (send the same `filter[...]` / `filter_groups`
        query params as the list); `all_stale` targets every stale pre-cutover (frozen
        history) entry, so one `rebuild` call drains the entire stale worklist rather
        than only its preview page. Both are resolved server-side and capped at 5000;
        `entry_ids` is then optional/ignored.

        - `entry_ids` (array, required unless `scope=all` or `scope=all_stale`, max
        1000) — the explicitly selected entry ids.

        - `override` (required when `action=set_override`) — `force_enabled` | `force_disabled`
        | null (clear).


        **Eligibility (excluded from the action, counted in `excluded_count`):** `sync_now`
        → entries eligible on at least one connection; `rebuild` → source still exists;
        `unlink` and `fetch_remote` → entry currently has a live remote link; `clear_errors`
        → entry carries a clearable parked error; `set_override` and `delete` → always
        applicable.


        **Note:** when ledger generation is disabled (kill switch) no job dispatches
        — the response carries `note: "generation_disabled"` and `tracked_job_log_id:
        null`. The `delete` action is the one exception: it always dispatches its
        job so test/erroneous entries can be cleaned up while the kill switch is on.


        **Response fields:** `tracked_job_log_id` (null when no job dispatched), `total`
        (entries the job will process), `eligible_count`, `excluded_count`. When `scope=all`
        or `scope=all_stale` and the match set exceeds the cap (default 5000, `ledger.bulk.all_scope_cap`),
        the remainder is dropped and the response adds `all_scope_truncated: true`,
        `matched_total` (total entries matching the filters), and `cap` (the limit
        applied); the message then names how many of how many entries were started.


        **`replace_nominal_code` action (find & replace account):** remaps every line
        deriving `from_nominal_code_id` to `to_nominal_code_id` across the selected/all-filtered
        entries by pinning a durable per-entry override (re-applied on every rebuild).
        Extra body fields when `action = "replace_nominal_code"`:

        - `from_nominal_code_id` (required, integer, exists:nominal_codes)

        - `to_nominal_code_id` (required, integer, exists:nominal_codes, different
        from `from`)

        Runs as a tracked background job (tracked job log endpoints).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                action:
                  type: string
                entry_ids:
                  type: array
                  items:
                    type: integer
              example:
                action: unlink
                entry_ids:
                - 1842
                - 1836
                - 1831
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 OK — job dispatched
                  value:
                    data:
                      tracked_job_log_id: 4821
                      total: 312
                      eligible_count: 298
                      excluded_count: 14
                    message: Bulk action started — track progress in the job tray.
                    status: success
                example-1:
                  summary: 200 OK — hard delete dispatched
                  value:
                    data:
                      tracked_job_log_id: 4823
                      total: 2
                      eligible_count: 2
                      excluded_count: 0
                    message: Deletion started — track progress in the job tray.
                    status: success
                example-2:
                  summary: 200 OK — all-scope truncated (cap reached)
                  value:
                    data:
                      tracked_job_log_id: 4822
                      total: 5000
                      eligible_count: 5000
                      excluded_count: 0
                      all_scope_truncated: true
                      matched_total: 7340
                      cap: 5000
                    message: Bulk action started on the first 5000 of 7340 matching
                      entries (the cap was reached — the remainder were not included).
                      Track progress in the job tray.
                    status: success
                example-3:
                  summary: 200 OK — generation disabled (no job dispatched)
                  value:
                    data:
                      tracked_job_log_id: null
                      total: 3
                      eligible_count: 0
                      excluded_count: 0
                      note: generation_disabled
                    message: Ledger generation is disabled — no bulk action was started.
                    status: success
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      entry_ids:
                        type: array
                        items:
                          type: string
                      override:
                        type: array
                        items:
                          type: string
                example:
                  message: A maximum of 1000 entries can be processed at once.
                  errors:
                    entry_ids:
                    - A maximum of 1000 entries can be processed at once.
                    override:
                    - The override field must be present when action is set_override.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-ledger-entries-bulk
  /api/ledger/entries/export:
    get:
      tags:
      - Ledger (Accounting v2)
      summary: Export Journal Entries
      description: 'Download the journal-entry list as an XLSX or CSV file (the Export
        modal). Honours the same filters as the index plus `format` (xlsx/csv) and
        `columns` (visible-column subset). Scope is expressed by the filters sent:
        ''all'' sends only the base scope, ''filtered'' sends the active filters,
        ''selected'' adds filter[ids]. Returns a binary file download (Content-Disposition),
        not JSON. Requires a Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-ledger-entries-export
  /api/ledger/entries/selection-summary:
    post:
      tags:
      - Ledger (Accounting v2)
      summary: Get Selection Summary
      description: 'Per-nominal-code debit/credit/line-count breakdown of a selection
        of entries plus grand totals — powers the table''s expandable Selection Summary
        panel (parity with the legacy SelectedTransactionsSummary), sourced from the
        real journal lines.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Authentication:** Requires Bearer token.


        **Request body:**

        - `scope` (optional, `selected` default | `all`) — `all` summarizes every
        entry matching the CURRENT filters (forward the same `filter[...]` / `filter_groups`
        query params), capped at 5000; `entry_ids` then optional.

        - `entry_ids` (array, required unless `scope=all`, max 5000) — the selected
        entry ids.


        **Response:** `entry_count`, `currency` (null when the selection mixes currencies),
        `total_debit`, `total_credit`, and `accounts[]` of `{nominal_code_id, code,
        name, debit, credit, line_count}` (unmapped lines collapse under a null nominal_code_id).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                entry_ids:
                  type: array
                  items:
                    type: integer
              example:
                entry_ids:
                - 1842
                - 1836
                - 1831
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      selection_summary:
                        type: object
                        properties:
                          entry_count:
                            type: integer
                          currency:
                            type: string
                          total_debit:
                            type: string
                          total_credit:
                            type: string
                          accounts:
                            type: array
                            items:
                              type: object
                              properties:
                                nominal_code_id:
                                  type: integer
                                code:
                                  type: string
                                name:
                                  type: string
                                debit:
                                  type: string
                                credit:
                                  type: string
                                line_count:
                                  type: integer
                  status:
                    type: string
                example:
                  data:
                    selection_summary:
                      entry_count: 2
                      currency: USD
                      total_debit: '140.0000'
                      total_credit: '140.0000'
                      accounts:
                      - nominal_code_id: 4
                        code: '1000'
                        name: Inventory Control
                        debit: '140.0000'
                        credit: '0.0000'
                        line_count: 2
                      - nominal_code_id: 3
                        code: '5000'
                        name: Cost of Goods Sold
                        debit: '0.0000'
                        credit: '140.0000'
                        line_count: 2
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-ledger-entries-selection-summary
  /api/ledger/entries/repost-all:
    post:
      tags:
      - Ledger (Accounting v2)
      summary: Repost All Entries
      description: 'Repost every current (non-discarded, non-reversed) ledger entry
        so posted GL lines pick up a changed chart of accounts — the onboarding backfill
        after adopting a provider''s chart. Reuses the bulk rebuild pipeline: posted
        entries auto-reverse + replace with the new nominal codes, drafts regenerate
        in place, batch aggregates route through the batch state machine. Requires
        the `accounting.sync` permission. Returns the tracked job log id + eligible/excluded
        counts.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 OK
                  value:
                    data:
                      tracked_job_log_id: 5120
                      total: 842
                      eligible_count: 842
                      excluded_count: 0
                    message: Repost started for 842 ledger entries — track progress
                      in the job tray.
                example-1:
                  summary: 200 Generation disabled
                  value:
                    data:
                      tracked_job_log_id: null
                      total: 0
                      eligible_count: 0
                      excluded_count: 0
                      note: generation_disabled
                    message: Ledger generation is disabled — no repost was started.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-ledger-entries-repost-all
  /api/ledger/entries/by-source:
    get:
      tags:
      - Ledger (Accounting v2)
      summary: Get Entry by Source
      description: 'The current v2 ledger journal entry for a source document (or
        data:null). Lets a source-doc accounting tab (Purchase Invoice, PO, Sales
        Order, etc.) show its v2 ledger entry as the accounting transaction — linked
        to /v2/ledger/entries/{id} — instead of the legacy v1 accounting_transaction.
        source_type is the source model FQN.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: source_type
        in: query
        schema:
          type: string
        description: Source model FQN (required)
        example: App\Models\PurchaseInvoice
      - name: source_id
        in: query
        schema:
          type: integer
        description: Source record id (required)
        example: '3'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 OK (entry found)
                  value:
                    data:
                      id: 3
                      document_number: JE-3
                      reference: 'PO-0001: ionv001'
                      display_status: excluded
                      can_sync_now: true
                      locked_update_pending: false
                      locked_amend_blocked: false
                      total_debit: '5000.0000'
                      total_credit: '5000.0000'
                      effective_at: '2026-06-26T00:00:00Z'
                example-1:
                  summary: 200 OK (no entry)
                  value:
                    data: null
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-ledger-entries-by-source
  /api/ledger/entries/by-source-list:
    get:
      tags:
      - Ledger (Accounting v2)
      summary: List Entries by Source
      description: 'Every live (non-discarded, non-reversal, non-reversed) v2 ledger
        journal entry for a source document, as a lightweight list. Where /by-source
        returns only the latest single entry, a source can post more than one current
        entry — an Amazon settlement posts both an invoice AND a bill — so a source-doc
        accounting list (e.g. the Amazon bank-transaction detail page) needs the full
        set. Each item links to /v2/ledger/entries/{id}. source_type is the source
        model FQN.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Returns data: an array of { id, type, reference, total }. Empty array when
        the source has no live entries.


        **`total`** is the NET document total (the provider-booked face value — net
        control-account movement), not the gross debit total. For an Amazon settlement
        bill with internal reserve contra legs the two differ (e.g. 842.67 net vs
        1,305.86 gross).'
      parameters:
      - name: source_type
        in: query
        schema:
          type: string
        description: Source model FQN (required)
        example: Modules\Amazon\Entities\AmazonFinancialEventGroup
      - name: source_id
        in: query
        schema:
          type: integer
        description: Source record id (required)
        example: '16'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 OK (invoice + bill)
                  value:
                    data:
                    - id: 29
                      type: sales_order_invoice
                      document_number: INV-29
                      reference: aS1O-So4T6lFwowEq3JBCtjdts5TNjL553ZUrzAGZFk
                      total: '115229.9300'
                    - id: 30
                      type: bill
                      document_number: BILL-30
                      reference: aS1O-So4T6lFwowEq3JBCtjdts5TNjL553ZUrzAGZFk
                      total: '38755.6700'
                example-1:
                  summary: 200 OK (no entries)
                  value:
                    data: []
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-ledger-entries-by-source-list
  /api/ledger/payments:
    get:
      tags:
      - Ledger (Accounting v2)
      summary: List Payments
      description: 'SKU-side payments (App\Models\Payment) paginated, each with its
        source document and the linked accounting-provider payment (Xero/QBO) cross-link.
        Backs the Accounting v2 Payments tab. `provider_payment` is null when the
        payment has not been synced to a provider; `status` is synced / error / not_synced.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authenticate with a Personal Access Token (PAT).'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        amount:
                          type: string
                        currency_code:
                          type: string
                        payment_date:
                          type: string
                        type:
                          type: string
                        payment_type:
                          type: string
                        external_reference:
                          type: string
                        source:
                          type: object
                          properties:
                            type:
                              type: string
                            id:
                              type: integer
                            label:
                              type: string
                            link_type_label:
                              type: string
                            link_route:
                              type: string
                            link_legacy_url:
                              type: string
                              nullable: true
                            url:
                              type: string
                        provider_payment:
                          type: object
                          properties:
                            provider:
                              type: string
                            reference:
                              type: string
                            link_route:
                              type: string
                            remote_url:
                              type: string
                            sync_status:
                              type: string
                        status:
                          type: string
                        created_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - id: 4821
                    amount: '59.99'
                    currency_code: USD
                    payment_date: '2026-06-14T00:00:00+00:00'
                    type: direct
                    payment_type: Amazon Payment
                    external_reference: 114-4389768-5982613
                    source:
                      type: App\Models\SalesOrder
                      id: 18519
                      label: 114-4389768-5982613
                      link_type_label: Sales Order
                      link_route: /orders/sales-orders/18519
                      link_legacy_url: null
                      url: /orders/sales-orders/18519
                    provider_payment:
                      provider: Xero
                      reference: pay-86906814-f1e5
                      link_route: /integrations/xero/payments/12
                      remote_url: https://go.xero.com/Bank/ViewTransaction.aspx?bankTransactionID=pay-86906814-f1e5
                      sync_status: synced
                    status: synced
                    created_at: '2026-06-14T08:58:00+00:00'
                  current_page: 1
                  last_page: 2704
                  per_page: 15
                  total: 40547
                  from: 1
                  to: 15
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-ledger-payments
  /api/ledger/payments/{payment}/sync:
    post:
      tags:
      - Ledger (Accounting v2)
      summary: Sync Payment to Provider
      description: 'Manually push (or re-push) one SKU payment to the connected accounting
        provider (two-way payment sync) — the row action on the Payments tab. Runs
        inline: eligibility rejections and provider validation errors are persisted
        to the payment''s last_sync_error and returned as 422; transport/auth failures
        return 502 with no state change.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Requires Bearer token + `accounting.sync` permission and an active ledger
        cutover.


        Eligibility: the payment must be SKU-originated (not ingested from the provider),
        a cash-style type, and its owner document''s current ledger entry must have
        a live sync link to a provider invoice/bill. On success the payment is linked
        to the created provider payment (accounting_integration) and its status on
        the Payments tab flips to Synced.'
      requestBody:
        content: {}
      parameters:
      - name: payment
        in: path
        schema:
          type: integer
        required: true
        description: The SKU payment id
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  status:
                    type: string
                example:
                  message: Payment synced to the accounting provider.
                  status: success
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  status:
                    type: string
                example:
                  message: Payment type "Wire" is not mapped to a Xero bank account
                    — map it in the Xero payment type settings.
                  status: failure
        '502':
          description: Bad Gateway
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  status:
                    type: string
                example:
                  message: Could not reach the provider to sync the payment — please
                    try again. (Xero must be reauthorized.)
                  status: failure
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-ledger-payments-payment-sync
  /api/ledger/batches:
    get:
      tags:
      - Ledger (Accounting v2)
      summary: List Batches
      description: 'Paginated ledger batches listing: the grouping key (type, period,
        channel, currency), lifecycle status with the derived `is_dirty` flag, members_count
        and the aggregate journal entry summary.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Authentication:** Requires Bearer token.


        **Filters (Spatie QueryBuilder):**

        - `filter[type]` — exact entry type

        - `filter[period_type]` — daily | monthly

        - `filter[status]` — open | dirty | closing | posted | reopened

        - `filter[currency_code]` — exact currency

        - `filter[channel]` — exact integration_instance_id

        - `filter[date_from]` / `filter[date_to]` — m/d/Y on period_start (invalid
        dates silently ignored)

        - `filter[dirty]` — boolean; true = status dirty or reopened (the needs-rebuild
        indicator), false = everything else


        **Sorts:** id, period_start, type, members_count, created_at (default: -period_start).


        **Pagination:** per_page default 10, clamped to max 100.


        `entry` is the batch''s current aggregate journal entry summary (null when
        not yet built). `channel` is null for batches not scoped to a channel.


        **Advanced filters (`filter_groups`):** base64-encoded JSON tree of AND/OR
        groups via GroupedFilterSupport (same stack as the entries index).

        **Filterable columns:** `batch_type`, `batch_status`, `batch_period_type`,
        `currency` (text operators); `id`, `members_count` (numeric operators); `period_start`,
        `period_end` (date operators); `created_at` (datetime operators). Unregistered
        columns are rejected with HTTP 400.


        **Search:** `filter[search]` matches the batch type and the aggregate journal
        entry''s reference.

        **Sorts:** id, period_start, type, members_count, currency_code, status, created_at,
        channel (channel name via subquery) — prefix with - for DESC; default -period_start.


        **Provider sync (entry object):** each batch''s `entry` includes `provider_status`
        — the accounting provider''s own status for the synced document (e.g. AUTHORISED,
        POSTED, PAID; null when never synced) — and `provider_link`, the linked provider
        document (`provider`, `label`, `link_route`, `remote_url`; null when never
        synced).'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        type:
                          type: object
                          properties:
                            value:
                              type: string
                            label:
                              type: string
                        period_type:
                          type: string
                        period_start:
                          type: string
                        period_end:
                          type: string
                        channel:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        currency_code:
                          type: string
                        status:
                          type: string
                        is_dirty:
                          type: boolean
                        members_count:
                          type: integer
                        entry:
                          type: object
                          properties:
                            id:
                              type: integer
                            reference:
                              type: string
                            status:
                              type: string
                            display_status:
                              type: object
                              properties:
                                key:
                                  type: string
                                label:
                                  type: string
                                color:
                                  type: string
                            can_sync_now:
                              type: boolean
                            provider_link:
                              type: string
                              nullable: true
                            provider_status:
                              type: string
                              nullable: true
                            total_debit:
                              type: string
                            total_credit:
                              type: string
                        created_at:
                          type: string
                  current_page:
                    type: integer
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                    items:
                      type: object
                      properties:
                        url:
                          type: string
                          nullable: true
                        label:
                          type: string
                        active:
                          type: boolean
                  next_page_url:
                    type: string
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 57
                    type:
                      value: fba_shipments
                      label: FBA Shipments
                    period_type: monthly
                    period_start: '2026-06-01'
                    period_end: '2026-06-30'
                    channel:
                      id: 8
                      name: Amazon US
                    currency_code: USD
                    status: open
                    is_dirty: false
                    members_count: 1240
                    entry:
                      id: 1901
                      reference: BATCH-FBA-SHIPMENTS-2026-06
                      status: draft
                      display_status:
                        key: pending_sync
                        label: Pending Sync
                        color: info
                      can_sync_now: true
                      provider_link: null
                      provider_status: null
                      total_debit: '48211.7500'
                      total_credit: '48211.7500'
                    created_at: '2026-06-01T00:05:11+00:00'
                  - id: 52
                    type:
                      value: batch_sales_order_invoice
                      label: Batch Sales Order Invoice
                    period_type: daily
                    period_start: '2026-06-08'
                    period_end: '2026-06-08'
                    channel:
                      id: 5
                      name: Shopify Main Store
                    currency_code: USD
                    status: posted
                    is_dirty: false
                    members_count: 86
                    entry:
                      id: 1888
                      reference: BATCH-SALES-2026-06-08-SHOPIFY
                      status: posted
                      display_status:
                        key: synced
                        label: Synced
                        color: success
                      can_sync_now: true
                      provider_link:
                        provider: Xero
                        remote_type: xero_invoice
                        remote_id: b7c1e2a4-9f3d-4a2b-8e6c-2f1d0a9b8c77
                        link_type_label: Invoice
                        label: INV-1042
                        link_route: /integrations/xero/invoices/318
                        remote_url: https://go.xero.com/app/invoicing/view/b7c1e2a4-9f3d-4a2b-8e6c-2f1d0a9b8c77
                      provider_status: AUTHORISED
                      total_debit: '10422.9000'
                      total_credit: '10422.9000'
                    created_at: '2026-06-08T00:02:33+00:00'
                  current_page: 1
                  first_page_url: https://sku-alt.test/api/ledger/batches?page=1
                  from: 1
                  last_page: 6
                  last_page_url: https://sku-alt.test/api/ledger/batches?page=6
                  links:
                  - url: null
                    label: '&laquo; Previous'
                    active: false
                  - url: https://sku-alt.test/api/ledger/batches?page=1
                    label: '1'
                    active: true
                  - url: https://sku-alt.test/api/ledger/batches?page=2
                    label: Next &raquo;
                    active: false
                  next_page_url: https://sku-alt.test/api/ledger/batches?page=2
                  path: https://sku-alt.test/api/ledger/batches
                  per_page: 10
                  prev_page_url: null
                  to: 10
                  total: 54
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-ledger-batches
  /api/ledger/batches/{batch}:
    get:
      tags:
      - Ledger (Accounting v2)
      summary: Get Batch
      description: 'Batch detail: the batch resource (under the `batch` key) plus
        `totals_by_account` — the aggregate journal entry''s GL impact grouped by
        nominal code, one row per account with its debit and credit sums (4-decimal
        strings).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Authentication:** Requires Bearer token.


        `totals_by_account` is an empty array when the batch''s aggregate entry has
        not been built yet. Returns 404 when the batch does not exist.


        **Provider sync (entry object):** each batch''s `entry` includes `provider_status`
        — the accounting provider''s own status for the synced document (e.g. AUTHORISED,
        POSTED, PAID; null when never synced) — and `provider_link`, the linked provider
        document (`provider`, `label`, `link_route`, `remote_url`; null when never
        synced).'
      parameters:
      - name: batch
        in: path
        schema:
          type: integer
        required: true
        description: Ledger batch ID (numeric). Route-model bound — returns 404 if
          the batch does not exist.
        example: '57'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      batch:
                        type: object
                        properties:
                          id:
                            type: integer
                          type:
                            type: object
                            properties:
                              value:
                                type: string
                              label:
                                type: string
                          period_type:
                            type: string
                          period_start:
                            type: string
                          period_end:
                            type: string
                          channel:
                            type: object
                            properties:
                              id:
                                type: integer
                              name:
                                type: string
                          currency_code:
                            type: string
                          status:
                            type: string
                          is_dirty:
                            type: boolean
                          members_count:
                            type: integer
                          entry:
                            type: object
                            properties:
                              id:
                                type: integer
                              reference:
                                type: string
                              status:
                                type: string
                              display_status:
                                type: object
                                properties:
                                  key:
                                    type: string
                                  label:
                                    type: string
                                  color:
                                    type: string
                              can_sync_now:
                                type: boolean
                              provider_link:
                                type: string
                                nullable: true
                              provider_status:
                                type: string
                                nullable: true
                              total_debit:
                                type: string
                              total_credit:
                                type: string
                          created_at:
                            type: string
                      totals_by_account:
                        type: array
                        items:
                          type: object
                          properties:
                            nominal_code:
                              type: object
                              properties:
                                id:
                                  type: integer
                                code:
                                  type: string
                                name:
                                  type: string
                            debit:
                              type: string
                            credit:
                              type: string
                example:
                  data:
                    batch:
                      id: 57
                      type:
                        value: fba_shipments
                        label: FBA Shipments
                      period_type: monthly
                      period_start: '2026-06-01'
                      period_end: '2026-06-30'
                      channel:
                        id: 8
                        name: Amazon US
                      currency_code: USD
                      status: open
                      is_dirty: false
                      members_count: 1240
                      entry:
                        id: 1901
                        reference: BATCH-FBA-SHIPMENTS-2026-06
                        status: draft
                        display_status:
                          key: pending_sync
                          label: Pending Sync
                          color: info
                        can_sync_now: true
                        provider_link: null
                        provider_status: null
                        total_debit: '48211.7500'
                        total_credit: '48211.7500'
                      created_at: '2026-06-01T00:05:11+00:00'
                    totals_by_account:
                    - nominal_code:
                        id: 40
                        code: '4000'
                        name: Sales Revenue
                      debit: '0.0000'
                      credit: '48211.7500'
                    - nominal_code:
                        id: 12
                        code: '1100'
                        name: Accounts Receivable
                      debit: '48211.7500'
                      credit: '0.0000'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-ledger-batches-batch
  /api/ledger/batches/{batch}/members:
    get:
      tags:
      - Ledger (Accounting v2)
      summary: List Batch Members
      description: 'Paginated member documents of a batch — the A2X-style lineage
        view. Each member row carries:


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        - `member` — the cross-link view-model for the member document (morph type
        + ID, friendly label/reference, link_type_label, the application UI link_route
        when a detail page exists)

        - `contribution` — the member''s debit/credit contribution inside this batch
        (its journal lines summed by direction, 4-decimal strings)

        - `added_at` — when the document joined the batch


        **Authentication:** Requires Bearer token.


        **Pagination:** per_page default 10, clamped to max 100. Newest members first.


        Returns 404 when the batch does not exist.


        **Advanced filters (`filter_groups`):** base64-encoded JSON tree of AND/OR
        groups via GroupedFilterSupport.

        **Filterable columns:** `member_type` (text operators); `member_id`, `id`
        (numeric operators); `added_at` (datetime operators). Unregistered columns
        are rejected with HTTP 400.


        **Search:** `filter[search]` matches the member''s morph type and (when numeric,
        # prefix allowed) the document id.

        **Sorts:** id, member_id, member_type, added_at, member (alias of member_id),
        debit, credit, document_date (contribution sums via correlated subquery) —
        prefix with - for DESC; default -id.


        **Response field `document_date`:** the member''s accounting date (its entry''s
        effective_at — the source document''s date), distinct from `added_at` (when
        the membership row was created). Sortable via `sort=document_date`.'
      parameters:
      - name: batch
        in: path
        schema:
          type: integer
        required: true
        description: Ledger batch ID (numeric). Route-model bound — returns 404 if
          the batch does not exist.
        example: '57'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        member:
                          type: object
                          properties:
                            type:
                              type: string
                            id:
                              type: integer
                            label:
                              type: string
                            link_type_label:
                              type: string
                            link_route:
                              type: string
                              nullable: true
                            link_legacy_url:
                              type: string
                              nullable: true
                            url:
                              type: string
                              nullable: true
                        contribution:
                          type: object
                          properties:
                            debit:
                              type: string
                            credit:
                              type: string
                        added_at:
                          type: string
                  current_page:
                    type: integer
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                    items:
                      type: object
                      properties:
                        url:
                          type: string
                          nullable: true
                        label:
                          type: string
                        active:
                          type: boolean
                  next_page_url:
                    type: string
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 9120
                    member:
                      type: App\Models\SalesOrderFulfillment
                      id: 44312
                      label: SO-10293-F1
                      link_type_label: Sales Order Fulfillment
                      link_route: null
                      link_legacy_url: null
                      url: null
                    contribution:
                      debit: '129.9900'
                      credit: '129.9900'
                    added_at: '2026-06-08T10:15:30+00:00'
                  - id: 9119
                    member:
                      type: App\Models\SalesOrder
                      id: 10288
                      label: SO-10288
                      link_type_label: Sales Order
                      link_route: /orders/sales-orders/10288
                      link_legacy_url: null
                      url: /orders/sales-orders/10288
                    contribution:
                      debit: '84.5000'
                      credit: '84.5000'
                    added_at: '2026-06-08T09:42:12+00:00'
                  current_page: 1
                  first_page_url: https://sku-alt.test/api/ledger/batches/57/members?page=1
                  from: 1
                  last_page: 124
                  last_page_url: https://sku-alt.test/api/ledger/batches/57/members?page=124
                  links:
                  - url: null
                    label: '&laquo; Previous'
                    active: false
                  - url: https://sku-alt.test/api/ledger/batches/57/members?page=1
                    label: '1'
                    active: true
                  - url: https://sku-alt.test/api/ledger/batches/57/members?page=2
                    label: Next &raquo;
                    active: false
                  next_page_url: https://sku-alt.test/api/ledger/batches/57/members?page=2
                  path: https://sku-alt.test/api/ledger/batches/57/members
                  per_page: 10
                  prev_page_url: null
                  to: 10
                  total: 1240
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-ledger-batches-batch-members
  /api/ledger/batches/{batch}/history:
    get:
      tags:
      - Ledger (Accounting v2)
      summary: Get Batch History
      description: 'Batch membership + correction history. Returns two keys:


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        - `events` — a paginated list of membership audit events (action added | removed,
        the member cross-link, `occurred_after_post` — whether the batch''s aggregate
        entry was already POSTED at the moment of the change, i.e. the change triggered
        an automatic reversal + replacement) — newest first, per_page default 10 clamped
        to 100

        - `reversal_chain` — every non-discarded aggregate journal entry sourced from
        this batch, oldest first: the current entry, reversed originals and the reversal
        mirror rows (id, reference, status, reversal_of_id, replaced_by_id, created_at)


        **Authentication:** Requires Bearer token.


        Returns 404 when the batch does not exist.'
      parameters:
      - name: batch
        in: path
        schema:
          type: integer
        required: true
        description: Ledger batch ID (numeric). Route-model bound — returns 404 if
          the batch does not exist.
        example: '57'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      events:
                        type: object
                        properties:
                          data:
                            type: array
                            items:
                              type: object
                              properties:
                                id:
                                  type: integer
                                action:
                                  type: string
                                member:
                                  type: object
                                  properties:
                                    type:
                                      type: string
                                    id:
                                      type: integer
                                    label:
                                      type: string
                                    link_type_label:
                                      type: string
                                    link_route:
                                      type: string
                                    link_legacy_url:
                                      type: string
                                      nullable: true
                                    url:
                                      type: string
                                occurred_after_post:
                                  type: boolean
                                created_at:
                                  type: string
                          current_page:
                            type: integer
                          first_page_url:
                            type: string
                          from:
                            type: integer
                          last_page:
                            type: integer
                          last_page_url:
                            type: string
                          links:
                            type: array
                            items:
                              type: object
                              properties:
                                url:
                                  type: string
                                  nullable: true
                                label:
                                  type: string
                                active:
                                  type: boolean
                          next_page_url:
                            type: string
                          path:
                            type: string
                          per_page:
                            type: integer
                          prev_page_url:
                            type: string
                            nullable: true
                          to:
                            type: integer
                          total:
                            type: integer
                      reversal_chain:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            reference:
                              type: string
                            status:
                              type: string
                            reversal_of_id:
                              type: string
                              nullable: true
                            replaced_by_id:
                              type: integer
                            created_at:
                              type: string
                example:
                  data:
                    events:
                      data:
                      - id: 15233
                        action: added
                        member:
                          type: App\Models\SalesOrder
                          id: 10301
                          label: SO-10301
                          link_type_label: Sales Order
                          link_route: /orders/sales-orders/10301
                          link_legacy_url: null
                          url: /orders/sales-orders/10301
                        occurred_after_post: true
                        created_at: '2026-06-09T16:20:44+00:00'
                      - id: 15201
                        action: removed
                        member:
                          type: App\Models\SalesOrder
                          id: 10295
                          label: SO-10295
                          link_type_label: Sales Order
                          link_route: /orders/sales-orders/10295
                          link_legacy_url: null
                          url: /orders/sales-orders/10295
                        occurred_after_post: false
                        created_at: '2026-06-08T11:02:10+00:00'
                      current_page: 1
                      first_page_url: https://sku-alt.test/api/ledger/batches/52/history?page=1
                      from: 1
                      last_page: 9
                      last_page_url: https://sku-alt.test/api/ledger/batches/52/history?page=9
                      links:
                      - url: null
                        label: '&laquo; Previous'
                        active: false
                      - url: https://sku-alt.test/api/ledger/batches/52/history?page=1
                        label: '1'
                        active: true
                      - url: https://sku-alt.test/api/ledger/batches/52/history?page=2
                        label: Next &raquo;
                        active: false
                      next_page_url: https://sku-alt.test/api/ledger/batches/52/history?page=2
                      path: https://sku-alt.test/api/ledger/batches/52/history
                      per_page: 10
                      prev_page_url: null
                      to: 10
                      total: 88
                    reversal_chain:
                    - id: 1888
                      reference: BATCH-SALES-2026-06-08-SHOPIFY
                      status: reversed
                      reversal_of_id: null
                      replaced_by_id: 1925
                      created_at: '2026-06-08T00:02:35+00:00'
                    - id: 1924
                      reference: BATCH-SALES-2026-06-08-SHOPIFY
                      status: posted
                      reversal_of_id: 1888
                      replaced_by_id: null
                      created_at: '2026-06-09T16:21:02+00:00'
                    - id: 1925
                      reference: BATCH-SALES-2026-06-08-SHOPIFY
                      status: posted
                      reversal_of_id: null
                      replaced_by_id: null
                      created_at: '2026-06-09T16:21:02+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-ledger-batches-batch-history
  /api/ledger/batches/{batch}/activity-log:
    get:
      tags:
      - Ledger (Accounting v2)
      summary: Get Batch Activity Log
      description: 'The batch''s standard LogsActivity feed (the detail page Activity
        tab): creation plus every status transition (open, dirty, closing, posted,
        reopened) with old/new values, causer and timestamp. Guarded query-update
        transitions are logged manually by the repository, so the feed covers the
        full state machine.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Authentication:** Requires Bearer token.


        Note: membership add/remove changes are NOT mirrored here — they live in the
        dedicated `/history` endpoint (ledger_batch_member_events).'
      parameters:
      - name: batch
        in: path
        schema:
          type: integer
        required: true
        description: Ledger batch id
        example: '12'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        description:
                          type: string
                        event:
                          type: string
                        subject_type:
                          type: string
                        subject_id:
                          type: integer
                        properties:
                          type: object
                          properties:
                            attributes:
                              type: object
                              properties:
                                status:
                                  type: string
                            old:
                              type: object
                              properties:
                                status:
                                  type: string
                            metadata:
                              type: object
                              properties:
                                type:
                                  type: string
                                period_type:
                                  type: string
                                period_start:
                                  type: string
                                currency_code:
                                  type: string
                        causer_name:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 166
                    description: updated
                    event: updated
                    subject_type: LedgerBatch
                    subject_id: 12
                    properties:
                      attributes:
                        status: dirty
                      old:
                        status: closing
                      metadata:
                        type: sales_order_fulfillment
                        period_type: daily
                        period_start: '2026-06-11'
                        currency_code: USD
                    causer_name: null
                    created_at: '2026-06-12T23:12:00.000000Z'
                  per_page: 15
                  total: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-ledger-batches-batch-activity-log
  /api/ledger/batches/{batch}/rebuild:
    post:
      tags:
      - Ledger (Accounting v2)
      summary: Rebuild Batch
      description: 'Manually rebuild the batch''s aggregate journal entry: marks the
        batch dirty (posted batches flip to `reopened` — the post-post correction
        pathway, where the rebuild reverses + replaces the posted aggregate entry)
        and dispatches a background job immediately (no debounce for a manual request;
        the job''s per-batch uniqueness still collapses doubles).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Deliberately NOT a tracked job: batch builds run in seconds on the per-tenant
        serial queue, and the batch row''s status transition (dirty/reopened → open/closing)
        is the user-visible completion signal.


        **Authentication:** Requires Bearer token.


        **Request body:** none.


        **Response:** accepted-style 200 — the work is queued (App\Response normalizes
        every 2xx to 200). Returns 404 when the batch does not exist.


        Permission: requires `accounting.sync` (granular permissions; admins bypass;
        unenforced when the tenant''s granular_permissions feature flag is off). Returns
        403 without it.'
      requestBody:
        content: {}
      parameters:
      - name: batch
        in: path
        schema:
          type: integer
        required: true
        description: Ledger batch ID (numeric). Route-model bound — returns 404 if
          the batch does not exist.
        example: '57'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                  message:
                    type: string
                example:
                  data: []
                  message: Batch rebuild queued — the aggregate entry will be rebuilt
                    shortly.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-ledger-batches-batch-rebuild
  /api/ledger/accounts/{nominalCode}:
    get:
      tags:
      - Ledger (Accounting v2)
      summary: Get Account Overview
      description: 'GL account drill-down header (the nominal code detail page): the
        account''s identity plus debit/credit/net totals and line count. Accepts the
        SAME filter[...] and `filter_groups` params as the lines endpoint, so the
        KPIs always describe exactly what the lines table shows.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Authentication:** Requires Bearer token.


        **Filterable columns (filter_groups):** `entry_reference`, `entry_type`, `line_direction`,
        `line_description`, `currency` (text operators); `amount`, `entry_id`, `id`
        (numeric operators); `effective_at` (date operators). Unregistered columns
        are rejected with HTTP 400.


        `account.posted_lines_count` is the UNfiltered count of live journal lines
        on the account (independent of the filter params) — the type editor uses it
        to decide whether a reclassification is guarded.


        `account.is_system_reserved` is true when the account is a control account
        mapped in the accounting settings (A/R, A/P, inventory control, …) — its type
        is locked and the editor disables the control.


        `account.integration_account` is the connected accounting-provider account
        (Xero or QBO) this nominal code maps to, or null when no provider is connected
        or no match exists. `link_basis` is `mapping` for an explicit polymorphic
        mapping (QBO always sets it; Xero sets it when the chart was mapped through
        the onboarding wizard) or `code` when inferred by matching the account code
        (xero_accounts.Code ⇄ nominal_codes.code — the fallback Xero''s sync uses
        for an adopted chart). The ledger account page renders the provider account
        inline and, for Xero, deep-links to /v2/integrations/xero/accounts/{integration_account.id}.'
      parameters:
      - name: nominalCode
        in: path
        schema:
          type: integer
        required: true
        description: Nominal code id
        example: '6'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      account:
                        type: object
                        properties:
                          id:
                            type: integer
                          code:
                            type: string
                          name:
                            type: string
                          type:
                            type: string
                          posted_lines_count:
                            type: integer
                          is_system_reserved:
                            type: boolean
                          archived_at:
                            type: string
                            nullable: true
                          integration_account:
                            type: object
                            properties:
                              provider:
                                type: string
                              provider_label:
                                type: string
                              id:
                                type: integer
                              external_id:
                                type: string
                              code:
                                type: string
                              name:
                                type: string
                              type:
                                type: string
                              class:
                                type: string
                              status:
                                type: string
                              link_basis:
                                type: string
                      totals:
                        type: object
                        properties:
                          total_debit:
                            type: string
                          total_credit:
                            type: string
                          net:
                            type: string
                          lines_count:
                            type: integer
                  status:
                    type: string
                example:
                  data:
                    account:
                      id: 6
                      code: '1200'
                      name: Accounts Receivable
                      type: Current
                      posted_lines_count: 16
                      is_system_reserved: true
                      archived_at: null
                      integration_account:
                        provider: xero
                        provider_label: Xero
                        id: 61
                        external_id: 2c8b3e10-7f4a-4d2e-9b1c-5a6f8e0d1234
                        code: '1200'
                        name: Accounts Receivable
                        type: CURRENT
                        class: ASSET
                        status: ACTIVE
                        link_basis: code
                    totals:
                      total_debit: '44545.4100'
                      total_credit: '0.0000'
                      net: '44545.4100'
                      lines_count: 16
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-ledger-accounts-nominalcode
  /api/ledger/accounts/{nominalCode}/lines:
    get:
      tags:
      - Ledger (Accounting v2)
      summary: List Account Lines
      description: 'Paginated journal lines hitting one GL account — every line of
        every non-discarded entry, reversals included (originals and reversal mirrors
        both appear and net to zero, as a general ledger account view should read).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Authentication:** Requires Bearer token.


        **Quick filters:** `filter[direction]` (debit|credit), `filter[type]` (entry
        type), `filter[date_from]` / `filter[date_to]` (m/d/Y on entry effective date),
        `filter[search]` (entry reference + descriptions).

        **Advanced filters (`filter_groups`):** same columns as Get Account Overview.

        **Sorts:** id, amount, direction, effective_at, entry (reference), entry_type,
        debit, credit — default -effective_at.'
      parameters:
      - name: nominalCode
        in: path
        schema:
          type: integer
        required: true
        description: Nominal code id
        example: '6'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        direction:
                          type: string
                        amount:
                          type: string
                        tax_amount:
                          type: string
                          nullable: true
                        description:
                          type: string
                        entry:
                          type: object
                          properties:
                            id:
                              type: integer
                            reference:
                              type: string
                            reference_suffix:
                              type: integer
                            type:
                              type: object
                              properties:
                                value:
                                  type: string
                                label:
                                  type: string
                            status:
                              type: string
                            effective_at:
                              type: string
                            currency_code:
                              type: string
                        source:
                          type: object
                          properties:
                            type:
                              type: string
                            id:
                              type: integer
                            label:
                              type: string
                            link_type_label:
                              type: string
                            link_route:
                              type: string
                            link_legacy_url:
                              type: string
                              nullable: true
                            url:
                              type: string
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 91
                    direction: debit
                    amount: '5081.13'
                    tax_amount: null
                    description: Accounts receivable
                    entry:
                      id: 24
                      reference: SALES_ORDER_INVOICE-2671
                      reference_suffix: 0
                      type:
                        value: sales_order_invoice
                        label: Sales Order Invoice
                      status: draft
                      effective_at: '2026-06-08T00:00:00+00:00'
                      currency_code: USD
                    source:
                      type: App\Models\SalesOrder
                      id: 2671
                      label: SO-2671
                      link_type_label: Sales Order
                      link_route: /orders/sales-orders/2671
                      link_legacy_url: null
                      url: /orders/sales-orders/2671
                  per_page: 10
                  total: 16
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-ledger-accounts-nominalcode-lines
  /api/ledger/accounts/{nominalCode}/type:
    put:
      tags:
      - Ledger (Accounting v2)
      summary: Update Account Type
      description: 'Reclassify a GL account''s type (the account-class enum).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Authentication:** Requires Bearer token. Gated by the `accounting.manage_settings`
        permission.


        **Body:** `type` (required) — one of: Revenue, Expense, Asset, Liability,
        Equity, Bank, Current, Inventory, Fixed, Directcosts, Currliab, Termliab,
        Sales.


        **Tiered guardrail (mirrors NetSuite/SAP/QBO/Xero):**

        1. No-op (same type) → always allowed.

        2. System/reserved control account (mapped in accounting settings — A/R, A/P,
        inventory control, COGS, sales tax) → BLOCKED regardless of posting (422).
        Re-map the setting to a different account instead.

        3. No posted journal lines → the type may change to anything.

        4. Posted lines exist → the new type must stay in the SAME reclassification
        group (same statement side AND same normal balance): same-group changes (e.g.
        Current → Fixed asset, Liability → Equity) are allowed; changes that cross
        the Balance Sheet ↔ Income Statement boundary or flip the normal balance (e.g.
        Asset → Expense) are rejected with 422.


        Returns the same shape as Get Account Overview so the page header re-renders
        in place. The change is recorded in the account''s activity log.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                type:
                  type: string
              example:
                type: Fixed
      parameters:
      - name: nominalCode
        in: path
        schema:
          type: integer
        required: true
        description: Nominal code id
        example: '6'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      account:
                        type: object
                        properties:
                          id:
                            type: integer
                          code:
                            type: string
                          name:
                            type: string
                          type:
                            type: string
                          posted_lines_count:
                            type: integer
                          is_system_reserved:
                            type: boolean
                          archived_at:
                            type: string
                            nullable: true
                      totals:
                        type: object
                        properties:
                          total_debit:
                            type: string
                          total_credit:
                            type: string
                          net:
                            type: string
                          lines_count:
                            type: integer
                  message:
                    type: string
                  status:
                    type: string
                example:
                  data:
                    account:
                      id: 6
                      code: '1500'
                      name: Office Equipment
                      type: Fixed
                      posted_lines_count: 4
                      is_system_reserved: false
                      archived_at: null
                    totals:
                      total_debit: '12000.0000'
                      total_credit: '0.0000'
                      net: '12000.0000'
                      lines_count: 4
                  message: Account type updated.
                  status: success
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 422 — change leaves the reclassification group (account
                    has posted lines)
                  value:
                    message: This account already has 4 posted journal line(s), so
                      its type can only change to another balance sheet, debit-normal
                      account (same statement, same normal balance). Moving it across
                      the Balance Sheet / Income Statement boundary would silently
                      restate posted balances and retained earnings. Create a new
                      account and post a reclassifying journal entry to move the balance
                      instead.
                    errors:
                      type:
                      - This account already has 4 posted journal line(s), so its
                        type can only change to another balance sheet, debit-normal
                        account (same statement, same normal balance). Moving it across
                        the Balance Sheet / Income Statement boundary would silently
                        restate posted balances and retained earnings. Create a new
                        account and post a reclassifying journal entry to move the
                        balance instead.
                example-1:
                  summary: 422 — system/reserved control account is locked
                  value:
                    message: This is a system control account mapped in your accounting
                      settings (e.g. Accounts Receivable, Inventory Control). Its
                      type is assumed by reports and posting rules and cannot be changed
                      here — re-map the setting to a different account instead.
                    errors:
                      type:
                      - This is a system control account mapped in your accounting
                        settings (e.g. Accounts Receivable, Inventory Control). Its
                        type is assumed by reports and posting rules and cannot be
                        changed here — re-map the setting to a different account instead.
                example-2:
                  summary: 422 — invalid type value
                  value:
                    message: The selected type is invalid.
                    errors:
                      type:
                      - The selected type is invalid.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: put-api-ledger-accounts-nominalcode-type
  /api/ledger/accounts/{nominalCode}/activity-log:
    get:
      tags:
      - Ledger (Accounting v2)
      summary: Get Ledger Account Activity Log
      description: 'Returns a paginated audit trail for a single general-ledger account,
        newest first. Each entry records the event, the affected record, a snapshot
        of changed properties, who made the change, and when. Supports free-text search
        across the actor name, event and properties.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: nominalCode
        in: path
        schema:
          type: integer
        required: true
        description: Ledger (nominal) account ID
        example: '48'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        description:
                          type: string
                        event:
                          type: string
                        subject_type:
                          type: string
                        subject_id:
                          type: integer
                        properties:
                          type: object
                          properties:
                            old:
                              type: object
                              properties:
                                account_type:
                                  type: string
                            attributes:
                              type: object
                              properties:
                                account_type:
                                  type: string
                        causer_name:
                          type: string
                        created_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - id: 771204
                    description: updated
                    event: updated
                    subject_type: NominalCode
                    subject_id: 48
                    properties:
                      old:
                        account_type: asset
                      attributes:
                        account_type: expense
                    causer_name: Jane Accountant
                    created_at: '2026-07-05T09:12:44Z'
                  current_page: 1
                  last_page: 1
                  per_page: 15
                  total: 1
                  from: 1
                  to: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-ledger-accounts-nominalcode-activity-log
  /api/ledger/settings/granularity:
    get:
      tags:
      - Ledger (Accounting v2)
      summary: Get Granularity Matrix
      description: 'Read the type × channel posting granularity matrix stored on the
        accounting connection (— the Cin7-style settings matrix), consumed by BatchGranularityResolver.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Authentication:** Requires Bearer token.


        **Matrix shape:** `{ "<type>": { "default": "<granularity>", "channels": {
        "<integration instance id>": "<granularity>" } } }` where granularity is one
        of:

        - `off` — the type generates no synced accounting output for the channel

        - `per_document` — every source document syncs as its own journal entry

        - `daily` — documents aggregate into one batch per local day

        - `monthly` — documents aggregate into one batch per local month


        An empty object means no overrides are stored — legacy per-type defaults apply.
        Also returns `connection_id` — the accounting connection the matrix lives
        on.


        Returns 404 when no accounting connection is configured.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      granularity_matrix:
                        type: object
                        properties:
                          sales_order_invoice:
                            type: object
                            properties:
                              default:
                                type: string
                              channels:
                                type: object
                                properties:
                                  '5':
                                    type: string
                                  '8':
                                    type: string
                          sales_order_fulfillment:
                            type: object
                            properties:
                              default:
                                type: string
                          fba_shipments:
                            type: object
                            properties:
                              default:
                                type: string
                              channels:
                                type: object
                                properties:
                                  '8':
                                    type: string
                          inventory_adjustment:
                            type: object
                            properties:
                              default:
                                type: string
                      connection_id:
                        type: integer
                example:
                  data:
                    granularity_matrix:
                      sales_order_invoice:
                        default: per_document
                        channels:
                          '5': daily
                          '8': 'off'
                      sales_order_fulfillment:
                        default: 'off'
                      fba_shipments:
                        default: monthly
                        channels:
                          '8': monthly
                      inventory_adjustment:
                        default: per_document
                    connection_id: 3
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No accounting connection is configured.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-ledger-settings-granularity
    put:
      tags:
      - Ledger (Accounting v2)
      summary: Update Granularity Matrix
      description: 'Validate, clamp and persist the type × channel granularity matrix.
        Returns the matrix AS SAVED — the client must re-render from the response
        because of the server-side clamp.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Authentication:** Requires Bearer token.


        **Request body fields:**

        - `matrix` (present, object) — MAY be an empty object `{}`: an empty matrix
        clears all stored overrides back to the legacy per-type defaults

        - `matrix.<type>` (object) — keyed by AccountingTransactionTypeEnum value
        (e.g. sales_order_invoice, fba_shipments); unknown types are rejected

        - `matrix.<type>.default` (required, string) — `off` | `per_document` | `daily`
        | `monthly`

        - `matrix.<type>.channels` (optional, object) — per-channel overrides keyed
        by EXISTING integration instance ID (string keys); unknown IDs are rejected

        - `matrix.<type>.channels.<id>` (string) — `off` | `per_document` | `daily`
        | `monthly`


        **Server-side FBA clamp:** FBA monthly-only types (fba_adjustments, fba_customer_returns,
        fba_receipts, fba_shipments, fba_vendor_returns, fba_warehouse_transfers,
        amazon_pending_inbound_shipment) are clamped server-side — `daily` / `per_document`
        become `monthly`; `off` survives. The clamp is never trusted to the client.


        **Validation errors (422):** unknown type key, invalid granularity value,
        non-object type/channels config, or non-existent channel integration instance
        ID — all reported under the `matrix` key.


        Returns 404 when no accounting connection is configured.


        Permission: requires `accounting.manage_settings` (granular permissions; admins
        bypass; unenforced when the tenant''s granular_permissions feature flag is
        off). Returns 403 without it.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                matrix:
                  type: object
                  properties:
                    sales_order_invoice:
                      type: object
                      properties:
                        default:
                          type: string
                        channels:
                          type: object
                          properties:
                            '5':
                              type: string
                            '8':
                              type: string
                    sales_order_fulfillment:
                      type: object
                      properties:
                        default:
                          type: string
                    fba_shipments:
                      type: object
                      properties:
                        default:
                          type: string
                        channels:
                          type: object
                          properties:
                            '8':
                              type: string
                    inventory_adjustment:
                      type: object
                      properties:
                        default:
                          type: string
              example:
                matrix:
                  sales_order_invoice:
                    default: per_document
                    channels:
                      '5': daily
                      '8': 'off'
                  sales_order_fulfillment:
                    default: 'off'
                  fba_shipments:
                    default: monthly
                    channels:
                      '8': monthly
                  inventory_adjustment:
                    default: per_document
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      granularity_matrix:
                        type: object
                        properties:
                          sales_order_invoice:
                            type: object
                            properties:
                              default:
                                type: string
                              channels:
                                type: object
                                properties:
                                  '5':
                                    type: string
                                  '8':
                                    type: string
                          sales_order_fulfillment:
                            type: object
                            properties:
                              default:
                                type: string
                          fba_shipments:
                            type: object
                            properties:
                              default:
                                type: string
                              channels:
                                type: object
                                properties:
                                  '8':
                                    type: string
                          inventory_adjustment:
                            type: object
                            properties:
                              default:
                                type: string
                  message:
                    type: string
                example:
                  data:
                    granularity_matrix:
                      sales_order_invoice:
                        default: per_document
                        channels:
                          '5': daily
                          '8': 'off'
                      sales_order_fulfillment:
                        default: 'off'
                      fba_shipments:
                        default: monthly
                        channels:
                          '8': monthly
                      inventory_adjustment:
                        default: per_document
                  message: Granularity settings saved.
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No accounting connection is configured.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      matrix:
                        type: array
                        items:
                          type: string
                example:
                  message: Unknown accounting transaction type 'bogus_type'.
                  errors:
                    matrix:
                    - Unknown accounting transaction type 'bogus_type'.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: put-api-ledger-settings-granularity
  /api/ledger/settings/generation:
    get:
      tags:
      - Ledger (Accounting v2)
      summary: Get Generation Status
      description: 'Effective state of the ledger-generation kill switch plus outbox
        health (the Settings → Generation card).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Authentication:** Requires Bearer token.


        **Response fields:**

        - `enabled` — the EFFECTIVE state: tenant switch OR the environment override

        - `tenant_enabled` — the per-tenant switch (`AccountingSettings::$ledger_generation_enabled`)

        - `environment_override` — the `LEDGER_GENERATION_ENABLED` env flag; when
        true, generation runs for every tenant on the install regardless of the tenant
        switch

        - `generate_purchase_order_transactions` — per-tenant opt-in (`AccountingSettings::$generate_purchase_order_transactions`,
        default false) for the non-posting PURCHASE_ORDER commitment entry; off by
        default — when true a PURCHASE_ORDER commitment entry is generated per PO,
        when false (the default) the PURCHASE_ORDER posting rule returns null so no
        PO entries are generated (existing ones are left untouched)

        - `outbox.pending` — document changes waiting to be turned into ledger entries

        - `outbox.failed` — outbox rows that exhausted their retry budget (terminal)

        - `outbox.last_processed_at` — last time the generation worker completed a
        row (null = never)

        - `schedule.next_generation_run_at` — UTC datetime of the next per-minute
        outbox drain run

        - `schedule.next_reconcile_run_at` — UTC datetime of the next daily reconciliation
        sweep'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      generation:
                        type: object
                        properties:
                          enabled:
                            type: boolean
                          tenant_enabled:
                            type: boolean
                          environment_override:
                            type: boolean
                          generate_purchase_order_transactions:
                            type: boolean
                          outbox:
                            type: object
                            properties:
                              pending:
                                type: integer
                              failed:
                                type: integer
                              last_processed_at:
                                type: string
                          schedule:
                            type: object
                            properties:
                              next_generation_run_at:
                                type: string
                              next_reconcile_run_at:
                                type: string
                  status:
                    type: string
                example:
                  data:
                    generation:
                      enabled: true
                      tenant_enabled: true
                      environment_override: false
                      generate_purchase_order_transactions: true
                      outbox:
                        pending: 3
                        failed: 0
                        last_processed_at: '2026-06-12 02:31:32'
                      schedule:
                        next_generation_run_at: '2026-06-12 20:21:00'
                        next_reconcile_run_at: '2026-06-13 00:00:00'
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-ledger-settings-generation
    put:
      tags:
      - Ledger (Accounting v2)
      summary: Update Generation Switch
      description: 'Flip the per-tenant generation kill switch (`AccountingSettings::$ledger_generation_enabled`)
        and return the refreshed status.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Authentication:** Requires Bearer token + `accounting.manage_settings` permission
        (403 without it).


        **Request body:**

        - `enabled` (boolean, required) — whether this tenant generates accounting
        entries

        - `generate_purchase_order_transactions` (boolean, optional) — per-tenant
        opt-in for the non-posting PURCHASE_ORDER commitment entry (`AccountingSettings::$generate_purchase_order_transactions`,
        default false). Off by default. Omit to leave it unchanged; set true to opt
        in so a PURCHASE_ORDER commitment entry is generated per PO. When false (the
        default) the PURCHASE_ORDER posting rule returns null and no PO entries are
        generated (existing ones are left untouched).


        **Note:** the `LEDGER_GENERATION_ENABLED` environment override is not writable
        from the API — disabling the tenant switch while the override is on leaves
        generation effectively running, which the response surfaces via `environment_override`.

        - `schedule.next_generation_run_at` — UTC datetime of the next per-minute
        outbox drain run

        - `schedule.next_reconcile_run_at` — UTC datetime of the next daily reconciliation
        sweep'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                enabled:
                  type: boolean
                generate_purchase_order_transactions:
                  type: boolean
              example:
                enabled: true
                generate_purchase_order_transactions: true
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      generation:
                        type: object
                        properties:
                          enabled:
                            type: boolean
                          tenant_enabled:
                            type: boolean
                          environment_override:
                            type: boolean
                          generate_purchase_order_transactions:
                            type: boolean
                          outbox:
                            type: object
                            properties:
                              pending:
                                type: integer
                              failed:
                                type: integer
                              last_processed_at:
                                type: string
                          schedule:
                            type: object
                            properties:
                              next_generation_run_at:
                                type: string
                              next_reconcile_run_at:
                                type: string
                  status:
                    type: string
                example:
                  data:
                    generation:
                      enabled: true
                      tenant_enabled: true
                      environment_override: false
                      generate_purchase_order_transactions: true
                      outbox:
                        pending: 3
                        failed: 0
                        last_processed_at: '2026-06-12 02:31:32'
                      schedule:
                        next_generation_run_at: '2026-06-12 20:21:00'
                        next_reconcile_run_at: '2026-06-13 00:00:00'
                  status: success
        '422':
          description: Unprocessable Content
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      enabled:
                        type: array
                        items:
                          type: string
                example:
                  message: The enabled field must be true or false.
                  errors:
                    enabled:
                    - The enabled field must be true or false.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: put-api-ledger-settings-generation
  /api/ledger/connections:
    get:
      tags:
      - Ledger (Accounting v2)
      summary: List Connections
      description: 'The connections panel view-model: one row per supported accounting
        integration instance (QuickBooks Online / Xero).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Authentication:** Requires Bearer token.


        **Per-connection fields:**

        - `id` / `provider` (`qbo` | `xero`) / `name`

        - `health.sync_status` — the connection''s sync status value; `health.paused`
        — true when sync is not active

        - `lock_date` — the imported provider books-closed lock date (Y-m-d), or null

        - `rate_budget_remaining` — Xero only: the remaining daily API budget from
        the X-DayLimit-Remaining header; null for QBO (no daily budget)

        - `last_inbound_event_at` — when the last inbound (webhook/CDC) event arrived,
        or null

        - `open_operations` — open sync-operation counts keyed by state (pending,
        queued, in_flight, failed_retryable, needs_action); empty object when no open
        work

        - `capabilities` — per-provider feature flags used to show/hide reconciliation
        lanes: `supports_trial_balance` (Starting Balances lane — true for both Xero
        and QuickBooks Online), `supports_bank_statement_lines` (Statement Match lane
        — Xero only), `supports_webhooks` (inbound change events — Xero only)'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      connections:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            provider:
                              type: string
                            name:
                              type: string
                            health:
                              type: object
                              properties:
                                sync_status:
                                  type: string
                                paused:
                                  type: boolean
                            lock_date:
                              type: string
                            rate_budget_remaining:
                              type: string
                              nullable: true
                            last_inbound_event_at:
                              type: string
                            open_operations:
                              type: object
                              properties:
                                pending:
                                  type: integer
                                queued:
                                  type: integer
                                in_flight:
                                  type: integer
                                needs_action:
                                  type: integer
                                failed_retryable:
                                  type: integer
                            capabilities:
                              type: object
                              properties:
                                supports_trial_balance:
                                  type: boolean
                                supports_bank_statement_lines:
                                  type: boolean
                                supports_webhooks:
                                  type: boolean
                example:
                  data:
                    connections:
                    - id: 3
                      provider: qbo
                      name: QuickBooks Online
                      health:
                        sync_status: active
                        paused: false
                      lock_date: '2026-04-30'
                      rate_budget_remaining: null
                      last_inbound_event_at: '2026-06-10T18:42:11+00:00'
                      open_operations:
                        pending: 4
                        queued: 2
                        in_flight: 1
                        needs_action: 3
                        failed_retryable: 1
                      capabilities:
                        supports_trial_balance: true
                        supports_bank_statement_lines: false
                        supports_webhooks: false
                    - id: 7
                      provider: xero
                      name: Xero AU
                      health:
                        sync_status: paused
                        paused: true
                      lock_date: '2026-03-31'
                      rate_budget_remaining: 4120
                      last_inbound_event_at: '2026-06-09T02:15:40+00:00'
                      open_operations: {}
                      capabilities:
                        supports_trial_balance: true
                        supports_bank_statement_lines: true
                        supports_webhooks: true
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-ledger-connections
  /api/ledger/setup/status:
    get:
      tags:
      - Ledger (Accounting v2)
      summary: Get Setup Status
      description: 'Accounting setup wizard state: which steps are done and what''s
        left.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Authentication:** Requires Bearer token.


        Returns `generation_enabled` (the per-tenant on/off switch), `has_chart` +
        `chart_count` (does a chart of accounts exist), `accounting_integration` ({provider:xero|qbo,
        name} or null), and `required_mappings` — the step 2 role list (`role`, `label`,
        `category` plus the default `code`/`name`/`type`), and `suggested_accounts`
        — the step 1 chart of accounts, each `code` defined once (`code`, `name`,
        `type`). Manual setup is two steps: edit the accounts, then map each role
        to one of them. Several roles can share an account. `warehouses` lists the
        stock-holding warehouses, for the optional step that gives a warehouse its
        own inventory account.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      setup:
                        type: object
                        properties:
                          generation_enabled:
                            type: boolean
                          has_chart:
                            type: boolean
                          chart_count:
                            type: integer
                          accounting_integration:
                            type: string
                            nullable: true
                          suggested_accounts:
                            type: array
                            items:
                              type: object
                              properties:
                                code:
                                  type: string
                                name:
                                  type: string
                                type:
                                  type: string
                          required_mappings:
                            type: array
                            items:
                              type: object
                              properties:
                                role:
                                  type: string
                                label:
                                  type: string
                                category:
                                  type: string
                                code:
                                  type: string
                                name:
                                  type: string
                                type:
                                  type: string
                          warehouses:
                            type: array
                            items:
                              type: object
                              properties:
                                id:
                                  type: integer
                                name:
                                  type: string
                                type:
                                  type: string
                  status:
                    type: string
                example:
                  data:
                    setup:
                      generation_enabled: false
                      has_chart: false
                      chart_count: 0
                      accounting_integration: null
                      suggested_accounts:
                      - code: '4000'
                        name: Sales
                        type: Sales
                      - code: '5000'
                        name: Cost of Goods Sold
                        type: Directcosts
                      - code: '2100'
                        name: Accrued Purchases
                        type: Currliab
                      - code: '6900'
                        name: Rounding
                        type: Expense
                      required_mappings:
                      - role: sales_orders
                        label: Revenue recognised when you invoice a sales order.
                        category: Sales & revenue
                        code: '4000'
                        name: Sales
                        type: Sales
                      - role: shipping_sales_orders
                        label: Shipping revenue charged to customers on sales orders.
                        category: Sales & revenue
                        code: '4000'
                        name: Sales
                        type: Sales
                      - role: cogs
                        label: The inventory cost of items shipped — your cost of
                          goods sold.
                        category: Cost of goods sold
                        code: '5000'
                        name: Cost of Goods Sold
                        type: Directcosts
                      warehouses:
                      - id: 1
                        name: Main Warehouse
                        type: direct
                      - id: 2
                        name: West Coast 3PL
                        type: 3pl
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-ledger-setup-status
  /api/ledger/setup/apply-suggested-chart:
    post:
      tags:
      - Ledger (Accounting v2)
      summary: Apply Suggested Chart
      description: 'Manual accounting setup in two parts: create the chart of accounts,
        then wire each NominalCodeMappingSettings role to one of those accounts. Gated
        by the `accounting.manage_settings` permission.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Body (both optional, sent together — omit both to apply SKU''s default chart
        + assignments):**

        - `accounts` — the chart of accounts. Each: `code` (string), `name` (string),
        `type` (one of: Revenue, Expense, Asset, Liability, Equity, Bank, Current,
        Inventory, Fixed, Directcosts, Currliab, Termliab, Sales). Codes must be unique.

        - `assignments` — a `role` → account `code` map. Keys are NominalCodeMappingSettings
        roles (e.g. `sales_orders`, `cogs`, `inventory_control`, `accounts_payable`);
        each value is one of the account codes above. Several roles may share a code
        (e.g. `sales_orders` + `shipping_sales_orders` both on `4000`).

        - `warehouse_inventory_accounts` (optional) — a warehouse id → account `code`
        map giving a warehouse its own inventory account (posting resolves the inventory
        account per warehouse). Each code must be one of the accounts above; unknown
        warehouses are skipped.


        Only allowed when the tenant has NO chart yet — otherwise 422 on `accounts`.
        Every assignment must reference an account in `accounts`, else 422 on `assignments`;
        a warehouse mapped to a missing code is 422 on `warehouse_inventory_accounts`.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                accounts:
                  type: array
                  items:
                    type: object
                    properties:
                      code:
                        type: string
                      name:
                        type: string
                      type:
                        type: string
                assignments:
                  type: object
                  properties:
                    inventory_control:
                      type: string
                    sales_orders:
                      type: string
                    shipping_sales_orders:
                      type: string
                    cogs:
                      type: string
                warehouse_inventory_accounts:
                  type: object
                  properties:
                    '12':
                      type: string
              example:
                accounts:
                - code: '1000'
                  name: Inventory Control
                  type: Current
                - code: '4000'
                  name: Sales
                  type: Sales
                - code: '5000'
                  name: Cost of Goods Sold
                  type: Directcosts
                assignments:
                  inventory_control: '1000'
                  sales_orders: '4000'
                  shipping_sales_orders: '4000'
                  cogs: '5000'
                warehouse_inventory_accounts:
                  '12': '1000'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      result:
                        type: object
                        properties:
                          created:
                            type: integer
                          chart_count:
                            type: integer
                  message:
                    type: string
                  status:
                    type: string
                example:
                  data:
                    result:
                      created: 14
                      chart_count: 14
                  message: Chart of accounts created — 14 accounts added.
                  status: success
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 422 — a chart already exists
                  value:
                    message: This tenant already has a chart of accounts. Edit accounts
                      in Settings or import a provider chart instead.
                    errors:
                      accounts:
                      - This tenant already has a chart of accounts. Edit accounts
                        in Settings or import a provider chart instead.
                example-1:
                  summary: 422 — invalid account type
                  value:
                    message: The selected accounts.0.type is invalid.
                    errors:
                      accounts.0.type:
                      - The selected accounts.0.type is invalid.
                example-2:
                  summary: 422 — assignment references an unknown account
                  value:
                    message: Role "cogs" is mapped to account "9999", which isn't
                      in the chart of accounts.
                    errors:
                      assignments:
                      - Role "cogs" is mapped to account "9999", which isn't in the
                        chart of accounts.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-ledger-setup-apply-suggested-chart
  /api/ledger/accounting-dimensions:
    get:
      tags:
      - Ledger (Accounting v2)
      summary: Get Accounting Dimensions
      description: 'Read the tracking-category (Xero) / class (QBO) settings for the
        accounting connection: the active provider, its dimension capabilities, the
        mirrored tracking categories/options (or classes) available to map, the sales
        channels (including a synthetic "SKU.io (internal)" pseudo-channel for internal
        orders), and the saved per-channel slot configuration. Used to build P&L segmentation
        such as COGS by sales channel.


        **Authentication:** Requires Bearer token.


        Returns 404 when no accounting connection is configured. For QBO the `capabilities`
        object also carries `class_tracking_enabled`, `class_tracking_per_line`, and
        `plan_supports_classes`.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      connection_id:
                        type: integer
                      provider:
                        type: string
                      capabilities:
                        type: object
                        properties:
                          max_slots:
                            type: integer
                          dimension_types:
                            type: array
                            items:
                              type: string
                          class_tracking_enabled:
                            type: string
                            nullable: true
                          class_tracking_per_line:
                            type: string
                            nullable: true
                          plan_supports_classes:
                            type: string
                            nullable: true
                          write_scope_available:
                            type: boolean
                          warnings:
                            type: array
                      dimensions:
                        type: array
                        items:
                          type: object
                          properties:
                            mirror_id:
                              type: integer
                            name:
                              type: string
                            status:
                              type: string
                            values:
                              type: array
                              items:
                                type: object
                                properties:
                                  mirror_id:
                                    type: integer
                                  name:
                                    type: string
                                  status:
                                    type: string
                      channels:
                        type: array
                        items:
                          type: object
                          properties:
                            instance_id:
                              type: integer
                            name:
                              type: string
                            sub_channels:
                              type: array
                              items:
                                type: object
                                properties:
                                  id:
                                    type: integer
                                  name:
                                    type: string
                      config:
                        type: object
                        properties:
                          slots:
                            type: array
                            items:
                              type: object
                              properties:
                                slot:
                                  type: integer
                                provider_dimension:
                                  type: object
                                  properties:
                                    type:
                                      type: string
                                    mirror_id:
                                      type: integer
                                driver:
                                  type: string
                                apply_to:
                                  type: object
                                  properties:
                                    revenue:
                                      type: boolean
                                    cogs:
                                      type: boolean
                                    fba:
                                      type: boolean
                                default_value_mirror_id:
                                  type: string
                                  nullable: true
                                mappings:
                                  type: array
                                  items:
                                    type: object
                                    properties:
                                      channel_instance_id:
                                        type: integer
                                      value_mirror_id:
                                        type: integer
                                      sub_channel_overrides:
                                        type: object
                                        properties:
                                          '12':
                                            type: integer
                      warnings:
                        type: array
                        items:
                          type: object
                          properties:
                            slot:
                              type: integer
                            type:
                              type: string
                            count:
                              type: integer
                example:
                  data:
                    connection_id: 7
                    provider: xero
                    capabilities:
                      max_slots: 2
                      dimension_types:
                      - xero_tracking_category
                      class_tracking_enabled: null
                      class_tracking_per_line: null
                      plan_supports_classes: null
                      write_scope_available: true
                      warnings: []
                    dimensions:
                    - mirror_id: 12
                      name: Sales Channel
                      status: ACTIVE
                      values:
                      - mirror_id: 33
                        name: Amazon US
                        status: ACTIVE
                      - mirror_id: 34
                        name: Shopify
                        status: ACTIVE
                    channels:
                    - instance_id: 5
                      name: Amazon US
                      sub_channels:
                      - id: 12
                        name: amazon.com
                    - instance_id: null
                      name: SKU.io (internal)
                      sub_channels: []
                    config:
                      slots:
                      - slot: 1
                        provider_dimension:
                          type: xero_tracking_category
                          mirror_id: 12
                        driver: sales_channel
                        apply_to:
                          revenue: true
                          cogs: true
                          fba: true
                        default_value_mirror_id: null
                        mappings:
                        - channel_instance_id: 5
                          value_mirror_id: 33
                          sub_channel_overrides:
                            '12': 34
                    warnings:
                    - slot: 1
                      type: unmapped_channels
                      count: 1
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-ledger-accounting-dimensions
    put:
      tags:
      - Ledger (Accounting v2)
      summary: Update Accounting Dimensions
      description: 'Save the per-channel slot configuration. Up to two dimension slots
        are allowed; each slot must reference a distinct provider dimension (a 422
        is returned otherwise).


        **Authentication:** Requires Bearer token.


        **Slot fields:**

        - `slot` — 1 or 2

        - `provider_dimension.type` — `xero_tracking_category` or `qbo_class`

        - `provider_dimension.mirror_id` — the local id of the chosen dimension

        - `driver` — `sales_channel`

        - `apply_to` — object with `revenue`, `cogs`, `fba` booleans (which document
        families are tagged)

        - `default_value_mirror_id` — fallback value id applied to unmapped channels
        (null to leave them untagged)

        - `mappings[]` — one row per channel: `channel_instance_id` (null for the
        internal pseudo-channel), `value_mirror_id`, and optional `sub_channel_overrides`
        keyed by sub-channel id


        Returns the saved configuration with recomputed warnings.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                slots:
                  type: array
                  items:
                    type: object
                    properties:
                      slot:
                        type: integer
                      provider_dimension:
                        type: object
                        properties:
                          type:
                            type: string
                          mirror_id:
                            type: integer
                      driver:
                        type: string
                      apply_to:
                        type: object
                        properties:
                          revenue:
                            type: boolean
                          cogs:
                            type: boolean
                          fba:
                            type: boolean
                      default_value_mirror_id:
                        type: string
                        nullable: true
                      mappings:
                        type: array
                        items:
                          type: object
                          properties:
                            channel_instance_id:
                              type: integer
                            value_mirror_id:
                              type: integer
                            sub_channel_overrides:
                              type: object
                              properties: {}
              example:
                slots:
                - slot: 1
                  provider_dimension:
                    type: xero_tracking_category
                    mirror_id: 12
                  driver: sales_channel
                  apply_to:
                    revenue: true
                    cogs: true
                    fba: true
                  default_value_mirror_id: null
                  mappings:
                  - channel_instance_id: 5
                    value_mirror_id: 33
                    sub_channel_overrides: {}
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      provider:
                        type: string
                      capabilities:
                        type: object
                        properties:
                          max_slots:
                            type: integer
                          dimension_types:
                            type: array
                            items:
                              type: string
                          class_tracking_enabled:
                            type: string
                            nullable: true
                          class_tracking_per_line:
                            type: string
                            nullable: true
                          plan_supports_classes:
                            type: string
                            nullable: true
                          write_scope_available:
                            type: boolean
                          warnings:
                            type: array
                      dimensions:
                        type: array
                        items:
                          type: object
                          properties:
                            mirror_id:
                              type: integer
                            name:
                              type: string
                            status:
                              type: string
                            values:
                              type: array
                              items:
                                type: object
                                properties:
                                  mirror_id:
                                    type: integer
                                  name:
                                    type: string
                                  status:
                                    type: string
                      channels:
                        type: array
                        items:
                          type: object
                          properties:
                            instance_id:
                              type: integer
                            name:
                              type: string
                            sub_channels:
                              type: array
                              items:
                                type: object
                                properties:
                                  id:
                                    type: integer
                                  name:
                                    type: string
                      config:
                        type: object
                        properties:
                          slots:
                            type: array
                            items:
                              type: object
                              properties:
                                slot:
                                  type: integer
                                provider_dimension:
                                  type: object
                                  properties:
                                    type:
                                      type: string
                                    mirror_id:
                                      type: integer
                                driver:
                                  type: string
                                apply_to:
                                  type: object
                                  properties:
                                    revenue:
                                      type: boolean
                                    cogs:
                                      type: boolean
                                    fba:
                                      type: boolean
                                default_value_mirror_id:
                                  type: string
                                  nullable: true
                                mappings:
                                  type: array
                                  items:
                                    type: object
                                    properties:
                                      channel_instance_id:
                                        type: integer
                                      value_mirror_id:
                                        type: integer
                                      sub_channel_overrides:
                                        type: object
                                        properties:
                                          '12':
                                            type: integer
                      warnings:
                        type: array
                        items:
                          type: object
                          properties:
                            slot:
                              type: integer
                            type:
                              type: string
                            count:
                              type: integer
                example:
                  data:
                    provider: xero
                    capabilities:
                      max_slots: 2
                      dimension_types:
                      - xero_tracking_category
                      class_tracking_enabled: null
                      class_tracking_per_line: null
                      plan_supports_classes: null
                      write_scope_available: true
                      warnings: []
                    dimensions:
                    - mirror_id: 12
                      name: Sales Channel
                      status: ACTIVE
                      values:
                      - mirror_id: 33
                        name: Amazon US
                        status: ACTIVE
                      - mirror_id: 34
                        name: Shopify
                        status: ACTIVE
                    channels:
                    - instance_id: 5
                      name: Amazon US
                      sub_channels:
                      - id: 12
                        name: amazon.com
                    - instance_id: null
                      name: SKU.io (internal)
                      sub_channels: []
                    config:
                      slots:
                      - slot: 1
                        provider_dimension:
                          type: xero_tracking_category
                          mirror_id: 12
                        driver: sales_channel
                        apply_to:
                          revenue: true
                          cogs: true
                          fba: true
                        default_value_mirror_id: null
                        mappings:
                        - channel_instance_id: 5
                          value_mirror_id: 33
                          sub_channel_overrides:
                            '12': 34
                    warnings:
                    - slot: 1
                      type: unmapped_channels
                      count: 1
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      slots.1.provider_dimension:
                        type: array
                        items:
                          type: string
                example:
                  message: The given data was invalid.
                  errors:
                    slots.1.provider_dimension:
                    - Each slot must reference a distinct tracking category / dimension.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: put-api-ledger-accounting-dimensions
  /api/ledger/accounting-dimensions/refresh:
    post:
      tags:
      - Ledger (Accounting v2)
      summary: Refresh Accounting Dimensions
      description: 'Re-pull the connected provider''s tracking categories/options
        (Xero) or classes (QBO) into the local mirror, then return the refreshed settings
        payload. Runs synchronously; the datasets are small.


        **Authentication:** Requires Bearer token.


        Returns 502 when the provider could not be reached.'
      requestBody:
        content: {}
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      provider:
                        type: string
                      capabilities:
                        type: object
                        properties:
                          max_slots:
                            type: integer
                          dimension_types:
                            type: array
                            items:
                              type: string
                          class_tracking_enabled:
                            type: string
                            nullable: true
                          class_tracking_per_line:
                            type: string
                            nullable: true
                          plan_supports_classes:
                            type: string
                            nullable: true
                          write_scope_available:
                            type: boolean
                          warnings:
                            type: array
                      dimensions:
                        type: array
                        items:
                          type: object
                          properties:
                            mirror_id:
                              type: integer
                            name:
                              type: string
                            status:
                              type: string
                            values:
                              type: array
                              items:
                                type: object
                                properties:
                                  mirror_id:
                                    type: integer
                                  name:
                                    type: string
                                  status:
                                    type: string
                      channels:
                        type: array
                        items:
                          type: object
                          properties:
                            instance_id:
                              type: integer
                            name:
                              type: string
                            sub_channels:
                              type: array
                              items:
                                type: object
                                properties:
                                  id:
                                    type: integer
                                  name:
                                    type: string
                      config:
                        type: object
                        properties:
                          slots:
                            type: array
                            items:
                              type: object
                              properties:
                                slot:
                                  type: integer
                                provider_dimension:
                                  type: object
                                  properties:
                                    type:
                                      type: string
                                    mirror_id:
                                      type: integer
                                driver:
                                  type: string
                                apply_to:
                                  type: object
                                  properties:
                                    revenue:
                                      type: boolean
                                    cogs:
                                      type: boolean
                                    fba:
                                      type: boolean
                                default_value_mirror_id:
                                  type: string
                                  nullable: true
                                mappings:
                                  type: array
                                  items:
                                    type: object
                                    properties:
                                      channel_instance_id:
                                        type: integer
                                      value_mirror_id:
                                        type: integer
                                      sub_channel_overrides:
                                        type: object
                                        properties:
                                          '12':
                                            type: integer
                      warnings:
                        type: array
                        items:
                          type: object
                          properties:
                            slot:
                              type: integer
                            type:
                              type: string
                            count:
                              type: integer
                example:
                  data:
                    provider: xero
                    capabilities:
                      max_slots: 2
                      dimension_types:
                      - xero_tracking_category
                      class_tracking_enabled: null
                      class_tracking_per_line: null
                      plan_supports_classes: null
                      write_scope_available: true
                      warnings: []
                    dimensions:
                    - mirror_id: 12
                      name: Sales Channel
                      status: ACTIVE
                      values:
                      - mirror_id: 33
                        name: Amazon US
                        status: ACTIVE
                      - mirror_id: 34
                        name: Shopify
                        status: ACTIVE
                    channels:
                    - instance_id: 5
                      name: Amazon US
                      sub_channels:
                      - id: 12
                        name: amazon.com
                    - instance_id: null
                      name: SKU.io (internal)
                      sub_channels: []
                    config:
                      slots:
                      - slot: 1
                        provider_dimension:
                          type: xero_tracking_category
                          mirror_id: 12
                        driver: sales_channel
                        apply_to:
                          revenue: true
                          cogs: true
                          fba: true
                        default_value_mirror_id: null
                        mappings:
                        - channel_instance_id: 5
                          value_mirror_id: 33
                          sub_channel_overrides:
                            '12': 34
                    warnings:
                    - slot: 1
                      type: unmapped_channels
                      count: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-ledger-accounting-dimensions-refresh
  /api/ledger/accounting-dimensions/values:
    post:
      tags:
      - Ledger (Accounting v2)
      summary: Create Accounting Dimension Values
      description: 'Create one or more tracking options (Xero) or classes (QBO) in
        the connected provider and mirror them locally. Names are matched case-insensitively
        against the mirror first, so an existing value is reused instead of duplicated.


        **Authentication:** Requires Bearer token.


        **Body:** `slot` (1 or 2) and `names` (array of value names, each ≤ 100 chars).


        Returns per-name results: `created`, `matched_existing`, and `failed` (each
        failure carries an `error` code such as `qbo_usage_limit` or `missing_scope`
        and a message). Partial success is expected.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                slot:
                  type: integer
                names:
                  type: array
                  items:
                    type: string
              example:
                slot: 1
                names:
                - Amazon US
                - eBay
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      created:
                        type: array
                        items:
                          type: object
                          properties:
                            mirror_id:
                              type: integer
                            name:
                              type: string
                            status:
                              type: string
                      matched_existing:
                        type: array
                        items:
                          type: object
                          properties:
                            mirror_id:
                              type: integer
                            name:
                              type: string
                      failed:
                        type: array
                        items:
                          type: object
                          properties:
                            name:
                              type: string
                            error:
                              type: string
                            message:
                              type: string
                example:
                  data:
                    created:
                    - mirror_id: 41
                      name: Amazon US
                      status: ACTIVE
                    matched_existing:
                    - mirror_id: 33
                      name: eBay
                    failed:
                    - name: Retail
                      error: qbo_usage_limit
                      message: QuickBooks Plus allows 40 combined classes and locations.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-ledger-accounting-dimensions-values
  /api/ledger/accounting-dimensions/dimensions:
    post:
      tags:
      - Ledger (Accounting v2)
      summary: Create Accounting Dimension
      description: 'Create a new Xero tracking category in the connected organisation.
        Only succeeds when a free active category slot is available (Xero allows at
        most two active tracking categories).


        **Authentication:** Requires Bearer token.


        **Body:** `name` (≤ 100 chars).


        When both active category slots are already consumed, returns an `{ error:
        "xero_category_slots_consumed", message }` body.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
              example:
                name: Sales Channel
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 OK — created
                  value:
                    data:
                      mirror_id: 13
                      name: Sales Channel
                      status: ACTIVE
                example-1:
                  summary: 200 OK — slots consumed
                  value:
                    data:
                      error: xero_category_slots_consumed
                      message: This Xero organisation already has 2 active tracking
                        categories.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-ledger-accounting-dimensions-dimensions
  /api/ledger/period-locks:
    get:
      tags:
      - Ledger (Accounting v2)
      summary: Get Lock Dates
      description: 'The accounting lock-date control surface: the effective lock (later
        of your lock date and enforced provider locks), the internal lock with audit
        info, per-connection provider locks + enforcement, and the locked-period policy.


        **Authentication:** Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      period_locks:
                        type: object
                        properties:
                          effective_lock_date:
                            type: string
                          internal:
                            type: object
                            properties:
                              lock_date:
                                type: string
                              note:
                                type: string
                              set_by:
                                type: object
                                properties:
                                  id:
                                    type: integer
                                  name:
                                    type: string
                              set_at:
                                type: string
                          providers:
                            type: array
                            items:
                              type: object
                              properties:
                                connection_id:
                                  type: integer
                                provider:
                                  type: string
                                connection_name:
                                  type: string
                                lock_date:
                                  type: string
                                enforced:
                                  type: boolean
                                imported_at:
                                  type: string
                                suggestable:
                                  type: boolean
                          policy:
                            type: string
                example:
                  data:
                    period_locks:
                      effective_lock_date: '2026-07-31'
                      internal:
                        lock_date: '2026-06-30'
                        note: June close
                        set_by:
                          id: 12
                          name: Jamie Rivera
                        set_at: '2026-07-01T14:03:00+00:00'
                      providers:
                      - connection_id: 30
                        provider: xero
                        connection_name: Xero
                        lock_date: '2026-05-31'
                        enforced: true
                        imported_at: '2026-07-01T06:00:02+00:00'
                        suggestable: false
                      policy: redate
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-ledger-period-locks
  /api/ledger/period-locks/apply-suggestion:
    post:
      tags:
      - Ledger (Accounting v2)
      summary: Apply Provider Lock Suggestion
      description: 'Adopt a connection''s imported provider lock date as the internal
        accounting lock date.


        **Body:** `connection_id` (integer, required).


        Returns the updated lock-date surface; 422 when the connection has no imported
        provider lock or the date precedes the accounting start date.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                connection_id:
                  type: integer
              example:
                connection_id: 30
      parameters: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      period_locks:
                        type: object
                        properties:
                          effective_lock_date:
                            type: string
                          internal:
                            type: object
                            properties:
                              lock_date:
                                type: string
                              note:
                                type: string
                              set_by:
                                type: object
                                properties:
                                  id:
                                    type: integer
                                  name:
                                    type: string
                              set_at:
                                type: string
                          providers:
                            type: array
                            items:
                              type: object
                              properties:
                                connection_id:
                                  type: integer
                                provider:
                                  type: string
                                connection_name:
                                  type: string
                                lock_date:
                                  type: string
                                enforced:
                                  type: boolean
                                imported_at:
                                  type: string
                                suggestable:
                                  type: boolean
                          policy:
                            type: string
                example:
                  data:
                    period_locks:
                      effective_lock_date: '2026-07-31'
                      internal:
                        lock_date: '2026-06-30'
                        note: June close
                        set_by:
                          id: 12
                          name: Jamie Rivera
                        set_at: '2026-07-01T14:03:00+00:00'
                      providers:
                      - connection_id: 30
                        provider: xero
                        connection_name: Xero
                        lock_date: '2026-05-31'
                        enforced: true
                        imported_at: '2026-07-01T06:00:02+00:00'
                        suggestable: false
                      policy: redate
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-ledger-period-locks-apply-suggestion
  /api/ledger/period-locks/provider/{connectionId}:
    patch:
      tags:
      - Ledger (Accounting v2)
      summary: Toggle Provider Lock Enforcement
      description: 'Set whether a connection''s imported provider lock is enforced
        locally.


        **Path:** `connectionId` (integer). **Body:** `enforced` (boolean). Off ⇒
        the provider date is suggestion-only.


        Returns the updated lock-date surface.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                enforced:
                  type: boolean
              example:
                enforced: false
      parameters:
      - name: connectionId
        in: path
        schema:
          type: string
        required: true
        description: The connection ID.
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      period_locks:
                        type: object
                        properties:
                          effective_lock_date:
                            type: string
                          internal:
                            type: object
                            properties:
                              lock_date:
                                type: string
                              note:
                                type: string
                              set_by:
                                type: object
                                properties:
                                  id:
                                    type: integer
                                  name:
                                    type: string
                              set_at:
                                type: string
                          providers:
                            type: array
                            items:
                              type: object
                              properties:
                                connection_id:
                                  type: integer
                                provider:
                                  type: string
                                connection_name:
                                  type: string
                                lock_date:
                                  type: string
                                enforced:
                                  type: boolean
                                imported_at:
                                  type: string
                                suggestable:
                                  type: boolean
                          policy:
                            type: string
                example:
                  data:
                    period_locks:
                      effective_lock_date: '2026-07-31'
                      internal:
                        lock_date: '2026-06-30'
                        note: June close
                        set_by:
                          id: 12
                          name: Jamie Rivera
                        set_at: '2026-07-01T14:03:00+00:00'
                      providers:
                      - connection_id: 30
                        provider: xero
                        connection_name: Xero
                        lock_date: '2026-05-31'
                        enforced: true
                        imported_at: '2026-07-01T06:00:02+00:00'
                        suggestable: false
                      policy: redate
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: patch-api-ledger-period-locks-provider-connectionid
  /api/ledger/opening-balance:
    get:
      tags:
      - Ledger (Accounting v2)
      summary: Get Opening Balance Overview
      description: 'The opening balance is an INTERNAL journal entry seeding each
        GL account''s position as of the tenant''s books-start date — it is NEVER
        synced to the accounting provider (non-bypassable `internal_only` eligibility),
        which already holds these balances. The inventory line is derived from the
        valuation at end of day prior to the Inventory Start Date and snapshotted
        at apply time. Spec: docs/plans/ledger-opening-balance-entry.md.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Authentication:** Requires Bearer token.


        Returns the document (draft or applied) with its lines, the live derived inventory
        figure, drift vs the applied snapshot, the suggested equity account, the prior-history
        double-count warning count, and the effective generation switch.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      opening_balance_overview:
                        type: object
                        properties:
                          opening_balance:
                            type: object
                            properties:
                              id:
                                type: integer
                              as_of_date:
                                type: string
                              currency_code:
                                type: string
                              status:
                                type: string
                              inventory_total:
                                type: string
                              equity_nominal_code:
                                type: object
                                properties:
                                  id:
                                    type: integer
                                  code:
                                    type: string
                                  name:
                                    type: string
                              notes:
                                type: string
                                nullable: true
                              lines:
                                type: array
                                items:
                                  type: object
                                  properties:
                                    id:
                                      type: integer
                                    nominal_code:
                                      type: object
                                      properties:
                                        id:
                                          type: integer
                                        code:
                                          type: string
                                        name:
                                          type: string
                                    direction:
                                      type: string
                                    amount:
                                      type: string
                                    is_inventory_line:
                                      type: boolean
                              entry:
                                type: object
                                properties:
                                  id:
                                    type: integer
                                  reference:
                                    type: string
                                  status:
                                    type: string
                                  total_debit:
                                    type: string
                                  effective_at:
                                    type: string
                          inventory_start_date:
                            type: string
                          derived_inventory_total:
                            type: string
                          inventory_nominal_code:
                            type: object
                            properties:
                              id:
                                type: integer
                              code:
                                type: string
                              name:
                                type: string
                          suggested_equity_nominal_code:
                            type: object
                            properties:
                              id:
                                type: integer
                              code:
                                type: string
                              name:
                                type: string
                          drift:
                            type: string
                            nullable: true
                          prior_history_count:
                            type: integer
                          generation_enabled:
                            type: boolean
                  status:
                    type: string
                example:
                  data:
                    opening_balance_overview:
                      opening_balance:
                        id: 1
                        as_of_date: '2026-01-01'
                        currency_code: USD
                        status: applied
                        inventory_total: '12500.0000'
                        equity_nominal_code:
                          id: 14
                          code: '960'
                          name: Opening Balance Equity
                        notes: null
                        lines:
                        - id: 1
                          nominal_code:
                            id: 6
                            code: '1200'
                            name: Accounts Receivable
                          direction: debit
                          amount: '5000.0000'
                          is_inventory_line: false
                        - id: 2
                          nominal_code:
                            id: 4
                            code: '1000'
                            name: Inventory Control
                          direction: debit
                          amount: '12500.0000'
                          is_inventory_line: true
                        entry:
                          id: 61
                          reference: OB-2026-01-01
                          status: draft
                          total_debit: '17500.0000'
                          effective_at: '2025-12-31T23:59:59+00:00'
                      inventory_start_date: '2026-01-01'
                      derived_inventory_total: '12500.0000'
                      inventory_nominal_code:
                        id: 4
                        code: '1000'
                        name: Inventory Control
                      suggested_equity_nominal_code:
                        id: 14
                        code: '960'
                        name: Opening Balance Equity
                      drift: null
                      prior_history_count: 0
                      generation_enabled: true
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-ledger-opening-balance
    put:
      tags:
      - Ledger (Accounting v2)
      summary: Upsert Opening Balance Draft
      description: 'The opening balance is an INTERNAL journal entry seeding each
        GL account''s position as of the tenant''s books-start date — it is NEVER
        synced to the accounting provider (non-bypassable `internal_only` eligibility),
        which already holds these balances. The inventory line is derived from the
        valuation at end of day prior to the Inventory Start Date and snapshotted
        at apply time. Spec: docs/plans/ledger-opening-balance-entry.md.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Authentication:** Requires Bearer token + `accounting.manage_settings`.


        **Request body:** `as_of_date` (Y-m-d, must equal the Inventory Start Date
        at apply time), optional `equity_nominal_code_id` (balancing account), optional
        `notes`, and `lines[]` of `{nominal_code_id, direction: debit|credit, amount
        > 0}` — accounts must be unique; the inventory account is system-managed and
        may not appear. 422 once the document is applied (delete and recreate, or
        rebuild).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                as_of_date:
                  type: string
                equity_nominal_code_id:
                  type: integer
                notes:
                  type: string
                  nullable: true
                lines:
                  type: array
                  items:
                    type: object
                    properties:
                      nominal_code_id:
                        type: integer
                      direction:
                        type: string
                      amount:
                        type: string
              example:
                as_of_date: '2026-01-01'
                equity_nominal_code_id: 14
                notes: null
                lines:
                - nominal_code_id: 6
                  direction: debit
                  amount: '5000.0000'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      opening_balance_overview:
                        type: object
                        properties:
                          opening_balance:
                            type: object
                            properties:
                              id:
                                type: integer
                              as_of_date:
                                type: string
                              currency_code:
                                type: string
                              status:
                                type: string
                              inventory_total:
                                type: string
                              equity_nominal_code:
                                type: object
                                properties:
                                  id:
                                    type: integer
                                  code:
                                    type: string
                                  name:
                                    type: string
                              notes:
                                type: string
                                nullable: true
                              lines:
                                type: array
                                items:
                                  type: object
                                  properties:
                                    id:
                                      type: integer
                                    nominal_code:
                                      type: object
                                      properties:
                                        id:
                                          type: integer
                                        code:
                                          type: string
                                        name:
                                          type: string
                                    direction:
                                      type: string
                                    amount:
                                      type: string
                                    is_inventory_line:
                                      type: boolean
                              entry:
                                type: object
                                properties:
                                  id:
                                    type: integer
                                  reference:
                                    type: string
                                  status:
                                    type: string
                                  total_debit:
                                    type: string
                                  effective_at:
                                    type: string
                          inventory_start_date:
                            type: string
                          derived_inventory_total:
                            type: string
                          inventory_nominal_code:
                            type: object
                            properties:
                              id:
                                type: integer
                              code:
                                type: string
                              name:
                                type: string
                          suggested_equity_nominal_code:
                            type: object
                            properties:
                              id:
                                type: integer
                              code:
                                type: string
                              name:
                                type: string
                          drift:
                            type: string
                            nullable: true
                          prior_history_count:
                            type: integer
                          generation_enabled:
                            type: boolean
                  status:
                    type: string
                example:
                  data:
                    opening_balance_overview:
                      opening_balance:
                        id: 1
                        as_of_date: '2026-01-01'
                        currency_code: USD
                        status: applied
                        inventory_total: '12500.0000'
                        equity_nominal_code:
                          id: 14
                          code: '960'
                          name: Opening Balance Equity
                        notes: null
                        lines:
                        - id: 1
                          nominal_code:
                            id: 6
                            code: '1200'
                            name: Accounts Receivable
                          direction: debit
                          amount: '5000.0000'
                          is_inventory_line: false
                        - id: 2
                          nominal_code:
                            id: 4
                            code: '1000'
                            name: Inventory Control
                          direction: debit
                          amount: '12500.0000'
                          is_inventory_line: true
                        entry:
                          id: 61
                          reference: OB-2026-01-01
                          status: draft
                          total_debit: '17500.0000'
                          effective_at: '2025-12-31T23:59:59+00:00'
                      inventory_start_date: '2026-01-01'
                      derived_inventory_total: '12500.0000'
                      inventory_nominal_code:
                        id: 4
                        code: '1000'
                        name: Inventory Control
                      suggested_equity_nominal_code:
                        id: 14
                        code: '960'
                        name: Opening Balance Equity
                      drift: null
                      prior_history_count: 0
                      generation_enabled: true
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: put-api-ledger-opening-balance
    delete:
      tags:
      - Ledger (Accounting v2)
      summary: Delete Opening Balance
      description: 'The opening balance is an INTERNAL journal entry seeding each
        GL account''s position as of the tenant''s books-start date — it is NEVER
        synced to the accounting provider (non-bypassable `internal_only` eligibility),
        which already holds these balances. The inventory line is derived from the
        valuation at end of day prior to the Inventory Start Date and snapshotted
        at apply time. Spec: docs/plans/ledger-opening-balance-entry.md.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Authentication:** Requires Bearer token + `accounting.manage_settings`.


        Removes the document; an applied document''s entry is discarded (drafts) or
        reversed (posted) through the standard source-deleted pathway — the correction
        chain remains auditable.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                  message:
                    type: string
                  status:
                    type: string
                example:
                  data: []
                  message: Opening balance deleted.
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: delete-api-ledger-opening-balance
  /api/ledger/opening-balance/provider-preview:
    get:
      tags:
      - Ledger (Accounting v2)
      summary: Preview Opening Balances from Provider
      description: 'Reads the selected connection''s Trial Balance "as at" the snapshot
        date and proposes opening-balance lines mapped onto SKU''s chart of accounts.
        Works for both QuickBooks Online and Xero connections — the trial balance
        is fetched from whichever provider the connection belongs to. Read-only —
        nothing is persisted; the frontend uses the result to seed the opening-balance
        draft editor, which the user then reviews and applies.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Mapping rules:

        - Each provider account is matched to a SKU nominal code by **code**.

        - The signed provider balance (debit-positive) is split into a `direction`
        (`debit` when ≥ 0, else `credit`) and a positive `amount`.

        - Near-zero balances (|balance| < 0.005) are skipped.

        - The **inventory-control** account is excluded (returned as `skipped_inventory`)
        — SKU derives that opening line from its own valuation, so importing the provider
        figure would double-count it.

        - Provider accounts with no code, or whose code matches no nominal code, are
        returned in `unmatched` so the user can map them and re-fetch.


        **Errors:** returns `422` with a friendly message when the connection''s provider
        cannot produce a trial balance report, and `404` when `connection_id` is not
        a supported accounting connection.


        **Authentication:** Requires Bearer token. (Read-only route — no extra permission
        middleware; the mutating apply/upsert routes enforce `accounting.manage_settings`.)


        **Query parameters:**

        - `connection_id` (integer, required) — the integration instance to read from.

        - `as_of` (date `Y-m-d`, optional) — trial-balance snapshot date; defaults
        to today.


        Each `lines[]` and `unmatched[]` item also carries account metadata from the
        provider''s chart of accounts: `account_class` (normalized bucket: `Asset`,
        `Liability`, `Equity`, `Revenue`, or `Expense`; null when unknown), `account_type`
        (the provider''s own finer account type label, e.g. "Fixed Asset"), and `mirror_account_id`
        (the id of the provider account record in SKU, for linking to its detail view;
        null when the account is not mirrored locally).'
      parameters:
      - name: connection_id
        in: query
        schema:
          type: integer
        description: REQUIRED. Integer ID of the accounting connection (QuickBooks
          Online or Xero) whose trial balance is read.
        example: '12'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      opening_balance_import:
                        type: object
                        properties:
                          connection_id:
                            type: integer
                          as_of:
                            type: string
                          lines:
                            type: array
                            items:
                              type: object
                              properties:
                                nominal_code_id:
                                  type: integer
                                code:
                                  type: string
                                name:
                                  type: string
                                direction:
                                  type: string
                                amount:
                                  type: string
                                provider_account_name:
                                  type: string
                                provider_balance:
                                  type: integer
                          unmatched:
                            type: array
                            items:
                              type: object
                              properties:
                                code:
                                  type: string
                                name:
                                  type: string
                                provider_balance:
                                  type: number
                          skipped_inventory:
                            type: object
                            properties:
                              nominal_code_id:
                                type: integer
                              code:
                                type: string
                              name:
                                type: string
                              direction:
                                type: string
                              amount:
                                type: string
                              provider_account_name:
                                type: string
                              provider_balance:
                                type: integer
                  status:
                    type: string
                example:
                  data:
                    opening_balance_import:
                      connection_id: 12
                      as_of: '2026-01-01'
                      lines:
                      - nominal_code_id: 6
                        code: '1200'
                        name: Accounts Receivable
                        direction: debit
                        amount: '5000.00'
                        provider_account_name: Accounts Receivable (1200)
                        provider_balance: 5000
                      - nominal_code_id: 21
                        code: '2100'
                        name: Accounts Payable
                        direction: credit
                        amount: '3200.50'
                        provider_account_name: Accounts Payable (2100)
                        provider_balance: -3200.5
                      unmatched:
                      - code: '4500'
                        name: Foreign Exchange Gains (4500)
                        provider_balance: -125.75
                      - code: null
                        name: Rounding
                        provider_balance: 0.42
                      skipped_inventory:
                        nominal_code_id: 4
                        code: '1000'
                        name: Inventory Control
                        direction: debit
                        amount: '12500.00'
                        provider_account_name: Inventory Control (1000)
                        provider_balance: 12500
                  status: success
        '422':
          description: Unprocessable Content
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      connection_id:
                        type: array
                        items:
                          type: string
                      as_of:
                        type: array
                        items:
                          type: string
                example:
                  message: The connection id field is required.
                  errors:
                    connection_id:
                    - The connection id field is required.
                    as_of:
                    - The as of does not match the format Y-m-d.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-ledger-opening-balance-provider-preview
  /api/ledger/opening-balance/equity-account:
    post:
      tags:
      - Ledger (Accounting v2)
      summary: Create Opening Balance Equity Account
      description: 'Create the provider-conventional "Opening Balance Equity" account
        when the chart of accounts has none, so the opening-balance form''s balancing-equity
        selector has something to point at. The created account is type `Equity` and
        is a never-synced internal plug. Its `code` is the first free preferred code
        (970, then 3000, then 9999, then numerically incremented past the last candidate),
        checked against ALL codes including archived ones since `code` is the unique
        key.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Authentication:** Requires Bearer token + `accounting.manage_settings`.


        **Idempotent:** if an account whose name contains "opening balance" already
        exists, that existing account is returned and no new account is created.


        No request body. Returns the created (or existing) nominal code as `data.nominal_code`.'
      requestBody:
        content: {}
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      nominal_code:
                        type: object
                        properties:
                          id:
                            type: integer
                          code:
                            type: string
                          name:
                            type: string
                  message:
                    type: string
                  status:
                    type: string
                example:
                  data:
                    nominal_code:
                      id: 14
                      code: '970'
                      name: Opening Balance Equity
                  message: Opening Balance Equity account created.
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-ledger-opening-balance-equity-account
  /api/ledger/opening-balance/apply:
    post:
      tags:
      - Ledger (Accounting v2)
      summary: Apply Opening Balance
      description: 'The opening balance is an INTERNAL journal entry seeding each
        GL account''s position as of the tenant''s books-start date — it is NEVER
        synced to the accounting provider (non-bypassable `internal_only` eligibility),
        which already holds these balances. The inventory line is derived from the
        valuation at end of day prior to the Inventory Start Date and snapshotted
        at apply time. Spec: docs/plans/ledger-opening-balance-entry.md.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Authentication:** Requires Bearer token + `accounting.manage_settings`.


        Validates (as_of_date === Inventory Start Date; equity account present when
        lines don''t balance; Inventory Control mapping set when valuation > 0; generation
        enabled), snapshots the derived inventory figure, and generates the entry
        through the standard outbox pipeline. The computed equity counter-line guarantees
        the entry balances.


        **Errors:** 422 with field-specific messages for each failed precondition.'
      requestBody:
        content: {}
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      opening_balance_overview:
                        type: object
                        properties:
                          opening_balance:
                            type: object
                            properties:
                              id:
                                type: integer
                              as_of_date:
                                type: string
                              currency_code:
                                type: string
                              status:
                                type: string
                              inventory_total:
                                type: string
                              equity_nominal_code:
                                type: object
                                properties:
                                  id:
                                    type: integer
                                  code:
                                    type: string
                                  name:
                                    type: string
                              notes:
                                type: string
                                nullable: true
                              lines:
                                type: array
                                items:
                                  type: object
                                  properties:
                                    id:
                                      type: integer
                                    nominal_code:
                                      type: object
                                      properties:
                                        id:
                                          type: integer
                                        code:
                                          type: string
                                        name:
                                          type: string
                                    direction:
                                      type: string
                                    amount:
                                      type: string
                                    is_inventory_line:
                                      type: boolean
                              entry:
                                type: object
                                properties:
                                  id:
                                    type: integer
                                  reference:
                                    type: string
                                  status:
                                    type: string
                                  total_debit:
                                    type: string
                                  effective_at:
                                    type: string
                          inventory_start_date:
                            type: string
                          derived_inventory_total:
                            type: string
                          inventory_nominal_code:
                            type: object
                            properties:
                              id:
                                type: integer
                              code:
                                type: string
                              name:
                                type: string
                          suggested_equity_nominal_code:
                            type: object
                            properties:
                              id:
                                type: integer
                              code:
                                type: string
                              name:
                                type: string
                          drift:
                            type: string
                            nullable: true
                          prior_history_count:
                            type: integer
                          generation_enabled:
                            type: boolean
                  status:
                    type: string
                example:
                  data:
                    opening_balance_overview:
                      opening_balance:
                        id: 1
                        as_of_date: '2026-01-01'
                        currency_code: USD
                        status: applied
                        inventory_total: '12500.0000'
                        equity_nominal_code:
                          id: 14
                          code: '960'
                          name: Opening Balance Equity
                        notes: null
                        lines:
                        - id: 1
                          nominal_code:
                            id: 6
                            code: '1200'
                            name: Accounts Receivable
                          direction: debit
                          amount: '5000.0000'
                          is_inventory_line: false
                        - id: 2
                          nominal_code:
                            id: 4
                            code: '1000'
                            name: Inventory Control
                          direction: debit
                          amount: '12500.0000'
                          is_inventory_line: true
                        entry:
                          id: 61
                          reference: OB-2026-01-01
                          status: draft
                          total_debit: '17500.0000'
                          effective_at: '2025-12-31T23:59:59+00:00'
                      inventory_start_date: '2026-01-01'
                      derived_inventory_total: '12500.0000'
                      inventory_nominal_code:
                        id: 4
                        code: '1000'
                        name: Inventory Control
                      suggested_equity_nominal_code:
                        id: 14
                        code: '960'
                        name: Opening Balance Equity
                      drift: null
                      prior_history_count: 0
                      generation_enabled: true
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-ledger-opening-balance-apply
  /api/ledger/opening-balance/rebuild:
    post:
      tags:
      - Ledger (Accounting v2)
      summary: Rebuild Opening Balance
      description: 'The opening balance is an INTERNAL journal entry seeding each
        GL account''s position as of the tenant''s books-start date — it is NEVER
        synced to the accounting provider (non-bypassable `internal_only` eligibility),
        which already holds these balances. The inventory line is derived from the
        valuation at end of day prior to the Inventory Start Date and snapshotted
        at apply time. Spec: docs/plans/ledger-opening-balance-entry.md.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Authentication:** Requires Bearer token + `accounting.sync`.


        Re-derives the inventory snapshot and regenerates the entry — an unchanged
        document is a hash no-op; a posted entry is corrected via reversal + replacement.
        Use when the overview reports `drift` (the live valuation moved after a backfill).'
      requestBody:
        content: {}
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      opening_balance_overview:
                        type: object
                        properties:
                          opening_balance:
                            type: object
                            properties:
                              id:
                                type: integer
                              as_of_date:
                                type: string
                              currency_code:
                                type: string
                              status:
                                type: string
                              inventory_total:
                                type: string
                              equity_nominal_code:
                                type: object
                                properties:
                                  id:
                                    type: integer
                                  code:
                                    type: string
                                  name:
                                    type: string
                              notes:
                                type: string
                                nullable: true
                              lines:
                                type: array
                                items:
                                  type: object
                                  properties:
                                    id:
                                      type: integer
                                    nominal_code:
                                      type: object
                                      properties:
                                        id:
                                          type: integer
                                        code:
                                          type: string
                                        name:
                                          type: string
                                    direction:
                                      type: string
                                    amount:
                                      type: string
                                    is_inventory_line:
                                      type: boolean
                              entry:
                                type: object
                                properties:
                                  id:
                                    type: integer
                                  reference:
                                    type: string
                                  status:
                                    type: string
                                  total_debit:
                                    type: string
                                  effective_at:
                                    type: string
                          inventory_start_date:
                            type: string
                          derived_inventory_total:
                            type: string
                          inventory_nominal_code:
                            type: object
                            properties:
                              id:
                                type: integer
                              code:
                                type: string
                              name:
                                type: string
                          suggested_equity_nominal_code:
                            type: object
                            properties:
                              id:
                                type: integer
                              code:
                                type: string
                              name:
                                type: string
                          drift:
                            type: string
                            nullable: true
                          prior_history_count:
                            type: integer
                          generation_enabled:
                            type: boolean
                  status:
                    type: string
                example:
                  data:
                    opening_balance_overview:
                      opening_balance:
                        id: 1
                        as_of_date: '2026-01-01'
                        currency_code: USD
                        status: applied
                        inventory_total: '12500.0000'
                        equity_nominal_code:
                          id: 14
                          code: '960'
                          name: Opening Balance Equity
                        notes: null
                        lines:
                        - id: 1
                          nominal_code:
                            id: 6
                            code: '1200'
                            name: Accounts Receivable
                          direction: debit
                          amount: '5000.0000'
                          is_inventory_line: false
                        - id: 2
                          nominal_code:
                            id: 4
                            code: '1000'
                            name: Inventory Control
                          direction: debit
                          amount: '12500.0000'
                          is_inventory_line: true
                        entry:
                          id: 61
                          reference: OB-2026-01-01
                          status: draft
                          total_debit: '17500.0000'
                          effective_at: '2025-12-31T23:59:59+00:00'
                      inventory_start_date: '2026-01-01'
                      derived_inventory_total: '12500.0000'
                      inventory_nominal_code:
                        id: 4
                        code: '1000'
                        name: Inventory Control
                      suggested_equity_nominal_code:
                        id: 14
                        code: '960'
                        name: Opening Balance Equity
                      drift: null
                      prior_history_count: 0
                      generation_enabled: true
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-ledger-opening-balance-rebuild
  /api/ledger/opening-balance/transition:
    get:
      tags:
      - Ledger (Accounting v2)
      summary: Get Pending Start Date Transition
      description: 'Returns the pending guarded accounting-start-date change awaiting
        confirmation, or `null` under `start_date_transition` when the books are settled
        (no change in flight).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        When an applied opening balance''s effective accounting start date is moved,
        the change is PARKED rather than applied immediately: the old anchor''s books
        are already posted, so the user must explicitly confirm (apply) or abandon
        (rollback). This read-only endpoint surfaces that parked change so the UI
        can render the review banner.


        **Authentication:** Requires Bearer token.


        **Response fields (`start_date_transition`):**

        - `id` — transition row id

        - `status` — `pending` while awaiting confirmation

        - `old_effective_start_date` / `new_effective_start_date` — the effective
        accounting start dates (where the opening entry posts)

        - `old_anchor_date` / `new_anchor_date` — the trial-balance "as at" anchor
        (= effective start − 1 day) that the replacement opening balance is imported
        against

        - `old_opening_total` — the frozen total of the currently-applied opening
        balance

        - `new_opening_total` — the PROJECTED total of the replacement opening balance
        at the new anchor. This is `null` until the replacement trial balance has
        been captured at `new_anchor_date` — a GET preview never forces a metered
        provider capture, so the projection is simply withheld until the async capture
        lands.


        Returns `{ "start_date_transition": null }` when no transition is pending.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 OK — pending transition (projection ready)
                  value:
                    data:
                      start_date_transition:
                        id: 7
                        status: pending
                        old_effective_start_date: '2026-05-01'
                        new_effective_start_date: '2026-06-01'
                        old_anchor_date: '2026-04-30'
                        new_anchor_date: '2026-05-31'
                        old_opening_total: '1234.5600'
                        new_opening_total: '500.0000'
                    status: success
                example-1:
                  summary: 200 OK — pending, projection withheld until TB captured
                  value:
                    data:
                      start_date_transition:
                        id: 7
                        status: pending
                        old_effective_start_date: '2026-05-01'
                        new_effective_start_date: '2026-06-01'
                        old_anchor_date: '2026-04-30'
                        new_anchor_date: '2026-05-31'
                        old_opening_total: '1234.5600'
                        new_opening_total: null
                    status: success
                example-2:
                  summary: 200 OK — no transition pending
                  value:
                    data:
                      start_date_transition: null
                    status: success
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-ledger-opening-balance-transition
  /api/ledger/opening-balance/transition/apply:
    post:
      tags:
      - Ledger (Accounting v2)
      summary: Apply Start Date Transition
      description: 'Confirms the parked accounting-start-date change. The opening
        balance is re-imported IN PLACE from the replacement trial balance at the
        new anchor (the same opening-balance row is kept — preserving its notes, created-by,
        equity account, applied status and history), its entry is reversed and reposted
        through the standard outbox pipeline, and the reconciliation is re-anchored
        + re-backfilled via a tracked Sync Provider GL Journals job.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Authentication:** Requires Bearer token + `accounting.manage_settings`.


        No request body. Applying intentionally permits a metered provider capture
        if the replacement trial balance hasn''t been snapshotted yet (it is a deliberate
        user action). On success the pending transition settles to `applied` and `opening_balance_overview.pending_start_date_transition`
        becomes `null`.


        **Errors:** 422 when there is no pending transition, when no Xero accounting
        connection exists, or when ledger generation is disabled for the tenant.'
      requestBody:
        content: {}
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      opening_balance_overview:
                        type: object
                        properties:
                          opening_balance:
                            type: object
                            properties:
                              id:
                                type: integer
                              as_of_date:
                                type: string
                              currency_code:
                                type: string
                              status:
                                type: string
                              inventory_total:
                                type: string
                              equity_nominal_code:
                                type: object
                                properties:
                                  id:
                                    type: integer
                                  code:
                                    type: string
                                  name:
                                    type: string
                              notes:
                                type: string
                                nullable: true
                              lines:
                                type: array
                                items:
                                  type: object
                                  properties:
                                    id:
                                      type: integer
                                    nominal_code:
                                      type: object
                                      properties:
                                        id:
                                          type: integer
                                        code:
                                          type: string
                                        name:
                                          type: string
                                    direction:
                                      type: string
                                    amount:
                                      type: string
                                    is_inventory_line:
                                      type: boolean
                              entry:
                                type: object
                                properties:
                                  id:
                                    type: integer
                                  reference:
                                    type: string
                                  status:
                                    type: string
                                  total_debit:
                                    type: string
                                  effective_at:
                                    type: string
                          inventory_start_date:
                            type: string
                          derived_inventory_total:
                            type: string
                          inventory_nominal_code:
                            type: object
                            properties:
                              id:
                                type: integer
                              code:
                                type: string
                              name:
                                type: string
                          suggested_equity_nominal_code:
                            type: object
                            properties:
                              id:
                                type: integer
                              code:
                                type: string
                              name:
                                type: string
                          drift:
                            type: string
                            nullable: true
                          prior_history_count:
                            type: integer
                          generation_enabled:
                            type: boolean
                          pending_start_date_transition:
                            type: string
                            nullable: true
                  status:
                    type: string
                example:
                  data:
                    opening_balance_overview:
                      opening_balance:
                        id: 1
                        as_of_date: '2026-05-01'
                        currency_code: USD
                        status: applied
                        inventory_total: '0.0000'
                        equity_nominal_code:
                          id: 14
                          code: '970'
                          name: Opening Balance Equity
                        notes: null
                        lines:
                        - id: 12
                          nominal_code:
                            id: 9
                            code: '4000'
                            name: Sales
                          direction: debit
                          amount: '500.0000'
                          is_inventory_line: false
                        entry:
                          id: 88
                          reference: OB-2026-05-01/R
                          status: draft
                          total_debit: '500.0000'
                          effective_at: '2026-04-30T23:59:59+00:00'
                      inventory_start_date: '2026-05-01'
                      derived_inventory_total: '0.0000'
                      inventory_nominal_code:
                        id: 4
                        code: '1000'
                        name: Inventory Control
                      suggested_equity_nominal_code:
                        id: 14
                        code: '970'
                        name: Opening Balance Equity
                      drift: null
                      prior_history_count: 1
                      generation_enabled: true
                      pending_start_date_transition: null
                  status: success
        '422':
          description: Unprocessable Content
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      transition:
                        type: array
                        items:
                          type: string
                example:
                  message: There is no pending accounting start date change to apply.
                  errors:
                    transition:
                    - There is no pending accounting start date change to apply.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-ledger-opening-balance-transition-apply
  /api/ledger/opening-balance/transition/rollback:
    post:
      tags:
      - Ledger (Accounting v2)
      summary: Rollback Start Date Transition
      description: 'Abandons the parked accounting-start-date change while it is still
        pending. The effective accounting start date is reverted to its old value
        and the transition settles to `cancelled` — the posted books are left completely
        untouched (no reversal, no rebuild, no reconciliation re-anchor). Safe because
        while pending the books were never changed.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        The revert is written directly to settings (not through the Settings endpoint)
        so it does NOT re-trigger the start-date-change hook that would park a fresh
        transition.


        **Authentication:** Requires Bearer token + `accounting.manage_settings`.


        No request body. On success `opening_balance_overview.pending_start_date_transition`
        becomes `null` and the opening balance + its posted entry are unchanged.


        **Errors:** 422 when there is no pending transition to roll back.'
      requestBody:
        content: {}
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      opening_balance_overview:
                        type: object
                        properties:
                          opening_balance:
                            type: object
                            properties:
                              id:
                                type: integer
                              as_of_date:
                                type: string
                              currency_code:
                                type: string
                              status:
                                type: string
                              inventory_total:
                                type: string
                              equity_nominal_code:
                                type: object
                                properties:
                                  id:
                                    type: integer
                                  code:
                                    type: string
                                  name:
                                    type: string
                              notes:
                                type: string
                                nullable: true
                              lines:
                                type: array
                                items:
                                  type: object
                                  properties:
                                    id:
                                      type: integer
                                    nominal_code:
                                      type: object
                                      properties:
                                        id:
                                          type: integer
                                        code:
                                          type: string
                                        name:
                                          type: string
                                    direction:
                                      type: string
                                    amount:
                                      type: string
                                    is_inventory_line:
                                      type: boolean
                              entry:
                                type: object
                                properties:
                                  id:
                                    type: integer
                                  reference:
                                    type: string
                                  status:
                                    type: string
                                  total_debit:
                                    type: string
                                  effective_at:
                                    type: string
                          inventory_start_date:
                            type: string
                          derived_inventory_total:
                            type: string
                          inventory_nominal_code:
                            type: object
                            properties:
                              id:
                                type: integer
                              code:
                                type: string
                              name:
                                type: string
                          suggested_equity_nominal_code:
                            type: object
                            properties:
                              id:
                                type: integer
                              code:
                                type: string
                              name:
                                type: string
                          drift:
                            type: string
                            nullable: true
                          prior_history_count:
                            type: integer
                          generation_enabled:
                            type: boolean
                          pending_start_date_transition:
                            type: string
                            nullable: true
                  status:
                    type: string
                example:
                  data:
                    opening_balance_overview:
                      opening_balance:
                        id: 1
                        as_of_date: '2026-05-01'
                        currency_code: USD
                        status: applied
                        inventory_total: '1234.5600'
                        equity_nominal_code:
                          id: 14
                          code: '970'
                          name: Opening Balance Equity
                        notes: null
                        lines:
                        - id: 3
                          nominal_code:
                            id: 6
                            code: '1200'
                            name: Accounts Receivable
                          direction: debit
                          amount: '1234.5600'
                          is_inventory_line: false
                        entry:
                          id: 61
                          reference: OB-2026-05-01
                          status: posted
                          total_debit: '1234.5600'
                          effective_at: '2026-04-30T23:59:59+00:00'
                      inventory_start_date: '2026-05-01'
                      derived_inventory_total: '1234.5600'
                      inventory_nominal_code:
                        id: 4
                        code: '1000'
                        name: Inventory Control
                      suggested_equity_nominal_code:
                        id: 14
                        code: '970'
                        name: Opening Balance Equity
                      drift: null
                      prior_history_count: 1
                      generation_enabled: true
                      pending_start_date_transition: null
                  status: success
        '422':
          description: Unprocessable Content
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      transition:
                        type: array
                        items:
                          type: string
                example:
                  message: There is no pending accounting start date change to apply.
                  errors:
                    transition:
                    - There is no pending accounting start date change to apply.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-ledger-opening-balance-transition-rollback
  /api/ledger/generation/candidates:
    get:
      tags:
      - Ledger (Accounting v2)
      summary: List Generation Candidates
      description: 'Preview of the source documents eligible to have ledger entries
        generated — the entries page "Generate" modal. A document is a candidate when
        it passes the same readiness gate the legacy generation used (`scopeAccountingReady`:
        drafts, unmapped lines, Amazon channel orders, … are excluded) AND it has
        no current (non-discarded, non-reversed) ledger entry.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Authentication:** Requires Bearer token.


        **Response fields:**

        - `candidates` — Laravel paginator of `{source_type, source_id, type_label,
        reference, url, date}` rows. `url` is the application UI detail route when
        one exists; `date` is the document''s accounting date (Y-m-d). Without `filter[source_type]`
        the listing walks every type in tab (label) order, each type''s rows newest-first.

        - `tabs` — one row per source type that currently has candidates (`{source_type,
        label, count}`), label-sorted — drives the modal''s tab strip

        - `total` — candidate count across all types for the date range

        - `schedule.next_generation_run_at` / `schedule.next_reconcile_run_at` — UTC
        datetimes of the next per-minute drain run and the next daily reconciliation
        sweep (these documents are picked up automatically; a manual run just front-runs
        the schedule)

        - `has_frozen_history` — whether the tenant has any imported (migrated) ledger
        history. When true, imported entries are frozen: scope runs skip them unless
        `include_frozen` is passed to Run Generation Now.

        - `enabled` — the effective generation switch (tenant setting OR environment
        override); when false a run request would be rejected


        **Date filtering** applies to each document''s own accounting date column
        (invoice date, fulfillment date, adjustment date, …), not created_at.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      candidates:
                        type: object
                        properties:
                          current_page:
                            type: integer
                          data:
                            type: array
                            items:
                              type: object
                              properties:
                                source_type:
                                  type: string
                                source_id:
                                  type: integer
                                type_label:
                                  type: string
                                reference:
                                  type: string
                                url:
                                  type: string
                                  nullable: true
                                date:
                                  type: string
                          last_page:
                            type: integer
                          per_page:
                            type: integer
                          total:
                            type: integer
                          from:
                            type: integer
                          to:
                            type: integer
                      tabs:
                        type: array
                        items:
                          type: object
                          properties:
                            source_type:
                              type: string
                            label:
                              type: string
                            count:
                              type: integer
                      total:
                        type: integer
                      schedule:
                        type: object
                        properties:
                          next_generation_run_at:
                            type: string
                          next_reconcile_run_at:
                            type: string
                      enabled:
                        type: boolean
                      has_frozen_history:
                        type: boolean
                  status:
                    type: string
                example:
                  data:
                    candidates:
                      current_page: 1
                      data:
                      - source_type: App\Models\Bill
                        source_id: 4
                        type_label: Bill
                        reference: BILL-1042
                        url: null
                        date: '2026-06-05'
                      - source_type: App\Models\SalesOrderFulfillment
                        source_id: 911
                        type_label: Sales Order Fulfillment
                        reference: SO-2231/F1
                        url: null
                        date: '2026-06-04'
                      last_page: 1
                      per_page: 10
                      total: 2
                      from: 1
                      to: 2
                    tabs:
                    - source_type: App\Models\Bill
                      label: Bill
                      count: 1
                    - source_type: App\Models\SalesOrderFulfillment
                      label: Sales Order Fulfillment
                      count: 1
                    total: 2
                    schedule:
                      next_generation_run_at: '2026-06-12 20:21:00'
                      next_reconcile_run_at: '2026-06-13 00:00:00'
                    enabled: true
                    has_frozen_history: true
                  status: success
        '422':
          description: Unprocessable Content
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      filter.source_type:
                        type: array
                        items:
                          type: string
                example:
                  message: Unknown source type — it must be one of the registered
                    ledger source document types.
                  errors:
                    filter.source_type:
                    - Unknown source type — it must be one of the registered ledger
                      source document types.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-ledger-generation-candidates
  /api/ledger/generation/run:
    post:
      tags:
      - Ledger (Accounting v2)
      summary: Run Generation Now
      description: 'Trigger on-demand entry generation: every candidate in scope (see
        List Generation Candidates) is enqueued as an `updated` ledger outbox row
        and the drain job is dispatched immediately — the SAME pipeline the per-minute
        schedule runs, just started now. The posting service''s source_version_hash
        makes already-current documents a free no-op, so the trigger is idempotent.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Authentication:** Requires Bearer token + `accounting.sync` permission (403
        without it).


        **Request body (all optional):**

        - `candidates` (array|null, max 1000) — explicit selection of documents to
        generate: `[{source_type, source_id}, ...]`. When present, ONLY these are
        enqueued and the type/date scope is ignored (the modal''s multi-select). Each
        `source_type` must be a registered source FQN (422 otherwise).

        - `source_type` (string|null) — restrict to one source document FQN from the
        posting-rule registry; omit/null for all types

        - `date_from` / `date_to` (Y-m-d|null) — restrict by each document''s accounting
        date; `date_to` must be >= `date_from`

        - `include_frozen` (boolean, default false) — scope runs normally skip documents
        dated before the tenant''s accounting cutover (their imported history is frozen
        so it is never rewritten by accident). Set true to deliberately re-derive
        that frozen history with the current posting rules — this replaces the migrated
        figures and can update linked, still-editable provider documents, so treat
        it as a confirmed administrative action. Ignored when `candidates` is present
        (hand-picked documents always regenerate).


        **Errors:** 422 with an `enabled` error when ledger generation is disabled
        for the tenant (enable it under Settings → Generation first); 422 for unknown
        `source_type`.


        **Response:** `data.result.enqueued` is the number of documents processed/enqueued.
        `data.result.skipped_locked_period` counts documents that were skipped because
        they are dated in a locked accounting period — these are not generated (unlock
        the period or change the document date, then try again). A locked-period document
        is reported this way rather than failing the whole run.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                source_type:
                  type: string
                date_from:
                  type: string
                date_to:
                  type: string
                candidates:
                  type: array
                  items:
                    type: object
                    properties:
                      source_type:
                        type: string
                      source_id:
                        type: integer
                include_frozen:
                  type: boolean
              example:
                source_type: App\Models\Bill
                date_from: '2026-06-01'
                date_to: '2026-06-30'
                candidates:
                - source_type: App\Models\Bill
                  source_id: 4
                - source_type: App\Models\SalesOrderFulfillment
                  source_id: 911
                include_frozen: false
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 OK — candidates enqueued
                  value:
                    data:
                      result:
                        enqueued: 2
                        skipped_locked_period: 0
                    message: Enqueued 2 document(s) for generation — entries will
                      appear within the next minute.
                    status: success
                example-1:
                  summary: 200 OK — some candidates skipped (locked period)
                  value:
                    data:
                      result:
                        enqueued: 0
                        skipped_locked_period: 2
                    message: 2 documents could not be generated — each is dated in
                      a locked period. Unlock the period or change their dates, then
                      try again.
                    status: success
        '422':
          description: Unprocessable Content
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      enabled:
                        type: array
                        items:
                          type: string
                example:
                  message: Ledger generation is disabled for this tenant — enable
                    it under Settings → Generation first.
                  errors:
                    enabled:
                    - Ledger generation is disabled for this tenant — enable it under
                      Settings → Generation first.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-ledger-generation-run
  /api/ledger/reconciliation/window:
    get:
      tags:
      - Ledger (Accounting v2)
      summary: Get Reconciliation Window
      description: 'The connection''s reconcile window and per-kind cache freshness
        — "documents cached from X through Y, last refreshed Z".


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Authentication:** Requires Bearer token.


        The window runs from now back to the LATER of the connection''s sync start
        floor and the generation start (earliest current ledger entry). 404 when connection_id
        is not a supported accounting connection.'
      parameters:
      - name: connection_id
        in: query
        schema:
          type: integer
        description: Accounting connection (IntegrationInstance) id. Required.
        example: '5'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      connection_id:
                        type: integer
                      from:
                        type: string
                      to:
                        type: string
                      cache_status:
                        type: array
                        items:
                          type: object
                          properties:
                            remote_type:
                              type: string
                            backfilled_from:
                              type: string
                            backfilled_through:
                              type: string
                            document_count:
                              type: integer
                            last_backfilled_at:
                              type: string
                example:
                  data:
                    connection_id: 5
                    from: '2026-01-01'
                    to: '2026-06-13'
                    cache_status:
                    - remote_type: qbo_invoice
                      backfilled_from: '2026-01-01'
                      backfilled_through: '2026-06-13'
                      document_count: 182
                      last_backfilled_at: '2026-06-12T02:00:00+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-ledger-reconciliation-window
  /api/ledger/reconciliation/matches:
    get:
      tags:
      - Ledger (Accounting v2)
      summary: Reconciliation Matches
      description: 'The three reconcile buckets for a connection over the (optional)
        document-date window.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Authentication:** Requires Bearer token.


        **Buckets:**

        - `matched` — SKU entries linked to a provider document (with the cached remote
        snapshot for variance display)

        - `sku_only` — eligible SKU entries with no link (would create a remote document)

        - `provider_only` — cached provider documents with no link and not dismissed


        `from`/`to` (Y-m-d) override the default window. `meta.counts` carries the
        bucket sizes, including `excluded` (the count of unlinked entries that are
        not eligible to sync — fetched in full via the excluded endpoint). 404 when
        connection_id is not a supported accounting connection.'
      parameters:
      - name: connection_id
        in: query
        schema:
          type: integer
        description: Accounting connection id. Required.
        example: '5'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      matched:
                        type: array
                        items:
                          type: object
                          properties:
                            entry:
                              type: object
                              properties:
                                id:
                                  type: integer
                                uuid:
                                  type: string
                                type:
                                  type: object
                                  properties:
                                    value:
                                      type: string
                                    label:
                                      type: string
                                status:
                                  type: string
                                effective_at:
                                  type: string
                                currency_code:
                                  type: string
                                total_debit:
                                  type: string
                                total_credit:
                                  type: string
                                reference:
                                  type: string
                                reference_suffix:
                                  type: integer
                            link:
                              type: object
                              properties:
                                id:
                                  type: integer
                                provider:
                                  type: string
                                remote_type:
                                  type: string
                                remote_id:
                                  type: string
                                remote_url:
                                  type: string
                                link_state:
                                  type: string
                                remote_status:
                                  type: string
                                last_remote_seen_at:
                                  type: string
                            remote:
                              type: object
                              properties:
                                remote_type:
                                  type: string
                                remote_id:
                                  type: string
                                reference:
                                  type: string
                                total:
                                  type: string
                                currency:
                                  type: string
                                document_date:
                                  type: string
                                status:
                                  type: string
                                remote_url:
                                  type: string
                      sku_only:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            uuid:
                              type: string
                            type:
                              type: object
                              properties:
                                value:
                                  type: string
                                label:
                                  type: string
                            status:
                              type: string
                            effective_at:
                              type: string
                            currency_code:
                              type: string
                            total_debit:
                              type: string
                            total_credit:
                              type: string
                            reference:
                              type: string
                            reference_suffix:
                              type: integer
                      provider_only:
                        type: array
                        items:
                          type: object
                          properties:
                            remote_type:
                              type: string
                            remote_id:
                              type: string
                            reference:
                              type: string
                            total:
                              type: string
                            currency:
                              type: string
                            document_date:
                              type: string
                            status:
                              type: string
                            remote_url:
                              type: string
                  meta:
                    type: object
                    properties:
                      from:
                        type: string
                      to:
                        type: string
                      counts:
                        type: object
                        properties:
                          matched:
                            type: integer
                          sku_only:
                            type: integer
                          provider_only:
                            type: integer
                          excluded:
                            type: integer
                example:
                  data:
                    matched:
                    - entry:
                        id: 4821
                        uuid: 9f1c...
                        type:
                          value: sales_order_invoice
                          label: Sales Order Invoice
                        status: posted
                        effective_at: '2026-06-05T00:00:00+00:00'
                        currency_code: USD
                        total_debit: '250.0000'
                        total_credit: '250.0000'
                        reference: INV-1042
                        reference_suffix: 0
                      link:
                        id: 77
                        provider: qbo
                        remote_type: qbo_invoice
                        remote_id: '145'
                        remote_url: https://app.qbo.intuit.com/app/invoice?txnId=145
                        link_state: linked_current
                        remote_status: Active
                        last_remote_seen_at: '2026-06-12T02:00:00+00:00'
                      remote:
                        remote_type: qbo_invoice
                        remote_id: '145'
                        reference: INV-1042
                        total: '250.0000'
                        currency: USD
                        document_date: '2026-06-05'
                        status: Active
                        remote_url: https://app.qbo.intuit.com/app/invoice?txnId=145
                    sku_only:
                    - id: 4822
                      uuid: 9f1c...
                      type:
                        value: sales_order_invoice
                        label: Sales Order Invoice
                      status: posted
                      effective_at: '2026-06-05T00:00:00+00:00'
                      currency_code: USD
                      total_debit: '250.0000'
                      total_credit: '250.0000'
                      reference: INV-1043
                      reference_suffix: 0
                    provider_only:
                    - remote_type: qbo_invoice
                      remote_id: '146'
                      reference: INV-9001
                      total: '250.0000'
                      currency: USD
                      document_date: '2026-06-05'
                      status: Active
                      remote_url: https://app.qbo.intuit.com/app/invoice?txnId=145
                  meta:
                    from: '2026-01-01'
                    to: '2026-06-13'
                    counts:
                      matched: 1
                      sku_only: 1
                      provider_only: 1
                      excluded: 12
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-ledger-reconciliation-matches
  /api/ledger/reconciliation/excluded:
    get:
      tags:
      - Ledger (Accounting v2)
      summary: List Excluded SKU Entries
      description: 'The SKU ledger entries that are excluded from sync for a connection
        over the (optional) document-date window — unlinked entries that are not eligible
        to sync, each with the reason(s) it''s blocked.


        **Authentication:** Requires Bearer token.


        These are exactly the entries hidden from the `sku_only` bucket of the matches
        endpoint (an empty `sku_only` does not mean everything is synced — thousands
        of entries can be excluded). Loaded on its own so the matches payload stays
        light.


        Each row carries `reasons[]` as `{code, label}` pairs. Common reason codes:
        `override_disabled` (manually disabled), `type_disabled`, `channel_disabled`,
        `before_provider_sync_start_date`, `before_type_sync_start_date`, `batch_member`,
        `batch_open`, `connection_inactive`, `internal_only`, `granularity_off`.


        `from`/`to` (Y-m-d) override the default window. 404 when connection_id is
        not a supported accounting connection.'
      parameters:
      - name: connection_id
        in: query
        schema:
          type: integer
        description: Accounting connection id. Required.
        example: '5'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        reference:
                          type: string
                        type:
                          type: object
                          properties:
                            value:
                              type: string
                            label:
                              type: string
                        effective_at:
                          type: string
                        currency_code:
                          type: string
                        document_total:
                          type: string
                        reasons:
                          type: array
                          items:
                            type: object
                            properties:
                              code:
                                type: string
                              label:
                                type: string
                example:
                  data:
                  - id: 4830
                    reference: INV-1050
                    type:
                      value: sales_order_invoice
                      label: Sales Order Invoice
                    effective_at: '2026-06-05T00:00:00+00:00'
                    currency_code: USD
                    document_total: '250.0000'
                    reasons:
                    - code: override_disabled
                      label: Sync manually disabled
                  - id: 4831
                    reference: BILL-2201
                    type:
                      value: bill
                      label: Bill
                    effective_at: '2026-06-04T00:00:00+00:00'
                    currency_code: USD
                    document_total: '980.0000'
                    reasons:
                    - code: type_disabled
                      label: Transaction type not synced
                    - code: before_provider_sync_start_date
                      label: Dated before the sync start date
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-ledger-reconciliation-excluded
  /api/ledger/reconciliation/matched:
    get:
      tags:
      - Ledger (Accounting v2)
      summary: List Matched Entries
      description: 'The SKU ledger entries already linked to a provider document on
        a connection, as a paginated, filterable, sortable list. Each row also carries
        the linked provider document''s snapshot in `remote` (remote total, status,
        and a deep link) so a variance between the two sides can be spotted.


        **Authentication:** Requires Bearer token.


        **Query parameters:** `connection_id` (required); standard pagination (`page`,
        `per_page`), `sort`, per-field `filter[...]`, general `search`, and `filter_groups`
        (advanced filter tree). Allowed sorts: id, effective_at, reference, total_debit,
        created_at, type, display_status.


        **Response:** 200, a paginated list of entries.'
      parameters:
      - name: connection_id
        in: query
        schema:
          type: integer
        description: Accounting connection id. Required.
        example: '5'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        document_number:
                          type: string
                        type:
                          type: object
                          properties:
                            value:
                              type: string
                            label:
                              type: string
                        status:
                          type: string
                        display_status:
                          type: object
                          properties:
                            key:
                              type: string
                            label:
                              type: string
                            color:
                              type: string
                            reason:
                              type: string
                              nullable: true
                        effective_at:
                          type: string
                        currency_code:
                          type: string
                        total_debit:
                          type: string
                        document_total:
                          type: string
                        reference:
                          type: string
                        remote:
                          type: object
                          properties:
                            remote_type:
                              type: string
                            remote_id:
                              type: string
                            link_state:
                              type: string
                            remote_status:
                              type: string
                            total:
                              type: string
                            document_date:
                              type: string
                            remote_url:
                              type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - id: 10488
                    document_number: BILL-10488
                    type:
                      value: purchase_order_invoice
                      label: Purchase Order Invoice
                    status: posted
                    display_status:
                      key: synced
                      label: Synced
                      color: success
                      reason: null
                    effective_at: '2026-05-01T00:00:00+00:00'
                    currency_code: USD
                    total_debit: '3062.6000'
                    document_total: '3062.6000'
                    reference: SIBER10488
                    remote:
                      remote_type: xero_bill
                      remote_id: 85414bb6-6f88-4c0f-8c53-53e7c1f7128c
                      link_state: linked_current
                      remote_status: AUTHORISED
                      total: '3062.6000'
                      document_date: '2026-05-01'
                      remote_url: https://go.xero.com/AccountsPayable/View.aspx?InvoiceID=85414bb6-6f88-4c0f-8c53-53e7c1f7128c
                  current_page: 1
                  last_page: 1
                  per_page: 25
                  total: 1
                  from: 1
                  to: 1
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-ledger-reconciliation-matched
  /api/ledger/reconciliation/unlinked:
    get:
      tags:
      - Ledger (Accounting v2)
      summary: List Unlinked Entries
      description: 'The SKU ledger entries in the window that are NOT yet linked to
        a provider document on a connection — both the sync-eligible ones and the
        ineligible (excluded) ones — as a paginated, filterable, sortable list. Each
        row carries its live per-connection sync `eligibility` (`eligible` plus the
        block `reasons`, e.g. `type_disabled`, `channel_disabled`) so the ineligible
        ones can be flagged.


        **Authentication:** Requires Bearer token.


        **Query parameters:** `connection_id` (required); standard pagination, `sort`,
        per-field `filter[...]`, general `search`, and `filter_groups`.


        **Response:** 200, a paginated list of entries.'
      parameters:
      - name: connection_id
        in: query
        schema:
          type: integer
        description: Accounting connection id. Required.
        example: '5'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        document_number:
                          type: string
                        type:
                          type: object
                          properties:
                            value:
                              type: string
                            label:
                              type: string
                        status:
                          type: string
                        display_status:
                          type: object
                          properties:
                            key:
                              type: string
                            label:
                              type: string
                            color:
                              type: string
                            reason:
                              type: string
                              nullable: true
                        effective_at:
                          type: string
                        currency_code:
                          type: string
                        total_debit:
                          type: string
                        document_total:
                          type: string
                        reference:
                          type: string
                        eligibility:
                          type: object
                          properties:
                            eligible:
                              type: boolean
                            reasons:
                              type: array
                              items:
                                type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - id: 10488
                    document_number: BILL-10488
                    type:
                      value: purchase_order_invoice
                      label: Purchase Order Invoice
                    status: posted
                    display_status:
                      key: synced
                      label: Synced
                      color: success
                      reason: null
                    effective_at: '2026-05-01T00:00:00+00:00'
                    currency_code: USD
                    total_debit: '3062.6000'
                    document_total: '3062.6000'
                    reference: 'FBA181D492B4: 55641'
                    eligibility:
                      eligible: false
                      reasons:
                      - type_disabled
                  current_page: 1
                  last_page: 1
                  per_page: 25
                  total: 1
                  from: 1
                  to: 1
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-ledger-reconciliation-unlinked
  /api/ledger/reconciliation/provider-documents:
    get:
      tags:
      - Ledger (Accounting v2)
      summary: List Provider-only Documents
      description: 'The provider documents (Xero/QBO) that have NOT been linked to
        a SKU ledger entry and have not been dismissed, over a connection''s window
        — a normalized, paginated, filterable, sortable list across every document
        kind (invoices, bills, credit notes, journals).


        **Authentication:** Requires Bearer token.


        **Query parameters:** `connection_id` (required); standard pagination; `sort`
        (prefix with - for DESC; allowed: reference, secondary_reference, counterparty,
        total, sub_total, tax_total, amount_due, document_date, due_date, line_count,
        provider_updated_at, status, remote_type, remote_id); per-field `filter[...]`
        (`remote_type`, `status`, `doc_class` = `invoice`|`journal`, `date_from`/`date_to`);
        general `search` (matches reference, secondary reference, counterparty, amount,
        and exact provider id); and `filter_groups`. Each row''s `id` is the composite
        "{remote_type}:{remote_id}".


        **Response fields:** `doc_class` splits invoice-shaped documents (invoices/bills/credit
        notes) from journals. Invoice-shaped rows carry `counterparty`, `secondary_reference`
        (the provider''s free-text reference), `sub_total`, `tax_total`, `amount_due`,
        and `due_date`; journal rows carry `line_count`. `provider_updated_at` is
        the provider-side last-modified timestamp. Fields not applicable to a document
        kind are null.


        **Response:** 200, a paginated list of provider documents.'
      parameters:
      - name: connection_id
        in: query
        schema:
          type: integer
        description: Accounting connection id. Required.
        example: '5'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: string
                        remote_type:
                          type: string
                        remote_id:
                          type: string
                        doc_class:
                          type: string
                        reference:
                          type: string
                        secondary_reference:
                          type: string
                        counterparty:
                          type: string
                        total:
                          type: string
                        sub_total:
                          type: string
                        tax_total:
                          type: string
                        amount_due:
                          type: string
                        currency:
                          type: string
                        document_date:
                          type: string
                        due_date:
                          type: string
                        line_count:
                          type: string
                          nullable: true
                        provider_updated_at:
                          type: string
                        status:
                          type: string
                        remote_url:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - id: xero_bill:85414bb6-6f88-4c0f-8c53-53e7c1f7128c
                    remote_type: xero_bill
                    remote_id: 85414bb6-6f88-4c0f-8c53-53e7c1f7128c
                    doc_class: invoice
                    reference: 'FBA181D492B4: 55641'
                    secondary_reference: PO-7788
                    counterparty: Acme Corp
                    total: '3950.0000'
                    sub_total: '3291.6700'
                    tax_total: '658.3300'
                    amount_due: '0.0000'
                    currency: USD
                    document_date: '2026-05-23'
                    due_date: '2026-06-22'
                    line_count: null
                    provider_updated_at: '2026-05-24T09:15:00+00:00'
                    status: PAID
                    remote_url: https://go.xero.com/AccountsPayable/View.aspx?InvoiceID=85414bb6-6f88-4c0f-8c53-53e7c1f7128c
                  current_page: 1
                  last_page: 1
                  per_page: 25
                  total: 1
                  from: 1
                  to: 1
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-ledger-reconciliation-provider-documents
  /api/ledger/reconciliation/dismissed:
    get:
      tags:
      - Ledger (Accounting v2)
      summary: List Dismissed Documents
      description: 'The provider documents previously dismissed from reconciliation
        on a connection, as a paginated, filterable, sortable list — the "show dismissed"
        view for reviewing and restoring documents that were hidden. Restore them
        with POST /api/ledger/reconciliation/restore or /restore/bulk.


        **Authentication:** Requires Bearer token.


        **Query parameters:** `connection_id` (required); standard pagination; `sort`
        (prefix with - for DESC; allowed: reference, secondary_reference, counterparty,
        total, sub_total, tax_total, amount_due, document_date, due_date, line_count,
        provider_updated_at, status, remote_type, remote_id); `filter[...]` (`remote_type`,
        `status`, `doc_class` = `invoice`|`journal`, `date_from`/`date_to`); `search`;
        and `filter_groups`. Each row''s `id` is the composite "{remote_type}:{remote_id}".


        **Response:** 200, a paginated list of dismissed documents (same row shape
        as the provider-only list, including `doc_class`, `counterparty`, `secondary_reference`,
        `sub_total`, `tax_total`, `amount_due`, `due_date`, `line_count`, and `provider_updated_at`).'
      parameters:
      - name: connection_id
        in: query
        schema:
          type: integer
        description: Accounting connection id. Required.
        example: '5'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: string
                        remote_type:
                          type: string
                        remote_id:
                          type: string
                        doc_class:
                          type: string
                        reference:
                          type: string
                        secondary_reference:
                          type: string
                        counterparty:
                          type: string
                        total:
                          type: string
                        sub_total:
                          type: string
                        tax_total:
                          type: string
                        amount_due:
                          type: string
                        currency:
                          type: string
                        document_date:
                          type: string
                        due_date:
                          type: string
                        line_count:
                          type: string
                          nullable: true
                        provider_updated_at:
                          type: string
                        status:
                          type: string
                        remote_url:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - id: xero_bill:11c2a7d0-882e-4a19-9f6b-73c0d9a1e2ff
                    remote_type: xero_bill
                    remote_id: 11c2a7d0-882e-4a19-9f6b-73c0d9a1e2ff
                    doc_class: invoice
                    reference: Regular Payroll Jun 1 – Jun 15
                    secondary_reference: PO-7788
                    counterparty: Acme Corp
                    total: '1371.2600'
                    sub_total: '3291.6700'
                    tax_total: '658.3300'
                    amount_due: '0.0000'
                    currency: USD
                    document_date: '2026-06-15'
                    due_date: '2026-06-22'
                    line_count: null
                    provider_updated_at: '2026-05-24T09:15:00+00:00'
                    status: PAID
                    remote_url: https://go.xero.com/AccountsPayable/View.aspx?InvoiceID=11c2a7d0-882e-4a19-9f6b-73c0d9a1e2ff
                  current_page: 1
                  last_page: 1
                  per_page: 25
                  total: 1
                  from: 1
                  to: 1
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-ledger-reconciliation-dismissed
  /api/ledger/reconciliation/counts:
    get:
      tags:
      - Ledger (Accounting v2)
      summary: Get Reconciliation Counts
      description: 'The unfiltered counts for a connection: matched (linked), SKU-only
        (eligible unlinked), excluded (ineligible unlinked), and provider-only (unlinked
        provider documents).


        **Authentication:** Requires Bearer token.


        **Response:** 200 with the four counts.'
      parameters:
      - name: connection_id
        in: query
        schema:
          type: integer
        description: Accounting connection id. Required.
        example: '5'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      matched:
                        type: integer
                      sku_only:
                        type: integer
                      excluded:
                        type: integer
                      provider_only:
                        type: integer
                example:
                  data:
                    matched: 546
                    sku_only: 0
                    excluded: 8257
                    provider_only: 258
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-ledger-reconciliation-counts
  /api/ledger/reconciliation/link-candidates:
    get:
      tags:
      - Ledger (Accounting v2)
      summary: List Entry Link Candidates
      description: 'The SKU ledger entries a provider-only document could be linked
        to — the confidence-ranked picker for the reverse direction of the manual
        link (pick the SKU entry that matches a provider document, identified by `remote_type`
        + `remote_id`).


        Ranks the connection''s unlinked entries against the target document, spanning
        BOTH the eligible (`sku_only`) and the excluded (ineligible) entries — an
        entry that will never sync can still be the real counterpart of a provider
        document, and linking it is safe (it reconciles the document out of the provider-only
        set without pushing anything). Each candidate carries per-signal match flags
        — `amount_match`, `date_match`, `reference_match`, `confident` — plus its
        sync eligibility: `eligible` (boolean) and `eligibility_reasons[]` (reason
        codes such as `type_disabled`, `channel_disabled`) so ineligible candidates
        can be flagged.


        **Authentication:** Requires Bearer token.


        **Query parameters:** `connection_id` (required), `remote_type` (required,
        e.g. xero_bill), `remote_id` (required — the provider document id), `search`
        (optional). Returns 404 when connection_id is not a supported accounting connection,
        and 422 when a required parameter is missing.


        **Response:** 200 with `data` as an array of candidate entries ordered most-confident
        first. Link the chosen entry with POST /api/ledger/reconciliation/link.'
      parameters:
      - name: connection_id
        in: query
        schema:
          type: integer
        description: Accounting connection id. Required.
        example: '30'
      - name: remote_type
        in: query
        schema:
          type: string
        description: The kind of provider document (e.g. xero_bill, xero_invoice,
          qbo_invoice). Required.
        example: xero_bill
      - name: remote_id
        in: query
        schema:
          type: string
        description: The provider document id to find SKU entries for. Required.
        example: 85414bb6-6f88-4c0f-8c53-53e7c1f7128c
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        entry_id:
                          type: integer
                        reference:
                          type: string
                        document_number:
                          type: string
                        type_label:
                          type: string
                        date:
                          type: string
                        total:
                          type: string
                        currency:
                          type: string
                        amount_match:
                          type: boolean
                        date_match:
                          type: boolean
                        reference_match:
                          type: boolean
                        confident:
                          type: boolean
                        eligible:
                          type: boolean
                        eligibility_reasons:
                          type: array
                          items:
                            type: string
                example:
                  data:
                  - entry_id: 10927
                    reference: 'FBA181D492B4: 55641'
                    document_number: BILL-10927
                    type_label: Purchase Order Invoice
                    date: '2024-05-22T07:00:00+00:00'
                    total: '3950.0000'
                    currency: USD
                    amount_match: true
                    date_match: true
                    reference_match: true
                    confident: true
                    eligible: false
                    eligibility_reasons:
                    - type_disabled
                  - entry_id: 10930
                    reference: FBA181D492B4
                    document_number: BILL-10930
                    type_label: Purchase Order Invoice
                    date: '2024-06-01T07:00:00+00:00'
                    total: '120.0000'
                    currency: USD
                    amount_match: false
                    date_match: false
                    reference_match: true
                    confident: false
                    eligible: true
                    eligibility_reasons: []
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-ledger-reconciliation-link-candidates
  /api/ledger/reconciliation/report:
    get:
      tags:
      - Ledger (Accounting v2)
      summary: Reconciliation Report
      description: 'The period-comparison report for a connection over the (optional)
        document-date window: monthly SKU-ledger totals vs the provider-mirror, with
        per-period and grand-total variance highlighting. Read entirely off the local
        provider document cache — no provider API calls.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Authentication:** Requires Bearer token.


        **Shape:** `data.rows[]` is one row per calendar month with activity, most-recent
        first. Each row carries `sku_entry_count` / `sku_total_debit` / `sku_total_credit`
        (the matched + SKU-only entries), `provider_document_count` / `provider_total`
        (the matched remotes + provider-only documents), and the deltas `count_variance`
        (sku − provider count) and `amount_variance` (sku debit − provider total,
        4dp). `has_variance` is true when the counts differ or the amount delta exceeds
        the configured tolerance (`ledger.sync.dedup.amount_tolerance`, default 0.01).


        `data.summary` rolls the same fields up across every period (`period_count`,
        `periods_with_variance`). `data.currency` is the dominant currency or null
        when the window is empty. `from`/`to` (Y-m-d) override the default window.
        404 when connection_id is not a supported accounting connection.'
      parameters:
      - name: connection_id
        in: query
        schema:
          type: integer
        description: Accounting connection id. Required.
        example: '5'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      connection_id:
                        type: integer
                      from:
                        type: string
                      to:
                        type: string
                      currency:
                        type: string
                      rows:
                        type: array
                        items:
                          type: object
                          properties:
                            period:
                              type: string
                            period_label:
                              type: string
                            sku_entry_count:
                              type: integer
                            sku_total_debit:
                              type: string
                            sku_total_credit:
                              type: string
                            provider_document_count:
                              type: integer
                            provider_total:
                              type: string
                            count_variance:
                              type: integer
                            amount_variance:
                              type: string
                            has_variance:
                              type: boolean
                      summary:
                        type: object
                        properties:
                          period_count:
                            type: integer
                          periods_with_variance:
                            type: integer
                          sku_entry_count:
                            type: integer
                          sku_total_debit:
                            type: string
                          sku_total_credit:
                            type: string
                          provider_document_count:
                            type: integer
                          provider_total:
                            type: string
                          count_variance:
                            type: integer
                          amount_variance:
                            type: string
                          has_variance:
                            type: boolean
                example:
                  data:
                    connection_id: 5
                    from: '2026-01-01'
                    to: '2026-06-13'
                    currency: USD
                    rows:
                    - period: 2026-06
                      period_label: Jun 2026
                      sku_entry_count: 12
                      sku_total_debit: '4250.0000'
                      sku_total_credit: '4250.0000'
                      provider_document_count: 12
                      provider_total: '4250.0000'
                      count_variance: 0
                      amount_variance: '0.0000'
                      has_variance: false
                    - period: 2026-05
                      period_label: May 2026
                      sku_entry_count: 9
                      sku_total_debit: '3100.0000'
                      sku_total_credit: '3100.0000'
                      provider_document_count: 8
                      provider_total: '2850.0000'
                      count_variance: 1
                      amount_variance: '250.0000'
                      has_variance: true
                    summary:
                      period_count: 2
                      periods_with_variance: 1
                      sku_entry_count: 21
                      sku_total_debit: '7350.0000'
                      sku_total_credit: '7350.0000'
                      provider_document_count: 20
                      provider_total: '7100.0000'
                      count_variance: 1
                      amount_variance: '250.0000'
                      has_variance: true
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-ledger-reconciliation-report
  /api/ledger/reconciliation/auto-match/preview:
    post:
      tags:
      - Ledger (Accounting v2)
      summary: Preview Auto-Match
      description: 'Compute the confident auto-match pairs for a connection WITHOUT
        linking anything — the preview behind the reconcile Auto-Match confirmation.
        Returns one row per proposed pairing of an unmatched SKU entry (SKU-only or
        excluded) to a provider-only document whose reference, amount (within tolerance)
        and date (within window) confidently match. Review the rows, then send the
        ones you want to keep to Run Auto-Match to link them.


        **Authentication:** Requires Bearer token + `accounting.sync` permission.


        `from`/`to` (Y-m-d) are optional and default to the connection''s reconcile
        window.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                connection_id:
                  type: integer
                from:
                  type: string
                to:
                  type: string
              example:
                connection_id: 5
                from: '2026-01-01'
                to: '2026-06-13'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        entry_id:
                          type: integer
                        entry_reference:
                          type: string
                        entry_document_number:
                          type: string
                        entry_type_label:
                          type: string
                        entry_date:
                          type: string
                        entry_total:
                          type: string
                        entry_currency:
                          type: string
                        remote_type:
                          type: string
                        remote_id:
                          type: string
                        remote_reference:
                          type: string
                        remote_status:
                          type: string
                        remote_date:
                          type: string
                        remote_total:
                          type: string
                        remote_currency:
                          type: string
                        remote_url:
                          type: string
                example:
                  data:
                  - entry_id: 8213
                    entry_reference: INV-1042
                    entry_document_number: INV-8213
                    entry_type_label: Sales Order Invoice
                    entry_date: '2026-06-02T00:00:00+00:00'
                    entry_total: '200.00'
                    entry_currency: USD
                    remote_type: qbo_invoice
                    remote_id: '142'
                    remote_reference: INV-1042
                    remote_status: Open
                    remote_date: '2026-06-03'
                    remote_total: '200.00'
                    remote_currency: USD
                    remote_url: https://app.qbo.intuit.com/app/invoice?txnId=142
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-ledger-reconciliation-auto-match-preview
  /api/ledger/reconciliation/auto-match:
    post:
      tags:
      - Ledger (Accounting v2)
      summary: Run Auto-Match
      description: 'Link the auto-match pairs confirmed from Preview Auto-Match. Send
        a `matches` array of `{entry_id, remote_type, remote_id}` rows; the eligible
        set is recomputed and only the intersection is linked, so a pairing that has
        since become ineligible is skipped rather than force-linked. Returns the number
        of links forged; each is recorded linked_stale so the next sync pushes an
        Update. An empty `matches` array links nothing.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Authentication:** Requires Bearer token + `accounting.sync` permission.


        **Body fields:**

        - `connection_id` (integer, required) — the accounting connection.

        - `matches` (array, required) — confirmed pairs; each `{entry_id, remote_type,
        remote_id}`. May be empty.

        - `matches[].entry_id` (integer, required) — the SKU ledger entry to link.

        - `matches[].remote_type` (string, required) — provider document type, e.g.
        `qbo_invoice`, `xero_invoice`.

        - `matches[].remote_id` (string, required) — the provider document id.

        - `from` / `to` (Y-m-d, optional) — window override; defaults to the connection''s
        reconcile window.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                connection_id:
                  type: integer
                matches:
                  type: array
                  items:
                    type: object
                    properties:
                      entry_id:
                        type: integer
                      remote_type:
                        type: string
                      remote_id:
                        type: string
                from:
                  type: string
                to:
                  type: string
              example:
                connection_id: 5
                matches:
                - entry_id: 8213
                  remote_type: qbo_invoice
                  remote_id: '142'
                - entry_id: 8214
                  remote_type: qbo_invoice
                  remote_id: '143'
                from: '2026-01-01'
                to: '2026-06-13'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      linked:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    linked: 2
                  message: 2 documents auto-matched.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-ledger-reconciliation-auto-match
  /api/ledger/reconciliation/backfill:
    post:
      tags:
      - Ledger (Accounting v2)
      summary: Backfill Provider Cache
      description: 'Populate the local provider document cache (the xero_/qbo_ mirror)
        for a connection by dispatching a tracked background job that downloads every
        remote document over the reconcile window. The reconcile screen, matching,
        and the period-comparison report all read off this local cache, so this is
        the on-demand, UI-triggered equivalent of the `ledger:cache:backfill` artisan
        command. Returns the tracked job log id so the frontend can follow progress
        via the tracked job log endpoints.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Authentication:** Requires Bearer token + `accounting.sync` permission.


        `from`/`to` (Y-m-d) are optional and default to the connection''s reconcile
        window (the connection''s sync start date through today).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                connection_id:
                  type: integer
              example:
                connection_id: 5
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 8412
                  message: Caching provider documents from Xero — track progress in
                    the job tray.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-ledger-reconciliation-backfill
  /api/ledger/reconciliation/link:
    post:
      tags:
      - Ledger (Accounting v2)
      summary: Link Remote Document
      description: 'Manually link a SKU entry to an existing provider document — the
        operator''s "this is the same document" action. Recorded linked_stale so the
        next sync pushes an Update bringing the remote into line.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Linking a document also clears any reconcile-screen dismissal recorded against
        it.


        **Authentication:** Requires Bearer token + `accounting.sync` permission.


        422 when the entry already has a link on this connection.


        **Ownership validation:** the (remote_type, remote_id) pair must be a cached
        provider document belonging to the given connection. A document from another
        connection (or one not yet pulled into the local cache) is rejected with HTTP
        422 — pull provider documents for the connection first, then link.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                connection_id:
                  type: integer
                entry_id:
                  type: integer
                remote_type:
                  type: string
                remote_id:
                  type: string
              example:
                connection_id: 5
                entry_id: 4822
                remote_type: qbo_invoice
                remote_id: '146'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      provider:
                        type: string
                      remote_type:
                        type: string
                      remote_id:
                        type: string
                      remote_url:
                        type: string
                      link_state:
                        type: string
                      remote_status:
                        type: string
                      last_remote_seen_at:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 78
                    provider: qbo
                    remote_type: qbo_invoice
                    remote_id: '146'
                    remote_url: https://app.qbo.intuit.com/app/invoice?txnId=145
                    link_state: linked_stale
                    remote_status: Active
                    last_remote_seen_at: '2026-06-12T02:00:00+00:00'
                  message: Linked to the provider document.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Document qbo_invoice:184 is not a cached provider document
                    of this connection — refresh the provider cache or re-check the
                    selected connection.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-ledger-reconciliation-link
  /api/ledger/reconciliation/dismiss:
    post:
      tags:
      - Ledger (Accounting v2)
      summary: Dismiss Provider Document
      description: 'Dismiss a provider-only document — mark a remote document as "not
        a SKU document" so it stops surfacing in the provider-only bucket. Idempotent
        on the remote identity.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Authentication:** Requires Bearer token + `accounting.sync` permission.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                connection_id:
                  type: integer
                remote_type:
                  type: string
                remote_id:
                  type: string
                reason:
                  type: string
              example:
                connection_id: 5
                remote_type: qbo_invoice
                remote_id: '146'
                reason: Pre-existing supplier bill, not SKU-managed
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Document dismissed from reconciliation.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-ledger-reconciliation-dismiss
  /api/ledger/reconciliation/dismiss/bulk:
    post:
      tags:
      - Ledger (Accounting v2)
      summary: Bulk Dismiss Provider Documents
      description: 'Dismiss many provider-only documents from reconciliation in one
        action (idempotent). Provide either `ids` (an array of composite "{remote_type}:{remote_id}"
        identifiers — the selected rows) or `apply_to_all: true` with `filters` to
        dismiss every provider-only document matching those filters. An optional `reason`
        is stored on each.


        **Authentication:** Requires Bearer token.


        **Body:** `connection_id` (required, integer); `ids` (array of strings, required
        unless `apply_to_all`); `apply_to_all` (boolean); `filters` (object, optional)
        — the list filters to scope `apply_to_all`, e.g. `{"search": "Contractor Payment"}`.
        Accepts flat filter values (`search`, `remote_type`, `status`, `date_from`,
        `date_to`) plus an optional `filter_groups` tree (same structure as the list
        endpoint''s `filter_groups` parameter). When omitted, `apply_to_all` targets
        every document in the reconcile window.; `reason` (string, optional).


        **Response:** 200 with the number dismissed.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                connection_id:
                  type: integer
                apply_to_all:
                  type: boolean
                filters:
                  type: object
                  properties:
                    search:
                      type: string
                reason:
                  type: string
              example:
                connection_id: 5
                apply_to_all: true
                filters:
                  search: Contractor Payment
                reason: not a SKU document
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      dismissed:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    dismissed: 1
                  message: 1 document dismissed from reconciliation.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-ledger-reconciliation-dismiss-bulk
  /api/ledger/reconciliation/restore/bulk:
    post:
      tags:
      - Ledger (Accounting v2)
      summary: Bulk Restore Provider Documents
      description: 'Restore (un-dismiss) many provider documents in one action, returning
        them to reconciliation. Provide either `ids` (composite "{remote_type}:{remote_id}"
        identifiers — the selected rows) or `apply_to_all: true` with `filters` to
        restore every dismissed document matching those filters.


        **Authentication:** Requires Bearer token.


        **Body:** `connection_id` (required, integer); `ids` (array of strings, required
        unless `apply_to_all`); `apply_to_all` (boolean); `filters` (object, optional)
        — the list filters to scope `apply_to_all`, e.g. `{"search": "Contractor Payment"}`.
        Accepts flat filter values (`search`, `remote_type`, `status`, `date_from`,
        `date_to`) plus an optional `filter_groups` tree (same structure as the list
        endpoint''s `filter_groups` parameter). When omitted, `apply_to_all` targets
        every document in the reconcile window..


        **Response:** 200 with the number restored.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                connection_id:
                  type: integer
                apply_to_all:
                  type: boolean
                filters:
                  type: object
                  properties:
                    search:
                      type: string
              example:
                connection_id: 5
                apply_to_all: true
                filters:
                  search: Contractor Payment
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      restored:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    restored: 1
                  message: 1 document restored to reconciliation.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-ledger-reconciliation-restore-bulk
  /api/ledger/reconciliation/restore:
    post:
      tags:
      - Ledger (Accounting v2)
      summary: Restore Provider Document
      description: 'Undo a dismissal — restore a previously dismissed provider document
        to the reconcile screen.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Authentication:** Requires Bearer token + `accounting.sync` permission.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                connection_id:
                  type: integer
                remote_type:
                  type: string
                remote_id:
                  type: string
              example:
                connection_id: 5
                remote_type: qbo_invoice
                remote_id: '146'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Document restored to reconciliation.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-ledger-reconciliation-restore
  /api/ledger/reconciliation/payments:
    get:
      tags:
      - Ledger (Accounting v2)
      summary: List Provider Payments
      description: 'Provider payments (Xero/QBO) from the local mirror for a connection,
        each flagged with whether it has already been imported as a SKU payment. Backs
        the Reconciliation > Payments view.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authenticate with a PAT.'
      parameters:
      - name: connection_id
        in: query
        schema:
          type: integer
        description: Accounting connection (IntegrationInstance) id.
        example: '2'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        remote_type:
                          type: string
                        remote_id:
                          type: string
                        reference:
                          type: string
                        amount:
                          type: string
                        date:
                          type: string
                        imported:
                          type: boolean
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - remote_type: xero_payment
                    remote_id: 19979c8d-b674-4784-a5ed-595a1c5356d4
                    reference: 19979c8d-b674-4784-a5ed-595a1c5356d4
                    amount: '500.0000'
                    date: '2026-06-18T00:00:00+00:00'
                    imported: false
                  current_page: 1
                  last_page: 5
                  per_page: 15
                  total: 74
                  from: 1
                  to: 15
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-ledger-reconciliation-payments
  /api/ledger/reconciliation/payments/import:
    post:
      tags:
      - Ledger (Accounting v2)
      summary: Import Provider Payments
      description: 'Import provider payments into SKU — create the matching SKU payment
        on each payment''s source document, via the same idempotent pathway as the
        automatic inbound pull. With remote_ids, only those; omit remote_ids to import
        every not-yet-imported provider payment. Requires accounting.sync permission.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Response data: {attempted, imported}.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                connection_id:
                  type: integer
                remote_ids:
                  type: array
                  items:
                    type: string
              example:
                connection_id: 2
                remote_ids:
                - 19979c8d-b674-4784-a5ed-595a1c5356d4
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      attempted:
                        type: integer
                      imported:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    attempted: 1
                    imported: 1
                  message: 1 payment imported into SKU.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-ledger-reconciliation-payments-import
  /api/ledger/reconciliation/inventory:
    get:
      tags:
      - Ledger (Accounting v2)
      summary: Get Inventory Divergence
      description: 'Inventory sub-ledger reconciliation (Lane 2). SKU is the authoritative
        subsidiary ledger for inventory, so this returns one row per inventory control
        account comparing SKU''s per-account inventory value against the provider''s
        live GL balance (pulled from the Xero Trial Balance) — most divergent first.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Authentication:** Requires Bearer token. The provider connection must have
        the `accounting.reports.read` scope.


        **Row fields:** `gl_code`, `gl_account_name`, `gl_account_id`, `sku_value`
        (null when SKU cannot value the account, e.g. Amazon FBA accounts valued via
        a separate subsystem), `sku_quantity`, `provider_balance`, `divergence` (provider_balance
        − sku_value; null when sku_value is null), `status` (`divergent` | `matched`
        | `sku_unavailable`).


        The warehouse→GL mapping is SKU''s own `warehouses.nominal_code_id`. A non-zero
        divergence is the basis for a suggested adjusting journal on the provider
        side.'
      parameters:
      - name: connection_id
        in: query
        schema:
          type: integer
        description: Accounting connection (IntegrationInstance) id. Required.
        example: '5'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        gl_code:
                          type: string
                        gl_account_name:
                          type: string
                        gl_account_id:
                          type: string
                        sku_value:
                          type: number
                        sku_quantity:
                          type: integer
                        provider_balance:
                          type: number
                        divergence:
                          type: number
                        status:
                          type: string
                  success:
                    type: boolean
                example:
                  data:
                  - gl_code: '142'
                    gl_account_name: SMO Inventory (142)
                    gl_account_id: 5e55e704-1a2b-4c3d-9e8f-0a1b2c3d4e5f
                    sku_value: 569947.14
                    sku_quantity: 26463
                    provider_balance: 1042053.4
                    divergence: 472106.26
                    status: divergent
                  - gl_code: '141'
                    gl_account_name: Amazon FBA US Inventory (141)
                    gl_account_id: d35c45a4-aa11-4b22-8c33-9d44e55f6071
                    sku_value: null
                    sku_quantity: null
                    provider_balance: 269416
                    divergence: null
                    status: sku_unavailable
                  - gl_code: '145'
                    gl_account_name: Amazon FBA CA Inventory (145)
                    gl_account_id: b312ed80-1122-4334-8556-77889900aabb
                    sku_value: null
                    sku_quantity: null
                    provider_balance: 8859
                    divergence: null
                    status: sku_unavailable
                  success: true
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-ledger-reconciliation-inventory
  /api/ledger/reconciliation/inventory/accounts:
    get:
      tags:
      - Ledger (Accounting v2)
      summary: Inventory Recon Accounts (Earmark Suggestions)
      description: 'Candidate inventory control accounts for the daily reconciliation
        earmark step. Pulls SKU''s current-asset nominal codes (plus any warehouse-mapped
        account), cross-references the provider''s cached current-asset chart (Xero
        `xero_accounts`, matched by code — **no live provider call**), computes each
        account''s point-in-time SKU inventory value as-of now, and flags which look
        like inventory accounts. Suggested-then-code ordered.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Authentication:** Requires Bearer token.


        **Row fields:** `nominal_code_id`, `code`, `sku_name`, `sku_type`, `provider_account_name`,
        `provider_account_type`, `provider_account_id` (nullable when no provider
        match), `warehouse_count`, `warehouse_names[]`, `is_earmarked` (the user''s
        persisted decision), `is_suggested` (heuristic), `suggestion_reasons[]` (strongest
        first: warehouse-mapped, SKU type Inventory, provider type Inventory, name
        looks like inventory), `current_sku_value` (null when no warehouse — and therefore
        no SKU inventory — maps to it).'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        nominal_code_id:
                          type: integer
                        code:
                          type: string
                        sku_name:
                          type: string
                        sku_type:
                          type: string
                        provider_account_name:
                          type: string
                        provider_account_type:
                          type: string
                        provider_account_id:
                          type: string
                        warehouse_count:
                          type: integer
                        warehouse_names:
                          type: array
                          items:
                            type: string
                        is_earmarked:
                          type: boolean
                        is_suggested:
                          type: boolean
                        suggestion_reasons:
                          type: array
                          items:
                            type: string
                        current_sku_value:
                          type: number
                  success:
                    type: boolean
                example:
                  data:
                  - nominal_code_id: 87
                    code: '142'
                    sku_name: SMO Inventory
                    sku_type: Inventory
                    provider_account_name: SMO Inventory
                    provider_account_type: INVENTORY
                    provider_account_id: 5e55e704-1a2b-4c3d-9e8f-0a1b2c3d4e5f
                    warehouse_count: 1
                    warehouse_names:
                    - ShipMyOrders
                    is_earmarked: true
                    is_suggested: true
                    suggestion_reasons:
                    - Mapped to warehouse ShipMyOrders
                    - SKU account type is Inventory
                    - Name looks like inventory
                    current_sku_value: 569792.24
                  - nominal_code_id: 88
                    code: '141'
                    sku_name: Amazon FBA US Inventory
                    sku_type: Inventory
                    provider_account_name: Amazon FBA US Inventory
                    provider_account_type: INVENTORY
                    provider_account_id: d35c45a4-aa11-4b22-8c33-9d44e55f6071
                    warehouse_count: 0
                    warehouse_names: []
                    is_earmarked: false
                    is_suggested: true
                    suggestion_reasons:
                    - SKU account type is Inventory
                    - Name looks like inventory
                    current_sku_value: null
                  success: true
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-ledger-reconciliation-inventory-accounts
    put:
      tags:
      - Ledger (Accounting v2)
      summary: Save Earmarked Inventory Accounts
      description: 'Replace the earmarked inventory control account set and return
        the refreshed candidate list. The submitted set replaces existing earmarks
        wholesale — an empty array clears them. The earmarked accounts are what the
        daily series and rebuild job operate on.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Authentication:** Requires Bearer token + `accounting.sync` permission.


        **Request body:**

        - `nominal_code_ids` (array, **required/present** — may be empty): nominal
        code ids to earmark. Each must exist in `nominal_codes`.


        Returns the same payload shape as `GET .../inventory/accounts` with `is_earmarked`
        reflecting the new set.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                nominal_code_ids:
                  type: array
                  items:
                    type: integer
              example:
                nominal_code_ids:
                - 87
                - 88
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        nominal_code_id:
                          type: integer
                        code:
                          type: string
                        sku_name:
                          type: string
                        sku_type:
                          type: string
                        provider_account_name:
                          type: string
                        provider_account_type:
                          type: string
                        provider_account_id:
                          type: string
                        warehouse_count:
                          type: integer
                        warehouse_names:
                          type: array
                          items:
                            type: string
                        is_earmarked:
                          type: boolean
                        is_suggested:
                          type: boolean
                        suggestion_reasons:
                          type: array
                          items:
                            type: string
                        current_sku_value:
                          type: number
                  success:
                    type: boolean
                example:
                  data:
                  - nominal_code_id: 87
                    code: '142'
                    sku_name: SMO Inventory
                    sku_type: Inventory
                    provider_account_name: SMO Inventory
                    provider_account_type: INVENTORY
                    provider_account_id: 5e55e704-1a2b-4c3d-9e8f-0a1b2c3d4e5f
                    warehouse_count: 1
                    warehouse_names:
                    - ShipMyOrders
                    is_earmarked: true
                    is_suggested: true
                    suggestion_reasons:
                    - Mapped to warehouse ShipMyOrders
                    - SKU account type is Inventory
                    - Name looks like inventory
                    current_sku_value: 569792.24
                  - nominal_code_id: 88
                    code: '141'
                    sku_name: Amazon FBA US Inventory
                    sku_type: Inventory
                    provider_account_name: Amazon FBA US Inventory
                    provider_account_type: INVENTORY
                    provider_account_id: d35c45a4-aa11-4b22-8c33-9d44e55f6071
                    warehouse_count: 0
                    warehouse_names: []
                    is_earmarked: false
                    is_suggested: true
                    suggestion_reasons:
                    - SKU account type is Inventory
                    - Name looks like inventory
                    current_sku_value: null
                  success: true
        '422':
          description: Unprocessable Content
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      nominal_code_ids:
                        type: array
                        items:
                          type: string
                example:
                  message: The nominal code ids field must be present.
                  errors:
                    nominal_code_ids:
                    - The nominal code ids field must be present.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: put-api-ledger-reconciliation-inventory-accounts
  /api/ledger/reconciliation/inventory/daily:
    get:
      tags:
      - Ledger (Accounting v2)
      summary: Inventory Daily Divergence Series
      description: 'The materialized daily reconciliation series, one entry per earmarked
        account (or per `nominal_code_ids[]` when given): SKU''s point-in-time inventory
        value vs the provider GL balance for each end-of-day, and the stored divergence
        — the "which days diverge" view. Reads materialized rows only (**no live provider
        or valuation call**); the SKU side is built by the rebuild job and the provider
        side by capture-provider.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Each day''s SKU value uses the same valuation cutoff as the inventory valuation
        report, so a day ties to running that report for that end-of-day.


        **Authentication:** Requires Bearer token.


        **Series fields:** `nominal_code_id`, `code`, `name`, `provider_account_name`,
        `days_total`, `days_divergent`, `days_matched`, `days_provider_missing`, `latest_sku_value`,
        `latest_provider_balance`, `latest_divergence`, `latest_as_of_date`, `points[]`.


        **Point fields:** `as_of_date`, `sku_value`, `sku_quantity`, `provider_balance`
        (null on days not yet captured), `divergence` (null when either side missing),
        `status` (`divergent` | `matched` | `provider_missing` | `sku_missing`).'
      parameters:
      - name: connection_id
        in: query
        schema:
          type: integer
        description: Accounting connection (IntegrationInstance) id. Required.
        example: '5'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        nominal_code_id:
                          type: integer
                        code:
                          type: string
                        name:
                          type: string
                        provider_account_name:
                          type: string
                        days_total:
                          type: integer
                        days_divergent:
                          type: integer
                        days_matched:
                          type: integer
                        days_provider_missing:
                          type: integer
                        latest_sku_value:
                          type: number
                        latest_provider_balance:
                          type: number
                        latest_divergence:
                          type: number
                        latest_as_of_date:
                          type: string
                        points:
                          type: array
                          items:
                            type: object
                            properties:
                              as_of_date:
                                type: string
                              sku_value:
                                type: integer
                              sku_quantity:
                                type: integer
                              provider_balance:
                                type: string
                                nullable: true
                              divergence:
                                type: string
                                nullable: true
                              status:
                                type: string
                  success:
                    type: boolean
                example:
                  data:
                  - nominal_code_id: 87
                    code: '142'
                    name: SMO Inventory
                    provider_account_name: SMO Inventory
                    days_total: 796
                    days_divergent: 540
                    days_matched: 250
                    days_provider_missing: 6
                    latest_sku_value: 569792.24
                    latest_provider_balance: 1042053.4
                    latest_divergence: 472261.16
                    latest_as_of_date: '2026-06-27'
                    points:
                    - as_of_date: '2024-04-23'
                      sku_value: 0
                      sku_quantity: 0
                      provider_balance: null
                      divergence: null
                      status: provider_missing
                    - as_of_date: '2026-06-26'
                      sku_value: 568120.05
                      sku_quantity: 26390
                      provider_balance: null
                      divergence: null
                      status: provider_missing
                    - as_of_date: '2026-06-27'
                      sku_value: 569792.24
                      sku_quantity: 26463
                      provider_balance: 1042053.4
                      divergence: 472261.16
                      status: divergent
                  success: true
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-ledger-reconciliation-inventory-daily
  /api/ledger/reconciliation/inventory/day-detail:
    get:
      tags:
      - Ledger (Accounting v2)
      summary: Get Inventory Reconciliation Day Detail
      description: 'For one earmarked inventory control account on one day, returns
        the reconciled figures for that day (SKU inventory value, provider GL balance,
        and their divergence) plus the underlying detail that produced them: the provider
        journal lines posted to the account that day and the inventory movements that
        changed SKU''s value that day. Use it to trace a divergence to its source
        documents — reads materialized/cached data only, no live provider call.


        **Authentication:** Requires Bearer token.


        **Response fields:** `as_of_date`, `nominal_code_id`, `code`, `name`, `provider_account_name`,
        `sku_value`, `sku_quantity`, `provider_balance`, `divergence`, `provider_net_total`
        (sum of the day''s provider journal-line net amounts), `sku_value_delta_total`
        (sum of the day''s movement value deltas), `provider_lines[]` (`journal_number`,
        `journal_date`, `source_type`, `source_id`, `account_code`, `account_name`,
        `net_amount`, `gross_amount`, `tax_amount`), `sku_movements[]` (`id`, `movement_date`,
        `type`, `warehouse_name`, `product_sku`, `product_name`, `quantity`, `unit_cost`,
        `value_delta`, `reference`, `link_type`, `link_id`).'
      parameters:
      - name: connection_id
        in: query
        schema:
          type: integer
        description: Accounting connection id. Required.
        example: '5'
      - name: nominal_code_id
        in: query
        schema:
          type: integer
        description: The earmarked inventory control account (nominal code) id to
          explain. Required.
        example: '87'
      - name: date
        in: query
        schema:
          type: string
        description: The local day to explain (date). Required.
        example: '2026-06-27'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      as_of_date:
                        type: string
                      nominal_code_id:
                        type: integer
                      code:
                        type: string
                      name:
                        type: string
                      provider_account_name:
                        type: string
                      sku_value:
                        type: number
                      sku_quantity:
                        type: integer
                      provider_balance:
                        type: number
                      divergence:
                        type: number
                      provider_net_total:
                        type: number
                      sku_value_delta_total:
                        type: number
                      provider_lines:
                        type: array
                        items:
                          type: object
                          properties:
                            journal_number:
                              type: string
                            journal_date:
                              type: string
                            source_type:
                              type: string
                            source_id:
                              type: string
                            account_code:
                              type: string
                            account_name:
                              type: string
                            net_amount:
                              type: number
                            gross_amount:
                              type: number
                            tax_amount:
                              type: integer
                      sku_movements:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            movement_date:
                              type: string
                            type:
                              type: string
                            warehouse_name:
                              type: string
                            product_sku:
                              type: string
                            product_name:
                              type: string
                            quantity:
                              type: integer
                            unit_cost:
                              type: number
                            value_delta:
                              type: number
                            reference:
                              type: string
                            link_type:
                              type: string
                            link_id:
                              type: integer
                example:
                  data:
                    as_of_date: '2026-06-27'
                    nominal_code_id: 87
                    code: '142'
                    name: SMO Inventory
                    provider_account_name: SMO Inventory
                    sku_value: 569792.24
                    sku_quantity: 41250
                    provider_balance: 571675.22
                    divergence: 1882.98
                    provider_net_total: 1882.98
                    sku_value_delta_total: -63.28
                    provider_lines:
                    - journal_number: '212538'
                      journal_date: '2026-06-27'
                      source_type: ACCPAY
                      source_id: b1f2c0d4-5e6f-4a7b-8c9d-0e1f2a3b4c5d
                      account_code: '142'
                      account_name: SMO Inventory
                      net_amount: 1882.98
                      gross_amount: 1882.98
                      tax_amount: 0
                    sku_movements:
                    - id: 3071
                      movement_date: '2026-06-27T09:14:00.000000Z'
                      type: adjustment
                      warehouse_name: ShipMyOrders Warehouse
                      product_sku: TM-191-O-124
                      product_name: Titanium Mount 191
                      quantity: -1
                      unit_cost: 63.28
                      value_delta: -63.28
                      reference: '3071'
                      link_type: InventoryAdjustment
                      link_id: 3071
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-ledger-reconciliation-inventory-day-detail
  /api/ledger/reconciliation/inventory/unsynced:
    get:
      tags:
      - Ledger (Accounting v2)
      summary: Get Inventory Reconciliation Awaiting-Sync Items
      description: 'Per earmarked inventory account, the SKU ledger activity not reflected
        in the provider balance, split by sync disposition: `pending_ledger`/`pending_count`
        WILL reach the provider once it syncs (self-resolving), while `excluded_ledger`/`excluded_count`
        will NEVER sync (dated before the books'' sync start date, or internal-only)
        — a permanent mismatch a measure-from baseline sets aside. Batch-aggregate
        aware (a batched document counts once, via its batch). Requires connection_id.'
      parameters:
      - name: connection_id
        in: query
        schema:
          type: integer
        description: Accounting connection id. Required.
        example: '5'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      as_of_date:
                        type: string
                      accounts:
                        type: array
                        items:
                          type: object
                          properties:
                            nominal_code_id:
                              type: integer
                            code:
                              type: string
                            name:
                              type: string
                            pending_ledger:
                              type: integer
                            excluded_ledger:
                              type: number
                            pending_count:
                              type: integer
                            excluded_count:
                              type: integer
                example:
                  data:
                    as_of_date: '2026-07-20'
                    accounts:
                    - nominal_code_id: 87
                      code: '141'
                      name: Amazon FBA US Inventory
                      pending_ledger: 0
                      excluded_ledger: -299950.38
                      pending_count: 0
                      excluded_count: 41
                    - nominal_code_id: 88
                      code: '142'
                      name: SMO Inventory
                      pending_ledger: -1010.56
                      excluded_ledger: 1498366.15
                      pending_count: 2
                      excluded_count: 239
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-ledger-reconciliation-inventory-unsynced
  /api/ledger/reconciliation/inventory/opening-breakdown:
    get:
      tags:
      - Ledger (Accounting v2)
      summary: Get Inventory Reconciliation Opening Breakdown
      description: 'The warehouse-first opening breakdown for reconciling inventory
        to the accounting provider. For each earmarked inventory control account,
        returns the provider general-ledger balance and its divergence from the SKU
        inventory value at the opening date, broken down into the individual warehouses
        that hold that account''s stock. The provider balance and divergence are reported
        at the account level (a provider account has no warehouse dimension); the
        SKU side sums standard and Amazon FBA inventory per warehouse. Warehouses
        that currently hold no stock are still listed so an account''s full warehouse
        footprint is visible. The opening date is the reconciliation baseline when
        one has been set, otherwise the configured inventory start date. Reads materialized/cached
        data only — no live provider call.


        **Authentication:** Requires Bearer token.


        **Response fields:** `as_of_date` (the effective opening date, null when no
        accounts are earmarked or no opening date is configured), `from_baseline`
        (whether `as_of_date` came from a set baseline rather than the inventory start
        date), `accounts[]` — each with `nominal_code_id`, `code`, `name`, `provider_account_name`,
        `sku_value` (sum of its warehouses), `sku_quantity`, `provider_balance`, `divergence`
        (provider_balance minus sku_value, null when no provider balance is available),
        `point_as_of_date` (the day the provider balance was measured), and `warehouses[]`
        (`warehouse_id`, `warehouse_name`, `is_fba`, `sku_value`, `sku_quantity`).
        Each account also carries `unsynced_ledger` — SKU ledger postings dated on/before
        the opening that haven''t synced to the provider yet; adding it to `divergence`
        shows how much of the opening gap is just unsynced pre-baseline activity (self-resolving)
        versus a true gap. Each account also carries `pending_ledger` (unsynced activity
        dated on/before the opening that WILL sync) and `excluded_ledger` (activity
        that will never sync — the pre-baseline mismatch the baseline sets aside).'
      parameters:
      - name: connection_id
        in: query
        schema:
          type: integer
        description: Accounting connection id. Required.
        example: '5'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      as_of_date:
                        type: string
                      from_baseline:
                        type: boolean
                      accounts:
                        type: array
                        items:
                          type: object
                          properties:
                            nominal_code_id:
                              type: integer
                            code:
                              type: string
                            name:
                              type: string
                            provider_account_name:
                              type: string
                            sku_value:
                              type: number
                            sku_quantity:
                              type: integer
                            provider_balance:
                              type: integer
                            divergence:
                              type: number
                            pending_ledger:
                              type: integer
                            excluded_ledger:
                              type: integer
                            point_as_of_date:
                              type: string
                            warehouses:
                              type: array
                              items:
                                type: object
                                properties:
                                  warehouse_id:
                                    type: integer
                                  warehouse_name:
                                    type: string
                                  is_fba:
                                    type: boolean
                                  sku_value:
                                    type: number
                                  sku_quantity:
                                    type: integer
                example:
                  data:
                    as_of_date: '2024-04-22'
                    from_baseline: true
                    accounts:
                    - nominal_code_id: 88
                      code: '141'
                      name: Amazon FBA US Inventory
                      provider_account_name: Amazon FBA US Inventory
                      sku_value: 4024.84
                      sku_quantity: 65
                      provider_balance: 0
                      divergence: -4024.84
                      pending_ledger: 0
                      excluded_ledger: 0
                      point_as_of_date: '2024-04-22'
                      warehouses:
                      - warehouse_id: 29
                        warehouse_name: FBA US (AMZ)
                        is_fba: true
                        sku_value: 4024.84
                        sku_quantity: 65
                    - nominal_code_id: 87
                      code: '142'
                      name: SMO Inventory
                      provider_account_name: SMO Inventory
                      sku_value: 569792.24
                      sku_quantity: 41250
                      provider_balance: 0
                      divergence: -569792.24
                      pending_ledger: 0
                      excluded_ledger: -125000
                      point_as_of_date: '2024-04-22'
                      warehouses:
                      - warehouse_id: 4
                        warehouse_name: ShipMyOrders Warehouse
                        is_fba: false
                        sku_value: 569792.24
                        sku_quantity: 41250
                      - warehouse_id: 12
                        warehouse_name: Overflow Warehouse
                        is_fba: false
                        sku_value: 0
                        sku_quantity: 0
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-ledger-reconciliation-inventory-opening-breakdown
  /api/ledger/reconciliation/inventory/baseline:
    get:
      tags:
      - Ledger (Accounting v2)
      summary: Get Inventory Reconciliation Baseline
      description: 'The reconcile-opening context for an inventory reconciliation
        connection: the current recon baseline (a "line in the sand" date the divergence
        view is measured from — null when none is set), the inventory start date the
        series otherwise opens from, and the accounting provider''s lock date.


        **Authentication:** Requires Bearer token.


        **Response fields:** `baseline_date` (null when no baseline is set), `baseline_note`,
        `inventory_start_date` (where the series opens from without a baseline), `provider_lock_date`
        (null when the provider reports no lock), `opening_locked` (true when the
        correction date falls on/before the provider lock — corrections then must
        be made on the SKU side, not posted to the provider).'
      parameters:
      - name: connection_id
        in: query
        schema:
          type: integer
        description: Accounting connection id. Required.
        example: '5'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      baseline_date:
                        type: string
                      baseline_note:
                        type: string
                      inventory_start_date:
                        type: string
                      provider_lock_date:
                        type: string
                      opening_locked:
                        type: boolean
                example:
                  data:
                    baseline_date: '2025-01-01'
                    baseline_note: Pre-2025 books unreliable — fresh start
                    inventory_start_date: '2024-04-22'
                    provider_lock_date: '2013-12-31'
                    opening_locked: false
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-ledger-reconciliation-inventory-baseline
    put:
      tags:
      - Ledger (Accounting v2)
      summary: Set Inventory Reconciliation Baseline
      description: 'Draw the reconciliation baseline: measure divergence from `baseline_date`
        forward and freeze the history before it out of the view. View-only and reversible
        — no reconciled figure, opening balance, or start date is changed. Returns
        the refreshed context.


        **Authentication:** Requires Bearer token.


        **Body:** `connection_id` (required), `baseline_date` (required, date), `note`
        (optional, max 500 chars).


        **Response fields:** `baseline_date` (null when no baseline is set), `baseline_note`,
        `inventory_start_date` (where the series opens from without a baseline), `provider_lock_date`
        (null when the provider reports no lock), `opening_locked` (true when the
        correction date falls on/before the provider lock — corrections then must
        be made on the SKU side, not posted to the provider).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                connection_id:
                  type: integer
                baseline_date:
                  type: string
                note:
                  type: string
              example:
                connection_id: 5
                baseline_date: '2025-01-01'
                note: Pre-2025 books unreliable — fresh start
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      baseline_date:
                        type: string
                      baseline_note:
                        type: string
                      inventory_start_date:
                        type: string
                      provider_lock_date:
                        type: string
                      opening_locked:
                        type: boolean
                example:
                  data:
                    baseline_date: '2025-01-01'
                    baseline_note: Pre-2025 books unreliable — fresh start
                    inventory_start_date: '2024-04-22'
                    provider_lock_date: '2013-12-31'
                    opening_locked: false
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: put-api-ledger-reconciliation-inventory-baseline
    delete:
      tags:
      - Ledger (Accounting v2)
      summary: Clear Inventory Reconciliation Baseline
      description: 'Remove the reconciliation baseline; the full history returns to
        the divergence view. Returns the refreshed context.


        **Authentication:** Requires Bearer token.


        **Response fields:** `baseline_date` (null when no baseline is set), `baseline_note`,
        `inventory_start_date` (where the series opens from without a baseline), `provider_lock_date`
        (null when the provider reports no lock), `opening_locked` (true when the
        correction date falls on/before the provider lock — corrections then must
        be made on the SKU side, not posted to the provider).'
      parameters:
      - name: connection_id
        in: query
        schema:
          type: integer
        description: Accounting connection id. Required.
        example: '5'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      baseline_date:
                        type: string
                        nullable: true
                      baseline_note:
                        type: string
                        nullable: true
                      inventory_start_date:
                        type: string
                      provider_lock_date:
                        type: string
                      opening_locked:
                        type: boolean
                example:
                  data:
                    baseline_date: null
                    baseline_note: null
                    inventory_start_date: '2024-04-22'
                    provider_lock_date: '2013-12-31'
                    opening_locked: false
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: delete-api-ledger-reconciliation-inventory-baseline
  /api/ledger/reconciliation/inventory/adjustment/preview:
    get:
      tags:
      - Ledger (Accounting v2)
      summary: Get Inventory Reconciliation Adjustment Preview
      description: 'The proposed adjusting journal that would move the provider''s
        inventory control account to match SKU as of a date — computed read-only so
        you see exactly what would post. `divergence = provider − SKU`; a positive
        gap credits the inventory control account (reducing it) and debits the counter,
        both for the same amount. When the date is inside a locked provider period
        `postable` is false: post the journal dated on or after `earliest_postable_date`
        instead. Accounts backed by Amazon warehouses (FBA/AWD) are Amazon-sourced
        — their stock comes from Amazon and cannot be adjusted in SKU (`sku_side_adjustable`
        is false), so they can only be reconciled provider-side; other accounts may
        instead correct SKU''s opening for the warehouses in `warehouses`.


        **Authentication:** Requires Bearer token.


        **Response fields:** `divergence`, `amount`, `needs_adjustment`, `direction_summary`,
        `counter_nominal_code_id`/`counter_code`/`counter_name`, `postable`, `blocked_reason`,
        `provider_lock_date`, `sku_side_adjustable` (whether the account has editable
        non-Amazon warehouses), `earliest_postable_date` (first date the provider
        accepts a post — lock date + 1 day, null when unlocked), `lines[]` (`nominal_code_id`,
        `code`, `name`, `direction`, `amount`), `warehouses[]` (`id`, `name` — the
        SKU-adjustable, non-Amazon warehouses the SKU-side fix can target). `already_adjusted`
        is true when this account was already reconciled on this date (posting is
        blocked to avoid double-correcting), with `existing_adjustment_id` pointing
        at the prior adjustment.'
      parameters:
      - name: connection_id
        in: query
        schema:
          type: integer
        description: Accounting connection id. Required.
        example: '5'
      - name: nominal_code_id
        in: query
        schema:
          type: integer
        description: The earmarked inventory control account. Required.
        example: '87'
      - name: effective_date
        in: query
        schema:
          type: string
        description: The date to align at. Required.
        example: '2024-04-22'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      nominal_code_id:
                        type: integer
                      code:
                        type: string
                      name:
                        type: string
                      provider_account_name:
                        type: string
                      effective_date:
                        type: string
                      divergence:
                        type: number
                      amount:
                        type: number
                      needs_adjustment:
                        type: boolean
                      direction_summary:
                        type: string
                      counter_nominal_code_id:
                        type: integer
                      counter_code:
                        type: string
                      counter_name:
                        type: string
                      postable:
                        type: boolean
                      blocked_reason:
                        type: string
                        nullable: true
                      provider_lock_date:
                        type: string
                      sku_side_adjustable:
                        type: boolean
                      earliest_postable_date:
                        type: string
                      already_adjusted:
                        type: boolean
                      existing_adjustment_id:
                        type: string
                        nullable: true
                      lines:
                        type: array
                        items:
                          type: object
                          properties:
                            nominal_code_id:
                              type: integer
                            code:
                              type: string
                            name:
                              type: string
                            direction:
                              type: string
                            amount:
                              type: number
                      warehouses:
                        type: array
                example:
                  data:
                    nominal_code_id: 87
                    code: '141'
                    name: Amazon FBA US Inventory
                    provider_account_name: Amazon FBA US Inventory
                    effective_date: '2024-04-22'
                    divergence: 104005.26
                    amount: 104005.26
                    needs_adjustment: true
                    direction_summary: Credit Amazon FBA US Inventory and debit Opening
                      Balance Equity — reduces the provider GL to match SKU.
                    counter_nominal_code_id: 94
                    counter_code: '970'
                    counter_name: Opening Balance Equity
                    postable: true
                    blocked_reason: null
                    provider_lock_date: '2013-12-31'
                    sku_side_adjustable: false
                    earliest_postable_date: '2014-01-01'
                    already_adjusted: false
                    existing_adjustment_id: null
                    lines:
                    - nominal_code_id: 87
                      code: '141'
                      name: Amazon FBA US Inventory
                      direction: credit
                      amount: 104005.26
                    - nominal_code_id: 94
                      code: '970'
                      name: Opening Balance Equity
                      direction: debit
                      amount: 104005.26
                    warehouses: []
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-ledger-reconciliation-inventory-adjustment-preview
  /api/ledger/reconciliation/inventory/adjustment/journal:
    get:
      tags:
      - Ledger (Accounting v2)
      summary: Get Inventory Reconciliation Adjustment Journal
      description: 'Where a posted inventory reconciliation adjustment landed in SKU''s
        ledger — so a client can deep-link the user to the journal entry the adjustment
        created. The adjustment posts asynchronously, so immediately after posting
        this returns `pending: true` with null ids; poll it with the returned `adjustment_id`
        until `pending` is false, then use `journal_entry_id` to open the journal.


        **Authentication:** Requires Bearer token.


        **Response fields:** `pending` (true until the journal exists), `journal_entry_id`
        (the created journal entry''s id, null while pending), `reference` (the journal''s
        reference, e.g. `INV-RECON-ADJ-1`), `status` (the journal''s lifecycle state,
        e.g. `draft` or `posted`), `deletable` (true while the journal has not yet
        synced to the provider — so the adjustment can be reversed and discarded cleanly).'
      parameters:
      - name: connection_id
        in: query
        schema:
          type: integer
        description: Accounting connection id. Required.
        example: '5'
      - name: adjustment_id
        in: query
        schema:
          type: integer
        description: The posted adjustment id (returned by the post endpoint). Required.
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      pending:
                        type: boolean
                      journal_entry_id:
                        type: integer
                      reference:
                        type: string
                      status:
                        type: string
                      deletable:
                        type: boolean
                example:
                  data:
                    pending: false
                    journal_entry_id: 49687
                    reference: INV-RECON-ADJ-1
                    status: draft
                    deletable: true
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-ledger-reconciliation-inventory-adjustment-journal
  /api/ledger/reconciliation/inventory/adjustment/counter-account:
    post:
      tags:
      - Ledger (Accounting v2)
      summary: Ensure Adjustment Counter Account
      description: 'Ensure a conventional "Opening Balance Equity" counter account
        exists (creating it if the chart of accounts has none), so the adjusting journal''s
        balancing leg has a target. Idempotent — reuses an existing opening-balance-named
        account.


        **Authentication:** Requires Bearer token.


        **Body:** `connection_id` (required).


        **Response:** `{ data: { id, code, name } }`.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                connection_id:
                  type: integer
              example:
                connection_id: 5
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      code:
                        type: string
                      name:
                        type: string
                example:
                  data:
                    id: 94
                    code: '970'
                    name: Opening Balance Equity
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-ledger-reconciliation-inventory-adjustment-counter-account
  /api/ledger/reconciliation/inventory/adjustment:
    post:
      tags:
      - Ledger (Accounting v2)
      summary: Post Inventory Reconciliation Adjustment
      description: 'Post the adjusting journal to bring the provider''s inventory
        control account into line with SKU. The amount and direction are recomputed
        server-side from the divergence (the client can''t post an arbitrary figure);
        the balanced journal is posted to the provider as a manual journal. An already-aligned
        or locked-period account is rejected 422.


        **Authentication:** Requires Bearer token.


        **Body:** `connection_id` (required), `nominal_code_id` (required), `counter_nominal_code_id`
        (required), `effective_date` (required, date), `note` (optional, max 500 chars).


        **Response:** `{ data: { adjustment_id }, message }`.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                connection_id:
                  type: integer
                nominal_code_id:
                  type: integer
                counter_nominal_code_id:
                  type: integer
                effective_date:
                  type: string
                note:
                  type: string
              example:
                connection_id: 5
                nominal_code_id: 87
                counter_nominal_code_id: 94
                effective_date: '2024-04-22'
                note: Align opening to SKU
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      adjustment_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    adjustment_id: 12
                  message: Adjusting journal posted — it will sync to the provider.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: The provider period is locked on this date — post the fix
                    on the SKU side instead.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-ledger-reconciliation-inventory-adjustment
    delete:
      tags:
      - Ledger (Accounting v2)
      summary: Reverse Inventory Reconciliation Adjustment
      description: 'Reverse (delete) a posted inventory reconciliation adjustment
        while its journal has not yet synced to the accounting provider, discarding
        the draft journal so the opening can be re-reconciled (for example, at a corrected
        date). Once the journal has synced to the provider this returns 422 — undoing
        it then requires posting a reversing entry in the provider.


        **Authentication:** Requires Bearer token.


        **Query parameters:** `connection_id` (required), `adjustment_id` (required
        — the adjustment returned by the post endpoint).


        **Behavior:** discards the adjustment''s unsynced draft journal via the standard
        source-deleted pathway; the SKU inventory value is unchanged.'
      parameters:
      - name: connection_id
        in: query
        schema:
          type: integer
        description: Accounting connection id. Required.
        example: '5'
      - name: adjustment_id
        in: query
        schema:
          type: integer
        description: The posted adjustment id to reverse. Required.
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Adjustment reversed — its journal was discarded.
        '422':
          description: Unprocessable Content
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: This adjustment's journal has already synced to your provider
                    and can't be deleted here — post a reversing entry in your provider
                    instead.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: delete-api-ledger-reconciliation-inventory-adjustment
  /api/ledger/reconciliation/inventory/sync-estimate:
    get:
      tags:
      - Ledger (Accounting v2)
      summary: Provider GL Sync Estimate
      description: 'A **pre-flight, zero-API** estimate for the unified provider GL
        sync (Lane 2): how many Xero calls the operation would cost for the chosen
        window against how many remain in today''s API budget, so the user can weigh
        it before spending any of it. Computed locally from the cached journal cadence
        (distinct journals over their date span) plus the one Trial Balance anchor
        call — it makes **no** calls to the provider.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Authentication:** Requires Bearer token.


        **Query parameters:**

        - `connection_id` (integer, **required**): accounting connection id whose
        journals/budget are estimated.

        - `from` (date, optional): window start (Y-m-d). Clamped up to the Inventory
        Start Date — an earlier value never lowers the window below the opening-balance
        anchor. Defaults to the Inventory Start Date.

        - `to` (date, optional, `after_or_equal:from`): window end (Y-m-d). Defaults
        to today.


        **Response (`data`):**

        - `can_sync` (boolean): false when the Inventory Start Date is unset (no lower
        bound to anchor against); `reason` explains why.

        - `reason` (string|null): why the sync can''t run, when `can_sync` is false.

        - `cadence_known` (boolean): false on a first-ever sync (nothing cached to
        extrapolate from) — then `estimated_calls` is null.

        - `estimated_calls` (integer|null): total projected Xero calls (pages + probes
        + anchor). Null when cadence is unknown.

        - `estimated_pages` (integer|null): projected forward Journals pages (incl.
        the terminating empty page).

        - `estimated_probe_calls` (integer): binary-search probe calls to locate a
        start offset below the cache (0 when resuming above the cache or from empty).

        - `anchor_calls` (integer): 0 or 1 — the metered Trial Balance call, charged
        only when no anchor has been captured for the opening day yet.

        - `journals_per_day` (number|null): the cached cadence the page count is extrapolated
        from.

        - `daily_remaining` (integer|null): Xero calls left in today''s budget (from
        the connection''s tracked usage; null if not tracked yet).

        - `daily_limit` (integer): Xero''s per-organisation daily API cap (5000).

        - `daily_reset_at` (string|null): ISO8601 timestamp when the daily budget
        resets.

        - `over_budget` (boolean): true when `estimated_calls` exceeds `daily_remaining`.

        - `inventory_start_date` (string|null): Y-m-d lower bound of the window.

        - `window_from` (string|null): Y-m-d clamped window start actually estimated.

        - `window_to` (string): Y-m-d window end actually estimated.

        - `cached_from` / `cached_to` (string|null): Y-m-d span of journals already
        cached.'
      parameters:
      - name: connection_id
        in: query
        schema:
          type: integer
        description: Accounting connection id (the provider's integration instance).
          Required.
        example: '5'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 OK (cadence known, within budget)
                  value:
                    data:
                      can_sync: true
                      reason: null
                      cadence_known: true
                      estimated_calls: 19
                      estimated_pages: 18
                      estimated_probe_calls: 0
                      anchor_calls: 1
                      journals_per_day: 9.42
                      daily_remaining: 4870
                      daily_limit: 5000
                      daily_reset_at: '2026-06-28T00:00:00+00:00'
                      over_budget: false
                      inventory_start_date: '2026-01-01'
                      window_from: '2026-01-01'
                      window_to: '2026-06-27'
                      cached_from: '2026-03-15'
                      cached_to: '2026-06-20'
                example-1:
                  summary: 200 OK (Inventory Start Date unset — cannot sync)
                  value:
                    data:
                      can_sync: false
                      reason: Set the Inventory Start Date first.
                      cadence_known: false
                      estimated_calls: null
                      estimated_pages: null
                      estimated_probe_calls: 0
                      anchor_calls: 0
                      journals_per_day: null
                      daily_remaining: 4870
                      daily_limit: 5000
                      daily_reset_at: '2026-06-28T00:00:00+00:00'
                      over_budget: false
                      inventory_start_date: null
                      window_from: null
                      window_to: '2026-06-27'
                      cached_from: null
                      cached_to: null
        '422':
          description: Unprocessable Content
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      connection_id:
                        type: array
                        items:
                          type: string
                example:
                  message: The connection id field is required.
                  errors:
                    connection_id:
                    - The connection id field is required.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-ledger-reconciliation-inventory-sync-estimate
  /api/ledger/reconciliation/inventory/rebuild:
    post:
      tags:
      - Ledger (Accounting v2)
      summary: Rebuild Inventory Daily Series
      description: 'Kick the background tracked job that materializes the **SKU side**
        of the daily series (point-in-time inventory value per account per day). Free
        — no provider calls. Returns the tracked job log id so the UI can follow it
        in the global progress tray.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Authentication:** Requires Bearer token + `accounting.sync` permission.


        **Request body:**

        - `connection_id` (integer, **required**): accounting connection id the points
        are keyed to.

        - `nominal_code_ids` (array, optional): subset of earmarked account ids. Defaults
        to all earmarked.

        - `from` (date, optional): local-day window start. Defaults to the inventory
        start date.

        - `to` (date, optional, after_or_equal:from): local-day window end. Defaults
        to now.


        Window defaults span inventory_start_date → today (~hundreds of days), so
        this is a long-running job.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                connection_id:
                  type: integer
                nominal_code_ids:
                  type: array
                  items:
                    type: integer
                from:
                  type: string
                to:
                  type: string
              example:
                connection_id: 5
                nominal_code_ids:
                - 87
                from: '2026-01-01'
                to: '2026-06-27'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 4821
                  message: Inventory reconciliation rebuild started
        '422':
          description: Unprocessable Content
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      connection_id:
                        type: array
                        items:
                          type: string
                example:
                  message: The connection id field is required.
                  errors:
                    connection_id:
                    - The connection id field is required.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-ledger-reconciliation-inventory-rebuild
  /api/ledger/reconciliation/inventory/capture-provider:
    post:
      tags:
      - Ledger (Accounting v2)
      summary: Capture Provider Inventory Balances
      description: 'Capture the provider''s GL balance for the earmarked inventory
        accounts as-of a day onto the daily series — the metered counterpart to the
        (free) SKU-side rebuild. **Makes one live Xero Trial Balance call** (needs
        `accounting.reports.read`), so callers drive the cadence; the provider series
        is intentionally sparse (only captured days get a row). Days/accounts with
        no matching provider account are skipped.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Authentication:** Requires Bearer token + `accounting.sync` permission.


        **Request body:**

        - `connection_id` (integer, **required**): accounting connection id.

        - `to` (date, optional): as-of day for the Trial Balance. Defaults to now.


        Returns `{ captured: <number of accounts written> }`.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                connection_id:
                  type: integer
                to:
                  type: string
              example:
                connection_id: 5
                to: '2026-06-27'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      captured:
                        type: integer
                  success:
                    type: boolean
                example:
                  data:
                    captured: 1
                  success: true
        '422':
          description: Unprocessable Content
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      connection_id:
                        type: array
                        items:
                          type: string
                example:
                  message: The connection id field is required.
                  errors:
                    connection_id:
                    - The connection id field is required.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-ledger-reconciliation-inventory-capture-provider
  /api/ledger/reconciliation/inventory/sync-journals:
    post:
      tags:
      - Ledger (Accounting v2)
      summary: Sync Provider GL Journals
      description: 'Kick the background tracked job that pulls the provider''s **GL
        journals feed** (Xero Journals) into the local cache — the metered half of
        the daily reconciliation. One paginated pull per run; resumes incrementally
        from the highest JournalNumber already cached. Once cached, **Rebuild Inventory
        Daily Series** reconstructs the daily provider balance from the cache with
        no further provider call. Returns the tracked job log id so the UI can follow
        it in the global progress tray.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Authentication:** Requires Bearer token + `accounting.sync` permission.


        **Request body:**

        - `connection_id` (integer, **required**): accounting connection id (the provider''s
        integration instance) whose journals are pulled.

        - `from` (date `Y-m-d`, optional): lower-bounds the pull by journal date.
        Clamped up to the Inventory Start Date (the opening anchor replaces summing
        the ledger before it), so an earlier value is accepted but never lowers the
        window below the anchor. When omitted, the window starts at the Inventory
        Start Date.

        - `full` (boolean, optional, default `false`): when `true`, re-pulls the entire
        ledger from JournalNumber 0 instead of resuming incrementally from the highest
        cached journal.


        **Side effect:** makes metered API calls to the accounting provider (one page
        per ~100 journals), capped at the connection''s remaining daily Xero API budget
        — a budget-out pauses the run cleanly and it auto-resumes once the budget
        refreshes.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                connection_id:
                  type: integer
                from:
                  type: string
                full:
                  type: boolean
              example:
                connection_id: 5
                from: '2026-01-01'
                full: false
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 4822
                  message: Provider GL journals sync started
        '422':
          description: Unprocessable Content
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      connection_id:
                        type: array
                        items:
                          type: string
                example:
                  message: The connection id field is required.
                  errors:
                    connection_id:
                    - The connection id field is required.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-ledger-reconciliation-inventory-sync-journals
  /api/ledger/reconciliation/bank-statements:
    get:
      tags:
      - Ledger (Accounting v2)
      summary: List Statement Imports
      description: 'Paginated list of prior bank-statement screenshot extractions
        (most recent first), each with its parsed line count and spent/received totals.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Authentication:** Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        status:
                          type: string
                        source:
                          type: string
                        original_filename:
                          type: string
                        line_count:
                          type: integer
                        spent_total:
                          type: string
                        received_total:
                          type: string
                        error_message:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                  current_page:
                    type: integer
                  per_page:
                    type: integer
                  last_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - id: 6
                    status: ready
                    source: upload
                    original_filename: statement.png
                    line_count: 2
                    spent_total: '621.1100'
                    received_total: '144.2200'
                    error_message: null
                    created_at: '2026-06-28T10:00:00+00:00'
                  current_page: 1
                  per_page: 15
                  last_page: 1
                  total: 1
                  from: 1
                  to: 1
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-ledger-reconciliation-bank-statements
    post:
      tags:
      - Ledger (Accounting v2)
      summary: Upload Statement Screenshot
      description: 'Upload a screenshot of bank statement lines and **queue** its
        OCR extraction (Azure Document Intelligence prebuilt-layout). Returns immediately
        with the import in the `extracting` state plus a top-level `tracked_job_log_id`;
        the parsed lines arrive once the background a background job completes (watch
        it via the tracked job log endpoints, then re-fetch the import via GET `.../bank-statements/{id}`).
        Deferring the OCR keeps an unreachable provider from hanging the upload request.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Xero exposes no API for raw statement lines, hence the screenshot path. Handles
        both Xero layouts: the cash-coding grid (one line per row) and the two-column
        reconcile card view (date / description / type stacked in one column).


        **Content-Type:** multipart/form-data.

        **Authentication:** Requires Bearer token.


        If the OCR provider cannot read the image, the job flips the import to `failed`
        with an `error_message` (surfaced via the tracked job log endpoints and on
        re-fetch) — the upload request itself still succeeds.'
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                image:
                  type: string
                  description: Required. Screenshot of the bank statement lines (Xero
                    reconcile / cash-coding view). PNG, JPG, or WEBP; max 10 MB.
                  format: binary
                source:
                  type: string
                  description: Optional. 'upload' or 'clipboard'. Defaults to 'upload'.
                  example: upload
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      status:
                        type: string
                      source:
                        type: string
                      original_filename:
                        type: string
                      line_count:
                        type: integer
                      spent_total:
                        type: string
                        nullable: true
                      received_total:
                        type: string
                        nullable: true
                      error_message:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      lines:
                        type: array
                  tracked_job_log_id:
                    type: integer
                example:
                  data:
                    id: 6
                    status: extracting
                    source: upload
                    original_filename: statement.png
                    line_count: 0
                    spent_total: null
                    received_total: null
                    error_message: null
                    created_at: '2026-06-28T10:00:00+00:00'
                    lines: []
                  tracked_job_log_id: 42
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-ledger-reconciliation-bank-statements
  /api/ledger/reconciliation/bank-statements/{bankStatementImport}:
    get:
      tags:
      - Ledger (Accounting v2)
      summary: Get Statement Import
      description: 'A single statement-screenshot extraction with all its parsed lines.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Authentication:** Requires Bearer token.'
      parameters:
      - name: bankStatementImport
        in: path
        schema:
          type: integer
        required: true
        description: Import id.
        example: '6'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      status:
                        type: string
                      source:
                        type: string
                      original_filename:
                        type: string
                      line_count:
                        type: integer
                      spent_total:
                        type: string
                      received_total:
                        type: string
                      error_message:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            bank_statement_import_id:
                              type: integer
                            statement_date:
                              type: string
                            payee:
                              type: string
                              nullable: true
                            description:
                              type: string
                            reference:
                              type: string
                            spent:
                              type: string
                              nullable: true
                            received:
                              type: string
                            direction:
                              type: string
                            match_status:
                              type: string
                            sort_order:
                              type: integer
                example:
                  data:
                    id: 6
                    status: ready
                    source: upload
                    original_filename: statement.png
                    line_count: 2
                    spent_total: '621.1100'
                    received_total: '144.2200'
                    error_message: null
                    created_at: '2026-06-28T10:00:00+00:00'
                    lines:
                    - id: 11
                      bank_statement_import_id: 6
                      statement_date: '2025-12-15'
                      payee: null
                      description: ORIG CO NAME:Amazon Mexico Se
                      reference: POSCREDIT
                      spent: null
                      received: '144.2200'
                      direction: received
                      match_status: unmatched
                      sort_order: 0
                    - id: 12
                      bank_statement_import_id: 6
                      statement_date: '2026-01-08'
                      payee: null
                      description: Online ACH Payment To Stainout
                      reference: BILLPAYMENT
                      spent: '621.1100'
                      received: null
                      direction: spent
                      match_status: unmatched
                      sort_order: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-ledger-reconciliation-bank-statements-bankstatementimport
    delete:
      tags:
      - Ledger (Accounting v2)
      summary: Delete Statement Import
      description: 'Delete a statement extraction and its parsed lines.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Authentication:** Requires Bearer token.'
      parameters:
      - name: bankStatementImport
        in: path
        schema:
          type: integer
        required: true
        description: Import id.
        example: '6'
      responses:
        '204':
          description: No Content
          content:
            text/plain:
              schema:
                type: string
                example: ''
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-ledger-reconciliation-bank-statements-bankstatementimport
  /api/ledger/reconciliation/bank-statements/{bankStatementImport}/suggestions:
    get:
      tags:
      - Ledger (Accounting v2)
      summary: List Line Match Suggestions
      description: 'For each parsed line in an import, candidate SKU ledger entries
        it could reconcile against. Money-in lines (Received) match AR documents (Sales
        Order Invoice, Vendor Credit); money-out lines (Spent) match AP documents
        (Bill, Purchase Order Invoice, Sales Credit). Candidates are entries of the
        matching type whose total is within $0.01 of the line amount and whose effective
        date is within 60 days of the statement date, ranked by date proximity then
        amount closeness. `synced` flags entries already pushed to the provider.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Authentication:** Requires Bearer token.


        **Candidate kinds:** `match_kind=entry` is a single SKU document; `match_kind=settlement`
        is an Amazon settlement aggregate — matched on the settlement''s recorded
        payout (amazon_financial_event_groups.ConvertedTotalCurrencyAmount), carrying
        every ledger entry it generated in `entry_ids` (sales invoices + fee bills
        + carved-out landed-cost bills linked via amazon_report_settlement_data).
        Confirming a settlement candidate POSTs all of `entry_ids`.


        Settlement candidates carry `settlement_id` (the AmazonFinancialEventGroup
        id — links to /integrations/amazon/finance/bank-transaction/{id}), `settlement_reference`
        (the FinancialEventGroupId shown as the settlement #), and `entries[]` (each
        linked ledger entry: id, reference, entry_type_label, is_landed_cost) so the
        UI can deep-link every document.


        **Per-suggestion `dismissed_count`** (integer): how many candidates the user
        has declared “not a match” on this line (via Dismiss Line Match Suggestion).
        Dismissed candidates are excluded from `candidates` and restorable as a set
        via Restore Dismissed Suggestions.


        **Group candidates** (`match_kind=group`): several of one supplier''s documents
        that together settle a money-out payment. When the line''s memo names the
        supplier, combinations may also NET vendor credits against the invoices (payment
        = invoices − credits) — the label reads e.g. ''2 invoices − 1 credit'' and
        `amount` is the net. Each `entries[]` element carries its own `entry_type`,
        `amount`, `counterparty_name` and `effective_at` so the UI renders a signed
        calculation.'
      parameters:
      - name: bankStatementImport
        in: path
        schema:
          type: integer
        required: true
        description: Import id.
        example: '24'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        line:
                          type: object
                          properties:
                            id:
                              type: integer
                            bank_statement_import_id:
                              type: integer
                            statement_date:
                              type: string
                            payee:
                              type: string
                              nullable: true
                            description:
                              type: string
                            reference:
                              type: string
                            spent:
                              type: string
                              nullable: true
                            received:
                              type: string
                            direction:
                              type: string
                            match_status:
                              type: string
                            sort_order:
                              type: integer
                            matches:
                              type: array
                        candidates:
                          type: array
                          items:
                            type: object
                            properties:
                              match_kind:
                                type: string
                              amount:
                                type: string
                              effective_at:
                                type: string
                              source_label:
                                type: string
                              synced:
                                type: boolean
                              ledger_journal_entry_id:
                                type: integer
                              entry_type:
                                type: string
                              entry_type_label:
                                type: string
                              counterparty_name:
                                type: string
                              reference:
                                type: string
                              currency_code:
                                type: string
                              source_type:
                                type: string
                              source_id:
                                type: integer
                example:
                  data:
                  - line:
                      id: 451
                      bank_statement_import_id: 23
                      statement_date: '2026-04-28'
                      payee: null
                      description: ORIG CO NAME:Amazon Mexico
                      reference: POSCREDIT
                      spent: null
                      received: '432.2700'
                      direction: received
                      match_status: unmatched
                      sort_order: 0
                      matches: []
                    candidates:
                    - match_kind: entry
                      amount: '432.2700'
                      effective_at: '2026-04-26'
                      source_label: Bill
                      synced: false
                      ledger_journal_entry_id: 612
                      entry_type: bill
                      entry_type_label: Bill
                      counterparty_name: Acme Supplies Inc
                      reference: …
                      currency_code: USD
                      source_type: App\Models\Bill
                      source_id: 91
                    - match_kind: settlement
                      amount: '432.2700'
                      effective_at: '2026-04-28'
                      source_label: Amazon Settlement
                      synced: false
                      settlement_id: 350
                      settlement_reference: 5cKTkaXNDp…
                      entry_ids:
                      - 700
                      - 701
                      - 702
                      entry_count: 3
                      components:
                      - label: Sales Order Invoice
                        count: 1
                        amount: '1274.9395'
                      - label: Bill
                        count: 1
                        amount: '1305.8630'
                      - label: Landed-cost Bill
                        count: 1
                        amount: '129.8400'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-ledger-reconciliation-bank-statements-bankstatementimport-suggestions
  /api/ledger/reconciliation/bank-statements/lines/{bankStatementLine}/match:
    post:
      tags:
      - Ledger (Accounting v2)
      summary: Confirm Line Match
      description: 'Confirm one or more ledger entries as the match for a line. Persists
        a denormalized snapshot of each match (so it survives ledger rebuilds) and
        marks the line `matched`. Idempotent — re-matching the same entry is a no-op.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Body:** `entry_ids` (required array of ledger_journal_entry ids).

        **Authentication:** Requires Bearer token.


        **`sync_block`** (on each line): pre-push sync verdict for the line''s matched
        document(s) — `null` when every document will sync, otherwise `{ blocked:
        true, enableable: bool, reasons: string[], blocked_entry_ids: int[], enableable_entry_ids:
        int[] }`. Surfaced so the UI can warn (and offer Enable sync) BEFORE a push
        that would otherwise silently not reach Xero.


        **Optional Amazon-settlement context** (omit for a single-document match):
        `match_kind` (''entry'' | ''settlement''), `settlement_id` (required when
        match_kind=settlement), `settlement_reference`, `settlement_payout` (the net
        payout the bank line matched on). When present, every persisted match row
        records the settlement so the UI labels it an ''Amazon Settlement · {payout}''
        regardless of how many SKU documents it touched.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                entry_ids:
                  type: array
                  items:
                    type: integer
                match_kind:
                  type: string
                settlement_id:
                  type: integer
                settlement_reference:
                  type: string
                settlement_payout:
                  type: string
              example:
                entry_ids:
                - 10
                match_kind: settlement
                settlement_id: 337
                settlement_reference: 5cKTkaXNDpXqmNv0MzaOHAMppp6CsZOYXrgMbDv4UDg
                settlement_payout: '432.27'
      parameters:
      - name: bankStatementLine
        in: path
        schema:
          type: integer
        required: true
        description: Statement line id.
        example: '479'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      bank_statement_import_id:
                        type: integer
                      statement_date:
                        type: string
                      payee:
                        type: string
                        nullable: true
                      description:
                        type: string
                      reference:
                        type: string
                      spent:
                        type: string
                      received:
                        type: string
                        nullable: true
                      direction:
                        type: string
                      match_status:
                        type: string
                      sort_order:
                        type: integer
                      sync_block:
                        type: string
                        nullable: true
                      matches:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            ledger_journal_entry_id:
                              type: integer
                            entry_type:
                              type: string
                            entry_type_label:
                              type: string
                            match_kind:
                              type: string
                            settlement_id:
                              type: integer
                            settlement_reference:
                              type: string
                            settlement_payout:
                              type: string
                            reference:
                              type: string
                            counterparty_name:
                              type: string
                            amount:
                              type: string
                            effective_at:
                              type: string
                            source_type:
                              type: string
                            source_id:
                              type: integer
                            source_label:
                              type: string
                example:
                  data:
                    id: 479
                    bank_statement_import_id: 24
                    statement_date: '2024-04-26'
                    payee: null
                    description: ACH Payment to supplier A
                    reference: BILLPAYMENT
                    spent: '73.9000'
                    received: null
                    direction: spent
                    match_status: matched
                    sort_order: 0
                    sync_block: null
                    matches:
                    - id: 1
                      ledger_journal_entry_id: 10
                      entry_type: bill
                      entry_type_label: Bill
                      match_kind: settlement
                      settlement_id: 337
                      settlement_reference: 5cKTkaXNDpXqmNv0MzaOHAMppp6CsZOYXrgMbDv4UDg
                      settlement_payout: '432.2700'
                      reference: xjwbaRFTPT8...
                      counterparty_name: Supplier A
                      amount: '73.9000'
                      effective_at: '2024-04-24'
                      source_type: App\Models\Bill
                      source_id: 42
                      source_label: Bill
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-ledger-reconciliation-bank-statements-lines-bankstatementline-match
    delete:
      tags:
      - Ledger (Accounting v2)
      summary: Clear Line Match
      description: 'Remove all confirmed matches for a line and mark it `unmatched`.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Authentication:** Requires Bearer token.'
      parameters:
      - name: bankStatementLine
        in: path
        schema:
          type: integer
        required: true
        description: Statement line id.
        example: '479'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      bank_statement_import_id:
                        type: integer
                      statement_date:
                        type: string
                      payee:
                        type: string
                        nullable: true
                      description:
                        type: string
                      reference:
                        type: string
                      spent:
                        type: string
                      received:
                        type: string
                        nullable: true
                      direction:
                        type: string
                      match_status:
                        type: string
                      sort_order:
                        type: integer
                      matches:
                        type: array
                example:
                  data:
                    id: 479
                    bank_statement_import_id: 24
                    statement_date: '2024-04-26'
                    payee: null
                    description: ACH Payment to supplier A
                    reference: BILLPAYMENT
                    spent: '73.9000'
                    received: null
                    direction: spent
                    match_status: unmatched
                    sort_order: 0
                    matches: []
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-ledger-reconciliation-bank-statements-lines-bankstatementline-match
  /api/ledger/reconciliation/bank-statements/lines/{bankStatementLine}/dismiss-match:
    post:
      tags:
      - Ledger (Accounting v2)
      summary: Dismiss Line Match Suggestion
      description: 'Declare a suggested candidate "not a match" for this line. The
        candidate''s identity is pinned to the line (order-independent fingerprint),
        so the same document/combination is never re-offered by Line Match Suggestions
        or confirmed by Auto-match — and a dismissed group combination''s per-supplier
        slot frees up for the next-best combination on the next refresh. Undone by
        the Restore Dismissed Suggestions endpoint.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Body:**

        - `match_kind` (required, ''entry'' | ''settlement'' | ''group'') — the candidate''s
        kind exactly as the suggestions endpoint returned it.

        - `entry_ids` (required unless match_kind=settlement, array of integers) —
        the candidate''s ledger entry id(s); order does not matter.

        - `settlement_id` (required when match_kind=settlement, integer) — the Amazon
        settlement id.


        **Authentication:** Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                match_kind:
                  type: string
                entry_ids:
                  type: array
                  items:
                    type: integer
              example:
                match_kind: group
                entry_ids:
                - 338
                - 5348
                - 5623
      parameters:
      - name: bankStatementLine
        in: path
        schema:
          type: integer
        required: true
        description: Statement line id.
        example: '93'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                  data:
                    type: array
                example:
                  success: true
                  message: Dismissed — that combination will not be suggested again.
                  data: []
        '422':
          description: Unprocessable Content
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      entry_ids:
                        type: array
                        items:
                          type: string
                example:
                  message: The entry ids field is required unless match kind is in
                    settlement.
                  errors:
                    entry_ids:
                    - The entry ids field is required unless match kind is in settlement.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-ledger-reconciliation-bank-statements-lines-bankstatementline-dismiss-match
  /api/ledger/reconciliation/bank-statements/lines/{bankStatementLine}/dismissals:
    delete:
      tags:
      - Ledger (Accounting v2)
      summary: Restore Dismissed Suggestions
      description: 'Clear every "not a match" verdict on the line, putting all dismissed
        candidates back into circulation — they reappear on the next Line Match Suggestions
        call. Returns how many dismissals were removed.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Authentication:** Requires Bearer token.'
      parameters:
      - name: bankStatementLine
        in: path
        schema:
          type: integer
        required: true
        description: Statement line id.
        example: '93'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      restored:
                        type: integer
                example:
                  success: true
                  message: Dismissed suggestions restored.
                  data:
                    restored: 2
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-ledger-reconciliation-bank-statements-lines-bankstatementline-dismissals
  /api/ledger/reconciliation/bank-statements/{bankStatementImport}/auto-match:
    post:
      tags:
      - Ledger (Accounting v2)
      summary: Auto-match Single-candidate Lines
      description: 'Confirm every still-unmatched line in the import that has EXACTLY
        ONE candidate (an unambiguous match). Lines with zero or multiple candidates
        are left for the user. Optional body `line_ids` scopes it to a selection (bulk-match
        the ticked rows); omit to match all.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Returns the number matched and the refreshed import (lines + their matches).


        **Authentication:** Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                line_ids:
                  type: array
                  items:
                    type: integer
              example:
                line_ids:
                - 479
                - 480
      parameters:
      - name: bankStatementImport
        in: path
        schema:
          type: integer
        required: true
        description: Import id.
        example: '23'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      matched:
                        type: integer
                      import:
                        type: object
                        properties:
                          id:
                            type: integer
                          status:
                            type: string
                          line_count:
                            type: integer
                          lines:
                            type: array
                            items:
                              type: string
                example:
                  data:
                    matched: 31
                    import:
                      id: 23
                      status: ready
                      line_count: 38
                      lines:
                      - …
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-ledger-reconciliation-bank-statements-bankstatementimport-auto-match
  /api/ledger/reconciliation/bank-statements/{bankStatementImport}/unmatch-all:
    post:
      tags:
      - Ledger (Accounting v2)
      summary: Unmatch All Lines
      description: 'Clear the confirmed matches across the import (bulk unmatch).
        Only lines whose `match_status` is `matched` are affected; the linked SKU
        documents are untouched — only the bank-line links are removed. Optional body
        `line_ids` scopes it to a selection (unmatch the ticked rows); omit to unmatch
        every matched line.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Returns the number unmatched and the refreshed import (lines + their matches).


        **Authentication:** Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                line_ids:
                  type: array
                  items:
                    type: integer
              example:
                line_ids:
                - 479
                - 480
      parameters:
      - name: bankStatementImport
        in: path
        schema:
          type: integer
        required: true
        description: Import id.
        example: '23'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      unmatched:
                        type: integer
                      import:
                        type: object
                        properties:
                          id:
                            type: integer
                          status:
                            type: string
                          line_count:
                            type: integer
                          lines:
                            type: array
                            items:
                              type: string
                example:
                  data:
                    unmatched: 31
                    import:
                      id: 23
                      status: ready
                      line_count: 38
                      lines:
                      - …
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-ledger-reconciliation-bank-statements-bankstatementimport-unmatch-all
  /api/ledger/reconciliation/bank-statements/{bankStatementImport}/push-to-xero:
    post:
      tags:
      - Ledger (Accounting v2)
      summary: Push Matched Lines to Xero
      description: 'Push the matched line(s)'' SKU document(s) to the accounting provider
        (Xero) via the shared ledger sync pipeline (the same dedup-aware path the
        rest of the app posts through). Only lines whose `match_status` is `matched`
        are pushed; each matched entry that is already linked-current in Xero is skipped,
        others are enqueued as a Create/Update sync operation. Optional body `line_ids`
        scopes it to a selection (a single line, or a bulk pick); omit to push every
        matched line.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        A line flips to `synced` the moment all of its documents are confirmed in
        Xero; lines whose documents are still being pushed stay `matched` and self-heal
        to `synced` on the next refresh (suggestions / show) once the async push lands.


        Returns: `entries_enqueued` (entries run through the sync pipeline), `lines_synced`
        (lines now fully in Xero), `lines_pending` (lines still pushing), and the
        refreshed import (lines + their matches).


        **Authentication:** Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                line_ids:
                  type: array
                  items:
                    type: integer
              example:
                line_ids:
                - 479
                - 480
      parameters:
      - name: bankStatementImport
        in: path
        schema:
          type: integer
        required: true
        description: Import id.
        example: '23'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      entries_enqueued:
                        type: integer
                      lines_synced:
                        type: integer
                      lines_pending:
                        type: integer
                      import:
                        type: object
                        properties:
                          id:
                            type: integer
                          status:
                            type: string
                          line_count:
                            type: integer
                          lines:
                            type: array
                            items:
                              type: string
                example:
                  data:
                    entries_enqueued: 33
                    lines_synced: 28
                    lines_pending: 5
                    import:
                      id: 23
                      status: ready
                      line_count: 38
                      lines:
                      - …
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-ledger-reconciliation-bank-statements-bankstatementimport-push-to-xero
  /api/ledger/reconciliation/bank-statements/{bankStatementImport}/enable-sync:
    post:
      tags:
      - Ledger (Accounting v2)
      summary: Enable Sync on Matched Lines
      description: 'Force-enable sync on the matched line(s)'' document(s) whose sync
        is currently **disabled-but-enableable** — a settings opt-out (e.g. this entry
        type isn''t synced, or it''s before the sync start date) or a per-entry `force_disabled`
        override. Writes a `force_enabled` override on each such entry (via the same
        path as the per-entry override endpoint) so a subsequent **Push to Xero**
        actually reaches the provider instead of silently no-opping.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Structurally-blocked documents — a batch member, an open batch, an inactive
        connection, or internal-only entries — are **left untouched** (they can''t
        be force-enabled). Optional body `line_ids` scopes it to a single line''s
        Enable or a bulk selection; omit to enable across every matched line.


        Returns: `entries_enabled` (documents flipped to force_enabled), `lines_affected`
        (matched lines touched), and the refreshed import (lines + their matches,
        with cleared `sync_block`s).


        Guarded by the `accounting.sync` permission.


        **Authentication:** Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                line_ids:
                  type: array
                  items:
                    type: integer
              example:
                line_ids:
                - 479
                - 480
      parameters:
      - name: bankStatementImport
        in: path
        schema:
          type: integer
        required: true
        description: Import id.
        example: '23'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      entries_enabled:
                        type: integer
                      lines_affected:
                        type: integer
                      import:
                        type: object
                        properties:
                          id:
                            type: integer
                          status:
                            type: string
                          line_count:
                            type: integer
                          lines:
                            type: array
                            items:
                              type: string
                example:
                  data:
                    entries_enabled: 4
                    lines_affected: 1
                    import:
                      id: 23
                      status: ready
                      line_count: 38
                      lines:
                      - …
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-ledger-reconciliation-bank-statements-bankstatementimport-enable-sync
  /api/ledger/reconciliation/inventory/resume-journals:
    post:
      tags:
      - Ledger (Accounting v2)
      summary: Resume Provider GL Journals Sync
      description: 'Manually **resume a budget-paused** provider GL journals sync
        from its stored cursor, instead of waiting for the hourly auto-resume sweep
        (`ledger:reconciliation:resume-provider-sync`).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        When the metered backfill (see **Sync Provider GL Journals**) exhausts its
        reserved per-run provider-call budget, it pauses cleanly and records a resume
        cursor on the connection (`integration_settings.inventoryReconSync`: `resume_offset`,
        `from`, `user_id`, `paused_at`). This endpoint re-dispatches the tracked job
        from that cursor — same `connection_id`, `full=false`, picking up at the saved
        `from` / `resume_offset` — and returns the tracked job log id so the UI can
        follow it in the global progress tray.


        **Authentication:** Requires Bearer token + `accounting.sync` permission.


        **Request body:**

        - `connection_id` (integer, **required**): accounting connection id whose
        paused sync is resumed.


        **Responses:**

        - `200` — a paused run existed; the resume job was dispatched. Returns `data.tracked_job_log_id`.

        - `409` — no paused provider GL sync is recorded for this connection (nothing
        to resume).

        - `422` — `connection_id` missing or not an integer.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                connection_id:
                  type: integer
              example:
                connection_id: 5
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 4823
                  message: Provider GL journals sync resumed
        '409':
          description: Conflict
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No paused provider GL sync to resume for this connection.
        '422':
          description: Unprocessable Content
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      connection_id:
                        type: array
                        items:
                          type: string
                example:
                  message: The connection id field is required.
                  errors:
                    connection_id:
                    - The connection id field is required.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-ledger-reconciliation-inventory-resume-journals
  /api/ledger/close/periods:
    get:
      tags:
      - Ledger (Accounting v2)
      summary: List Close Periods
      description: 'Every month in the closable range (most recent first) with lifecycle
        status (open, in_review, closing, closed), checklist progress, blocking-failure
        and warning counts, and close sign-off metadata. Months are materialized lazily
        — a month that has never been interacted with reports status open with is_started
        false.


        Authentication: Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      periods:
                        type: array
                        items:
                          type: object
                          properties:
                            period:
                              type: string
                            period_start:
                              type: string
                            period_end:
                              type: string
                            status:
                              type: string
                            is_started:
                              type: boolean
                            is_closable:
                              type: boolean
                            is_reopenable:
                              type: boolean
                            progress:
                              type: object
                              properties:
                                done:
                                  type: integer
                                total:
                                  type: integer
                            blocking_failures:
                              type: integer
                            warnings:
                              type: integer
                            closed_at:
                              type: string
                              nullable: true
                            closed_by:
                              type: string
                              nullable: true
                example:
                  data:
                    periods:
                    - period: 2026-06
                      period_start: '2026-06-01'
                      period_end: '2026-06-30'
                      status: in_review
                      is_started: true
                      is_closable: true
                      is_reopenable: false
                      progress:
                        done: 12
                        total: 14
                      blocking_failures: 0
                      warnings: 2
                      closed_at: null
                      closed_by: null
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-ledger-close-periods
  /api/ledger/close/periods/{period}:
    get:
      tags:
      - Ledger (Accounting v2)
      summary: Get Close Period
      description: 'Full detail for one period (period key format YYYY-MM): the close
        checklist with each item''s latest evaluation, lock state (active lock date
        plus per-connection provider lock dates), report snapshot index, and close/reopen
        eligibility flags. For a month that has not been started, the checklist is
        a live read-only preview.


        Authentication: Bearer token.


        Errors: 422 when the period predates the accounting start date or is in the
        future.'
      parameters:
      - name: period
        in: path
        schema:
          type: string
        required: true
        description: The period ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      period:
                        type: object
                        properties:
                          period:
                            type: string
                          period_start:
                            type: string
                          period_end:
                            type: string
                          status:
                            type: string
                          status_label:
                            type: string
                          is_started:
                            type: boolean
                          is_closable:
                            type: boolean
                          is_reopenable:
                            type: boolean
                          closed_at:
                            type: string
                            nullable: true
                          closed_by:
                            type: string
                            nullable: true
                          reopened_at:
                            type: string
                            nullable: true
                          reopened_by:
                            type: string
                            nullable: true
                          reopen_reason:
                            type: string
                            nullable: true
                          notes:
                            type: string
                            nullable: true
                          lock:
                            type: object
                            properties:
                              active_lock_date:
                                type: string
                              provider_locks:
                                type: array
                                items:
                                  type: object
                                  properties:
                                    connection_id:
                                      type: integer
                                    connection_name:
                                      type: string
                                    lock_date:
                                      type: string
                          checklist:
                            type: array
                            items:
                              type: object
                              properties:
                                id:
                                  type: integer
                                key:
                                  type: string
                                title:
                                  type: string
                                description:
                                  type: string
                                  nullable: true
                                category:
                                  type: string
                                category_label:
                                  type: string
                                type:
                                  type: string
                                severity:
                                  type: string
                                status:
                                  type: string
                                result:
                                  type: object
                                  properties:
                                    count:
                                      type: integer
                                    link:
                                      type: object
                                      properties:
                                        tab:
                                          type: string
                                        filter:
                                          type: object
                                          properties:
                                            balance_mismatch:
                                              type: boolean
                                acknowledged:
                                  type: boolean
                                completed_by:
                                  type: string
                                  nullable: true
                                completed_at:
                                  type: string
                                  nullable: true
                                evaluated_at:
                                  type: string
                                sort_order:
                                  type: integer
                          snapshots:
                            type: array
                example:
                  data:
                    period:
                      period: 2026-06
                      period_start: '2026-06-01'
                      period_end: '2026-06-30'
                      status: in_review
                      status_label: In Review
                      is_started: true
                      is_closable: true
                      is_reopenable: false
                      closed_at: null
                      closed_by: null
                      reopened_at: null
                      reopened_by: null
                      reopen_reason: null
                      notes: null
                      lock:
                        active_lock_date: '2026-05-31'
                        provider_locks:
                        - connection_id: 30
                          connection_name: Xero
                          lock_date: '2026-05-31'
                      checklist:
                      - id: 41
                        key: entries_balanced
                        title: All entries balanced
                        description: null
                        category: data_completeness
                        category_label: Data completeness
                        type: automated
                        severity: blocking
                        status: pass
                        result:
                          count: 0
                          link:
                            tab: transactions
                            filter:
                              balance_mismatch: true
                        acknowledged: false
                        completed_by: null
                        completed_at: null
                        evaluated_at: '2026-07-17T10:04:00+00:00'
                        sort_order: 11
                      - id: 52
                        key: review_income_statement
                        title: Review Income Statement
                        description: Read through the month's Income Statement for
                          unexpected balances before sign-off.
                        category: review
                        category_label: Review
                        type: manual
                        severity: null
                        status: done
                        result:
                          report_key: income_statement
                        acknowledged: false
                        completed_by:
                          id: 5
                          name: Dana Bookkeeper
                        completed_at: '2026-07-16T22:10:00+00:00'
                        evaluated_at: null
                        sort_order: 300
                      snapshots: []
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-ledger-close-periods-period
  /api/ledger/close/periods/{period}/start:
    post:
      tags:
      - Ledger (Accounting v2)
      summary: Start Period Close
      description: 'Begin the close for a month: materializes the period, seeds its
        checklist (automated checks, built-in review items, and any custom items configured
        in accounting settings), and evaluates every automated check. Returns the
        full period detail.


        Authentication: Bearer token. Requires the accounting sync permission.'
      requestBody:
        content: {}
      parameters:
      - name: period
        in: path
        schema:
          type: string
        required: true
        description: The period ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      period:
                        type: object
                        properties:
                          period:
                            type: string
                          period_start:
                            type: string
                          period_end:
                            type: string
                          status:
                            type: string
                          status_label:
                            type: string
                          is_started:
                            type: boolean
                          is_closable:
                            type: boolean
                          is_reopenable:
                            type: boolean
                          closed_at:
                            type: string
                            nullable: true
                          closed_by:
                            type: string
                            nullable: true
                          reopened_at:
                            type: string
                            nullable: true
                          reopened_by:
                            type: string
                            nullable: true
                          reopen_reason:
                            type: string
                            nullable: true
                          notes:
                            type: string
                            nullable: true
                          lock:
                            type: object
                            properties:
                              active_lock_date:
                                type: string
                              provider_locks:
                                type: array
                                items:
                                  type: object
                                  properties:
                                    connection_id:
                                      type: integer
                                    connection_name:
                                      type: string
                                    lock_date:
                                      type: string
                          checklist:
                            type: array
                            items:
                              type: object
                              properties:
                                id:
                                  type: integer
                                key:
                                  type: string
                                title:
                                  type: string
                                description:
                                  type: string
                                  nullable: true
                                category:
                                  type: string
                                category_label:
                                  type: string
                                type:
                                  type: string
                                severity:
                                  type: string
                                status:
                                  type: string
                                result:
                                  type: object
                                  properties:
                                    count:
                                      type: integer
                                    link:
                                      type: object
                                      properties:
                                        tab:
                                          type: string
                                        filter:
                                          type: object
                                          properties:
                                            balance_mismatch:
                                              type: boolean
                                acknowledged:
                                  type: boolean
                                completed_by:
                                  type: string
                                  nullable: true
                                completed_at:
                                  type: string
                                  nullable: true
                                evaluated_at:
                                  type: string
                                sort_order:
                                  type: integer
                          snapshots:
                            type: array
                  message:
                    type: string
                example:
                  data:
                    period:
                      period: 2026-06
                      period_start: '2026-06-01'
                      period_end: '2026-06-30'
                      status: in_review
                      status_label: In Review
                      is_started: true
                      is_closable: true
                      is_reopenable: false
                      closed_at: null
                      closed_by: null
                      reopened_at: null
                      reopened_by: null
                      reopen_reason: null
                      notes: null
                      lock:
                        active_lock_date: '2026-05-31'
                        provider_locks:
                        - connection_id: 30
                          connection_name: Xero
                          lock_date: '2026-05-31'
                      checklist:
                      - id: 41
                        key: entries_balanced
                        title: All entries balanced
                        description: null
                        category: data_completeness
                        category_label: Data completeness
                        type: automated
                        severity: blocking
                        status: pass
                        result:
                          count: 0
                          link:
                            tab: transactions
                            filter:
                              balance_mismatch: true
                        acknowledged: false
                        completed_by: null
                        completed_at: null
                        evaluated_at: '2026-07-17T10:04:00+00:00'
                        sort_order: 11
                      - id: 52
                        key: review_income_statement
                        title: Review Income Statement
                        description: Read through the month's Income Statement for
                          unexpected balances before sign-off.
                        category: review
                        category_label: Review
                        type: manual
                        severity: null
                        status: done
                        result:
                          report_key: income_statement
                        acknowledged: false
                        completed_by:
                          id: 5
                          name: Dana Bookkeeper
                        completed_at: '2026-07-16T22:10:00+00:00'
                        evaluated_at: null
                        sort_order: 300
                      snapshots: []
                  message: Close started for 2026-06.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-ledger-close-periods-period-start
  /api/ledger/close/periods/{period}/refresh:
    post:
      tags:
      - Ledger (Accounting v2)
      summary: Refresh Close Checklist
      description: 'Re-evaluate every automated check on a started, non-closed period
        and append any newly configured custom checklist items. Completed manual items
        are never reset.


        Authentication: Bearer token. Requires the accounting sync permission.


        Errors: 422 when the period has not been started or is already closed.'
      requestBody:
        content: {}
      parameters:
      - name: period
        in: path
        schema:
          type: string
        required: true
        description: The period ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      period:
                        type: object
                        properties:
                          period:
                            type: string
                          period_start:
                            type: string
                          period_end:
                            type: string
                          status:
                            type: string
                          status_label:
                            type: string
                          is_started:
                            type: boolean
                          is_closable:
                            type: boolean
                          is_reopenable:
                            type: boolean
                          closed_at:
                            type: string
                            nullable: true
                          closed_by:
                            type: string
                            nullable: true
                          reopened_at:
                            type: string
                            nullable: true
                          reopened_by:
                            type: string
                            nullable: true
                          reopen_reason:
                            type: string
                            nullable: true
                          notes:
                            type: string
                            nullable: true
                          lock:
                            type: object
                            properties:
                              active_lock_date:
                                type: string
                              provider_locks:
                                type: array
                                items:
                                  type: object
                                  properties:
                                    connection_id:
                                      type: integer
                                    connection_name:
                                      type: string
                                    lock_date:
                                      type: string
                          checklist:
                            type: array
                            items:
                              type: object
                              properties:
                                id:
                                  type: integer
                                key:
                                  type: string
                                title:
                                  type: string
                                description:
                                  type: string
                                  nullable: true
                                category:
                                  type: string
                                category_label:
                                  type: string
                                type:
                                  type: string
                                severity:
                                  type: string
                                status:
                                  type: string
                                result:
                                  type: object
                                  properties:
                                    count:
                                      type: integer
                                    link:
                                      type: object
                                      properties:
                                        tab:
                                          type: string
                                        filter:
                                          type: object
                                          properties:
                                            balance_mismatch:
                                              type: boolean
                                acknowledged:
                                  type: boolean
                                completed_by:
                                  type: string
                                  nullable: true
                                completed_at:
                                  type: string
                                  nullable: true
                                evaluated_at:
                                  type: string
                                sort_order:
                                  type: integer
                          snapshots:
                            type: array
                  message:
                    type: string
                example:
                  data:
                    period:
                      period: 2026-06
                      period_start: '2026-06-01'
                      period_end: '2026-06-30'
                      status: in_review
                      status_label: In Review
                      is_started: true
                      is_closable: true
                      is_reopenable: false
                      closed_at: null
                      closed_by: null
                      reopened_at: null
                      reopened_by: null
                      reopen_reason: null
                      notes: null
                      lock:
                        active_lock_date: '2026-05-31'
                        provider_locks:
                        - connection_id: 30
                          connection_name: Xero
                          lock_date: '2026-05-31'
                      checklist:
                      - id: 41
                        key: entries_balanced
                        title: All entries balanced
                        description: null
                        category: data_completeness
                        category_label: Data completeness
                        type: automated
                        severity: blocking
                        status: pass
                        result:
                          count: 0
                          link:
                            tab: transactions
                            filter:
                              balance_mismatch: true
                        acknowledged: false
                        completed_by: null
                        completed_at: null
                        evaluated_at: '2026-07-17T10:04:00+00:00'
                        sort_order: 11
                      - id: 52
                        key: review_income_statement
                        title: Review Income Statement
                        description: Read through the month's Income Statement for
                          unexpected balances before sign-off.
                        category: review
                        category_label: Review
                        type: manual
                        severity: null
                        status: done
                        result:
                          report_key: income_statement
                        acknowledged: false
                        completed_by:
                          id: 5
                          name: Dana Bookkeeper
                        completed_at: '2026-07-16T22:10:00+00:00'
                        evaluated_at: null
                        sort_order: 300
                      snapshots: []
                  message: Checklist re-evaluated.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-ledger-close-periods-period-refresh
  /api/ledger/close/periods/{period}/checklist/{item}/complete:
    post:
      tags:
      - Ledger (Accounting v2)
      summary: Complete Checklist Item
      description: 'Check a manual checklist item off, recording who completed it
        and when. Automated checks cannot be checked off — re-evaluate them with Refresh
        Close Checklist instead.


        Authentication: Bearer token. Requires the accounting sync permission.


        Errors: 422 for automated items or when the period is closed.'
      requestBody:
        content: {}
      parameters:
      - name: period
        in: path
        schema:
          type: string
        required: true
        description: The period ID.
      - name: item
        in: path
        schema:
          type: string
        required: true
        description: The item ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      item:
                        type: object
                        properties:
                          id:
                            type: integer
                          key:
                            type: string
                          title:
                            type: string
                          description:
                            type: string
                          category:
                            type: string
                          category_label:
                            type: string
                          type:
                            type: string
                          severity:
                            type: string
                            nullable: true
                          status:
                            type: string
                          result:
                            type: object
                            properties:
                              report_key:
                                type: string
                          acknowledged:
                            type: boolean
                          completed_by:
                            type: object
                            properties:
                              id:
                                type: integer
                              name:
                                type: string
                          completed_at:
                            type: string
                          evaluated_at:
                            type: string
                            nullable: true
                          sort_order:
                            type: integer
                  message:
                    type: string
                example:
                  data:
                    item:
                      id: 52
                      key: review_income_statement
                      title: Review Income Statement
                      description: Read through the month's Income Statement for unexpected
                        balances before sign-off.
                      category: review
                      category_label: Review
                      type: manual
                      severity: null
                      status: done
                      result:
                        report_key: income_statement
                      acknowledged: false
                      completed_by:
                        id: 5
                        name: Dana Bookkeeper
                      completed_at: '2026-07-16T22:10:00+00:00'
                      evaluated_at: null
                      sort_order: 300
                  message: Review Income Statement checked off.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-ledger-close-periods-period-checklist-item-complete
    delete:
      tags:
      - Ledger (Accounting v2)
      summary: Uncomplete Checklist Item
      description: 'Undo a manual checklist item''s completion on a non-closed period.


        Authentication: Bearer token. Requires the accounting sync permission.'
      parameters:
      - name: period
        in: path
        schema:
          type: string
        required: true
        description: The period ID.
      - name: item
        in: path
        schema:
          type: string
        required: true
        description: The item ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      item:
                        type: object
                        properties:
                          id:
                            type: integer
                          key:
                            type: string
                          title:
                            type: string
                          description:
                            type: string
                          category:
                            type: string
                          category_label:
                            type: string
                          type:
                            type: string
                          severity:
                            type: string
                            nullable: true
                          status:
                            type: string
                          result:
                            type: object
                            properties:
                              report_key:
                                type: string
                          acknowledged:
                            type: boolean
                          completed_by:
                            type: string
                            nullable: true
                          completed_at:
                            type: string
                            nullable: true
                          evaluated_at:
                            type: string
                            nullable: true
                          sort_order:
                            type: integer
                  message:
                    type: string
                example:
                  data:
                    item:
                      id: 52
                      key: review_income_statement
                      title: Review Income Statement
                      description: Read through the month's Income Statement for unexpected
                        balances before sign-off.
                      category: review
                      category_label: Review
                      type: manual
                      severity: null
                      status: open
                      result:
                        report_key: income_statement
                      acknowledged: false
                      completed_by: null
                      completed_at: null
                      evaluated_at: null
                      sort_order: 300
                  message: Review Income Statement reopened.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-ledger-close-periods-period-checklist-item-complete
  /api/ledger/close/periods/{period}/close:
    post:
      tags:
      - Ledger (Accounting v2)
      summary: Close Period
      description: 'Close and lock the period. Only the earliest non-closed month
        can close (periods close strictly in order). Every failing blocking check
        refuses the close; every warning-level failure and incomplete manual item
        must be listed in acknowledged_keys. The close runs as a background job that
        re-validates all gates, snapshots the report pack, inserts the period lock
        (new entries dated on or before the period end are refused; corrections are
        redated to the first open day), and records the sign-off. Returns the background
        job id.


        Authentication: Bearer token. Requires the accounting settings management
        permission.


        Errors: 422 when a blocking check fails, an acknowledgement is missing, the
        month is out of order, or another close is already running.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                acknowledged_keys:
                  type: array
                  items:
                    type: string
                notes:
                  type: string
              example:
                acknowledged_keys:
                - provider_docs_reconciled
                - review_income_statement
                - review_balance_sheet
                - review_inventory_valuation
                notes: June close complete.
      parameters:
      - name: period
        in: path
        schema:
          type: string
        required: true
        description: The period ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 9311
                  message: Closing 2026-06 — track progress in the job tray.
        '422':
          description: Unprocessable Content
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      acknowledged_keys:
                        type: array
                        items:
                          type: string
                example:
                  message: 'These items need acknowledgement before closing: Review
                    Balance Sheet.'
                  errors:
                    acknowledged_keys:
                    - 'These items need acknowledgement before closing: Review Balance
                      Sheet.'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-ledger-close-periods-period-close
  /api/ledger/close/periods/{period}/reopen:
    post:
      tags:
      - Ledger (Accounting v2)
      summary: Reopen Period
      description: 'Reopen the most recently closed period (a reason is required and
        audit-logged). Removes the period''s own lock, flags its report snapshots
        stale, and returns the period to review. When the accounting provider still
        has the month locked, residual_provider_locks lists those connections — entries
        stay locked provider-side until the books are reopened there too.


        Authentication: Bearer token. Requires the accounting settings management
        permission.


        Errors: 422 when the period is not the most recently closed one or a close
        is currently running.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                reason:
                  type: string
              example:
                reason: Client sent late invoices for June.
      parameters:
      - name: period
        in: path
        schema:
          type: string
        required: true
        description: The period ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      period:
                        type: object
                        properties:
                          period:
                            type: string
                          period_start:
                            type: string
                          period_end:
                            type: string
                          status:
                            type: string
                          status_label:
                            type: string
                          is_started:
                            type: boolean
                          is_closable:
                            type: boolean
                          is_reopenable:
                            type: boolean
                          closed_at:
                            type: string
                            nullable: true
                          closed_by:
                            type: string
                            nullable: true
                          reopened_at:
                            type: string
                            nullable: true
                          reopened_by:
                            type: string
                            nullable: true
                          reopen_reason:
                            type: string
                            nullable: true
                          notes:
                            type: string
                            nullable: true
                          lock:
                            type: object
                            properties:
                              active_lock_date:
                                type: string
                              provider_locks:
                                type: array
                                items:
                                  type: object
                                  properties:
                                    connection_id:
                                      type: integer
                                    connection_name:
                                      type: string
                                    lock_date:
                                      type: string
                          checklist:
                            type: array
                            items:
                              type: object
                              properties:
                                id:
                                  type: integer
                                key:
                                  type: string
                                title:
                                  type: string
                                description:
                                  type: string
                                  nullable: true
                                category:
                                  type: string
                                category_label:
                                  type: string
                                type:
                                  type: string
                                severity:
                                  type: string
                                status:
                                  type: string
                                result:
                                  type: object
                                  properties:
                                    count:
                                      type: integer
                                    link:
                                      type: object
                                      properties:
                                        tab:
                                          type: string
                                        filter:
                                          type: object
                                          properties:
                                            balance_mismatch:
                                              type: boolean
                                acknowledged:
                                  type: boolean
                                completed_by:
                                  type: string
                                  nullable: true
                                completed_at:
                                  type: string
                                  nullable: true
                                evaluated_at:
                                  type: string
                                sort_order:
                                  type: integer
                          snapshots:
                            type: array
                      residual_provider_locks:
                        type: array
                  message:
                    type: string
                example:
                  data:
                    period:
                      period: 2026-06
                      period_start: '2026-06-01'
                      period_end: '2026-06-30'
                      status: in_review
                      status_label: In Review
                      is_started: true
                      is_closable: true
                      is_reopenable: false
                      closed_at: null
                      closed_by: null
                      reopened_at: null
                      reopened_by: null
                      reopen_reason: null
                      notes: null
                      lock:
                        active_lock_date: '2026-05-31'
                        provider_locks:
                        - connection_id: 30
                          connection_name: Xero
                          lock_date: '2026-05-31'
                      checklist:
                      - id: 41
                        key: entries_balanced
                        title: All entries balanced
                        description: null
                        category: data_completeness
                        category_label: Data completeness
                        type: automated
                        severity: blocking
                        status: pass
                        result:
                          count: 0
                          link:
                            tab: transactions
                            filter:
                              balance_mismatch: true
                        acknowledged: false
                        completed_by: null
                        completed_at: null
                        evaluated_at: '2026-07-17T10:04:00+00:00'
                        sort_order: 11
                      - id: 52
                        key: review_income_statement
                        title: Review Income Statement
                        description: Read through the month's Income Statement for
                          unexpected balances before sign-off.
                        category: review
                        category_label: Review
                        type: manual
                        severity: null
                        status: done
                        result:
                          report_key: income_statement
                        acknowledged: false
                        completed_by:
                          id: 5
                          name: Dana Bookkeeper
                        completed_at: '2026-07-16T22:10:00+00:00'
                        evaluated_at: null
                        sort_order: 300
                      snapshots: []
                    residual_provider_locks: []
                  message: 2026-06 reopened.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-ledger-close-periods-period-reopen
  /api/ledger/close/periods/{period}/reports/{report}:
    get:
      tags:
      - Ledger (Accounting v2)
      summary: Get Close Report
      description: 'One report of the month-end pack. Report keys: income_statement,
        balance_sheet, trial_balance, inventory_valuation, cogs, ginr, reconciliation_summary.
        On a closed period this returns the snapshot frozen at close time (source:
        snapshot); otherwise a live build flagged preliminary. Payloads carry statement-level
        rows plus a totals map of headline figures.


        Authentication: Bearer token.


        Errors: 422 for an unknown report key.'
      parameters:
      - name: period
        in: path
        schema:
          type: string
        required: true
        description: The period ID.
      - name: report
        in: path
        schema:
          type: string
        required: true
        description: The report ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      report:
                        type: object
                        properties:
                          report_key:
                            type: string
                          label:
                            type: string
                          source:
                            type: string
                          preliminary:
                            type: boolean
                          is_stale:
                            type: boolean
                          generated_at:
                            type: string
                          payload:
                            type: object
                            properties:
                              totals:
                                type: object
                                properties:
                                  total_opening:
                                    type: integer
                                  total_debits:
                                    type: number
                                  total_credits:
                                    type: number
                                  total_closing:
                                    type: integer
                              rows:
                                type: array
                                items:
                                  type: object
                                  properties:
                                    account_code:
                                      type: string
                                    account_name:
                                      type: string
                                    opening_balance:
                                      type: integer
                                    period_debits:
                                      type: integer
                                    period_credits:
                                      type: integer
                                    closing_balance:
                                      type: integer
                example:
                  data:
                    report:
                      report_key: trial_balance
                      label: Trial Balance
                      source: snapshot
                      preliminary: false
                      is_stale: false
                      generated_at: '2026-07-05T14:22:00+00:00'
                      payload:
                        totals:
                          total_opening: 0
                          total_debits: 633597.98
                          total_credits: 633597.98
                          total_closing: 0
                        rows:
                        - account_code: '1200'
                          account_name: Inventory
                          opening_balance: 700000
                          period_debits: 45000
                          period_credits: 38000
                          closing_balance: 707000
                        - account_code: '4000'
                          account_name: Sales
                          opening_balance: 0
                          period_debits: 0
                          period_credits: 80095.74
                          closing_balance: -80095.74
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-ledger-close-periods-period-reports-report
  /api/ledger/close/periods/{period}/verify:
    get:
      tags:
      - Ledger (Accounting v2)
      summary: Verify Closed Period
      description: 'Drift check for a closed period: recomputes each snapshotted report
        live and diffs the totals against the snapshot with a $0.01 tolerance. Any
        difference means the closed month''s numbers moved after close (for example
        via data repairs) and lists the changed figures. The reconciliation summary
        is informational — it legitimately changes as reconciliation work continues
        and never trips the period-level verdict.


        Authentication: Bearer token.


        Errors: 422 when the period is not closed.'
      parameters:
      - name: period
        in: path
        schema:
          type: string
        required: true
        description: The period ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      verification:
                        type: object
                        properties:
                          period:
                            type: string
                          has_drift:
                            type: boolean
                          reports:
                            type: array
                            items:
                              type: object
                              properties:
                                report_key:
                                  type: string
                                label:
                                  type: string
                                matches:
                                  type: boolean
                                informational:
                                  type: boolean
                                is_stale:
                                  type: boolean
                                snapshot_generated_at:
                                  type: string
                                drift:
                                  type: array
                example:
                  data:
                    verification:
                      period: 2026-06
                      has_drift: false
                      reports:
                      - report_key: trial_balance
                        label: Trial Balance
                        matches: true
                        informational: false
                        is_stale: false
                        snapshot_generated_at: '2026-07-05T14:22:00+00:00'
                        drift: []
                      - report_key: reconciliation_summary
                        label: Reconciliation Summary
                        matches: false
                        informational: true
                        is_stale: false
                        snapshot_generated_at: '2026-07-05T14:22:00+00:00'
                        drift:
                        - field: provider_variance
                          snapshot: 13891.46
                          live: 12100.02
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-ledger-close-periods-period-verify
  /api/ledger/close/periods/{period}/capture-provider-balances:
    post:
      tags:
      - Ledger (Accounting v2)
      summary: Capture Provider Trial Balances
      description: 'Capture the accounting provider''s trial balance as of the period
        end (period key format YYYY-MM), for every connected accounting integration.
        This is the one metered provider pull behind the Trial Balance Reconciliation
        report and the trial_balance_reconciled close check — both read only the cached
        snapshot this produces. Synchronous: one trial-balance call per connection;
        connections whose provider exposes no trial-balance report are skipped, not
        failed. Re-running re-captures in place so provider-side edits are picked
        up.


        Authentication: Bearer token. Requires the accounting sync permission.'
      requestBody:
        content: {}
      parameters:
      - name: period
        in: path
        schema:
          type: string
        required: true
        description: The period ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      captured:
                        type: integer
                      unsupported:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    captured: 1
                    unsupported: 0
                  message: 1 provider trial balance captured. Re-check the close to
                    reconcile.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-ledger-close-periods-period-capture-provider-balances
  /api/ledger/close/periods/{period}/sync-breakdown:
    get:
      tags:
      - Ledger (Accounting v2)
      summary: Sync Breakdown (why not synced)
      description: 'The why-not-synced breakdown. For the period (key format YYYY-MM),
        returns every journal entry that has NOT reached the accounting provider,
        grouped by reason (display status), with an entry count, a dollar total, and
        a per-reason deep-link filter that lands the entries list on exactly those
        rows. The synced total rides along as context (how much DID sync). Read-only
        and entirely local — no provider call.


        Each row''s `disposition` is one of: `excluded` (unsynced by design), `in_flight`
        (queued/syncing/retrying), `needs_attention` (failed/conflict/removed-in-provider/needs-attention).
        `link` is a checklist-style deep link ({tab, filter}) for the entries list.


        Authentication: Bearer token.'
      parameters:
      - name: period
        in: path
        schema:
          type: string
        required: true
        description: The period ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      breakdown:
                        type: object
                        properties:
                          synced:
                            type: object
                            properties:
                              entry_count:
                                type: integer
                              total:
                                type: integer
                          rows:
                            type: array
                            items:
                              type: object
                              properties:
                                entry_display_status:
                                  type: string
                                label:
                                  type: string
                                disposition:
                                  type: string
                                reason:
                                  type: string
                                entry_count:
                                  type: integer
                                total:
                                  type: integer
                                link:
                                  type: object
                                  properties:
                                    tab:
                                      type: string
                                    filter:
                                      type: object
                                      properties:
                                        entry_display_status:
                                          type: string
                          totals:
                            type: object
                            properties:
                              unsynced_count:
                                type: integer
                              unsynced_total:
                                type: integer
                example:
                  data:
                    breakdown:
                      synced:
                        entry_count: 128
                        total: 84250
                      rows:
                      - entry_display_status: excluded
                        label: Disabled
                        disposition: excluded
                        reason: Excluded by design — not configured to sync to the
                          provider.
                        entry_count: 12
                        total: 3400
                        link:
                          tab: all
                          filter:
                            entry_display_status: excluded
                      - entry_display_status: failed
                        label: Failed
                        disposition: needs_attention
                        reason: Failed — the provider rejected the push.
                        entry_count: 2
                        total: 560
                        link:
                          tab: all
                          filter:
                            entry_display_status: failed
                      totals:
                        unsynced_count: 14
                        unsynced_total: 3960
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-ledger-close-periods-period-sync-breakdown
  /api/ledger/close/periods/{period}/export:
    post:
      tags:
      - Ledger (Accounting v2)
      summary: Export Close Pack
      description: 'Generate the month-end close pack workbook (XLSX) as a background
        job: a cover sheet with the period''s status, sign-off and checklist outcomes,
        plus one sheet per report of the pack. Closed periods export their frozen
        snapshots; open periods export live figures flagged PRELIMINARY. The finished
        file is delivered as a download from the job result.


        Authentication: Bearer token. Requires the accounting sync permission.'
      requestBody:
        content: {}
      parameters:
      - name: period
        in: path
        schema:
          type: string
        required: true
        description: The period ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 9312
                  message: Close pack export started — the download will appear in
                    the job tray.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-ledger-close-periods-period-export
  /api/ledger/reports/lock-date-exceptions:
    get:
      tags:
      - Ledger (Accounting v2)
      summary: List Lock Date Exceptions
      description: 'Paginated journal entries displaced out of a locked accounting
        period (booked on the first open day, source date on `original_effective_at`).


        **Filters:** type, source_type, original_from/original_to (m/d/Y). **Sort:**
        original_effective_at (default), effective_at, id, document_total. **Pagination:**
        page, per_page (default 15, max 100).'
      parameters: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        type:
                          type: object
                          properties:
                            value:
                              type: string
                            label:
                              type: string
                        status:
                          type: string
                        effective_at:
                          type: string
                        original_effective_at:
                          type: string
                        posted_at:
                          type: string
                        reference:
                          type: string
                        document_total:
                          type: string
                        currency_code:
                          type: string
                        display_status:
                          type: object
                          properties:
                            key:
                              type: string
                            label:
                              type: string
                            color:
                              type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - id: 8891
                    type:
                      value: customer_return
                      label: Customer Return
                    status: posted
                    effective_at: '2026-07-01T00:00:00+00:00'
                    original_effective_at: '2026-05-12T00:00:00+00:00'
                    posted_at: '2026-07-01T00:00:00+00:00'
                    reference: CR-1042/R1
                    document_total: '210.55'
                    currency_code: USD
                    display_status:
                      key: synced
                      label: Synced
                      color: success
                  current_page: 1
                  last_page: 1
                  per_page: 15
                  total: 1
                  from: 1
                  to: 1
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-ledger-reports-lock-date-exceptions
  /api/ledger/reports/lock-date-exceptions/summary:
    get:
      tags:
      - Ledger (Accounting v2)
      summary: Get Lock Date Exceptions Summary
      description: Displaced-entry counts and net document-total impact grouped by
        entry type, plus grand totals. Honours the same original_from/original_to
        + type/source_type filters as the list.
      parameters: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      summary:
                        type: object
                        properties:
                          total_count:
                            type: integer
                          total_amount:
                            type: string
                          by_type:
                            type: array
                            items:
                              type: object
                              properties:
                                type:
                                  type: string
                                type_label:
                                  type: string
                                count:
                                  type: integer
                                amount:
                                  type: string
                example:
                  data:
                    summary:
                      total_count: 14
                      total_amount: '3412.88'
                      by_type:
                      - type: customer_return
                        type_label: Customer Return
                        count: 6
                        amount: '-1204.10'
                      - type: bill
                        type_label: Bill
                        count: 5
                        amount: '4102.33'
                      - type: fba_customer_returns
                        type_label: FBA Customer Returns
                        count: 3
                        amount: '514.65'
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-ledger-reports-lock-date-exceptions-summary
  /api/auth/login:
    post:
      tags:
      - Misc
      summary: Login
      description: 'Authenticates a user and returns a Bearer token.


        Local development credentials:

        '
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                email:
                  type: string
                password:
                  type: string
              example:
                email: jane@example.com
                password: your-password
      parameters: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  token:
                    type: string
                  user:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      email:
                        type: string
                example:
                  token: 1|abcdefghijklmnopqrstuvwxyz1234567890
                  user:
                    id: 1
                    name: Jane Doe
                    email: jane@example.com
        '429': *id001
        '422': *id005
      security: []
      operationId: post-api-auth-login
  /api/auth/logout:
    post:
      tags:
      - Misc
      summary: Logout
      description: 'Revokes the current Bearer token.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Logged out successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-session-only: true
      operationId: post-api-auth-logout
  /api/auth/refresh:
    get:
      tags:
      - Authentication
      summary: Refresh Token
      description: 'Refreshes the authentication token. Does not require Bearer token
        as the current token is used from the request context.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Not required (uses current token for refresh).'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  access_token:
                    type: string
                  token_type:
                    type: string
                example:
                  access_token: 2|newtoken123abc456def789ghi012jkl345mno678pqr
                  token_type: bearer
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                example:
                  status: failed
                  message: Token has expired and can no longer be refreshed
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-auth-refresh
  /api/auth/profile:
    get:
      tags:
      - Authentication
      summary: Get Profile
      description: 'Returns the authenticated user''s profile information along with
        a top-level `is_production_server` flag indicating whether the server is running
        in production (used by the SPA to gate sandbox-environment UI affordances).


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.


        **Response flags:**

        - `is_production_server` (boolean) — true when this pod is the production
        environment.

        - `features` (object) — per-account feature-flag map (same as `GET /api/features`);
        each value is a boolean.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      email:
                        type: string
                      email_verified_at:
                        type: string
                      activated_at:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      deleted_at:
                        type: string
                        nullable: true
                      is_admin:
                        type: boolean
                      is_power_user:
                        type: boolean
                      is_super_admin:
                        type: boolean
                      role:
                        type: string
                      features:
                        type: object
                        properties:
                          granular_permissions:
                            type: boolean
                  is_production_server:
                    type: boolean
                example:
                  data:
                    id: 1
                    name: Jane Doe
                    email: jane@example.com
                    email_verified_at: '2024-01-01T00:00:00.000000Z'
                    activated_at: '2024-01-01T00:00:00.000000Z'
                    created_at: '2024-01-01T00:00:00.000000Z'
                    updated_at: '2024-01-15T10:00:00.000000Z'
                    deleted_at: null
                    is_admin: true
                    is_power_user: true
                    is_super_admin: false
                    role: Admin
                    features:
                      granular_permissions: false
                  is_production_server: false
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: get-api-auth-profile
    put:
      tags:
      - Authentication
      summary: Update Profile
      description: 'Updates the authenticated user''s profile (name and email).


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.


        Fields:

        - name (required): Full name (max 255 chars)

        - email (required): Email address (must be unique)'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                email:
                  type: string
              example:
                name: Updated Name
                email: newemail@sku.io
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Successfully updated
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      email:
                        type: array
                        items:
                          type: string
                example:
                  message: The given data was invalid.
                  errors:
                    email:
                    - The email has already been taken.
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: put-api-auth-profile
  /api/auth/password:
    put:
      tags:
      - Authentication
      summary: Update Password
      description: 'Updates the authenticated user''s password. Sends a confirmation
        email upon success.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.


        Fields:

        - old_password (required): Current password (verified against stored hash)

        - password (required): New password (min 8 chars)

        - password_confirmation (required): Must match password field'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                old_password:
                  type: string
                password:
                  type: string
                password_confirmation:
                  type: string
              example:
                old_password: current-password
                password: new-secure-password
                password_confirmation: new-secure-password
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Successfully updated password
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      old_password:
                        type: array
                        items:
                          type: string
                      password:
                        type: array
                        items:
                          type: string
                example:
                  message: The given data was invalid.
                  errors:
                    old_password:
                    - The old password is incorrect.
                    password:
                    - The password confirmation does not match.
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: put-api-auth-password
  /api/auth/alerts:
    get:
      tags:
      - Authentication
      summary: Get Alerts
      description: 'Returns paginated alerts for the authenticated user.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.


        Query params:

        - limit: Number of alerts per page (default: 10)'
      parameters:
      - name: limit
        in: query
        schema:
          type: integer
        description: 'Items per page (default: 10)'
        example: '10'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        user_id:
                          type: integer
                        activity_log_id:
                          type: integer
                        show_in_ui_notification:
                          type: integer
                        read_at:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 10
                    user_id: 1
                    activity_log_id: 500
                    show_in_ui_notification: 1
                    read_at: null
                    created_at: '2024-06-01T09:00:00.000000Z'
                  per_page: 10
                  total: 1
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: get-api-auth-alerts
  /api/auth/unread-notifications:
    get:
      tags:
      - Authentication
      summary: Get Unread Notifications
      description: 'Returns paginated unread UI notifications for the authenticated
        user. Only returns alerts with show_in_ui_notification=1 that have not been
        read.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: limit
        in: query
        schema:
          type: integer
        description: 'Items per page (default: 10)'
        example: '10'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        user_id:
                          type: integer
                        activity_log_id:
                          type: integer
                        show_in_ui_notification:
                          type: integer
                        read_at:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 10
                    user_id: 1
                    activity_log_id: 500
                    show_in_ui_notification: 1
                    read_at: null
                    created_at: '2024-06-01T09:00:00.000000Z'
                  per_page: 10
                  total: 1
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: get-api-auth-unread-notifications
  /api/auth/{id}/read-notification:
    put:
      tags:
      - Authentication
      summary: Mark Notification as Read
      description: 'Marks a specific notification as read for the authenticated user.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.


        Path params:

        - activity_log_id: ID of the activity log / notification to mark as read'
      requestBody:
        content: {}
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                example:
                  status: success
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No query results for model
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-session-only: true
      operationId: put-api-auth-id-read-notification
  /api/auth/token:
    delete:
      tags:
      - Authentication
      summary: Sign Out of All Sessions (Global Logout)
      description: 'Signs the authenticated user out of every browser and device —
        across every subdomain and every pod.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        What it does:

        - Increments the user''s central `auth_version` counter by 1

        - Deletes every Session-type Personal Access Token for the user (Sanctum bearer
        sessions)

        - Invalidates the caller''s own cookie session (if cookie-authenticated)

        - Busts the per-user auth_version cache so the next request reads the new
        value immediately


        What survives:

        - Personal Access Tokens (PAT type) — long-lived API credentials. Revoke individually
        from Settings → Developer → Personal Access Tokens.

        - Integration tokens (3PL / channel connections). Revoke individually from
        Connected Apps.


        How other devices are kicked: every request authenticated by a Session token
        (or cookie session) carries a stamped `auth_v`. The EnforceAuthVersion middleware
        compares it to the current `auth_version` on the user row; if the stamp is
        stale, the request is rejected with 401 / ERR_AUTH_REVOKED and the cookie
        session is invalidated. This works across all pods because `users.auth_version`
        lives in the central DB.


        Authentication: Requires Bearer token (Session type) or active cookie session.


        Note: Not available when CACHE_STORE is ''array'' — the auth_version cache
        bust would be a no-op across processes.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: All sessions logged out.
        '501':
          description: Not Implemented
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: This is not available when CACHE_STORE is array.
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: delete-api-auth-token
  /api/users/list:
    get:
      tags:
      - Users
      summary: Get User Lookup List
      description: 'Returns a minimal list of users (id and name only), ordered by
        name. Intended for dropdown/combo box lookups.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Tenant scoping: Results are restricted to users who are members of the current
        tenant. The `users` table lives on the central connection and is shared across
        all tenants, so without scoping every dropdown would leak users from every
        tenant in the installation.


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                example:
                  data:
                  - id: 1
                    name: Alice Johnson
                  - id: 2
                    name: Bob Smith
                  - id: 3
                    name: Carol White
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: get-api-users-list
  /api/users/store-user:
    post:
      tags:
      - Users
      summary: Invite User
      description: 'Creates a new user and sends them an email invitation to set their
        own password (in production). In non-production environments, a password is
        generated and returned in the response.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.


        Fields:

        - email (required, unique, max:255) — User''s email address

        - name (required, string, max:255) — User''s full name

        - is_admin (optional, boolean, default: false) — Grant admin privileges

        - is_power_user (optional, boolean, default: false) — Grant power user privileges


        **Requires permission:** `users.create`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                email:
                  type: string
                is_admin:
                  type: boolean
                is_power_user:
                  type: boolean
              example:
                name: David Lee
                email: david@example.com
                is_admin: false
                is_power_user: true
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 OK (production — invitation sent)
                  value:
                    message: user David Lee was successfully created
                example-1:
                  summary: 200 OK (non-production — password returned)
                  value:
                    message: user David Lee was successfully created
                    generated_password: xK9mPqR2
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      email:
                        type: array
                        items:
                          type: string
                example:
                  message: The email has already been taken.
                  errors:
                    email:
                    - The email has already been taken.
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: post-api-users-store-user
  /api/users/{user}:
    get:
      tags:
      - Users
      summary: Show User
      description: 'Returns a single user by ID.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Tenant scoping: Returns 404 if the user is not a member of the current tenant.
        The `users` table is on the central connection, so route model binding would
        otherwise resolve any user ID system-wide.


        Authentication: Requires Bearer token.'
      parameters:
      - name: user
        in: path
        schema:
          type: integer
        required: true
        description: User ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      email:
                        type: string
                      email_verified_at:
                        type: string
                      activated_at:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      deleted_at:
                        type: string
                        nullable: true
                      is_admin:
                        type: boolean
                      is_power_user:
                        type: boolean
                      is_super_admin:
                        type: boolean
                      role:
                        type: string
                example:
                  data:
                    id: 1
                    name: Alice Johnson
                    email: alice@example.com
                    email_verified_at: '2024-01-10T08:00:00.000000Z'
                    activated_at: '2024-01-10T08:00:00.000000Z'
                    created_at: '2024-01-10T08:00:00.000000Z'
                    updated_at: '2024-03-15T12:00:00.000000Z'
                    deleted_at: null
                    is_admin: true
                    is_power_user: false
                    is_super_admin: false
                    role: Admin
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No query results for model [App\Models\User] 999
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: get-api-users-user
    put:
      tags:
      - Users
      summary: Update User
      description: 'Updates an existing user. The is_admin field can only be set by
        admin users.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Tenant scoping: Returns 404 if the user is not a member of the current tenant.
        Closes a privilege-escalation hole where any tenant admin could otherwise
        mutate any user system-wide by guessing IDs.


        is_admin / is_power_user propagation: when provided, these flags are mirrored
        to the `tenant_users` pivot row for the current tenant (the per-tenant source
        of truth) and also written to the central `users` columns (for legacy readers).
        Without this mirror, an admin elevated in one tenant would silently become
        admin in every tenant they''re attached to.


        Authentication: Requires Bearer token.


        Fields (all optional):

        - name (optional, max:255) — User''s full name

        - email (optional, email, max:255) — User''s email address

        - is_admin (optional, boolean) — Admin privileges (only settable by admins)

        - is_power_user (optional, boolean) — Power user privileges


        **Requires permission:** `users.update`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                email:
                  type: string
                is_admin:
                  type: boolean
                is_power_user:
                  type: boolean
              example:
                name: Alice Johnson-Smith
                email: alice.new@example.com
                is_admin: false
                is_power_user: true
      parameters:
      - name: user
        in: path
        schema:
          type: integer
        required: true
        description: User ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: user Alice Johnson-Smith was successfully updated
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: ''
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-session-only: true
      operationId: put-api-users-user
    delete:
      tags:
      - Users
      summary: Delete (Deactivate) / Restore User
      description: 'Toggles user activation status, scoped to the current tenant.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Delete (user not trashed): detaches the `tenant_users` pivot row for the current
        tenant. If the user has no remaining pivot rows after the detach, the central
        `users` row is soft-deleted as well; otherwise the central row stays intact
        so the user remains usable in other tenants.


        Restore (user trashed): re-attaches the pivot row for the current tenant (mirroring
        central''s is_admin / is_power_user flags) and un-soft-deletes the central
        row. Restore is allowed when the user is already attached here OR is fully
        orphaned (no pivot rows anywhere). Restoring a user whose only pivots are
        to OTHER tenants is rejected (404) to prevent cross-tenant claim attacks.


        Tenant scoping: Returns 404 if the user is not a member of the current tenant
        on the delete path. Prevents any tenant admin from deactivating users system-wide
        by guessing IDs.


        Authentication: Requires Bearer token.


        **Requires permission:** `users.delete`'
      parameters:
      - name: user
        in: path
        schema:
          type: integer
        required: true
        description: User ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 OK (deactivated)
                  value:
                    message: user Alice Johnson-Smith was successfully deleted
                example-1:
                  summary: 200 OK (restored)
                  value:
                    message: User activated successfully
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: ''
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: delete-api-users-user
  /api/users:
    get:
      tags:
      - Users
      summary: List Users (list view)
      description: 'Returns a paginated list view list of users. Supports search,
        sort, and pagination.


        Authentication: Requires Bearer token.


        Query parameters:

        - page — Page number (default: 1)

        - limit — Results per page (default: 15)

        - search — Full-text search across name and email

        - sort — Sort field, prefix with - for descending (e.g., -created_at)

        - archived — 0 = active users, 1 = soft-deleted users

        - included[] — IDs to force-include in results

        - excluded[] — IDs to exclude from results'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        description: Page number for pagination
        example: '1'
      - name: limit
        in: query
        schema:
          type: integer
        description: Number of results per page
        example: '15'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        email:
                          type: string
                        email_verified_at:
                          type: string
                        activated_at:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                        deleted_at:
                          type: string
                          nullable: true
                        is_admin:
                          type: boolean
                        is_power_user:
                          type: boolean
                        is_super_admin:
                          type: boolean
                        role:
                          type: string
                  total:
                    type: integer
                  per_page:
                    type: integer
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                example:
                  data:
                  - id: 1
                    name: Alice Johnson
                    email: alice@example.com
                    email_verified_at: '2024-01-10T08:00:00.000000Z'
                    activated_at: '2024-01-10T08:00:00.000000Z'
                    created_at: '2024-01-10T08:00:00.000000Z'
                    updated_at: '2024-03-15T12:00:00.000000Z'
                    deleted_at: null
                    is_admin: true
                    is_power_user: false
                    is_super_admin: false
                    role: Admin
                  - id: 2
                    name: Bob Smith
                    email: bob@example.com
                    email_verified_at: '2024-02-01T09:00:00.000000Z'
                    activated_at: '2024-02-01T09:00:00.000000Z'
                    created_at: '2024-02-01T09:00:00.000000Z'
                    updated_at: '2024-02-01T09:00:00.000000Z'
                    deleted_at: null
                    is_admin: false
                    is_power_user: true
                    is_super_admin: false
                    role: Power User
                  total: 25
                  per_page: 15
                  current_page: 1
                  last_page: 2
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-users
  /api/roles:
    get:
      tags:
      - Roles & Permissions
      summary: List Roles
      description: 'Lists all roles (sanctum guard) with their permissions and a users_count.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        description:
                          type: string
                        guard_name:
                          type: string
                        users_count:
                          type: integer
                        permissions:
                          type: array
                          items:
                            type: object
                            properties:
                              id:
                                type: integer
                              name:
                                type: string
                              guard_name:
                                type: string
                              resource:
                                type: string
                              action:
                                type: string
                              created_at:
                                type: string
                              updated_at:
                                type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                example:
                  data:
                  - id: 1
                    name: admin
                    description: Full system access with all permissions including
                      user management, settings, and system configuration.
                    guard_name: sanctum
                    users_count: 3
                    permissions:
                    - id: 1
                      name: users.index
                      guard_name: sanctum
                      resource: users
                      action: index
                      created_at: '2024-01-01T00:00:00+00:00'
                      updated_at: '2024-01-01T00:00:00+00:00'
                    - id: 2
                      name: users.show
                      guard_name: sanctum
                      resource: users
                      action: show
                      created_at: '2024-01-01T00:00:00+00:00'
                      updated_at: '2024-01-01T00:00:00+00:00'
                    created_at: '2024-01-01T00:00:00+00:00'
                    updated_at: '2024-01-15T10:00:00+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: get-api-roles
    post:
      tags:
      - Roles & Permissions
      summary: Create Role
      description: 'Creates a new role (guard_name is forced to ''sanctum'') and syncs
        the given permissions.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Body fields:

        - name (required, string, max 255, unique in roles)

        - description (optional, string, max 500)

        - permissions (optional, array of permission names; each must exist in permissions)


        Authentication: Requires Bearer token.


        **Requires permission:** `roles.create`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                description:
                  type: string
                permissions:
                  type: array
                  items:
                    type: string
              example:
                name: warehouse_manager
                description: Manage warehouses and inventory
                permissions:
                - warehouses.index
                - warehouses.update
                - inventory.index
                - inventory.adjust
      parameters: []
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      description:
                        type: string
                      guard_name:
                        type: string
                      users_count:
                        type: integer
                      permissions:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            guard_name:
                              type: string
                            resource:
                              type: string
                            action:
                              type: string
                            created_at:
                              type: string
                            updated_at:
                              type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 1
                    name: admin
                    description: Full system access with all permissions including
                      user management, settings, and system configuration.
                    guard_name: sanctum
                    users_count: 3
                    permissions:
                    - id: 1
                      name: users.index
                      guard_name: sanctum
                      resource: users
                      action: index
                      created_at: '2024-01-01T00:00:00+00:00'
                      updated_at: '2024-01-01T00:00:00+00:00'
                    - id: 2
                      name: users.show
                      guard_name: sanctum
                      resource: users
                      action: show
                      created_at: '2024-01-01T00:00:00+00:00'
                      updated_at: '2024-01-01T00:00:00+00:00'
                    created_at: '2024-01-01T00:00:00+00:00'
                    updated_at: '2024-01-15T10:00:00+00:00'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      name:
                        type: array
                        items:
                          type: string
                example:
                  message: The name has already been taken.
                  errors:
                    name:
                    - The name has already been taken.
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: post-api-roles
  /api/roles/permissions/grouped:
    get:
      tags:
      - Roles & Permissions
      summary: Get Permissions (Grouped)
      description: 'Returns the full permission catalog grouped by resource for the
        permission-matrix UI. Each group has a resource key, human label, icon, and
        its permissions.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        resource:
                          type: string
                        label:
                          type: string
                        icon:
                          type: string
                        permissions:
                          type: array
                          items:
                            type: object
                            properties:
                              id:
                                type: integer
                              name:
                                type: string
                              guard_name:
                                type: string
                              resource:
                                type: string
                              action:
                                type: string
                              created_at:
                                type: string
                              updated_at:
                                type: string
                example:
                  data:
                  - resource: users
                    label: Users
                    icon: mdi-account-group
                    permissions:
                    - id: 1
                      name: users.index
                      guard_name: sanctum
                      resource: users
                      action: index
                      created_at: '2024-01-01T00:00:00+00:00'
                      updated_at: '2024-01-01T00:00:00+00:00'
                    - id: 2
                      name: users.show
                      guard_name: sanctum
                      resource: users
                      action: show
                      created_at: '2024-01-01T00:00:00+00:00'
                      updated_at: '2024-01-01T00:00:00+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: get-api-roles-permissions-grouped
  /api/roles/{role}:
    get:
      tags:
      - Roles & Permissions
      summary: Show Role
      description: 'Returns a single role with its permissions and users_count.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: role
        in: path
        schema:
          type: integer
        required: true
        description: Role ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      description:
                        type: string
                      guard_name:
                        type: string
                      users_count:
                        type: integer
                      permissions:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            guard_name:
                              type: string
                            resource:
                              type: string
                            action:
                              type: string
                            created_at:
                              type: string
                            updated_at:
                              type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 1
                    name: admin
                    description: Full system access with all permissions including
                      user management, settings, and system configuration.
                    guard_name: sanctum
                    users_count: 3
                    permissions:
                    - id: 1
                      name: users.index
                      guard_name: sanctum
                      resource: users
                      action: index
                      created_at: '2024-01-01T00:00:00+00:00'
                      updated_at: '2024-01-01T00:00:00+00:00'
                    - id: 2
                      name: users.show
                      guard_name: sanctum
                      resource: users
                      action: show
                      created_at: '2024-01-01T00:00:00+00:00'
                      updated_at: '2024-01-01T00:00:00+00:00'
                    created_at: '2024-01-01T00:00:00+00:00'
                    updated_at: '2024-01-15T10:00:00+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-session-only: true
      operationId: get-api-roles-role
    put:
      tags:
      - Roles & Permissions
      summary: Update Role
      description: 'Updates an existing role and re-syncs its permissions.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Body fields:

        - name (required, string, max 255, unique in roles ignoring this role)

        - description (optional, string, max 500)

        - permissions (optional, array of permission names; each must exist in permissions)


        Authentication: Requires Bearer token.


        **Requires permission:** `roles.update`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                description:
                  type: string
                permissions:
                  type: array
                  items:
                    type: string
              example:
                name: warehouse_manager
                description: Manage warehouses and inventory
                permissions:
                - warehouses.index
                - warehouses.update
                - inventory.index
                - inventory.adjust
      parameters:
      - name: role
        in: path
        schema:
          type: integer
        required: true
        description: Role ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      description:
                        type: string
                      guard_name:
                        type: string
                      users_count:
                        type: integer
                      permissions:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            guard_name:
                              type: string
                            resource:
                              type: string
                            action:
                              type: string
                            created_at:
                              type: string
                            updated_at:
                              type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 1
                    name: admin
                    description: Full system access with all permissions including
                      user management, settings, and system configuration.
                    guard_name: sanctum
                    users_count: 3
                    permissions:
                    - id: 1
                      name: users.index
                      guard_name: sanctum
                      resource: users
                      action: index
                      created_at: '2024-01-01T00:00:00+00:00'
                      updated_at: '2024-01-01T00:00:00+00:00'
                    - id: 2
                      name: users.show
                      guard_name: sanctum
                      resource: users
                      action: show
                      created_at: '2024-01-01T00:00:00+00:00'
                      updated_at: '2024-01-01T00:00:00+00:00'
                    created_at: '2024-01-01T00:00:00+00:00'
                    updated_at: '2024-01-15T10:00:00+00:00'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      name:
                        type: array
                        items:
                          type: string
                example:
                  message: The name has already been taken.
                  errors:
                    name:
                    - The name has already been taken.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-session-only: true
      operationId: put-api-roles-role
    delete:
      tags:
      - Roles & Permissions
      summary: Delete Role
      description: 'Deletes a role. Users assigned the role lose its permissions.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Returns 204 No Content on success.


        Authentication: Requires Bearer token AND the `roles.delete` permission (403
        Forbidden otherwise).


        **Requires permission:** `roles.delete`'
      parameters:
      - name: role
        in: path
        schema:
          type: integer
        required: true
        description: Role ID
        example: '1'
      responses:
        '204':
          description: No Content
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            text/plain:
              schema:
                type: string
                example: ''
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-session-only: true
      operationId: delete-api-roles-role
  /api/users/{user}/roles:
    put:
      tags:
      - Roles & Permissions
      summary: Assign Roles to User
      description: 'Syncs the Spatie roles assigned to a user (sanctum guard). Replaces
        the user''s current roles with the provided list.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Body fields:

        - roles (array of role names; each must exist in roles)


        Returns the updated user (including roles and flattened permissions).


        Authentication: Requires Bearer token AND the `users.update` permission (403
        Forbidden otherwise).


        Errors:

        - 403 Forbidden — authenticated user lacks the `users.update` permission

        - 404 Not Found — the target user does not belong to the current tenant (cross-tenant
        access is rejected)

        - 422 Unprocessable Entity — a provided role name does not exist


        **Requires permission:** `users.update`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                roles:
                  type: array
                  items:
                    type: string
              example:
                roles:
                - admin
      parameters:
      - name: user
        in: path
        schema:
          type: integer
        required: true
        description: User ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      email:
                        type: string
                      is_admin:
                        type: boolean
                      is_power_user:
                        type: boolean
                      is_super_admin:
                        type: boolean
                      role:
                        type: string
                      roles:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            description:
                              type: string
                            guard_name:
                              type: string
                      permissions:
                        type: array
                        items:
                          type: string
                example:
                  data:
                    id: 1
                    name: Alice Johnson
                    email: alice@example.com
                    is_admin: true
                    is_power_user: false
                    is_super_admin: false
                    role: Admin
                    roles:
                    - id: 1
                      name: admin
                      description: Full system access...
                      guard_name: sanctum
                    permissions:
                    - users.index
                    - users.show
                    - users.create
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-session-only: true
      operationId: put-api-users-user-roles
  /api/users/roles/bulk:
    put:
      tags:
      - Roles & Permissions
      summary: Bulk Update User Roles
      description: 'Add or remove Spatie roles across many users at once (sanctum
        guard). Each user''s other roles are left unchanged — this is NOT a sync/replace.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Two targeting modes:

        - Selected rows — pass `ids` (array of user IDs).

        - All filtered — pass `apply_to_all: true` and `filters` (the same filter
        set as the users list); every user matching the filters is targeted. Empty
        `filters` targets all tenant users.


        Body fields:

        - ids (array of user IDs; required unless filters/apply_to_all provided)

        - apply_to_all (boolean; optional)

        - filters (object; required unless ids provided — flat `column.operator` keys
        and/or a `filter_groups` tree)

        - action (string; required; one of: add, remove)

        - roles (array of role names; required, min 1; each must exist in roles)


        Only users attached to the current tenant are affected — cross-tenant IDs
        are silently ignored.


        Returns a count message. If no users matched, returns 200 with a "No users
        matched" message.


        Authentication: Requires Bearer token AND the `users.update` permission (403
        Forbidden otherwise).


        Errors:

        - 403 Forbidden — authenticated user lacks the `users.update` permission

        - 422 Unprocessable Entity — invalid action, empty roles, or a role name that
        does not exist


        **Requires permission:** `users.update`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
                action:
                  type: string
                roles:
                  type: array
                  items:
                    type: string
              example:
                ids:
                - 1
                - 2
                - 3
                action: add
                roles:
                - admin
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 OK (Selected)
                  value:
                    message: 3 user(s) updated — roles added to the selection.
                example-1:
                  summary: 200 OK (All Filtered, Remove)
                  value:
                    message: 12 user(s) updated — roles removed from the selection.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      action:
                        type: array
                        items:
                          type: string
                      roles:
                        type: array
                        items:
                          type: string
                example:
                  message: 'The action field must be one of: add, remove.'
                  errors:
                    action:
                    - The selected action is invalid.
                    roles:
                    - The roles field is required.
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: put-api-users-roles-bulk
  /api/features:
    get:
      tags:
      - Feature Flags
      summary: Get Feature Flags
      description: 'Returns the resolved feature-flag map for the account associated
        with the authenticated token. Each key is a feature name and each value is
        a boolean indicating whether that feature is enabled for the account. The
        same map is also included on `GET /api/auth/profile` under `features`; this
        standalone endpoint lets a client refresh feature state without re-fetching
        the full profile.


        Authentication: Requires Bearer token.


        **Response fields (`data`):**

        - `granular_permissions` (boolean) — granular role/permission authorization
        is enabled.


        A feature absent from the map (or any value other than `true`) should be treated
        as disabled.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      granular_permissions:
                        type: boolean
                  status:
                    type: string
                example:
                  data:
                    granular_permissions: false
                  status: success
        '401':
          description: Unauthorized
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Unauthenticated.
        '429': *id001
        '403': *id003
      operationId: get-api-features
  /api/alerts:
    get:
      tags:
      - Alerts
      summary: List Alerts
      description: 'Paginated list of the authenticated user''s alerts.


        :::info[Required scope: `settings:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Alerts are deduplicated: repeat occurrences of the same condition update a
        single alert (see `occurrences` and `last_seen_at`) instead of creating duplicates.
        State-type alerts (`lifecycle: state`) describe an ongoing condition and are
        automatically resolved when it clears — resolved alerts move out of the default
        listing and are available via `filter[status]=resolved`.


        Each alert carries a `reason` and human-readable `reason_label` explaining
        why the user received it (for example, "You''re an administrator" or "You''re
        subscribed to this alert type").


        Default listing excludes dismissed and resolved alerts. Default sort: -last_seen_at.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: string
                        priority:
                          type: string
                        category:
                          type: string
                        alert_type:
                          type: string
                        lifecycle:
                          type: string
                        entity_tag:
                          type: string
                        title:
                          type: string
                        message:
                          type: string
                        action_url:
                          type: string
                        alertable_type:
                          type: string
                          nullable: true
                        alertable_id:
                          type: string
                          nullable: true
                        reason:
                          type: string
                        reason_label:
                          type: string
                        occurrences:
                          type: integer
                        status:
                          type: string
                        is_read:
                          type: boolean
                        read_at:
                          type: string
                          nullable: true
                        resolved_at:
                          type: string
                          nullable: true
                        resolved_ago:
                          type: string
                          nullable: true
                        last_seen_at:
                          type: string
                        created_at:
                          type: string
                        first_seen_ago:
                          type: string
                        time_ago:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - id: 9c2f4c1e-8a4e-4f7c-9a2b-1d2f3a4b5c6d
                    priority: high
                    category: integrations
                    alert_type: amazon_missing_nominal_code
                    lifecycle: state
                    entity_tag: Amazon
                    title: Missing Amazon Accounting Mappings
                    message: 65 Amazon settlement codes need mapping for Amazon Leaf
                      Shave.
                    action_url: /integrations/amazon/finance/settlement-mappings
                    alertable_type: null
                    alertable_id: null
                    reason: role:admin
                    reason_label: You're an administrator
                    occurrences: 4
                    status: active
                    is_read: false
                    read_at: null
                    resolved_at: null
                    resolved_ago: null
                    last_seen_at: '2026-07-16T14:05:00+00:00'
                    created_at: '2026-07-13T09:12:00+00:00'
                    first_seen_ago: 3 days ago
                    time_ago: 2 hours ago
                  current_page: 1
                  last_page: 1
                  per_page: 20
                  total: 1
                  from: 1
                  to: 1
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: settings:read
      operationId: get-api-alerts
  /api/alerts/unread-count:
    get:
      tags:
      - Alerts
      summary: Get Unread Count
      description: 'Returns unread alert counts broken down by priority for the authenticated
        user. Used to populate notification badges.


        :::info[Required scope: `settings:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  high:
                    type: integer
                  normal:
                    type: integer
                example:
                  high: 3
                  normal: 12
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: settings:read
      operationId: get-api-alerts-unread-count
  /api/alerts/category-counts:
    get:
      tags:
      - Alerts
      summary: Get Category Counts
      description: 'Returns alert counts grouped by category for the authenticated
        user. Used to show category-level notification counts in the UI.


        :::info[Required scope: `settings:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token


        Categories: orders, inventory, purchase_orders, integrations, system, financial'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  orders:
                    type: integer
                  inventory:
                    type: integer
                  purchase_orders:
                    type: integer
                  integrations:
                    type: integer
                  system:
                    type: integer
                  financial:
                    type: integer
                example:
                  orders: 5
                  inventory: 2
                  purchase_orders: 0
                  integrations: 1
                  system: 0
                  financial: 3
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: settings:read
      operationId: get-api-alerts-category-counts
  /api/alerts/{alert}/read:
    put:
      tags:
      - Alerts
      summary: Mark Alert as Read
      description: 'Marks the specified alert as read by setting the read_at timestamp.


        :::info[Required scope: `settings:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token'
      requestBody:
        content: {}
      parameters:
      - name: alert
        in: path
        schema:
          type: string
        required: true
        description: Alert ID (UUID)
        example: 550e8400-e29b-41d4-a716-446655440000
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Alert marked as read.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: settings:write
      operationId: put-api-alerts-alert-read
  /api/alerts/{alert}/unread:
    put:
      tags:
      - Alerts
      summary: Mark Alert as Unread
      description: 'Marks the specified alert as unread by clearing the read_at timestamp.


        :::info[Required scope: `settings:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token'
      requestBody:
        content: {}
      parameters:
      - name: alert
        in: path
        schema:
          type: string
        required: true
        description: Alert ID (UUID)
        example: 550e8400-e29b-41d4-a716-446655440000
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Alert marked as unread.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: settings:write
      operationId: put-api-alerts-alert-unread
  /api/alerts/mark-all-read:
    put:
      tags:
      - Alerts
      summary: Mark All as Read
      description: 'Marks all alerts as read for the authenticated user. Optionally
        filter by priority.


        :::info[Required scope: `settings:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token


        Request body (optional):

        - priority (string, optional): Filter to only mark alerts of this priority
        as read. Values: ''high'', ''normal''. Omit to mark all alerts read.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                priority:
                  type: string
              example:
                priority: high
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: All alerts marked as read.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      priority:
                        type: array
                        items:
                          type: string
                example:
                  message: 'The priority field must be one of: high, normal.'
                  errors:
                    priority:
                    - 'The priority field must be one of: high, normal.'
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: settings:write
      operationId: put-api-alerts-mark-all-read
  /api/alerts/dismiss-all:
    put:
      tags:
      - Alerts
      summary: Dismiss All Alerts
      description: 'Dismisses all alerts for the authenticated user by setting their
        dismissed_at timestamp. Optionally filter by priority.


        :::info[Required scope: `settings:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token


        Request body (optional):

        - priority (string, optional): Filter to only dismiss alerts of this priority.
        Values: ''high'', ''normal''. Omit to dismiss all.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                priority:
                  type: string
              example:
                priority: normal
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: All alerts dismissed.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: settings:write
      operationId: put-api-alerts-dismiss-all
  /api/alerts/{alert}/dismiss:
    put:
      tags:
      - Alerts
      summary: Dismiss Alert
      description: 'Dismisses the specified alert by setting the dismissed_at timestamp.


        :::info[Required scope: `settings:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token'
      requestBody:
        content: {}
      parameters:
      - name: alert
        in: path
        schema:
          type: string
        required: true
        description: Alert ID (UUID)
        example: 550e8400-e29b-41d4-a716-446655440000
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Alert dismissed.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: settings:write
      operationId: put-api-alerts-alert-dismiss
  /api/alerts/{alert}/undismiss:
    put:
      tags:
      - Alerts
      summary: Undismiss Alert
      description: 'Restores (undismisses) the specified alert by clearing the dismissed_at
        timestamp.


        :::info[Required scope: `settings:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token'
      requestBody:
        content: {}
      parameters:
      - name: alert
        in: path
        schema:
          type: string
        required: true
        description: Alert ID (UUID)
        example: 550e8400-e29b-41d4-a716-446655440000
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Alert restored.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: settings:write
      operationId: put-api-alerts-alert-undismiss
  /api/alerts/bulk-read:
    put:
      tags:
      - Alerts
      summary: Bulk Mark as Read
      description: 'Marks multiple alerts as read in a single request.


        :::info[Required scope: `settings:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token


        Request body:

        - ids (array, required): Array of alert UUIDs to mark as read'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: string
              example:
                ids:
                - 550e8400-e29b-41d4-a716-446655440000
                - 661f9511-f30c-52e5-b827-557766551111
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 2 alerts marked as read.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      ids:
                        type: array
                        items:
                          type: string
                example:
                  message: The ids field is required.
                  errors:
                    ids:
                    - The ids field is required.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: settings:write
      operationId: put-api-alerts-bulk-read
  /api/alerts/bulk-unread:
    put:
      tags:
      - Alerts
      summary: Bulk Mark as Unread
      description: 'Marks multiple alerts as unread in a single request.


        :::info[Required scope: `settings:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token


        Request body:

        - ids (array, required): Array of alert UUIDs to mark as unread'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: string
              example:
                ids:
                - 550e8400-e29b-41d4-a716-446655440000
                - 661f9511-f30c-52e5-b827-557766551111
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 2 alerts marked as unread.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: settings:write
      operationId: put-api-alerts-bulk-unread
  /api/alerts/bulk-dismiss:
    put:
      tags:
      - Alerts
      summary: Bulk Dismiss
      description: 'Dismisses multiple alerts in a single request.


        :::info[Required scope: `settings:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token


        Request body:

        - ids (array, required): Array of alert UUIDs to dismiss'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: string
              example:
                ids:
                - 550e8400-e29b-41d4-a716-446655440000
                - 661f9511-f30c-52e5-b827-557766551111
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 2 alerts dismissed.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: settings:write
      operationId: put-api-alerts-bulk-dismiss
  /api/alerts/bulk-undismiss:
    put:
      tags:
      - Alerts
      summary: Bulk Undismiss
      description: 'Restores (undismisses) multiple alerts in a single request.


        :::info[Required scope: `settings:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token


        Request body:

        - ids (array, required): Array of alert UUIDs to undismiss'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: string
              example:
                ids:
                - 550e8400-e29b-41d4-a716-446655440000
                - 661f9511-f30c-52e5-b827-557766551111
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 2 alerts restored.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: settings:write
      operationId: put-api-alerts-bulk-undismiss
  /api/alert-subscriptions:
    get:
      tags:
      - Alerts
      summary: Get Alert Audience
      description: 'Returns the resolved audience for one alert type: every user who
        currently receives it and why. The audience is the type''s default audience
        (administrators, all users, or holders of a permission) merged with explicit
        subscribe/unsubscribe changes.


        Each member''s `source` explains their inclusion: `role:admin`, `permission:<name>`,
        `subscription`, or `all_users`.


        Requires a token with permission to view alert preferences.'
      parameters:
      - name: alert_type
        in: query
        schema:
          type: string
        description: The alert type to inspect (required). One of the alert type identifiers
          returned by List Alert Preferences.
        example: amazon_missing_nominal_code
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      alert_type:
                        type: string
                      default_audience:
                        type: string
                      mandatory:
                        type: boolean
                      users:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            email:
                              type: string
                            source:
                              type: string
                example:
                  data:
                    alert_type: amazon_missing_nominal_code
                    default_audience: all administrators
                    mandatory: false
                    users:
                    - id: 7
                      name: Jane Winters
                      email: jane@acme.com
                      source: role:admin
                    - id: 42
                      name: Sam Okafor
                      email: sam@acme.com
                      source: subscription
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-alert-subscriptions
    put:
      tags:
      - Alerts
      summary: Update Alert Audience
      description: 'Applies audience changes for one alert type.


        Actions per change:

        - `subscribe` — add the user to the audience (beyond the default audience)

        - `unsubscribe` — remove the user, including default-audience members

        - `reset` — remove any explicit change so the user reverts to plain default-audience
        membership


        Returns the refreshed audience. Returns 422 when a change would leave a critical
        alert type with an empty audience, or when a user does not belong to this
        account.


        Requires a token with permission to update alert preferences.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                alert_type:
                  type: string
                changes:
                  type: array
                  items:
                    type: object
                    properties:
                      user_id:
                        type: integer
                      action:
                        type: string
              example:
                alert_type: amazon_missing_nominal_code
                changes:
                - user_id: 42
                  action: subscribe
                - user_id: 7
                  action: unsubscribe
                - user_id: 13
                  action: reset
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      alert_type:
                        type: string
                      default_audience:
                        type: string
                      mandatory:
                        type: boolean
                      users:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            email:
                              type: string
                            source:
                              type: string
                example:
                  data:
                    alert_type: amazon_missing_nominal_code
                    default_audience: all administrators
                    mandatory: false
                    users:
                    - id: 7
                      name: Jane Winters
                      email: jane@acme.com
                      source: role:admin
                    - id: 42
                      name: Sam Okafor
                      email: sam@acme.com
                      source: subscription
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      changes:
                        type: array
                        items:
                          type: string
                example:
                  message: '"Integration Authorization Expired" is a critical alert
                    — its audience cannot be emptied.'
                  errors:
                    changes:
                    - '"Integration Authorization Expired" is a critical alert — its
                      audience cannot be emptied.'
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: put-api-alert-subscriptions
  /api/alert-subscriptions/counts:
    get:
      tags:
      - Alerts
      summary: Get Alert Audience Counts
      description: 'Audience size per alert type — how many users currently receive
        each type after subscribe/unsubscribe changes are applied to the default audience.
        A count of 0 means nobody will receive that alert.


        Requires a token with permission to view alert preferences.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      export_completed:
                        type: integer
                      amazon_missing_nominal_code:
                        type: integer
                      integration_sync_inactive:
                        type: integer
                example:
                  data:
                    export_completed: 3
                    amazon_missing_nominal_code: 4
                    integration_sync_inactive: 3
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-alert-subscriptions-counts
  /api/alert-preferences/mine:
    get:
      tags:
      - Alerts
      summary: Get My Notification Preferences
      description: 'The authenticated user''s personal notification preference matrix.
        Only alert types whose audience includes the user are returned, grouped by
        category (and by integration for integration-specific types).


        Each row shows the resolved value per channel plus an `inherited` marker —
        `true` means the value comes from the account-wide preference or the built-in
        default rather than a personal override. Rows with `mandatory: true` cannot
        have their in-app channel disabled. `audience_reason` explains why the user
        receives the type at all.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      groups:
                        type: object
                        properties:
                          purchase_orders:
                            type: object
                            properties:
                              label:
                                type: string
                              icon:
                                type: string
                                nullable: true
                              preferences:
                                type: array
                                items:
                                  type: object
                                  properties:
                                    alert_type:
                                      type: string
                                    label:
                                      type: string
                                    description:
                                      type: string
                                    mandatory:
                                      type: boolean
                                    audience_reason:
                                      type: string
                                    audience_reason_label:
                                      type: string
                                    priority:
                                      type: string
                                    tenant_enabled:
                                      type: boolean
                                    in_app:
                                      type: object
                                      properties:
                                        value:
                                          type: boolean
                                        inherited:
                                          type: boolean
                                    email:
                                      type: object
                                      properties:
                                        value:
                                          type: boolean
                                        inherited:
                                          type: boolean
                                    frequency:
                                      type: object
                                      properties:
                                        value:
                                          type: string
                                        inherited:
                                          type: boolean
                example:
                  data:
                    groups:
                      purchase_orders:
                        label: Purchase Orders
                        icon: null
                        preferences:
                        - alert_type: purchase_order_approval_requested
                          label: Purchase Order Approval Requested
                          description: Triggered when a user without approval permission
                            submits a purchase order for approval.
                          mandatory: false
                          audience_reason: permission:purchase_orders.approve
                          audience_reason_label: You can approve purchase orders
                          priority: high
                          tenant_enabled: true
                          in_app:
                            value: true
                            inherited: true
                          email:
                            value: false
                            inherited: true
                          frequency:
                            value: instant
                            inherited: true
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-alert-preferences-mine
    put:
      tags:
      - Alerts
      summary: Update My Notification Preferences
      description: 'Updates the authenticated user''s personal notification overrides.
        Fields are tri-state: send `null` to reset a field so it inherits the account-wide
        preference / built-in default again; omit a field to leave it unchanged.


        Fields per preference:

        - `alert_type` (string, required)

        - `in_app_enabled` (boolean or null) — whether this alert appears in your
        in-app alert tray

        - `email_enabled` (boolean or null) — whether this alert is emailed to your
        own address

        - `notification_frequency` (string or null) — `instant`, `daily_digest`, or
        `weekly_digest`


        Returns 422 when disabling the in-app channel for a critical (mandatory) alert
        type.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                preferences:
                  type: array
                  items:
                    type: object
                    properties:
                      alert_type:
                        type: string
                      in_app_enabled:
                        type: boolean
                      email_enabled:
                        type: boolean
                      notification_frequency:
                        type: string
              example:
                preferences:
                - alert_type: purchase_order_approval_requested
                  in_app_enabled: true
                  email_enabled: false
                  notification_frequency: daily_digest
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Notification preferences updated.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      preferences:
                        type: array
                        items:
                          type: string
                example:
                  message: '"Integration Authorization Expired" is a critical alert
                    and cannot be turned off.'
                  errors:
                    preferences:
                    - '"Integration Authorization Expired" is a critical alert and
                      cannot be turned off.'
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: put-api-alert-preferences-mine
  /api/alert-preferences/mine/preset:
    post:
      tags:
      - Alerts
      summary: Apply My Notification Preset
      description: 'Applies a notification preset as a starting point for the authenticated
        user''s preference matrix (individual rows stay editable afterwards).


        Presets:

        - `everything` — clear all personal overrides; every channel inherits the
        defaults

        - `important` — keep the in-app channel for high-priority and critical types
        only

        - `critical` — keep the in-app channel for critical types only'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                preset:
                  type: string
              example:
                preset: important
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Preset applied.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-alert-preferences-mine-preset
  /api/tracked-job-logs/{tracked_job_log}:
    get:
      tags:
      - Jobs & Logs
      summary: Show Tracked Job Log
      description: 'Returns a single tracked job log by ID with full progress details
        including batch progress, results, and status transitions.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: tracked_job_log
        in: path
        schema:
          type: integer
        required: true
        description: Tracked job log ID
        example: '142'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      job_type:
                        type: string
                      queue:
                        type: string
                      job_name:
                        type: string
                      status:
                        type: string
                      related_model:
                        type: object
                        properties:
                          id:
                            type: integer
                          type:
                            type: string
                          reference:
                            type: string
                      related_model_reference:
                        type: string
                      messages:
                        type: string
                        nullable: true
                      attempted_at:
                        type: string
                      completed_at:
                        type: string
                      duration:
                        type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      fetch_batch:
                        type: object
                        properties:
                          batch_id:
                            type: string
                          total:
                            type: integer
                          processed:
                            type: integer
                          failed:
                            type: integer
                          progress_percentage:
                            type: integer
                          finished:
                            type: boolean
                      detail_batch:
                        type: string
                        nullable: true
                      status_batches:
                        type: string
                        nullable: true
                      results:
                        type: object
                        properties:
                          synced_orders:
                            type: integer
                          skipped:
                            type: integer
                          has_failures:
                            type: boolean
                          failed_count:
                            type: integer
                      total_items:
                        type: integer
                      processed_items:
                        type: integer
                      progress_percentage:
                        type: integer
                example:
                  data:
                    id: 142
                    job_type: App\Jobs\Shopify\SyncShopifyOrdersJob
                    queue: default
                    job_name: 'Sync Shopify Orders: MyStore'
                    status: completed
                    related_model:
                      id: 5
                      type: App\Modules\Shopify\Models\ShopifyIntegrationInstance
                      reference: MyStore
                    related_model_reference: MyStore
                    messages: null
                    attempted_at: '2024-06-01T09:00:00.000000Z'
                    completed_at: '2024-06-01T09:05:23.000000Z'
                    duration: 323
                    created_at: '2024-06-01T09:00:00.000000Z'
                    updated_at: '2024-06-01T09:05:23.000000Z'
                    fetch_batch:
                      batch_id: abc123
                      total: 50
                      processed: 50
                      failed: 0
                      progress_percentage: 100
                      finished: true
                    detail_batch: null
                    status_batches: null
                    results:
                      synced_orders: 45
                      skipped: 2
                      has_failures: false
                      failed_count: 0
                    total_items: 47
                    processed_items: 47
                    progress_percentage: 100
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No query results for model [App\Models\TrackedJobLog] 999
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: get-api-tracked-job-logs-tracked-job-log
    delete:
      tags:
      - Jobs & Logs
      summary: Delete Tracked Job Log
      description: 'Deletes a tracked job log by ID.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: tracked_job_log
        in: path
        schema:
          type: integer
        required: true
        description: Tracked job log ID
        example: '142'
      responses:
        '204':
          description: No Content
          content:
            text/plain:
              schema:
                type: string
                example: ''
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-session-only: true
      operationId: delete-api-tracked-job-logs-tracked-job-log
    put:
      tags:
      - Jobs & Logs
      summary: Update Tracked Job Log
      description: 'Updates a tracked job log (e.g., to mark it as cancelled). Used
        by the frontend tracked job log endpoints to cancel running jobs.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                status:
                  type: string
              example:
                status: cancelled
      parameters:
      - name: tracked_job_log
        in: path
        schema:
          type: integer
        required: true
        description: Tracked job log ID
        example: '142'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      status:
                        type: string
                example:
                  data:
                    id: 142
                    status: cancelled
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-session-only: true
      operationId: put-api-tracked-job-logs-tracked-job-log
  /api/tracked-job-logs/retry/{trackedJobLog}:
    get:
      tags:
      - Jobs & Logs
      summary: Retry Job
      description: 'Re-dispatches a previously tracked background job using the same
        arguments stored in the job log. The job is re-created via reflection and
        dispatched to the same queue.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: trackedJobLog
        in: path
        schema:
          type: integer
        required: true
        description: Tracked job log ID
        example: '142'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Job has been requeued.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-session-only: true
      operationId: get-api-tracked-job-logs-retry-trackedjoblog
  /api/tracked-job-logs:
    get:
      tags:
      - Jobs & Logs
      summary: List Tracked Job Logs
      description: 'Returns a paginated list view list of tracked job logs. Tracked
        jobs represent background queue jobs visible via the tracked job log endpoints.


        Authentication: Requires Bearer token.


        Query parameters:

        - page — Page number (default: 1)

        - limit — Results per page (default: 15)

        - search — Full-text search by job name or type

        - sort — Sort field, prefix with - for descending (e.g., -created_at)

        - archived — 0 = active records, 1 = archived records'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        description: Page number for pagination
        example: '1'
      - name: limit
        in: query
        schema:
          type: integer
        description: Number of results per page
        example: '15'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        job_type:
                          type: string
                        queue:
                          type: string
                        job_name:
                          type: string
                        status:
                          type: string
                        related_model:
                          type: object
                          properties:
                            id:
                              type: integer
                            type:
                              type: string
                            reference:
                              type: string
                        related_model_reference:
                          type: string
                        messages:
                          type: string
                          nullable: true
                        attempted_at:
                          type: string
                        completed_at:
                          type: string
                        duration:
                          type: integer
                        created_at:
                          type: string
                        updated_at:
                          type: string
                        fetch_batch:
                          type: string
                          nullable: true
                        detail_batch:
                          type: string
                          nullable: true
                        status_batches:
                          type: string
                          nullable: true
                        results:
                          type: object
                          properties:
                            synced_orders:
                              type: integer
                            skipped:
                              type: integer
                        total_items:
                          type: integer
                        processed_items:
                          type: integer
                        progress_percentage:
                          type: integer
                  total:
                    type: integer
                  per_page:
                    type: integer
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                example:
                  data:
                  - id: 142
                    job_type: App\Jobs\Shopify\SyncShopifyOrdersJob
                    queue: default
                    job_name: 'Sync Shopify Orders: MyStore'
                    status: completed
                    related_model:
                      id: 5
                      type: App\Modules\Shopify\Models\ShopifyIntegrationInstance
                      reference: MyStore
                    related_model_reference: MyStore
                    messages: null
                    attempted_at: '2024-06-01T09:00:00.000000Z'
                    completed_at: '2024-06-01T09:05:23.000000Z'
                    duration: 323
                    created_at: '2024-06-01T09:00:00.000000Z'
                    updated_at: '2024-06-01T09:05:23.000000Z'
                    fetch_batch: null
                    detail_batch: null
                    status_batches: null
                    results:
                      synced_orders: 45
                      skipped: 2
                    total_items: 47
                    processed_items: 47
                    progress_percentage: 100
                  total: 350
                  per_page: 15
                  current_page: 1
                  last_page: 24
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-tracked-job-logs
    post:
      tags:
      - Jobs & Logs
      summary: Create Tracked Job Log
      description: 'Creates a new tracked job log entry. Note: Tracked job logs are
        typically created automatically by the TrackableJobTrait when background jobs
        are dispatched.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                job_name:
                  type: string
                status:
                  type: string
              example:
                job_name: Manual Job Entry
                status: pending
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: integer
                  job_name:
                    type: string
                  status:
                    type: string
                example:
                  id: 143
                  job_name: Manual Job Entry
                  status: pending
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-session-only: true
      operationId: post-api-tracked-job-logs
  /api/integrations:
    get:
      tags:
      - Integration Instances
      summary: List Integrations (Picker)
      description: 'List all available integrations and their connected instances.
        Powers the integration picker in the UI.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token + Power User access.


        Each integration includes a `deprecated` boolean. **Deprecated integrations
        (e.g. ShipMyOrders) are hidden from this list unless the tenant still has
        at least one connected instance**, in which case the integration is returned
        so its existing instances can be shown read-only. Deprecated integrations
        can no longer be connected (see `POST /api/integration-instances`).'
      parameters:
      - name: include_sku_io
        in: query
        schema:
          type: integer
        description: Optional (0/1). When 1, prepends the internal SKU.io integration
          to the list.
        example: '0'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        integration_settings_template:
                          type: object
                          properties: {}
                        image_url:
                          type: string
                        country:
                          type: string
                          nullable: true
                        supports_multiple_instances:
                          type: boolean
                        integration_type:
                          type: string
                        integration_sub_type:
                          type: string
                          nullable: true
                        deprecated:
                          type: boolean
                        last_sync:
                          type: string
                        integration_instances:
                          type: array
                  automated_warehouses:
                    type: array
                  status:
                    type: string
                example:
                  data:
                  - id: 1
                    name: Shopify
                    integration_settings_template: {}
                    image_url: https://cdn.sku.io/integrations/shopify.png
                    country: null
                    supports_multiple_instances: true
                    integration_type: sales_channel
                    integration_sub_type: null
                    deprecated: false
                    last_sync: '2026-06-15T08:30:00.000000Z'
                    integration_instances: []
                  - id: 12
                    name: ShipMyOrders
                    integration_settings_template: {}
                    image_url: https://cdn.sku.io/integrations/shipmyorders.png
                    country: null
                    supports_multiple_instances: false
                    integration_type: shipping_provider
                    integration_sub_type: null
                    deprecated: true
                    last_sync: null
                    integration_instances:
                    - id: 44
                      integration_id: 12
                      name: ShipMyOrders
                  automated_warehouses: []
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: get-api-integrations
  /api/integration-instances:
    post:
      tags:
      - Integration Instances
      summary: Create Integration Instance
      description: 'Create a new integration instance.


        :::info[Required scope: `integrations:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token + Power User access.


        Required: integration_id. Either name or integration_settings.settings.connectionName
        must be provided.


        The store ID from integration_settings.settings.store.id will create an associated
        sales channel.

        For Shopify: triggers location, webhook, products, and orders download if
        credentials are present.

        For ShipStation: fetches shipping services and creates webhooks.

        For ShipMyOrders: queues warehouse initialization.

        For Veracore: converts linked warehouse type to 3PL.


        Note: name must be unique across all integration instances.


        **Requires permission:** `integrations.create`


        **Deprecated integrations:** If the supplied `integration_id` belongs to a
        permanently deprecated integration (e.g. ShipMyOrders), the request is rejected
        with `400 Bad Request` and code `IsUnacceptable`. Existing instances and their
        historical data are retained read-only, but no new instance can be connected.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                integration_id:
                  type: integer
                name:
                  type: string
                connection_settings:
                  type: object
                  properties: {}
                integration_settings:
                  type: object
                  properties:
                    settings:
                      type: object
                      properties:
                        connectionName:
                          type: string
                        store:
                          type: object
                          properties:
                            id:
                              type: string
                    orders:
                      type: object
                      properties:
                        download:
                          type: object
                          properties:
                            open_start_date:
                              type: string
                            closed_start_date:
                              type: string
                    emailCustomers:
                      type: boolean
                is_automatic_sync_enabled:
                  type: boolean
              example:
                integration_id: 3
                name: My Shopify Store
                connection_settings: {}
                integration_settings:
                  settings:
                    connectionName: My Shopify Store
                    store:
                      id: myshop.myshopify.com
                  orders:
                    download:
                      open_start_date: '2024-01-01T00:00:00'
                      closed_start_date: '2024-01-01T00:00:00'
                  emailCustomers: false
                is_automatic_sync_enabled: true
      parameters: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_id:
                        type: integer
                      integration:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          integration_type:
                            type: string
                      name:
                        type: string
                      connection_settings:
                        type: object
                        properties: {}
                      integration_settings:
                        type: object
                        properties:
                          settings:
                            type: object
                            properties:
                              connectionName:
                                type: string
                          emailCustomers:
                            type: boolean
                      sales_channel:
                        type: object
                        properties:
                          id:
                            type: integer
                          integration_instance_id:
                            type: integer
                          store_id:
                            type: string
                      store_mappings:
                        type: array
                      is_deleting:
                        type: boolean
                      connection_status:
                        type: string
                      is_automatic_sync_enabled:
                        type: boolean
                  automated_warehouses:
                    type: array
                example:
                  data:
                    id: 12
                    integration_id: 3
                    integration:
                      id: 3
                      name: Shopify
                      integration_type: sales_channel
                    name: My Shopify Store
                    connection_settings: {}
                    integration_settings:
                      settings:
                        connectionName: My Shopify Store
                      emailCustomers: false
                    sales_channel:
                      id: 8
                      integration_instance_id: 12
                      store_id: myshop.myshopify.com
                    store_mappings: []
                    is_deleting: false
                    connection_status: connected
                    is_automatic_sync_enabled: true
                  automated_warehouses: []
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      integration_id:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: array
                example:
                  status: failure
                  message: ShipMyOrders is a deprecated integration and can no longer
                    be connected.
                  errors:
                    integration_id:
                    - message: ShipMyOrders is a deprecated integration and can no
                        longer be connected.
                      code: IsUnacceptable
                      data: []
        '422':
          description: Unprocessable Entity
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      integration_id:
                        type: array
                        items:
                          type: string
                      name:
                        type: array
                        items:
                          type: string
                example:
                  message: The given data was invalid.
                  errors:
                    integration_id:
                    - The integration id field is required.
                    name:
                    - The name has already been taken.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: integrations:write
      operationId: post-api-integration-instances
    get:
      tags:
      - Misc
      summary: List Integration Instances
      description: 'Returns all integration instances (connections to external platforms
        like Shopify, Amazon, Xero, etc.).


        Authentication: Requires Bearer token.'
      parameters:
      - name: per_page
        in: query
        schema:
          type: integer
        example: '10'
        description: Results per page (default 10).
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        type:
                          type: string
                        status:
                          type: string
                        created_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 3
                    name: My Shopify Store
                    type: shopify
                    status: active
                    created_at: '2023-06-01T00:00:00.000000Z'
                  current_page: 1
                  last_page: 1
                  per_page: 10
                  total: 3
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-integration-instances
  /api/integration-instances/{integration_instance}:
    get:
      tags:
      - Integration Instances
      summary: Get Integration Instance
      description: 'Get a single integration instance with its integration, store
        mappings, and warehouse location map.


        :::info[Required scope: `integrations:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token + Power User access.


        Note: access_token is stripped from connection_settings before returning.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '12'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_id:
                        type: integer
                      integration:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          integration_type:
                            type: string
                      name:
                        type: string
                      connection_settings:
                        type: object
                        properties:
                          shop_url:
                            type: string
                      integration_settings:
                        type: object
                        properties:
                          settings:
                            type: object
                            properties:
                              connectionName:
                                type: string
                          emailCustomers:
                            type: boolean
                          inventory:
                            type: object
                            properties:
                              sync_all_warehouses:
                                type: boolean
                      sales_channel:
                        type: object
                        properties:
                          id:
                            type: integer
                          store_id:
                            type: string
                      store_mappings:
                        type: array
                      is_deleting:
                        type: boolean
                      connection_status:
                        type: string
                      is_automatic_sync_enabled:
                        type: boolean
                  automated_warehouses:
                    type: array
                  warehouse_location_map:
                    type: array
                    items:
                      type: object
                      properties:
                        shopify_location_id:
                          type: integer
                        name:
                          type: string
                        warehouse_id:
                          type: integer
                        warehouse_name:
                          type: string
                example:
                  data:
                    id: 12
                    integration_id: 3
                    integration:
                      id: 3
                      name: Shopify
                      integration_type: sales_channel
                    name: My Shopify Store
                    connection_settings:
                      shop_url: myshop.myshopify.com
                    integration_settings:
                      settings:
                        connectionName: My Shopify Store
                      emailCustomers: false
                      inventory:
                        sync_all_warehouses: true
                    sales_channel:
                      id: 8
                      store_id: myshop.myshopify.com
                    store_mappings: []
                    is_deleting: false
                    connection_status: connected
                    is_automatic_sync_enabled: true
                  automated_warehouses: []
                  warehouse_location_map:
                  - shopify_location_id: 123456789
                    name: Main Warehouse
                    warehouse_id: 1
                    warehouse_name: Main Warehouse
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: integrations:read
      operationId: get-api-integration-instances-integration-instance
    put:
      tags:
      - Integration Instances
      summary: Update Integration Instance
      description: 'Update an integration instance. Settings are merged (not replaced)
        with existing settings.


        :::info[Required scope: `integrations:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token + Power User access.


        All fields are optional. Name must be unique.


        If inventory settings change for a sales channel integration, triggers inventory
        cache invalidation.

        If pricing settings change, triggers product listing price cache refresh.

        For sales channel integrations: syncs accounting transaction statuses if sync
        settings change.


        Allowed integration_settings.batch_period_sales_order_fulfillments values:
        daily, monthly, none.


        **Requires permission:** `integrations.update`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                integration_settings:
                  type: object
                  properties:
                    settings:
                      type: object
                      properties:
                        connectionName:
                          type: string
                    inventory:
                      type: object
                      properties:
                        sync_all_warehouses:
                          type: boolean
                    sync_sales_order_invoices_to_accounting:
                      type: boolean
                    sync_sales_credit_to_accounting:
                      type: boolean
                    batch_period_sales_order_fulfillments:
                      type: string
                    proforma_marketplace_cost_percentage:
                      type: number
                    proforma_payment_cost_percentage:
                      type: number
                is_automatic_sync_enabled:
                  type: boolean
              example:
                name: My Shopify Store (Updated)
                integration_settings:
                  settings:
                    connectionName: My Shopify Store (Updated)
                  inventory:
                    sync_all_warehouses: true
                  sync_sales_order_invoices_to_accounting: false
                  sync_sales_credit_to_accounting: false
                  batch_period_sales_order_fulfillments: daily
                  proforma_marketplace_cost_percentage: 2.5
                  proforma_payment_cost_percentage: 1.5
                is_automatic_sync_enabled: true
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '12'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      integration_settings:
                        type: object
                        properties:
                          settings:
                            type: object
                            properties:
                              connectionName:
                                type: string
                          inventory:
                            type: object
                            properties:
                              sync_all_warehouses:
                                type: boolean
                          sync_sales_order_invoices_to_accounting:
                            type: boolean
                      is_automatic_sync_enabled:
                        type: boolean
                  automated_warehouses:
                    type: array
                example:
                  data:
                    id: 12
                    name: My Shopify Store (Updated)
                    integration_settings:
                      settings:
                        connectionName: My Shopify Store (Updated)
                      inventory:
                        sync_all_warehouses: true
                      sync_sales_order_invoices_to_accounting: false
                    is_automatic_sync_enabled: true
                  automated_warehouses: []
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: integrations:write
      operationId: put-api-integration-instances-integration-instance
    delete:
      tags:
      - Integration Instances
      summary: Delete Integration Instance
      description: 'Queue deletion of an integration instance. The actual deletion
        is handled asynchronously via the salesOrderProcessing queue.


        :::info[Required scope: `integrations:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token + Power User access.


        **Requires permission:** `integrations.delete`'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '12'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Added to the queue.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: integrations:write
      operationId: delete-api-integration-instances-integration-instance
  /api/integration-instances/{integration_instance}/listings/{id}:
    get:
      tags:
      - Integration Instances
      summary: Get Single Listing
      description: 'Lookup a listing document in the sales channel. For Amazon: searches
        by seller_sku. For Shopify: by variant_id, sku, or id. For others: by sku
        or _id.


        :::info[Required scope: `integrations:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token + Power User access.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '12'
      - name: id
        in: path
        schema:
          type: string
        required: true
        description: Listing ID (SKU, variant_id, seller_sku, or _id depending on
          integration)
        example: abc123
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: string
                      sku:
                        type: string
                      title:
                        type: string
                      integration_instance_id:
                        type: integer
                      product_listing:
                        type: object
                        properties:
                          id:
                            type: integer
                          product:
                            type: object
                            properties:
                              id:
                                type: integer
                              name:
                                type: string
                example:
                  data:
                    id: abc123
                    sku: WIDGET-001
                    title: Widget A
                    integration_instance_id: 12
                    product_listing:
                      id: 300
                      product:
                        id: 55
                        name: Widget A
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: integrations:read
      operationId: get-api-integration-instances-integration-instance-listings-id
    delete:
      tags:
      - Integration Instances
      summary: Delete Single Listing
      description: 'Delete a single listing from the integration instance.


        :::info[Required scope: `integrations:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token + Power User access.


        Returns 400 if the listing is linked and cannot be deleted.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '12'
      - name: id
        in: path
        schema:
          type: string
        required: true
        description: Listing ID
        example: abc123
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: listing abc123 deleted successfully
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      listings:
                        type: string
                example:
                  message: Failed to delete listing abc123
                  errors:
                    listings: Listing is linked to a product
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: integrations:write
      operationId: delete-api-integration-instances-integration-instance-listings-id
  /api/integration-instances/{integration_instance}/listings/download:
    post:
      tags:
      - Integration Instances
      summary: Download Listings from Channel
      description: 'Queue a download of listings (products) from the sales channel.


        :::info[Required scope: `integrations:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token + Power User access.


        Supports: Shopify. Other integrations return an informational message.'
      requestBody:
        content: {}
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '12'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Shopify Listings download added to the Queue, it will be
                    processed shortly.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: integrations:write
      operationId: post-api-integration-instances-integration-instance-listings-download
  /api/integration-instances/{integration_instance}/import-mappings:
    post:
      tags:
      - Integration Instances
      summary: Import Listing Mappings
      description: 'Import listing mappings from a previously uploaded file. Dispatches
        an ImportListingMapping job.


        :::info[Required scope: `integrations:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token + Power User access.


        Returns a task_id for progress tracking.


        **Requires permission:** `integrations.manage`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                original_name:
                  type: string
                stored_name:
                  type: string
              example:
                original_name: mappings.csv
                stored_name: abc123.csv
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '12'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  task_id:
                    type: string
                example:
                  task_id: task-uuid-abc123
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: integrations:write
      operationId: post-api-integration-instances-integration-instance-import-mappings
  /api/integration-instances/{integration_instance}/orders/{order}:
    get:
      tags:
      - Integration Instances
      summary: Get Single Sales Channel Order
      description: 'Get a single sales channel order with its linked SKU sales order.


        :::info[Required scope: `integrations:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token + Power User access.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '12'
      - name: order
        in: path
        schema:
          type: string
        required: true
        description: Order ID
        example: order_abc
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: string
                      order_number:
                        type: string
                      integration_instance_id:
                        type: integer
                      sales_order:
                        type: string
                        nullable: true
                example:
                  data:
                    id: order_abc
                    order_number: '#1001'
                    integration_instance_id: 12
                    sales_order: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: integrations:read
      operationId: get-api-integration-instances-integration-instance-orders-order
  /api/integration-instances/{integration_instance}/orders/{order}/refresh:
    post:
      tags:
      - Integration Instances
      summary: Refresh Order from Sales Channel
      description: 'Refresh a sales channel order with fresh data from the channel
        API, then reconcile the linked SKU sales order.


        :::info[Required scope: `integrations:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token + Power User access.


        Supported channels: Shopify, WooCommerce, eBay, Walmart, BigCommerce, and
        Faire. Fetches the latest order from the channel and propagates changes to
        the linked SKU sales order (status/payment, and — for Faire — line additions,
        quantity edits, and removals). Returns the updated SalesOrder resource. Unsupported
        channels return an UnsupportedChannel error.'
      requestBody:
        content: {}
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '12'
      - name: order
        in: path
        schema:
          type: string
        required: true
        description: Order ID
        example: order_abc
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      order_number:
                        type: string
                      status:
                        type: string
                example:
                  data:
                    id: 501
                    order_number: SO-2024-1001
                    status: open
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: integrations:write
      operationId: post-api-integration-instances-integration-instance-orders-order-refresh
  /api/integration-instances/{integration_instance}/download-orders:
    post:
      tags:
      - Integration Instances
      summary: Download Orders from Channel
      description: 'Queue a download of orders from the sales channel.


        :::info[Required scope: `integrations:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token + Power User access.


        For Shopify: date_method (created|updated) and from_date.

        For Amazon: downloads MFN orders.


        **Requires permission:** `integrations.sync`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                date_method:
                  type: string
                from_date:
                  type: string
                status:
                  type: string
              example:
                date_method: created
                from_date: '2024-01-01'
                status: open
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '12'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Added to the Queue, it will be processed shortly
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: integrations:write
      operationId: post-api-integration-instances-integration-instance-download-orders
  /api/integration-instances/{integration_instance}/orders/{order}/archive:
    put:
      tags:
      - Integration Instances
      summary: Archive Single Channel Order
      description: 'Archive a single sales channel order.


        :::info[Required scope: `integrations:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token + Power User access.'
      requestBody:
        content: {}
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '12'
      - name: order
        in: path
        schema:
          type: string
        required: true
        description: Order ID
        example: order_abc
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: order archived successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: integrations:write
      operationId: put-api-integration-instances-integration-instance-orders-order-archive
  /api/integration-instances/{integration_instance}/orders/{order}/unarchived:
    put:
      tags:
      - Integration Instances
      summary: Unarchive Single Channel Order
      description: 'Unarchive a single sales channel order.


        :::info[Required scope: `integrations:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token + Power User access.'
      requestBody:
        content: {}
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '12'
      - name: order
        in: path
        schema:
          type: string
        required: true
        description: Order ID
        example: order_abc
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: order unarchived successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: integrations:write
      operationId: put-api-integration-instances-integration-instance-orders-order-unarchived
  /api/integration-instances/{integration_instance}/sync-inventory/preview:
    get:
      tags:
      - Integration Instances
      summary: Preview Sync Inventory
      description: 'Preview what inventory values would be synced to the sales channel
        before actually syncing.


        :::info[Required scope: `integrations:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token + Power User access.


        Calculates current available quantities for all product listings in the integration.
        Returns 400 if no product listings found.


        **Requires permission:** `integrations.sync`'
      parameters:
      - name: location_id
        in: query
        schema:
          type: integer
        description: 'Optional: filter to a specific location ID'
        example: '123456'
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '12'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: array
                items:
                  type: object
                  properties:
                    sku:
                      type: string
                    product_name:
                      type: string
                    current_quantity:
                      type: integer
                    calculated_quantity:
                      type: integer
                    location_id:
                      type: integer
                example:
                - sku: WIDGET-001
                  product_name: Widget A
                  current_quantity: 150
                  calculated_quantity: 145
                  location_id: 123456
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: integrations:read
      operationId: get-api-integration-instances-integration-instance-sync-inventory-preview
  /api/integration-instances/{integration_instance}/store-mapped-warehouse-locations:
    put:
      tags:
      - Integration Instances
      summary: Store Mapped Warehouse Locations
      description: 'Save Shopify location to warehouse mappings for an integration
        instance.


        :::info[Required scope: `integrations:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token + Power User access.


        Required: warehouse_mappings array. shopify_location_id must exist in shopify_locations.
        warehouse_id must exist in warehouses.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                warehouse_mappings:
                  type: array
                  items:
                    type: object
                    properties:
                      shopify_location_id:
                        type: integer
                      warehouse_id:
                        type: integer
              example:
                warehouse_mappings:
                - shopify_location_id: 123456789
                  warehouse_id: 1
                - shopify_location_id: 987654321
                  warehouse_id: 2
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '12'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Warehouse mappings updated successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: integrations:write
      operationId: put-api-integration-instances-integration-instance-store-mapped-warehouse-locations
  /api/integration-instances/{integration_instance}/sync-controls:
    patch:
      tags:
      - Integration Instances
      summary: Update Sync Controls
      description: 'Apply a granular, direction- and entity-aware sync-controls update
        for a channel integration instance. Replaces the overloaded `is_automatic_sync_enabled`
        boolean with per-capability toggles.


        :::info[Required scope: `integrations:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token + `integrations.update` permission.


        All sections are OPTIONAL — send a partial PATCH and only the provided keys
        are merged onto the instance''s current (or default) controls:


        - `schedule_state` — `active` or `paused`. Drives the derived `is_automatic_sync_enabled`
        coarse flag and pauses/resumes all scheduled sync.

        - `capabilities` — map of direction (`inbound`/`outbound`) to a map of entity
        (`orders`, `products`, `inventory`, `pricing`, `tracking`) to boolean. Capabilities
        outside the integration''s applicable matrix are silently discarded.

        - `source_of_truth` — for BIDIRECTIONAL entities only (`inventory`, `pricing`):
        `sku` or `channel`. Non-bidirectional entries are ignored.


        Returns the updated integration instance object, including `sync_controls`,
        `applicable_sync_capabilities`, and `is_sync_schedule_paused`. Each `applicable_sync_capabilities`
        descriptor carries `entity`, `label`, `capability_label`, `is_bidirectional`,
        plus `environment_blocked` (bool) and `environment_blocked_reason` (string|null).
        `environment_blocked` is `true` when the current backend environment refuses
        to run that outbound push — e.g. outside production, Amazon''s production-only
        inventory feed, or Shopify''s inventory push (unless `shopify.inventory_sync_enabled`)
        and tracking push. Always `false` in production and for unrestricted pushes
        — so the UI renders that toggle as disabled with `environment_blocked_reason`
        as the explanation.


        Accounting integrations are rejected with 400 — they use the separate accounting
        sync configuration.


        **Deprecation note:** `is_automatic_sync_enabled` is a legacy coarse flag
        kept as a derived mirror of the sync-controls schedule state (`sync_controls.scheduleState`).
        New consumers should read `is_sync_schedule_paused` for the schedule and `sync_controls`
        for per-capability state; the legacy field is slated for rename to `sync_schedule_active`.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                schedule_state:
                  type: string
                capabilities:
                  type: object
                  properties:
                    inbound:
                      type: object
                      properties:
                        orders:
                          type: boolean
                        products:
                          type: boolean
                    outbound:
                      type: object
                      properties:
                        tracking:
                          type: boolean
                        inventory:
                          type: boolean
                        pricing:
                          type: boolean
                source_of_truth:
                  type: object
                  properties:
                    inventory:
                      type: string
                    pricing:
                      type: string
              example:
                schedule_state: active
                capabilities:
                  inbound:
                    orders: true
                    products: true
                  outbound:
                    tracking: true
                    inventory: true
                    pricing: false
                source_of_truth:
                  inventory: sku
                  pricing: channel
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '12'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_id:
                        type: integer
                      name:
                        type: string
                      connection_status:
                        type: string
                      is_automatic_sync_enabled:
                        type: boolean
                      sync_status:
                        type: string
                      sync_controls:
                        type: object
                        properties:
                          schedule_state:
                            type: string
                          capabilities:
                            type: object
                            properties:
                              inbound:
                                type: object
                                properties:
                                  orders:
                                    type: boolean
                                  products:
                                    type: boolean
                              outbound:
                                type: object
                                properties:
                                  tracking:
                                    type: boolean
                                  inventory:
                                    type: boolean
                                  pricing:
                                    type: boolean
                          source_of_truth:
                            type: object
                            properties:
                              inventory:
                                type: string
                              pricing:
                                type: string
                      applicable_sync_capabilities:
                        type: object
                        properties:
                          inbound:
                            type: array
                            items:
                              type: object
                              properties:
                                entity:
                                  type: string
                                label:
                                  type: string
                                capability_label:
                                  type: string
                                is_bidirectional:
                                  type: boolean
                                environment_blocked:
                                  type: boolean
                                environment_blocked_reason:
                                  type: string
                                  nullable: true
                          outbound:
                            type: array
                            items:
                              type: object
                              properties:
                                entity:
                                  type: string
                                label:
                                  type: string
                                capability_label:
                                  type: string
                                is_bidirectional:
                                  type: boolean
                                environment_blocked:
                                  type: boolean
                                environment_blocked_reason:
                                  type: string
                                  nullable: true
                      is_sync_schedule_paused:
                        type: boolean
                example:
                  data:
                    id: 12
                    integration_id: 3
                    name: My Shopify Store
                    connection_status: connected
                    is_automatic_sync_enabled: true
                    sync_status: active
                    sync_controls:
                      schedule_state: active
                      capabilities:
                        inbound:
                          orders: true
                          products: true
                        outbound:
                          tracking: true
                          inventory: true
                          pricing: false
                      source_of_truth:
                        inventory: sku
                        pricing: channel
                    applicable_sync_capabilities:
                      inbound:
                      - entity: orders
                        label: Orders
                        capability_label: Import Orders
                        is_bidirectional: false
                        environment_blocked: false
                        environment_blocked_reason: null
                      - entity: products
                        label: Products
                        capability_label: Import Products
                        is_bidirectional: false
                        environment_blocked: false
                        environment_blocked_reason: null
                      outbound:
                      - entity: tracking
                        label: Tracking
                        capability_label: Submit Tracking
                        is_bidirectional: false
                        environment_blocked: false
                        environment_blocked_reason: null
                      - entity: inventory
                        label: Inventory
                        capability_label: Push Inventory
                        is_bidirectional: true
                        environment_blocked: false
                        environment_blocked_reason: null
                      - entity: pricing
                        label: Pricing
                        capability_label: Push Pricing
                        is_bidirectional: true
                        environment_blocked: false
                        environment_blocked_reason: null
                    is_sync_schedule_paused: false
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      integration_instance:
                        type: array
                        items:
                          type: string
                example:
                  message: Accounting integrations use a separate sync configuration.
                  errors:
                    integration_instance:
                    - Accounting integrations use a separate sync configuration.
        '422':
          description: Unprocessable Entity
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      schedule_state:
                        type: array
                        items:
                          type: string
                example:
                  message: The schedule state must be active or paused.
                  errors:
                    schedule_state:
                    - The schedule state must be active or paused.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: integrations:write
      operationId: patch-api-integration-instances-integration-instance-sync-controls
  /api/integration-instances/{integration_instance}/sync-controls/pause:
    post:
      tags:
      - Integration Instances
      summary: Pause Sync Schedule
      description: 'Pause the integration instance''s automatic sync schedule. Sets
        `schedule_state` to `paused`, which short-circuits all scheduled inbound pulls,
        inbound webhook processing, and outbound submissions, and flips the derived
        `is_automatic_sync_enabled` flag to false. Per-capability toggles are preserved
        so resuming restores the prior configuration.


        :::info[Required scope: `integrations:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token + `integrations.update` permission.


        No request body. Returns the updated integration instance object.


        **Deprecation note:** `is_automatic_sync_enabled` is a legacy coarse flag
        kept as a derived mirror of the sync-controls schedule state (`sync_controls.scheduleState`).
        New consumers should read `is_sync_schedule_paused` for the schedule and `sync_controls`
        for per-capability state; the legacy field is slated for rename to `sync_schedule_active`.'
      requestBody:
        content: {}
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '12'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_id:
                        type: integer
                      name:
                        type: string
                      connection_status:
                        type: string
                      is_automatic_sync_enabled:
                        type: boolean
                      sync_status:
                        type: string
                      sync_controls:
                        type: object
                        properties:
                          schedule_state:
                            type: string
                          capabilities:
                            type: object
                            properties:
                              inbound:
                                type: object
                                properties:
                                  orders:
                                    type: boolean
                                  products:
                                    type: boolean
                              outbound:
                                type: object
                                properties:
                                  tracking:
                                    type: boolean
                                  inventory:
                                    type: boolean
                                  pricing:
                                    type: boolean
                          source_of_truth:
                            type: object
                            properties:
                              inventory:
                                type: string
                              pricing:
                                type: string
                      applicable_sync_capabilities:
                        type: object
                        properties:
                          inbound:
                            type: array
                            items:
                              type: object
                              properties:
                                entity:
                                  type: string
                                label:
                                  type: string
                                capability_label:
                                  type: string
                                is_bidirectional:
                                  type: boolean
                                environment_blocked:
                                  type: boolean
                                environment_blocked_reason:
                                  type: string
                                  nullable: true
                          outbound:
                            type: array
                            items:
                              type: object
                              properties:
                                entity:
                                  type: string
                                label:
                                  type: string
                                capability_label:
                                  type: string
                                is_bidirectional:
                                  type: boolean
                                environment_blocked:
                                  type: boolean
                                environment_blocked_reason:
                                  type: string
                                  nullable: true
                      is_sync_schedule_paused:
                        type: boolean
                example:
                  data:
                    id: 12
                    integration_id: 3
                    name: My Shopify Store
                    connection_status: connected
                    is_automatic_sync_enabled: false
                    sync_status: active
                    sync_controls:
                      schedule_state: paused
                      capabilities:
                        inbound:
                          orders: true
                          products: true
                        outbound:
                          tracking: true
                          inventory: true
                          pricing: false
                      source_of_truth:
                        inventory: sku
                        pricing: channel
                    applicable_sync_capabilities:
                      inbound:
                      - entity: orders
                        label: Orders
                        capability_label: Import Orders
                        is_bidirectional: false
                        environment_blocked: false
                        environment_blocked_reason: null
                      - entity: products
                        label: Products
                        capability_label: Import Products
                        is_bidirectional: false
                        environment_blocked: false
                        environment_blocked_reason: null
                      outbound:
                      - entity: tracking
                        label: Tracking
                        capability_label: Submit Tracking
                        is_bidirectional: false
                        environment_blocked: false
                        environment_blocked_reason: null
                      - entity: inventory
                        label: Inventory
                        capability_label: Push Inventory
                        is_bidirectional: true
                        environment_blocked: false
                        environment_blocked_reason: null
                      - entity: pricing
                        label: Pricing
                        capability_label: Push Pricing
                        is_bidirectional: true
                        environment_blocked: false
                        environment_blocked_reason: null
                    is_sync_schedule_paused: true
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: integrations:write
      operationId: post-api-integration-instances-integration-instance-sync-controls-pause
  /api/integration-instances/{integration_instance}/sync-controls/resume:
    post:
      tags:
      - Integration Instances
      summary: Resume Sync Schedule
      description: 'Resume the integration instance''s automatic sync schedule. Sets
        `schedule_state` to `active`, re-enabling scheduled sync and flipping the
        derived `is_automatic_sync_enabled` flag back to true. Per-capability toggles
        set before pausing are restored unchanged.


        :::info[Required scope: `integrations:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token + `integrations.update` permission.


        No request body. Returns the updated integration instance object.


        **Deprecation note:** `is_automatic_sync_enabled` is a legacy coarse flag
        kept as a derived mirror of the sync-controls schedule state (`sync_controls.scheduleState`).
        New consumers should read `is_sync_schedule_paused` for the schedule and `sync_controls`
        for per-capability state; the legacy field is slated for rename to `sync_schedule_active`.'
      requestBody:
        content: {}
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '12'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_id:
                        type: integer
                      name:
                        type: string
                      connection_status:
                        type: string
                      is_automatic_sync_enabled:
                        type: boolean
                      sync_status:
                        type: string
                      sync_controls:
                        type: object
                        properties:
                          schedule_state:
                            type: string
                          capabilities:
                            type: object
                            properties:
                              inbound:
                                type: object
                                properties:
                                  orders:
                                    type: boolean
                                  products:
                                    type: boolean
                              outbound:
                                type: object
                                properties:
                                  tracking:
                                    type: boolean
                                  inventory:
                                    type: boolean
                                  pricing:
                                    type: boolean
                          source_of_truth:
                            type: object
                            properties:
                              inventory:
                                type: string
                              pricing:
                                type: string
                      applicable_sync_capabilities:
                        type: object
                        properties:
                          inbound:
                            type: array
                            items:
                              type: object
                              properties:
                                entity:
                                  type: string
                                label:
                                  type: string
                                capability_label:
                                  type: string
                                is_bidirectional:
                                  type: boolean
                                environment_blocked:
                                  type: boolean
                                environment_blocked_reason:
                                  type: string
                                  nullable: true
                          outbound:
                            type: array
                            items:
                              type: object
                              properties:
                                entity:
                                  type: string
                                label:
                                  type: string
                                capability_label:
                                  type: string
                                is_bidirectional:
                                  type: boolean
                                environment_blocked:
                                  type: boolean
                                environment_blocked_reason:
                                  type: string
                                  nullable: true
                      is_sync_schedule_paused:
                        type: boolean
                example:
                  data:
                    id: 12
                    integration_id: 3
                    name: My Shopify Store
                    connection_status: connected
                    is_automatic_sync_enabled: true
                    sync_status: active
                    sync_controls:
                      schedule_state: active
                      capabilities:
                        inbound:
                          orders: true
                          products: true
                        outbound:
                          tracking: true
                          inventory: true
                          pricing: false
                      source_of_truth:
                        inventory: sku
                        pricing: channel
                    applicable_sync_capabilities:
                      inbound:
                      - entity: orders
                        label: Orders
                        capability_label: Import Orders
                        is_bidirectional: false
                        environment_blocked: false
                        environment_blocked_reason: null
                      - entity: products
                        label: Products
                        capability_label: Import Products
                        is_bidirectional: false
                        environment_blocked: false
                        environment_blocked_reason: null
                      outbound:
                      - entity: tracking
                        label: Tracking
                        capability_label: Submit Tracking
                        is_bidirectional: false
                        environment_blocked: false
                        environment_blocked_reason: null
                      - entity: inventory
                        label: Inventory
                        capability_label: Push Inventory
                        is_bidirectional: true
                        environment_blocked: false
                        environment_blocked_reason: null
                      - entity: pricing
                        label: Pricing
                        capability_label: Push Pricing
                        is_bidirectional: true
                        environment_blocked: false
                        environment_blocked_reason: null
                    is_sync_schedule_paused: false
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: integrations:write
      operationId: post-api-integration-instances-integration-instance-sync-controls-resume
  /api/auth/user:
    get:
      tags:
      - Misc
      summary: Get Authenticated User
      description: 'Returns the currently authenticated user''s profile. The `features`
        object reports per-tenant feature flags (e.g. `features.granular_permissions`
        — whether granular role/permission enforcement is enabled for the tenant;
        `false` when the flag is off or unset).


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: integer
                  name:
                    type: string
                  email:
                    type: string
                  role:
                    type: string
                  features:
                    type: object
                    properties:
                      granular_permissions:
                        type: boolean
                  created_at:
                    type: string
                example:
                  id: 1
                  name: Dev User
                  email: dev@sku.io
                  role: admin
                  features:
                    granular_permissions: false
                  created_at: '2023-01-01T00:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-auth-user
  /api/account-setup:
    post:
      tags:
      - Misc
      summary: Account Setup
      description: 'Completes initial account setup after registration.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                company_name:
                  type: string
                timezone:
                  type: string
                currency:
                  type: string
              example:
                company_name: My Company
                timezone: America/New_York
                currency: USD
      parameters: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Account setup completed successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-account-setup
  /api/company-profile:
    get:
      tags:
      - Misc
      summary: Get Company Profile
      description: 'Returns the company profile settings.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      company_name:
                        type: string
                      timezone:
                        type: string
                      currency:
                        type: string
                      logo_url:
                        type: string
                        nullable: true
                example:
                  data:
                    company_name: My Company
                    timezone: America/New_York
                    currency: USD
                    logo_url: null
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: get-api-company-profile
    put:
      tags:
      - Misc
      summary: Update Company Profile
      description: 'Updates the company profile.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                company_name:
                  type: string
                timezone:
                  type: string
              example:
                company_name: My Updated Company
                timezone: America/Los_Angeles
      parameters: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      company_name:
                        type: string
                      timezone:
                        type: string
                      currency:
                        type: string
                example:
                  data:
                    company_name: My Updated Company
                    timezone: America/Los_Angeles
                    currency: USD
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-session-only: true
      operationId: put-api-company-profile
  /api/app-settings:
    get:
      tags:
      - Misc
      summary: App Settings
      description: 'Returns global application settings (feature flags, configuration)
        for the frontend.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      features:
                        type: object
                        properties:
                          inventory_forecasting:
                            type: boolean
                          amazon_integration:
                            type: boolean
                      limits:
                        type: object
                        properties:
                          max_products:
                            type: integer
                example:
                  data:
                    features:
                      inventory_forecasting: true
                      amazon_integration: true
                    limits:
                      max_products: 10000
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: get-api-app-settings
  /api/activity:
    get:
      tags:
      - Misc
      summary: List Activity
      description: 'Returns a paginated activity/audit log across all entities.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: per_page
        in: query
        schema:
          type: integer
        example: '20'
        description: Results per page (default 10).
      - name: page
        in: query
        schema:
          type: integer
        example: '1'
        description: Page number (default 1).
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        log_name:
                          type: string
                        description:
                          type: string
                        subject_type:
                          type: string
                        subject_id:
                          type: integer
                        causer_type:
                          type: string
                        causer_id:
                          type: integer
                        properties:
                          type: object
                          properties:
                            attributes:
                              type: object
                              properties:
                                status:
                                  type: string
                        created_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 1001
                    log_name: default
                    description: created
                    subject_type: App\Models\SalesOrder
                    subject_id: 30
                    causer_type: App\Models\User
                    causer_id: 1
                    properties:
                      attributes:
                        status: open
                    created_at: '2024-03-10T09:00:00.000000Z'
                  current_page: 1
                  last_page: 50
                  per_page: 20
                  total: 982
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: get-api-activity
  /api/addresses/{address}:
    put:
      tags:
      - Misc
      summary: Update Address
      description: 'Updates an address record.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                line1:
                  type: string
                city:
                  type: string
                state:
                  type: string
                postcode:
                  type: string
                country:
                  type: string
              example:
                line1: 123 Main St
                city: New York
                state: NY
                postcode: '10001'
                country: US
      parameters:
      - name: address
        in: path
        schema:
          type: integer
        required: true
        description: Address ID
        example: '1'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      line1:
                        type: string
                      line2:
                        type: string
                        nullable: true
                      city:
                        type: string
                      state:
                        type: string
                      postcode:
                        type: string
                      country:
                        type: string
                example:
                  data:
                    id: 1
                    line1: 123 Main St
                    line2: null
                    city: New York
                    state: NY
                    postcode: '10001'
                    country: US
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-session-only: true
      operationId: put-api-addresses-address
    delete:
      tags:
      - Misc
      summary: Delete Address
      description: 'Deletes an address record.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: address
        in: path
        schema:
          type: integer
        required: true
        description: Address ID
        example: '1'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: string
                    nullable: true
                example:
                  data: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-session-only: true
      operationId: delete-api-addresses-address
  /api/addresses/deletable:
    post:
      tags:
      - Misc
      summary: Check If Address Is Deletable
      description: 'Checks whether an address can be safely deleted (not referenced
        by active records).


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                address_id:
                  type: integer
              example:
                address_id: 1
      parameters: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  deletable:
                    type: boolean
                example:
                  deletable: true
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-session-only: true
      operationId: post-api-addresses-deletable
  /api/addresses/locked:
    post:
      tags:
      - Misc
      summary: Check If Address Is Locked
      description: 'Checks whether an address is locked (read-only due to being used
        in finalized orders).


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                address_id:
                  type: integer
              example:
                address_id: 1
      parameters: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  locked:
                    type: boolean
                example:
                  locked: false
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-session-only: true
      operationId: post-api-addresses-locked
  /api/alert-preferences:
    get:
      tags:
      - Misc
      summary: List Alert Preferences
      description: 'Returns the current user''s alert notification preferences.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.


        Requires a token with permission to view alert preferences.'
      parameters: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        alert_type:
                          type: string
                        email:
                          type: boolean
                        in_app:
                          type: boolean
                example:
                  data:
                  - alert_type: low_stock
                    email: true
                    in_app: true
                  - alert_type: order_pending
                    email: false
                    in_app: true
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: get-api-alert-preferences
    put:
      tags:
      - Misc
      summary: Bulk Update Alert Preferences
      description: 'Updates multiple alert preferences at once.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.


        Requires a token with permission to update alert preferences.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                preferences:
                  type: array
                  items:
                    type: object
                    properties:
                      alert_type:
                        type: string
                      email:
                        type: boolean
                      in_app:
                        type: boolean
              example:
                preferences:
                - alert_type: low_stock
                  email: true
                  in_app: true
                - alert_type: order_pending
                  email: true
                  in_app: true
      parameters: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Alert preferences updated.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-session-only: true
      operationId: put-api-alert-preferences
  /api/notes:
    post:
      tags:
      - Misc
      summary: Create Note
      description: 'Creates a note on a noteable entity (SalesOrder, PurchaseOrder,
        etc.).


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                notable_type:
                  type: string
                notable_id:
                  type: integer
                content:
                  type: string
              example:
                notable_type: SalesOrder
                notable_id: 30
                content: Customer requested gift wrapping.
      parameters: []
      responses:
        '201':
          description: Created
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      notable_type:
                        type: string
                      notable_id:
                        type: integer
                      content:
                        type: string
                      user:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      created_at:
                        type: string
                example:
                  data:
                    id: 55
                    notable_type: App\Models\SalesOrder
                    notable_id: 30
                    content: Customer requested gift wrapping.
                    user:
                      id: 1
                      name: Dev User
                    created_at: '2024-03-20T10:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-session-only: true
      operationId: post-api-notes
  /api/notes/{note}:
    delete:
      tags:
      - Misc
      summary: Delete Note
      description: 'Deletes a note.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: note
        in: path
        schema:
          type: integer
        required: true
        description: Note ID
        example: '55'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: string
                    nullable: true
                example:
                  data: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-session-only: true
      operationId: delete-api-notes-note
    put:
      tags:
      - Misc
      summary: Update Note
      description: 'Updates a note.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                content:
                  type: string
              example:
                content: Updated note content.
      parameters:
      - name: note
        in: path
        schema:
          type: integer
        required: true
        description: Note ID
        example: '55'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      content:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 55
                    content: Updated note content.
                    updated_at: '2024-03-20T11:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-notes-note
  /api/search:
    get:
      tags:
      - Misc
      summary: Global Search
      description: 'Performs a global search across multiple entity types.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.


        Query Parameters:

        - q (required): Search term

        - types[] (optional): Limit search to specific entity types'
      parameters:
      - name: q
        in: query
        schema:
          type: string
        description: Search query string
        example: widget
      - name: types[]
        in: query
        schema:
          type: string
        description: Entity types to search (products, sales_orders, customers, suppliers,
          purchase_orders)
        example: products
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      products:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            sku:
                              type: string
                            name:
                              type: string
                            type:
                              type: string
                      sales_orders:
                        type: array
                example:
                  data:
                    products:
                    - id: 15
                      sku: WIDGET-001
                      name: Blue Widget
                      type: product
                    sales_orders: []
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: get-api-search
  /api/enums:
    get:
      tags:
      - Misc
      summary: List Enums
      description: 'Returns all application enum values used by the frontend for dropdowns
        and validation.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      order_statuses:
                        type: array
                        items:
                          type: string
                      fulfillment_types:
                        type: array
                        items:
                          type: string
                      inventory_statuses:
                        type: array
                        items:
                          type: string
                example:
                  data:
                    order_statuses:
                    - open
                    - processing
                    - shipped
                    - completed
                    - cancelled
                    fulfillment_types:
                    - standard
                    - dropship
                    - fba
                    inventory_statuses:
                    - on_hand
                    - committed
                    - available
                    - incoming
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: get-api-enums
  /api/user-api:
    get:
      tags:
      - Misc
      summary: List User API Keys
      description: 'Returns all API keys for the current user.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        last_used_at:
                          type: string
                        created_at:
                          type: string
                example:
                  data:
                  - id: 1
                    name: My API Key
                    last_used_at: '2024-03-19T15:30:00.000000Z'
                    created_at: '2024-01-01T00:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: get-api-user-api
    post:
      tags:
      - Misc
      summary: Create API Key
      description: 'Creates a new API key for the current user. The token is only
        shown once in the response.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
              example:
                name: My New API Key
      parameters: []
      responses:
        '201':
          description: Created
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      token:
                        type: string
                      created_at:
                        type: string
                example:
                  data:
                    id: 2
                    name: My New API Key
                    token: 2|secretTokenValueOnlyShownOnce1234567890
                    created_at: '2024-03-20T10:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-session-only: true
      operationId: post-api-user-api
  /api/user-api/{token}:
    delete:
      tags:
      - Misc
      summary: Delete API Key
      description: 'Revokes an API key.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: token
        in: path
        schema:
          type: integer
        required: true
        description: API Token ID
        example: '1'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: API key revoked.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-session-only: true
      operationId: delete-api-user-api-token
  /api/low-stock-items:
    get:
      tags:
      - Misc
      summary: Get Low Stock Items
      description: 'Returns products that are at or below their reorder point.


        :::info[Required scope: `inventory:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: per_page
        in: query
        schema:
          type: integer
        example: '20'
        description: Results per page (default 10).
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        product_id:
                          type: integer
                        sku:
                          type: string
                        name:
                          type: string
                        available_quantity:
                          type: integer
                        reorder_point:
                          type: integer
                        warehouse_id:
                          type: integer
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - product_id: 15
                    sku: WIDGET-001
                    name: Blue Widget
                    available_quantity: 3
                    reorder_point: 10
                    warehouse_id: 2
                  current_page: 1
                  last_page: 2
                  per_page: 20
                  total: 8
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: inventory:read
      operationId: get-api-low-stock-items
  /api/low-stock-items/export:
    get:
      tags:
      - Misc
      summary: Export Low Stock Items
      description: 'Exports low-stock items as a downloadable CSV or XLSX file.


        :::info[Required scope: `inventory:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Filename pattern: `low-stock-items-{Y-m-d_His}.{ext}`


        Supports the same filters as `GET /api/low-stock-items` (search, severity,
        brand_id, warehouse_id, archived_status). The `columns` query parameter accepts
        a comma-separated list of columns to include in the export — defaults to all
        available columns.


        Response Content-Type:

        - CSV → `text/csv`

        - XLSX → `application/vnd.openxmlformats-officedocument.spreadsheetml.sheet`


        Authentication: Requires Bearer token.'
      parameters:
      - name: format
        in: query
        schema:
          type: string
        description: 'Export format: csv (default) or xlsx'
        example: csv
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: text/csv; charset=UTF-8
            Content-Disposition:
              schema:
                type: string
                example: attachment; filename="low-stock-items-2026-05-27_143052.csv"
          content:
            text/plain:
              schema:
                type: string
                example: 'sku,name,brand,supplier,inventory_available,min_stock_level,daily_average_consumption,days_of_supply,deficit

                  WIDGET-001,Blue Widget,Acme,Acme Supply,3,10,1.5,2,7

                  '
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: inventory:read
      operationId: get-api-low-stock-items-export
  /api/inventory-management:
    get:
      tags:
      - Misc
      summary: Inventory Management Settings
      description: 'Returns inventory management configuration settings.


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      costing_method:
                        type: string
                      negative_stock_allowed:
                        type: boolean
                      auto_allocate:
                        type: boolean
                example:
                  data:
                    costing_method: fifo
                    negative_stock_allowed: false
                    auto_allocate: true
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-inventory-management
  /api/inventory-management/valuation:
    get:
      tags:
      - Misc
      summary: Get Inventory Valuation
      description: 'Returns the total value of on-hand and in-transit inventory across
        all warehouses, broken down by inventory status. Each status carries both
        a quantity and a valuation, plus an overall average unit cost. Use it to power
        an inventory valuation summary. Optionally scope the figures to a single warehouse
        or to an as-of cut-off date.


        :::info[Required scope: `inventory:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      total_quantity:
                        type: integer
                      total_valuation:
                        type: number
                      average_cost:
                        type: number
                      active_quantity:
                        type: integer
                      active_valuation:
                        type: number
                      in_transit_quantity:
                        type: integer
                      in_transit_valuation:
                        type: number
                  status:
                    type: string
                example:
                  data:
                    total_quantity: 18450
                    total_valuation: 254310.75
                    average_cost: 13.78
                    active_quantity: 17200
                    active_valuation: 236100.5
                    in_transit_quantity: 1250
                    in_transit_valuation: 18210.25
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: inventory:read
      operationId: get-api-inventory-management-valuation
  /api/inventory-management/valuation-by-product:
    get:
      tags:
      - Misc
      summary: Get Inventory Valuation by Product
      description: 'Returns a flat, per-product breakdown of inventory value. Every
        product row includes quantities and valuations split by status (active, reserved,
        in-transit, inbound, on-hand) together with average unit costs, and the response
        ends with a totals block summing all products. Use it to build a detailed
        inventory valuation report.


        :::info[Required scope: `inventory:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      products:
                        type: array
                        items:
                          type: object
                          properties:
                            sku:
                              type: string
                            name:
                              type: string
                            active_quantity:
                              type: integer
                            reserved_quantity:
                              type: integer
                            in_transit_quantity:
                              type: integer
                            inbound_quantity:
                              type: integer
                            total_quantity:
                              type: integer
                            average_cost:
                              type: number
                            on_hand_average_cost:
                              type: number
                            in_transit_average_cost:
                              type: number
                            inbound_average_cost:
                              type: number
                            active_valuation:
                              type: integer
                            reserved_valuation:
                              type: integer
                            in_transit_valuation:
                              type: integer
                            inbound_valuation:
                              type: integer
                            on_hand_valuation:
                              type: integer
                            total_valuation:
                              type: integer
                      totals:
                        type: object
                        properties:
                          active_quantity:
                            type: integer
                          reserved_quantity:
                            type: integer
                          in_transit_quantity:
                            type: integer
                          inbound_quantity:
                            type: integer
                          total_quantity:
                            type: integer
                          active_valuation:
                            type: integer
                          reserved_valuation:
                            type: integer
                          in_transit_valuation:
                            type: integer
                          inbound_valuation:
                            type: integer
                          on_hand_valuation:
                            type: integer
                          total_valuation:
                            type: integer
                  status:
                    type: string
                example:
                  data:
                    products:
                    - sku: WIDGET-BLK-01
                      name: Black Widget
                      active_quantity: 320
                      reserved_quantity: 40
                      in_transit_quantity: 60
                      inbound_quantity: 100
                      total_quantity: 380
                      average_cost: 12.5
                      on_hand_average_cost: 12.5
                      in_transit_average_cost: 12.75
                      inbound_average_cost: 12.9
                      active_valuation: 4000
                      reserved_valuation: 500
                      in_transit_valuation: 765
                      inbound_valuation: 1290
                      on_hand_valuation: 4500
                      total_valuation: 4750
                    totals:
                      active_quantity: 320
                      reserved_quantity: 40
                      in_transit_quantity: 60
                      inbound_quantity: 100
                      total_quantity: 380
                      active_valuation: 4000
                      reserved_valuation: 500
                      in_transit_valuation: 765
                      inbound_valuation: 1290
                      on_hand_valuation: 4500
                      total_valuation: 4750
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: inventory:read
      operationId: get-api-inventory-management-valuation-by-product
  /api/inventory-movements/tallies:
    get:
      tags:
      - Inventory
      summary: Get Inventory Movement Tallies
      description: 'Get running inventory tallies for a single product in a single
        warehouse. Returns a map keyed by inventory movement ID where each value is
        the cumulative on-hand quantity (running balance) after that movement was
        applied, computed in movement-date order (oldest first).


        :::info[Required scope: `inventory:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        All three query parameters are required:

        - `product_id` — the product to tally. Returns 404 if the product does not
        exist.

        - `warehouse_id` — the warehouse to tally within.

        - `inventory_status` — which stock ledger to tally: `active` (on-hand stock)
        or `in_transit` (stock moving between warehouses).


        Use this to reconstruct the balance history of a product at a warehouse, movement
        by movement.


        Authentication: Requires Bearer token.'
      parameters:
      - name: product_id
        in: query
        schema:
          type: integer
        description: (Required) Product ID to tally. 404 if not found.
        example: '42'
      - name: warehouse_id
        in: query
        schema:
          type: integer
        description: (Required) Warehouse ID to tally within.
        example: '1'
      - name: inventory_status
        in: query
        schema:
          type: string
        description: '(Required) Stock ledger to tally: active or in_transit.'
        example: active
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      '18234':
                        type: integer
                      '18240':
                        type: integer
                      '18255':
                        type: integer
                      '18291':
                        type: integer
                example:
                  data:
                    '18234': 100
                    '18240': 88
                    '18255': 63
                    '18291': 113
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No query results for model.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: inventory:read
      operationId: get-api-inventory-movements-tallies
  /api/inventory-movements/{inventoryMovement}:
    get:
      tags:
      - Inventory
      summary: Get Inventory Movement
      description: 'Get a single inventory movement with its product and warehouse
        details.


        :::info[Required scope: `inventory:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        An inventory movement is one immutable ledger entry: a positive quantity adds
        stock (purchase receipt, return, adjustment up, assembly output) and a negative
        quantity removes stock (sale, transfer out, adjustment down). Movement `type`
        values include: purchase_receipt, transfer, sale, adjustment, stock_take,
        assembly, return, purchase_return, reclassification, manufacturing_consumption,
        manufacturing_scrap, manufacturing_output. `inventory_status` is `active`
        (on-hand) or `in_transit` (between warehouses).


        The `type` object also carries the polymorphic source document link (`link_type`
        + `link_id`) that created the movement, and `layer` identifies the FIFO cost
        layer the movement consumed or created.


        Authentication: Requires Bearer token.'
      parameters:
      - name: inventoryMovement
        in: path
        schema:
          type: integer
        required: true
        description: Inventory movement ID
        example: '18234'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      inventory_movement_date:
                        type: string
                      product_id:
                        type: integer
                      sku:
                        type: string
                      barcode:
                        type: string
                      product_name:
                        type: string
                      stock_uom_code:
                        type: string
                      type:
                        type: object
                        properties:
                          name:
                            type: string
                          link_type:
                            type: string
                          link_id:
                            type: integer
                          parent_link_id:
                            type: string
                            nullable: true
                          detail_link_id:
                            type: string
                            nullable: true
                          manufacturing_order:
                            type: string
                            nullable: true
                      inventory_status:
                        type: string
                      quantity:
                        type: integer
                      warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      layer:
                        type: object
                        properties:
                          fifo_layer_id:
                            type: integer
                          name:
                            type: string
                      fifo_layer_id:
                        type: integer
                      reference:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                  status:
                    type: string
                example:
                  data:
                    id: 18234
                    inventory_movement_date: '2026-05-12T14:30:00.000000Z'
                    product_id: 42
                    sku: WIDGET-001
                    barcode: 0123456789012
                    product_name: Blue Widget
                    stock_uom_code: EA
                    type:
                      name: purchase_receipt
                      link_type: App\Models\PurchaseOrderShipmentReceiptLine
                      link_id: 5121
                      parent_link_id: null
                      detail_link_id: null
                      manufacturing_order: null
                    inventory_status: active
                    quantity: 100
                    warehouse:
                      id: 1
                      name: Main Warehouse
                    layer:
                      fifo_layer_id: 3311
                      name: PO-1042
                    fifo_layer_id: 3311
                    reference: PO-1042
                    created_at: '2026-05-12T14:30:05.000000Z'
                    updated_at: '2026-05-12T14:30:05.000000Z'
                  status: success
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No query results for model.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: inventory:read
      operationId: get-api-inventory-movements-inventorymovement
  /api/inventory-movements/{inventoryMovement}/activity-log:
    get:
      tags:
      - Inventory
      summary: Get Inventory Movement Activity Log
      description: 'Get the paginated change history (activity log) for an inventory
        movement, newest first. Each entry records what changed (`properties` holds
        the new and old attribute values plus the change source), the event type,
        and who made the change (`causer_name`).


        :::info[Required scope: `inventory:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Filters:

        - `filter[search]` — matches against the causing user''s name, the event,
        the changed properties, and the subject type.

        - `filter[event]` — exact event match: created, updated, deleted, bulk_upsert.

        - `filter[source]` — matches the change source recorded in properties (e.g.
        manual, amazon_sync, inventory_allocation).

        - `filter[batch_uuid]` — all entries written by one bulk operation.


        Pagination: `page` and `per_page` (default 15).


        Authentication: Requires Bearer token.'
      parameters:
      - name: inventoryMovement
        in: path
        schema:
          type: integer
        required: true
        description: Inventory movement ID
        example: '18234'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        description:
                          type: string
                        event:
                          type: string
                        subject_type:
                          type: string
                        subject_id:
                          type: integer
                        properties:
                          type: object
                          properties:
                            attributes:
                              type: object
                              properties:
                                quantity:
                                  type: integer
                            old:
                              type: object
                              properties:
                                quantity:
                                  type: integer
                            source:
                              type: string
                        causer_name:
                          type: string
                        created_at:
                          type: string
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                    items:
                      type: object
                      properties:
                        url:
                          type: string
                          nullable: true
                        label:
                          type: string
                        active:
                          type: boolean
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 90211
                    description: updated
                    event: updated
                    subject_type: InventoryMovement
                    subject_id: 18234
                    properties:
                      attributes:
                        quantity: 100
                      old:
                        quantity: 90
                      source: manual
                    causer_name: Jane Smith
                    created_at: '2026-05-12T15:02:11.000000Z'
                  - id: 90180
                    description: created
                    event: created
                    subject_type: InventoryMovement
                    subject_id: 18234
                    properties:
                      attributes:
                        quantity: 90
                        inventory_status: active
                        warehouse_id: 1
                      source: manual
                    causer_name: Jane Smith
                    created_at: '2026-05-12T14:30:05.000000Z'
                  first_page_url: https://sku3.test/api/inventory-movements/18234/activity-log?page=1
                  from: 1
                  last_page: 1
                  last_page_url: https://sku3.test/api/inventory-movements/18234/activity-log?page=1
                  links:
                  - url: null
                    label: '&laquo; Previous'
                    active: false
                  - url: https://sku3.test/api/inventory-movements/18234/activity-log?page=1
                    label: '1'
                    active: true
                  - url: null
                    label: Next &raquo;
                    active: false
                  next_page_url: null
                  path: https://sku3.test/api/inventory-movements/18234/activity-log
                  per_page: 15
                  prev_page_url: null
                  to: 2
                  total: 2
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: inventory:read
      operationId: get-api-inventory-movements-inventorymovement-activity-log
  /api/low-stock-items/metrics:
    get:
      tags:
      - Misc
      summary: Get Low Stock Metrics
      description: 'Returns summary counts for the low-stock report: how many products
        are low on stock, how many are critically low (below the configured days-of-supply
        threshold), how many are out of stock, and how many have no minimum stock
        level configured, along with the threshold in days. Accepts the same filters
        as the low-stock list so the metrics match the filtered view.


        :::info[Required scope: `inventory:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  total_low_stock:
                    type: integer
                  critically_low:
                    type: integer
                  out_of_stock:
                    type: integer
                  without_min_stock_level:
                    type: integer
                  threshold_days:
                    type: integer
                example:
                  total_low_stock: 42
                  critically_low: 9
                  out_of_stock: 5
                  without_min_stock_level: 130
                  threshold_days: 14
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: inventory:read
      operationId: get-api-low-stock-items-metrics
  /api/discount-codes:
    get:
      tags:
      - Discount Codes
      summary: List Discount Codes
      description: 'List all discount codes. Uses standard list query parameters supporting
        search, sort, and pagination.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.


        Allowed sorts: code, type, scope, is_active, created_at, updated_at'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        code:
                          type: string
                        description:
                          type: string
                        type:
                          type: string
                        rate:
                          type: number
                        amount:
                          type: string
                          nullable: true
                        scope:
                          type: string
                        apply_before_tax:
                          type: boolean
                        is_active:
                          type: boolean
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  total:
                    type: integer
                  per_page:
                    type: integer
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                example:
                  data:
                  - id: 1
                    code: SUMMER10
                    description: 10% off for summer sale
                    type: percentage
                    rate: 10.0
                    amount: null
                    scope: order
                    apply_before_tax: false
                    is_active: true
                    created_at: '2024-06-01T00:00:00.000000Z'
                    updated_at: '2024-06-01T00:00:00.000000Z'
                  - id: 2
                    code: FLAT5
                    description: $5 off any order
                    type: fixed_amount
                    rate: null
                    amount: 5.0
                    scope: order
                    apply_before_tax: true
                    is_active: true
                    created_at: '2024-01-01T00:00:00.000000Z'
                    updated_at: '2024-01-01T00:00:00.000000Z'
                  total: 2
                  per_page: 10
                  current_page: 1
                  last_page: 1
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: get-api-discount-codes
    post:
      tags:
      - Discount Codes
      summary: Create Discount Code
      description: 'Create a new discount code.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.


        Fields:

        - code (required): Unique discount code string (max 255 chars)

        - description (optional): Description of the discount (max 500 chars)

        - type (required): Discount value type. One of: percentage, fixed_amount

        - rate (optional): Percentage rate (0–100). Used when type is ''percentage''

        - amount (optional): Fixed amount. Used when type is ''fixed_amount''

        - scope (required): What the discount applies to. One of: line, order, both

        - apply_before_tax (optional): Whether discount is applied before tax calculation

        - is_active (optional): Whether the code is active


        **Requires permission:** `discount_codes.create`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                code:
                  type: string
                description:
                  type: string
                type:
                  type: string
                rate:
                  type: integer
                amount:
                  type: string
                  nullable: true
                scope:
                  type: string
                apply_before_tax:
                  type: boolean
                is_active:
                  type: boolean
              example:
                code: SUMMER10
                description: 10% off for summer sale
                type: percentage
                rate: 10
                amount: null
                scope: order
                apply_before_tax: false
                is_active: true
      parameters: []
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      code:
                        type: string
                      description:
                        type: string
                      type:
                        type: string
                      rate:
                        type: number
                      amount:
                        type: string
                        nullable: true
                      scope:
                        type: string
                      apply_before_tax:
                        type: boolean
                      is_active:
                        type: boolean
                      created_at:
                        type: string
                      updated_at:
                        type: string
                  message:
                    type: string
                  status:
                    type: string
                example:
                  data:
                    id: 5
                    code: SUMMER10
                    description: 10% off for summer sale
                    type: percentage
                    rate: 10.0
                    amount: null
                    scope: order
                    apply_before_tax: false
                    is_active: true
                    created_at: '2024-06-01T00:00:00.000000Z'
                    updated_at: '2024-06-01T00:00:00.000000Z'
                  message: discount code created successfully.
                  status: success
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      code:
                        type: array
                        items:
                          type: string
                      type:
                        type: array
                        items:
                          type: string
                      scope:
                        type: array
                        items:
                          type: string
                example:
                  message: The given data was invalid.
                  errors:
                    code:
                    - The code has already been taken.
                    type:
                    - The selected type is invalid.
                    scope:
                    - The selected scope is invalid.
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: post-api-discount-codes
  /api/discount-codes/{discountCode}:
    get:
      tags:
      - Discount Codes
      summary: Get Discount Code
      description: 'Retrieve a single discount code by ID.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: discountCode
        in: path
        required: true
        schema:
          type: string
        description: The discountCode identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      code:
                        type: string
                      description:
                        type: string
                      type:
                        type: string
                      rate:
                        type: number
                      amount:
                        type: string
                        nullable: true
                      scope:
                        type: string
                      apply_before_tax:
                        type: boolean
                      is_active:
                        type: boolean
                      created_at:
                        type: string
                      updated_at:
                        type: string
                  status:
                    type: string
                example:
                  data:
                    id: 1
                    code: SUMMER10
                    description: 10% off for summer sale
                    type: percentage
                    rate: 10.0
                    amount: null
                    scope: order
                    apply_before_tax: false
                    is_active: true
                    created_at: '2024-06-01T00:00:00.000000Z'
                    updated_at: '2024-06-01T00:00:00.000000Z'
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-session-only: true
      operationId: get-api-discount-codes-discountcode
    put:
      tags:
      - Discount Codes
      summary: Update Discount Code
      description: 'Update an existing discount code.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.


        Same fields as create. Unique code validation ignores the current record.


        **Requires permission:** `discount_codes.update`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                code:
                  type: string
                description:
                  type: string
                type:
                  type: string
                rate:
                  type: integer
                scope:
                  type: string
                is_active:
                  type: boolean
              example:
                code: SUMMER15
                description: 15% off for summer sale
                type: percentage
                rate: 15
                scope: order
                is_active: true
      parameters:
      - name: discountCode
        in: path
        required: true
        schema:
          type: string
        description: The discountCode identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      code:
                        type: string
                      description:
                        type: string
                      type:
                        type: string
                      rate:
                        type: number
                      amount:
                        type: string
                        nullable: true
                      scope:
                        type: string
                      apply_before_tax:
                        type: boolean
                      is_active:
                        type: boolean
                      created_at:
                        type: string
                      updated_at:
                        type: string
                  message:
                    type: string
                  status:
                    type: string
                example:
                  data:
                    id: 1
                    code: SUMMER15
                    description: 15% off for summer sale
                    type: percentage
                    rate: 15.0
                    amount: null
                    scope: order
                    apply_before_tax: false
                    is_active: true
                    created_at: '2024-06-01T00:00:00.000000Z'
                    updated_at: '2024-06-15T00:00:00.000000Z'
                  message: discount code SUMMER15 updated successfully.
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-session-only: true
      operationId: put-api-discount-codes-discountcode
    delete:
      tags:
      - Discount Codes
      summary: Delete Discount Code
      description: 'Soft-delete a discount code. Soft-deleted codes are excluded from
        the unique code constraint for future codes with the same name.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `discount_codes.delete`'
      parameters:
      - name: discountCode
        in: path
        required: true
        schema:
          type: string
        description: The discountCode identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  status:
                    type: string
                example:
                  message: discount code SUMMER10 deleted successfully.
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-session-only: true
      operationId: delete-api-discount-codes-discountcode
  /api/custom-fields:
    post:
      tags:
      - Custom Fields
      summary: Create Custom Field
      description: 'Creates a new custom field definition. Custom fields are then
        attached to records via the custom-field-values API.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.


        Fields:

        - name (required) — Display name of the custom field. Must be unique within
        the same link_type.

        - link_type (required) — Fully qualified model class name the field applies
        to (e.g., App\Models\PurchaseOrder)


        Uniqueness: The (name, link_type) combination must be unique. Attempting to
        create a duplicate returns 422 with a friendly error message instead of a
        500.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                link_type:
                  type: string
              example:
                name: Internal Reference
                link_type: App\Models\PurchaseOrder
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: integer
                  name:
                    type: string
                  link_type:
                    type: string
                  archived_at:
                    type: string
                    nullable: true
                  created_at:
                    type: string
                  updated_at:
                    type: string
                example:
                  id: 3
                  name: Internal Reference
                  link_type: App\Models\PurchaseOrder
                  archived_at: null
                  created_at: '2024-06-01T09:00:00.000000Z'
                  updated_at: '2024-06-01T09:00:00.000000Z'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      name:
                        type: array
                        items:
                          type: string
                      link_type:
                        type: array
                        items:
                          type: string
                example:
                  message: The name field is required.
                  errors:
                    name:
                    - The name field is required.
                    link_type:
                    - The link type field is required.
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: post-api-custom-fields
    get:
      tags:
      - Custom Fields
      summary: List Custom Fields
      description: 'Returns a paginated list of custom fields. Custom fields can be
        attached to different entity types (link_type).


        Authentication: Requires Bearer token.


        Query parameters:

        - page — Page number (default: 1)

        - limit — Results per page (default: 15)

        - search — Full-text search by name

        - sort — Sort field, prefix with - for descending

        - archived — 0 = active, 1 = archived (soft-deleted)'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        description: Page number for pagination
        example: '1'
      - name: limit
        in: query
        schema:
          type: integer
        description: Number of results per page
        example: '15'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        link_type:
                          type: string
                        archived_at:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  total:
                    type: integer
                  per_page:
                    type: integer
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                example:
                  data:
                  - id: 1
                    name: Purchase Order Notes
                    link_type: App\Models\PurchaseOrder
                    archived_at: null
                    created_at: '2024-01-15T10:00:00.000000Z'
                    updated_at: '2024-01-15T10:00:00.000000Z'
                  - id: 2
                    name: Supplier Rating
                    link_type: App\Models\Supplier
                    archived_at: null
                    created_at: '2024-02-01T09:00:00.000000Z'
                    updated_at: '2024-02-01T09:00:00.000000Z'
                  total: 12
                  per_page: 15
                  current_page: 1
                  last_page: 1
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-custom-fields
  /api/custom-fields/{customField}:
    put:
      tags:
      - Custom Fields
      summary: Update Custom Field
      description: 'Updates an existing custom field. All fields are optional.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.


        Fields (all optional):

        - name (optional) — Display name of the custom field. Must be unique within
        the same link_type (the record''s own existing name is allowed).

        - link_type (optional) — Fully qualified model class name

        - archived_at (optional, nullable, date) — Set to a date to archive, null
        to unarchive


        Uniqueness: The (name, link_type) combination must be unique. Renaming to
        a name that already exists for the same link_type returns 422 with a friendly
        error message instead of a 500.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                link_type:
                  type: string
                archived_at:
                  type: string
                  nullable: true
              example:
                name: Purchase Order Internal Notes
                link_type: App\Models\PurchaseOrder
                archived_at: null
      parameters:
      - name: customField
        in: path
        required: true
        schema:
          type: string
        description: The customField identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: integer
                  name:
                    type: string
                  link_type:
                    type: string
                  archived_at:
                    type: string
                    nullable: true
                  created_at:
                    type: string
                  updated_at:
                    type: string
                example:
                  id: 1
                  name: Purchase Order Internal Notes
                  link_type: App\Models\PurchaseOrder
                  archived_at: null
                  created_at: '2024-01-15T10:00:00.000000Z'
                  updated_at: '2024-06-01T11:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-session-only: true
      operationId: put-api-custom-fields-customfield
    delete:
      tags:
      - Custom Fields
      summary: Delete Custom Field
      description: 'Deletes a custom field definition by ID.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: customField
        in: path
        required: true
        schema:
          type: string
        description: The customField identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: customField Purchase Order Notes was successfully deleted
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-session-only: true
      operationId: delete-api-custom-fields-customfield
    get:
      tags:
      - Custom Fields
      summary: Get Custom Field
      description: 'Returns a single custom field by ID.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: customField
        in: path
        required: true
        schema:
          type: string
        description: The customField identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      link_type:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 1
                    name: Purchase Order Notes
                    link_type: App\Models\PurchaseOrder
                    archived_at: null
                    created_at: '2024-01-15T10:00:00.000000Z'
                    updated_at: '2024-01-15T10:00:00.000000Z'
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No query results for model [App\Models\CustomField] 999
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: get-api-custom-fields-customfield
  /api/custom-field-values/{entity}/{entityId}:
    put:
      tags:
      - Misc
      summary: Update Custom Field Values
      description: 'Sets custom field values for a specific entity instance.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                values:
                  type: object
                  properties:
                    '1':
                      type: boolean
                    '2':
                      type: string
              example:
                values:
                  '1': true
                  '2': some text value
      parameters:
      - name: entity
        in: path
        schema:
          type: string
        required: true
        description: Entity type
        example: product
      - name: entityId
        in: path
        schema:
          type: integer
        required: true
        description: Entity ID
        example: '15'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Custom field values updated.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-custom-field-values-entity-entityid
  /api/sales-reps:
    get:
      tags:
      - Sales Reps
      summary: List Sales Reps
      description: 'List all sales reps with pagination, filtering, and sorting via
        Spatie QueryBuilder.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.


        Allowed sorts: name, email, phone, active, created_at, updated_at (default:
        name)'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        email:
                          type: string
                        active:
                          type: boolean
                        sales_orders_count:
                          type: integer
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 1
                    name: Jane Smith
                    email: jane@example.com
                    active: true
                    sales_orders_count: 42
                  current_page: 1
                  last_page: 3
                  per_page: 10
                  total: 28
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: get-api-sales-reps
    post:
      tags:
      - Sales Reps
      summary: Create Sales Rep
      description: 'Create a new sales rep. Defaults active to true if not provided.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.


        Fields:

        - name (required): Sales rep display name (max 255 chars)

        - email (optional): Unique email address

        - phone (optional): Phone number

        - user_id (optional): Link to a user account

        - active (optional): Whether the sales rep is active (default: true)'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                email:
                  type: string
                phone:
                  type: string
                user_id:
                  type: integer
                active:
                  type: boolean
              example:
                name: Jane Smith
                email: jane@example.com
                phone: 555-123-4567
                user_id: 5
                active: true
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      active:
                        type: boolean
                  message:
                    type: string
                  status:
                    type: string
                example:
                  data:
                    id: 5
                    name: Jane Smith
                    active: true
                  message: Sales rep created successfully.
                  status: success
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      name:
                        type: array
                        items:
                          type: string
                example:
                  message: The given data was invalid.
                  errors:
                    name:
                    - The sales rep name is required.
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: post-api-sales-reps
  /api/sales-reps/{id}:
    delete:
      tags:
      - Misc
      summary: Delete Sales Rep
      description: 'Deletes a sales rep.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token


        Side effects (performed in a single transaction before the delete):

        - Unlinks the rep from all sales orders (sales_orders.sales_rep_id set to
        null)

        - Clears the rep as the default on any linked customers (customers.default_sales_rep_id
        set to null)


        Returns 404 if the sales rep does not exist.'
      parameters:
      - name: id
        in: path
        schema:
          type: integer
        required: true
        description: Sales rep ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                example:
                  status: Success
                  message: Sales rep 'Jane Doe' deleted successfully.
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No query results for model [App\Models\SalesRep] 999
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: delete-api-sales-reps-id
    get:
      tags:
      - Sales Reps
      summary: Get Sales Rep
      description: 'Get a single sales rep by ID, including their linked user account
        and sales order count.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      active:
                        type: boolean
                      sales_orders_count:
                        type: integer
                  status:
                    type: string
                example:
                  data:
                    id: 1
                    name: Jane Smith
                    active: true
                    sales_orders_count: 42
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-session-only: true
      operationId: get-api-sales-reps-id
    put:
      tags:
      - Sales Reps
      summary: Update Sales Rep
      description: 'Update an existing sales rep.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                email:
                  type: string
                phone:
                  type: string
                active:
                  type: boolean
              example:
                name: Jane Smith-Johnson
                email: jane.johnson@example.com
                phone: 555-999-0000
                active: true
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      active:
                        type: boolean
                  message:
                    type: string
                  status:
                    type: string
                example:
                  data:
                    id: 1
                    name: Jane Smith-Johnson
                    active: true
                  message: Sales rep updated successfully.
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-session-only: true
      operationId: put-api-sales-reps-id
  /api/lookup:
    get:
      tags:
      - Misc
      summary: Lookup
      description: 'Generic autocomplete lookup endpoint used by select/dropdown inputs
        throughout the UI. Returns a list of matching records for a given entity type.


        Authentication: Requires Bearer token.


        Common types: warehouses, products, customers, suppliers, sales_channels,
        tags, users'
      parameters:
      - name: type
        in: query
        schema:
          type: string
        description: Entity type for autocomplete lookup
        example: warehouses
      - name: search
        in: query
        schema:
          type: string
        description: Search term
        example: main
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        label:
                          type: string
                        value:
                          type: integer
                example:
                  data:
                  - id: 2
                    label: Main Warehouse
                    value: 2
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-lookup
  /api/constants:
    get:
      tags:
      - Misc
      summary: List Constants
      description: 'Returns application constants used for frontend configuration.


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      max_import_rows:
                        type: integer
                      supported_currencies:
                        type: array
                        items:
                          type: string
                example:
                  data:
                    max_import_rows: 5000
                    supported_currencies:
                    - USD
                    - EUR
                    - GBP
                    - AUD
                    - CAD
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-constants
  /api/sales-channels:
    get:
      tags:
      - Misc
      summary: List Sales Channels
      description: 'Returns all sales channels (Shopify stores, Amazon marketplaces,
        etc.).


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        type:
                          type: string
                        integration_instance_id:
                          type: integer
                        is_active:
                          type: boolean
                        created_at:
                          type: string
                example:
                  data:
                  - id: 5
                    name: My Shopify Store
                    type: shopify
                    integration_instance_id: 3
                    is_active: true
                    created_at: '2023-06-01T00:00:00.000000Z'
                  - id: 6
                    name: Amazon US
                    type: amazon
                    integration_instance_id: 5
                    is_active: true
                    created_at: '2023-07-01T00:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-sales-channels
  /api/password/change:
    post:
      tags:
      - Misc
      summary: Change Password
      description: 'Changes the current user''s password.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                current_password:
                  type: string
                password:
                  type: string
                password_confirmation:
                  type: string
              example:
                current_password: current-password
                password: new-secure-password
                password_confirmation: new-secure-password
      parameters: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Password changed successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-password-change
  /api/password/email:
    post:
      tags:
      - Misc
      summary: Request Password Reset Email
      description: Sends a password-reset link to the supplied email address if an
        account exists for it. This is a public, unauthenticated endpoint. Returns
        a confirmation message on success, or a validation error if the email is missing/invalid
        or no account matches.
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                email:
                  type: string
              example:
                email: user@example.com
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: We have emailed your password reset link.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  email:
                    type: string
                example:
                  email: We can't find a user with that email address.
        '429': *id001
      security: []
      operationId: post-api-password-email
  /api/password/reset:
    post:
      tags:
      - Misc
      summary: Reset Password
      description: Completes a password reset using the token from the reset email.
        Provide the token, the account email, and the new password with its confirmation.
        This is a public, unauthenticated endpoint. On success the password is updated
        (and an invited-but-unactivated account is activated); on failure a validation
        error is returned.
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                token:
                  type: string
                email:
                  type: string
                password:
                  type: string
                password_confirmation:
                  type: string
              example:
                token: 9f8c1b2a3d4e5f60718293a4b5c6d7e8f90a1b2c3d4e5f6071829304a5b6c7d8
                email: user@example.com
                password: new-secret-password
                password_confirmation: new-secret-password
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Your password has been reset.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  email:
                    type: string
                example:
                  email: This password reset token is invalid.
        '429': *id001
      security: []
      operationId: post-api-password-reset
  /api/webhooks:
    get:
      tags:
      - Misc
      summary: List Webhooks
      description: 'Returns all configured outbound webhooks.


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        url:
                          type: string
                        events:
                          type: array
                          items:
                            type: string
                        is_active:
                          type: boolean
                example:
                  data:
                  - id: 1
                    url: https://example.com/webhook
                    events:
                    - order.created
                    - order.shipped
                    is_active: true
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-webhooks
    post:
      tags:
      - Misc
      summary: Create Webhook
      description: 'Creates a new outbound webhook.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                url:
                  type: string
                events:
                  type: array
                  items:
                    type: string
                secret:
                  type: string
              example:
                url: https://example.com/webhook
                events:
                - order.created
                - order.shipped
                secret: my-webhook-secret
      parameters: []
      responses:
        '201':
          description: Created
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      url:
                        type: string
                      events:
                        type: array
                        items:
                          type: string
                      is_active:
                        type: boolean
                example:
                  data:
                    id: 2
                    url: https://example.com/webhook
                    events:
                    - order.created
                    - order.shipped
                    is_active: true
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-webhooks
  /api/webhooks/{webhook}:
    get:
      tags:
      - Misc
      summary: Show Webhook
      description: 'Returns a single webhook.


        Authentication: Requires Bearer token.'
      parameters:
      - name: webhook
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The webhook ID.
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      url:
                        type: string
                      events:
                        type: array
                        items:
                          type: string
                      is_active:
                        type: boolean
                example:
                  data:
                    id: 1
                    url: https://example.com/webhook
                    events:
                    - order.created
                    is_active: true
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-webhooks-webhook
    put:
      tags:
      - Misc
      summary: Update Webhook
      description: 'Updates a webhook.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                is_active:
                  type: boolean
              example:
                is_active: false
      parameters:
      - name: webhook
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The webhook ID.
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      url:
                        type: string
                      is_active:
                        type: boolean
                example:
                  data:
                    id: 1
                    url: https://example.com/webhook
                    is_active: false
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-webhooks-webhook
    delete:
      tags:
      - Misc
      summary: Delete Webhook
      description: 'Deletes a webhook.


        Authentication: Requires Bearer token.'
      parameters:
      - name: webhook
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The webhook ID.
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: string
                    nullable: true
                example:
                  data: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-webhooks-webhook
  /api/warehouse-locations/{warehouse}:
    get:
      tags:
      - Warehouses
      summary: List Warehouse Locations
      description: 'List all storage locations defined for a warehouse. The path parameter
        is the WAREHOUSE ID (not a location ID).


        :::info[Required scope: `warehouses:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        A location is a physical slot addressed by aisle / bay / shelf / bin. At most
        one location per warehouse is flagged `is_default` — new stock is placed there
        unless a location is specified.


        Authentication: Requires Bearer token.'
      parameters:
      - name: warehouse
        in: path
        schema:
          type: integer
        required: true
        description: Warehouse ID whose locations to list
        example: '3'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        warehouse_id:
                          type: integer
                        aisle:
                          type: string
                        bay:
                          type: string
                        shelf:
                          type: string
                        bin:
                          type: string
                        is_default:
                          type: boolean
                  status:
                    type: string
                example:
                  data:
                  - id: 1
                    warehouse_id: 3
                    aisle: A
                    bay: '1'
                    shelf: '2'
                    bin: B
                    is_default: true
                  - id: 2
                    warehouse_id: 3
                    aisle: B
                    bay: '4'
                    shelf: null
                    bin: null
                    is_default: false
                  status: success
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No query results for model.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: warehouses:read
      operationId: get-api-warehouse-locations-warehouse
    put:
      tags:
      - Warehouses
      summary: Update Warehouse Location
      description: 'Update a storage location. All fields are optional — send only
        the fields to change.


        :::info[Required scope: `warehouses:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Fields:

        - `aisle`, `bay`, `shelf`, `bin` (max 255 each).

        - `is_default` (boolean) — when true, this location becomes the warehouse''s
        default and the flag is cleared from every other location in that warehouse.


        Note: empty, null, and false values are ignored by this endpoint — it only
        applies non-empty values. To clear a location''s default flag, set `is_default:
        true` on another location in the same warehouse instead of sending false here.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                aisle:
                  type: string
                bay:
                  type: string
                shelf:
                  type: string
                bin:
                  type: string
                is_default:
                  type: boolean
              example:
                aisle: C
                bay: '3'
                shelf: '1'
                bin: A
                is_default: true
      parameters:
      - name: warehouse
        in: path
        required: true
        schema:
          type: string
        description: The warehouse identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      warehouse_id:
                        type: integer
                      aisle:
                        type: string
                      bay:
                        type: string
                      shelf:
                        type: string
                      bin:
                        type: string
                      is_default:
                        type: boolean
                  status:
                    type: string
                example:
                  message: The warehouse location '7' updated successfully
                  data:
                    id: 7
                    warehouse_id: 3
                    aisle: C
                    bay: '3'
                    shelf: '1'
                    bin: A
                    is_default: true
                  status: success
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No query results for model.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      aisle:
                        type: array
                        items:
                          type: string
                example:
                  message: The aisle field must not be greater than 255 characters.
                  errors:
                    aisle:
                    - The aisle field must not be greater than 255 characters.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: warehouses:write
      operationId: put-api-warehouse-locations-warehouse
  /api/warehouse-locations:
    post:
      tags:
      - Warehouses
      summary: Create Warehouse Location
      description: 'Create a storage location inside a warehouse.


        :::info[Required scope: `warehouses:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Fields:

        - `warehouse_id` (required) — must be an existing warehouse.

        - `aisle` (required, max 255).

        - `bay`, `shelf`, `bin` (optional, max 255 each).

        - `is_default` (optional boolean) — when true, this location becomes the warehouse''s
        default and the default flag is automatically cleared from every other location
        in that warehouse.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                warehouse_id:
                  type: integer
                aisle:
                  type: string
                bay:
                  type: string
                shelf:
                  type: string
                bin:
                  type: string
                is_default:
                  type: boolean
              example:
                warehouse_id: 3
                aisle: C
                bay: '2'
                shelf: '1'
                bin: A
                is_default: false
      parameters: []
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      warehouse_id:
                        type: integer
                      aisle:
                        type: string
                      bay:
                        type: string
                      shelf:
                        type: string
                      bin:
                        type: string
                      is_default:
                        type: boolean
                      id:
                        type: integer
                  status:
                    type: string
                example:
                  message: The warehouse location created successfully
                  data:
                    warehouse_id: 3
                    aisle: C
                    bay: '2'
                    shelf: '1'
                    bin: A
                    is_default: false
                    id: 7
                  status: success
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      warehouse_id:
                        type: array
                        items:
                          type: string
                      aisle:
                        type: array
                        items:
                          type: string
                example:
                  message: The warehouse id field is required. (and 1 more error)
                  errors:
                    warehouse_id:
                    - The warehouse id field is required.
                    aisle:
                    - The aisle field is required.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: warehouses:write
      operationId: post-api-warehouse-locations
  /api/v2/fifo-layers:
    get:
      tags:
      - FIFO Layers
      summary: List FIFO Layers
      description: 'Returns a paginated list of FIFO inventory layers. Supports GroupedFilterSupport
        filter trees and sorting.


        :::info[Required scope: `inventory:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Sort options: id, fifo_layer_date, original_quantity, fulfilled_quantity,
        available_quantity, avg_cost, total_cost, condition, created_at, updated_at,
        warehouse_name, sku, product_name


        Archived layers are excluded by default.'
      parameters:
      - name: sort
        in: query
        schema:
          type: string
        description: 'Sort field. Prefix with - for descending. Options: id, fifo_layer_date,
          original_quantity, fulfilled_quantity, available_quantity, avg_cost, total_cost,
          condition, created_at, updated_at, warehouse_name, sku, product_name'
        example: -fifo_layer_date
      - name: per_page
        in: query
        schema:
          type: integer
        example: '10'
        description: Results per page (default 10).
      - name: page
        in: query
        schema:
          type: integer
        example: '1'
        description: Page number (default 1).
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        product_id:
                          type: integer
                        fifo_layer_date:
                          type: string
                        sku:
                          type: string
                        product_name:
                          type: string
                        product_barcode:
                          type: string
                        original_quantity:
                          type: integer
                        fulfilled_quantity:
                          type: integer
                        avg_cost:
                          type: string
                        total_cost:
                          type: string
                        origin:
                          type: object
                          properties:
                            link_type:
                              type: string
                            link_id:
                              type: integer
                            name:
                              type: string
                            parent_link_id:
                              type: string
                              nullable: true
                            detail_link_id:
                              type: string
                              nullable: true
                            reference:
                              type: string
                        warehouse:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        is_fba:
                          type: boolean
                        condition:
                          type: string
                        integration_unique_id:
                          type: string
                          nullable: true
                        allocated_quantity:
                          type: integer
                        available_quantity:
                          type: integer
                        archived_at:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - id: 42
                    product_id: 15
                    fifo_layer_date: '2024-03-01'
                    sku: WIDGET-001
                    product_name: Blue Widget
                    product_barcode: '123456789'
                    original_quantity: 100
                    fulfilled_quantity: 35
                    avg_cost: '4.5000'
                    total_cost: '450.0000'
                    origin:
                      link_type: purchase_order
                      link_id: 8
                      name: PO-0008
                      parent_link_id: null
                      detail_link_id: null
                      reference: REF-123
                    warehouse:
                      id: 2
                      name: Main Warehouse
                    is_fba: false
                    condition: new
                    integration_unique_id: null
                    allocated_quantity: 10
                    available_quantity: 55
                    archived_at: null
                    created_at: '2024-03-01T10:00:00.000000Z'
                    updated_at: '2024-03-15T14:30:00.000000Z'
                  current_page: 1
                  last_page: 5
                  per_page: 10
                  total: 48
                  from: 1
                  to: 10
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: inventory:read
      operationId: get-api-v2-fifo-layers
    post:
      tags:
      - FIFO Layers
      summary: Search FIFO Layers
      description: 'Returns the same paginated list of FIFO cost layers as the GET
        version of this endpoint, but accepts filters as a JSON request body instead
        of the query string. Use this POST variant when the filter set is too large
        or too complex to fit in a URL.


        :::info[Required scope: `inventory:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Provide advanced filters under `filter_groups`, a tree of conditions combined
        with a `conjunction` of `and` or `or`. Each condition names a `column`, an
        `operator`, and a `value`. A free-text `search` term matches against layer
        id, SKU, product name, and warehouse.


        Text columns (`batch_number`, `product_name`, `sku`, `condition`, `source_type`,
        `link_type`) accept: is, is_not, contains, does_not_contain, starts_with,
        ends_with, is_empty, is_not_empty, is_one_of, is_not_one_of.

        Numeric and date columns (`id`, `original_quantity`, `fulfilled_quantity`,
        `avg_cost`, `total_cost`, `fifo_layer_date`, `created_at`, `updated_at`, `manufacture_date`,
        `expiry_date`) accept: is, is_not, greater_than, greater_than_or_equal, less_than,
        less_than_or_equal, between, is_empty, is_not_empty. Additional filters include
        `warehouse`, `availability`, `expiring_within_days`, and `archived`.


        Sortable columns (via `sort`, prefix with `-` for descending): id, fifo_layer_date,
        original_quantity, fulfilled_quantity, available_quantity, avg_cost, total_cost,
        condition, batch_number, manufacture_date, expiry_date, created_at, updated_at,
        warehouse_name, sku, product_name. Results default to `-fifo_layer_date`.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                per_page:
                  type: integer
                page:
                  type: integer
                sort:
                  type: string
                filter_groups:
                  type: object
                  properties:
                    conjunction:
                      type: string
                    children:
                      type: array
                      items:
                        type: object
                        properties:
                          type:
                            type: string
                          condition:
                            type: object
                            properties:
                              column:
                                type: string
                              operator:
                                type: string
                              value:
                                type: array
                                items:
                                  type: string
              example:
                per_page: 25
                page: 1
                sort: -fifo_layer_date
                filter_groups:
                  conjunction: and
                  children:
                  - type: condition
                    condition:
                      column: sku
                      operator: is_one_of
                      value:
                      - WIDGET-BLUE-01
                      - WIDGET-RED-02
                  - type: condition
                    condition:
                      column: avg_cost
                      operator: between
                      value:
                      - 5
                      - 20
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        product_id:
                          type: integer
                        fifo_layer_date:
                          type: string
                        sku:
                          type: string
                        product_name:
                          type: string
                        product_barcode:
                          type: string
                        stock_uom_code:
                          type: string
                        batch_number:
                          type: string
                        manufacture_date:
                          type: string
                        expiry_date:
                          type: string
                        days_to_expiry:
                          type: integer
                        lot_notes:
                          type: string
                          nullable: true
                        original_quantity:
                          type: integer
                        fulfilled_quantity:
                          type: integer
                        avg_cost:
                          type: number
                        total_cost:
                          type: integer
                        origin:
                          type: object
                          properties:
                            link_type:
                              type: string
                            link_id:
                              type: integer
                            name:
                              type: string
                            parent_link_id:
                              type: integer
                            detail_link_id:
                              type: string
                              nullable: true
                            reference:
                              type: string
                            parent_reference:
                              type: string
                        warehouse:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        is_fba:
                          type: boolean
                        condition:
                          type: string
                        allocated_quantity:
                          type: integer
                        available_quantity:
                          type: integer
                        archived_at:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  per_page:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                  last_page:
                    type: integer
                  total:
                    type: integer
                  next_page_url:
                    type: string
                  prev_page_url:
                    type: string
                    nullable: true
                example:
                  data:
                  - id: 90312
                    product_id: 3312
                    fifo_layer_date: '2026-05-01T00:00:00.000000Z'
                    sku: WIDGET-BLUE-01
                    product_name: Blue Widget
                    product_barcode: '8801234567890'
                    stock_uom_code: EA
                    batch_number: LOT-2026-05
                    manufacture_date: '2026-04-20'
                    expiry_date: '2027-04-20'
                    days_to_expiry: 288
                    lot_notes: null
                    original_quantity: 20
                    fulfilled_quantity: 0
                    avg_cost: 13.75
                    total_cost: 275
                    origin:
                      link_type: App\Models\PurchaseOrderShipmentReceiptLine
                      link_id: 55210
                      name: PO-1042
                      parent_link_id: 1042
                      detail_link_id: null
                      reference: PO-1042
                      parent_reference: PO-1042
                    warehouse:
                      id: 2
                      name: Main Warehouse
                    is_fba: false
                    condition: new
                    allocated_quantity: 0
                    available_quantity: 20
                    archived_at: null
                    created_at: '2026-05-01T10:22:00.000000Z'
                    updated_at: '2026-05-01T10:22:00.000000Z'
                  current_page: 1
                  per_page: 25
                  from: 1
                  to: 1
                  last_page: 40
                  total: 987
                  next_page_url: https://api.example.com/api/v2/fifo-layers?page=2
                  prev_page_url: null
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: inventory:write
      operationId: post-api-v2-fifo-layers
  /api/v2/fifo-layers/{fifoLayer}:
    get:
      tags:
      - FIFO Layers
      summary: Show FIFO Layer
      description: 'Returns a single FIFO layer with product, warehouse, source-document
        link, and origin-movement relations loaded.


        :::info[Required scope: `inventory:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        The `origin` block identifies the source document that created the layer and
        now includes `origin.movement` — the metadata of the inventory movement that
        created the layer (id, date, type, source link, quantity, unit_cost, inventory_status,
        reference, batch_number, expiry_date, warehouse, and warehouse_location).
        That origin movement is excluded from the layer''s usage-movements listing
        by default, so its details are surfaced here instead.


        Lot fields (`batch_number`, `manufacture_date`, `expiry_date`, `days_to_expiry`,
        `lot_notes`) are always included; `days_to_expiry` is a signed whole-day countdown
        (negative = already expired, null when the lot has no expiry).


        Authentication: Requires Bearer token.'
      parameters:
      - name: fifoLayer
        in: path
        schema:
          type: integer
        required: true
        description: FIFO Layer ID
        example: '42'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      product_id:
                        type: integer
                      fifo_layer_date:
                        type: string
                      sku:
                        type: string
                      product_name:
                        type: string
                      product_barcode:
                        type: string
                      stock_uom_code:
                        type: string
                      batch_number:
                        type: string
                      manufacture_date:
                        type: string
                      expiry_date:
                        type: string
                      days_to_expiry:
                        type: integer
                      lot_notes:
                        type: string
                        nullable: true
                      original_quantity:
                        type: integer
                      fulfilled_quantity:
                        type: integer
                      avg_cost:
                        type: string
                      total_cost:
                        type: string
                      cost_breakdown:
                        type: string
                        nullable: true
                      origin:
                        type: object
                        properties:
                          link_type:
                            type: string
                          link_id:
                            type: integer
                          name:
                            type: string
                          parent_link_id:
                            type: string
                            nullable: true
                          detail_link_id:
                            type: string
                            nullable: true
                          reference:
                            type: string
                          parent_reference:
                            type: string
                            nullable: true
                          movement:
                            type: object
                            properties:
                              id:
                                type: integer
                              date:
                                type: string
                              type:
                                type: string
                              link_type:
                                type: string
                              link_id:
                                type: integer
                              quantity:
                                type: integer
                              unit_cost:
                                type: string
                              inventory_status:
                                type: string
                              reference:
                                type: string
                              batch_number:
                                type: string
                              expiry_date:
                                type: string
                              warehouse:
                                type: object
                                properties:
                                  id:
                                    type: integer
                                  name:
                                    type: string
                              warehouse_location:
                                type: object
                                properties:
                                  id:
                                    type: integer
                                  code:
                                    type: string
                                  name:
                                    type: string
                      warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      is_fba:
                        type: boolean
                      is_consignment:
                        type: boolean
                      condition:
                        type: string
                      integration_unique_id:
                        type: string
                        nullable: true
                      allocated_quantity:
                        type: integer
                      available_quantity:
                        type: integer
                      archived_at:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 42
                    product_id: 15
                    fifo_layer_date: '2024-03-01'
                    sku: WIDGET-001
                    product_name: Blue Widget
                    product_barcode: '123456789'
                    stock_uom_code: EA
                    batch_number: LOT-2024-03-001
                    manufacture_date: '2024-02-28'
                    expiry_date: '2025-02-28'
                    days_to_expiry: 226
                    lot_notes: null
                    original_quantity: 100
                    fulfilled_quantity: 35
                    avg_cost: '4.5000'
                    total_cost: '450.0000'
                    cost_breakdown: null
                    origin:
                      link_type: purchase_order
                      link_id: 8
                      name: PO-0008
                      parent_link_id: null
                      detail_link_id: null
                      reference: REF-123
                      parent_reference: null
                      movement:
                        id: 187
                        date: '2024-03-01T10:00:00.000000Z'
                        type: purchase_order_received
                        link_type: purchase_order_shipment_item
                        link_id: 91
                        quantity: 100
                        unit_cost: '4.5000'
                        inventory_status: active
                        reference: REF-123
                        batch_number: LOT-2024-03-001
                        expiry_date: '2025-02-28'
                        warehouse:
                          id: 2
                          name: Main Warehouse
                        warehouse_location:
                          id: 7
                          code: A-01-02
                          name: Aisle A Bay 1 Shelf 2
                    warehouse:
                      id: 2
                      name: Main Warehouse
                    is_fba: false
                    is_consignment: false
                    condition: new
                    integration_unique_id: null
                    allocated_quantity: 10
                    available_quantity: 65
                    archived_at: null
                    created_at: '2024-03-01T10:00:00.000000Z'
                    updated_at: '2024-03-15T14:30:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: inventory:read
      operationId: get-api-v2-fifo-layers-fifolayer
  /api/v2/fifo-layers/{fifoLayer}/allocations:
    get:
      tags:
      - FIFO Layers
      summary: FIFO Layer Allocations
      description: 'Returns sales order line allocations for this FIFO layer — which
        sales orders have reserved quantity from this layer.


        :::info[Required scope: `inventory:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: fifoLayer
        in: path
        schema:
          type: integer
        required: true
        description: FIFO Layer ID
        example: '42'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        quantity:
                          type: integer
                        sales_order_line_id:
                          type: integer
                        sales_order:
                          type: object
                          properties:
                            id:
                              type: integer
                            order_number:
                              type: string
                            customer_id:
                              type: integer
                            customer_name:
                              type: string
                            order_status:
                              type: string
                        product:
                          type: object
                          properties:
                            id:
                              type: integer
                            sku:
                              type: string
                            name:
                              type: string
                        allocation_status:
                          type: string
                        created_at:
                          type: string
                example:
                  data:
                  - id: 101
                    quantity: 10
                    sales_order_line_id: 55
                    sales_order:
                      id: 30
                      order_number: SO-0030
                      customer_id: 7
                      customer_name: Acme Corp
                      order_status: processing
                    product:
                      id: 15
                      sku: WIDGET-001
                      name: Blue Widget
                    allocation_status: allocated
                    created_at: '2024-03-10T09:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: inventory:read
      operationId: get-api-v2-fifo-layers-fifolayer-allocations
  /api/v2/fifo-layers/{fifoLayer}/inventory-movements:
    get:
      tags:
      - FIFO Layers
      summary: FIFO Layer Inventory Movements
      description: 'Paginated usage movements for a FIFO layer (standard paginated
        response: `data[]` plus `current_page`, `last_page`, `per_page`, `total`,
        ...).


        :::info[Required scope: `inventory:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        The movement that originally created the layer is **excluded by default**
        — it is presented in the layer''s `origin` block on the single-layer endpoint
        instead of as a usage. Pass `exclude_origin=0` to include it (e.g. to tally
        the layer''s full movement history).


        Filters (server-side):

        - `filter[type]` — exact movement type match. Dotted operator variants are
        also available (`filter[type.is]`, `filter[type.contains]`, ...).

        - `filter[link_type]` — exact source-document type match.

        - `filter[inventory_status]` — defaults to `active`; pass `all` for no status
        restriction. Dotted operator variants (`filter[inventory_status.is]`, ...)
        are also available.

        - `filter[reference]` — text operator filters (`filter[reference.contains]`,
        ...).

        - `filter[quantity]` — numeric operator filters (`filter[quantity.gte]`, ...).

        - `filter[inventory_movement_date]`, `filter[created_at]` — date operator
        filters (`.on`, `.before`, `.after`, `.between`).

        - `filter[search]` — searches ID (exact), Reference, SKU, and Product Name.


        Allowed sorts: id, inventory_movement_date, type, inventory_status, quantity,
        reference, created_at (prefix with - for descending; default: -inventory_movement_date).


        Authentication: Requires Bearer token.'
      parameters:
      - name: fifoLayer
        in: path
        schema:
          type: integer
        required: true
        description: FIFO Layer ID
        example: '42'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        inventory_movement_date:
                          type: string
                        product_id:
                          type: integer
                        sku:
                          type: string
                        barcode:
                          type: string
                        product_name:
                          type: string
                        stock_uom_code:
                          type: string
                        type:
                          type: object
                          properties:
                            name:
                              type: string
                            link_type:
                              type: string
                            link_id:
                              type: integer
                            parent_link_id:
                              type: integer
                            detail_link_id:
                              type: string
                              nullable: true
                        inventory_status:
                          type: string
                        quantity:
                          type: integer
                        warehouse:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        layer:
                          type: object
                          properties:
                            fifo_layer_id:
                              type: integer
                            name:
                              type: string
                        fifo_layer_id:
                          type: integer
                        reference:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - id: 201
                    inventory_movement_date: '2024-03-12T11:00:00.000000Z'
                    product_id: 15
                    sku: WIDGET-001
                    barcode: '123456789'
                    product_name: Blue Widget
                    stock_uom_code: EA
                    type:
                      name: fulfillment
                      link_type: sales_order_fulfillment_line
                      link_id: 3411
                      parent_link_id: 812
                      detail_link_id: null
                    inventory_status: active
                    quantity: -5
                    warehouse:
                      id: 2
                      name: Main Warehouse
                    layer:
                      fifo_layer_id: 42
                      name: PO-0008
                    fifo_layer_id: 42
                    reference: SO-1042
                    created_at: '2024-03-12T11:00:00.000000Z'
                    updated_at: '2024-03-12T11:00:00.000000Z'
                  current_page: 1
                  last_page: 3
                  per_page: 15
                  total: 35
                  from: 1
                  to: 15
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: inventory:read
      operationId: get-api-v2-fifo-layers-fifolayer-inventory-movements
  /api/v2/fifo-layers/{fifoLayer}/archive:
    put:
      tags:
      - FIFO Layers
      summary: Archive FIFO Layer
      description: 'Archives a single FIFO layer. Only fully utilized layers (available_quantity
        = 0) can be archived.


        :::info[Required scope: `inventory:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: fifoLayer
        in: path
        schema:
          type: integer
        required: true
        description: FIFO Layer ID
        example: '42'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      archived_at:
                        type: string
                example:
                  message: FIFO Layer 42 has been archived.
                  data:
                    id: 42
                    archived_at: '2024-03-20T10:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: inventory:write
      operationId: put-api-v2-fifo-layers-fifolayer-archive
  /api/v2/fifo-layers/{fifoLayer}/unarchive:
    put:
      tags:
      - FIFO Layers
      summary: Unarchive FIFO Layer
      description: 'Unarchives a previously archived FIFO layer.


        :::info[Required scope: `inventory:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: fifoLayer
        in: path
        schema:
          type: integer
        required: true
        description: FIFO Layer ID
        example: '42'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      archived_at:
                        type: string
                        nullable: true
                example:
                  message: FIFO Layer 42 has been unarchived.
                  data:
                    id: 42
                    archived_at: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: inventory:write
      operationId: put-api-v2-fifo-layers-fifolayer-unarchive
  /api/v2/fifo-layers/archive:
    put:
      tags:
      - FIFO Layers
      summary: Bulk Archive FIFO Layers
      description: 'Archives multiple FIFO layers. Only fully utilized layers (available_quantity
        = 0) can be archived. Use apply_to_all with filters to archive all matching
        layers.


        :::info[Required scope: `inventory:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Request Body:

        - ids (required_without:apply_to_all, array): Array of FIFO layer IDs

        - apply_to_all (nullable, boolean): If true, archive all layers matching filters

        - filters (nullable, array): Filter criteria when using apply_to_all'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 42
                - 43
                - 44
      parameters: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 2 of 2 fifo layers have been archived successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: inventory:write
      operationId: put-api-v2-fifo-layers-archive
  /api/v2/fifo-layers/unarchive:
    put:
      tags:
      - FIFO Layers
      summary: Bulk Unarchive FIFO Layers
      description: 'Unarchives multiple FIFO layers.


        :::info[Required scope: `inventory:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Request Body:

        - ids (required_without:apply_to_all, array): Array of FIFO layer IDs

        - apply_to_all (nullable, boolean): If true, unarchive all matching layers

        - filters (nullable, array): Filter criteria when using apply_to_all'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 42
                - 43
      parameters: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 2 of 2 fifo layers have been un-archived successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: inventory:write
      operationId: put-api-v2-fifo-layers-unarchive
  /api/v2/data-imports:
    post:
      tags:
      - Data Imports
      summary: Upload Data Import
      description: 'Uploads mapped CSV data for import and kicks off background validation.
        Returns the data import ID and a tracked job log ID to poll for validation
        progress.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.


        Per-entity authorization: For the gated entity types (customers, warehouses,
        suppliers, sales_reps, categories) the user must hold the matching `<entity>.import`
        permission (e.g. customers.import). Other entity types are not gated here.
        The check resolves through the granular_permissions feature flag — it is a
        no-op while that flag is off. Returns 403 when the user lacks the required
        permission.


        Request Body:

        - entity_type (required, string): Type of entity being imported (e.g. products,
        customers, warehouses, suppliers, sales_reps)

        - file_name (required, string, max:255): Original filename for display

        - column_mapping (required, array): Maps column positions to field names

        - mapped_rows (required, array, min:1): Array of row objects with mapped field
        values

        - metadata (nullable, array): Optional metadata'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                entity_type:
                  type: string
                file_name:
                  type: string
                column_mapping:
                  type: object
                  properties:
                    A:
                      type: string
                    B:
                      type: string
                    C:
                      type: string
                mapped_rows:
                  type: array
                  items:
                    type: object
                    properties:
                      sku:
                        type: string
                      name:
                        type: string
                      cost:
                        type: string
                metadata:
                  type: string
                  nullable: true
              example:
                entity_type: products
                file_name: products-import.csv
                column_mapping:
                  A: sku
                  B: name
                  C: cost
                mapped_rows:
                - sku: PROD-001
                  name: Product One
                  cost: '9.99'
                - sku: PROD-002
                  name: Product Two
                  cost: '14.99'
                metadata: null
      parameters: []
      responses:
        '201':
          description: Created
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    id: 5
                    tracked_job_log_id: 88
                  message: Import uploaded and validation started.
        '403':
          description: Forbidden
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: You are not authorized to import this resource.
        '429': *id001
        '401': *id002
        '422': *id005
      x-session-only: true
      operationId: post-api-v2-data-imports
  /api/v2/data-imports/{dataImport}/summary:
    get:
      tags:
      - Data Imports
      summary: Get Data Import Summary
      description: 'Returns the summary for a data import including status, row counts,
        and validation/import summaries.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: dataImport
        in: path
        schema:
          type: integer
        required: true
        description: Data Import ID
        example: '5'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      status:
                        type: string
                      file_name:
                        type: string
                      total_rows:
                        type: integer
                      validation_summary:
                        type: object
                        properties:
                          valid_rows:
                            type: integer
                          invalid_rows:
                            type: integer
                          errors:
                            type: array
                            items:
                              type: string
                      import_summary:
                        type: string
                        nullable: true
                example:
                  data:
                    id: 5
                    status: validated
                    file_name: products-import.csv
                    total_rows: 100
                    validation_summary:
                      valid_rows: 98
                      invalid_rows: 2
                      errors:
                      - 'Row 5: SKU is required'
                      - 'Row 12: Cost must be numeric'
                    import_summary: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-session-only: true
      operationId: get-api-v2-data-imports-dataimport-summary
  /api/v2/data-imports/{dataImport}/validation-results:
    get:
      tags:
      - Data Imports
      summary: Get Validation Results
      description: 'Returns paginated validation results for a data import. Optionally
        filter by result type.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.


        Query Parameters:

        - filter: Filter by result type (errors, warnings, valid)

        - per_page: Results per page (default 50)

        - page: Page number'
      parameters:
      - name: per_page
        in: query
        schema:
          type: integer
        example: '50'
        description: Results per page (default 10).
      - name: page
        in: query
        schema:
          type: integer
        example: '1'
        description: Page number (default 1).
      - name: dataImport
        in: path
        schema:
          type: integer
        required: true
        description: Data Import ID
        example: '5'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        row:
                          type: integer
                        status:
                          type: string
                        errors:
                          type: array
                          items:
                            type: string
                        data:
                          type: object
                          properties:
                            name:
                              type: string
                            cost:
                              type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - row: 5
                    status: error
                    errors:
                    - SKU is required
                    data:
                      name: Missing SKU Product
                      cost: '9.99'
                  - row: 1
                    status: valid
                    errors: []
                    data:
                      sku: PROD-001
                      name: Product One
                      cost: '9.99'
                  current_page: 1
                  last_page: 2
                  per_page: 50
                  total: 100
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-session-only: true
      operationId: get-api-v2-data-imports-dataimport-validation-results
  /api/v2/data-imports/{dataImport}/execute:
    post:
      tags:
      - Data Imports
      summary: Execute Data Import
      description: 'Executes a validated data import. Kicks off the background import
        job and returns a tracked job log ID to monitor progress.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.


        Per-entity authorization: For the gated entity types (customers, warehouses,
        suppliers, sales_reps, categories) the user must hold the matching `<entity>.import`
        permission for the import''s entity_type. Returns 403 when the user lacks
        the required permission. The check resolves through the granular_permissions
        feature flag — it is a no-op while that flag is off.'
      requestBody:
        content: {}
      parameters:
      - name: dataImport
        in: path
        schema:
          type: integer
        required: true
        description: Data Import ID
        example: '5'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    id: 5
                    tracked_job_log_id: 92
                  message: Import execution started.
        '403':
          description: Forbidden
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: You are not authorized to import this resource.
        '429': *id001
        '401': *id002
        '404': *id004
        '422': *id005
      x-session-only: true
      operationId: post-api-v2-data-imports-dataimport-execute
  /api/v2/data-imports/{dataImport}/import-results:
    get:
      tags:
      - Data Imports
      summary: Get Import Results
      description: 'Returns the import results after execution has completed.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: dataImport
        in: path
        schema:
          type: integer
        required: true
        description: Data Import ID
        example: '5'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      created:
                        type: integer
                      updated:
                        type: integer
                      failed:
                        type: integer
                      errors:
                        type: array
                        items:
                          type: object
                          properties:
                            row:
                              type: integer
                            error:
                              type: string
                example:
                  data:
                    created: 96
                    updated: 2
                    failed: 2
                    errors:
                    - row: 5
                      error: SKU is required
                    - row: 12
                      error: Cost must be numeric
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-session-only: true
      operationId: get-api-v2-data-imports-dataimport-import-results
  /api/v2/data-imports/template:
    get:
      tags:
      - Data Imports
      summary: Download Import Template
      description: 'Download an XLSX import template for the given import type: the
        field labels as headers plus a sample data row where available. Headers match
        the import wizard''s field labels exactly, so an exported template maps automatically.'
      parameters:
      - name: entity_type
        in: query
        schema:
          type: string
        description: Registered import type (e.g. `suppliers`, `customers`, `warehouses`,
          `contacts`).
        example: contacts
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-v2-data-imports-template
  /api/v2/customers:
    get:
      tags:
      - Customers
      summary: List Customers
      description: 'Returns a paginated list of customers.


        :::info[Required scope: `customers:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: per_page
        in: query
        schema:
          type: integer
        example: '10'
        description: Results per page (default 10).
      - name: page
        in: query
        schema:
          type: integer
        example: '1'
        description: Page number (default 1).
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        email:
                          type: string
                        phone:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 7
                    name: Acme Corp
                    email: orders@acme.com
                    phone: +1-555-0100
                    created_at: '2023-06-15T08:00:00.000000Z'
                    updated_at: '2024-01-10T12:00:00.000000Z'
                  current_page: 1
                  last_page: 3
                  per_page: 10
                  total: 25
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: customers:read
      operationId: get-api-v2-customers
  /api/v2/customers/{customer}:
    get:
      tags:
      - Customers
      summary: Show Customer
      description: 'Returns a single customer.


        :::info[Required scope: `customers:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Use the `with` query parameter (comma-separated) to include relations: `salesChannelOrigin`,
        `productPricingTier`, `store`, `shippingMethodDomestic`, `shippingMethodInternational`,
        `warehouse`, `defaultSalesRep`, `defaultIncoterm`, `integrationInstance`,
        `shippingAddress`, `billingAddress`, `addresses`.


        Authentication: Requires Bearer token.'
      parameters:
      - name: customer
        in: path
        schema:
          type: integer
        required: true
        description: Customer ID
        example: '7'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      email:
                        type: string
                      phone:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 7
                    name: Acme Corp
                    email: orders@acme.com
                    phone: +1-555-0100
                    created_at: '2023-06-15T08:00:00.000000Z'
                    updated_at: '2024-01-10T12:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: customers:read
      operationId: get-api-v2-customers-customer
  /api/customers/lookup:
    get:
      tags:
      - Customers
      summary: Customer Lookup (Quick Search)
      description: 'Lightweight customer quick-search used by the POS register to
        attach a customer at checkout. Returns a compact card per customer including
        the live store-credit wallet balance (summed in one join, N+1-safe), the assigned
        pricing tier, and tax-exemption status. Archived customers are excluded.


        :::info[Required scope: `customers:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Query params: `q` (optional; matches name/company/email/phone), `limit` (optional;
        1–50, default 15).


        Authentication: Requires Bearer token (PAT).'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        company:
                          type: string
                        email:
                          type: string
                        phone:
                          type: string
                        tax_exempt:
                          type: boolean
                        tax_exemption_reference:
                          type: string
                          nullable: true
                        product_pricing_tier_id:
                          type: integer
                        pricing_tier_name:
                          type: string
                        store_credit_balance:
                          type: number
                        loyalty_points_balance:
                          type: integer
                        house_account_enabled:
                          type: boolean
                        credit_limit:
                          type: integer
                        house_account_balance:
                          type: number
                        billing_email:
                          type: string
                        payment_terms_days:
                          type: integer
                example:
                  data:
                  - id: 501
                    name: Ada Lovelace
                    company: Analytical Engines
                    email: ada@example.com
                    phone: '5550100'
                    tax_exempt: false
                    tax_exemption_reference: null
                    product_pricing_tier_id: 3
                    pricing_tier_name: Wholesale
                    store_credit_balance: 42.5
                    loyalty_points_balance: 250
                    house_account_enabled: true
                    credit_limit: 5000
                    house_account_balance: 1200.5
                    billing_email: ap@acme-wholesale.com
                    payment_terms_days: 30
                  - id: 502
                    name: Ada Byron
                    company: null
                    email: byron@example.com
                    phone: '5550111'
                    tax_exempt: true
                    tax_exemption_reference: RESALE-12345
                    product_pricing_tier_id: null
                    pricing_tier_name: null
                    store_credit_balance: 0
                    loyalty_points_balance: 250
                    house_account_enabled: true
                    credit_limit: 5000
                    house_account_balance: 1200.5
                    billing_email: ap@acme-wholesale.com
                    payment_terms_days: 30
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      limit:
                        type: array
                        items:
                          type: string
                example:
                  message: The limit must not be greater than 50.
                  errors:
                    limit:
                    - The limit must not be greater than 50.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: customers:read
      operationId: get-api-customers-lookup
  /api/v2/customers/duplicate-runs/{trackedJobLog}/pairs:
    get:
      tags:
      - Customers
      summary: List Duplicate Customer Pairs
      description: 'List the candidate duplicate pairs produced by a completed detection
        run, hydrated with each customer''s identifying details for side-by-side comparison.
        Pairs are ordered by match score (highest first) and paginated; pairs that
        have since been marked ''not a duplicate'' are excluded from the results.


        :::info[Required scope: `customers:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Each pair contains: customer_a and customer_b detail cards, the 0-100 match
        score, a bucket (''auto'' = score of 90 or higher, ''review'' = 60 or higher,
        ''hidden'' otherwise), and the per-field scoring signals (field, score, weight,
        contribution, note).


        For runs with scope ''sku'' the cards include the sales order count and last
        order date. For scope ''qbo'' the cards include the QuickBooks customer details
        (display name, company, given/family name, linked customer ID, active flag).


        If the run has not completed or produced no results, an empty list is returned
        with meta.total = 0.


        Pagination: page (default 1) and per_page (default 25).


        Authentication: Requires Bearer token with the customers read/write scope
        and the customer merge permission.'
      parameters:
      - name: trackedJobLog
        in: path
        schema:
          type: integer
        required: true
        description: Detection run ID - the tracked_job_log_id returned when the run
          was started
        example: '9451'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 Success (sku scope)
                  value:
                    data:
                    - customer_a:
                        id: 101
                        name: John Smith
                        company: Acme Corp
                        email: john@acmecorp.com
                        phone: +1-555-0101
                        address: 500 Industrial Way, 91201
                        archived_at: null
                        sales_orders_count: 14
                        last_order_date: '2026-06-12'
                      customer_b:
                        id: 2384
                        name: John A. Smith
                        company: Acme Corporation
                        email: john@acmecorp.com
                        phone: null
                        address: null
                        archived_at: null
                        sales_orders_count: 2
                        last_order_date: '2025-11-03'
                      score: 91
                      bucket: auto
                      signals:
                      - field: email
                        score: 1
                        weight: 50
                        contribution: 50
                        note: null
                      - field: company
                        score: 0.97
                        weight: 30
                        contribution: 29.1
                        note: fuzzy_company_high
                      - field: name
                        score: 0.8
                        weight: 15
                        contribution: 12
                        note: null
                      - field: address
                        score: 0
                        weight: 3
                        contribution: 0
                        note: null
                      - field: phone
                        score: 0
                        weight: 2
                        contribution: 0
                        note: null
                    meta:
                      total: 37
                      pairs_count: 40
                      page: 1
                      per_page: 25
                      last_page: 2
                      scope: sku
                      integration_instance_id: null
                example-1:
                  summary: 200 Success (qbo scope)
                  value:
                    data:
                    - customer_a:
                        id: 55
                        qbo_id: '158'
                        display_name: Acme Corp
                        company_name: Acme Corp
                        given_name: John
                        family_name: Smith
                        email: john@acmecorp.com
                        sku_customer_id: 101
                        active: true
                        address: 500 Industrial Way, Glendale, CA, 91201
                      customer_b:
                        id: 89
                        qbo_id: '412'
                        display_name: Acme Corporation
                        company_name: Acme Corporation
                        given_name: null
                        family_name: null
                        email: accounts@acmecorp.com
                        sku_customer_id: null
                        active: true
                        address: null
                      score: 78
                      bucket: review
                      signals:
                      - field: email
                        score: 0.7
                        weight: 50
                        contribution: 35
                        note: same_domain_only
                      - field: company
                        score: 0.97
                        weight: 30
                        contribution: 29.1
                        note: fuzzy_company_high
                      - field: name
                        score: 0.93
                        weight: 15
                        contribution: 13.95
                        note: null
                      - field: address
                        score: 0
                        weight: 3
                        contribution: 0
                        note: null
                      - field: phone
                        score: 0
                        weight: 2
                        contribution: 0
                        note: null
                    meta:
                      total: 5
                      pairs_count: 5
                      page: 1
                      per_page: 25
                      last_page: 1
                      scope: qbo
                      integration_instance_id: 3
                example-2:
                  summary: 200 Run Not Finished or No Results
                  value:
                    data: []
                    meta:
                      total: 0
                      scope: null
                      pairs_count: 0
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: customers:read
      operationId: get-api-v2-customers-duplicate-runs-trackedjoblog-pairs
  /api/v2/customers/export:
    get:
      tags:
      - Customers
      summary: Export Customers
      description: 'Download all customers matching the current filters as a spreadsheet
        file (CSV by default, XLSX when format=xlsx). The file contains the columns:
        Sr No., id, name, company, email, sales_channel_origin_name, integration_instance_name,
        created_at, updated_at. Rows are ordered by customer ID ascending and the
        export is not paginated - every matching customer is included.


        :::info[Required scope: `customers:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Privacy: customers originating from Amazon are redacted - the row keeps its
        serial number but every other column is blank.


        Timestamps in the file are converted to the account''s local timezone (matching
        on-screen values).


        Filtering uses operator-style parameters: filter[column.operator]=value. A
        bare filter[column]=value acts as the ''is'' operator.


        Text columns (name, email, company, phone, city, province, country) support:
        contains, does_not_contain, is, is_not, is_one_of, is_not_one_of, starts_with,
        does_not_start_with, ends_with, does_not_end_with, is_empty, is_not_empty.
        The city, province, and country filters match the customer''s default shipping
        address.


        Date columns (created_at, updated_at, archived_at) support: is, is_not, before,
        after, on_or_before, on_or_after, between (two comma-separated dates), is_empty,
        is_not_empty, today, yesterday, tomorrow, past_week, past_month, past_year,
        next_week, next_month, next_year, days_ago, days_from_now, past_days, next_days.
        Dates use YYYY-MM-DD format and are interpreted in the account''s local timezone.


        Archived customers are excluded unless filter[archived] is provided (''only''
        = archived customers only, ''all'' = archived and active).


        The response is a file download (Content-Type: text/csv or the XLSX MIME type),
        not JSON.


        Authentication: Requires Bearer token with the customers read/write scope.


        Optional. When `include_contacts=1`, the export flattens to one row per contact
        with the parent columns repeated (parent-only row when a record has no contacts),
        appending Contact ID/Name/Email/Phone/Role/Title/Primary/Notes columns.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: text/csv
          content:
            text/plain:
              schema:
                type: string
                example: 'Sr No.,id,name,company,email,sales_channel_origin_name,integration_instance_name,created_at,updated_at

                  1,101,John Smith,Acme Corp,john@acmecorp.com,Shopify,Acme Shopify
                  Store,2026-01-14 09:32:11,2026-06-02 15:04:27

                  2,,,,,,,,

                  3,214,Jane Rivera,Rivera Trading,jane@riveratrading.com,,,2026-02-20
                  11:05:44,2026-02-20 11:05:44


                  (CSV file download named customers-2026-07-07-14-21-05.csv. Row
                  2 is an Amazon-origin customer redacted for privacy.)'
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: customers:read
      operationId: get-api-v2-customers-export
  /api/v2/customers/dedup-decisions:
    post:
      tags:
      - Customers
      summary: Mark Customer Pair as Not Duplicate
      description: 'Record a decision that two customers are not duplicates of each
        other, so the pair stops appearing in duplicate detection results. The decision
        is order-independent (the pair is stored with the lower ID first) and idempotent
        - repeating the call for the same pair returns the existing decision.


        :::info[Required scope: `customers:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        For scope ''qbo'', the IDs refer to customer records synced from the connected
        QuickBooks Online instance identified by integration_instance_id.


        Body fields:

        - customer_id_a (integer, required): first customer of the pair.

        - customer_id_b (integer, required): second customer of the pair; must differ
        from customer_id_a.

        - scope (string, required): ''sku'' or ''qbo''.

        - integration_instance_id (integer, optional): the connected integration instance
        the decision applies to (used with scope ''qbo''); must reference an existing
        integration instance.


        Authentication: Requires Bearer token with the customers read/write scope
        and the customer merge permission.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                customer_id_a:
                  type: integer
                customer_id_b:
                  type: integer
                scope:
                  type: string
                integration_instance_id:
                  type: string
                  nullable: true
              example:
                customer_id_a: 101
                customer_id_b: 2384
                scope: sku
                integration_instance_id: null
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      scope:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 55
                    scope: sku
                  message: Marked as not duplicate.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      customer_id_b:
                        type: array
                        items:
                          type: string
                example:
                  message: The customer id b field and customer id a must be different.
                  errors:
                    customer_id_b:
                    - The customer id b field and customer id a must be different.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: customers:write
      operationId: post-api-v2-customers-dedup-decisions
  /api/v2/customers/duplicate-runs:
    post:
      tags:
      - Customers
      summary: Start Customer Duplicate Detection Run
      description: 'Start an asynchronous duplicate-detection run over customer records.
        The work is dispatched to a background job and the endpoint returns immediately
        with a tracked_job_log_id. Once the run completes, fetch the scored candidate
        pairs from the List Duplicate Customer Pairs endpoint using that ID.


        :::info[Required scope: `customers:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Scopes:

        - sku - scans the account''s own customer records.

        - qbo - scans customer records synced from a connected QuickBooks Online instance
        (integration_instance_id is required for this scope).


        Candidates are grouped by normalized email and company, then each pair is
        scored 0-100 across weighted signals (email, company, name, address, phone).
        Only pairs scoring at or above the threshold (default 80) are kept, and pairs
        previously marked ''not a duplicate'' are excluded.


        Body fields:

        - scope (string, required): ''sku'' or ''qbo''.

        - integration_instance_id (integer, optional): required when scope is ''qbo'';
        must reference a connected integration instance.

        - threshold (integer, optional): minimum match score (0-100) for a pair to
        be included. Default: 80.


        Authentication: Requires Bearer token with the customers read/write scope
        and the customer merge permission.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                scope:
                  type: string
                integration_instance_id:
                  type: string
                  nullable: true
                threshold:
                  type: integer
              example:
                scope: sku
                integration_instance_id: null
                threshold: 80
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 9451
                  message: Duplicate detection started
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 422 Validation Error
                  value:
                    message: The selected scope is invalid.
                    errors:
                      scope:
                      - The selected scope is invalid.
                example-1:
                  summary: 422 Missing Integration Instance
                  value:
                    errors:
                      integration_instance_id:
                      - Required when scope is qbo
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: customers:write
      operationId: post-api-v2-customers-duplicate-runs
  /api/v2/customers/merge:
    post:
      tags:
      - Customers
      summary: Merge Customers
      description: 'Merge the secondary customer into the primary customer. This is
        a destructive operation performed in a single transaction:


        :::info[Required scope: `customers:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        - All related records - sales orders, sales credits, customer SKU mappings,
        order document extractions, and linked QuickBooks customer records - are reassigned
        from the secondary to the primary customer.

        - Contact fields (email, company, phone, fax, tax number, default shipping/billing
        address) are copied from the secondary onto the primary only where the primary''s
        value is empty; existing primary data is never overwritten.

        - The secondary customer is archived.

        - A merge log is written capturing a snapshot of both customers and the per-table
        reassignment counts (fk_moves).


        The returned merge_log_id can be used to reverse the merge within 30 days
        via Undo Customer Merge. The request fails if the secondary customer is already
        archived.


        Body fields:

        - primary_customer_id (integer, required): the customer to keep; must reference
        an existing customer.

        - secondary_customer_id (integer, required): the customer to merge away; must
        reference an existing customer and differ from primary_customer_id.


        Authentication: Requires Bearer token with the customers read/write scope
        and the customer merge permission.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                primary_customer_id:
                  type: integer
                secondary_customer_id:
                  type: integer
              example:
                primary_customer_id: 101
                secondary_customer_id: 2384
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      merge_log_id:
                        type: integer
                      fk_moves:
                        type: object
                        properties:
                          sales_orders:
                            type: integer
                          sales_credits:
                            type: integer
                          customer_sku_mappings:
                            type: integer
                          sales_order_ocr_extractions:
                            type: integer
                          qbo_customers:
                            type: integer
                  message:
                    type: string
                example:
                  data:
                    merge_log_id: 12
                    fk_moves:
                      sales_orders: 14
                      sales_credits: 2
                      customer_sku_mappings: 0
                      sales_order_ocr_extractions: 1
                      qbo_customers: 1
                  message: Customers merged successfully.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      secondary_customer_id:
                        type: array
                        items:
                          type: string
                example:
                  message: The secondary customer id field and primary customer id
                    must be different.
                  errors:
                    secondary_customer_id:
                    - The secondary customer id field and primary customer id must
                      be different.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: customers:write
      operationId: post-api-v2-customers-merge
  /api/v2/customers/merge-logs/{mergeLog}/undo:
    post:
      tags:
      - Customers
      summary: Undo Customer Merge
      description: 'Reverse a previous customer merge: un-archives the secondary customer
        and moves the records that were reassigned during the merge back to it.


        :::info[Required scope: `customers:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        A merge can only be reversed once, and only within 30 days of the original
        merge; attempting to reverse an already-reversed or expired merge fails. Use
        the merge_log_id returned by Merge Customers as the path parameter.


        Authentication: Requires Bearer token with the customers read/write scope
        and the customer merge permission.'
      requestBody:
        content: {}
      parameters:
      - name: mergeLog
        in: path
        schema:
          type: integer
        required: true
        description: Merge log ID returned by the merge endpoint
        example: '12'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      merge_log_id:
                        type: integer
                      reversed_at:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    merge_log_id: 12
                    reversed_at: '2026-07-07T14:21:05+00:00'
                  message: Merge reversed.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: customers:write
      operationId: post-api-v2-customers-merge-logs-mergelog-undo
  /api/v2/customers/merge/preview:
    post:
      tags:
      - Customers
      summary: Preview Customer Merge
      description: 'Preview the effect of merging one customer (secondary) into another
        (primary) without changing any data. Returns, per related record type, the
        number of records currently attached to the secondary customer that would
        be reassigned to the primary: sales orders (sales_orders), sales credits (sales_credits),
        customer SKU mappings (customer_sku_mappings), order document extractions
        (sales_order_ocr_extractions), and linked QuickBooks customer records (qbo_customers).


        :::info[Required scope: `customers:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Use this before calling Merge Customers so the operator can review what will
        move.


        Body fields:

        - primary_customer_id (integer, required): the customer that will be kept;
        must reference an existing customer.

        - secondary_customer_id (integer, required): the customer that will be merged
        away; must reference an existing customer and differ from primary_customer_id.


        Authentication: Requires Bearer token with the customers read/write scope
        and the customer merge permission.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                primary_customer_id:
                  type: integer
                secondary_customer_id:
                  type: integer
              example:
                primary_customer_id: 101
                secondary_customer_id: 2384
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      fk_moves:
                        type: object
                        properties:
                          sales_orders:
                            type: integer
                          sales_credits:
                            type: integer
                          customer_sku_mappings:
                            type: integer
                          sales_order_ocr_extractions:
                            type: integer
                          qbo_customers:
                            type: integer
                example:
                  data:
                    fk_moves:
                      sales_orders: 14
                      sales_credits: 2
                      customer_sku_mappings: 0
                      sales_order_ocr_extractions: 1
                      qbo_customers: 1
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      secondary_customer_id:
                        type: array
                        items:
                          type: string
                example:
                  message: The selected secondary customer id is invalid.
                  errors:
                    secondary_customer_id:
                    - The selected secondary customer id is invalid.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: customers:write
      operationId: post-api-v2-customers-merge-preview
  /api/v2/settings:
    get:
      tags:
      - Settings
      summary: List Settings
      description: 'Returns all application settings.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        slug:
                          type: string
                        value:
                          type: string
                        label:
                          type: string
                example:
                  data:
                  - slug: default_warehouse_id
                    value: '2'
                    label: Default Warehouse
                  - slug: currency
                    value: USD
                    label: Currency
                  - slug: timezone
                    value: America/New_York
                    label: Timezone
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: get-api-v2-settings
    put:
      tags:
      - Settings
      summary: Bulk Update Settings
      description: 'Updates multiple settings at once.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `settings.update`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                settings:
                  type: array
                  items:
                    type: object
                    properties:
                      slug:
                        type: string
                      value:
                        type: string
              example:
                settings:
                - slug: default_warehouse_id
                  value: '3'
                - slug: timezone
                  value: America/Los_Angeles
      parameters: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        slug:
                          type: string
                        value:
                          type: string
                  message:
                    type: string
                example:
                  data:
                  - slug: default_warehouse_id
                    value: '3'
                  - slug: timezone
                    value: America/Los_Angeles
                  message: Settings updated successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-session-only: true
      operationId: put-api-v2-settings
  /api/v2/settings/{slug}:
    get:
      tags:
      - Settings
      summary: Show Setting
      description: 'Returns a single settings group by slug as a flat JSON object
        of its fields.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        **Slug `general`** includes (among others):

        - `connectivity_alert_sound_enabled` (boolean, default `false`) — play a repeating
        audio alert on the device when the app loses connection to the server, and
        a confirmation tone when restored.


        Authentication: Requires Bearer token.'
      parameters:
      - name: slug
        in: path
        schema:
          type: string
        required: true
        description: Setting slug
        example: default_warehouse_id
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 Success
                  value:
                    data:
                      slug: default_warehouse_id
                      value: '2'
                      label: Default Warehouse
                example-1:
                  summary: 200 Success (general)
                  value:
                    timezone: America/New_York
                    date_format: MM/DD/YYYY
                    weight_unit: lb
                    dimension_unit: in
                    fulfill_on_mapped_shipping_method: false
                    auto_dispatch_excluded_shipping_methods: null
                    blemished_sku_pattern: RETURN-{{sku}}-{{date:YYYYMMDD}}
                    use_blemished_sku_pattern: false
                    asn_cc_email: null
                    connectivity_alert_sound_enabled: false
                    asn_file_format: csv
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-session-only: true
      operationId: get-api-v2-settings-slug
    put:
      tags:
      - Settings
      summary: Update Setting
      description: 'Updates a single setting by slug. Body shape varies per slug —
        for simple settings the body is `{"value": ...}`; for grouped settings (e.g.
        `purchase-order`, `forecasting`, `general`) the body is a flat object of allowed
        keys.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        **Slug `purchase-order`** accepts:

        - `cc_outgoing_email` (string|null, max 500) — comma-separated CC list applied
        to outgoing PO emails.


        **Slug `general`** accepts (validated keys):

        - `connectivity_alert_sound_enabled` (boolean) — play a repeating audio alert
        on the device when the app loses connection to the server, and a confirmation
        tone when restored. Non-boolean values are rejected with 422.


        Authentication: Requires Bearer token.


        **Requires permission:** `settings.update`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                value:
                  type: string
              example:
                value: '3'
      parameters:
      - name: slug
        in: path
        schema:
          type: string
        required: true
        description: Setting slug
        example: default_warehouse_id
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 Success
                  value:
                    data:
                      slug: default_warehouse_id
                      value: '3'
                      label: Default Warehouse
                example-1:
                  summary: 200 Success (general — connectivity alert sound)
                  value:
                    timezone: America/New_York
                    date_format: MM/DD/YYYY
                    weight_unit: lb
                    dimension_unit: in
                    fulfill_on_mapped_shipping_method: false
                    auto_dispatch_excluded_shipping_methods: null
                    blemished_sku_pattern: RETURN-{{sku}}-{{date:YYYYMMDD}}
                    use_blemished_sku_pattern: false
                    asn_cc_email: null
                    connectivity_alert_sound_enabled: true
                    asn_file_format: csv
        '422':
          description: Unprocessable Entity
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      connectivity_alert_sound_enabled:
                        type: array
                        items:
                          type: string
                example:
                  message: The connectivity alert sound enabled field must be true
                    or false.
                  errors:
                    connectivity_alert_sound_enabled:
                    - The connectivity alert sound enabled field must be true or false.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-session-only: true
      operationId: put-api-v2-settings-slug
  /api/v2/tracked-job-logs:
    get:
      tags:
      - Tracked Job Logs
      summary: List Tracked Job Logs
      description: 'Returns a paginated list of tracked job logs.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: per_page
        in: query
        schema:
          type: integer
        example: '10'
        description: Results per page (default 10).
      - name: page
        in: query
        schema:
          type: integer
        example: '1'
        description: Page number (default 1).
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        job_name:
                          type: string
                        status:
                          type: string
                        progress:
                          type: integer
                        total:
                          type: integer
                        results:
                          type: object
                          properties:
                            created:
                              type: integer
                            updated:
                              type: integer
                            failed:
                              type: integer
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 88
                    job_name: 'Import Products: products.csv'
                    status: completed
                    progress: 100
                    total: 100
                    results:
                      created: 96
                      updated: 2
                      failed: 2
                    created_at: '2024-03-20T10:00:00.000000Z'
                    updated_at: '2024-03-20T10:05:00.000000Z'
                  current_page: 1
                  last_page: 5
                  per_page: 10
                  total: 42
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: get-api-v2-tracked-job-logs
  /api/v2/tracked-job-logs/active:
    get:
      tags:
      - Tracked Job Logs
      summary: List Active Tracked Job Logs
      description: 'Returns all currently active (running or pending) tracked job
        logs. Used by the tracked job log endpoints to poll for running jobs.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        job_name:
                          type: string
                        status:
                          type: string
                        progress:
                          type: integer
                        total:
                          type: integer
                        results:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                        updated_at:
                          type: string
                example:
                  data:
                  - id: 92
                    job_name: 'Sync Shopify Orders: My Store'
                    status: processing
                    progress: 45
                    total: 200
                    results: null
                    created_at: '2024-03-20T10:10:00.000000Z'
                    updated_at: '2024-03-20T10:10:30.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: get-api-v2-tracked-job-logs-active
  /api/v2/tracked-job-logs/{trackedJobLog}/cancel:
    post:
      tags:
      - Tracked Job Logs
      summary: Cancel Tracked Job
      description: 'Requests cancellation of a running tracked job. The job will stop
        at the next cancellation checkpoint.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: trackedJobLog
        in: path
        schema:
          type: integer
        required: true
        description: Tracked Job Log ID
        example: '92'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      status:
                        type: string
                example:
                  message: Job cancellation requested.
                  data:
                    id: 92
                    status: cancelling
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-session-only: true
      operationId: post-api-v2-tracked-job-logs-trackedjoblog-cancel
  /api/v2/tracked-job-logs/{trackedJobLog}/retry:
    post:
      tags:
      - Tracked Job Logs
      summary: Retry Tracked Job
      description: 'Retries a failed tracked job.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: trackedJobLog
        in: path
        schema:
          type: integer
        required: true
        description: Tracked Job Log ID
        example: '88'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      status:
                        type: string
                example:
                  message: Job queued for retry.
                  data:
                    id: 95
                    status: pending
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-session-only: true
      operationId: post-api-v2-tracked-job-logs-trackedjoblog-retry
  /api/v2/suppliers:
    get:
      tags:
      - Suppliers
      summary: List Suppliers
      description: 'List all suppliers with list support. Supports filtering, sorting,
        and pagination.


        :::info[Required scope: `suppliers:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token. Requires IsPowerUserAccess middleware.


        Sort fields: name, email, company_name, leadtime, created_at, updated_at,
        archived_at.'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        description: 'Page number (default: 1)'
        example: '1'
      - name: limit
        in: query
        schema:
          type: integer
        description: 'Items per page (default: 10)'
        example: '10'
      - name: search
        in: query
        schema:
          type: string
        description: Search by supplier name, email, company name
      - name: sort
        in: query
        schema:
          type: string
        description: Sort field. Prefix with - for descending (e.g. -name, created_at,
          leadtime)
      - name: archived
        in: query
        schema:
          type: integer
        description: 0 = active only, 1 = archived only
        example: '0'
      - name: included[]
        in: query
        schema:
          type: string
        description: Columns to include in response
      - name: excluded[]
        in: query
        schema:
          type: string
        description: Columns to exclude from response
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        company_name:
                          type: string
                        email:
                          type: string
                        primary_contact_name:
                          type: string
                        purchase_order_email:
                          type: string
                        messaging_phone:
                          type: string
                        website:
                          type: string
                        leadtime:
                          type: integer
                        minimum_order_quantity:
                          type: integer
                        target_stock_days:
                          type: integer
                        minimum_purchase_order:
                          type: number
                        purchase_order_format:
                          type: string
                          nullable: true
                        po_processing_method:
                          type: string
                        auto_fulfill_dropship:
                          type: boolean
                        auto_submit_dropship_po:
                          type: boolean
                        auto_generate_backorder_po:
                          type: boolean
                        auto_submit_backorder_po:
                          type: boolean
                        auto_split_backorder_po_by_brand:
                          type: boolean
                        auto_receive_backorder_po:
                          type: boolean
                        default_warehouse_id:
                          type: integer
                        default_store_id:
                          type: string
                          nullable: true
                        default_tax_rate_id:
                          type: string
                          nullable: true
                        default_payment_term_id:
                          type: string
                          nullable: true
                        wire_instructions:
                          type: string
                        wire_instructions_verified_at:
                          type: string
                        timezone:
                          type: string
                        products_count:
                          type: integer
                        address:
                          type: object
                          properties:
                            id:
                              type: integer
                            label:
                              type: string
                            address1:
                              type: string
                            city:
                              type: string
                            zip:
                              type: string
                            country:
                              type: string
                            country_code:
                              type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                        archived_at:
                          type: string
                          nullable: true
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 1
                    name: Acme Supplier
                    company_name: Acme Wholesale Co
                    email: orders@acmewholesale.com
                    primary_contact_name: Bob Johnson
                    purchase_order_email: po@acmewholesale.com
                    messaging_phone: '+15551234567'
                    website: https://acmewholesale.com
                    leadtime: 7
                    minimum_order_quantity: 10
                    target_stock_days: 30
                    minimum_purchase_order: 500.0
                    purchase_order_format: null
                    po_processing_method: email
                    auto_fulfill_dropship: false
                    auto_submit_dropship_po: false
                    auto_generate_backorder_po: false
                    auto_submit_backorder_po: false
                    auto_split_backorder_po_by_brand: false
                    auto_receive_backorder_po: false
                    default_warehouse_id: 2
                    default_store_id: null
                    default_tax_rate_id: null
                    default_payment_term_id: null
                    wire_instructions: 'Beneficiary: Acme Wholesale Co

                      Bank: Example Bank

                      Routing: 021000021

                      Account: 12345678'
                    wire_instructions_verified_at: '2026-07-10T04:00:00.000000Z'
                    timezone: Australia/Sydney
                    products_count: 45
                    address:
                      id: 3
                      label: Default
                      address1: 100 Supplier Lane
                      city: Sydney
                      zip: '2000'
                      country: Australia
                      country_code: AU
                    created_at: '2024-01-01T00:00:00.000000Z'
                    updated_at: '2024-01-15T09:00:00.000000Z'
                    archived_at: null
                  current_page: 1
                  last_page: 3
                  per_page: 10
                  total: 28
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: suppliers:read
      operationId: get-api-v2-suppliers
  /api/v2/suppliers/{supplier}:
    get:
      tags:
      - Suppliers
      summary: Show Supplier
      description: 'Returns a single supplier. The response includes the supplier''s
        address, default payment term, default shipping method, default incoterm,
        and warehouses (each with its address) by default.


        :::info[Required scope: `suppliers:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Use the `with` query parameter (comma-separated) to include additional relations:
        `pricingTiers` (also aliased as `pricing`), `defaultStore`, `defaultIncoterm`,
        `wireInstructionsVerifiedBy`, `customFieldValues`. Passing `customFieldValues`
        adds `custom_field_values` to the response — each stored custom-field value
        with its field metadata (`custom_field_id`, `name`, `slug`, `field_type`,
        `options`, `description`, `is_visible_in_details`). Pass `bill_stats` to include
        bill activity statistics for the supplier.'
      parameters:
      - name: supplier
        in: path
        schema:
          type: integer
        required: true
        description: Supplier ID
        example: '3'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      email:
                        type: string
                      phone:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 3
                    name: Global Supplies Inc
                    email: orders@globalsupplies.com
                    phone: +1-555-0200
                    created_at: '2023-01-10T08:00:00.000000Z'
                    updated_at: '2024-02-01T10:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: suppliers:read
      operationId: get-api-v2-suppliers-supplier
  /api/v2/warehouses:
    get:
      tags:
      - Warehouses
      summary: List Warehouses
      description: 'Returns all warehouses.


        :::info[Required scope: `warehouses:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Contract-manufacturer warehouses are direct warehouses with subtype = "contractor"
        and a non-null contractor_supplier_id (the linked supplier). Their stock is
        real owned inventory, but they are excluded from channel available-to-sell
        and are never auto-routed for fulfillment (auto_routing_enabled is always
        false).'
      parameters: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        display_name:
                          type: string
                        type:
                          type: string
                        subtype:
                          type: string
                          nullable: true
                        contractor_supplier_id:
                          type: string
                          nullable: true
                        supplier_id:
                          type: string
                          nullable: true
                        supplier_name:
                          type: string
                          nullable: true
                        integration_instance_id:
                          type: string
                          nullable: true
                        country_code:
                          type: string
                        address_id:
                          type: integer
                        order_fulfillment:
                          type: string
                        nominal_code_id:
                          type: string
                          nullable: true
                        nominal_code_name:
                          type: string
                          nullable: true
                        dropship_enabled:
                          type: boolean
                        direct_returns:
                          type: boolean
                        customer_returns:
                          type: boolean
                        auto_routing_enabled:
                          type: boolean
                        auto_dispatch_enabled:
                          type: boolean
                        partial_dispatch_enabled:
                          type: boolean
                        archived_at:
                          type: string
                          nullable: true
                        is_archivable:
                          type: boolean
                        archive_blocked_reason:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                        updated_at:
                          type: string
                        city:
                          type: string
                        province:
                          type: string
                        country:
                          type: string
                        zip:
                          type: string
                  current_page:
                    type: integer
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 2
                    name: Main Warehouse
                    display_name: Main Warehouse
                    type: direct
                    subtype: null
                    contractor_supplier_id: null
                    supplier_id: null
                    supplier_name: null
                    integration_instance_id: null
                    country_code: US
                    address_id: 14
                    order_fulfillment: auto
                    nominal_code_id: null
                    nominal_code_name: null
                    dropship_enabled: false
                    direct_returns: true
                    customer_returns: true
                    auto_routing_enabled: true
                    auto_dispatch_enabled: false
                    partial_dispatch_enabled: false
                    archived_at: null
                    is_archivable: true
                    archive_blocked_reason: null
                    created_at: '2026-01-01T00:00:00.000000Z'
                    updated_at: '2026-06-01T00:00:00.000000Z'
                    city: Austin
                    province: Texas
                    country: United States
                    zip: '78701'
                  - id: 9
                    name: Acme Assembly Co (Contractor)
                    display_name: Acme Assembly Co (Contractor)
                    type: direct
                    subtype: contractor
                    contractor_supplier_id: 12
                    supplier_id: null
                    supplier_name: null
                    integration_instance_id: null
                    country_code: US
                    address_id: 31
                    order_fulfillment: manual
                    nominal_code_id: null
                    nominal_code_name: null
                    dropship_enabled: false
                    direct_returns: false
                    customer_returns: false
                    auto_routing_enabled: false
                    auto_dispatch_enabled: false
                    partial_dispatch_enabled: false
                    archived_at: null
                    is_archivable: true
                    archive_blocked_reason: null
                    created_at: '2026-03-15T00:00:00.000000Z'
                    updated_at: '2026-06-01T00:00:00.000000Z'
                    city: null
                    province: null
                    country: null
                    zip: null
                  current_page: 1
                  first_page_url: https://example.test/api/v2/warehouses?page=1
                  from: 1
                  last_page: 1
                  last_page_url: https://example.test/api/v2/warehouses?page=1
                  links: []
                  next_page_url: null
                  path: https://example.test/api/v2/warehouses
                  per_page: 10
                  prev_page_url: null
                  to: 2
                  total: 2
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: warehouses:read
      operationId: get-api-v2-warehouses
  /api/v2/warehouses/{warehouse}:
    get:
      tags:
      - Warehouses
      summary: Show Warehouse
      description: 'Returns a single warehouse.


        :::info[Required scope: `warehouses:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Contract-manufacturer warehouses are direct warehouses with subtype = "contractor"
        and a non-null contractor_supplier_id (the linked supplier). Their stock is
        real owned inventory, but they are excluded from channel available-to-sell
        and are never auto-routed for fulfillment (auto_routing_enabled is always
        false).'
      parameters:
      - name: warehouse
        in: path
        schema:
          type: integer
        required: true
        description: Warehouse ID
        example: '2'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      display_name:
                        type: string
                      type:
                        type: string
                      subtype:
                        type: string
                        nullable: true
                      contractor_supplier_id:
                        type: string
                        nullable: true
                      supplier_id:
                        type: string
                        nullable: true
                      supplier_name:
                        type: string
                        nullable: true
                      integration_instance_id:
                        type: string
                        nullable: true
                      country_code:
                        type: string
                      address_id:
                        type: integer
                      order_fulfillment:
                        type: string
                      nominal_code_id:
                        type: string
                        nullable: true
                      nominal_code_name:
                        type: string
                        nullable: true
                      dropship_enabled:
                        type: boolean
                      direct_returns:
                        type: boolean
                      customer_returns:
                        type: boolean
                      auto_routing_enabled:
                        type: boolean
                      auto_dispatch_enabled:
                        type: boolean
                      partial_dispatch_enabled:
                        type: boolean
                      archived_at:
                        type: string
                        nullable: true
                      is_archivable:
                        type: boolean
                      archive_blocked_reason:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      city:
                        type: string
                      province:
                        type: string
                      country:
                        type: string
                      zip:
                        type: string
                example:
                  data:
                    id: 2
                    name: Main Warehouse
                    display_name: Main Warehouse
                    type: direct
                    subtype: null
                    contractor_supplier_id: null
                    supplier_id: null
                    supplier_name: null
                    integration_instance_id: null
                    country_code: US
                    address_id: 14
                    order_fulfillment: auto
                    nominal_code_id: null
                    nominal_code_name: null
                    dropship_enabled: false
                    direct_returns: true
                    customer_returns: true
                    auto_routing_enabled: true
                    auto_dispatch_enabled: false
                    partial_dispatch_enabled: false
                    archived_at: null
                    is_archivable: true
                    archive_blocked_reason: null
                    created_at: '2026-01-01T00:00:00.000000Z'
                    updated_at: '2026-06-01T00:00:00.000000Z'
                    city: Austin
                    province: Texas
                    country: United States
                    zip: '78701'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: warehouses:read
      operationId: get-api-v2-warehouses-warehouse
  /api/v2/attribute-groups:
    get:
      tags:
      - Reference Data (Read-Only)
      summary: List Attribute Groups
      description: 'Returns all attribute groups.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        created_at:
                          type: string
                example:
                  data:
                  - id: 1
                    name: Physical Attributes
                    created_at: '2024-01-01T00:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: get-api-v2-attribute-groups
  /api/v2/attributes:
    get:
      tags:
      - Reference Data (Read-Only)
      summary: List Attributes
      description: 'Returns all product attributes.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        attribute_group_id:
                          type: integer
                        type:
                          type: string
                example:
                  data:
                  - id: 1
                    name: Color
                    attribute_group_id: 1
                    type: text
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: get-api-v2-attributes
  /api/v2/brands:
    get:
      tags:
      - Reference Data (Read-Only)
      summary: List Brands
      description: 'Returns all product brands.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        created_at:
                          type: string
                example:
                  data:
                  - id: 1
                    name: My Brand
                    created_at: '2024-01-01T00:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: get-api-v2-brands
  /api/v2/categories:
    get:
      tags:
      - Reference Data (Read-Only)
      summary: List Categories
      description: 'Returns all product categories.


        :::info[Required scope: `products:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        parent_id:
                          type: string
                          nullable: true
                example:
                  data:
                  - id: 1
                    name: Electronics
                    parent_id: null
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: products:read
      operationId: get-api-v2-categories
  /api/v2/csv-templates:
    get:
      tags:
      - Reference Data (Read-Only)
      summary: List CSV Templates
      description: 'Returns all CSV import/export templates.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        entity_type:
                          type: string
                example:
                  data:
                  - id: 1
                    name: Product Import Template
                    entity_type: products
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: get-api-v2-csv-templates
  /api/v2/data-feeds:
    get:
      tags:
      - Reference Data (Read-Only)
      summary: List Data Feeds
      description: 'Returns all data feeds.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        type:
                          type: string
                example:
                  data:
                  - id: 1
                    name: Daily Inventory Feed
                    type: inventory
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: get-api-v2-data-feeds
  /api/v2/financial-alerts:
    get:
      tags:
      - Reference Data (Read-Only)
      summary: List Financial Alerts
      description: 'Returns all financial alerts.


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        type:
                          type: string
                        threshold:
                          type: string
                example:
                  data:
                  - id: 1
                    name: Negative Margin Alert
                    type: margin
                    threshold: '0'
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:read
      operationId: get-api-v2-financial-alerts
  /api/v2/financial-line-types:
    get:
      tags:
      - Reference Data (Read-Only)
      summary: List Financial Line Types
      description: 'Returns all financial line types.


        :::info[Required scope: `settings:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        type:
                          type: string
                example:
                  data:
                  - id: 1
                    name: Revenue
                    type: revenue
                  - id: 2
                    name: COGS
                    type: cogs
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: settings:read
      operationId: get-api-v2-financial-line-types
  /api/v2/incoterms:
    get:
      tags:
      - Reference Data (Read-Only)
      summary: List Incoterms
      description: 'Paginated list of incoterms.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Search: `filter[search]` matches id, code, name, and description.


        Text filters accept operator suffixes: `.is`, `.is_not`, `.contains`, `.does_not_contain`,
        `.starts_with`, `.does_not_start_with`, `.ends_with`, `.does_not_end_with`,
        `.is_one_of`, `.is_not_one_of`, `.is_empty`, `.is_not_empty`. The bare `filter[column]`
        form is an exact match. Filterable columns: code, name, description, transport_mode,
        family. `filter[is_standard.is]` filters on the standard ICC rows. `filter[archived]`
        accepts `only` or `all` to include archived rows.


        Allowed sorts: id, code, name, transport_mode, family, is_standard, created_at,
        updated_at. Prefix with `-` for descending (default: `-id`).


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        code:
                          type: string
                        id:
                          type: integer
                        name:
                          type: string
                        description:
                          type: string
                        transport_mode:
                          type: string
                        family:
                          type: string
                        seller_pays_main_carriage:
                          type: boolean
                        export_cleared_by:
                          type: string
                        import_cleared_by:
                          type: string
                        seller_insurance:
                          type: string
                        risk_transfer_point:
                          type: string
                        is_standard:
                          type: boolean
                        is_deprecated:
                          type: boolean
                        created_at:
                          type: string
                        updated_at:
                          type: string
                        archived_at:
                          type: string
                          nullable: true
                        sort_order:
                          type: integer
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - code: EXW
                    id: 1
                    name: Ex Works
                    description: Ex Works — seller makes goods available at their
                      premises.
                    transport_mode: any
                    family: E
                    seller_pays_main_carriage: true
                    export_cleared_by: seller
                    import_cleared_by: buyer
                    seller_insurance: none
                    risk_transfer_point: At the named place of destination, when goods
                      are ready for unloading.
                    is_standard: true
                    is_deprecated: false
                    created_at: '2026-07-13T10:30:00.000000Z'
                    updated_at: '2026-07-13T10:30:00.000000Z'
                    archived_at: null
                    sort_order: 1
                  - code: FOB
                    id: 2
                    name: Free On Board
                    description: Free On Board — risk passes when goods are on board
                      the vessel.
                    transport_mode: any
                    family: F
                    seller_pays_main_carriage: true
                    export_cleared_by: seller
                    import_cleared_by: buyer
                    seller_insurance: none
                    risk_transfer_point: At the named place of destination, when goods
                      are ready for unloading.
                    is_standard: true
                    is_deprecated: false
                    created_at: '2026-07-13T10:30:00.000000Z'
                    updated_at: '2026-07-13T10:30:00.000000Z'
                    archived_at: null
                    sort_order: 2
                  current_page: 1
                  last_page: 2
                  per_page: 10
                  total: 12
                  from: 1
                  to: 10
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: get-api-v2-incoterms
  /api/v2/nominal-codes:
    get:
      tags:
      - Reference Data (Read-Only)
      summary: List Nominal Codes
      description: 'Returns all nominal codes (accounting chart of accounts codes).


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        code:
                          type: string
                        name:
                          type: string
                example:
                  data:
                  - id: 1
                    code: '4000'
                    name: Sales Revenue
                  - id: 2
                    code: '5000'
                    name: Cost of Goods Sold
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: get-api-v2-nominal-codes
  /api/v2/payment-terms:
    get:
      tags:
      - Reference Data (Read-Only)
      summary: List Payment Terms
      description: 'Returns all payment terms.


        :::info[Required scope: `settings:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        days:
                          type: integer
                example:
                  data:
                  - id: 1
                    name: Net 30
                    days: 30
                  - id: 2
                    name: Net 60
                    days: 60
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: settings:read
      operationId: get-api-v2-payment-terms
  /api/v2/payment-types:
    get:
      tags:
      - Reference Data (Read-Only)
      summary: List Payment Types
      description: 'Returns all payment types.


        :::info[Required scope: `settings:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                example:
                  data:
                  - id: 1
                    name: Credit Card
                  - id: 2
                    name: Bank Transfer
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: settings:read
      operationId: get-api-v2-payment-types
  /api/v2/product-pricing-tiers:
    get:
      tags:
      - Reference Data (Read-Only)
      summary: List Product Pricing Tiers
      description: 'Returns all product pricing tiers.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        discount_percent:
                          type: string
                example:
                  data:
                  - id: 1
                    name: Wholesale
                    discount_percent: '20.00'
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: get-api-v2-product-pricing-tiers
  /api/v2/return-reasons:
    get:
      tags:
      - Returns & RMAs
      summary: List Return Reasons
      description: 'List all return reasons using the standard list interface. Supports
        filtering, sorting, search and pagination.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.


        Sort fields: id, name, created_at, updated_at.'
      parameters:
      - name: archived
        in: query
        schema:
          type: integer
        description: 'Filter by archived status: 0 (active) or 1 (archived). Default:
          0'
        example: '0'
      - name: search
        in: query
        schema:
          type: string
        description: Search return reasons by name
      - name: sort
        in: query
        schema:
          type: string
        description: 'Sort field. Prefix with - for descending. Allowed: id, name,
          created_at, updated_at'
        example: name
      - name: page
        in: query
        schema:
          type: integer
        description: Page number for pagination
        example: '1'
      - name: limit
        in: query
        schema:
          type: integer
        description: Records per page
        example: '25'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                        archived_at:
                          type: string
                          nullable: true
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 1
                    name: Defective Item
                    created_at: '2024-01-01T00:00:00Z'
                    updated_at: '2024-01-01T00:00:00Z'
                    archived_at: null
                  - id: 2
                    name: Wrong Item Shipped
                    created_at: '2024-01-01T00:00:00Z'
                    updated_at: '2024-01-01T00:00:00Z'
                    archived_at: null
                  current_page: 1
                  last_page: 1
                  per_page: 25
                  total: 2
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: get-api-v2-return-reasons
  /api/v2/shipping-methods:
    get:
      tags:
      - Reference Data (Read-Only)
      summary: List Shipping Methods
      description: 'Returns all shipping methods.


        :::info[Required scope: `settings:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                example:
                  data:
                  - id: 1
                    name: Standard Ground
                  - id: 2
                    name: Express 2-Day
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: settings:read
      operationId: get-api-v2-shipping-methods
  /api/v2/stores:
    get:
      tags:
      - Reference Data (Read-Only)
      summary: List Stores
      description: 'Returns all stores (sales channel store integrations).


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        platform:
                          type: string
                example:
                  data:
                  - id: 1
                    name: My Shopify Store
                    platform: shopify
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: get-api-v2-stores
  /api/v2/supplier-pricing-tiers:
    get:
      tags:
      - Reference Data (Read-Only)
      summary: List Supplier Pricing Tiers
      description: 'Returns all supplier pricing tiers.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        discount_percent:
                          type: string
                example:
                  data:
                  - id: 1
                    name: Preferred
                    discount_percent: '10.00'
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: get-api-v2-supplier-pricing-tiers
  /api/v2/tags:
    get:
      tags:
      - Reference Data (Read-Only)
      summary: List Tags
      description: 'Returns all tags.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                example:
                  data:
                  - id: 1
                    name: Bestseller
                  - id: 2
                    name: Seasonal
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: get-api-v2-tags
  /api/v2/tax-rates:
    get:
      tags:
      - Reference Data (Read-Only)
      summary: List Tax Rates
      description: 'Returns all tax rates.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        rate:
                          type: string
                example:
                  data:
                  - id: 1
                    name: Standard Rate
                    rate: '20.00'
                  - id: 2
                    name: Zero Rate
                    rate: '0.00'
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: get-api-v2-tax-rates
  /api/v2/users:
    get:
      tags:
      - Reference Data (Read-Only)
      summary: List Users
      description: 'Returns a paginated list of users for the current tenant, with
        Spatie QueryBuilder filtering and sorting. Includes soft-deleted users.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Tenant scoping: Results are restricted to users who are members of the current
        tenant. The `users` table lives on the central connection and is shared across
        all tenants, so without scoping every tenant''s settings UI would see every
        user in the entire installation.


        Authentication: Requires Bearer token.


        Response notes: Each user includes `roles` (the user''s assigned roles with
        id, name, description, guard_name) and `permissions` (a flattened, de-duplicated
        list of permission names across all assigned roles) — both are always present
        since the endpoint eager-loads roles with their permissions. `features.granular_permissions`
        reflects the per-tenant feature flag; frontends treat anything other than
        `true` as OFF.'
      parameters: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        email:
                          type: string
                        email_verified_at:
                          type: string
                        activated_at:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                        deleted_at:
                          type: string
                          nullable: true
                        is_admin:
                          type: boolean
                        is_power_user:
                          type: boolean
                        is_super_admin:
                          type: boolean
                        features:
                          type: object
                          properties:
                            granular_permissions:
                              type: boolean
                        role:
                          type: string
                        roles:
                          type: array
                          items:
                            type: object
                            properties:
                              id:
                                type: integer
                              name:
                                type: string
                              description:
                                type: string
                              guard_name:
                                type: string
                        permissions:
                          type: array
                          items:
                            type: string
                  current_page:
                    type: integer
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 1
                    name: John Smith
                    email: john@example.com
                    email_verified_at: '2025-01-15T10:00:00.000000Z'
                    activated_at: '2025-01-15T10:00:00.000000Z'
                    created_at: '2025-01-10T09:30:00.000000Z'
                    updated_at: '2025-06-01T14:22:00.000000Z'
                    deleted_at: null
                    is_admin: true
                    is_power_user: false
                    is_super_admin: false
                    features:
                      granular_permissions: false
                    role: Admin
                    roles:
                    - id: 1
                      name: admin
                      description: Full access to all features and settings.
                      guard_name: sanctum
                    permissions:
                    - users.index
                    - users.create
                    - users.update
                    - roles.index
                    - sales_orders.index
                  current_page: 1
                  first_page_url: https://sku2.test/api/v2/users?page=1
                  from: 1
                  last_page: 1
                  last_page_url: https://sku2.test/api/v2/users?page=1
                  links: []
                  next_page_url: null
                  path: https://sku2.test/api/v2/users
                  per_page: 10
                  prev_page_url: null
                  to: 1
                  total: 1
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: get-api-v2-users
  /api/v2/incoterms/{incoterm}:
    get:
      tags:
      - Reference Data (Read-Only)
      summary: Get Incoterm
      description: 'Returns a single incoterm for its detail page, including archived
        rows.


        Authentication: Requires Bearer token.'
      parameters:
      - name: incoterm
        in: path
        schema:
          type: integer
        required: true
        description: Incoterm id
        example: '4'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      code:
                        type: string
                      id:
                        type: integer
                      name:
                        type: string
                      description:
                        type: string
                      transport_mode:
                        type: string
                      family:
                        type: string
                      seller_pays_main_carriage:
                        type: boolean
                      export_cleared_by:
                        type: string
                      import_cleared_by:
                        type: string
                      seller_insurance:
                        type: string
                      risk_transfer_point:
                        type: string
                      is_standard:
                        type: boolean
                      is_deprecated:
                        type: boolean
                      sort_order:
                        type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                example:
                  data:
                    code: FOB
                    id: 4
                    name: Free On Board
                    description: Sea and inland-waterway transport only. The seller
                      clears the goods for export and loads them onto the vessel;
                      risk passes once they are on board.
                    transport_mode: sea_inland
                    family: F
                    seller_pays_main_carriage: false
                    export_cleared_by: seller
                    import_cleared_by: buyer
                    seller_insurance: none
                    risk_transfer_point: Goods on board the vessel at the named port
                      of shipment.
                    is_standard: true
                    is_deprecated: false
                    sort_order: 4
                    created_at: '2026-07-15T06:16:45.000000Z'
                    updated_at: '2026-07-15T06:16:45.000000Z'
                    archived_at: null
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No query results for model.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-v2-incoterms-incoterm
  /api/v2/incoterms/{incoterm}/activity-log:
    get:
      tags:
      - Reference Data (Read-Only)
      summary: Get Incoterm Activity Log
      description: 'Paginated activity history for an incoterm. Surfaces two signals:
        the term''s own events (create, edit, archive, restore) and document assignment
        changes — a purchase or sales order whose incoterm was set to or cleared from
        this term.


        Authentication: Requires Bearer token.'
      parameters:
      - name: incoterm
        in: path
        schema:
          type: integer
        required: true
        description: Incoterm id
        example: '4'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        description:
                          type: string
                        event:
                          type: string
                        subject_type:
                          type: string
                        subject_id:
                          type: integer
                        properties:
                          type: object
                          properties:
                            attributes:
                              type: object
                              properties:
                                sort_order:
                                  type: integer
                            old:
                              type: object
                              properties:
                                sort_order:
                                  type: integer
                        causer_name:
                          type: string
                        created_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - id: 42
                    description: updated
                    event: updated
                    subject_type: Incoterm
                    subject_id: 4
                    properties:
                      attributes:
                        sort_order: 44
                      old:
                        sort_order: 4
                    causer_name: Administrator
                    created_at: '2026-07-15T23:32:35.000000Z'
                  current_page: 1
                  last_page: 1
                  per_page: 15
                  total: 1
                  from: 1
                  to: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-v2-incoterms-incoterm-activity-log
  /api/v2/incoterms/export:
    get:
      tags:
      - Reference Data (Read-Only)
      summary: Export Incoterms
      description: 'Downloads the incoterms reference table as a spreadsheet. Columns:
        code, name, description, transport mode, family, seller pays main carriage,
        export cleared by, import cleared by, seller insurance, risk transfer point,
        standard, deprecated.


        Response is a file download (`text/csv` or the XLSX mime type), not JSON.
        Honors the current `filter[search]` / `filter[archived]` query params.


        `format` must be `csv` or `xlsx` — any other value returns a 422 validation
        error.


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-v2-incoterms-export
  /api/v2/inventory-adjustments:
    get:
      tags:
      - Inventory Adjustments
      summary: List Inventory Adjustments
      description: 'Returns a paginated list of inventory adjustments.


        :::info[Required scope: `inventory:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: per_page
        in: query
        schema:
          type: integer
        example: '10'
        description: Results per page (default 10).
      - name: page
        in: query
        schema:
          type: integer
        example: '1'
        description: Page number (default 1).
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        product_id:
                          type: integer
                        warehouse_id:
                          type: integer
                        quantity:
                          type: integer
                        reason:
                          type: string
                        created_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 1
                    product_id: 15
                    warehouse_id: 2
                    quantity: -5
                    reason: Damaged
                    created_at: '2024-03-10T10:00:00.000000Z'
                  current_page: 1
                  last_page: 10
                  per_page: 10
                  total: 95
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: inventory:read
      operationId: get-api-v2-inventory-adjustments
    post:
      tags:
      - Inventory Adjustments
      summary: Search Inventory Adjustments
      description: 'Returns the same paginated list of inventory adjustments as the
        GET version of this endpoint, but accepts filters as a JSON request body instead
        of the query string. Use this POST variant when the filter set is too large
        or too complex to fit in a URL.


        :::info[Required scope: `inventory:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Provide advanced filters under `filter_groups`, a tree of conditions combined
        with a `conjunction` of `and` or `or`. Each condition names a `column`, an
        `operator`, and a `value`. A free-text `search` term matches against id, notes,
        SKU, product name, and warehouse.


        Text columns (`notes`, `sku`, `product_name`, `warehouse`) accept: is, is_not,
        contains, does_not_contain, starts_with, ends_with, is_empty, is_not_empty,
        is_one_of, is_not_one_of.

        Numeric and date columns (`id`, `quantity`, `adjustment_date`, `created_at`,
        `updated_at`) accept: is, is_not, greater_than, greater_than_or_equal, less_than,
        less_than_or_equal, between, is_empty, is_not_empty. The `direction` filter
        accepts `positive` or `negative`, `is_correction` accepts `yes` or `no`, and
        `archived` toggles archived records.


        Sortable columns (via `sort`, prefix with `-` for descending): id, adjustment_date,
        quantity, archived_at, created_at, updated_at. Results default to `-created_at`.
        `per_page` is capped at 100.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                per_page:
                  type: integer
                page:
                  type: integer
                sort:
                  type: string
                filter_groups:
                  type: object
                  properties:
                    conjunction:
                      type: string
                    children:
                      type: array
                      items:
                        type: object
                        properties:
                          type:
                            type: string
                          condition:
                            type: object
                            properties:
                              column:
                                type: string
                              operator:
                                type: string
                              value:
                                type: string
              example:
                per_page: 25
                page: 1
                sort: -adjustment_date
                filter_groups:
                  conjunction: and
                  children:
                  - type: condition
                    condition:
                      column: direction
                      operator: is
                      value: negative
                  - type: condition
                    condition:
                      column: adjustment_date
                      operator: between
                      value:
                      - '2026-06-01'
                      - '2026-06-30'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        adjustment_date:
                          type: string
                        product_id:
                          type: integer
                        sku:
                          type: string
                        product_name:
                          type: string
                        stock_uom_code:
                          type: string
                        is_lot_tracked:
                          type: boolean
                        lot_tracking_method:
                          type: string
                          nullable: true
                        product_average_cost:
                          type: number
                        quantity:
                          type: integer
                        warehouse:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        notes:
                          type: string
                        reason:
                          type: string
                        is_correction:
                          type: boolean
                        type:
                          type: object
                          properties:
                            link_type:
                              type: string
                            link_id:
                              type: integer
                            parent_link_type:
                              type: string
                              nullable: true
                            parent_link_id:
                              type: string
                              nullable: true
                        reference:
                          type: integer
                        unit_cost:
                          type: number
                        archived_at:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  per_page:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                  last_page:
                    type: integer
                  total:
                    type: integer
                  next_page_url:
                    type: string
                  prev_page_url:
                    type: string
                    nullable: true
                example:
                  data:
                  - id: 55231
                    adjustment_date: '2026-06-15T00:00:00.000000Z'
                    product_id: 3312
                    sku: WIDGET-BLUE-01
                    product_name: Blue Widget
                    stock_uom_code: EA
                    is_lot_tracked: false
                    lot_tracking_method: null
                    product_average_cost: 13.75
                    quantity: -4
                    warehouse:
                      id: 2
                      name: Main Warehouse
                    notes: Damaged in receiving
                    reason: damaged
                    is_correction: false
                    type:
                      link_type: App\Models\InventoryAdjustment
                      link_id: 55231
                      parent_link_type: null
                      parent_link_id: null
                    reference: 55231
                    unit_cost: 13.75
                    archived_at: null
                    created_at: '2026-06-15T08:41:00.000000Z'
                    updated_at: '2026-06-15T08:41:00.000000Z'
                  current_page: 1
                  per_page: 25
                  from: 1
                  to: 1
                  last_page: 9
                  total: 214
                  next_page_url: https://api.example.com/api/v2/inventory-adjustments?page=2
                  prev_page_url: null
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: inventory:write
      operationId: post-api-v2-inventory-adjustments
  /api/v2/inventory-adjustments/export:
    get:
      tags:
      - Inventory Adjustments
      summary: Export Inventory Adjustments
      description: 'Exports inventory adjustments as a CSV file.


        :::info[Required scope: `inventory:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `inventory.export`'
      parameters: []
      responses:
        '200':
          description: OK
          content:
            text/plain:
              schema:
                type: string
                example: 'id,product_id,warehouse_id,quantity,reason,created_at

                  1,15,2,-5,Damaged,2024-03-10 10:00:00'
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: inventory:read
      operationId: get-api-v2-inventory-adjustments-export
  /api/v2/inventory-adjustments/{inventoryAdjustment}:
    get:
      tags:
      - Inventory Adjustments
      summary: Show Inventory Adjustment
      description: 'Returns a single inventory adjustment.


        :::info[Required scope: `inventory:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: inventoryAdjustment
        in: path
        schema:
          type: integer
        required: true
        description: Inventory Adjustment ID
        example: '1'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      product_id:
                        type: integer
                      warehouse_id:
                        type: integer
                      quantity:
                        type: integer
                      reason:
                        type: string
                      created_at:
                        type: string
                example:
                  data:
                    id: 1
                    product_id: 15
                    warehouse_id: 2
                    quantity: -5
                    reason: Damaged
                    created_at: '2024-03-10T10:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: inventory:read
      operationId: get-api-v2-inventory-adjustments-inventoryadjustment
  /api/v2/inventory-movements:
    get:
      tags:
      - Inventory Movements
      summary: List Inventory Movements
      description: 'Returns a paginated list of inventory movements.


        :::info[Required scope: `inventory:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: per_page
        in: query
        schema:
          type: integer
        example: '10'
        description: Results per page (default 10).
      - name: page
        in: query
        schema:
          type: integer
        example: '1'
        description: Page number (default 1).
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        type:
                          type: string
                        quantity:
                          type: integer
                        inventory_status:
                          type: string
                        warehouse_id:
                          type: integer
                        product_id:
                          type: integer
                        created_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 201
                    type: fulfillment
                    quantity: -5
                    inventory_status: committed
                    warehouse_id: 2
                    product_id: 15
                    created_at: '2024-03-12T11:00:00.000000Z'
                  current_page: 1
                  last_page: 50
                  per_page: 10
                  total: 498
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: inventory:read
      operationId: get-api-v2-inventory-movements
    post:
      tags:
      - Inventory Movements
      summary: Search Inventory Movements
      description: 'Returns the same paginated inventory movement audit trail as the
        GET version of this endpoint, but accepts filters as a JSON request body instead
        of the query string. Use this POST variant when the filter set is too large
        or too complex to fit in a URL.


        :::info[Required scope: `inventory:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Provide advanced filters under `filter_groups`, a tree of conditions combined
        with a `conjunction` of `and` or `or`. Each condition names a `column`, an
        `operator`, and a `value`. A free-text `search` term matches against id, SKU,
        product name, warehouse, and reference.


        Text columns (`type`, `inventory_status`, `link_type`, `reference`, `product_name`,
        `sku`) accept: is, is_not, contains, does_not_contain, starts_with, ends_with,
        is_empty, is_not_empty, is_one_of, is_not_one_of.

        Numeric and date columns (`id`, `quantity`, `inventory_movement_date`, `created_at`,
        `updated_at`) accept: is, is_not, greater_than, greater_than_or_equal, less_than,
        less_than_or_equal, between, is_empty, is_not_empty. The `warehouse` filter
        narrows by warehouse.


        Sortable columns (via `sort`, prefix with `-` for descending): id, inventory_movement_date,
        quantity, type, inventory_status, reference, created_at, updated_at, warehouse_name,
        sku, product_name. Results default to `-inventory_movement_date`.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                per_page:
                  type: integer
                page:
                  type: integer
                sort:
                  type: string
                filter_groups:
                  type: object
                  properties:
                    conjunction:
                      type: string
                    children:
                      type: array
                      items:
                        type: object
                        properties:
                          type:
                            type: string
                          condition:
                            type: object
                            properties:
                              column:
                                type: string
                              operator:
                                type: string
                              value:
                                type: array
                                items:
                                  type: string
              example:
                per_page: 25
                page: 1
                sort: -inventory_movement_date
                filter_groups:
                  conjunction: and
                  children:
                  - type: condition
                    condition:
                      column: type
                      operator: is_one_of
                      value:
                      - sale
                      - adjustment
                  - type: condition
                    condition:
                      column: quantity
                      operator: less_than
                      value: 0
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        inventory_movement_date:
                          type: string
                        product_id:
                          type: integer
                        sku:
                          type: string
                        barcode:
                          type: string
                        product_name:
                          type: string
                        stock_uom_code:
                          type: string
                        type:
                          type: object
                          properties:
                            name:
                              type: string
                            link_type:
                              type: string
                            link_id:
                              type: integer
                            parent_link_id:
                              type: integer
                            detail_link_id:
                              type: string
                              nullable: true
                        inventory_status:
                          type: string
                        quantity:
                          type: integer
                        warehouse:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        layer:
                          type: object
                          properties:
                            fifo_layer_id:
                              type: integer
                            name:
                              type: string
                        fifo_layer_id:
                          type: integer
                        reference:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  per_page:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                  last_page:
                    type: integer
                  total:
                    type: integer
                  next_page_url:
                    type: string
                  prev_page_url:
                    type: string
                    nullable: true
                example:
                  data:
                  - id: 442190
                    inventory_movement_date: '2026-06-30T09:15:00.000000Z'
                    product_id: 3312
                    sku: WIDGET-BLUE-01
                    barcode: '8801234567890'
                    product_name: Blue Widget
                    stock_uom_code: EA
                    type:
                      name: sale
                      link_type: App\Models\SalesOrderLine
                      link_id: 88231
                      parent_link_id: 6021
                      detail_link_id: null
                    inventory_status: available
                    quantity: -3
                    warehouse:
                      id: 2
                      name: Main Warehouse
                    layer:
                      fifo_layer_id: 90312
                      name: PO-1042
                    fifo_layer_id: 90312
                    reference: SO-6021
                    created_at: '2026-06-30T09:15:00.000000Z'
                    updated_at: '2026-06-30T09:15:00.000000Z'
                  current_page: 1
                  per_page: 25
                  from: 1
                  to: 1
                  last_page: 120
                  total: 2984
                  next_page_url: https://api.example.com/api/v2/inventory-movements?page=2
                  prev_page_url: null
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: inventory:write
      operationId: post-api-v2-inventory-movements
  /api/v2/inventory-movements/list/export:
    get:
      tags:
      - Inventory Movements
      summary: Export Inventory Movements
      description: 'Exports inventory movements as an XLSX or CSV file download. Reuses
        the same Spatie QueryBuilder filters and sorts as the List Inventory Movements
        endpoint when scope=filtered.


        :::info[Required scope: `inventory:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Scopes:

        - all: ignore active filters/sort and export every record

        - filtered (default): apply the current filter/sort/search query params

        - current_page: export the rows on the current page (matches the visible table)

        - selected: export only the IDs supplied via the ids query param


        The response is a binary file (xlsx or csv); Content-Type is application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
        or text/csv. Authentication: Requires Bearer token.


        **Requires permission:** `inventory.export`'
      parameters:
      - name: format
        in: query
        schema:
          type: string
        description: 'Output format: xlsx (default) or csv'
        example: xlsx
      - name: scope
        in: query
        schema:
          type: string
        description: 'Export scope: all (ignore filters), filtered (apply current
          filters/search/sort), current_page (rows on the current page), selected
          (specific IDs via the ids parameter)'
        example: filtered
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: inventory:read
      operationId: get-api-v2-inventory-movements-list-export
  /api/v2/listings:
    get:
      tags:
      - Listings
      summary: List Listings
      description: 'Returns a paginated list of channel listings (products listed
        on sales channels).


        :::info[Required scope: `products:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: per_page
        in: query
        schema:
          type: integer
        example: '10'
        description: Results per page (default 10).
      - name: page
        in: query
        schema:
          type: integer
        example: '1'
        description: Page number (default 1).
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        product_id:
                          type: integer
                        sales_channel_id:
                          type: integer
                        channel_product_id:
                          type: string
                        status:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 1
                    product_id: 15
                    sales_channel_id: 5
                    channel_product_id: shopify-12345
                    status: active
                  current_page: 1
                  last_page: 20
                  per_page: 10
                  total: 195
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: products:read
      operationId: get-api-v2-listings
  /api/v2/listings/summary:
    get:
      tags:
      - Listings
      summary: Listings Summary
      description: 'Returns summary counts for listings by status.


        :::info[Required scope: `products:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      total:
                        type: integer
                      active:
                        type: integer
                      archived:
                        type: integer
                example:
                  data:
                    total: 195
                    active: 180
                    archived: 15
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: products:read
      operationId: get-api-v2-listings-summary
  /api/v2/listings/bulk-archive:
    post:
      tags:
      - Listings
      summary: Bulk Archive Listings
      description: 'Archives multiple listings.


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1
                - 2
                - 3
      parameters: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 2 listings archived successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: products:write
      operationId: post-api-v2-listings-bulk-archive
  /api/v2/listings/bulk-unarchive:
    post:
      tags:
      - Listings
      summary: Bulk Unarchive Listings
      description: 'Unarchives multiple listings.


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1
                - 2
                - 3
      parameters: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 2 listings unarchived successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: products:write
      operationId: post-api-v2-listings-bulk-unarchive
  /api/v2/listings/bulk-edit-fetch:
    get:
      tags:
      - Listings
      summary: Fetch Listings for Bulk Edit
      description: 'Fetches a specific set of listings by id together with their current
        inventory settings, ready to populate a bulk-edit form. Pass the listing ids
        as a comma-separated string. For each listing you get its SKU, title, FBA
        flag, integration instance name, master-of-stock source, selected warehouse
        ids, fulfillment latency and whether it inherits settings from its integration.


        :::info[Required scope: `products:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: ids
        in: query
        schema:
          type: string
        description: Comma-separated listing ids to fetch
        example: 1201,1202,1203
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        listing_sku:
                          type: string
                        title:
                          type: string
                        is_fba:
                          type: boolean
                        integration_instance_name:
                          type: string
                        master_of_stock:
                          type: string
                        warehouse_ids:
                          type: array
                          items:
                            type: integer
                        fulfillment_latency:
                          type: integer
                        inherit_settings:
                          type: boolean
                  status:
                    type: string
                example:
                  data:
                  - id: 1201
                    listing_sku: ACME-WIDGET-BLU
                    title: Acme Widget - Blue
                    is_fba: false
                    integration_instance_name: Shopify US
                    master_of_stock: sku.io
                    warehouse_ids:
                    - 3
                    - 7
                    fulfillment_latency: 2
                    inherit_settings: false
                  - id: 1202
                    listing_sku: ACME-WIDGET-RED
                    title: Acme Widget - Red
                    is_fba: false
                    integration_instance_name: Shopify US
                    master_of_stock: null
                    warehouse_ids: []
                    fulfillment_latency: null
                    inherit_settings: true
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: products:read
      operationId: get-api-v2-listings-bulk-edit-fetch
  /api/v2/listings/channel-inventory:
    get:
      tags:
      - Product Listings
      summary: List Channel Inventory
      description: 'Returns paginated channel inventory, aggregated to one row per
        listing across all of that listing''s channel locations. Each row compares
        the quantity calculated by SKU.io (total_sku_quantity) against the quantity
        last reported by the sales channel (total_channel_quantity) and exposes the
        variance between them. Archived listings are excluded.


        :::info[Required scope: `products:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Rows are ordered by listing ID descending; custom sorting is not supported
        on this endpoint.


        Filters: filter[search] (listing SKU / title / channel listing ID / product
        SKU; numeric values also match the listing ID), filter[integration_instance_id],
        filter[integration_id], filter[is_fba] (true/false), filter[is_sku_recalculation_needed]
        (true/false), filter[sync_status] (in_sync, mismatch, never_synced, pending_recalc),
        filter[product_listing_id].


        Pagination: page, per_page (default: 15).


        master_of_stock resolves the effective value: a listing-level override wins,
        otherwise the value is inherited from the channel account''s settings.


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        product_listing_id:
                          type: integer
                        total_sku_quantity:
                          type: integer
                        total_channel_quantity:
                          type: integer
                        total_variance:
                          type: integer
                        location_count:
                          type: integer
                        any_recalc_needed:
                          type: boolean
                        oldest_synced_at:
                          type: string
                        latest_sku_qty_updated:
                          type: string
                        listing_sku:
                          type: string
                        listing_title:
                          type: string
                        sales_channel_listing_id:
                          type: string
                        is_fba:
                          type: boolean
                        master_of_stock:
                          type: string
                        product_id:
                          type: integer
                        product_sku:
                          type: string
                        product_name:
                          type: string
                        integration_id:
                          type: integer
                        integration_name:
                          type: string
                        integration_instance_id:
                          type: integer
                        integration_instance_name:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                    items:
                      type: object
                      properties:
                        url:
                          type: string
                          nullable: true
                        label:
                          type: string
                        active:
                          type: boolean
                  next_page_url:
                    type: string
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 4521
                    product_listing_id: 4521
                    total_sku_quantity: 120
                    total_channel_quantity: 118
                    total_variance: 2
                    location_count: 2
                    any_recalc_needed: false
                    oldest_synced_at: '2026-07-05 14:22:10'
                    latest_sku_qty_updated: '2026-07-06 02:15:44'
                    listing_sku: WIDGET-BLUE-01
                    listing_title: Blue Widget - 2 Pack
                    sales_channel_listing_id: B0B12345XY
                    is_fba: false
                    master_of_stock: sku.io
                    product_id: 42
                    product_sku: WIDGET-BLUE
                    product_name: Blue Widget
                    integration_id: 3
                    integration_name: Amazon
                    integration_instance_id: 7
                    integration_instance_name: Amazon US
                    created_at: '2025-11-02T09:14:33.000000Z'
                    updated_at: '2026-07-06T02:15:44.000000Z'
                  first_page_url: https://example.sku.io/api/v2/listings/channel-inventory?page=1
                  from: 1
                  last_page: 349
                  last_page_url: https://example.sku.io/api/v2/listings/channel-inventory?page=349
                  links:
                  - url: null
                    label: '&laquo; Previous'
                    active: false
                  - url: https://example.sku.io/api/v2/listings/channel-inventory?page=1
                    label: '1'
                    active: true
                  - url: https://example.sku.io/api/v2/listings/channel-inventory?page=2
                    label: Next &raquo;
                    active: false
                  next_page_url: https://example.sku.io/api/v2/listings/channel-inventory?page=2
                  path: https://example.sku.io/api/v2/listings/channel-inventory
                  per_page: 15
                  prev_page_url: null
                  to: 15
                  total: 5231
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: products:read
      operationId: get-api-v2-listings-channel-inventory
  /api/v2/listings/channel-inventory/export:
    get:
      tags:
      - Product Listings
      summary: Export Channel Inventory
      description: 'Streams a CSV file download of channel inventory records (one
        row per listing location, not aggregated per listing). Archived listings are
        excluded.


        :::info[Required scope: `products:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        The response is a file download with Content-Type text/csv and a Content-Disposition
        attachment filename of the form channel-inventory-YYYY-MM-DD.csv.


        Columns: ID, Listing SKU, Listing ID, Title, Product SKU, Product Name, Integration,
        Channel, Location ID, SKU Qty, Channel Qty, Variance, Needs Recalc, FBA, Master
        of Stock, SKU Qty Updated, Last Synced.


        Supported filters: filter[search], filter[integration_instance_id], filter[integration_id],
        filter[sync_status] (in_sync, mismatch, never_synced, pending_recalc).


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: text/csv
            Content-Disposition:
              schema:
                type: string
                example: attachment; filename="channel-inventory-2026-07-06.csv"
          content:
            text/plain:
              schema:
                type: string
                example: 'ID,Listing SKU,Listing ID,Title,Product SKU,Product Name,Integration,Channel,Location
                  ID,SKU Qty,Channel Qty,Variance,Needs Recalc,FBA,Master of Stock,SKU
                  Qty Updated,Last Synced

                  88213,WIDGET-BLUE-01,B0B12345XY,Blue Widget - 2 Pack,WIDGET-BLUE,Blue
                  Widget,Amazon,Amazon US,12345678,120,118,2,No,No,sku.io,2026-07-06
                  02:15:44,2026-07-05 14:22:10

                  '
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: products:read
      operationId: get-api-v2-listings-channel-inventory-export
  /api/v2/listings/channel-inventory/summary:
    get:
      tags:
      - Product Listings
      summary: Get Channel Inventory Summary
      description: 'Returns channel inventory counts grouped by integration, the list
        of connected channel accounts (integration instances) that have at least one
        active listing, and a breakdown of inventory records by sync status.


        :::info[Required scope: `products:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        status_counts fields: in_sync (SKU.io and channel quantities match and no
        recalculation is pending), mismatch (quantities differ or a recalculation
        is pending), never_synced (the channel has never reported a quantity), pending_recalc
        (flagged for quantity recalculation).


        Integrations with listings but no channel inventory records yet (fresh setup)
        still appear with a count of 0. Archived listings are excluded throughout.


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      total:
                        type: integer
                      integrations:
                        type: array
                        items:
                          type: object
                          properties:
                            integration_name:
                              type: string
                            integration_id:
                              type: integer
                            count:
                              type: integer
                      instances:
                        type: array
                        items:
                          type: object
                          properties:
                            integration_instance_id:
                              type: integer
                            integration_instance_name:
                              type: string
                            integration_id:
                              type: integer
                      status_counts:
                        type: object
                        properties:
                          in_sync:
                            type: integer
                          mismatch:
                            type: integer
                          never_synced:
                            type: integer
                          pending_recalc:
                            type: integer
                example:
                  data:
                    total: 5231
                    integrations:
                    - integration_name: Amazon
                      integration_id: 3
                      count: 3120
                    - integration_name: Shopify
                      integration_id: 5
                      count: 1685
                    - integration_name: Walmart
                      integration_id: 9
                      count: 426
                    instances:
                    - integration_instance_id: 7
                      integration_instance_name: Amazon US
                      integration_id: 3
                    - integration_instance_id: 8
                      integration_instance_name: Shopify Main Store
                      integration_id: 5
                    - integration_instance_id: 12
                      integration_instance_name: Walmart US
                      integration_id: 9
                    status_counts:
                      in_sync: 4655
                      mismatch: 310
                      never_synced: 221
                      pending_recalc: 45
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: products:read
      operationId: get-api-v2-listings-channel-inventory-summary
  /api/v2/listings/export:
    get:
      tags:
      - Product Listings
      summary: Export Listings
      description: 'Streams a CSV file download of all non-archived listings across
        every connected sales channel. This endpoint does not accept filters — it
        always exports the full active listing set, ordered by most recently created
        first.


        :::info[Required scope: `products:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        The response is a file download with Content-Type text/csv and a Content-Disposition
        attachment filename of the form listings-YYYY-MM-DD.csv.


        Columns: ID, Listing SKU, Listing ID, Title, Product SKU, Product Name, Integration,
        Channel, Price, Quantity, FBA, Master of Price, Master of Stock, Inherit from
        Integration, Warehouses, Fulfillment Latency (days), Max Rule Type, Max Rule
        Value, Min Rule Type, Min Rule Value, Buffer Stock, ASIN, Shopify Status,
        Walmart WPID, Archived At, Created At, Updated At.


        Warehouse IDs from each listing''s inventory settings are resolved to warehouse
        names.


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: text/csv
            Content-Disposition:
              schema:
                type: string
                example: attachment; filename="listings-2026-07-06.csv"
          content:
            text/plain:
              schema:
                type: string
                example: 'ID,Listing SKU,Listing ID,Title,Product SKU,Product Name,Integration,Channel,Price,Quantity,FBA,Master
                  of Price,Master of Stock,Inherit from Integration,Warehouses,Fulfillment
                  Latency (days),Max Rule Type,Max Rule Value,Min Rule Type,Min Rule
                  Value,Buffer Stock,ASIN,Shopify Status,Walmart WPID,Archived At,Created
                  At,Updated At

                  4521,WIDGET-BLUE-01,B0B12345XY,Blue Widget - 2 Pack,WIDGET-BLUE,Blue
                  Widget,Amazon,Amazon US,24.99,120,No,Inherited,sku.io,No,"Main Warehouse,
                  East Coast FC",2,Fixed Allocation,100,None,,10,B0B12345XY,,,,2025-11-02T09:14:33.000000Z,2026-07-06T02:15:44.000000Z

                  '
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: products:read
      operationId: get-api-v2-listings-export
  /api/v2/listings/inventory-settings-import-template:
    get:
      tags:
      - Product Listings
      summary: Download Inventory Settings Import Template
      description: 'Downloads an XLSX import template for bulk-editing listing inventory
        settings via spreadsheet import.


        :::info[Required scope: `products:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        The workbook contains sample rows (a full settings override, a partial update,
        and a reset-to-inherit example) plus a reference sheet listing the valid values
        for your account: warehouse names, connected channel names, master-of-stock
        values (sku.io, sales_channel, neither), rule types (None, Fixed Allocation,
        % of Available), and up to 50 sample listing SKUs.


        The response is a file download with Content-Type application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
        and a filename of the form listing-inventory-settings-import-template-YYYY-MM-DD.xlsx.


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
            Content-Disposition:
              schema:
                type: string
                example: attachment; filename=listing-inventory-settings-import-template-2026-07-06.xlsx
          content:
            text/plain:
              schema:
                type: string
                example: (binary XLSX file download)
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: products:read
      operationId: get-api-v2-listings-inventory-settings-import-template
  /api/v2/listings/{productListing}/inventory-caches:
    get:
      tags:
      - Product Listings
      summary: List Listing Inventory Caches
      description: 'Returns the per-location channel inventory records for a single
        listing, ordered by channel location ID. Each record compares the quantity
        calculated by SKU.io (sku_quantity) against the quantity last reported by
        the sales channel (sales_channel_quantity) and includes the variance.


        :::info[Required scope: `products:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        location_name is resolved from the channel account''s configured inventory
        locations and is null when the location is not configured there. variance
        is null when the channel has never reported a quantity.


        Authentication: Requires Bearer token.'
      parameters:
      - name: productListing
        in: path
        schema:
          type: integer
        required: true
        description: Product listing ID
        example: '4521'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        sales_channel_location_id:
                          type: string
                        location_name:
                          type: string
                        sku_quantity:
                          type: integer
                        sales_channel_quantity:
                          type: integer
                        variance:
                          type: integer
                        is_sku_recalculation_needed:
                          type: boolean
                        sku_quantity_updated_at:
                          type: string
                        sales_channel_quantity_synced_at:
                          type: string
                example:
                  data:
                  - id: 88213
                    sales_channel_location_id: '12345678'
                    location_name: Default Location
                    sku_quantity: 120
                    sales_channel_quantity: 118
                    variance: 2
                    is_sku_recalculation_needed: false
                    sku_quantity_updated_at: '2026-07-06T02:15:44.000000Z'
                    sales_channel_quantity_synced_at: '2026-07-05T14:22:10.000000Z'
                  - id: 88214
                    sales_channel_location_id: '87654321'
                    location_name: East Coast FC
                    sku_quantity: 45
                    sales_channel_quantity: null
                    variance: null
                    is_sku_recalculation_needed: true
                    sku_quantity_updated_at: '2026-07-06T02:15:44.000000Z'
                    sales_channel_quantity_synced_at: null
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No query results for model.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: products:read
      operationId: get-api-v2-listings-productlisting-inventory-caches
  /api/v2/listings/bulk-edit-inventory-preview:
    post:
      tags:
      - Product Listings
      summary: Preview Bulk Listing Inventory Settings Update
      description: 'Dry run for Bulk Update Listing Inventory Settings. Computes exactly
        which listings would change and what each field''s old and new values would
        be, without applying anything. Use it to validate a bulk update before committing
        it.


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Body fields:

        - ids (required, array of integers) — listing IDs to evaluate

        - inventory_settings (required, object) — the settings that would be applied


        inventory_settings fields (all optional within the object):

        - inherit (boolean) — when true, clears all listing-level overrides so the
        listing inherits settings from its channel account; all other settings fields
        are ignored

        - master_of_stock (string|null) — one of: sku.io, sales_channel, amazon, neither

        - warehouse_ids (array of integers|null) — warehouse IDs used for the listing''s
        available quantity

        - warehouse_action (string) — how warehouse_ids are applied: replace (default),
        add, or clear

        - fulfillment_latency (integer|null, 0-30) — handling time in days

        - max_rule_type (string|null) — one of: None, Fixed Allocation, % of Available

        - max_rule_value (number|null, min 0) — value paired with max_rule_type

        - min_rule_type (string|null) — one of: None, Fixed Allocation, % of Available

        - min_rule_value (number|null, min 0) — value paired with min_rule_type

        - subtract_buffer_stock (integer|null, min 0) — buffer quantity subtracted
        from availability


        FBA listings are excluded from the evaluation (their inventory is managed
        by the fulfillment network); the count of excluded listings is returned as
        skipped_fba. Listings whose settings already match report no changes and are
        not included in the changes array.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
                inventory_settings:
                  type: object
                  properties:
                    inherit:
                      type: boolean
                    master_of_stock:
                      type: string
                    warehouse_ids:
                      type: array
                      items:
                        type: integer
                    warehouse_action:
                      type: string
                    fulfillment_latency:
                      type: integer
                    max_rule_type:
                      type: string
                    max_rule_value:
                      type: integer
                    min_rule_type:
                      type: string
                    min_rule_value:
                      type: string
                      nullable: true
                    subtract_buffer_stock:
                      type: integer
              example:
                ids:
                - 4521
                - 4522
                - 4523
                inventory_settings:
                  inherit: false
                  master_of_stock: sku.io
                  warehouse_ids:
                  - 1
                  - 4
                  warehouse_action: replace
                  fulfillment_latency: 2
                  max_rule_type: Fixed Allocation
                  max_rule_value: 100
                  min_rule_type: None
                  min_rule_value: null
                  subtract_buffer_stock: 10
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      total_listings:
                        type: integer
                      affected_listings:
                        type: integer
                      skipped_fba:
                        type: integer
                      changes:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            listing_sku:
                              type: string
                            title:
                              type: string
                            changes:
                              type: array
                              items:
                                type: object
                                properties:
                                  field:
                                    type: string
                                  old_value:
                                    type: string
                                  new_value:
                                    type: string
                example:
                  data:
                    total_listings: 3
                    affected_listings: 2
                    skipped_fba: 1
                    changes:
                    - id: 4521
                      listing_sku: WIDGET-BLUE-01
                      title: Blue Widget - 2 Pack
                      changes:
                      - field: Master of Stock
                        old_value: Not set
                        new_value: SKU.io
                      - field: Fulfillment Latency
                        old_value: Not set
                        new_value: 2 days
                      - field: Warehouses
                        old_value: 0 warehouse(s)
                        new_value: 2 warehouse(s) (Replace)
                      - field: Max Rule
                        old_value: None
                        new_value: 'Fixed Allocation: 100'
                      - field: Buffer Stock
                        old_value: '0'
                        new_value: '10'
                    - id: 4522
                      listing_sku: WIDGET-RED-01
                      title: Red Widget - 2 Pack
                      changes:
                      - field: Master of Stock
                        old_value: Sales Channel
                        new_value: SKU.io
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      ids:
                        type: array
                        items:
                          type: string
                      inventory_settings:
                        type: array
                        items:
                          type: string
                example:
                  message: The ids field is required. (and 1 more error)
                  errors:
                    ids:
                    - The ids field is required.
                    inventory_settings:
                    - The inventory settings field is required.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: products:write
      operationId: post-api-v2-listings-bulk-edit-inventory-preview
  /api/v2/listings/bulk-update-inventory-settings:
    post:
      tags:
      - Product Listings
      summary: Bulk Update Listing Inventory Settings
      description: 'Applies inventory settings to many listings at once. Runs synchronously
        — the response reports the number of listings updated.


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Targeting (one of):

        - ids (array of integers, required unless apply_to_all is true) — explicit
        listing IDs

        - apply_to_all: true — target every listing matching the optional filters
        object: search (listing SKU / title / channel listing ID), integration_id,
        is_fba (true/false). Only non-archived listings are targeted in this mode.


        inventory_settings (required, object):

        inventory_settings fields (all optional within the object):

        - inherit (boolean) — when true, clears all listing-level overrides so the
        listing inherits settings from its channel account; all other settings fields
        are ignored

        - master_of_stock (string|null) — one of: sku.io, sales_channel, amazon, neither

        - warehouse_ids (array of integers|null) — warehouse IDs used for the listing''s
        available quantity

        - warehouse_action (string) — how warehouse_ids are applied: replace (default),
        add, or clear

        - fulfillment_latency (integer|null, 0-30) — handling time in days

        - max_rule_type (string|null) — one of: None, Fixed Allocation, % of Available

        - max_rule_value (number|null, min 0) — value paired with max_rule_type

        - min_rule_type (string|null) — one of: None, Fixed Allocation, % of Available

        - min_rule_value (number|null, min 0) — value paired with min_rule_type

        - subtract_buffer_stock (integer|null, min 0) — buffer quantity subtracted
        from availability


        Behavior notes:

        - Only the fields present in inventory_settings are changed; omitted fields
        keep their current values.

        - inherit: true is destructive — it deletes all listing-level overrides so
        the listing inherits from its channel account; any other settings sent alongside
        it are ignored.

        - warehouse_action controls how warehouse_ids merge with existing selections:
        replace (default) overwrites, add unions, clear empties the selection.

        - FBA listings are always skipped (their inventory is managed by the fulfillment
        network) and do not count toward the affected total.


        Use Preview Bulk Listing Inventory Settings Update first for a dry run of
        the same payload.


        Authentication: Requires Bearer token.


        Note: inventory_settings.inherit = true resets the listing''s inventory overrides
        but PRESERVES any per-listing FBM Backup rule (inventory_rules.fbmBackup)
        — that rule is orthogonal to inventory inheritance.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
                apply_to_all:
                  type: boolean
                filters:
                  type: object
                  properties:
                    search:
                      type: string
                    integration_id:
                      type: integer
                    is_fba:
                      type: boolean
                inventory_settings:
                  type: object
                  properties:
                    inherit:
                      type: boolean
                    master_of_stock:
                      type: string
                    warehouse_ids:
                      type: array
                      items:
                        type: integer
                    warehouse_action:
                      type: string
                    fulfillment_latency:
                      type: integer
                    max_rule_type:
                      type: string
                    max_rule_value:
                      type: integer
                    min_rule_type:
                      type: string
                    min_rule_value:
                      type: string
                      nullable: true
                    subtract_buffer_stock:
                      type: integer
              example:
                ids:
                - 4521
                - 4522
                - 4523
                apply_to_all: false
                filters:
                  search: WIDGET
                  integration_id: 3
                  is_fba: false
                inventory_settings:
                  inherit: false
                  master_of_stock: sku.io
                  warehouse_ids:
                  - 1
                  - 4
                  warehouse_action: replace
                  fulfillment_latency: 2
                  max_rule_type: Fixed Allocation
                  max_rule_value: 100
                  min_rule_type: None
                  min_rule_value: null
                  subtract_buffer_stock: 10
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 Success
                  value:
                    message: Updated inventory settings for 2 listing(s).
                    data:
                      affected: 2
                example-1:
                  summary: 200 No Listings Specified
                  value:
                    message: No listings specified.
                    data:
                      affected: 0
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      inventory_settings:
                        type: array
                        items:
                          type: string
                      ids:
                        type: array
                        items:
                          type: string
                example:
                  message: The inventory settings field is required. (and 1 more error)
                  errors:
                    inventory_settings:
                    - The inventory settings field is required.
                    ids:
                    - The ids field is required when apply to all is not present.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: products:write
      operationId: post-api-v2-listings-bulk-update-inventory-settings
  /api/v2/listings/channel-inventory/trigger-recalc:
    post:
      tags:
      - Product Listings
      summary: Trigger Channel Inventory Recalculation
      description: 'Flags channel inventory records for quantity recalculation. This
        is asynchronous: the request only marks the records; the quantities are recalculated
        by a scheduled background process on its next cycle, not immediately within
        this request.


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Targeting modes (checked in this order):

        - apply_to_all: true — flag every record matching the optional filters object
        (search, integration_instance_id, integration_id, is_sku_recalculation_needed).
        Archived listings are excluded.

        - product_listing_ids (array of integers) — flag all channel inventory records
        belonging to the given listing IDs.

        - ids (array of integers) — flag specific channel inventory record IDs.


        All body fields are optional, but supply at least one targeting mode; otherwise
        0 records are affected.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
                product_listing_ids:
                  type: array
                  items:
                    type: integer
                apply_to_all:
                  type: boolean
                filters:
                  type: object
                  properties:
                    search:
                      type: string
                    integration_instance_id:
                      type: integer
                    integration_id:
                      type: integer
                    is_sku_recalculation_needed:
                      type: boolean
              example:
                ids:
                - 88213
                - 88214
                product_listing_ids:
                - 4521
                apply_to_all: false
                filters:
                  search: WIDGET
                  integration_instance_id: 7
                  integration_id: 3
                  is_sku_recalculation_needed: false
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      affected:
                        type: integer
                example:
                  message: Marked 3 record(s) for recalculation.
                  data:
                    affected: 3
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      ids.0:
                        type: array
                        items:
                          type: string
                example:
                  message: The ids.0 field must be an integer.
                  errors:
                    ids.0:
                    - The ids.0 field must be an integer.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: products:write
      operationId: post-api-v2-listings-channel-inventory-trigger-recalc
  /api/v2/sales-credits:
    get:
      tags:
      - Sales Credits
      summary: List Sales Credits
      description: 'Returns a paginated list of sales credits using the standard list
        interface. Supports search, archiving filter, and column selection.


        :::info[Required scope: `orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        This endpoint uses the standard list interface. Common filters are passed
        as query parameters directly.


        Response is wrapped with table_specifications metadata when table_specifications
        parameter is provided.


        Totals fields:

        - total: total credit amount

        - refund_payments_total: sum of cash/card refunds against the credit (always
        positive)

        - applied_to_other_total: sum of credit consumed by Loop Returns EXC-* exchange
        orders (always positive)

        - fees_retained_total: sum of fees Loop withheld out of the customer''s credit
        — return shipping, restocking, etc. (always positive)

        - outstanding_amount: total minus (refund_payments_total + applied_to_other_total
        + fees_retained_total), clamped to zero (i.e., the unrefunded, unapplied balance
        still owed back to the customer)'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        description: 'Page number (default: 1)'
        example: '1'
      - name: limit
        in: query
        schema:
          type: integer
        description: 'Items per page (default: 10)'
        example: '10'
      - name: sort
        in: query
        schema:
          type: string
        description: 'Sort field and direction (prefix with - for descending). Common
          fields: id, credit_date, sales_credit_number, created_at, updated_at, archived_at'
      - name: search
        in: query
        schema:
          type: string
        description: Full-text search across sales credit number, customer name, order
          number, SKU
      - name: archived
        in: query
        schema:
          type: integer
        description: 0 = active only (default), 1 = archived only
        example: '0'
      - name: included[]
        in: query
        schema:
          type: string
        description: IDs to force include in results
      - name: excluded[]
        in: query
        schema:
          type: string
        description: IDs to force exclude from results
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        sales_credit_number:
                          type: string
                        credit_date:
                          type: string
                        is_for_overpayment:
                          type: boolean
                        created_at:
                          type: string
                        updated_at:
                          type: string
                        archived_at:
                          type: string
                          nullable: true
                        statuses:
                          type: object
                          properties:
                            credit_status:
                              type: string
                            return_status:
                              type: string
                        additional_credit:
                          type: number
                        tax_credit:
                          type: number
                        product_total:
                          type: number
                        total:
                          type: number
                        refund_payments_total:
                          type: number
                        applied_to_other_total:
                          type: number
                        fees_retained_total:
                          type: number
                        outstanding_amount:
                          type: number
                        currency_code:
                          type: string
                        sales_order_id:
                          type: integer
                        has_products:
                          type: boolean
                        has_rma:
                          type: boolean
                        payments:
                          type: array
                        exchange_orders:
                          type: array
                  per_page:
                    type: integer
                  total:
                    type: integer
                  last_page:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 55
                    sales_credit_number: SC-00055
                    credit_date: '2025-04-10'
                    is_for_overpayment: false
                    created_at: '2025-04-10T09:00:00.000000Z'
                    updated_at: '2025-04-10T09:00:00.000000Z'
                    archived_at: null
                    statuses:
                      credit_status: open
                      return_status: pending
                    additional_credit: 0.0
                    tax_credit: 0.0
                    product_total: 150.0
                    total: 150.0
                    refund_payments_total: 0.0
                    applied_to_other_total: 0.0
                    fees_retained_total: 0.0
                    outstanding_amount: 150.0
                    currency_code: USD
                    sales_order_id: 100
                    has_products: true
                    has_rma: false
                    payments: []
                    exchange_orders: []
                  per_page: 10
                  total: 5
                  last_page: 1
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: orders:read
      operationId: get-api-v2-sales-credits
  /api/v2/sales-credits/{salesCredit}/activity-log:
    get:
      tags:
      - Sales Credits
      summary: Sales Credit Activity Log
      description: 'Returns the activity log for a sales credit.


        :::info[Required scope: `orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: salesCredit
        in: path
        schema:
          type: integer
        required: true
        description: Sales Credit ID
        example: '1'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        action:
                          type: string
                        user:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        created_at:
                          type: string
                example:
                  data:
                  - id: 1
                    action: created
                    user:
                      id: 1
                      name: John Smith
                    created_at: '2024-03-01T10:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:read
      operationId: get-api-v2-sales-credits-salescredit-activity-log
  /api/v2/sales-credits/filter-options:
    get:
      tags:
      - Sales Credits
      summary: Sales Credits Filter Options
      description: 'Returns available filter options (distinct values) for sales credits
        filtering.


        :::info[Required scope: `orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      statuses:
                        type: array
                        items:
                          type: string
                      customers:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                example:
                  data:
                    statuses:
                    - draft
                    - issued
                    - applied
                    - cancelled
                    customers:
                    - id: 7
                      name: Acme Corp
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: orders:read
      operationId: get-api-v2-sales-credits-filter-options
  /api/v2/financials/daily-summary:
    get:
      tags:
      - Financials
      summary: Daily Financial Summary
      description: 'Returns paginated daily financial summary rows. Each row is backed
        by a polymorphic reportable: a Product or a Financial Line Type.


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Filters (Spatie QueryBuilder syntax, filter[name]=value):

        - filter[search] — searches product SKU/name and financial line type name/classification;
        numeric values also match row ID

        - filter[date_from] / filter[date_to] — date range on the summary date (YYYY-MM-DD)

        - filter[id] / filter[reportable_type] — exact match

        - filter[financial_line_type.{operator}] — financial line type NAME on FinancialLineType-backed
        rows. The financial_line_type filter value can be a plain name ("Shipping")
        or a classification-qualified value ("Revenue: Shipping" / "Cost: Shipping")
        — line type names are only unique per classification, so the qualified form
        (which the application UI now sends) constrains both classification and name.
        Plain names still match across all classifications for backward compatibility.
        Advanced text filter operators (append to the filter name): is, is_not, contains,
        does_not_contain, is_one_of (comma-separated), starts_with, does_not_start_with,
        ends_with, does_not_end_with, is_empty, is_not_empty. Bare filter[financial_line_type]=value
        acts as implicit ''is''. Positive operators return only financial-line-type
        rows that match; negative operators (is_not, does_not_*) exclude matching
        line-type rows while keeping all other rows (e.g. product-backed rows).

        - filter[classification.{operator}] — financial line type classification (''revenue''
        or ''cost''), same operators as above

        - Numeric advanced filters on: id, quantity, quantity_returned, num_orders,
        revenue, revenue_allocated, revenue_credits, total_revenue, cost, cost_allocated,
        cost_invoices, cost_returned, total_cost, profit, profit_margin (operators:
        equals, not_equals, greater_than, greater_than_or_equal, less_than, less_than_or_equal,
        between, is_empty, is_not_empty)

        - Date advanced filters on: date, created_at, updated_at


        Sorting: sort param, prefix with - for DESC. Allowed sorts: id, date, quantity,
        num_orders, total_revenue, total_cost, profit, profit_margin, created_at,
        updated_at. Default: -date.


        Pagination: page, per_page (default 15).


        Grouped filters: this endpoint also accepts a filter_groups query param —
        a base64-encoded JSON tree with AND/OR conjunctions and nested groups (this
        is what the application UI advanced filters modal sends). Example JSON before
        encoding: {"conjunction":"and","children":[{"type":"condition","condition":{"column":"financial_line_type","operator":"is","value":"Shipping
        Revenue"}}]}. Conditions reference the same filter columns/operators listed
        above. When filter_groups is present, tree conditions are applied with proper
        parenthesization; flat filter[...] params still work for non-tree filters
        (search, date_from, date_to).'
      parameters: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        date:
                          type: string
                        reportable:
                          type: object
                          properties:
                            id:
                              type: integer
                            type:
                              type: string
                            financial_line_type:
                              type: object
                              properties:
                                id:
                                  type: integer
                                name:
                                  type: string
                                classification:
                                  type: string
                        quantity:
                          type: integer
                        quantity_returned:
                          type: integer
                        num_orders:
                          type: integer
                        revenue:
                          type: string
                        revenue_allocated:
                          type: string
                        revenue_credits:
                          type: string
                        revenue_discount:
                          type: string
                        total_revenue:
                          type: string
                        cost:
                          type: string
                        cost_allocated:
                          type: string
                        cost_invoices:
                          type: string
                        cost_returned:
                          type: string
                        cost_breakdown:
                          type: string
                          nullable: true
                        total_cost:
                          type: string
                        profit:
                          type: string
                        profit_margin:
                          type: string
                        updated_at:
                          type: string
                        created_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                  first_page_url:
                    type: string
                  last_page_url:
                    type: string
                  next_page_url:
                    type: string
                    nullable: true
                  prev_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  links:
                    type: array
                example:
                  data:
                  - id: 102
                    date: '2024-03-01'
                    reportable:
                      id: 3
                      type: App\Models\FinancialLineType
                      financial_line_type:
                        id: 3
                        name: Shipping Revenue
                        classification: revenue
                    quantity: 0
                    quantity_returned: 0
                    num_orders: 18
                    revenue: '240.00'
                    revenue_allocated: '0.00'
                    revenue_credits: '0.00'
                    revenue_discount: '0.00'
                    total_revenue: '240.00'
                    cost: '0.00'
                    cost_allocated: '0.00'
                    cost_invoices: '0.00'
                    cost_returned: '0.00'
                    cost_breakdown: null
                    total_cost: '0.00'
                    profit: '240.00'
                    profit_margin: '100.00'
                    updated_at: '2024-03-02T04:10:11.000000Z'
                    created_at: '2024-03-02T04:10:11.000000Z'
                  current_page: 1
                  last_page: 1
                  per_page: 15
                  total: 1
                  from: 1
                  to: 1
                  first_page_url: https://sku-alt2.test/api/v2/financials/daily-summary?page=1
                  last_page_url: https://sku-alt2.test/api/v2/financials/daily-summary?page=1
                  next_page_url: null
                  prev_page_url: null
                  path: https://sku-alt2.test/api/v2/financials/daily-summary
                  links: []
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:read
      operationId: get-api-v2-financials-daily-summary
  /api/v2/financials/sales-order-lines:
    get:
      tags:
      - Financials
      summary: Sales Order Line Financials
      description: 'Returns paginated financial data at the sales order line level.


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: per_page
        in: query
        schema:
          type: integer
        example: '10'
        description: Results per page (default 10).
      - name: page
        in: query
        schema:
          type: integer
        example: '1'
        description: Page number (default 1).
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        sales_order_id:
                          type: integer
                        product_id:
                          type: integer
                        quantity:
                          type: integer
                        unit_price:
                          type: string
                        unit_cost:
                          type: string
                        revenue:
                          type: string
                        cogs:
                          type: string
                        gross_profit:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 55
                    sales_order_id: 30
                    product_id: 15
                    quantity: 10
                    unit_price: '9.99'
                    unit_cost: '4.50'
                    revenue: '99.90'
                    cogs: '45.00'
                    gross_profit: '54.90'
                  current_page: 1
                  last_page: 100
                  per_page: 10
                  total: 998
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:read
      operationId: get-api-v2-financials-sales-order-lines
  /api/v2/reporting/ship-by-schedule:
    get:
      tags:
      - Reporting
      summary: Ship By Schedule
      description: 'Returns ship-by schedule report data showing orders that need
        to be shipped by specific dates.


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        ship_by_date:
                          type: string
                        order_count:
                          type: integer
                        total_units:
                          type: integer
                        overdue:
                          type: boolean
                example:
                  data:
                  - ship_by_date: '2024-03-25'
                    order_count: 12
                    total_units: 48
                    overdue: false
                  - ship_by_date: '2024-03-20'
                    order_count: 3
                    total_units: 9
                    overdue: true
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:read
      operationId: get-api-v2-reporting-ship-by-schedule
  /api/v2/product-listings/{productListing}:
    get:
      tags:
      - Product Listings
      summary: Get Product Listing
      description: 'Returns a single product listing with its sales channel, integration,
        pricing tier, inventory cache, and document relations loaded. The integration-specific
        resource class is used based on the sales channel.


        :::info[Required scope: `products:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        FBM Backup Mode (Amazon MFN listings only): send inventory_rules.fbmBackup
        = { inherit: bool, enabled: bool, fbaThreshold: int>=0, scope: "same_country"|"all_marketplaces"
        }. inherit:true (or omitting fbmBackup) inherits the Amazon integration default;
        inherit:false is a per-listing override. The response fbm_backup carries the
        EFFECTIVE config, `inherited` (bool), the `integration_default`, and (when
        effectively enabled) the live gate status. Enabling an override on a non-Amazon
        or FBA listing returns 422. fbm_backup is null only for non-Amazon-MFN listings.'
      parameters:
      - name: productListing
        in: path
        schema:
          type: integer
        required: true
        description: Product listing ID
        example: '1'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      product_id:
                        type: integer
                      product_sku:
                        type: string
                      product_name:
                        type: string
                      channel_name:
                        type: string
                      integration_name:
                        type: string
                      integration_instance_id:
                        type: integer
                      listing_sku:
                        type: string
                      sales_channel_listing_id:
                        type: string
                      document_id:
                        type: integer
                      listing_url:
                        type: string
                      title:
                        type: string
                      price:
                        type: number
                      is_fba:
                        type: boolean
                      price_inherit:
                        type: boolean
                      master_of_price:
                        type: string
                      pricing_tier_id:
                        type: integer
                      pricing_tier_name:
                        type: string
                      master_of_price_override:
                        type: string
                      product_pricing_tier_id_override:
                        type: integer
                      stock_inherit:
                        type: boolean
                      master_of_stock:
                        type: string
                      fulfillment_latency:
                        type: integer
                      inventory_rules:
                        type: object
                        properties:
                          fbmBackup:
                            type: object
                            properties:
                              inherit:
                                type: boolean
                              enabled:
                                type: boolean
                              fbaThreshold:
                                type: integer
                              scope:
                                type: string
                      sales_channel_settings:
                        type: object
                        properties:
                          inventory:
                            type: object
                            properties:
                              masterOfStock:
                                type: string
                              selectedWarehouses:
                                type: array
                                items:
                                  type: integer
                              fulfillmentLatency:
                                type: integer
                      inventory_caches:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            sales_channel_location_id:
                              type: integer
                            sku_quantity:
                              type: integer
                            sales_channel_quantity:
                              type: integer
                            is_sku_recalculation_needed:
                              type: boolean
                            sku_quantity_updated_at:
                              type: string
                            sales_channel_quantity_updated_at:
                              type: string
                            sales_channel_quantity_synced_at:
                              type: string
                      quantity:
                        type: integer
                      fbm_backup:
                        type: object
                        properties:
                          enabled:
                            type: boolean
                          fba_threshold:
                            type: integer
                          scope:
                            type: string
                          inherited:
                            type: boolean
                          integration_default:
                            type: object
                            properties:
                              enabled:
                                type: boolean
                              fbaThreshold:
                                type: integer
                              scope:
                                type: string
                          gate_active:
                            type: boolean
                          fba_available_total:
                            type: integer
                          pushed_quantity:
                            type: integer
                          warning:
                            type: string
                            nullable: true
                          fba_listings:
                            type: array
                            items:
                              type: object
                              properties:
                                listing_id:
                                  type: integer
                                listing_sku:
                                  type: string
                                country_code:
                                  type: string
                                available:
                                  type: integer
                      archived_at:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 1
                    product_id: 42
                    product_sku: WIDGET-001
                    product_name: Premium Widget
                    channel_name: Amazon US - Main
                    integration_name: amazon
                    integration_instance_id: 2
                    listing_sku: WIDGET-001-MFN
                    sales_channel_listing_id: B0EXAMPLE12
                    document_id: 4501
                    listing_url: https://www.amazon.com/dp/B0EXAMPLE12?psc=1
                    title: Premium Widget
                    price: 149.99
                    is_fba: false
                    price_inherit: false
                    master_of_price: sku.io
                    pricing_tier_id: 2
                    pricing_tier_name: Retail
                    master_of_price_override: sku.io
                    product_pricing_tier_id_override: 2
                    stock_inherit: true
                    master_of_stock: sku.io
                    fulfillment_latency: 2
                    inventory_rules:
                      fbmBackup:
                        inherit: false
                        enabled: true
                        fbaThreshold: 0
                        scope: same_country
                    sales_channel_settings:
                      inventory:
                        masterOfStock: sku.io
                        selectedWarehouses:
                        - 1
                        - 2
                        fulfillmentLatency: 2
                    inventory_caches:
                    - id: 901
                      sales_channel_location_id: 0
                      sku_quantity: 50
                      sales_channel_quantity: 0
                      is_sku_recalculation_needed: false
                      sku_quantity_updated_at: '2026-07-16T10:00:00.000000Z'
                      sales_channel_quantity_updated_at: '2026-07-16T10:04:00.000000Z'
                      sales_channel_quantity_synced_at: '2026-07-16T10:04:00.000000Z'
                    quantity: 50
                    fbm_backup:
                      enabled: true
                      fba_threshold: 0
                      scope: same_country
                      inherited: false
                      integration_default:
                        enabled: true
                        fbaThreshold: 0
                        scope: same_country
                      gate_active: true
                      fba_available_total: 142
                      pushed_quantity: 0
                      warning: null
                      fba_listings:
                      - listing_id: 4512
                        listing_sku: WIDGET-001-FBA
                        country_code: US
                        available: 142
                    archived_at: null
                    created_at: '2026-01-15T08:30:00.000000Z'
                    updated_at: '2026-07-16T10:04:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: products:read
      operationId: get-api-v2-product-listings-productlisting
    put:
      tags:
      - Product Listings
      summary: Update Product Listing
      description: 'Updates a product listing. If master_of_price or product_pricing_tier_id
        change, the price is pushed to the sales channel.


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        master_of_price / master_of_stock accept sku.io, sales_channel, or neither
        (null inherits). The effective master_of_stock is driven by inventory_rules.masterOfStock.


        Authentication: Requires Bearer token.


        FBM Backup Mode (Amazon MFN listings only): send inventory_rules.fbmBackup
        = { inherit: bool, enabled: bool, fbaThreshold: int>=0, scope: "same_country"|"all_marketplaces"
        }. inherit:true (or omitting fbmBackup) inherits the Amazon integration default;
        inherit:false is a per-listing override. The response fbm_backup carries the
        EFFECTIVE config, `inherited` (bool), the `integration_default`, and (when
        effectively enabled) the live gate status. Enabling an override on a non-Amazon
        or FBA listing returns 422. fbm_backup is null only for non-Amazon-MFN listings.


        Inventory modification rules: send inventory_rules.inventoryModificationRules
        = { maxRuleType: string, maxRuleTypeValue: numeric|null, minRuleType: string,
        minRuleTypeValue: numeric|null, subtractBufferStock: numeric|null }. All value
        fields are nullable; subtractBufferStock subtracts a buffer from the quantity
        pushed to the channel (null/0 = no buffer).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                master_of_price:
                  type: string
                product_pricing_tier_id:
                  type: integer
                inventory_rules:
                  type: object
                  properties:
                    masterOfStock:
                      type: string
                    selectedWarehouses:
                      type: array
                      items:
                        type: integer
                    inventoryModificationRules:
                      type: object
                      properties:
                        maxRuleType:
                          type: string
                        maxRuleTypeValue:
                          type: string
                          nullable: true
                        minRuleType:
                          type: string
                        minRuleTypeValue:
                          type: string
                          nullable: true
                        subtractBufferStock:
                          type: string
                          nullable: true
                    fbmBackup:
                      type: object
                      properties:
                        inherit:
                          type: boolean
                        enabled:
                          type: boolean
                        fbaThreshold:
                          type: integer
                        scope:
                          type: string
              example:
                master_of_price: sku.io
                product_pricing_tier_id: 2
                inventory_rules:
                  masterOfStock: sku.io
                  selectedWarehouses:
                  - 1
                  - 2
                  inventoryModificationRules:
                    maxRuleType: None
                    maxRuleTypeValue: null
                    minRuleType: None
                    minRuleTypeValue: null
                    subtractBufferStock: null
                  fbmBackup:
                    inherit: false
                    enabled: true
                    fbaThreshold: 0
                    scope: same_country
      parameters:
      - name: productListing
        in: path
        schema:
          type: integer
        required: true
        description: Product listing ID
        example: '1'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      product_id:
                        type: integer
                      product_sku:
                        type: string
                      product_name:
                        type: string
                      channel_name:
                        type: string
                      integration_name:
                        type: string
                      integration_instance_id:
                        type: integer
                      listing_sku:
                        type: string
                      sales_channel_listing_id:
                        type: string
                      document_id:
                        type: integer
                      listing_url:
                        type: string
                      title:
                        type: string
                      price:
                        type: number
                      is_fba:
                        type: boolean
                      price_inherit:
                        type: boolean
                      master_of_price:
                        type: string
                      pricing_tier_id:
                        type: integer
                      pricing_tier_name:
                        type: string
                      master_of_price_override:
                        type: string
                      product_pricing_tier_id_override:
                        type: integer
                      stock_inherit:
                        type: boolean
                      master_of_stock:
                        type: string
                      fulfillment_latency:
                        type: string
                        nullable: true
                      inventory_rules:
                        type: object
                        properties:
                          masterOfStock:
                            type: string
                          selectedWarehouses:
                            type: array
                            items:
                              type: integer
                          inventoryModificationRules:
                            type: object
                            properties:
                              maxRuleType:
                                type: string
                              maxRuleTypeValue:
                                type: string
                                nullable: true
                              minRuleType:
                                type: string
                              minRuleTypeValue:
                                type: string
                                nullable: true
                              subtractBufferStock:
                                type: string
                                nullable: true
                          fbmBackup:
                            type: object
                            properties:
                              inherit:
                                type: boolean
                              enabled:
                                type: boolean
                              fbaThreshold:
                                type: integer
                              scope:
                                type: string
                      sales_channel_settings:
                        type: object
                        properties:
                          inventory:
                            type: object
                            properties:
                              masterOfStock:
                                type: string
                              selectedWarehouses:
                                type: array
                                items:
                                  type: integer
                              fulfillmentLatency:
                                type: integer
                      inventory_caches:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            sales_channel_location_id:
                              type: integer
                            sku_quantity:
                              type: integer
                            sales_channel_quantity:
                              type: integer
                            is_sku_recalculation_needed:
                              type: boolean
                            sku_quantity_updated_at:
                              type: string
                            sales_channel_quantity_updated_at:
                              type: string
                            sales_channel_quantity_synced_at:
                              type: string
                      quantity:
                        type: integer
                      fbm_backup:
                        type: object
                        properties:
                          enabled:
                            type: boolean
                          fba_threshold:
                            type: integer
                          scope:
                            type: string
                          inherited:
                            type: boolean
                          integration_default:
                            type: object
                            properties:
                              enabled:
                                type: boolean
                              fbaThreshold:
                                type: integer
                              scope:
                                type: string
                          gate_active:
                            type: boolean
                          fba_available_total:
                            type: integer
                          pushed_quantity:
                            type: integer
                          warning:
                            type: string
                            nullable: true
                          fba_listings:
                            type: array
                            items:
                              type: object
                              properties:
                                listing_id:
                                  type: integer
                                listing_sku:
                                  type: string
                                country_code:
                                  type: string
                                available:
                                  type: integer
                      archived_at:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  message: Product listing updated successfully.
                  data:
                    id: 1
                    product_id: 42
                    product_sku: WIDGET-001
                    product_name: Premium Widget
                    channel_name: Amazon US - Main
                    integration_name: amazon
                    integration_instance_id: 2
                    listing_sku: WIDGET-001-MFN
                    sales_channel_listing_id: B0EXAMPLE12
                    document_id: 4501
                    listing_url: https://www.amazon.com/dp/B0EXAMPLE12?psc=1
                    title: Premium Widget
                    price: 149.99
                    is_fba: false
                    price_inherit: false
                    master_of_price: sku.io
                    pricing_tier_id: 2
                    pricing_tier_name: Retail
                    master_of_price_override: sku.io
                    product_pricing_tier_id_override: 2
                    stock_inherit: false
                    master_of_stock: sku.io
                    fulfillment_latency: null
                    inventory_rules:
                      masterOfStock: sku.io
                      selectedWarehouses:
                      - 1
                      - 2
                      inventoryModificationRules:
                        maxRuleType: None
                        maxRuleTypeValue: null
                        minRuleType: None
                        minRuleTypeValue: null
                        subtractBufferStock: null
                      fbmBackup:
                        inherit: false
                        enabled: true
                        fbaThreshold: 0
                        scope: same_country
                    sales_channel_settings:
                      inventory:
                        masterOfStock: sku.io
                        selectedWarehouses:
                        - 1
                        - 2
                        fulfillmentLatency: 2
                    inventory_caches:
                    - id: 901
                      sales_channel_location_id: 0
                      sku_quantity: 50
                      sales_channel_quantity: 0
                      is_sku_recalculation_needed: false
                      sku_quantity_updated_at: '2026-07-16T10:00:00.000000Z'
                      sales_channel_quantity_updated_at: '2026-07-16T10:04:00.000000Z'
                      sales_channel_quantity_synced_at: '2026-07-16T10:04:00.000000Z'
                    quantity: 50
                    fbm_backup:
                      enabled: true
                      fba_threshold: 0
                      scope: same_country
                      inherited: false
                      integration_default:
                        enabled: true
                        fbaThreshold: 0
                        scope: same_country
                      gate_active: true
                      fba_available_total: 142
                      pushed_quantity: 0
                      warning: null
                      fba_listings:
                      - listing_id: 4512
                        listing_sku: WIDGET-001-FBA
                        country_code: US
                        available: 142
                    archived_at: null
                    created_at: '2026-01-15T08:30:00.000000Z'
                    updated_at: '2026-07-16T10:04:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: products:write
      operationId: put-api-v2-product-listings-productlisting
  /api/v2/product-listings/{productListing}/end:
    post:
      tags:
      - Product Listings (V2)
      summary: End Listing on Channel
      description: 'End a live listing on its sales channel (listing publishing).


        Per-channel semantics:

        - Amazon: deletes the SKU''s listings item (SP-API deleteListingsItem)

        - BigCommerce: hides the product (is_visible=false, reversible)

        - eBay: ends the item (Trading EndFixedPriceItem, EndingReason=NotAvailable)

        - Walmart: retires the item (DELETE /v3/items/{sku}, async up to 48h)

        - Shopify: archives the product (productUpdate status ARCHIVED, reversible)

        - WooCommerce: trashes the product (DELETE without force, reversible)


        On success the local ProductListing''s remote_status is stamped with the channel-side
        state the listing was left in — `missing` for hard deletes/retires (Amazon,
        eBay, Walmart) or `archived` for native unpublish (Shopify, BigCommerce, WooCommerce)
        — so the catalog coverage matrix demotes the cell and offers a republish.


        Authentication: Requires Bearer token. Gated by the per-tenant listing-publishing
        feature flag (403 when disabled).


        Idempotent: ending a listing that was already removed on the channel still
        succeeds (remote_status becomes `missing`).'
      requestBody:
        content: {}
      parameters:
      - name: productListing
        in: path
        schema:
          type: integer
        required: true
        description: The ProductListing ID to end on its sales channel
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      remote_status:
                        type: string
                      remote_status_checked_at:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 55
                    remote_status: archived
                    remote_status_checked_at: '2026-07-03T08:15:42.000000Z'
                  message: Listing ended on the channel.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: array
                    items:
                      type: object
                      properties:
                        code:
                          type: string
                        message:
                          type: string
                example:
                  message: This channel does not support listing publishing.
                  errors:
                  - code: not_supported
                    message: This channel does not support listing publishing.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-v2-product-listings-productlisting-end
  /api/v2/dashboard/operational-kpis:
    get:
      tags:
      - Dashboard
      summary: Operational KPIs
      description: 'Returns operational KPI metrics for the dashboard.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      open_sales_orders:
                        type: integer
                      pending_fulfillments:
                        type: integer
                      low_stock_products:
                        type: integer
                      open_purchase_orders:
                        type: integer
                      pending_receipts:
                        type: integer
                example:
                  data:
                    open_sales_orders: 42
                    pending_fulfillments: 15
                    low_stock_products: 8
                    open_purchase_orders: 6
                    pending_receipts: 3
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: get-api-v2-dashboard-operational-kpis
  /api/v2/dashboard/summary:
    get:
      tags:
      - Dashboard
      summary: Dashboard Summary
      description: 'Returns aggregated summary data for the dashboard.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      revenue_30d:
                        type: string
                      orders_30d:
                        type: integer
                      units_sold_30d:
                        type: integer
                      inventory_value:
                        type: string
                example:
                  data:
                    revenue_30d: '125430.00'
                    orders_30d: 312
                    units_sold_30d: 1847
                    inventory_value: '284500.00'
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: get-api-v2-dashboard-summary
  /api/tags/{id}:
    get:
      tags:
      - Tags
      summary: Show Tag
      description: 'Returns a single tag by ID including counts of associated products,
        sales orders, and purchase orders.


        :::info[Required scope: `settings:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      num_products:
                        type: integer
                      num_sales_orders:
                        type: integer
                      num_purchase_orders:
                        type: integer
                      num_customers:
                        type: integer
                      archived_at:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 1
                    name: Electronics
                    num_products: 45
                    num_sales_orders: 120
                    num_purchase_orders: 30
                    num_customers: 3
                    archived_at: null
                    created_at: '2024-01-10T08:00:00.000000Z'
                    updated_at: '2024-01-10T08:00:00.000000Z'
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No query results for model [App\Models\Tag] 999
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: settings:read
      operationId: get-api-tags-id
    put:
      tags:
      - Tags
      summary: Update Tag
      description: 'Updates a tag''s name. Name must be unique (ignores current record).


        :::info[Required scope: `settings:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
              example:
                name: Renamed Category
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      num_products:
                        type: integer
                      num_sales_orders:
                        type: integer
                      num_purchase_orders:
                        type: integer
                      num_customers:
                        type: integer
                      archived_at:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 5
                    name: Renamed Category
                    num_products: 0
                    num_sales_orders: 0
                    num_purchase_orders: 0
                    num_customers: 0
                    archived_at: null
                    created_at: '2024-03-01T12:00:00.000000Z'
                    updated_at: '2024-03-01T13:00:00.000000Z'
                  message: tag Renamed Category updated successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: settings:write
      operationId: put-api-tags-id
    delete:
      tags:
      - Tags
      summary: Delete Tag
      description: 'Deletes a tag. Returns an error if the tag is still linked to
        any products, sales orders, or purchase orders.


        :::info[Required scope: `settings:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: tag Renamed Category deleted successfully
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: array
                    items:
                      type: object
                      properties:
                        message:
                          type: string
                        code:
                          type: string
                        field:
                          type: string
                  message:
                    type: string
                example:
                  errors:
                  - message: This is currently used by 45 items.
                    code: TagRESOURCE_LINKED
                    field: tags
                  message: tag Electronics could not be deleted
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: settings:write
      operationId: delete-api-tags-id
  /api/tags:
    post:
      tags:
      - Tags
      summary: Create Tag
      description: 'Creates a new tag.


        :::info[Required scope: `settings:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Fields:

        - name (required, string, unique across tags)


        **Requires permission:** `tags.create`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
              example:
                name: New Category
      parameters: []
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      num_products:
                        type: integer
                      num_sales_orders:
                        type: integer
                      num_purchase_orders:
                        type: integer
                      num_customers:
                        type: integer
                      archived_at:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 5
                    name: New Category
                    num_products: 0
                    num_sales_orders: 0
                    num_purchase_orders: 0
                    num_customers: 0
                    archived_at: null
                    created_at: '2024-03-01T12:00:00.000000Z'
                    updated_at: '2024-03-01T12:00:00.000000Z'
                  message: tag created successfully
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      name:
                        type: array
                        items:
                          type: string
                example:
                  message: The given data was invalid.
                  errors:
                    name:
                    - The name has already been taken.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: settings:write
      operationId: post-api-tags
    delete:
      tags:
      - Tags
      summary: Bulk Delete Tags
      description: 'Bulk deletes multiple tags by IDs.


        :::info[Required scope: `settings:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `tags.delete`'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 2 tags deleted successfully
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: settings:write
      operationId: delete-api-tags
    get:
      tags:
      - Tags
      summary: List Tags
      description: 'Returns a paginated list of tags with standard list query parameters.
        Supports search, sort, archive filtering, and column inclusion/exclusion.


        Authentication: Requires Bearer token.


        Response includes counts: num_products, num_sales_orders, num_purchase_orders,
        num_customers.'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        description: Page number
        example: '1'
      - name: limit
        in: query
        schema:
          type: integer
        description: Items per page
        example: '25'
      - name: sort
        in: query
        schema:
          type: string
        description: 'Sort field. Prefix with - for descending. Allowed: id, name,
          created_at, updated_at'
        example: name
      - name: search
        in: query
        schema:
          type: string
        description: Search by tag name
        example: electronics
      - name: archived
        in: query
        schema:
          type: integer
        description: 0 = active only, 1 = archived only
        example: '0'
      - name: included[]
        in: query
        schema:
          type: string
        description: Columns to include in DataTable response
        example: name
      - name: excluded[]
        in: query
        schema:
          type: string
        description: Columns to exclude from DataTable response
        example: archived_at
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        num_products:
                          type: integer
                        num_sales_orders:
                          type: integer
                        num_purchase_orders:
                          type: integer
                        num_customers:
                          type: integer
                        archived_at:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                  last_page:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 1
                    name: Electronics
                    num_products: 45
                    num_sales_orders: 120
                    num_purchase_orders: 30
                    num_customers: 3
                    archived_at: null
                    created_at: '2024-01-10T08:00:00.000000Z'
                    updated_at: '2024-01-10T08:00:00.000000Z'
                  - id: 2
                    name: Clearance
                    num_products: 12
                    num_sales_orders: 35
                    num_purchase_orders: 5
                    num_customers: 1
                    archived_at: null
                    created_at: '2024-01-11T09:00:00.000000Z'
                    updated_at: '2024-01-11T09:00:00.000000Z'
                  per_page: 25
                  total: 2
                  from: 1
                  to: 2
                  last_page: 1
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-tags
  /api/tags/{id}/archive:
    put:
      tags:
      - Tags
      summary: Archive Tag
      description: 'Archives a tag. Returns a warning if already archived.


        :::info[Required scope: `settings:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      archived_at:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 1
                    name: Electronics
                    archived_at: '2024-03-01T15:00:00.000000Z'
                  message: tag Electronics archived successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: settings:write
      operationId: put-api-tags-id-archive
  /api/tags/{id}/unarchived:
    put:
      tags:
      - Tags
      summary: Unarchive Tag
      description: 'Unarchives a tag. Returns a warning if not currently archived.


        :::info[Required scope: `settings:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                  message:
                    type: string
                example:
                  data:
                    id: 1
                    name: Electronics
                    archived_at: null
                  message: tag Electronics unarchived successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: settings:write
      operationId: put-api-tags-id-unarchived
  /api/tags/archive:
    put:
      tags:
      - Tags
      summary: Bulk Archive Tags
      description: 'Bulk archives multiple tags by IDs.


        :::info[Required scope: `settings:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `tags.archive`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1
                - 2
                - 3
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 3 tags archived successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: settings:write
      operationId: put-api-tags-archive
  /api/tags/unarchive:
    put:
      tags:
      - Tags
      summary: Bulk Unarchive Tags
      description: 'Bulk unarchives multiple tags by IDs.


        :::info[Required scope: `settings:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `tags.archive`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1
                - 2
                - 3
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 3 tags unarchived successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: settings:write
      operationId: put-api-tags-unarchive
  /api/tags/deletable:
    post:
      tags:
      - Tags
      summary: Check Deletable
      description: 'Checks which tags can be safely deleted (not linked to any products,
        sales orders, or purchase orders).


        :::info[Required scope: `settings:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `tags.delete`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1
                - 2
                - 5
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        deletable:
                          type: boolean
                        reason:
                          type: object
                          properties:
                            tags:
                              type: string
                example:
                  data:
                  - id: 1
                    name: Electronics
                    deletable: false
                    reason:
                      tags: This is currently used by 45 items.
                  - id: 2
                    name: Clearance
                    deletable: false
                    reason:
                      tags: This is currently used by 12 items.
                  - id: 5
                    name: Unused Tag
                    deletable: true
                    reason: null
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: settings:write
      operationId: post-api-tags-deletable
  /api/tags/import:
    post:
      tags:
      - Tags
      summary: Import Tags
      description: 'Imports tags in bulk from JSON data.


        :::info[Required scope: `settings:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `tags.import`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                data:
                  type: array
                  items:
                    type: object
                    properties:
                      name:
                        type: string
              example:
                data:
                - name: Imported Tag 1
                - name: Imported Tag 2
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Tags imported successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: settings:write
      operationId: post-api-tags-import
  /api/tags/import/preview:
    post:
      tags:
      - Tags
      summary: Preview Import Tags
      description: 'Previews a tag import without committing changes. Returns what
        would be created/updated.


        :::info[Required scope: `settings:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `tags.import`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                data:
                  type: array
                  items:
                    type: object
                    properties:
                      name:
                        type: string
              example:
                data:
                - name: Preview Tag 1
                - name: Preview Tag 2
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        name:
                          type: string
                        action:
                          type: string
                example:
                  data:
                  - name: Preview Tag 1
                    action: create
                  - name: Preview Tag 2
                    action: create
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: settings:write
      operationId: post-api-tags-import-preview
  /api/subscription-editions:
    get:
      tags:
      - Subscriptions
      summary: List Subscription Editions (Paginated)
      description: 'Returns a paginated list of all subscription editions across all
        offerings.


        :::info[Required scope: `subscriptions:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        description: 'Page number (default: 1)'
        example: '1'
      - name: per_page
        in: query
        schema:
          type: integer
        description: 'Items per page (default: 15)'
        example: '15'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        subscription_offering_id:
                          type: integer
                        edition_name:
                          type: string
                        effective_date:
                          type: string
                        cutoff_date:
                          type: string
                        priority:
                          type: integer
                        allocated_quantity:
                          type: integer
                        consumed_quantity:
                          type: integer
                        remaining_quantity:
                          type: integer
                        product_id:
                          type: integer
                        status:
                          type: string
                        notes:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                        subscription_offering:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        product:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            sku:
                              type: string
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 1
                    subscription_offering_id: 5
                    edition_name: Q1 2024 Edition
                    effective_date: '2024-01-01'
                    cutoff_date: '2024-03-31'
                    priority: 1
                    allocated_quantity: 100
                    consumed_quantity: 45
                    remaining_quantity: 55
                    product_id: 10
                    status: active
                    notes: Q1 release batch
                    created_at: '2023-12-15T10:00:00.000000Z'
                    updated_at: '2024-01-01T00:00:00.000000Z'
                    subscription_offering:
                      id: 5
                      name: Premium Widget Subscription
                    product:
                      id: 10
                      name: Widget Pro
                      sku: WIDGET-PRO-001
                  last_page: 1
                  per_page: 15
                  total: 1
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: subscriptions:read
      operationId: get-api-subscription-editions
    post:
      tags:
      - Subscriptions
      summary: Create Subscription Edition
      description: 'Creates a new subscription edition.


        :::info[Required scope: `subscriptions:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Fields:

        - subscription_offering_id (required): ID of the parent subscription offering

        - edition_name (required): Name of the edition (max 255 chars)

        - effective_date (required): When this edition becomes active (YYYY-MM-DD)

        - cutoff_date (optional): Last date for this edition (must be >= effective_date)

        - priority (optional): Sort priority (integer, min 1)

        - allocated_quantity (optional): Total quantity allocated to this edition

        - product_id (required): ID of the product for this edition

        - status (optional): One of: draft, active, archived

        - notes (optional): Free-text notes'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                subscription_offering_id:
                  type: integer
                edition_name:
                  type: string
                effective_date:
                  type: string
                cutoff_date:
                  type: string
                priority:
                  type: integer
                allocated_quantity:
                  type: integer
                product_id:
                  type: integer
                status:
                  type: string
                notes:
                  type: string
              example:
                subscription_offering_id: 5
                edition_name: Q2 2024 Edition
                effective_date: '2024-04-01'
                cutoff_date: '2024-06-30'
                priority: 2
                allocated_quantity: 150
                product_id: 10
                status: draft
                notes: Q2 pre-planned batch
      parameters: []
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      subscription_offering_id:
                        type: integer
                      edition_name:
                        type: string
                      effective_date:
                        type: string
                      cutoff_date:
                        type: string
                      priority:
                        type: integer
                      allocated_quantity:
                        type: integer
                      consumed_quantity:
                        type: integer
                      remaining_quantity:
                        type: integer
                      product_id:
                        type: integer
                      status:
                        type: string
                      notes:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      subscription_offering:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      product:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          sku:
                            type: string
                example:
                  message: Subscription Edition created successfully.
                  data:
                    id: 2
                    subscription_offering_id: 5
                    edition_name: Q2 2024 Edition
                    effective_date: '2024-04-01'
                    cutoff_date: '2024-06-30'
                    priority: 2
                    allocated_quantity: 150
                    consumed_quantity: 0
                    remaining_quantity: 150
                    product_id: 10
                    status: draft
                    notes: Q2 pre-planned batch
                    created_at: '2024-03-01T10:00:00.000000Z'
                    updated_at: '2024-03-01T10:00:00.000000Z'
                    subscription_offering:
                      id: 5
                      name: Premium Widget Subscription
                    product:
                      id: 10
                      name: Widget Pro
                      sku: WIDGET-PRO-001
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      edition_name:
                        type: array
                        items:
                          type: string
                      effective_date:
                        type: array
                        items:
                          type: string
                      product_id:
                        type: array
                        items:
                          type: string
                example:
                  message: The given data was invalid.
                  errors:
                    edition_name:
                    - The edition name field is required.
                    effective_date:
                    - The effective date field is required.
                    product_id:
                    - The selected product id is invalid.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: subscriptions:write
      operationId: post-api-subscription-editions
  /api/subscription-editions/{id}:
    get:
      tags:
      - Subscriptions
      summary: Get Subscription Edition
      description: 'Returns a single subscription edition with offering and product
        details.


        :::info[Required scope: `subscriptions:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      subscription_offering_id:
                        type: integer
                      edition_name:
                        type: string
                      effective_date:
                        type: string
                      cutoff_date:
                        type: string
                      priority:
                        type: integer
                      allocated_quantity:
                        type: integer
                      consumed_quantity:
                        type: integer
                      remaining_quantity:
                        type: integer
                      product_id:
                        type: integer
                      status:
                        type: string
                      notes:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      subscription_offering:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      product:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          sku:
                            type: string
                example:
                  data:
                    id: 1
                    subscription_offering_id: 5
                    edition_name: Q1 2024 Edition
                    effective_date: '2024-01-01'
                    cutoff_date: '2024-03-31'
                    priority: 1
                    allocated_quantity: 100
                    consumed_quantity: 45
                    remaining_quantity: 55
                    product_id: 10
                    status: active
                    notes: Q1 release batch
                    created_at: '2023-12-15T10:00:00.000000Z'
                    updated_at: '2024-01-01T00:00:00.000000Z'
                    subscription_offering:
                      id: 5
                      name: Premium Widget Subscription
                    product:
                      id: 10
                      name: Widget Pro
                      sku: WIDGET-PRO-001
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No query results for model [App\Models\SubscriptionEdition]
                    999
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: subscriptions:read
      operationId: get-api-subscription-editions-id
    put:
      tags:
      - Subscriptions
      summary: Update Subscription Edition
      description: 'Updates an existing subscription edition. All fields are optional
        for partial updates.


        :::info[Required scope: `subscriptions:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Fields (all optional):

        - edition_name: Updated name (max 255 chars)

        - effective_date: Updated effective date

        - cutoff_date: Updated cutoff date (must be >= effective_date)

        - priority: Updated priority (integer, min 1)

        - allocated_quantity: Updated allocated quantity

        - product_id: Updated product ID

        - status: One of: draft, active, archived

        - notes: Updated notes'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                edition_name:
                  type: string
                effective_date:
                  type: string
                cutoff_date:
                  type: string
                priority:
                  type: integer
                allocated_quantity:
                  type: integer
                product_id:
                  type: integer
                status:
                  type: string
                notes:
                  type: string
              example:
                edition_name: Q1 2024 Edition - Revised
                effective_date: '2024-01-01'
                cutoff_date: '2024-04-15'
                priority: 1
                allocated_quantity: 120
                product_id: 10
                status: active
                notes: Extended cutoff date
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      subscription_offering_id:
                        type: integer
                      edition_name:
                        type: string
                      effective_date:
                        type: string
                      cutoff_date:
                        type: string
                      priority:
                        type: integer
                      allocated_quantity:
                        type: integer
                      consumed_quantity:
                        type: integer
                      remaining_quantity:
                        type: integer
                      product_id:
                        type: integer
                      status:
                        type: string
                      notes:
                        type: string
                example:
                  message: Subscription Edition 'Q1 2024 Edition - Revised' updated
                    successfully.
                  data:
                    id: 1
                    subscription_offering_id: 5
                    edition_name: Q1 2024 Edition - Revised
                    effective_date: '2024-01-01'
                    cutoff_date: '2024-04-15'
                    priority: 1
                    allocated_quantity: 120
                    consumed_quantity: 45
                    remaining_quantity: 75
                    product_id: 10
                    status: active
                    notes: Extended cutoff date
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: subscriptions:write
      operationId: put-api-subscription-editions-id
    delete:
      tags:
      - Subscriptions
      summary: Delete Subscription Edition
      description: 'Deletes a subscription edition.


        :::info[Required scope: `subscriptions:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Subscription Edition 'Q1 2024 Edition' deleted successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: subscriptions:write
      operationId: delete-api-subscription-editions-id
  /api/subscription-editions/{id}/activate:
    post:
      tags:
      - Subscriptions
      summary: Activate Subscription Edition
      description: 'Activates a draft subscription edition by setting its status to
        ''active''.


        :::info[Required scope: `subscriptions:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      edition_name:
                        type: string
                      status:
                        type: string
                      subscription_offering:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      product:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          sku:
                            type: string
                example:
                  message: Edition activated successfully
                  data:
                    id: 1
                    edition_name: Q1 2024 Edition
                    status: active
                    subscription_offering:
                      id: 5
                      name: Premium Widget Subscription
                    product:
                      id: 10
                      name: Widget Pro
                      sku: WIDGET-PRO-001
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: subscriptions:write
      operationId: post-api-subscription-editions-id-activate
  /api/subscription-editions/{id}/archive:
    post:
      tags:
      - Subscriptions
      summary: Archive Subscription Edition
      description: 'Archives a subscription edition by setting its status to ''archived''.


        :::info[Required scope: `subscriptions:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      edition_name:
                        type: string
                      status:
                        type: string
                example:
                  message: Edition archived successfully
                  data:
                    id: 1
                    edition_name: Q1 2024 Edition
                    status: archived
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: subscriptions:write
      operationId: post-api-subscription-editions-id-archive
  /api/subscription-editions/{id}/copy:
    post:
      tags:
      - Subscriptions
      summary: Copy Subscription Edition
      description: 'Creates a new draft edition by copying an existing one with a
        new name and effective date.


        :::info[Required scope: `subscriptions:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Fields:

        - edition_name (required): Name for the new copy (max 255 chars)

        - effective_date (required): Effective date for the copy (YYYY-MM-DD)'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                edition_name:
                  type: string
                effective_date:
                  type: string
              example:
                edition_name: Q2 2024 Edition (Copy of Q1)
                effective_date: '2024-04-01'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      subscription_offering_id:
                        type: integer
                      edition_name:
                        type: string
                      effective_date:
                        type: string
                      cutoff_date:
                        type: string
                        nullable: true
                      priority:
                        type: integer
                      allocated_quantity:
                        type: integer
                      consumed_quantity:
                        type: integer
                      remaining_quantity:
                        type: integer
                      product_id:
                        type: integer
                      status:
                        type: string
                      notes:
                        type: string
                      subscription_offering:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      product:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          sku:
                            type: string
                example:
                  message: Subscription Edition created successfully.
                  data:
                    id: 3
                    subscription_offering_id: 5
                    edition_name: Q2 2024 Edition (Copy of Q1)
                    effective_date: '2024-04-01'
                    cutoff_date: null
                    priority: 1
                    allocated_quantity: 100
                    consumed_quantity: 0
                    remaining_quantity: 100
                    product_id: 10
                    status: draft
                    notes: Q1 release batch
                    subscription_offering:
                      id: 5
                      name: Premium Widget Subscription
                    product:
                      id: 10
                      name: Widget Pro
                      sku: WIDGET-PRO-001
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      edition_name:
                        type: array
                        items:
                          type: string
                      effective_date:
                        type: array
                        items:
                          type: string
                example:
                  message: The given data was invalid.
                  errors:
                    edition_name:
                    - The edition name field is required.
                    effective_date:
                    - The effective date field is required.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: subscriptions:write
      operationId: post-api-subscription-editions-id-copy
  /api/subscription-offerings:
    get:
      tags:
      - Subscriptions
      summary: List Subscription Offerings
      description: 'Get a paginated list of subscription offerings with filtering
        and sorting.


        :::info[Required scope: `subscriptions:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Allowed sorts: id, name, sku, status, created_at. Default sort: name.

        Pagination defaults to 15 per page.

        Each offering includes edition count and product listings count.'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        description: 'Page number (default: 1)'
        example: '1'
      - name: per_page
        in: query
        schema:
          type: integer
        description: 'Items per page (default: 15)'
        example: '15'
      - name: sort
        in: query
        schema:
          type: string
        description: 'Sort field. Prefix with - for descending. Allowed: id, name,
          sku, status, created_at. Default: name'
        example: name
      - name: filter[status]
        in: query
        schema:
          type: string
        description: 'Filter by status (text filter). Values: active, paused, archived'
        example: active
      - name: filter[name]
        in: query
        schema:
          type: string
        description: Filter by offering name (text filter)
      - name: filter[sku]
        in: query
        schema:
          type: string
        description: Filter by offering SKU (text filter)
      - name: filter[editions_count]
        in: query
        schema:
          type: string
        description: Filter by edition count (numeric filter)
      - name: filter[product_listings_count]
        in: query
        schema:
          type: string
        description: Filter by product listings count (numeric filter)
      - name: filter[created_at]
        in: query
        schema:
          type: string
        description: Filter by created_at (datetime filter)
      - name: filter[updated_at]
        in: query
        schema:
          type: string
        description: Filter by updated_at (datetime filter)
      - name: filter[search]
        in: query
        schema:
          type: string
        description: Search across id, name, and sku
        example: quarterly
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        sku:
                          type: string
                        default_product_id:
                          type: integer
                        status:
                          type: string
                        settings:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                        updated_at:
                          type: string
                        default_product:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            sku:
                              type: string
                        editions_count:
                          type: integer
                        product_listings_count:
                          type: integer
                        editions:
                          type: string
                          nullable: true
                        active_editions:
                          type: string
                          nullable: true
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 1
                    name: Quarterly Beauty Box
                    sku: QBB-Q1
                    default_product_id: 55
                    status: active
                    settings: null
                    created_at: '2024-01-01T00:00:00.000000Z'
                    updated_at: '2024-01-15T12:00:00.000000Z'
                    default_product:
                      id: 55
                      name: Beauty Box Standard
                      sku: BB-STD
                    editions_count: 4
                    product_listings_count: 2
                    editions: null
                    active_editions: null
                  current_page: 1
                  last_page: 3
                  per_page: 15
                  total: 32
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: subscriptions:read
      operationId: get-api-subscription-offerings
    post:
      tags:
      - Subscriptions
      summary: Create Subscription Offering
      description: 'Create a new subscription offering.


        :::info[Required scope: `subscriptions:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Required: name. Optional: sku (unique), default_product_id, status (active|paused|archived),
        settings.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                sku:
                  type: string
                default_product_id:
                  type: integer
                status:
                  type: string
                settings:
                  type: string
                  nullable: true
              example:
                name: Quarterly Beauty Box
                sku: QBB-Q1
                default_product_id: 55
                status: active
                settings: null
      parameters: []
      responses:
        '201':
          description: Created
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      sku:
                        type: string
                      default_product_id:
                        type: integer
                      status:
                        type: string
                      settings:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 3
                    name: Quarterly Beauty Box
                    sku: QBB-Q1
                    default_product_id: 55
                    status: active
                    settings: null
                    created_at: '2024-02-01T09:00:00.000000Z'
                    updated_at: '2024-02-01T09:00:00.000000Z'
                  message: Subscription Offering created successfully
        '422':
          description: Unprocessable Entity
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      name:
                        type: array
                        items:
                          type: string
                      sku:
                        type: array
                        items:
                          type: string
                example:
                  message: The given data was invalid.
                  errors:
                    name:
                    - The name field is required.
                    sku:
                    - The sku has already been taken.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: subscriptions:write
      operationId: post-api-subscription-offerings
  /api/subscription-offerings/active-list:
    get:
      tags:
      - Subscriptions
      summary: Get Active Offerings List (Picker)
      description: 'Get a lightweight list of active subscription offerings with edition
        counts — for use in pickers and dropdowns.


        :::info[Required scope: `subscriptions:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Returns only active offerings, ordered by name.'
      parameters: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        sku:
                          type: string
                        active_editions_count:
                          type: integer
                        default_product:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            sku:
                              type: string
                example:
                  data:
                  - id: 1
                    name: Quarterly Beauty Box
                    sku: QBB-Q1
                    active_editions_count: 2
                    default_product:
                      id: 55
                      name: Beauty Box Standard
                      sku: BB-STD
                  - id: 2
                    name: Monthly Coffee Club
                    sku: MCC-M1
                    active_editions_count: 1
                    default_product: null
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: subscriptions:read
      operationId: get-api-subscription-offerings-active-list
  /api/subscription-offerings/{subscription_offering}:
    get:
      tags:
      - Subscriptions
      summary: Get Subscription Offering
      description: 'Get a subscription offering with full detail including editions
        and product listings count.


        :::info[Required scope: `subscriptions:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: subscription_offering
        in: path
        schema:
          type: integer
        required: true
        description: Subscription offering ID
        example: '1'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      sku:
                        type: string
                      default_product_id:
                        type: integer
                      status:
                        type: string
                      settings:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      default_product:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          sku:
                            type: string
                      editions_count:
                        type: integer
                      product_listings_count:
                        type: integer
                      editions:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            subscription_offering_id:
                              type: integer
                            edition_name:
                              type: string
                            effective_date:
                              type: string
                            cutoff_date:
                              type: string
                            priority:
                              type: integer
                            allocated_quantity:
                              type: integer
                            consumed_quantity:
                              type: integer
                            remaining_quantity:
                              type: integer
                            product_id:
                              type: integer
                            status:
                              type: string
                            notes:
                              type: string
                              nullable: true
                example:
                  data:
                    id: 1
                    name: Quarterly Beauty Box
                    sku: QBB-Q1
                    default_product_id: 55
                    status: active
                    settings: null
                    created_at: '2024-01-01T00:00:00.000000Z'
                    updated_at: '2024-01-15T12:00:00.000000Z'
                    default_product:
                      id: 55
                      name: Beauty Box Standard
                      sku: BB-STD
                    editions_count: 4
                    product_listings_count: 2
                    editions:
                    - id: 10
                      subscription_offering_id: 1
                      edition_name: Q1 2024
                      effective_date: '2024-01-01'
                      cutoff_date: '2024-03-15'
                      priority: 1
                      allocated_quantity: 500
                      consumed_quantity: 123
                      remaining_quantity: 377
                      product_id: 55
                      status: active
                      notes: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: subscriptions:read
      operationId: get-api-subscription-offerings-subscription-offering
    put:
      tags:
      - Subscriptions
      summary: Update Subscription Offering
      description: 'Update an existing subscription offering. All fields are optional.


        :::info[Required scope: `subscriptions:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        SKU must be unique (ignores own record).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                sku:
                  type: string
                default_product_id:
                  type: integer
                status:
                  type: string
                settings:
                  type: object
                  properties:
                    auto_resolve:
                      type: boolean
              example:
                name: Quarterly Beauty Box (Updated)
                sku: QBB-Q1-V2
                default_product_id: 55
                status: active
                settings:
                  auto_resolve: true
      parameters:
      - name: subscription_offering
        in: path
        schema:
          type: integer
        required: true
        description: Subscription offering ID
        example: '1'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      sku:
                        type: string
                      status:
                        type: string
                      updated_at:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 1
                    name: Quarterly Beauty Box (Updated)
                    sku: QBB-Q1-V2
                    status: active
                    updated_at: '2024-02-01T10:00:00.000000Z'
                  message: Subscription Offering Quarterly Beauty Box (Updated) updated
                    successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: subscriptions:write
      operationId: put-api-subscription-offerings-subscription-offering
    delete:
      tags:
      - Subscriptions
      summary: Delete Subscription Offering
      description: 'Delete a subscription offering.


        :::info[Required scope: `subscriptions:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Returns 422 if the offering has linked product listings.'
      parameters:
      - name: subscription_offering
        in: path
        schema:
          type: integer
        required: true
        description: Subscription offering ID
        example: '1'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Subscription Offering Quarterly Beauty Box deleted successfully
        '422':
          description: Unprocessable Entity
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Cannot delete offering with linked product listings
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: subscriptions:write
      operationId: delete-api-subscription-offerings-subscription-offering
  /api/subscription-offerings/{subscription_offering}/activate:
    post:
      tags:
      - Subscriptions
      summary: Activate Offering
      description: 'Set the status of a subscription offering to active.


        :::info[Required scope: `subscriptions:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: subscription_offering
        in: path
        schema:
          type: integer
        required: true
        description: Subscription offering ID
        example: '1'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      status:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 1
                    name: Quarterly Beauty Box
                    status: active
                  message: Subscription Offering Quarterly Beauty Box updated successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: subscriptions:write
      operationId: post-api-subscription-offerings-subscription-offering-activate
  /api/subscription-offerings/{subscription_offering}/pause:
    post:
      tags:
      - Subscriptions
      summary: Pause Offering
      description: 'Set the status of a subscription offering to paused.


        :::info[Required scope: `subscriptions:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: subscription_offering
        in: path
        schema:
          type: integer
        required: true
        description: Subscription offering ID
        example: '1'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      status:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 1
                    name: Quarterly Beauty Box
                    status: paused
                  message: Subscription Offering Quarterly Beauty Box updated successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: subscriptions:write
      operationId: post-api-subscription-offerings-subscription-offering-pause
  /api/subscription-offerings/{subscription_offering}/editions:
    get:
      tags:
      - Subscriptions
      summary: List Editions for Offering
      description: 'Get paginated editions for a subscription offering.


        :::info[Required scope: `subscriptions:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: per_page
        in: query
        schema:
          type: integer
        description: Items per page
        example: '15'
      - name: page
        in: query
        schema:
          type: integer
        description: Page number
        example: '1'
      - name: subscription_offering
        in: path
        schema:
          type: integer
        required: true
        description: Subscription offering ID
        example: '1'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        subscription_offering_id:
                          type: integer
                        edition_name:
                          type: string
                        effective_date:
                          type: string
                        cutoff_date:
                          type: string
                        priority:
                          type: integer
                        allocated_quantity:
                          type: integer
                        consumed_quantity:
                          type: integer
                        remaining_quantity:
                          type: integer
                        product_id:
                          type: integer
                        status:
                          type: string
                        notes:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                        updated_at:
                          type: string
                        subscription_offering:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        product:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            sku:
                              type: string
                  current_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 10
                    subscription_offering_id: 1
                    edition_name: Q1 2024
                    effective_date: '2024-01-01'
                    cutoff_date: '2024-03-15'
                    priority: 1
                    allocated_quantity: 500
                    consumed_quantity: 123
                    remaining_quantity: 377
                    product_id: 55
                    status: active
                    notes: null
                    created_at: '2023-12-01T00:00:00.000000Z'
                    updated_at: '2024-01-10T00:00:00.000000Z'
                    subscription_offering:
                      id: 1
                      name: Quarterly Beauty Box
                    product:
                      id: 55
                      name: Beauty Box Standard
                      sku: BB-STD
                  current_page: 1
                  per_page: 15
                  total: 4
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: subscriptions:read
      operationId: get-api-subscription-offerings-subscription-offering-editions
    post:
      tags:
      - Subscriptions
      summary: Create Edition for Offering
      description: 'Create a new edition for a subscription offering.


        :::info[Required scope: `subscriptions:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Required: edition_name, effective_date, product_id. Optional: cutoff_date
        (must be >= effective_date), priority, allocated_quantity, status, notes.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                edition_name:
                  type: string
                effective_date:
                  type: string
                cutoff_date:
                  type: string
                priority:
                  type: integer
                allocated_quantity:
                  type: integer
                product_id:
                  type: integer
                status:
                  type: string
                notes:
                  type: string
              example:
                edition_name: Q2 2024
                effective_date: '2024-04-01'
                cutoff_date: '2024-06-15'
                priority: 1
                allocated_quantity: 600
                product_id: 56
                status: draft
                notes: Spring edition with new formula
      parameters:
      - name: subscription_offering
        in: path
        schema:
          type: integer
        required: true
        description: Subscription offering ID
        example: '1'
      responses:
        '201':
          description: Created
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      subscription_offering_id:
                        type: integer
                      edition_name:
                        type: string
                      effective_date:
                        type: string
                      cutoff_date:
                        type: string
                      priority:
                        type: integer
                      allocated_quantity:
                        type: integer
                      consumed_quantity:
                        type: integer
                      remaining_quantity:
                        type: integer
                      product_id:
                        type: integer
                      status:
                        type: string
                      notes:
                        type: string
                      subscription_offering:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      product:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          sku:
                            type: string
                  message:
                    type: string
                example:
                  data:
                    id: 11
                    subscription_offering_id: 1
                    edition_name: Q2 2024
                    effective_date: '2024-04-01'
                    cutoff_date: '2024-06-15'
                    priority: 1
                    allocated_quantity: 600
                    consumed_quantity: 0
                    remaining_quantity: 600
                    product_id: 56
                    status: draft
                    notes: Spring edition with new formula
                    subscription_offering:
                      id: 1
                      name: Quarterly Beauty Box
                    product:
                      id: 56
                      name: Beauty Box Spring
                      sku: BB-SPR
                  message: Subscription Edition created successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: subscriptions:write
      operationId: post-api-subscription-offerings-subscription-offering-editions
  /api/subscription-offerings/{subscription_offering}/editions/{edition}:
    get:
      tags:
      - Subscriptions
      summary: Get Edition for Offering
      description: 'Get a single subscription edition nested under an offering.


        :::info[Required scope: `subscriptions:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: subscription_offering
        in: path
        schema:
          type: integer
        required: true
        description: Subscription offering ID
        example: '1'
      - name: edition
        in: path
        schema:
          type: integer
        required: true
        description: Edition ID
        example: '10'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      subscription_offering_id:
                        type: integer
                      edition_name:
                        type: string
                      effective_date:
                        type: string
                      cutoff_date:
                        type: string
                      priority:
                        type: integer
                      allocated_quantity:
                        type: integer
                      consumed_quantity:
                        type: integer
                      remaining_quantity:
                        type: integer
                      product_id:
                        type: integer
                      status:
                        type: string
                      notes:
                        type: string
                        nullable: true
                      subscription_offering:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      product:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          sku:
                            type: string
                example:
                  data:
                    id: 10
                    subscription_offering_id: 1
                    edition_name: Q1 2024
                    effective_date: '2024-01-01'
                    cutoff_date: '2024-03-15'
                    priority: 1
                    allocated_quantity: 500
                    consumed_quantity: 123
                    remaining_quantity: 377
                    product_id: 55
                    status: active
                    notes: null
                    subscription_offering:
                      id: 1
                      name: Quarterly Beauty Box
                    product:
                      id: 55
                      name: Beauty Box Standard
                      sku: BB-STD
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: subscriptions:read
      operationId: get-api-subscription-offerings-subscription-offering-editions-edition
    put:
      tags:
      - Subscriptions
      summary: Update Edition for Offering
      description: 'Update an edition nested under an offering. All fields are optional.


        :::info[Required scope: `subscriptions:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        cutoff_date must be on or after effective_date.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                edition_name:
                  type: string
                cutoff_date:
                  type: string
                allocated_quantity:
                  type: integer
                status:
                  type: string
              example:
                edition_name: Q1 2024 (Final)
                cutoff_date: '2024-03-20'
                allocated_quantity: 550
                status: active
      parameters:
      - name: subscription_offering
        in: path
        schema:
          type: integer
        required: true
        description: Subscription offering ID
        example: '1'
      - name: edition
        in: path
        schema:
          type: integer
        required: true
        description: Edition ID
        example: '10'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      edition_name:
                        type: string
                      allocated_quantity:
                        type: integer
                      status:
                        type: string
                      updated_at:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 10
                    edition_name: Q1 2024 (Final)
                    allocated_quantity: 550
                    status: active
                    updated_at: '2024-02-01T10:00:00.000000Z'
                  message: Subscription Edition Q1 2024 (Final) updated successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: subscriptions:write
      operationId: put-api-subscription-offerings-subscription-offering-editions-edition
    delete:
      tags:
      - Subscriptions
      summary: Delete Edition for Offering
      description: 'Delete an edition from a subscription offering.


        :::info[Required scope: `subscriptions:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: subscription_offering
        in: path
        schema:
          type: integer
        required: true
        description: Subscription offering ID
        example: '1'
      - name: edition
        in: path
        schema:
          type: integer
        required: true
        description: Edition ID
        example: '10'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Subscription Edition Q1 2024 deleted successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: subscriptions:write
      operationId: delete-api-subscription-offerings-subscription-offering-editions-edition
  /api/subscription-offerings/{subscription_offering}/editions/orders-summary:
    get:
      tags:
      - Subscriptions
      summary: Editions Orders Summary
      description: 'Get orders summary grouped by edition for a subscription offering.


        :::info[Required scope: `subscriptions:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Includes order count, units sold, revenue, average order value, fulfillment
        rate, and current edition flag.'
      parameters:
      - name: date_range
        in: query
        schema:
          type: integer
        description: 'Date range in days to look back (default: 90). Use ''all'' for
          all time.'
        example: '90'
      - name: subscription_offering
        in: path
        schema:
          type: integer
        required: true
        description: Subscription offering ID
        example: '1'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        edition_id:
                          type: integer
                        edition_name:
                          type: string
                        orders_count:
                          type: integer
                        total_units:
                          type: integer
                        total_revenue:
                          type: integer
                        avg_order_value:
                          type: integer
                        effective_date:
                          type: string
                        fulfillment_rate:
                          type: integer
                        is_current:
                          type: boolean
                example:
                  data:
                  - edition_id: 10
                    edition_name: Q1 2024
                    orders_count: 123
                    total_units: 123
                    total_revenue: 4551
                    avg_order_value: 37
                    effective_date: '2024-01-01'
                    fulfillment_rate: 87
                    is_current: true
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: subscriptions:read
      operationId: get-api-subscription-offerings-subscription-offering-editions-orders-summary
  /api/subscription-offerings/{subscription_offering}/product-listings:
    get:
      tags:
      - Subscriptions
      summary: List Product Listings
      description: 'Get product listings linked to a subscription offering.


        :::info[Required scope: `subscriptions:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Includes integration instance details via salesChannel.'
      parameters:
      - name: filter[integration_id]
        in: query
        schema:
          type: string
        description: Filter by integration ID (comma-separated for multiple)
      - name: filter[integration_instance_id]
        in: query
        schema:
          type: integer
        description: Filter by integration instance ID (comma-separated for multiple)
        example: '5'
      - name: subscription_offering
        in: path
        schema:
          type: integer
        required: true
        description: Subscription offering ID
        example: '1'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        product_id:
                          type: integer
                        subscription_offering_id:
                          type: integer
                        integration_instance:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        created_at:
                          type: string
                example:
                  data:
                  - id: 300
                    product_id: 55
                    subscription_offering_id: 1
                    integration_instance:
                      id: 5
                      name: Shopify Store
                    created_at: '2024-01-05T00:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: subscriptions:read
      operationId: get-api-subscription-offerings-subscription-offering-product-listings
  /api/subscription-offerings/{subscription_offering}/product-listings/{product_listing}/link:
    post:
      tags:
      - Subscriptions
      summary: Link Product Listing
      description: 'Link a product listing to the subscription offering.


        :::info[Required scope: `subscriptions:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Clears any existing product mapping on the listing and sets the subscription
        offering, keeping the product/offering XOR constraint satisfied (a listing
        maps to EITHER a product OR an offering, never both).


        Authentication: Requires Bearer token.


        Returns 422 if the subscription offering is not found or is archived.'
      requestBody:
        content: {}
      parameters:
      - name: subscription_offering
        in: path
        schema:
          type: integer
        required: true
        description: Subscription offering ID
        example: '1'
      - name: product_listing
        in: path
        schema:
          type: integer
        required: true
        description: Product listing ID
        example: '300'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Product listing linked to subscription offering successfully
        '422':
          description: Unprocessable Entity
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Cannot link to an archived subscription offering.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: subscriptions:write
      operationId: post-api-subscription-offerings-subscription-offering-product-listings-product-listing-link
  /api/subscription-offerings/{subscription_offering}/product-listings/{product_listing}/unlink:
    post:
      tags:
      - Subscriptions
      summary: Unlink Product Listing
      description: 'Unlink a product listing from the subscription offering.


        :::info[Required scope: `subscriptions:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Offering-only listings carry no product mapping, so unlinking REMOVES the
        listing entirely rather than leaving it in a both-null state that would violate
        the product/offering XOR constraint. Deletion runs through the model so the
        FBA delete guard and cache observer both fire.


        Authentication: Requires Bearer token.


        Returns 400 if the listing is not linked to this offering. Returns 422 if
        the listing cannot be deleted because it has associated orders (FBA-protected
        listing).'
      requestBody:
        content: {}
      parameters:
      - name: subscription_offering
        in: path
        schema:
          type: integer
        required: true
        description: Subscription offering ID
        example: '1'
      - name: product_listing
        in: path
        schema:
          type: integer
        required: true
        description: Product listing ID
        example: '300'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Product listing unlinked from subscription offering successfully
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Product listing is not linked to this subscription offering
        '422':
          description: Unprocessable Entity
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: This product listing cannot be unlinked because it has
                    associated orders.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: subscriptions:write
      operationId: post-api-subscription-offerings-subscription-offering-product-listings-product-listing-unlink
  /api/subscription-offerings/{subscription_offering}/report:
    get:
      tags:
      - Subscriptions
      summary: Performance Report
      description: 'Get offering performance report data including summary metrics,
        edition performance, and upcoming cutoffs.


        :::info[Required scope: `subscriptions:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: date_range
        in: query
        schema:
          type: integer
        description: 'Look-back period in days (default: 90). Use ''all'' for all
          time.'
        example: '90'
      - name: subscription_offering
        in: path
        schema:
          type: integer
        required: true
        description: Subscription offering ID
        example: '1'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      summary:
                        type: object
                        properties:
                          total_orders:
                            type: integer
                          total_revenue:
                            type: integer
                          total_units:
                            type: integer
                          active_editions:
                            type: integer
                      editions:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            edition_name:
                              type: string
                            orders:
                              type: integer
                            revenue:
                              type: integer
                            units:
                              type: integer
                            is_current:
                              type: boolean
                      upcoming_cutoffs:
                        type: array
                        items:
                          type: object
                          properties:
                            edition_id:
                              type: integer
                            edition_name:
                              type: string
                            cutoff_date:
                              type: string
                            days_until:
                              type: integer
                example:
                  data:
                    summary:
                      total_orders: 347
                      total_revenue: 12839
                      total_units: 347
                      active_editions: 2
                    editions:
                    - id: 10
                      edition_name: Q1 2024
                      orders: 123
                      revenue: 4551
                      units: 123
                      is_current: true
                    upcoming_cutoffs:
                    - edition_id: 10
                      edition_name: Q1 2024
                      cutoff_date: '2024-03-15'
                      days_until: 14
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: subscriptions:read
      operationId: get-api-subscription-offerings-subscription-offering-report
  /api/subscription-offerings/{subscription_offering}/reports/demand-forecast:
    get:
      tags:
      - Subscriptions
      summary: Demand Forecast
      description: 'Get demand forecast for the offering based on historical order
        velocity.


        :::info[Required scope: `subscriptions:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Calculates daily order velocity from lookback period and projects expected
        remaining orders for the current edition.'
      parameters:
      - name: forecast_days
        in: query
        schema:
          type: integer
        description: 'Forecast period in days (default: 30)'
        example: '30'
      - name: lookback_days
        in: query
        schema:
          type: integer
        description: 'Historical lookback period in days (default: 90)'
        example: '90'
      - name: subscription_offering
        in: path
        schema:
          type: integer
        required: true
        description: Subscription offering ID
        example: '1'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      current_edition:
                        type: object
                        properties:
                          id:
                            type: integer
                          edition_name:
                            type: string
                          remaining_expected_orders:
                            type: integer
                          days_until_cutoff:
                            type: integer
                          cutoff_date:
                            type: string
                      upcoming_edition:
                        type: object
                        properties:
                          id:
                            type: integer
                          edition_name:
                            type: string
                          effective_date:
                            type: string
                          product:
                            type: object
                            properties:
                              id:
                                type: integer
                              name:
                                type: string
                              sku:
                                type: string
                      forecast_metrics:
                        type: object
                        properties:
                          daily_order_velocity:
                            type: integer
                          lookback_period_days:
                            type: integer
                          forecast_period_days:
                            type: integer
                          total_orders_in_lookback:
                            type: integer
                example:
                  data:
                    current_edition:
                      id: 10
                      edition_name: Q1 2024
                      remaining_expected_orders: 42
                      days_until_cutoff: 14
                      cutoff_date: '2024-03-15'
                    upcoming_edition:
                      id: 11
                      edition_name: Q2 2024
                      effective_date: '2024-04-01'
                      product:
                        id: 56
                        name: Beauty Box Spring
                        sku: BB-SPR
                    forecast_metrics:
                      daily_order_velocity: 3
                      lookback_period_days: 90
                      forecast_period_days: 30
                      total_orders_in_lookback: 270
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: subscriptions:read
      operationId: get-api-subscription-offerings-subscription-offering-reports-demand-forecast
  /api/subscription-offerings/{subscription_offering}/reports/low-stock-alerts:
    get:
      tags:
      - Subscriptions
      summary: Low Stock Alerts
      description: 'Get low stock alerts for active edition products.


        :::info[Required scope: `subscriptions:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Alert levels: critical (below min_stock_level), warning (< 2 weeks of stock),
        info (< 4 weeks of stock).'
      parameters:
      - name: subscription_offering
        in: path
        schema:
          type: integer
        required: true
        description: Subscription offering ID
        example: '1'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      alerts:
                        type: array
                        items:
                          type: object
                          properties:
                            edition_id:
                              type: integer
                            edition_name:
                              type: string
                            product:
                              type: object
                              properties:
                                id:
                                  type: integer
                                name:
                                  type: string
                                sku:
                                  type: string
                            current_inventory:
                              type: integer
                            min_stock_level:
                              type: integer
                            weekly_velocity:
                              type: integer
                            weeks_of_stock:
                              type: number
                            alert_level:
                              type: string
                      total_alerts:
                        type: integer
                example:
                  data:
                    alerts:
                    - edition_id: 10
                      edition_name: Q1 2024
                      product:
                        id: 55
                        name: Beauty Box Standard
                        sku: BB-STD
                      current_inventory: 50
                      min_stock_level: 10
                      weekly_velocity: 30
                      weeks_of_stock: 1.67
                      alert_level: warning
                    total_alerts: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: subscriptions:read
      operationId: get-api-subscription-offerings-subscription-offering-reports-low-stock-alerts
  /api/subscription-offerings/{subscription_offering}/reports/component-requirements:
    get:
      tags:
      - Subscriptions
      summary: Component Requirements
      description: 'Get component requirements for bundle edition products.


        :::info[Required scope: `subscriptions:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Only returns data for editions whose product type is ''bundle''.'
      parameters:
      - name: subscription_offering
        in: path
        schema:
          type: integer
        required: true
        description: Subscription offering ID
        example: '1'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      requirements:
                        type: array
                        items:
                          type: object
                          properties:
                            edition_id:
                              type: integer
                            edition_name:
                              type: string
                            bundle_product:
                              type: object
                              properties:
                                id:
                                  type: integer
                                name:
                                  type: string
                                sku:
                                  type: string
                            components:
                              type: array
                              items:
                                type: object
                                properties:
                                  id:
                                    type: integer
                                  name:
                                    type: string
                                  sku:
                                    type: string
                                  total_required:
                                    type: integer
                                  current_inventory:
                                    type: integer
                                  status:
                                    type: string
                            total_bundle_orders:
                              type: integer
                      total_bundle_editions:
                        type: integer
                example:
                  data:
                    requirements:
                    - edition_id: 10
                      edition_name: Q1 2024
                      bundle_product:
                        id: 55
                        name: Beauty Box Standard
                        sku: BB-STD
                      components:
                      - id: 60
                        name: Lip Gloss
                        sku: LG-001
                        total_required: 123
                        current_inventory: 200
                        status: sufficient
                      total_bundle_orders: 123
                    total_bundle_editions: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: subscriptions:read
      operationId: get-api-subscription-offerings-subscription-offering-reports-component-requirements
  /api/subscription-offerings/{subscription_offering}/reports/draft-editions-pending:
    get:
      tags:
      - Subscriptions
      summary: Draft Editions Pending
      description: 'Get draft editions pending activation, ordered by effective date.


        :::info[Required scope: `subscriptions:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Includes is_urgent flag for editions effective within 7 days.'
      parameters:
      - name: subscription_offering
        in: path
        schema:
          type: integer
        required: true
        description: Subscription offering ID
        example: '1'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      drafts:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            edition_name:
                              type: string
                            effective_date:
                              type: string
                            days_until_effective:
                              type: integer
                            is_urgent:
                              type: boolean
                            product:
                              type: object
                              properties:
                                id:
                                  type: integer
                                name:
                                  type: string
                                sku:
                                  type: string
                            notes:
                              type: string
                            created_at:
                              type: string
                      total_drafts:
                        type: integer
                      urgent_activations:
                        type: integer
                example:
                  data:
                    drafts:
                    - id: 11
                      edition_name: Q2 2024
                      effective_date: '2024-04-01'
                      days_until_effective: 5
                      is_urgent: true
                      product:
                        id: 56
                        name: Beauty Box Spring
                        sku: BB-SPR
                      notes: Spring edition
                      created_at: '2024-03-15T00:00:00.000000Z'
                    total_drafts: 1
                    urgent_activations: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: subscriptions:read
      operationId: get-api-subscription-offerings-subscription-offering-reports-draft-editions-pending
  /api/subscription-offerings/{subscription_offering}/reports/override-audit-log:
    get:
      tags:
      - Subscriptions
      summary: Override Audit Log
      description: 'Get edition override audit log — shows all order lines where the
        automatically-resolved edition was manually overridden.


        :::info[Required scope: `subscriptions:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: date_range
        in: query
        schema:
          type: integer
        description: 'Look-back period in days (default: 90). Use ''all'' for all
          time.'
        example: '90'
      - name: subscription_offering
        in: path
        schema:
          type: integer
        required: true
        description: Subscription offering ID
        example: '1'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      overrides:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            sales_order_id:
                              type: integer
                            order_reference:
                              type: string
                            overridden_edition_id:
                              type: integer
                            original_edition:
                              type: string
                            reason:
                              type: string
                            created_at:
                              type: string
                      total_overrides:
                        type: integer
                      override_rate:
                        type: number
                example:
                  data:
                    overrides:
                    - id: 500
                      sales_order_id: 1001
                      order_reference: SO-2024-1001
                      overridden_edition_id: 9
                      original_edition: Q4 2023
                      reason: Customer requested old edition
                      created_at: '2024-01-10T00:00:00.000000Z'
                    total_overrides: 1
                    override_rate: 0.81
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: subscriptions:read
      operationId: get-api-subscription-offerings-subscription-offering-reports-override-audit-log
  /api/subscription-offerings/{subscription_offering}/reports/offering-trends:
    get:
      tags:
      - Subscriptions
      summary: Offering Trends
      description: 'Get trends data for the subscription offering.


        :::info[Required scope: `subscriptions:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: subscription_offering
        in: path
        schema:
          type: integer
        required: true
        description: Subscription offering ID
        example: '1'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties: {}
                example:
                  data: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: subscriptions:read
      operationId: get-api-subscription-offerings-subscription-offering-reports-offering-trends
  /api/subscription-offerings/{subscription_offering}/timeline:
    get:
      tags:
      - Subscriptions
      summary: Timeline
      description: 'Get all editions ordered by effective_date for timeline visualization.


        :::info[Required scope: `subscriptions:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: subscription_offering
        in: path
        schema:
          type: integer
        required: true
        description: Subscription offering ID
        example: '1'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      offering:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      editions:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            edition_name:
                              type: string
                            effective_date:
                              type: string
                            cutoff_date:
                              type: string
                            status:
                              type: string
                            product:
                              type: object
                              properties:
                                id:
                                  type: integer
                                name:
                                  type: string
                                sku:
                                  type: string
                example:
                  data:
                    offering:
                      id: 1
                      name: Quarterly Beauty Box
                    editions:
                    - id: 9
                      edition_name: Q4 2023
                      effective_date: '2023-10-01'
                      cutoff_date: '2023-12-15'
                      status: archived
                      product:
                        id: 54
                        name: Beauty Box Winter
                        sku: BB-WIN
                    - id: 10
                      edition_name: Q1 2024
                      effective_date: '2024-01-01'
                      cutoff_date: '2024-03-15'
                      status: active
                      product:
                        id: 55
                        name: Beauty Box Standard
                        sku: BB-STD
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: subscriptions:read
      operationId: get-api-subscription-offerings-subscription-offering-timeline
  /api/subscription-offerings/{subscription_offering}/resolve:
    get:
      tags:
      - Subscriptions
      summary: Resolve Edition for Order Date
      description: 'Preview edition resolution for a given order date.


        :::info[Required scope: `subscriptions:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: order_date
        in: query
        schema:
          type: string
        description: Order date to resolve edition for (Y-m-d format). Defaults to
          now.
        example: '2024-02-15'
      - name: subscription_offering
        in: path
        schema:
          type: integer
        required: true
        description: Subscription offering ID
        example: '1'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      order_date:
                        type: string
                      resolved_edition:
                        type: object
                        properties:
                          id:
                            type: integer
                          edition_name:
                            type: string
                          effective_date:
                            type: string
                          cutoff_date:
                            type: string
                      resolved_product:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          sku:
                            type: string
                      resolution_source:
                        type: string
                      used_cutoff_logic:
                        type: boolean
                example:
                  data:
                    order_date: '2024-02-15 00:00:00'
                    resolved_edition:
                      id: 10
                      edition_name: Q1 2024
                      effective_date: '2024-01-01'
                      cutoff_date: '2024-03-15'
                    resolved_product:
                      id: 55
                      name: Beauty Box Standard
                      sku: BB-STD
                    resolution_source: edition
                    used_cutoff_logic: false
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: subscriptions:read
      operationId: get-api-subscription-offerings-subscription-offering-resolve
  /api/subscription-offerings/{subscription_offering}/resolve-for-order:
    get:
      tags:
      - Subscriptions
      summary: Resolve Edition for Sales Order
      description: 'Resolve the edition for a sales order given an order date and
        optional quantity. Used by the sales order offering picker to preview resolution.


        :::info[Required scope: `subscriptions:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Returns the resolved edition with remaining quantity, is_fallback flag, and
        resolution reason.'
      parameters:
      - name: order_date
        in: query
        schema:
          type: string
        description: Order date to resolve edition for (Y-m-d or datetime). Defaults
          to now.
        example: '2024-02-15'
      - name: quantity
        in: query
        schema:
          type: integer
        description: 'Quantity to check allocation for (default: 1)'
        example: '2'
      - name: edition_id
        in: query
        schema:
          type: integer
        description: 'Optional: manually override the resolved edition ID'
        example: '10'
      - name: subscription_offering
        in: path
        schema:
          type: integer
        required: true
        description: Subscription offering ID
        example: '1'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      resolved_edition:
                        type: object
                        properties:
                          id:
                            type: integer
                          edition_name:
                            type: string
                          effective_date:
                            type: string
                          cutoff_date:
                            type: string
                          priority:
                            type: integer
                          allocated_quantity:
                            type: integer
                          consumed_quantity:
                            type: integer
                          remaining_quantity:
                            type: integer
                          product:
                            type: object
                            properties:
                              id:
                                type: integer
                              name:
                                type: string
                              sku:
                                type: string
                      product_id:
                        type: integer
                      is_fallback:
                        type: boolean
                      resolution_reason:
                        type: string
                example:
                  data:
                    resolved_edition:
                      id: 10
                      edition_name: Q1 2024
                      effective_date: '2024-01-01'
                      cutoff_date: '2024-03-15'
                      priority: 1
                      allocated_quantity: 500
                      consumed_quantity: 123
                      remaining_quantity: 377
                      product:
                        id: 55
                        name: Beauty Box Standard
                        sku: BB-STD
                    product_id: 55
                    is_fallback: false
                    resolution_reason: edition_match
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: subscriptions:read
      operationId: get-api-subscription-offerings-subscription-offering-resolve-for-order
  /api/subscription-offerings/product-stock-summary/{product}:
    get:
      tags:
      - Subscriptions
      summary: Product Stock Summary
      description: 'Get stock summary for a product — used when planning edition allocations.


        :::info[Required scope: `subscriptions:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Returns on-hand, reserved, allocated, available, in-transit inventory, plus
        incoming purchase orders and warehouse transfers.'
      parameters:
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: Product ID
        example: '55'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      product_id:
                        type: integer
                      product_name:
                        type: string
                      product_sku:
                        type: string
                      on_hand:
                        type: integer
                      reserved:
                        type: integer
                      allocated:
                        type: integer
                      available:
                        type: integer
                      in_transit:
                        type: integer
                      incoming_po:
                        type: integer
                      incoming_transfers:
                        type: integer
                      available_to_allocate:
                        type: integer
                      purchase_orders:
                        type: array
                        items:
                          type: object
                          properties:
                            po_number:
                              type: string
                            po_id:
                              type: integer
                            ordered_quantity:
                              type: integer
                            received_quantity:
                              type: integer
                            pending_quantity:
                              type: integer
                            expected_date:
                              type: string
                      warehouse_transfers:
                        type: array
                example:
                  data:
                    product_id: 55
                    product_name: Beauty Box Standard
                    product_sku: BB-STD
                    on_hand: 500
                    reserved: 50
                    allocated: 123
                    available: 327
                    in_transit: 0
                    incoming_po: 200
                    incoming_transfers: 0
                    available_to_allocate: 527
                    purchase_orders:
                    - po_number: PO-2024-0022
                      po_id: 22
                      ordered_quantity: 200
                      received_quantity: 0
                      pending_quantity: 200
                      expected_date: '2024-03-01'
                    warehouse_transfers: []
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: subscriptions:read
      operationId: get-api-subscription-offerings-product-stock-summary-product
  /api/subscription-offerings/{subscription_offering}/export/report:
    get:
      tags:
      - Subscriptions
      summary: Export Performance Report
      description: 'Export the offering performance report to XLSX or CSV.


        :::info[Required scope: `subscriptions:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Columns: Edition, Product SKU, Product Name, Orders, Units Sold, Revenue,
        Effective Date, Status.'
      parameters:
      - name: format
        in: query
        schema:
          type: string
        description: 'Export format: xlsx or csv (default: xlsx)'
        example: xlsx
      - name: date_range
        in: query
        schema:
          type: integer
        description: 'Look-back period in days (default: 90). Use ''all'' for all
          time.'
        example: '90'
      - name: subscription_offering
        in: path
        schema:
          type: integer
        required: true
        description: Subscription offering ID
        example: '1'
      responses:
        '200':
          description: OK
          content:
            text/plain:
              schema:
                type: string
                example: (binary xlsx/csv file)
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: subscriptions:read
      operationId: get-api-subscription-offerings-subscription-offering-export-report
  /api/subscription-offerings/{subscription_offering}/export/demand-forecast:
    get:
      tags:
      - Subscriptions
      summary: Export Demand Forecast
      description: 'Export demand forecast data to XLSX or CSV.


        :::info[Required scope: `subscriptions:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Columns: Current Edition, Daily Velocity, Days Until Cutoff, Expected Remaining
        Orders, Lookback Period (Days), Total Orders in Lookback.'
      parameters:
      - name: format
        in: query
        schema:
          type: string
        description: 'Export format: xlsx or csv'
        example: xlsx
      - name: forecast_days
        in: query
        schema:
          type: integer
        description: 'Forecast period in days (default: 30)'
        example: '30'
      - name: lookback_days
        in: query
        schema:
          type: integer
        description: 'Historical lookback period in days (default: 90)'
        example: '90'
      - name: subscription_offering
        in: path
        schema:
          type: integer
        required: true
        description: Subscription offering ID
        example: '1'
      responses:
        '200':
          description: OK
          content:
            text/plain:
              schema:
                type: string
                example: (binary xlsx/csv file)
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: subscriptions:read
      operationId: get-api-subscription-offerings-subscription-offering-export-demand-forecast
  /api/subscription-offerings/{subscription_offering}/export/low-stock-alerts:
    get:
      tags:
      - Subscriptions
      summary: Export Low Stock Alerts
      description: 'Export low stock alerts to XLSX or CSV.


        :::info[Required scope: `subscriptions:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Columns: Edition, Product SKU, Product Name, Current Inventory, Min Stock
        Level, Weekly Velocity, Weeks of Stock, Alert Level.'
      parameters:
      - name: format
        in: query
        schema:
          type: string
        description: 'Export format: xlsx or csv'
        example: xlsx
      - name: subscription_offering
        in: path
        schema:
          type: integer
        required: true
        description: Subscription offering ID
        example: '1'
      responses:
        '200':
          description: OK
          content:
            text/plain:
              schema:
                type: string
                example: (binary xlsx/csv file)
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: subscriptions:read
      operationId: get-api-subscription-offerings-subscription-offering-export-low-stock-alerts
  /api/subscription-offerings/{subscription_offering}/export/override-audit-log:
    get:
      tags:
      - Subscriptions
      summary: Export Override Audit Log
      description: 'Export edition override audit log to XLSX or CSV.


        :::info[Required scope: `subscriptions:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Columns: Order Reference, Overridden Edition ID, Reason, Created At.'
      parameters:
      - name: format
        in: query
        schema:
          type: string
        description: 'Export format: xlsx or csv'
        example: xlsx
      - name: date_range
        in: query
        schema:
          type: integer
        description: 'Look-back period in days (default: 90). Use ''all'' for all
          time.'
        example: '90'
      - name: subscription_offering
        in: path
        schema:
          type: integer
        required: true
        description: Subscription offering ID
        example: '1'
      responses:
        '200':
          description: OK
          content:
            text/plain:
              schema:
                type: string
                example: (binary xlsx/csv file)
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: subscriptions:read
      operationId: get-api-subscription-offerings-subscription-offering-export-override-audit-log
  /api/pdf-templates:
    get:
      tags:
      - PDF Templates
      summary: List PDF Templates
      description: 'Returns every global (non store-specific) PDF template.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Bearer Personal Access Token with the `settings` scope (read
        access).


        Each template includes its raw `content`, resolved `variables`, a grouped
        `variables_tree`/`schema`, and `type`. Template types: purchase_order, sales_order,
        packing, quote, pick_list, vendor_credit, sales_credit. There is no server-side
        type filter — request the full list and filter by `type` on the client.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        content:
                          type: string
                        type:
                          type: string
                        description:
                          type: string
                        variables:
                          type: array
                          items:
                            type: object
                            properties:
                              name:
                                type: string
                              variable:
                                type: string
                              mockValue:
                                type: string
                        variables_tree:
                          type: object
                          properties:
                            order:
                              type: object
                              properties:
                                label:
                                  type: string
                                children:
                                  type: object
                                  properties:
                                    number:
                                      type: object
                                      properties:
                                        label:
                                          type: string
                                        type:
                                          type: string
                                        mock:
                                          type: string
                        schema:
                          type: object
                          properties:
                            order:
                              type: object
                              properties:
                                label:
                                  type: string
                                children:
                                  type: object
                                  properties:
                                    number:
                                      type: object
                                      properties:
                                        label:
                                          type: string
                                        type:
                                          type: string
                                        mock:
                                          type: string
                        store_id:
                          type: string
                          nullable: true
                        store_name:
                          type: string
                          nullable: true
                        updated_at:
                          type: string
                example:
                  data:
                  - id: 1
                    name: Purchase Order
                    content: <html><body><h1>Purchase Order {{order_number}}</h1></body></html>
                    type: purchase_order
                    description: Default purchase order layout.
                    variables:
                    - name: Order Number
                      variable: order_number
                      mockValue: PO-2044
                    - name: Vendor Name
                      variable: vendor_name
                      mockValue: Acme Supply Co.
                    variables_tree:
                      order:
                        label: Order
                        children:
                          number:
                            label: Order Number
                            type: string
                            mock: PO-2044
                    schema:
                      order:
                        label: Order
                        children:
                          number:
                            label: Order Number
                            type: string
                            mock: PO-2044
                    store_id: null
                    store_name: null
                    updated_at: '2026-07-20T14:32:10+00:00'
                  - id: 2
                    name: Sales Order
                    content: <html><body><h1>Sales Order {{order_number}}</h1></body></html>
                    type: sales_order
                    description: Default sales order layout.
                    variables:
                    - name: Order Number
                      variable: order_number
                      mockValue: SO-1001
                    - name: Customer Name
                      variable: customer_name
                      mockValue: Jane Doe
                    variables_tree:
                      order:
                        label: Order
                        children:
                          number:
                            label: Order Number
                            type: string
                            mock: SO-1001
                    schema:
                      order:
                        label: Order
                        children:
                          number:
                            label: Order Number
                            type: string
                            mock: SO-1001
                    store_id: null
                    store_name: null
                    updated_at: '2026-07-20T14:32:10+00:00'
                  - id: 3
                    name: Packing Slip
                    content: <html><body><h1>Packing Slip {{order_number}}</h1>{{#items}}<p>{{sku}}
                      x {{quantity}}</p>{{/items}}</body></html>
                    type: packing
                    description: Default packing slip layout.
                    variables:
                    - name: Order Number
                      variable: order_number
                      mockValue: SO-1001
                    - name: Warehouse
                      variable: warehouse
                      mockValue: Main Warehouse
                    - name: Items
                      variable: items
                      mockValue: ''
                    variables_tree:
                      order:
                        label: Order
                        children:
                          number:
                            label: Order Number
                            type: string
                            mock: SO-1001
                      items:
                        label: Items
                        type: section
                        mock: ''
                      asset:
                        label: Custom Assets
                        children:
                          company_logo:
                            label: Company Logo
                            type: html
                            mock: ''
                    schema:
                      order:
                        label: Order
                        children:
                          number:
                            label: Order Number
                            type: string
                            mock: SO-1001
                      items:
                        label: Items
                        type: section
                        mock: ''
                      asset:
                        label: Custom Assets
                        children:
                          company_logo:
                            label: Company Logo
                            type: html
                            mock: ''
                    store_id: null
                    store_name: null
                    updated_at: '2026-07-20T14:32:10+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: get-api-pdf-templates
  /api/pdf-templates/{id}:
    get:
      tags:
      - PDF Templates
      summary: Get PDF Template
      description: 'Returns a single PDF template by ID, including its raw `content`,
        resolved `variables`, and `variables_tree`/`schema`.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Bearer Personal Access Token with the `settings` scope (read
        access).'
      parameters:
      - name: id
        in: path
        schema:
          type: string
        required: true
        description: The record ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      content:
                        type: string
                      type:
                        type: string
                      description:
                        type: string
                      variables:
                        type: array
                        items:
                          type: object
                          properties:
                            name:
                              type: string
                            variable:
                              type: string
                            mockValue:
                              type: string
                      variables_tree:
                        type: object
                        properties:
                          order:
                            type: object
                            properties:
                              label:
                                type: string
                              children:
                                type: object
                                properties:
                                  number:
                                    type: object
                                    properties:
                                      label:
                                        type: string
                                      type:
                                        type: string
                                      mock:
                                        type: string
                      schema:
                        type: object
                        properties:
                          order:
                            type: object
                            properties:
                              label:
                                type: string
                              children:
                                type: object
                                properties:
                                  number:
                                    type: object
                                    properties:
                                      label:
                                        type: string
                                      type:
                                        type: string
                                      mock:
                                        type: string
                      store_id:
                        type: string
                        nullable: true
                      store_name:
                        type: string
                        nullable: true
                      updated_at:
                        type: string
                example:
                  data:
                    id: 1
                    name: Purchase Order
                    content: <html><body><h1>Purchase Order {{order_number}}</h1></body></html>
                    type: purchase_order
                    description: Default purchase order layout.
                    variables:
                    - name: Order Number
                      variable: order_number
                      mockValue: PO-2044
                    - name: Vendor Name
                      variable: vendor_name
                      mockValue: Acme Supply Co.
                    variables_tree:
                      order:
                        label: Order
                        children:
                          number:
                            label: Order Number
                            type: string
                            mock: PO-2044
                    schema:
                      order:
                        label: Order
                        children:
                          number:
                            label: Order Number
                            type: string
                            mock: PO-2044
                    store_id: null
                    store_name: null
                    updated_at: '2026-07-20T14:32:10+00:00'
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No query results for model
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: get-api-pdf-templates-id
    put:
      tags:
      - PDF Templates
      summary: Update PDF Template
      description: 'Updates the `content` of a PDF template and snapshots the previous
        content as a new version.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Bearer Personal Access Token with the `settings` scope (write
        access).


        Fields:

        - content (required): the template markup string.

        - updated_at (optional): the template''s last-known `updated_at` timestamp.
        When supplied it enables optimistic-lock checking so a concurrent edit is
        rejected instead of silently overwritten.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                content:
                  type: string
                updated_at:
                  type: string
              example:
                content: <html><body><h1>Purchase Order {{order_number}}</h1><p>Updated
                  layout</p></body></html>
                updated_at: '2026-07-20T14:32:10+00:00'
      parameters:
      - name: id
        in: path
        schema:
          type: string
        required: true
        description: The record ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      content:
                        type: string
                      type:
                        type: string
                      description:
                        type: string
                      variables:
                        type: array
                        items:
                          type: object
                          properties:
                            name:
                              type: string
                            variable:
                              type: string
                            mockValue:
                              type: string
                      variables_tree:
                        type: object
                        properties:
                          order:
                            type: object
                            properties:
                              label:
                                type: string
                              children:
                                type: object
                                properties:
                                  number:
                                    type: object
                                    properties:
                                      label:
                                        type: string
                                      type:
                                        type: string
                                      mock:
                                        type: string
                      schema:
                        type: object
                        properties:
                          order:
                            type: object
                            properties:
                              label:
                                type: string
                              children:
                                type: object
                                properties:
                                  number:
                                    type: object
                                    properties:
                                      label:
                                        type: string
                                      type:
                                        type: string
                                      mock:
                                        type: string
                      store_id:
                        type: string
                        nullable: true
                      store_name:
                        type: string
                        nullable: true
                      updated_at:
                        type: string
                example:
                  data:
                    id: 1
                    name: Purchase Order
                    content: <html><body><h1>Purchase Order {{order_number}}</h1><p>Updated
                      layout</p></body></html>
                    type: purchase_order
                    description: Default purchase order layout.
                    variables:
                    - name: Order Number
                      variable: order_number
                      mockValue: PO-2044
                    - name: Vendor Name
                      variable: vendor_name
                      mockValue: Acme Supply Co.
                    variables_tree:
                      order:
                        label: Order
                        children:
                          number:
                            label: Order Number
                            type: string
                            mock: PO-2044
                    schema:
                      order:
                        label: Order
                        children:
                          number:
                            label: Order Number
                            type: string
                            mock: PO-2044
                    store_id: null
                    store_name: null
                    updated_at: '2026-07-21T09:15:00+00:00'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      content:
                        type: array
                        items:
                          type: string
                example:
                  message: The given data was invalid.
                  errors:
                    content:
                    - The content field is required.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-session-only: true
      operationId: put-api-pdf-templates-id
  /api/pdf-templates/{id}/reset:
    post:
      tags:
      - PDF Templates
      summary: Reset PDF Template to Default
      description: 'Resets a PDF template back to its built-in default content and
        records the reset as a new version so the prior content can still be restored.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Bearer Personal Access Token with the `settings` scope (write
        access).'
      requestBody:
        content: {}
      parameters:
      - name: id
        in: path
        schema:
          type: string
        required: true
        description: The record ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      content:
                        type: string
                      type:
                        type: string
                      description:
                        type: string
                      variables:
                        type: array
                        items:
                          type: object
                          properties:
                            name:
                              type: string
                            variable:
                              type: string
                            mockValue:
                              type: string
                      variables_tree:
                        type: object
                        properties:
                          order:
                            type: object
                            properties:
                              label:
                                type: string
                              children:
                                type: object
                                properties:
                                  number:
                                    type: object
                                    properties:
                                      label:
                                        type: string
                                      type:
                                        type: string
                                      mock:
                                        type: string
                      schema:
                        type: object
                        properties:
                          order:
                            type: object
                            properties:
                              label:
                                type: string
                              children:
                                type: object
                                properties:
                                  number:
                                    type: object
                                    properties:
                                      label:
                                        type: string
                                      type:
                                        type: string
                                      mock:
                                        type: string
                      store_id:
                        type: string
                        nullable: true
                      store_name:
                        type: string
                        nullable: true
                      updated_at:
                        type: string
                example:
                  data:
                    id: 1
                    name: Purchase Order
                    content: <html><body><!-- default purchase order layout --></body></html>
                    type: purchase_order
                    description: Default purchase order layout.
                    variables:
                    - name: Order Number
                      variable: order_number
                      mockValue: PO-2044
                    - name: Vendor Name
                      variable: vendor_name
                      mockValue: Acme Supply Co.
                    variables_tree:
                      order:
                        label: Order
                        children:
                          number:
                            label: Order Number
                            type: string
                            mock: PO-2044
                    schema:
                      order:
                        label: Order
                        children:
                          number:
                            label: Order Number
                            type: string
                            mock: PO-2044
                    store_id: null
                    store_name: null
                    updated_at: '2026-07-20T14:32:10+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-session-only: true
      operationId: post-api-pdf-templates-id-reset
  /api/pdf-templates/{id}/preview:
    post:
      tags:
      - PDF Templates
      summary: Preview PDF Template
      description: 'Renders a preview of draft template content without saving it,
        using sample data.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Bearer Personal Access Token with the `settings` scope (read
        access).


        Fields:

        - content (required): the draft markup to render.

        - format (optional): `pdf` (default) returns a base64-encoded PDF in `data.pdf`;
        `html` returns rendered markup in `data.html`.

        - sales_order_id (optional): render against a real sales order''s data instead
        of sample data. Only applied for packing-slip templates; ignored for other
        types.


        Invalid template markup returns a 422 with the offending line rather than
        a server error.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                content:
                  type: string
                format:
                  type: string
                sales_order_id:
                  type: integer
              example:
                content: <html><body><h1>Packing Slip {{order_number}}</h1></body></html>
                format: pdf
                sales_order_id: 4821
      parameters:
      - name: id
        in: path
        schema:
          type: string
        required: true
        description: The record ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 OK (PDF)
                  value:
                    data:
                      pdf: JVBERi0xLjQKJeLjz9MKMyAwIG9iago8PC9UeXBlL1BhZ2UvUGFyZW50IDEgMCBSL1Jlc291cmNlcyAyIDAgUj4+CmVuZG9iagolJUVPRg==
                      type: application/pdf
                      rendered_with: wkhtmltopdf
                example-1:
                  summary: 200 OK (HTML)
                  value:
                    data:
                      html: <html><body><h1>Packing Slip SO-1001</h1></body></html>
                      rendered_with: interactive
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: array
                    items:
                      type: object
                      properties:
                        detail:
                          type: string
                        code:
                          type: string
                        source:
                          type: string
                example:
                  errors:
                  - detail: Unclosed section {{#items}} starting on line 4.
                    code: INVALID_TEMPLATE
                    source: content
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-session-only: true
      operationId: post-api-pdf-templates-id-preview
  /api/pdf-templates/preview-sales-order:
    post:
      tags:
      - PDF Templates
      summary: Preview Packing Slip for a Sales Order
      description: 'Renders the saved packing-slip template against a real sales order
        and returns a base64-encoded PDF in `data.pdf`.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Bearer Personal Access Token with the `settings` scope (read
        access).


        Fields:

        - sales_order_id (required): the sales order to render.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                sales_order_id:
                  type: integer
              example:
                sales_order_id: 4821
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      pdf:
                        type: string
                      type:
                        type: string
                example:
                  data:
                    pdf: JVBERi0xLjQKJeLjz9MKMyAwIG9iago8PC9UeXBlL1BhZ2UvUGFyZW50IDEgMCBSL1Jlc291cmNlcyAyIDAgUj4+CmVuZG9iagolJUVPRg==
                    type: application/pdf
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      sales_order_id:
                        type: array
                        items:
                          type: string
                example:
                  message: The given data was invalid.
                  errors:
                    sales_order_id:
                    - The selected sales order id is invalid.
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: post-api-pdf-templates-preview-sales-order
  /api/pdf-templates/search-sales-orders:
    get:
      tags:
      - PDF Templates
      summary: List Sales Orders for Preview
      description: 'Returns up to 20 recent sales orders (newest first) for use when
        picking a sample order to preview a packing slip against.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Bearer Personal Access Token with the `settings` scope (read
        access).


        Query params:

        - search (optional): match against the sales order number.

        - store_id (optional): restrict results to a single store.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        sales_order_number:
                          type: string
                        store_id:
                          type: integer
                        store_name:
                          type: string
                        order_date:
                          type: string
                example:
                  data:
                  - id: 4821
                    sales_order_number: SO-1001
                    store_id: 3
                    store_name: Acme Store
                    order_date: '2026-07-18T00:00:00+00:00'
                  - id: 4805
                    sales_order_number: SO-0998
                    store_id: 3
                    store_name: Acme Store
                    order_date: '2026-07-17T00:00:00+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: get-api-pdf-templates-search-sales-orders
  /api/pdf-templates/{id}/validate:
    post:
      tags:
      - PDF Templates
      summary: Validate PDF Template
      description: 'Validates draft template content against the template type''s
        schema without rendering it. Use this to surface unknown variables, unbalanced
        sections, and non-blocking warnings before saving.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Bearer Personal Access Token with the `settings` scope (read
        access).


        Fields:

        - content (required): the draft markup to validate.


        The response `data` contains `ok` (true when there are no errors), an `errors`
        array, and a `warnings` array.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                content:
                  type: string
              example:
                content: <html><body><h1>{{order_number}}</h1>{{#items}}<p>{{sku}}</p>{{/items}}</body></html>
      parameters:
      - name: id
        in: path
        schema:
          type: string
        required: true
        description: The record ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 OK (valid)
                  value:
                    data:
                      ok: true
                      errors: []
                      warnings:
                      - Template has no line-items block ({{items}} or {{#items}}…{{/items}}).
                        The PDF will render without itemized rows.
                example-1:
                  summary: 200 OK (with errors)
                  value:
                    data:
                      ok: false
                      errors:
                      - 'Unknown variable: {{customer_phne}}. Not in the schema for
                        this template type.'
                      warnings: []
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-session-only: true
      operationId: post-api-pdf-templates-id-validate
  /api/pdf-templates/{id}/versions:
    get:
      tags:
      - PDF Templates
      summary: List PDF Template Versions
      description: 'Returns the change history for a template, newest first, as a
        paginated list. Each version captures the content at that point plus who changed
        it and why.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Bearer Personal Access Token with the `settings` scope (read
        access).


        This endpoint returns a standard paginator envelope (`data`, `current_page`,
        `last_page`, `per_page`, `total`, …) rather than the `{ data: ... }` wrapper
        used by the other endpoints.


        Query params:

        - page (optional): page number (default 1).

        - per_page (optional): items per page (default 10).


        Version `source` is one of: manual, ai, reset, migration, import.'
      parameters:
      - name: id
        in: path
        schema:
          type: string
        required: true
        description: The record ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        pdf_template_id:
                          type: integer
                        content:
                          type: string
                        source:
                          type: string
                        source_label:
                          type: string
                        summary:
                          type: string
                        ai_message_id:
                          type: string
                          nullable: true
                        created_by:
                          type: integer
                        created_by_name:
                          type: string
                        created_at:
                          type: string
                  current_page:
                    type: integer
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  next_page_url:
                    type: string
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 58
                    pdf_template_id: 1
                    content: <html><body><h1>Purchase Order {{order_number}}</h1></body></html>
                    source: manual
                    source_label: Manual
                    summary: Updated footer address block.
                    ai_message_id: null
                    created_by: 7
                    created_by_name: Jane Smith
                    created_at: '2026-07-20T14:32:10+00:00'
                  - id: 57
                    pdf_template_id: 1
                    content: <html><body><h1>Purchase Order {{order_number}}</h1></body></html>
                    source: ai
                    source_label: AI
                    summary: Applied AI suggestion to restyle the header.
                    ai_message_id: null
                    created_by: 7
                    created_by_name: Jane Smith
                    created_at: '2026-07-20T14:32:10+00:00'
                  - id: 56
                    pdf_template_id: 1
                    content: <html><body><h1>Purchase Order {{order_number}}</h1></body></html>
                    source: reset
                    source_label: Reset
                    summary: Reset to default layout.
                    ai_message_id: null
                    created_by: 7
                    created_by_name: Ops Admin
                    created_at: '2026-07-20T14:32:10+00:00'
                  current_page: 1
                  first_page_url: '{{protocol}}{{domain}}/api/pdf-templates/1/versions?page=1'
                  from: 1
                  last_page: 4
                  last_page_url: '{{protocol}}{{domain}}/api/pdf-templates/1/versions?page=4'
                  next_page_url: '{{protocol}}{{domain}}/api/pdf-templates/1/versions?page=2'
                  path: '{{protocol}}{{domain}}/api/pdf-templates/1/versions'
                  per_page: 10
                  prev_page_url: null
                  to: 3
                  total: 34
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-session-only: true
      operationId: get-api-pdf-templates-id-versions
  /api/pdf-templates/{id}/versions/{versionId}:
    get:
      tags:
      - PDF Templates
      summary: Get PDF Template Version
      description: 'Returns a single template version by ID, including its full content
        snapshot.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Bearer Personal Access Token with the `settings` scope (read
        access).'
      parameters:
      - name: id
        in: path
        schema:
          type: string
        required: true
        description: The record ID.
      - name: versionId
        in: path
        schema:
          type: string
        required: true
        description: The version ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      pdf_template_id:
                        type: integer
                      content:
                        type: string
                      source:
                        type: string
                      source_label:
                        type: string
                      summary:
                        type: string
                      ai_message_id:
                        type: string
                        nullable: true
                      created_by:
                        type: integer
                      created_by_name:
                        type: string
                      created_at:
                        type: string
                example:
                  data:
                    id: 58
                    pdf_template_id: 1
                    content: <html><body><h1>Purchase Order {{order_number}}</h1></body></html>
                    source: manual
                    source_label: Manual
                    summary: Updated footer address block.
                    ai_message_id: null
                    created_by: 7
                    created_by_name: Jane Smith
                    created_at: '2026-07-20T14:32:10+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-session-only: true
      operationId: get-api-pdf-templates-id-versions-versionid
  /api/pdf-templates/{id}/versions/{versionId}/restore:
    post:
      tags:
      - PDF Templates
      summary: Restore PDF Template Version
      description: 'Restores a prior template version, replacing the template''s current
        content with that version''s snapshot and recording the previous content as
        a new version.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Bearer Personal Access Token with the `settings` scope (write
        access).'
      requestBody:
        content: {}
      parameters:
      - name: id
        in: path
        schema:
          type: string
        required: true
        description: The record ID.
      - name: versionId
        in: path
        schema:
          type: string
        required: true
        description: The version ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      content:
                        type: string
                      type:
                        type: string
                      description:
                        type: string
                      variables:
                        type: array
                        items:
                          type: object
                          properties:
                            name:
                              type: string
                            variable:
                              type: string
                            mockValue:
                              type: string
                      variables_tree:
                        type: object
                        properties:
                          order:
                            type: object
                            properties:
                              label:
                                type: string
                              children:
                                type: object
                                properties:
                                  number:
                                    type: object
                                    properties:
                                      label:
                                        type: string
                                      type:
                                        type: string
                                      mock:
                                        type: string
                      schema:
                        type: object
                        properties:
                          order:
                            type: object
                            properties:
                              label:
                                type: string
                              children:
                                type: object
                                properties:
                                  number:
                                    type: object
                                    properties:
                                      label:
                                        type: string
                                      type:
                                        type: string
                                      mock:
                                        type: string
                      store_id:
                        type: string
                        nullable: true
                      store_name:
                        type: string
                        nullable: true
                      updated_at:
                        type: string
                example:
                  data:
                    id: 1
                    name: Purchase Order
                    content: <html><body><h1>Purchase Order {{order_number}}</h1></body></html>
                    type: purchase_order
                    description: Default purchase order layout.
                    variables:
                    - name: Order Number
                      variable: order_number
                      mockValue: PO-2044
                    - name: Vendor Name
                      variable: vendor_name
                      mockValue: Acme Supply Co.
                    variables_tree:
                      order:
                        label: Order
                        children:
                          number:
                            label: Order Number
                            type: string
                            mock: PO-2044
                    schema:
                      order:
                        label: Order
                        children:
                          number:
                            label: Order Number
                            type: string
                            mock: PO-2044
                    store_id: null
                    store_name: null
                    updated_at: '2026-07-21T09:20:00+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-session-only: true
      operationId: post-api-pdf-templates-id-versions-versionid-restore
  /api/pdf-templates/{type}/store-overrides:
    get:
      tags:
      - PDF Templates
      summary: List Store Overrides
      description: 'Returns every store-specific override for a given template type.
        A store override is a copy of the global template that a single store can
        customize independently.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Bearer Personal Access Token with the `settings` scope (read
        access).


        Path params:

        - type: template type — one of purchase_order, sales_order, packing, quote,
        pick_list, vendor_credit, sales_credit.'
      parameters:
      - name: type
        in: path
        schema:
          type: string
        required: true
        description: The type ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        content:
                          type: string
                        type:
                          type: string
                        description:
                          type: string
                        variables:
                          type: array
                          items:
                            type: object
                            properties:
                              name:
                                type: string
                              variable:
                                type: string
                              mockValue:
                                type: string
                        variables_tree:
                          type: object
                          properties:
                            order:
                              type: object
                              properties:
                                label:
                                  type: string
                                children:
                                  type: object
                                  properties:
                                    number:
                                      type: object
                                      properties:
                                        label:
                                          type: string
                                        type:
                                          type: string
                                        mock:
                                          type: string
                            items:
                              type: object
                              properties:
                                label:
                                  type: string
                                type:
                                  type: string
                                mock:
                                  type: string
                            asset:
                              type: object
                              properties:
                                label:
                                  type: string
                                children:
                                  type: object
                                  properties:
                                    company_logo:
                                      type: object
                                      properties:
                                        label:
                                          type: string
                                        type:
                                          type: string
                                        mock:
                                          type: string
                        schema:
                          type: object
                          properties:
                            order:
                              type: object
                              properties:
                                label:
                                  type: string
                                children:
                                  type: object
                                  properties:
                                    number:
                                      type: object
                                      properties:
                                        label:
                                          type: string
                                        type:
                                          type: string
                                        mock:
                                          type: string
                            items:
                              type: object
                              properties:
                                label:
                                  type: string
                                type:
                                  type: string
                                mock:
                                  type: string
                            asset:
                              type: object
                              properties:
                                label:
                                  type: string
                                children:
                                  type: object
                                  properties:
                                    company_logo:
                                      type: object
                                      properties:
                                        label:
                                          type: string
                                        type:
                                          type: string
                                        mock:
                                          type: string
                        store_id:
                          type: integer
                        store_name:
                          type: string
                        updated_at:
                          type: string
                example:
                  data:
                  - id: 42
                    name: Packing Slip
                    content: <html><body><h1>Packing Slip {{order_number}}</h1>{{#items}}<p>{{sku}}
                      x {{quantity}}</p>{{/items}}</body></html>
                    type: packing
                    description: Default packing slip layout.
                    variables:
                    - name: Order Number
                      variable: order_number
                      mockValue: SO-1001
                    - name: Warehouse
                      variable: warehouse
                      mockValue: Main Warehouse
                    - name: Items
                      variable: items
                      mockValue: ''
                    variables_tree:
                      order:
                        label: Order
                        children:
                          number:
                            label: Order Number
                            type: string
                            mock: SO-1001
                      items:
                        label: Items
                        type: section
                        mock: ''
                      asset:
                        label: Custom Assets
                        children:
                          company_logo:
                            label: Company Logo
                            type: html
                            mock: ''
                    schema:
                      order:
                        label: Order
                        children:
                          number:
                            label: Order Number
                            type: string
                            mock: SO-1001
                      items:
                        label: Items
                        type: section
                        mock: ''
                      asset:
                        label: Custom Assets
                        children:
                          company_logo:
                            label: Company Logo
                            type: html
                            mock: ''
                    store_id: 3
                    store_name: Acme Store
                    updated_at: '2026-07-20T14:32:10+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-session-only: true
      operationId: get-api-pdf-templates-type-store-overrides
  /api/pdf-templates/{id}/store-override:
    post:
      tags:
      - PDF Templates
      summary: Create Store Override
      description: 'Creates a store-specific override from a global template. The
        override starts with the global template''s content and can then be edited
        independently for that store.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Bearer Personal Access Token with the `settings` scope (write
        access).


        Fields:

        - store_id (required): the store the override is created for.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                store_id:
                  type: integer
              example:
                store_id: 3
      parameters:
      - name: id
        in: path
        schema:
          type: string
        required: true
        description: The record ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      content:
                        type: string
                      type:
                        type: string
                      description:
                        type: string
                      variables:
                        type: array
                        items:
                          type: object
                          properties:
                            name:
                              type: string
                            variable:
                              type: string
                            mockValue:
                              type: string
                      variables_tree:
                        type: object
                        properties:
                          order:
                            type: object
                            properties:
                              label:
                                type: string
                              children:
                                type: object
                                properties:
                                  number:
                                    type: object
                                    properties:
                                      label:
                                        type: string
                                      type:
                                        type: string
                                      mock:
                                        type: string
                          items:
                            type: object
                            properties:
                              label:
                                type: string
                              type:
                                type: string
                              mock:
                                type: string
                          asset:
                            type: object
                            properties:
                              label:
                                type: string
                              children:
                                type: object
                                properties:
                                  company_logo:
                                    type: object
                                    properties:
                                      label:
                                        type: string
                                      type:
                                        type: string
                                      mock:
                                        type: string
                      schema:
                        type: object
                        properties:
                          order:
                            type: object
                            properties:
                              label:
                                type: string
                              children:
                                type: object
                                properties:
                                  number:
                                    type: object
                                    properties:
                                      label:
                                        type: string
                                      type:
                                        type: string
                                      mock:
                                        type: string
                          items:
                            type: object
                            properties:
                              label:
                                type: string
                              type:
                                type: string
                              mock:
                                type: string
                          asset:
                            type: object
                            properties:
                              label:
                                type: string
                              children:
                                type: object
                                properties:
                                  company_logo:
                                    type: object
                                    properties:
                                      label:
                                        type: string
                                      type:
                                        type: string
                                      mock:
                                        type: string
                      store_id:
                        type: integer
                      store_name:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 42
                    name: Packing Slip
                    content: <html><body><h1>Packing Slip {{order_number}}</h1>{{#items}}<p>{{sku}}
                      x {{quantity}}</p>{{/items}}</body></html>
                    type: packing
                    description: Default packing slip layout.
                    variables:
                    - name: Order Number
                      variable: order_number
                      mockValue: SO-1001
                    - name: Warehouse
                      variable: warehouse
                      mockValue: Main Warehouse
                    - name: Items
                      variable: items
                      mockValue: ''
                    variables_tree:
                      order:
                        label: Order
                        children:
                          number:
                            label: Order Number
                            type: string
                            mock: SO-1001
                      items:
                        label: Items
                        type: section
                        mock: ''
                      asset:
                        label: Custom Assets
                        children:
                          company_logo:
                            label: Company Logo
                            type: html
                            mock: ''
                    schema:
                      order:
                        label: Order
                        children:
                          number:
                            label: Order Number
                            type: string
                            mock: SO-1001
                      items:
                        label: Items
                        type: section
                        mock: ''
                      asset:
                        label: Custom Assets
                        children:
                          company_logo:
                            label: Company Logo
                            type: html
                            mock: ''
                    store_id: 3
                    store_name: Acme Store
                    updated_at: '2026-07-20T14:32:10+00:00'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      store_id:
                        type: array
                        items:
                          type: string
                example:
                  message: The given data was invalid.
                  errors:
                    store_id:
                    - The selected store id is invalid.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-session-only: true
      operationId: post-api-pdf-templates-id-store-override
    delete:
      tags:
      - PDF Templates
      summary: Delete Store Override
      description: 'Deletes a store-specific override. That store reverts to the global
        template of the same type.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Bearer Personal Access Token with the `settings` scope (write
        access).


        Path params:

        - id: the ID of the store override template to delete.'
      parameters:
      - name: id
        in: path
        schema:
          type: string
        required: true
        description: The record ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      message:
                        type: string
                example:
                  data:
                    message: Store override deleted successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-session-only: true
      operationId: delete-api-pdf-templates-id-store-override
  /api/pdf-template-assets:
    get:
      tags:
      - PDF Templates
      summary: List Template Assets
      description: 'Returns every uploaded image asset available to templates. Reference
        an asset inside template content with its `token` (for example `{{{asset.company_logo}}}`),
        which renders as an inline image in the PDF.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Bearer Personal Access Token with the `settings` scope (read
        access).'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        slug:
                          type: string
                        name:
                          type: string
                        mime_type:
                          type: string
                        size_bytes:
                          type: integer
                        width:
                          type: integer
                        height:
                          type: integer
                        url:
                          type: string
                        token:
                          type: string
                        created_at:
                          type: string
                example:
                  data:
                  - id: 11
                    slug: company_logo
                    name: Company Logo
                    mime_type: image/png
                    size_bytes: 20481
                    width: 320
                    height: 120
                    url: https://assets.sku.io/pdf-template-assets/company_logo.png
                    token: '{{{asset.company_logo}}}'
                    created_at: '2026-07-19T11:05:00+00:00'
                  - id: 12
                    slug: signature
                    name: Signature
                    mime_type: image/png
                    size_bytes: 20481
                    width: 320
                    height: 120
                    url: https://assets.sku.io/pdf-template-assets/signature.png
                    token: '{{{asset.signature}}}'
                    created_at: '2026-07-19T11:05:00+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: get-api-pdf-template-assets
    post:
      tags:
      - PDF Templates
      summary: Upload Template Asset
      description: 'Uploads a new image asset for use in templates. Send the request
        as multipart/form-data.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Bearer Personal Access Token with the `settings` scope (write
        access).


        Fields:

        - image (required): the image file (JPG, PNG, GIF, or WEBP, max 5 MB).

        - name (optional): a display name; the reference slug is derived from it.


        The response includes the generated `slug` and the `token` you place in template
        content.'
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                image:
                  type: string
                  format: binary
                name:
                  type: string
                  example: Company Logo
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      slug:
                        type: string
                      name:
                        type: string
                      mime_type:
                        type: string
                      size_bytes:
                        type: integer
                      width:
                        type: integer
                      height:
                        type: integer
                      url:
                        type: string
                      token:
                        type: string
                      created_at:
                        type: string
                example:
                  data:
                    id: 13
                    slug: company_logo
                    name: Company Logo
                    mime_type: image/png
                    size_bytes: 20481
                    width: 320
                    height: 120
                    url: https://assets.sku.io/pdf-template-assets/company_logo.png
                    token: '{{{asset.company_logo}}}'
                    created_at: '2026-07-19T11:05:00+00:00'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      image:
                        type: array
                        items:
                          type: string
                example:
                  message: The given data was invalid.
                  errors:
                    image:
                    - 'Allowed formats: JPG, PNG, GIF, WEBP.'
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: post-api-pdf-template-assets
  /api/pdf-template-assets/{id}:
    delete:
      tags:
      - PDF Templates
      summary: Delete Template Asset
      description: 'Deletes an uploaded image asset. Templates that reference the
        asset''s token will no longer render its image.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Bearer Personal Access Token with the `settings` scope (write
        access).


        Path params:

        - id: the ID of the asset to delete.'
      parameters:
      - name: id
        in: path
        schema:
          type: string
        required: true
        description: The record ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      message:
                        type: string
                example:
                  data:
                    message: Asset deleted.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-session-only: true
      operationId: delete-api-pdf-template-assets-id
  /api/data-tables:
    get:
      tags:
      - UI Utilities
      summary: Query list view Model
      description: 'Execute a paginated list view query against a model. The model
        must implement DataTableBlueprintInterface. Supports search, filtering (via
        filter[] params or a saved_view_id), and pagination.


        Authentication: Requires Bearer token.


        Query Parameters:

        - model (required, string): Fully qualified model class name

        - search (optional, string): Full-text search query

        - filter (optional, array): Filter conditions — mutually exclusive with saved_view_id

        - saved_view_id (optional, integer): Load state from a saved view — mutually
        exclusive with filter[]

        - include_data_table_blueprint (optional, boolean): Include the blueprint
        config in response

        - include_saved_views (optional, boolean): Include all saved views for the
        model


        Errors:

        - 400 ScopeFilterDoesNotExistException: Invalid filter scope

        - 400 BadScopeFilterValueException: Invalid filter value'
      parameters:
      - name: model
        in: query
        schema:
          type: string
        description: Required. Fully qualified model class name (must implement DataTableBlueprintInterface)
        example: App%5CModels%5CSalesOrder
      - name: search
        in: query
        schema:
          type: string
        description: Optional. Full-text search query
        example: C-1001
      - name: include_data_table_blueprint
        in: query
        schema:
          type: boolean
        description: Optional boolean. Include blueprint config and searchable fields
          in response
        example: 'false'
      - name: include_saved_views
        in: query
        schema:
          type: boolean
        description: Optional boolean. Include saved views for the model in response
        example: 'false'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        sales_order_number:
                          type: string
                        status:
                          type: string
                        created_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - id: 1001
                    sales_order_number: C-1001
                    status: open
                    created_at: '2024-04-15T10:00:00.000000Z'
                  current_page: 1
                  last_page: 5
                  per_page: 15
                  total: 73
                  from: 1
                  to: 15
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: array
                    items:
                      type: object
                      properties:
                        message:
                          type: string
                        code:
                          type: string
                        field:
                          type: string
                example:
                  errors:
                  - message: Scope filter 'invalid_scope' does not exist on this model.
                    code: ScopeFilterDoesNotExistException
                    field: invalid_filter
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-data-tables
  /horizon-restart:
    get:
      tags:
      - Horizon
      summary: Restart Horizon
      description: 'Custom application endpoint to trigger a Horizon restart. This
        sends a restart signal to Horizon workers, causing them to finish their current
        job and restart gracefully.


        Authentication: Requires Bearer token.


        Note: This endpoint is at /horizon-restart (not under /horizon/api).'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Horizon restart signal sent.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-horizon-restart
  /api/automation/workflows:
    get:
      tags:
      - Workflows
      summary: List Workflows
      description: 'Paginated list of automation workflows with run statistics (total,
        successful, and failed runs, average duration, and last run).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Filters:** `filter[status]` (draft, published, disabled), `filter[category]`,
        `filter[search]` (matches name or description).


        **Sorts:** `name`, `created_at`, `updated_at`. Prefix with `-` for descending.
        Default: `-updated_at`.


        Pagination: `page`, `per_page` (default 10).'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: string
                        name:
                          type: string
                        description:
                          type: string
                        status:
                          type: string
                        category:
                          type: string
                        version:
                          type: integer
                        triggerCount:
                          type: integer
                        nodeCount:
                          type: integer
                        stats:
                          type: object
                          properties:
                            totalRuns:
                              type: integer
                            successfulRuns:
                              type: integer
                            failedRuns:
                              type: integer
                            avgDuration:
                              type: integer
                            lastRun:
                              type: object
                              properties:
                                startedAt:
                                  type: string
                                status:
                                  type: string
                                duration:
                                  type: integer
                        createdAt:
                          type: string
                        updatedAt:
                          type: string
                        createdBy:
                          type: string
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: '7'
                    name: Notify on new sales orders
                    description: Posts a Slack message whenever a sales order is created
                    status: published
                    category: orders
                    version: 3
                    triggerCount: 1
                    nodeCount: 2
                    stats:
                      totalRuns: 128
                      successfulRuns: 126
                      failedRuns: 2
                      avgDuration: 1840
                      lastRun:
                        startedAt: '2026-07-05T09:12:44+00:00'
                        status: success
                        duration: 1650
                    createdAt: '2026-05-02T10:00:00+00:00'
                    updatedAt: '2026-07-01T08:30:00+00:00'
                    createdBy: Jane Smith
                  first_page_url: https://your-domain.sku.io/api/automation/workflows?page=1
                  from: 1
                  last_page: 1
                  last_page_url: https://your-domain.sku.io/api/automation/workflows?page=1
                  links: []
                  next_page_url: null
                  path: https://your-domain.sku.io/api/automation/workflows
                  per_page: 10
                  prev_page_url: null
                  to: 1
                  total: 1
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-automation-workflows
    post:
      tags:
      - Workflows
      summary: Create Workflow
      description: 'Create a new workflow in Draft status from a node/edge graph.
        The workflow''s trigger type is derived automatically from the trigger node
        in the graph.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Body fields:** `name` (required, string, max 128), `description` (optional),
        `category` (optional, string, max 50), `nodes` (required array - may be empty
        while drafting), `edges` (required array), `viewport` (optional canvas position
        object).


        Use List Workflow Node Types to discover valid `nodes[*].type` values and
        each node''s settings. Draft workflows are not executable until published.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                description:
                  type: string
                category:
                  type: string
                nodes:
                  type: array
                  items:
                    type: object
                    properties:
                      id:
                        type: string
                      type:
                        type: string
                      position:
                        type: object
                        properties:
                          x:
                            type: integer
                          y:
                            type: integer
                      data:
                        type: object
                        properties: {}
                      label:
                        type: string
                edges:
                  type: array
                  items:
                    type: object
                    properties:
                      id:
                        type: string
                      source:
                        type: string
                      target:
                        type: string
                viewport:
                  type: object
                  properties:
                    x:
                      type: integer
                    y:
                      type: integer
                    zoom:
                      type: integer
              example:
                name: Notify on new sales orders
                description: Posts a Slack message whenever a sales order is created
                category: orders
                nodes:
                - id: node_1
                  type: sales-order-created
                  position:
                    x: 80
                    y: 120
                  data: {}
                  label: Sales Order Created
                - id: node_2
                  type: slack-message
                  position:
                    x: 360
                    y: 120
                  data:
                    channel: '#orders'
                  label: Send Slack Message
                edges:
                - id: edge_1
                  source: node_1
                  target: node_2
                viewport:
                  x: 0
                  y: 0
                  zoom: 1
      parameters: []
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: string
                  uuid:
                    type: string
                  name:
                    type: string
                  description:
                    type: string
                  status:
                    type: string
                  version:
                    type: integer
                  category:
                    type: string
                  graph:
                    type: object
                    properties:
                      nodes:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: string
                            type:
                              type: string
                            position:
                              type: object
                              properties:
                                x:
                                  type: integer
                                y:
                                  type: integer
                            data:
                              type: object
                              properties: {}
                            label:
                              type: string
                      edges:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: string
                            source:
                              type: string
                            target:
                              type: string
                      viewport:
                        type: object
                        properties:
                          x:
                            type: integer
                          y:
                            type: integer
                          zoom:
                            type: integer
                  settings:
                    type: string
                    nullable: true
                  triggerType:
                    type: string
                  triggerConfig:
                    type: string
                    nullable: true
                  createdAt:
                    type: string
                  updatedAt:
                    type: string
                  publishedAt:
                    type: string
                    nullable: true
                  createdBy:
                    type: string
                  updatedBy:
                    type: string
                example:
                  id: '8'
                  uuid: 0f7a3c2e-9d41-4b8a-b1f2-6a5c88e01234
                  name: Notify on new sales orders
                  description: Posts a Slack message whenever a sales order is created
                  status: draft
                  version: 1
                  category: orders
                  graph:
                    nodes:
                    - id: node_1
                      type: sales-order-created
                      position:
                        x: 80
                        y: 120
                      data: {}
                      label: Sales Order Created
                    - id: node_2
                      type: slack-message
                      position:
                        x: 360
                        y: 120
                      data:
                        channel: '#orders'
                      label: Send Slack Message
                    edges:
                    - id: edge_1
                      source: node_1
                      target: node_2
                    viewport:
                      x: 0
                      y: 0
                      zoom: 1
                  settings: null
                  triggerType: event
                  triggerConfig: null
                  createdAt: '2026-05-02T10:00:00+00:00'
                  updatedAt: '2026-07-01T08:30:00+00:00'
                  publishedAt: null
                  createdBy: Jane Smith
                  updatedBy: Jane Smith
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      name:
                        type: array
                        items:
                          type: string
                example:
                  message: The name field is required.
                  errors:
                    name:
                    - The name field is required.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-automation-workflows
  /api/automation/workflows/{workflow}:
    get:
      tags:
      - Workflows
      summary: Get Workflow
      description: 'Get a single workflow with its full node/edge graph, trigger configuration,
        and publication state.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Path param: workflow = workflow id.'
      parameters:
      - name: workflow
        in: path
        schema:
          type: integer
        required: true
        example: '7'
        description: The workflow ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: string
                  uuid:
                    type: string
                  name:
                    type: string
                  description:
                    type: string
                  status:
                    type: string
                  version:
                    type: integer
                  category:
                    type: string
                  graph:
                    type: object
                    properties:
                      nodes:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: string
                            type:
                              type: string
                            position:
                              type: object
                              properties:
                                x:
                                  type: integer
                                y:
                                  type: integer
                            data:
                              type: object
                              properties: {}
                            label:
                              type: string
                      edges:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: string
                            source:
                              type: string
                            target:
                              type: string
                      viewport:
                        type: object
                        properties:
                          x:
                            type: integer
                          y:
                            type: integer
                          zoom:
                            type: integer
                  settings:
                    type: string
                    nullable: true
                  triggerType:
                    type: string
                  triggerConfig:
                    type: string
                    nullable: true
                  createdAt:
                    type: string
                  updatedAt:
                    type: string
                  publishedAt:
                    type: string
                  createdBy:
                    type: string
                  updatedBy:
                    type: string
                example:
                  id: '7'
                  uuid: 0f7a3c2e-9d41-4b8a-b1f2-6a5c88e01234
                  name: Notify on new sales orders
                  description: Posts a Slack message whenever a sales order is created
                  status: published
                  version: 3
                  category: orders
                  graph:
                    nodes:
                    - id: node_1
                      type: sales-order-created
                      position:
                        x: 80
                        y: 120
                      data: {}
                      label: Sales Order Created
                    - id: node_2
                      type: slack-message
                      position:
                        x: 360
                        y: 120
                      data:
                        channel: '#orders'
                      label: Send Slack Message
                    edges:
                    - id: edge_1
                      source: node_1
                      target: node_2
                    viewport:
                      x: 0
                      y: 0
                      zoom: 1
                  settings: null
                  triggerType: event
                  triggerConfig: null
                  createdAt: '2026-05-02T10:00:00+00:00'
                  updatedAt: '2026-07-01T08:30:00+00:00'
                  publishedAt: '2026-06-15T11:05:00+00:00'
                  createdBy: Jane Smith
                  updatedBy: Jane Smith
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-automation-workflows-workflow
    put:
      tags:
      - Workflows
      summary: Update Workflow
      description: 'Update a workflow''s name, description, category, graph, or settings.
        When `nodes` are submitted, the trigger type and trigger configuration are
        re-derived from the graph.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Body fields (all optional):** `name` (string, max 128), `description`, `category`
        (string, max 50), `nodes` (array - each node requires `id` (string, max 64),
        `type` (string, max 100), `position.x`/`position.y` (numeric), `data` (object,
        required per node), optional `label`), `edges` (array - each edge requires
        `id`, `source`, `target`; optional `sourceHandle`, `targetHandle`, `label`,
        `branchLabel`), `viewport`, `settings`.


        Path param: workflow = workflow id.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                nodes:
                  type: array
                  items:
                    type: object
                    properties:
                      id:
                        type: string
                      type:
                        type: string
                      position:
                        type: object
                        properties:
                          x:
                            type: integer
                          y:
                            type: integer
                      data:
                        type: object
                        properties: {}
                      label:
                        type: string
                edges:
                  type: array
                  items:
                    type: object
                    properties:
                      id:
                        type: string
                      source:
                        type: string
                      target:
                        type: string
                viewport:
                  type: object
                  properties:
                    x:
                      type: integer
                    y:
                      type: integer
                    zoom:
                      type: integer
                settings:
                  type: object
                  properties:
                    errorHandling:
                      type: string
              example:
                name: Notify on new sales orders
                nodes:
                - id: node_1
                  type: sales-order-created
                  position:
                    x: 80
                    y: 120
                  data: {}
                  label: Sales Order Created
                - id: node_2
                  type: slack-message
                  position:
                    x: 360
                    y: 120
                  data:
                    channel: '#orders'
                  label: Send Slack Message
                edges:
                - id: edge_1
                  source: node_1
                  target: node_2
                viewport:
                  x: 0
                  y: 0
                  zoom: 1
                settings:
                  errorHandling: stop
      parameters:
      - name: workflow
        in: path
        schema:
          type: integer
        required: true
        example: '7'
        description: The workflow ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: string
                  uuid:
                    type: string
                  name:
                    type: string
                  description:
                    type: string
                  status:
                    type: string
                  version:
                    type: integer
                  category:
                    type: string
                  graph:
                    type: object
                    properties:
                      nodes:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: string
                            type:
                              type: string
                            position:
                              type: object
                              properties:
                                x:
                                  type: integer
                                y:
                                  type: integer
                            data:
                              type: object
                              properties: {}
                            label:
                              type: string
                      edges:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: string
                            source:
                              type: string
                            target:
                              type: string
                      viewport:
                        type: object
                        properties:
                          x:
                            type: integer
                          y:
                            type: integer
                          zoom:
                            type: integer
                  settings:
                    type: string
                    nullable: true
                  triggerType:
                    type: string
                  triggerConfig:
                    type: string
                    nullable: true
                  createdAt:
                    type: string
                  updatedAt:
                    type: string
                  publishedAt:
                    type: string
                  createdBy:
                    type: string
                  updatedBy:
                    type: string
                example:
                  id: '7'
                  uuid: 0f7a3c2e-9d41-4b8a-b1f2-6a5c88e01234
                  name: Notify on new sales orders
                  description: Posts a Slack message whenever a sales order is created
                  status: published
                  version: 3
                  category: orders
                  graph:
                    nodes:
                    - id: node_1
                      type: sales-order-created
                      position:
                        x: 80
                        y: 120
                      data: {}
                      label: Sales Order Created
                    - id: node_2
                      type: slack-message
                      position:
                        x: 360
                        y: 120
                      data:
                        channel: '#orders'
                      label: Send Slack Message
                    edges:
                    - id: edge_1
                      source: node_1
                      target: node_2
                    viewport:
                      x: 0
                      y: 0
                      zoom: 1
                  settings: null
                  triggerType: event
                  triggerConfig: null
                  createdAt: '2026-05-02T10:00:00+00:00'
                  updatedAt: '2026-07-01T08:30:00+00:00'
                  publishedAt: '2026-06-15T11:05:00+00:00'
                  createdBy: Jane Smith
                  updatedBy: Jane Smith
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-automation-workflows-workflow
    delete:
      tags:
      - Workflows
      summary: Delete Workflow
      description: 'Permanently delete a workflow.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Path param: workflow = workflow id.'
      parameters:
      - name: workflow
        in: path
        schema:
          type: integer
        required: true
        example: '7'
        description: The workflow ID.
      responses:
        '204':
          description: No Content
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties: {}
                example: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-automation-workflows-workflow
  /api/automation/workflows/validate:
    post:
      tags:
      - Workflow Actions
      summary: Validate Workflow Graph
      description: 'Validate a node/edge graph without saving anything. Checks that
        the graph has exactly one trigger node, that every edge references existing
        nodes, and that every non-trigger node has an incoming connection.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Body fields:** `nodes` (required array), `edges` (required array).


        Each returned error has a `type` (`error` or `warning`), a `message`, and
        - when tied to a specific node - a `nodeId`. The graph is `valid` when no
        entries of type `error` are present.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                nodes:
                  type: array
                  items:
                    type: object
                    properties:
                      id:
                        type: string
                      type:
                        type: string
                      position:
                        type: object
                        properties:
                          x:
                            type: integer
                          y:
                            type: integer
                      data:
                        type: object
                        properties: {}
                      label:
                        type: string
                edges:
                  type: array
                  items:
                    type: object
                    properties:
                      id:
                        type: string
                      source:
                        type: string
                      target:
                        type: string
              example:
                nodes:
                - id: node_1
                  type: sales-order-created
                  position:
                    x: 80
                    y: 120
                  data: {}
                  label: Sales Order Created
                - id: node_2
                  type: slack-message
                  position:
                    x: 360
                    y: 120
                  data:
                    channel: '#orders'
                  label: Send Slack Message
                edges:
                - id: edge_1
                  source: node_1
                  target: node_2
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 Valid
                  value:
                    data:
                      valid: true
                      errors: []
                example-1:
                  summary: 200 Invalid Graph
                  value:
                    data:
                      valid: false
                      errors:
                      - type: error
                        message: Workflow must have exactly one trigger node
                      - type: error
                        nodeId: node_2
                        message: Node 'Send Slack Message' has no incoming connections
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-automation-workflows-validate
  /api/automation/workflows/{workflow}/publish:
    post:
      tags:
      - Workflow Actions
      summary: Publish Workflow
      description: 'Publish a workflow so its trigger becomes live. The graph is validated
        first - on failure nothing changes and the validation errors are returned
        with status 422. On success the version number is incremented, `publishedAt`
        is set, and the trigger type/configuration are re-derived from the graph.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Path param: workflow = workflow id.'
      requestBody:
        content: {}
      parameters:
      - name: workflow
        in: path
        schema:
          type: integer
        required: true
        example: '7'
        description: The workflow ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: string
                  uuid:
                    type: string
                  name:
                    type: string
                  description:
                    type: string
                  status:
                    type: string
                  version:
                    type: integer
                  category:
                    type: string
                  graph:
                    type: object
                    properties:
                      nodes:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: string
                            type:
                              type: string
                            position:
                              type: object
                              properties:
                                x:
                                  type: integer
                                y:
                                  type: integer
                            data:
                              type: object
                              properties: {}
                            label:
                              type: string
                      edges:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: string
                            source:
                              type: string
                            target:
                              type: string
                      viewport:
                        type: object
                        properties:
                          x:
                            type: integer
                          y:
                            type: integer
                          zoom:
                            type: integer
                  settings:
                    type: string
                    nullable: true
                  triggerType:
                    type: string
                  triggerConfig:
                    type: string
                    nullable: true
                  createdAt:
                    type: string
                  updatedAt:
                    type: string
                  publishedAt:
                    type: string
                  createdBy:
                    type: string
                  updatedBy:
                    type: string
                example:
                  id: '7'
                  uuid: 0f7a3c2e-9d41-4b8a-b1f2-6a5c88e01234
                  name: Notify on new sales orders
                  description: Posts a Slack message whenever a sales order is created
                  status: published
                  version: 3
                  category: orders
                  graph:
                    nodes:
                    - id: node_1
                      type: sales-order-created
                      position:
                        x: 80
                        y: 120
                      data: {}
                      label: Sales Order Created
                    - id: node_2
                      type: slack-message
                      position:
                        x: 360
                        y: 120
                      data:
                        channel: '#orders'
                      label: Send Slack Message
                    edges:
                    - id: edge_1
                      source: node_1
                      target: node_2
                    viewport:
                      x: 0
                      y: 0
                      zoom: 1
                  settings: null
                  triggerType: event
                  triggerConfig: null
                  createdAt: '2026-05-02T10:00:00+00:00'
                  updatedAt: '2026-07-01T08:30:00+00:00'
                  publishedAt: '2026-06-15T11:05:00+00:00'
                  createdBy: Jane Smith
                  updatedBy: Jane Smith
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: array
                    items:
                      type: object
                      properties:
                        type:
                          type: string
                        message:
                          type: string
                example:
                  message: Workflow validation failed
                  errors:
                  - type: error
                    message: Workflow must have exactly one trigger node
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-automation-workflows-workflow-publish
  /api/automation/workflows/{workflow}/toggle:
    post:
      tags:
      - Workflow Actions
      summary: Toggle Workflow
      description: 'Toggle a workflow between `published` (trigger live) and `disabled`
        (trigger paused). Only workflows in one of those two states can be toggled
        - draft workflows must be published first.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Path param: workflow = workflow id.'
      requestBody:
        content: {}
      parameters:
      - name: workflow
        in: path
        schema:
          type: integer
        required: true
        example: '7'
        description: The workflow ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: string
                  uuid:
                    type: string
                  name:
                    type: string
                  description:
                    type: string
                  status:
                    type: string
                  version:
                    type: integer
                  category:
                    type: string
                  graph:
                    type: object
                    properties:
                      nodes:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: string
                            type:
                              type: string
                            position:
                              type: object
                              properties:
                                x:
                                  type: integer
                                y:
                                  type: integer
                            data:
                              type: object
                              properties: {}
                            label:
                              type: string
                      edges:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: string
                            source:
                              type: string
                            target:
                              type: string
                      viewport:
                        type: object
                        properties:
                          x:
                            type: integer
                          y:
                            type: integer
                          zoom:
                            type: integer
                  settings:
                    type: string
                    nullable: true
                  triggerType:
                    type: string
                  triggerConfig:
                    type: string
                    nullable: true
                  createdAt:
                    type: string
                  updatedAt:
                    type: string
                  publishedAt:
                    type: string
                  createdBy:
                    type: string
                  updatedBy:
                    type: string
                example:
                  id: '7'
                  uuid: 0f7a3c2e-9d41-4b8a-b1f2-6a5c88e01234
                  name: Notify on new sales orders
                  description: Posts a Slack message whenever a sales order is created
                  status: disabled
                  version: 3
                  category: orders
                  graph:
                    nodes:
                    - id: node_1
                      type: sales-order-created
                      position:
                        x: 80
                        y: 120
                      data: {}
                      label: Sales Order Created
                    - id: node_2
                      type: slack-message
                      position:
                        x: 360
                        y: 120
                      data:
                        channel: '#orders'
                      label: Send Slack Message
                    edges:
                    - id: edge_1
                      source: node_1
                      target: node_2
                    viewport:
                      x: 0
                      y: 0
                      zoom: 1
                  settings: null
                  triggerType: event
                  triggerConfig: null
                  createdAt: '2026-05-02T10:00:00+00:00'
                  updatedAt: '2026-07-01T08:30:00+00:00'
                  publishedAt: '2026-06-15T11:05:00+00:00'
                  createdBy: Jane Smith
                  updatedBy: Jane Smith
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-automation-workflows-workflow-toggle
  /api/automation/workflows/{workflow}/clone:
    post:
      tags:
      - Workflow Actions
      summary: Clone Workflow
      description: 'Duplicate a workflow as a new Draft. The clone copies the graph,
        settings, and trigger configuration, and is named "&lt;name> (Copy)".


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Path param: workflow = workflow id.'
      requestBody:
        content: {}
      parameters:
      - name: workflow
        in: path
        schema:
          type: integer
        required: true
        example: '7'
        description: The workflow ID.
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: string
                  uuid:
                    type: string
                  name:
                    type: string
                  description:
                    type: string
                  status:
                    type: string
                  version:
                    type: integer
                  category:
                    type: string
                  graph:
                    type: object
                    properties:
                      nodes:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: string
                            type:
                              type: string
                            position:
                              type: object
                              properties:
                                x:
                                  type: integer
                                y:
                                  type: integer
                            data:
                              type: object
                              properties: {}
                            label:
                              type: string
                      edges:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: string
                            source:
                              type: string
                            target:
                              type: string
                      viewport:
                        type: object
                        properties:
                          x:
                            type: integer
                          y:
                            type: integer
                          zoom:
                            type: integer
                  settings:
                    type: string
                    nullable: true
                  triggerType:
                    type: string
                  triggerConfig:
                    type: string
                    nullable: true
                  createdAt:
                    type: string
                  updatedAt:
                    type: string
                  publishedAt:
                    type: string
                    nullable: true
                  createdBy:
                    type: string
                  updatedBy:
                    type: string
                example:
                  id: '9'
                  uuid: 0f7a3c2e-9d41-4b8a-b1f2-6a5c88e01234
                  name: Notify on new sales orders (Copy)
                  description: Posts a Slack message whenever a sales order is created
                  status: draft
                  version: 1
                  category: orders
                  graph:
                    nodes:
                    - id: node_1
                      type: sales-order-created
                      position:
                        x: 80
                        y: 120
                      data: {}
                      label: Sales Order Created
                    - id: node_2
                      type: slack-message
                      position:
                        x: 360
                        y: 120
                      data:
                        channel: '#orders'
                      label: Send Slack Message
                    edges:
                    - id: edge_1
                      source: node_1
                      target: node_2
                    viewport:
                      x: 0
                      y: 0
                      zoom: 1
                  settings: null
                  triggerType: event
                  triggerConfig: null
                  createdAt: '2026-05-02T10:00:00+00:00'
                  updatedAt: '2026-07-01T08:30:00+00:00'
                  publishedAt: null
                  createdBy: Jane Smith
                  updatedBy: Jane Smith
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-automation-workflows-workflow-clone
  /api/automation/workflows/{workflow}/execute:
    post:
      tags:
      - Workflow Actions
      summary: Execute Workflow
      description: 'Manually run a published workflow. The run is queued asynchronously:
        the response returns the new execution record immediately (status `pending`)
        - poll Get Workflow Execution for progress and step-by-step results.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Body fields:** `trigger_payload` (optional object) - data made available
        to the trigger node, in place of a real trigger event.


        Only published workflows can be executed. Returns 403 when workflow automation
        is disabled for the account.


        Path param: workflow = workflow id.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                trigger_payload:
                  type: object
                  properties:
                    salesOrderId:
                      type: integer
              example:
                trigger_payload:
                  salesOrderId: 1042
      parameters:
      - name: workflow
        in: path
        schema:
          type: integer
        required: true
        example: '7'
        description: The workflow ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: string
                  workflowId:
                    type: string
                  workflowVersion:
                    type: integer
                  status:
                    type: string
                  startedAt:
                    type: string
                    nullable: true
                  finishedAt:
                    type: string
                    nullable: true
                  duration:
                    type: string
                    nullable: true
                  triggerPayload:
                    type: object
                    properties:
                      salesOrderId:
                        type: integer
                  triggerReference:
                    type: string
                    nullable: true
                  errorMessage:
                    type: string
                    nullable: true
                example:
                  id: '513'
                  workflowId: '7'
                  workflowVersion: 3
                  status: pending
                  startedAt: null
                  finishedAt: null
                  duration: null
                  triggerPayload:
                    salesOrderId: 1042
                  triggerReference: null
                  errorMessage: null
        '403':
          description: Forbidden
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Workflow automation is disabled
        '429': *id001
        '401': *id002
        '404': *id004
        '422': *id005
      operationId: post-api-automation-workflows-workflow-execute
  /api/automation/workflows/{workflow}/upload-and-run:
    post:
      tags:
      - Workflow Actions
      summary: Upload File and Run Workflow
      description: 'Upload a file to a published workflow that has a File Upload trigger
        as its entry node, and run the workflow against it. The request is a `multipart/form-data`
        upload with a single `file` field.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        The run is queued asynchronously and the response returns 202 with an `idempotencyKey`
        that identifies the resulting execution - filter List Workflow Executions
        by `filter[search]` on that key to track it.


        Returns 422 when the workflow is not published, has no File Upload trigger,
        or the file fails the trigger''s format validation.


        Path param: workflow = workflow id.'
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                file:
                  type: string
                  description: Required. The file to run the workflow against. Accepted
                    formats depend on the workflow's File Upload trigger settings
                    (for example CSV or XLSX).
                  format: binary
      parameters:
      - name: workflow
        in: path
        schema:
          type: integer
        required: true
        example: '7'
        description: The workflow ID.
      responses:
        '202':
          description: Accepted
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  idempotencyKey:
                    type: string
                  fileName:
                    type: string
                example:
                  message: Upload accepted
                  idempotencyKey: 1c1f7c39-3f6e-4a9f-9a44-b1f0f2f9a001
                  fileName: orders.csv
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: This workflow does not have a File Upload trigger
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-automation-workflows-workflow-upload-and-run
  /api/automation/workflow-executions:
    get:
      tags:
      - Workflow Executions
      summary: List Workflow Executions
      description: 'Paginated list of workflow executions across all workflows, newest
        first. Each row includes the workflow name.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Filters:** `filter[status]`, `filter[workflow_id]`, `filter[date_range]`
        (last_hour, last_day, last_week, last_month), `filter[search]` (matches trigger
        reference or idempotency key).


        **Sorts:** `created_at`, `duration_ms`, `status`. Prefix with `-` for DESC.
        Default: `-created_at`.


        Pagination: `page`, `per_page` (default 15).


        Filter values use the stored statuses: pending, running, waiting, completed,
        failed, canceled. Response payloads expose display statuses where completed
        maps to success and canceled maps to cancelled.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: string
                        workflowId:
                          type: string
                        workflowVersion:
                          type: integer
                        status:
                          type: string
                        startedAt:
                          type: string
                        finishedAt:
                          type: string
                        duration:
                          type: integer
                        triggerPayload:
                          type: object
                          properties:
                            salesOrderId:
                              type: integer
                        triggerReference:
                          type: string
                        errorMessage:
                          type: string
                          nullable: true
                        workflowName:
                          type: string
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: '512'
                    workflowId: '7'
                    workflowVersion: 3
                    status: success
                    startedAt: '2026-07-05T09:12:44+00:00'
                    finishedAt: '2026-07-05T09:12:46+00:00'
                    duration: 1650
                    triggerPayload:
                      salesOrderId: 1042
                    triggerReference: SO-1042
                    errorMessage: null
                    workflowName: Notify on new sales orders
                  first_page_url: https://your-domain.sku.io/api/automation/workflow-executions?page=1
                  from: 1
                  last_page: 1
                  last_page_url: https://your-domain.sku.io/api/automation/workflow-executions?page=1
                  links: []
                  next_page_url: null
                  path: https://your-domain.sku.io/api/automation/workflow-executions
                  per_page: 15
                  prev_page_url: null
                  to: 1
                  total: 1
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-automation-workflow-executions
  /api/automation/workflow-executions/stats:
    get:
      tags:
      - Workflow Executions
      summary: Get Workflow Execution Stats
      description: 'Aggregate execution statistics across all workflows: total, successful,
        and failed run counts, the failure rate percentage, and the average run duration
        in milliseconds.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      totalRuns:
                        type: integer
                      successfulRuns:
                        type: integer
                      failedRuns:
                        type: integer
                      failureRate:
                        type: number
                      avgDuration:
                        type: integer
                example:
                  data:
                    totalRuns: 1284
                    successfulRuns: 1210
                    failedRuns: 74
                    failureRate: 5.8
                    avgDuration: 2140
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-automation-workflow-executions-stats
  /api/automation/workflow-executions/{execution}:
    get:
      tags:
      - Workflow Executions
      summary: Get Workflow Execution
      description: 'Get a single execution with its full step-by-step results - per
        node: input, output, logs, timing, attempt count, and per-item success/error
        counts.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Path param: execution = execution id.


        Filter values use the stored statuses: pending, running, waiting, completed,
        failed, canceled. Response payloads expose display statuses where completed
        maps to success and canceled maps to cancelled.'
      parameters:
      - name: execution
        in: path
        schema:
          type: integer
        required: true
        example: '512'
        description: The execution ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: string
                  workflowId:
                    type: string
                  workflowVersion:
                    type: integer
                  status:
                    type: string
                  startedAt:
                    type: string
                  finishedAt:
                    type: string
                  duration:
                    type: integer
                  triggerPayload:
                    type: object
                    properties:
                      salesOrderId:
                        type: integer
                  triggerReference:
                    type: string
                  errorMessage:
                    type: string
                    nullable: true
                  steps:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: string
                        executionId:
                          type: string
                        nodeId:
                          type: string
                        nodeName:
                          type: string
                        nodeType:
                          type: string
                        status:
                          type: string
                        startedAt:
                          type: string
                        finishedAt:
                          type: string
                        duration:
                          type: integer
                        attempt:
                          type: integer
                        input:
                          type: array
                        output:
                          type: object
                          properties:
                            salesOrderId:
                              type: integer
                            orderNumber:
                              type: string
                        errorMessage:
                          type: string
                          nullable: true
                        logs:
                          type: array
                        itemCount:
                          type: integer
                        itemSuccessCount:
                          type: integer
                        itemErrorCount:
                          type: integer
                        itemErrors:
                          type: array
                example:
                  id: '512'
                  workflowId: '7'
                  workflowVersion: 3
                  status: success
                  startedAt: '2026-07-05T09:12:44+00:00'
                  finishedAt: '2026-07-05T09:12:46+00:00'
                  duration: 1650
                  triggerPayload:
                    salesOrderId: 1042
                  triggerReference: SO-1042
                  errorMessage: null
                  steps:
                  - id: '2201'
                    executionId: '512'
                    nodeId: node_1
                    nodeName: Sales Order Created
                    nodeType: sales-order-created
                    status: success
                    startedAt: '2026-07-05T09:12:44+00:00'
                    finishedAt: '2026-07-05T09:12:44+00:00'
                    duration: 12
                    attempt: 1
                    input: []
                    output:
                      salesOrderId: 1042
                      orderNumber: SO-1042
                    errorMessage: null
                    logs: []
                    itemCount: 1
                    itemSuccessCount: 1
                    itemErrorCount: 0
                    itemErrors: []
                  - id: '2202'
                    executionId: '512'
                    nodeId: node_2
                    nodeName: Send Slack Message
                    nodeType: slack-message
                    status: success
                    startedAt: '2026-07-05T09:12:44+00:00'
                    finishedAt: '2026-07-05T09:12:46+00:00'
                    duration: 1610
                    attempt: 1
                    input:
                      salesOrderId: 1042
                      orderNumber: SO-1042
                    output:
                      ok: true
                    errorMessage: null
                    logs: []
                    itemCount: 1
                    itemSuccessCount: 1
                    itemErrorCount: 0
                    itemErrors: []
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-automation-workflow-executions-execution
    delete:
      tags:
      - Workflow Executions
      summary: Delete Workflow Execution
      description: 'Permanently delete an execution and its step results.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Path param: execution = execution id.'
      parameters:
      - name: execution
        in: path
        schema:
          type: integer
        required: true
        example: '512'
        description: The execution ID.
      responses:
        '204':
          description: No Content
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties: {}
                example: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-automation-workflow-executions-execution
  /api/automation/workflows/{workflow}/executions:
    get:
      tags:
      - Workflow Executions
      summary: List Executions for Workflow
      description: 'Paginated list of executions for one workflow, newest first.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Filters:** `filter[status]`, `filter[date_range]` (last_hour, last_day,
        last_week, last_month), `filter[search]` (matches trigger reference or idempotency
        key).


        **Sorts:** `created_at`. Prefix with `-` for DESC. Default: `-created_at`.


        Pagination: `page`, `per_page` (default 10).


        Path param: workflow = workflow id.


        Filter values use the stored statuses: pending, running, waiting, completed,
        failed, canceled. Response payloads expose display statuses where completed
        maps to success and canceled maps to cancelled.'
      parameters:
      - name: workflow
        in: path
        schema:
          type: integer
        required: true
        example: '7'
        description: The workflow ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: string
                        workflowId:
                          type: string
                        workflowVersion:
                          type: integer
                        status:
                          type: string
                        startedAt:
                          type: string
                        finishedAt:
                          type: string
                        duration:
                          type: integer
                        triggerPayload:
                          type: object
                          properties:
                            salesOrderId:
                              type: integer
                        triggerReference:
                          type: string
                        errorMessage:
                          type: string
                          nullable: true
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: '512'
                    workflowId: '7'
                    workflowVersion: 3
                    status: success
                    startedAt: '2026-07-05T09:12:44+00:00'
                    finishedAt: '2026-07-05T09:12:46+00:00'
                    duration: 1650
                    triggerPayload:
                      salesOrderId: 1042
                    triggerReference: SO-1042
                    errorMessage: null
                  first_page_url: https://your-domain.sku.io/api/automation/workflows/7/executions?page=1
                  from: 1
                  last_page: 1
                  last_page_url: https://your-domain.sku.io/api/automation/workflows/7/executions?page=1
                  links: []
                  next_page_url: null
                  path: https://your-domain.sku.io/api/automation/workflows/7/executions
                  per_page: 10
                  prev_page_url: null
                  to: 1
                  total: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-automation-workflows-workflow-executions
  /api/automation/workflow-executions/{execution}/replay:
    post:
      tags:
      - Workflow Executions
      summary: Replay Workflow Execution
      description: 'Re-run a past execution with the same trigger payload and the
        same workflow graph snapshot it originally ran against. A new execution record
        is created and queued asynchronously - the original execution is untouched.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Returns 403 when workflow automation is disabled for the account.


        Path param: execution = execution id to replay.'
      requestBody:
        content: {}
      parameters:
      - name: execution
        in: path
        schema:
          type: integer
        required: true
        example: '512'
        description: The execution ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: string
                  workflowId:
                    type: string
                  workflowVersion:
                    type: integer
                  status:
                    type: string
                  startedAt:
                    type: string
                    nullable: true
                  finishedAt:
                    type: string
                    nullable: true
                  duration:
                    type: string
                    nullable: true
                  triggerPayload:
                    type: object
                    properties:
                      salesOrderId:
                        type: integer
                  triggerReference:
                    type: string
                  errorMessage:
                    type: string
                    nullable: true
                example:
                  id: '514'
                  workflowId: '7'
                  workflowVersion: 3
                  status: pending
                  startedAt: null
                  finishedAt: null
                  duration: null
                  triggerPayload:
                    salesOrderId: 1042
                  triggerReference: SO-1042
                  errorMessage: null
        '403':
          description: Forbidden
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Workflow automation is disabled
        '429': *id001
        '401': *id002
        '404': *id004
        '422': *id005
      operationId: post-api-automation-workflow-executions-execution-replay
  /api/automation/workflow-executions/bulk-delete:
    post:
      tags:
      - Workflow Executions
      summary: Bulk Delete Workflow Executions
      description: 'Permanently delete multiple executions and their step results
        in one call.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Body fields:** `ids` (required, array of execution ids).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 510
                - 511
                - 512
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 3 execution(s) deleted
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      ids:
                        type: array
                        items:
                          type: string
                example:
                  message: The ids field is required.
                  errors:
                    ids:
                    - The ids field is required.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-automation-workflow-executions-bulk-delete
  /api/automation/workflow-nodes:
    get:
      tags:
      - Workflow Node Types
      summary: List Workflow Node Types
      description: 'Catalog of every node type available for building workflow graphs.
        Use the `type` values here as `nodes[*].type` when creating or updating a
        workflow.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Each definition describes the node''s category (`triggers`, `actions`, `logic`,
        ...), its inputs and outputs, the schema of the data it emits (`outputSchema`),
        and the settings it accepts (key, type, whether required, and default value).'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        type:
                          type: string
                        label:
                          type: string
                        category:
                          type: string
                        icon:
                          type: string
                        color:
                          type: string
                        description:
                          type: string
                        inputs:
                          type: array
                        outputs:
                          type: array
                          items:
                            type: object
                            properties:
                              key:
                                type: string
                              label:
                                type: string
                              type:
                                type: string
                              description:
                                type: string
                        outputSchema:
                          type: object
                          properties:
                            scheduledAt:
                              type: object
                              properties:
                                label:
                                  type: string
                                type:
                                  type: string
                        settings:
                          type: array
                          items:
                            type: object
                            properties:
                              key:
                                type: string
                              label:
                                type: string
                              type:
                                type: string
                              required:
                                type: boolean
                              description:
                                type: string
                              placeholder:
                                type: string
                        supportsBranching:
                          type: boolean
                example:
                  data:
                  - type: schedule-trigger
                    label: Schedule
                    category: triggers
                    icon: mdi-clock-outline
                    color: '#9C27B0'
                    description: Triggers on a recurring schedule using cron expressions
                    inputs: []
                    outputs:
                    - key: main
                      label: Main Output
                      type: main
                      description: Schedule trigger data
                    outputSchema:
                      scheduledAt:
                        label: Scheduled At
                        type: date
                    settings:
                    - key: cronExpression
                      label: Cron Expression
                      type: text
                      required: true
                      description: Cron schedule (e.g., "0 9 * * 1-5" for weekdays
                        at 9am)
                      placeholder: 0 9 * * *
                    - key: timezone
                      label: Timezone
                      type: text
                      description: IANA timezone (e.g., America/New_York)
                      defaultValue: UTC
                    supportsBranching: false
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-automation-workflow-nodes
  /api/automation/workflow-templates:
    get:
      tags:
      - Workflow Templates
      summary: List Workflow Templates
      description: "Returns all official workflow templates, ordered for the template\
        \ gallery.\n\n:::info[Authorization]\nAny valid API token can call this endpoint\
        \ — no specific scope required. [Manage tokens](https://app.sku.io/settings/api).\n\
        :::\n\n**Response:** `200 OK` — wrapped in `{data: [...]}`, NOT a paginator.\
        \ The list is expected to be small (a handful of official templates).\n\n\
        **Response shape:**\n```json\n{\n  \"data\": [\n    {\n      \"slug\": \"\
        import-products-csv-upload\",\n      \"name\": \"Import Products from CSV\
        \ Upload\",\n      \"description\": \"User drops a CSV through the workflow\
        \ webhook...\",\n      \"category\": \"imports\",\n      \"thumbnailPath\"\
        : null,\n      \"isOfficial\": true,\n      \"version\": 1,\n      \"parameterPrompts\"\
        : [\n        {\n          \"key\": \"allowedExtensions\",\n          \"path\"\
        : \"nodes.0.data.allowedExtensions\",\n          \"label\": \"Allowed file\
        \ extensions\",\n          \"type\": \"string\",\n          \"required\":\
        \ false,\n          \"default\": \"csv\",\n          \"help_text\": \"Comma-separated\
        \ list of file extensions to accept (e.g. csv,tsv)\"\n        }\n      ],\n\
        \      \"requiredCredentials\": [],\n      \"nodeCount\": 4,\n      \"updatedAt\"\
        : \"2026-04-16T12:34:56+00:00\"\n    }\n  ]\n}\n```\n\n**Route name:** `automation.templates.index`"
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-automation-workflow-templates
  /api/automation/workflow-templates/{slug}:
    get:
      tags:
      - Workflow Templates
      summary: Get Workflow Template
      description: 'Fetches a single workflow template by slug, including the full
        `parameterPrompts` and `requiredCredentials` arrays needed to drive the wizard.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Response:** `200 OK` — wrapped in `{data: {...}}` with the same workflow
        template object shape as the list endpoint. The `workflow_json` graph itself
        is NOT returned by this resource — only `nodeCount` is exposed. The graph
        is only materialised server-side during `instantiate`.


        **Errors:**

        - `404 Not Found` — unknown slug. Response body: `{"message": "No query results
        for model [WorkflowTemplate]."}`


        **Route name:** `automation.templates.show`'
      parameters:
      - name: slug
        in: path
        schema:
          type: string
        required: true
        description: 'Template slug. Seeded values: `import-products-csv-upload`,
          `import-products-ftp-hourly`, `import-supplier-products-csv-upload`.'
        example: import-products-csv-upload
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-automation-workflow-templates-slug
  /api/automation/workflow-templates/{slug}/instantiate:
    post:
      tags:
      - Workflow Templates
      summary: Instantiate Workflow Template
      description: "Creates a new **draft** workflow from the template. The server\
        \ deep-copies the template's `workflow_json`, applies each `parameters[key]`\
        \ value at its declared `path` (from the template's `parameterPrompts`), then\
        \ persists the result as a new draft workflow. The template row itself is\
        \ never mutated.\n\n:::info[Authorization]\nAny valid API token can call this\
        \ endpoint — no specific scope required. [Manage tokens](https://app.sku.io/settings/api).\n\
        :::\n\n**Validation (InstantiateWorkflowTemplateRequest):**\n- `name` — sometimes,\
        \ string, max 128. If omitted, the template's `name` is used.\n- `parameters`\
        \ — sometimes, array. Keys must match `parameterPrompts[*].key` from the template;\
        \ any unknown keys are silently ignored (defense against arbitrary-path injection).\
        \ Missing required prompts are NOT enforced here — the wizard is responsible\
        \ for collecting them before publish. Values can be strings, booleans, integers,\
        \ or credential UUIDs depending on the prompt `type`.\n\n**Behaviour notes:**\n\
        - The created workflow is a draft (`status = draft`). Publishing is a separate\
        \ explicit step (`POST /api/automation/workflows/{workflow}/publish`).\n-\
        \ The draft's `settings.instantiated_from_template` stores `{ slug, version\
        \ }` for drift tracking.\n- `trigger_type` is re-derived from the first trigger\
        \ node; do NOT pass it in.\n\n**Response:** `201 Created` with a workflow\
        \ object (same shape as `POST /api/automation/workflows`):\n```json\n{\n \
        \ \"data\": {\n    \"id\": \"42\",\n    \"uuid\": \"...\",\n    \"name\":\
        \ \"My FTP Product Import\",\n    \"description\": \"Polls an FTP directory\
        \ every hour...\",\n    \"status\": \"draft\",\n    \"version\": 1,\n    \"\
        category\": \"imports\",\n    \"graph\": {\n      \"nodes\": [ ... ],\n  \
        \    \"edges\": [ ... ],\n      \"viewport\": { \"x\": 0, \"y\": 0, \"zoom\"\
        : 1 }\n    },\n    \"settings\": {\n      \"instantiated_from_template\":\
        \ { \"slug\": \"import-products-ftp-hourly\", \"version\": 1 }\n    },\n \
        \   \"triggerType\": \"webhook\",\n    \"triggerConfig\": null,\n    \"createdAt\"\
        : \"2026-04-16T12:34:56+00:00\",\n    \"updatedAt\": \"2026-04-16T12:34:56+00:00\"\
        ,\n    \"publishedAt\": null,\n    \"createdBy\": \"Jane Doe\",\n    \"updatedBy\"\
        : \"Jane Doe\"\n  }\n}\n```\n\n**Errors:**\n- `404 Not Found` — unknown slug.\n\
        - `422 Unprocessable Entity` — validation failure (e.g. `name` longer than\
        \ 128 chars).\n  ```json\n  { \"message\": \"Workflow name must be 128 characters\
        \ or fewer\", \"errors\": { \"name\": [\"Workflow name must be 128 characters\
        \ or fewer\"] } }\n  ```\n\n**Route name:** `automation.templates.instantiate`"
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                parameters:
                  type: object
                  properties:
                    ftpCredential:
                      type: string
                    downloadCredential:
                      type: string
                    directory:
                      type: string
                    pattern:
                      type: string
              example:
                name: My FTP Product Import
                parameters:
                  ftpCredential: 00000000-0000-0000-0000-000000000000
                  downloadCredential: 00000000-0000-0000-0000-000000000000
                  directory: /inbox/products
                  pattern: '*.csv'
      parameters:
      - name: slug
        in: path
        schema:
          type: string
        required: true
        description: Template slug to instantiate from.
        example: import-products-ftp-hourly
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-automation-workflow-templates-slug-instantiate
  /api/automation/workflow-credentials:
    get:
      tags:
      - Workflow Credentials
      summary: List Workflow Credentials
      description: 'Returns a paginated list of workflow credentials for the authenticated
        user''s tenant.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Response:** Standard Laravel `LengthAwarePaginator` shape where `data[*]`
        are workflow credential object objects. Each item exposes `uuid`, `name`,
        `type`, `typeLabel`, `fields` (secrets redacted), optional `createdBy` (when
        `creator` is loaded), `createdAt`, and `updatedAt`.


        **Route name:** `automation.credentials.index`'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        description: Page number (1-based).
        example: '1'
      - name: per_page
        in: query
        schema:
          type: integer
        description: Page size. Defaults to the manager/repository default.
        example: '15'
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-automation-workflow-credentials
    post:
      tags:
      - Workflow Credentials
      summary: Create Workflow Credential
      description: "Creates a new workflow credential. Secret fields listed in `CredentialTypeEnum::secretFields`\
        \ are redacted in the response `fields` object.\n\n:::info[Authorization]\n\
        Any valid API token can call this endpoint — no specific scope required. [Manage\
        \ tokens](https://app.sku.io/settings/api).\n:::\n\n**Validation (StoreWorkflowCredentialRequest):**\n\
        - `name` — required, string, max 128\n- `type` — required, string, must be\
        \ a valid `CredentialTypeEnum`: `basic_auth`, `api_key`, `bearer_token`, `ftp`,\
        \ `sftp`, `google_oauth`, `webhook_token`\n- `data` — required, array (shape\
        \ varies by type)\n\n**Expected `data` shape per type:**\n- `basic_auth`:\
        \ `{ username, password }`\n- `api_key`: `{ key, header?: \"X-API-Key\" }`\n\
        - `bearer_token`: `{ token }`\n- `ftp` / `sftp`: `{ host, port, username,\
        \ password?, privateKey?, passphrase? }`\n- `google_oauth`: `{ accessToken,\
        \ refreshToken, clientId, clientSecret }`\n- `webhook_token`: `{ token }`\n\
        \n**Response:** `201 Created` with workflow credential object:\n```json\n\
        {\n  \"data\": {\n    \"uuid\": \"...\",\n    \"name\": \"...\",\n    \"type\"\
        : \"sftp\",\n    \"typeLabel\": \"SFTP\",\n    \"fields\": { \"host\": \"\
        ...\", \"port\": 22, \"username\": \"...\", \"password\": \"********\", \"\
        privateKey\": \"********\", \"passphrase\": \"********\" },\n    \"createdBy\"\
        : { \"id\": 1, \"name\": \"Jane Doe\" },\n    \"createdAt\": \"2026-04-16T12:34:56+00:00\"\
        ,\n    \"updatedAt\": \"2026-04-16T12:34:56+00:00\"\n  }\n}\n```\n\n**Route\
        \ name:** `automation.credentials.store`"
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                type:
                  type: string
                data:
                  type: object
                  properties:
                    host:
                      type: string
                    port:
                      type: integer
                    username:
                      type: string
                    password:
                      type: string
                    privateKey:
                      type: string
                    passphrase:
                      type: string
              example:
                name: Warehouse SFTP (Prod)
                type: sftp
                data:
                  host: sftp.example.com
                  port: 22
                  username: sku-integrations
                  password: super-secret-pass
                  privateKey: '-----BEGIN OPENSSH PRIVATE KEY-----

                    ...

                    -----END OPENSSH PRIVATE KEY-----'
                  passphrase: optional
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-automation-workflow-credentials
  /api/automation/workflow-credentials/lookup:
    get:
      tags:
      - Workflow Credentials
      summary: Lookup Workflow Credentials by Type
      description: "Lightweight dropdown lookup used by node config UIs. Returns only\
        \ `uuid` + `name` for credentials of the requested type.\n\n:::info[Authorization]\n\
        Any valid API token can call this endpoint — no specific scope required. [Manage\
        \ tokens](https://app.sku.io/settings/api).\n:::\n\n**Response shape:**\n\
        ```json\n{\n  \"data\": [\n    { \"uuid\": \"...\", \"name\": \"...\" }\n\
        \  ]\n}\n```\n\nIf `type` is missing or not a valid `CredentialTypeEnum` case\
        \ the endpoint silently returns `{\"data\": []}` (200 OK).\n\n**Route name:**\
        \ `automation.credentials.lookup`"
      parameters:
      - name: type
        in: query
        schema:
          type: string
        description: Required. One of `basic_auth`, `api_key`, `bearer_token`, `ftp`,
          `sftp`, `google_oauth`, `webhook_token`. An invalid or missing type returns
          an empty list.
        example: basic_auth
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-automation-workflow-credentials-lookup
  /api/automation/workflow-credentials/{uuid}:
    get:
      tags:
      - Workflow Credentials
      summary: Get Workflow Credential
      description: 'Fetches a single workflow credential by UUID. 404 if not found.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Response:** `200 OK` with workflow credential object (same shape as create).
        Secret fields are redacted.


        **Route name:** `automation.credentials.show`'
      parameters:
      - name: uuid
        in: path
        schema:
          type: string
        required: true
        description: The credential's UUID (not numeric ID).
        example: 00000000-0000-0000-0000-000000000000
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-automation-workflow-credentials-uuid
    put:
      tags:
      - Workflow Credentials
      summary: Update Workflow Credential
      description: 'Updates an existing workflow credential. Only the fields sent
        are updated.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Validation (UpdateWorkflowCredentialRequest):**

        - `name` — sometimes, string, max 128

        - `data` — sometimes, array


        `type` is not updatable via this endpoint. `updated_by` is set automatically
        from the authenticated user.


        **Response:** `200 OK` with workflow credential object (secrets redacted in
        `fields`).


        **Route name:** `automation.credentials.update`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                data:
                  type: object
                  properties:
                    host:
                      type: string
                    port:
                      type: integer
                    username:
                      type: string
                    password:
                      type: string
              example:
                name: Warehouse SFTP (Prod) - Renamed
                data:
                  host: sftp.example.com
                  port: 2222
                  username: sku-integrations
                  password: rotated-secret
      parameters:
      - name: uuid
        in: path
        schema:
          type: string
        required: true
        description: The credential's UUID.
        example: 00000000-0000-0000-0000-000000000000
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-automation-workflow-credentials-uuid
    delete:
      tags:
      - Workflow Credentials
      summary: Delete Workflow Credential
      description: 'Deletes a workflow credential by UUID. 404 if not found.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Response:** `200 OK`

        ```json

        { "message": "Credential deleted" }

        ```


        **Route name:** `automation.credentials.destroy`'
      parameters:
      - name: uuid
        in: path
        schema:
          type: string
        required: true
        description: The credential's UUID.
        example: 00000000-0000-0000-0000-000000000000
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-automation-workflow-credentials-uuid
  /api/big-commerce/{integrationInstance}/orders/refresh-tracked:
    post:
      tags:
      - BigCommerce
      summary: Refresh Orders from BigCommerce
      description: 'Start a background refresh that downloads orders from BigCommerce
        into SKU.io.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        The `mode` field controls which orders are fetched:

        - `latest` (default) - orders modified since the most recent local order

        - `from_start_date` - orders modified since the integration''s configured
        start date

        - `date_range` - orders modified within the `date_from` / `date_to` range

        - `all` - every order in the store


        The job runs asynchronously. The response includes a `tracked_job_log_id`
        you can use to poll job progress.


        Route name: big-commerce.orders.refresh-tracked'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                mode:
                  type: string
                date_from:
                  type: string
                date_to:
                  type: string
              example:
                mode: date_range
                date_from: '2026-01-01'
                date_to: '2026-01-31'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: BigCommerce integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                  status:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 5120
                  message: Order refresh job has been queued
                  status: Success
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      mode:
                        type: array
                        items:
                          type: string
                example:
                  message: The selected mode is invalid.
                  errors:
                    mode:
                    - The selected mode is invalid.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-big-commerce-integrationinstance-orders-refresh-tracked
  /api/big-commerce/{integrationInstance}/orders/latest-sync-info:
    get:
      tags:
      - BigCommerce
      summary: Get Latest Order Sync Info
      description: 'Get a summary of the most recently synced BigCommerce order plus
        counts of how many local BigCommerce orders exist and how many are linked
        to SKU.io sales orders. Useful for deciding whether a refresh is needed.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Route name: big-commerce.orders.latest-sync-info'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: BigCommerce integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      latest_order_id:
                        type: string
                      latest_order_date:
                        type: string
                      latest_order_status:
                        type: string
                      total_orders:
                        type: integer
                      with_sku_order:
                        type: integer
                      without_sku_order:
                        type: integer
                example:
                  data:
                    latest_order_id: '118'
                    latest_order_date: '2026-05-14T09:21:33.000000Z'
                    latest_order_status: Shipped
                    total_orders: 1240
                    with_sku_order: 1180
                    without_sku_order: 60
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-big-commerce-integrationinstance-orders-latest-sync-info
  /api/big-commerce/{integrationInstance}/orders/archive:
    put:
      tags:
      - BigCommerce
      summary: Bulk Archive Orders
      description: 'Archive multiple BigCommerce orders by their local IDs. Orders
        that are already archived are skipped.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Route name: big-commerce.orders.bulk-archive'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 4512
                - 4513
                - 4514
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: BigCommerce integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  archived_count:
                    type: integer
                example:
                  message: 3 orders archived successfully
                  archived_count: 3
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-big-commerce-integrationinstance-orders-archive
  /api/big-commerce/{integrationInstance}/orders/unarchive:
    put:
      tags:
      - BigCommerce
      summary: Bulk Unarchive Orders
      description: 'Restore multiple archived BigCommerce orders by their local IDs.
        Orders that are already active are skipped.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Route name: big-commerce.orders.bulk-unarchive'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 4512
                - 4513
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: BigCommerce integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  unarchived_count:
                    type: integer
                example:
                  message: 2 orders unarchived successfully
                  unarchived_count: 2
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-big-commerce-integrationinstance-orders-unarchive
  /api/big-commerce/{integrationInstance}/orders/bulk-delete:
    post:
      tags:
      - BigCommerce
      summary: Bulk Delete Orders
      description: 'Permanently delete multiple local BigCommerce order records by
        their local IDs. This removes the local copies only - orders in the BigCommerce
        store are not affected. Linked SKU.io sales orders are not deleted.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Route name: big-commerce.orders.bulk-delete'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 4512
                - 4513
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: BigCommerce integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  deleted_count:
                    type: integer
                example:
                  message: 2 orders deleted successfully
                  deleted_count: 2
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-big-commerce-integrationinstance-orders-bulk-delete
  /api/big-commerce/{integrationInstance}/orders/bulk-delete-sku-orders:
    post:
      tags:
      - BigCommerce
      summary: Bulk Delete Linked SKU.io Orders
      description: 'Delete the SKU.io sales orders linked to the given BigCommerce
        orders, keeping the BigCommerce order records intact. Set `archive_orders`
        to true to also archive the BigCommerce orders after their linked sales orders
        are removed.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Route name: big-commerce.orders.bulk-delete-sku-orders'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
                archive_orders:
                  type: boolean
              example:
                ids:
                - 4512
                - 4513
                archive_orders: true
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: BigCommerce integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  deleted_count:
                    type: integer
                example:
                  message: 2 SKU orders deleted successfully and BigCommerce orders
                    archived
                  deleted_count: 2
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-big-commerce-integrationinstance-orders-bulk-delete-sku-orders
  /api/big-commerce/{integrationInstance}/orders/update-sku-orders:
    post:
      tags:
      - BigCommerce
      summary: Update Linked SKU.io Orders
      description: 'Re-apply BigCommerce order data to the linked SKU.io sales orders
        (statuses, totals, addresses, lines).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Target orders either with `ids` (local BigCommerce order IDs) or by setting
        `update_all_orders` to true. When `use_jobs` is true (default) the updates
        are processed asynchronously on the queue; set it to false to process synchronously
        within the request.


        Route name: big-commerce.orders.update-sku-orders'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                update_all_orders:
                  type: boolean
                ids:
                  type: array
                  items:
                    type: integer
                use_jobs:
                  type: boolean
              example:
                update_all_orders: false
                ids:
                - 4512
                - 4513
                use_jobs: true
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: BigCommerce integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                  message:
                    type: string
                  status:
                    type: string
                example:
                  data: []
                  message: Sku.io sales orders successfully updated
                  status: Success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-big-commerce-integrationinstance-orders-update-sku-orders
  /api/big-commerce/{integrationInstance}/orders/{order}/activity-log:
    get:
      tags:
      - BigCommerce
      summary: Get Order Activity Log
      description: 'Get the paginated activity history for a single BigCommerce order
        - status changes, sync events, and edits, with the user who caused each change.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Route name: big-commerce.orders.activity-log'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: BigCommerce integration instance ID
        example: '1'
      - name: order
        in: path
        schema:
          type: integer
        required: true
        description: Local BigCommerce order ID
        example: '4512'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        description:
                          type: string
                        event:
                          type: string
                        subject_type:
                          type: string
                        subject_id:
                          type: integer
                        properties:
                          type: object
                          properties:
                            attributes:
                              type: object
                              properties:
                                status:
                                  type: string
                            old:
                              type: object
                              properties:
                                status:
                                  type: string
                        causer_name:
                          type: string
                        created_at:
                          type: string
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                    items:
                      type: object
                      properties:
                        url:
                          type: string
                          nullable: true
                        label:
                          type: string
                        active:
                          type: boolean
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 88213
                    description: updated
                    event: updated
                    subject_type: BigCommerceOrder
                    subject_id: 4512
                    properties:
                      attributes:
                        status: Shipped
                      old:
                        status: Awaiting Fulfillment
                    causer_name: Jane Smith
                    created_at: '2026-06-18T14:25:00.000000Z'
                  first_page_url: '{{base_url}}/api/big-commerce/1/orders/4512/activity-log?page=1'
                  from: 1
                  last_page: 1
                  last_page_url: '{{base_url}}/api/big-commerce/1/orders/4512/activity-log?page=1'
                  links:
                  - url: null
                    label: '&laquo; Previous'
                    active: false
                  - url: '{{base_url}}/api/big-commerce/1/orders/4512/activity-log?page=1'
                    label: '1'
                    active: true
                  - url: '{{base_url}}/api/big-commerce/1/orders/4512/activity-log?page=2'
                    label: Next &raquo;
                    active: false
                  next_page_url: null
                  path: '{{base_url}}/api/big-commerce/1/orders/4512/activity-log'
                  per_page: 15
                  prev_page_url: null
                  to: 6
                  total: 6
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-big-commerce-integrationinstance-orders-order-activity-log
  /api/big-commerce/{integrationInstance}/orders/{order}/raw:
    get:
      tags:
      - BigCommerce
      summary: Get Raw Order
      description: 'Fetch the raw order payload for a single order directly from the
        BigCommerce API (live request, not the locally cached copy).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Route name: big-commerce.orders.raw'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: BigCommerce integration instance ID
        example: '1'
      - name: order
        in: path
        schema:
          type: integer
        required: true
        description: Local BigCommerce order ID
        example: '4512'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      order:
                        type: object
                        properties:
                          id:
                            type: integer
                          status:
                            type: string
                          status_id:
                            type: integer
                          date_created:
                            type: string
                          date_modified:
                            type: string
                          subtotal_ex_tax:
                            type: string
                          total_inc_tax:
                            type: string
                          currency_code:
                            type: string
                          payment_method:
                            type: string
                          payment_status:
                            type: string
                          items_total:
                            type: integer
                          items_shipped:
                            type: integer
                          billing_address:
                            type: object
                            properties:
                              first_name:
                                type: string
                              last_name:
                                type: string
                              email:
                                type: string
                              city:
                                type: string
                              state:
                                type: string
                              country_iso2:
                                type: string
                example:
                  data:
                    order:
                      id: 118
                      status: Shipped
                      status_id: 2
                      date_created: Thu, 14 May 2026 09:21:33 +0000
                      date_modified: Fri, 15 May 2026 10:02:11 +0000
                      subtotal_ex_tax: '49.90'
                      total_inc_tax: '58.30'
                      currency_code: USD
                      payment_method: Credit Card
                      payment_status: captured
                      items_total: 3
                      items_shipped: 3
                      billing_address:
                        first_name: Jane
                        last_name: Smith
                        email: jane@example.com
                        city: Austin
                        state: Texas
                        country_iso2: US
        '403':
          description: Forbidden
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: Order does not belong to this integration instance
        '429': *id001
        '401': *id002
        '404': *id004
      operationId: get-api-big-commerce-integrationinstance-orders-order-raw
  /api/big-commerce/{integrationInstance}/orders/{order}/archive:
    put:
      tags:
      - BigCommerce
      summary: Archive Order
      description: 'Archive a single BigCommerce order. Archived orders are hidden
        from active listings but remain stored and can be restored later.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Route name: big-commerce.orders.archive'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties: {}
              example: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: BigCommerce integration instance ID
        example: '1'
      - name: order
        in: path
        schema:
          type: integer
        required: true
        description: Local BigCommerce order ID
        example: '4512'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  archived:
                    type: boolean
                example:
                  message: Order archived successfully
                  archived: true
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-big-commerce-integrationinstance-orders-order-archive
  /api/big-commerce/{integrationInstance}/orders/{order}/unarchive:
    put:
      tags:
      - BigCommerce
      summary: Unarchive Order
      description: 'Restore a single archived BigCommerce order to the active list.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Route name: big-commerce.orders.unarchive'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties: {}
              example: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: BigCommerce integration instance ID
        example: '1'
      - name: order
        in: path
        schema:
          type: integer
        required: true
        description: Local BigCommerce order ID
        example: '4512'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  unarchived:
                    type: boolean
                example:
                  message: Order unarchived successfully
                  unarchived: true
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-big-commerce-integrationinstance-orders-order-unarchive
  /api/big-commerce/{integrationInstance}/orders/{order}/sku-order:
    delete:
      tags:
      - BigCommerce
      summary: Delete Linked SKU.io Order
      description: 'Delete the SKU.io sales order linked to a BigCommerce order, keeping
        the BigCommerce order record intact. Pass `archive_order=true` to also archive
        the BigCommerce order afterwards.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Route name: big-commerce.orders.delete-sku-order'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: BigCommerce integration instance ID
        example: '1'
      - name: order
        in: path
        schema:
          type: integer
        required: true
        description: Local BigCommerce order ID
        example: '4512'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  archived_order:
                    type: boolean
                example:
                  message: SKU order deleted successfully and BigCommerce order archived
                  archived_order: true
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: No SKU order linked to this BigCommerce order
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: delete-api-big-commerce-integrationinstance-orders-order-sku-order
  /api/big-commerce/{integrationInstance}/orders/{order}:
    delete:
      tags:
      - BigCommerce
      summary: Delete Order
      description: 'Permanently delete a single local BigCommerce order record. This
        removes the local copy only - the order in the BigCommerce store is not affected.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Route name: big-commerce.orders.destroy'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: BigCommerce integration instance ID
        example: '1'
      - name: order
        in: path
        schema:
          type: integer
        required: true
        description: Local BigCommerce order ID
        example: '4512'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Order deleted successfully
        '403':
          description: Forbidden
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: Order does not belong to this integration instance
        '429': *id001
        '401': *id002
        '404': *id004
      operationId: delete-api-big-commerce-integrationinstance-orders-order
    get:
      tags:
      - BigCommerce
      summary: Get Order
      description: 'Get a single cached ShipStation order with the resolved SKU fulfillment
        link.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Query params:

        - `include_json` (optional, `1`/`true`): include the raw ShipStation `json_object`,
        per-item `product_links`, and the `merged_away` tombstone. The detail page
        always sends `include_json=1`.


        Response notes:

        - `merged_away` (only when `include_json` is set): non-null ONLY when this
        order was absorbed by a carrier-side merge into a surviving order and then
        removed at ShipStation (its id 404s). It carries the surviving order''s reference
        + a `survivor_detail_route` to its detail page. Null for ordinary orders.

        - `sku_fulfillment`: the linked SalesOrderFulfillment (or FulfillmentOrder
        fallback), null when unlinked.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: BigCommerce integration instance ID
        example: '1'
      - name: order
        in: path
        schema:
          type: integer
        required: true
        description: BigCommerce order ID
        example: '50'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      shipstation_order_id:
                        type: integer
                      order_key:
                        type: string
                      order_number:
                        type: string
                      external_url:
                        type: string
                      order_status:
                        type: string
                      order_status_label:
                        type: string
                      order_status_color:
                        type: string
                      customer_email:
                        type: string
                      order_date:
                        type: string
                      ship_date:
                        type: string
                        nullable: true
                      ship_by_date:
                        type: string
                        nullable: true
                      carrier_code:
                        type: string
                        nullable: true
                      service_code:
                        type: string
                        nullable: true
                      tracking_number:
                        type: string
                        nullable: true
                      tracking_url:
                        type: string
                        nullable: true
                      shipments:
                        type: array
                      sku_fulfillment:
                        type: string
                        nullable: true
                      has_detailed_data:
                        type: boolean
                      details_last_updated:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      merged_away:
                        type: object
                        properties:
                          provider_label:
                            type: string
                          survivor_reference:
                            type: string
                          survivor_external_id:
                            type: integer
                          survivor_internal_id:
                            type: integer
                          survivor_detail_route:
                            type: string
                      json_object:
                        type: object
                        properties:
                          orderId:
                            type: integer
                          orderNumber:
                            type: string
                          orderStatus:
                            type: string
                          advancedOptions:
                            type: object
                            properties:
                              mergedOrSplit:
                                type: string
                                nullable: true
                              mergedIds:
                                type: string
                                nullable: true
                      product_links:
                        type: object
                        properties: {}
                example:
                  data:
                    id: 92889
                    integration_instance_id: 4
                    shipstation_order_id: 536921166
                    order_key: SKUio_local_63676_1
                    order_number: '#63676.1'
                    external_url: https://ship15.shipstation.com/orders/all-orders-search-result?quickSearch=%2363676.1
                    order_status: awaiting_shipment
                    order_status_label: Awaiting Shipment
                    order_status_color: warning
                    customer_email: rachel@example.com
                    order_date: '2026-06-23T13:07:03+00:00'
                    ship_date: null
                    ship_by_date: null
                    carrier_code: null
                    service_code: null
                    tracking_number: null
                    tracking_url: null
                    shipments: []
                    sku_fulfillment: null
                    has_detailed_data: true
                    details_last_updated: '2026-06-29T10:05:16+00:00'
                    created_at: '2026-06-23T13:07:03+00:00'
                    updated_at: '2026-06-29T11:00:48+00:00'
                    merged_away:
                      provider_label: ShipStation
                      survivor_reference: '#63676.2'
                      survivor_external_id: 536921189
                      survivor_internal_id: 92890
                      survivor_detail_route: /integrations/shipstation/4/orders/92890
                    json_object:
                      orderId: 536921166
                      orderNumber: '#63676.1'
                      orderStatus: awaiting_shipment
                      advancedOptions:
                        mergedOrSplit: null
                        mergedIds: null
                    product_links: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-big-commerce-integrationinstance-orders-order
  /api/big-commerce/{integrationInstance}/pre-start-date-orders:
    get:
      tags:
      - BigCommerce
      summary: List Pre-Start-Date Orders
      description: 'Query the BigCommerce store live for orders created before your
        SKU.io inventory start date, so historical orders can be selectively imported
        without affecting inventory.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Each returned order carries an `eligible` flag with an `eligibility_reason`
        (cancelled and refunded orders are not eligible) and an `already_imported`
        flag for orders that already exist locally.


        Both dates must be before the inventory start date. Returns up to 2,500 matching
        orders per query.


        Route name: big-commerce.pre-start-date-orders.query'
      parameters:
      - name: created_at_min
        in: query
        schema:
          type: string
        description: Required. Earliest order creation date (must be before the inventory
          start date).
        example: '2025-10-01'
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: BigCommerce integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        bigcommerce_order_id:
                          type: integer
                        name:
                          type: string
                        email:
                          type: string
                        created_at:
                          type: string
                        fulfillment_status:
                          type: string
                        financial_status:
                          type: string
                        total_price:
                          type: string
                        currency:
                          type: string
                        fulfillments:
                          type: array
                          items:
                            type: object
                            properties:
                              id:
                                type: string
                                nullable: true
                              created_at:
                                type: string
                              status:
                                type: string
                              tracking_number:
                                type: string
                                nullable: true
                        line_items:
                          type: array
                          items:
                            type: object
                            properties:
                              title:
                                type: string
                              sku:
                                type: string
                              quantity:
                                type: integer
                              current_quantity:
                                type: integer
                              price:
                                type: string
                              variant_title:
                                type: string
                                nullable: true
                        eligible:
                          type: boolean
                        eligibility_reason:
                          type: string
                          nullable: true
                        already_imported:
                          type: boolean
                  inventory_start_date:
                    type: string
                  meta:
                    type: object
                    properties:
                      total_queried:
                        type: integer
                      eligible_count:
                        type: integer
                      already_imported_count:
                        type: integer
                example:
                  data:
                  - bigcommerce_order_id: 118
                    name: '#118'
                    email: jane@example.com
                    created_at: Mon, 03 Nov 2025 15:22:10 +0000
                    fulfillment_status: FULFILLED
                    financial_status: captured
                    total_price: '58.30'
                    currency: USD
                    fulfillments:
                    - id: null
                      created_at: Wed, 05 Nov 2025 09:00:00 +0000
                      status: shipped
                      tracking_number: null
                    line_items:
                    - title: Stainless Water Bottle 750ml
                      sku: WB-750-SS
                      quantity: 2
                      current_quantity: 2
                      price: '24.95'
                      variant_title: null
                    eligible: true
                    eligibility_reason: null
                    already_imported: false
                  inventory_start_date: '2026-01-01'
                  meta:
                    total_queried: 1
                    eligible_count: 1
                    already_imported_count: 0
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      created_at_min:
                        type: array
                        items:
                          type: string
                example:
                  message: Created at min must be before the inventory start date.
                  errors:
                    created_at_min:
                    - Created at min must be before the inventory start date.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-big-commerce-integrationinstance-pre-start-date-orders
  /api/big-commerce/{integrationInstance}/pre-start-date-orders/search:
    get:
      tags:
      - BigCommerce
      summary: Search Pre-Start-Date Orders
      description: 'Search the BigCommerce store for specific pre-start-date orders
        by order number, order ID, or customer email. Returns the same response format
        as the list endpoint, including eligibility and already-imported flags.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Route name: big-commerce.pre-start-date-orders.search'
      parameters:
      - name: search_by
        in: query
        schema:
          type: string
        description: 'Required. Field to search by: order_number, order_id, or email.'
        example: order_number
      - name: search_term
        in: query
        schema:
          type: integer
        description: Required. Value to search for (max 255 characters).
        example: '118'
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: BigCommerce integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        bigcommerce_order_id:
                          type: integer
                        name:
                          type: string
                        email:
                          type: string
                        created_at:
                          type: string
                        fulfillment_status:
                          type: string
                        financial_status:
                          type: string
                        total_price:
                          type: string
                        currency:
                          type: string
                        fulfillments:
                          type: array
                          items:
                            type: object
                            properties:
                              id:
                                type: string
                                nullable: true
                              created_at:
                                type: string
                              status:
                                type: string
                              tracking_number:
                                type: string
                                nullable: true
                        line_items:
                          type: array
                          items:
                            type: object
                            properties:
                              title:
                                type: string
                              sku:
                                type: string
                              quantity:
                                type: integer
                              current_quantity:
                                type: integer
                              price:
                                type: string
                              variant_title:
                                type: string
                                nullable: true
                        eligible:
                          type: boolean
                        eligibility_reason:
                          type: string
                          nullable: true
                        already_imported:
                          type: boolean
                  inventory_start_date:
                    type: string
                  meta:
                    type: object
                    properties:
                      total_queried:
                        type: integer
                      eligible_count:
                        type: integer
                      already_imported_count:
                        type: integer
                example:
                  data:
                  - bigcommerce_order_id: 118
                    name: '#118'
                    email: jane@example.com
                    created_at: Mon, 03 Nov 2025 15:22:10 +0000
                    fulfillment_status: FULFILLED
                    financial_status: captured
                    total_price: '58.30'
                    currency: USD
                    fulfillments:
                    - id: null
                      created_at: Wed, 05 Nov 2025 09:00:00 +0000
                      status: shipped
                      tracking_number: null
                    line_items:
                    - title: Stainless Water Bottle 750ml
                      sku: WB-750-SS
                      quantity: 2
                      current_quantity: 2
                      price: '24.95'
                      variant_title: null
                    eligible: true
                    eligibility_reason: null
                    already_imported: false
                  inventory_start_date: '2026-01-01'
                  meta:
                    total_queried: 1
                    eligible_count: 1
                    already_imported_count: 0
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-big-commerce-integrationinstance-pre-start-date-orders-search
  /api/big-commerce/{integrationInstance}/pre-start-date-orders/import:
    post:
      tags:
      - BigCommerce
      summary: Import Pre-Start-Date Orders
      description: 'Import selected pre-start-date orders from BigCommerce by their
        BigCommerce order IDs (max 10,000 per request). Because each order is fetched
        individually from BigCommerce, the import runs asynchronously as a background
        job. The response returns a tracked_job_log_id you can poll to follow progress
        and the per-order outcome (imported, marked, skipped, or error). Orders that
        already exist locally are marked as pre-start-date imports instead of duplicated.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Route name: big-commerce.pre-start-date-orders.import'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                bigcommerce_order_ids:
                  type: array
                  items:
                    type: integer
              example:
                bigcommerce_order_ids:
                - 118
                - 119
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: BigCommerce integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 8842
                  message: Importing 2 pre-start-date orders — track progress in the
                    job tray.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: Inventory start date must be set before importing pre-start-date
                    orders.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-big-commerce-integrationinstance-pre-start-date-orders-import
  /api/big-commerce/{integrationInstance}/products/refresh-tracked:
    post:
      tags:
      - BigCommerce
      summary: Refresh Products from BigCommerce
      description: 'Start a background refresh that downloads the product catalog
        from BigCommerce into SKU.io.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        The job runs asynchronously. The response includes a `tracked_job_log_id`
        you can use to poll job progress.


        Route name: big-commerce.products.refresh-tracked'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties: {}
              example: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: BigCommerce integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                  status:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 5121
                  message: Product refresh job has been queued
                  status: Success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-big-commerce-integrationinstance-products-refresh-tracked
  /api/big-commerce/{integrationInstance}/products/latest-sync-info:
    get:
      tags:
      - BigCommerce
      summary: Get Latest Product Sync Info
      description: 'Get a summary of the most recently updated BigCommerce product
        plus counts of total, mapped, and unmapped products for the integration instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Route name: big-commerce.products.latest-sync-info'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: BigCommerce integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      latest_product_title:
                        type: string
                      latest_product_date:
                        type: string
                      total_products:
                        type: integer
                      mapped_products:
                        type: integer
                      unmapped_products:
                        type: integer
                example:
                  data:
                    latest_product_title: Stainless Water Bottle 750ml
                    latest_product_date: '2026-05-20T08:13:29.000000Z'
                    total_products: 320
                    mapped_products: 295
                    unmapped_products: 25
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-big-commerce-integrationinstance-products-latest-sync-info
  /api/big-commerce/{integrationInstance}/products/{product}/raw:
    get:
      tags:
      - BigCommerce
      summary: Get Raw Product
      description: 'Fetch the raw product payload for a single product directly from
        the BigCommerce API (live request, not the locally cached copy).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Route name: big-commerce.products.raw'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: BigCommerce integration instance ID
        example: '1'
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: Local BigCommerce product ID
        example: '231'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      product:
                        type: object
                        properties:
                          data:
                            type: object
                            properties:
                              id:
                                type: integer
                              name:
                                type: string
                              sku:
                                type: string
                              type:
                                type: string
                              price:
                                type: number
                              inventory_level:
                                type: integer
                              is_visible:
                                type: boolean
                              availability:
                                type: string
                              upc:
                                type: string
                          meta:
                            type: object
                            properties: {}
                example:
                  data:
                    product:
                      data:
                        id: 812
                        name: Stainless Water Bottle 750ml
                        sku: WB-750-SS
                        type: physical
                        price: 24.95
                        inventory_level: 132
                        is_visible: true
                        availability: available
                        upc: '812345678901'
                      meta: {}
        '403':
          description: Forbidden
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: Product does not belong to this integration instance
        '429': *id001
        '401': *id002
        '404': *id004
      operationId: get-api-big-commerce-integrationinstance-products-product-raw
  /api/big-commerce/{integrationInstance}/products/{product}/smart-match:
    post:
      tags:
      - BigCommerce
      summary: Get Product Match Suggestions
      description: 'Find SKU.io products that likely correspond to a BigCommerce product.
        Returns an exact SKU match, a barcode/UPC match, and a list of fuzzy name-similarity
        matches - each with a `match_type` of sku, barcode, or fuzzy. Use the results
        to pick a product for the map endpoint.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Route name: big-commerce.products.smart-match'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties: {}
              example: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: BigCommerce integration instance ID
        example: '1'
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: Local BigCommerce product ID
        example: '231'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      exact_match:
                        type: object
                        properties:
                          id:
                            type: integer
                          sku:
                            type: string
                          name:
                            type: string
                          barcode:
                            type: string
                          price:
                            type: string
                          type:
                            type: string
                          match_type:
                            type: string
                      barcode_match:
                        type: string
                        nullable: true
                      similar_matches:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            sku:
                              type: string
                            name:
                              type: string
                            barcode:
                              type: string
                            price:
                              type: string
                            type:
                              type: string
                            match_type:
                              type: string
                example:
                  data:
                    exact_match:
                      id: 55
                      sku: WB-750-SS
                      name: Stainless Water Bottle 750ml
                      barcode: '812345678901'
                      price: '24.95'
                      type: product
                      match_type: sku
                    barcode_match: null
                    similar_matches:
                    - id: 61
                      sku: WB-500-SS
                      name: Stainless Water Bottle 500ml
                      barcode: '812345678902'
                      price: '19.95'
                      type: product
                      match_type: fuzzy
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-big-commerce-integrationinstance-products-product-smart-match
  /api/big-commerce/{integrationInstance}/products/{product}/map:
    post:
      tags:
      - BigCommerce
      summary: Map Product
      description: 'Map a BigCommerce product to an existing SKU.io product or subscription
        offering by creating (or updating) its product listing. Provide exactly one
        of `product_id` or `subscription_offering_id`.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        After mapping, a background job is dispatched to link any unmapped sales order
        lines that match the new listing.


        Route name: big-commerce.products.map-single'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                product_id:
                  type: integer
              example:
                product_id: 55
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: BigCommerce integration instance ID
        example: '1'
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: Local BigCommerce product ID
        example: '231'
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      product_listing_id:
                        type: integer
                      product:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          sku:
                            type: string
                          default_financial_line_type_id:
                            type: integer
                          default_financial_line_type:
                            type: object
                            properties:
                              id:
                                type: integer
                              name:
                                type: string
                              classification:
                                type: string
                          listing_id:
                            type: integer
                      subscription_offering:
                        type: string
                        nullable: true
                      mapped_at:
                        type: string
                      mapped_sku:
                        type: string
                      json_object:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          sku:
                            type: string
                          price:
                            type: number
                          inventory_level:
                            type: integer
                          is_visible:
                            type: boolean
                          availability:
                            type: string
                      image_url:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                      status:
                        type: string
                      slug:
                        type: string
                      price:
                        type: number
                      featured:
                        type: boolean
                      catalog_visibility:
                        type: boolean
                      dimensions_length:
                        type: string
                        nullable: true
                      dimensions_width:
                        type: integer
                      dimensions_height:
                        type: integer
                      sku:
                        type: string
                      big_commerce_id:
                        type: integer
                      name:
                        type: string
                      upc:
                        type: string
                      type:
                        type: string
                      base_price:
                        type: number
                      quantity:
                        type: integer
                      weight:
                        type: number
                      brand:
                        type: string
                      is_bundled_product:
                        type: boolean
                  message:
                    type: string
                example:
                  data:
                    id: 231
                    integration_instance_id: 1
                    product_listing_id: 977
                    product:
                      id: 55
                      name: Stainless Water Bottle 750ml
                      sku: WB-750-SS
                      default_financial_line_type_id: 3
                      default_financial_line_type:
                        id: 3
                        name: Product Sales
                        classification: revenue
                      listing_id: 977
                    subscription_offering: null
                    mapped_at: '2026-04-02T16:40:12.000000Z'
                    mapped_sku: WB-750-SS
                    json_object:
                      id: 812
                      name: Stainless Water Bottle 750ml
                      sku: WB-750-SS
                      price: 24.95
                      inventory_level: 132
                      is_visible: true
                      availability: available
                    image_url: https://cdn11.bigcommerce.com/s-abc123/images/stencil/original/products/812/bottle.jpg
                    created_at: '2026-03-28T11:05:44.000000Z'
                    updated_at: '2026-05-20T08:13:29.000000Z'
                    archived_at: null
                    status: active
                    slug: /stainless-water-bottle-750ml/
                    price: 24.95
                    featured: false
                    catalog_visibility: true
                    dimensions_length: null
                    dimensions_width: 8
                    dimensions_height: 26
                    sku: WB-750-SS
                    big_commerce_id: 812
                    name: Stainless Water Bottle 750ml
                    upc: '812345678901'
                    type: physical
                    base_price: 24.95
                    quantity: 132
                    weight: 0.6
                    brand: HydraCo
                    is_bundled_product: false
                  message: Product mapped successfully.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      product_id:
                        type: array
                        items:
                          type: string
                example:
                  message: The product id field is required when subscription offering
                    id is not present.
                  errors:
                    product_id:
                    - The product id field is required when subscription offering
                      id is not present.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-big-commerce-integrationinstance-products-product-map
    delete:
      tags:
      - BigCommerce
      summary: Unmap Product
      description: 'Remove the mapping between a BigCommerce product and its SKU.io
        product by deleting the product listing. The BigCommerce product and the SKU.io
        product both remain.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Route name: big-commerce.products.unmap-single'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: BigCommerce integration instance ID
        example: '1'
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: Local BigCommerce product ID
        example: '231'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      product_listing_id:
                        type: string
                        nullable: true
                      product:
                        type: string
                        nullable: true
                      subscription_offering:
                        type: string
                        nullable: true
                      mapped_at:
                        type: string
                        nullable: true
                      mapped_sku:
                        type: string
                        nullable: true
                      json_object:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          sku:
                            type: string
                          price:
                            type: number
                          inventory_level:
                            type: integer
                          is_visible:
                            type: boolean
                          availability:
                            type: string
                      image_url:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                      status:
                        type: string
                      slug:
                        type: string
                      price:
                        type: number
                      featured:
                        type: boolean
                      catalog_visibility:
                        type: boolean
                      dimensions_length:
                        type: string
                        nullable: true
                      dimensions_width:
                        type: integer
                      dimensions_height:
                        type: integer
                      sku:
                        type: string
                      big_commerce_id:
                        type: integer
                      name:
                        type: string
                      upc:
                        type: string
                      type:
                        type: string
                      base_price:
                        type: number
                      quantity:
                        type: integer
                      weight:
                        type: number
                      brand:
                        type: string
                      is_bundled_product:
                        type: boolean
                  message:
                    type: string
                example:
                  data:
                    id: 231
                    integration_instance_id: 1
                    product_listing_id: null
                    product: null
                    subscription_offering: null
                    mapped_at: null
                    mapped_sku: null
                    json_object:
                      id: 812
                      name: Stainless Water Bottle 750ml
                      sku: WB-750-SS
                      price: 24.95
                      inventory_level: 132
                      is_visible: true
                      availability: available
                    image_url: https://cdn11.bigcommerce.com/s-abc123/images/stencil/original/products/812/bottle.jpg
                    created_at: '2026-03-28T11:05:44.000000Z'
                    updated_at: '2026-05-20T08:13:29.000000Z'
                    archived_at: null
                    status: active
                    slug: /stainless-water-bottle-750ml/
                    price: 24.95
                    featured: false
                    catalog_visibility: true
                    dimensions_length: null
                    dimensions_width: 8
                    dimensions_height: 26
                    sku: WB-750-SS
                    big_commerce_id: 812
                    name: Stainless Water Bottle 750ml
                    upc: '812345678901'
                    type: physical
                    base_price: 24.95
                    quantity: 132
                    weight: 0.6
                    brand: HydraCo
                    is_bundled_product: false
                  message: Product unmapped successfully.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: Product is not mapped.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-big-commerce-integrationinstance-products-product-map
  /api/big-commerce/{integrationInstance}/products/{product}/create-sku-product:
    post:
      tags:
      - BigCommerce
      summary: Create SKU.io Product from BigCommerce Product
      description: 'Create a new SKU.io product from an unmapped BigCommerce product
        and map it in one step. If a SKU.io product with the same SKU already exists,
        the BigCommerce product is linked to it instead (indicated by `linked_existing`
        in the response).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Route name: big-commerce.products.create-sku-product'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties: {}
              example: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: BigCommerce integration instance ID
        example: '1'
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: Local BigCommerce product ID
        example: '231'
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      product_listing_id:
                        type: integer
                      product:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          sku:
                            type: string
                          default_financial_line_type_id:
                            type: integer
                          default_financial_line_type:
                            type: object
                            properties:
                              id:
                                type: integer
                              name:
                                type: string
                              classification:
                                type: string
                          listing_id:
                            type: integer
                      subscription_offering:
                        type: string
                        nullable: true
                      mapped_at:
                        type: string
                      mapped_sku:
                        type: string
                      json_object:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          sku:
                            type: string
                          price:
                            type: number
                          inventory_level:
                            type: integer
                          is_visible:
                            type: boolean
                          availability:
                            type: string
                      image_url:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                      status:
                        type: string
                      slug:
                        type: string
                      price:
                        type: number
                      featured:
                        type: boolean
                      catalog_visibility:
                        type: boolean
                      dimensions_length:
                        type: string
                        nullable: true
                      dimensions_width:
                        type: integer
                      dimensions_height:
                        type: integer
                      sku:
                        type: string
                      big_commerce_id:
                        type: integer
                      name:
                        type: string
                      upc:
                        type: string
                      type:
                        type: string
                      base_price:
                        type: number
                      quantity:
                        type: integer
                      weight:
                        type: number
                      brand:
                        type: string
                      is_bundled_product:
                        type: boolean
                  linked_existing:
                    type: boolean
                  message:
                    type: string
                example:
                  data:
                    id: 231
                    integration_instance_id: 1
                    product_listing_id: 977
                    product:
                      id: 55
                      name: Stainless Water Bottle 750ml
                      sku: WB-750-SS
                      default_financial_line_type_id: 3
                      default_financial_line_type:
                        id: 3
                        name: Product Sales
                        classification: revenue
                      listing_id: 977
                    subscription_offering: null
                    mapped_at: '2026-04-02T16:40:12.000000Z'
                    mapped_sku: WB-750-SS
                    json_object:
                      id: 812
                      name: Stainless Water Bottle 750ml
                      sku: WB-750-SS
                      price: 24.95
                      inventory_level: 132
                      is_visible: true
                      availability: available
                    image_url: https://cdn11.bigcommerce.com/s-abc123/images/stencil/original/products/812/bottle.jpg
                    created_at: '2026-03-28T11:05:44.000000Z'
                    updated_at: '2026-05-20T08:13:29.000000Z'
                    archived_at: null
                    status: active
                    slug: /stainless-water-bottle-750ml/
                    price: 24.95
                    featured: false
                    catalog_visibility: true
                    dimensions_length: null
                    dimensions_width: 8
                    dimensions_height: 26
                    sku: WB-750-SS
                    big_commerce_id: 812
                    name: Stainless Water Bottle 750ml
                    upc: '812345678901'
                    type: physical
                    base_price: 24.95
                    quantity: 132
                    weight: 0.6
                    brand: HydraCo
                    is_bundled_product: false
                  linked_existing: false
                  message: SKU product created and mapped successfully.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: Product is already mapped. Unmap it first.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-big-commerce-integrationinstance-products-product-create-sku-product
  /api/big-commerce/{integrationInstance}/products/{product}/sync:
    post:
      tags:
      - BigCommerce
      summary: Sync Product from BigCommerce
      description: 'Re-fetch a single product from the BigCommerce API and update
        the locally cached copy with the latest data.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Route name: big-commerce.products.sync-single'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties: {}
              example: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: BigCommerce integration instance ID
        example: '1'
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: Local BigCommerce product ID
        example: '231'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      product_listing_id:
                        type: integer
                      product:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          sku:
                            type: string
                          default_financial_line_type_id:
                            type: integer
                          default_financial_line_type:
                            type: object
                            properties:
                              id:
                                type: integer
                              name:
                                type: string
                              classification:
                                type: string
                          listing_id:
                            type: integer
                      subscription_offering:
                        type: string
                        nullable: true
                      mapped_at:
                        type: string
                      mapped_sku:
                        type: string
                      json_object:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          sku:
                            type: string
                          price:
                            type: number
                          inventory_level:
                            type: integer
                          is_visible:
                            type: boolean
                          availability:
                            type: string
                      image_url:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                      status:
                        type: string
                      slug:
                        type: string
                      price:
                        type: number
                      featured:
                        type: boolean
                      catalog_visibility:
                        type: boolean
                      dimensions_length:
                        type: string
                        nullable: true
                      dimensions_width:
                        type: integer
                      dimensions_height:
                        type: integer
                      sku:
                        type: string
                      big_commerce_id:
                        type: integer
                      name:
                        type: string
                      upc:
                        type: string
                      type:
                        type: string
                      base_price:
                        type: number
                      quantity:
                        type: integer
                      weight:
                        type: number
                      brand:
                        type: string
                      is_bundled_product:
                        type: boolean
                  message:
                    type: string
                example:
                  data:
                    id: 231
                    integration_instance_id: 1
                    product_listing_id: 977
                    product:
                      id: 55
                      name: Stainless Water Bottle 750ml
                      sku: WB-750-SS
                      default_financial_line_type_id: 3
                      default_financial_line_type:
                        id: 3
                        name: Product Sales
                        classification: revenue
                      listing_id: 977
                    subscription_offering: null
                    mapped_at: '2026-04-02T16:40:12.000000Z'
                    mapped_sku: WB-750-SS
                    json_object:
                      id: 812
                      name: Stainless Water Bottle 750ml
                      sku: WB-750-SS
                      price: 24.95
                      inventory_level: 132
                      is_visible: true
                      availability: available
                    image_url: https://cdn11.bigcommerce.com/s-abc123/images/stencil/original/products/812/bottle.jpg
                    created_at: '2026-03-28T11:05:44.000000Z'
                    updated_at: '2026-05-20T08:13:29.000000Z'
                    archived_at: null
                    status: active
                    slug: /stainless-water-bottle-750ml/
                    price: 24.95
                    featured: false
                    catalog_visibility: true
                    dimensions_length: null
                    dimensions_width: 8
                    dimensions_height: 26
                    sku: WB-750-SS
                    big_commerce_id: 812
                    name: Stainless Water Bottle 750ml
                    upc: '812345678901'
                    type: physical
                    base_price: 24.95
                    quantity: 132
                    weight: 0.6
                    brand: HydraCo
                    is_bundled_product: false
                  message: Product synced successfully.
        '403':
          description: Forbidden
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: Product does not belong to this integration instance
        '429': *id001
        '401': *id002
        '404': *id004
        '422': *id005
      operationId: post-api-big-commerce-integrationinstance-products-product-sync
  /api/big-commerce/{integrationInstance}/products/{product}/orders:
    get:
      tags:
      - BigCommerce
      summary: List Orders for Product
      description: 'Get a paginated list of BigCommerce orders that contain a given
        product, newest first.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Route name: big-commerce.products.orders'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: BigCommerce integration instance ID
        example: '1'
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: Local BigCommerce product ID
        example: '231'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        sku_sales_order:
                          type: object
                          properties:
                            id:
                              type: integer
                            number:
                              type: string
                            order_status:
                              type: string
                            fulfillment_status:
                              type: string
                            payment_status:
                              type: string
                        json_object:
                          type: object
                          properties:
                            id:
                              type: integer
                            status:
                              type: string
                            status_id:
                              type: integer
                            date_created:
                              type: string
                            currency_code:
                              type: string
                            total_inc_tax:
                              type: string
                        big_commerce_id:
                          type: string
                        sku_sales_order_id:
                          type: integer
                        customer_id:
                          type: string
                        external_id:
                          type: string
                          nullable: true
                        currency_code:
                          type: string
                        payment_status:
                          type: string
                        total_tax:
                          type: string
                        total_inc_tax:
                          type: string
                        payment_method:
                          type: string
                        status:
                          type: string
                        error_log:
                          type: string
                          nullable: true
                        items_total:
                          type: integer
                        items_shipped:
                          type: integer
                        date_created:
                          type: string
                        date_modified:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - id: 4512
                    integration_instance_id: 1
                    sku_sales_order:
                      id: 887
                      number: SO-1042
                      order_status: COMPLETED
                      fulfillment_status: FULFILLED
                      payment_status: PAID
                    json_object:
                      id: 118
                      status: Shipped
                      status_id: 2
                      date_created: Thu, 14 May 2026 09:21:33 +0000
                      currency_code: USD
                      total_inc_tax: '58.30'
                    big_commerce_id: '118'
                    sku_sales_order_id: 887
                    customer_id: '42'
                    external_id: null
                    currency_code: USD
                    payment_status: captured
                    total_tax: '4.35'
                    total_inc_tax: '58.30'
                    payment_method: Credit Card
                    status: Shipped
                    error_log: null
                    items_total: 3
                    items_shipped: 3
                    date_created: '2026-05-14T09:21:33.000000Z'
                    date_modified: '2026-05-15T10:02:11.000000Z'
                    updated_at: '2026-05-15T10:02:12.000000Z'
                  current_page: 1
                  last_page: 1
                  per_page: 10
                  total: 1
                  from: 1
                  to: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-big-commerce-integrationinstance-products-product-orders
  /api/big-commerce/{integrationInstance}/products/deleteable:
    put:
      tags:
      - BigCommerce
      summary: Check Deletable Products
      description: 'Check which BigCommerce products can be deleted. Provide `ids`
        (local BigCommerce product IDs) or set `mode` to `all` to check every product
        for the integration instance. Each result includes a `deleteable` flag and
        a `reason` when deletion is blocked.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Route name: big-commerce.products.deleteable'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 231
                - 232
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: BigCommerce integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        deleteable:
                          type: boolean
                        reason:
                          type: boolean
                  status:
                    type: string
                example:
                  data:
                  - id: 231
                    deleteable: true
                    reason: false
                  - id: 232
                    deleteable: true
                    reason: false
                  status: Success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-big-commerce-integrationinstance-products-deleteable
  /api/big-commerce/{integrationInstance}/mappings:
    get:
      tags:
      - BigCommerce
      summary: Get Field Mappings
      description: 'Get the product field mappings for a BigCommerce integration instance
        - which BigCommerce product fields populate which SKU.io product fields when
        products are created or updated from listings.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        The response includes the default mappings, any custom overrides, the effective
        (merged) mappings, and the catalog of available fields on both sides.


        Route name: big-commerce.mappings.show'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: BigCommerce integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      integration_instance_id:
                        type: integer
                      integration_name:
                        type: string
                      mappings:
                        type: array
                        items:
                          type: object
                          properties:
                            listing_field:
                              type: string
                            sku_field:
                              type: string
                            source:
                              type: string
                            description:
                              type: string
                      available_bigcommerce_fields:
                        type: object
                        properties:
                          sku:
                            type: object
                            properties:
                              name:
                                type: string
                              label:
                                type: string
                              type:
                                type: string
                              description:
                                type: string
                              group:
                                type: string
                          name:
                            type: object
                            properties:
                              name:
                                type: string
                              label:
                                type: string
                              type:
                                type: string
                              description:
                                type: string
                              group:
                                type: string
                          upc:
                            type: object
                            properties:
                              name:
                                type: string
                              label:
                                type: string
                              type:
                                type: string
                              description:
                                type: string
                              group:
                                type: string
                      available_sku_fields:
                        type: object
                        properties:
                          sku:
                            type: object
                            properties:
                              name:
                                type: string
                              label:
                                type: string
                              type:
                                type: string
                          name:
                            type: object
                            properties:
                              name:
                                type: string
                              label:
                                type: string
                              type:
                                type: string
                          barcode:
                            type: object
                            properties:
                              name:
                                type: string
                              label:
                                type: string
                              type:
                                type: string
                      default_mappings:
                        type: array
                        items:
                          type: object
                          properties:
                            listing_field:
                              type: string
                            sku_field:
                              type: string
                            source:
                              type: string
                            description:
                              type: string
                      custom_mappings:
                        type: array
                        items:
                          type: object
                          properties:
                            listing_field:
                              type: string
                            sku_field:
                              type: string
                            parsers:
                              type: array
                            source:
                              type: string
                            description:
                              type: string
                      effective_mappings:
                        type: array
                        items:
                          type: object
                          properties:
                            listing_field:
                              type: string
                            sku_field:
                              type: string
                            source:
                              type: string
                            description:
                              type: string
                example:
                  data:
                    integration_instance_id: 1
                    integration_name: My BigCommerce Store
                    mappings:
                    - listing_field: name
                      sku_field: name
                      source: default
                      description: Maps name to name
                    - listing_field: upc
                      sku_field: barcode
                      parsers: []
                      source: custom
                      description: 'Custom mapping: upc to barcode'
                    available_bigcommerce_fields:
                      sku:
                        name: sku
                        label: SKU
                        type: string
                        description: Stock Keeping Unit
                        group: Identifiers
                      name:
                        name: name
                        label: Product Name
                        type: string
                        description: Product name/title
                        group: Product Info
                      upc:
                        name: upc
                        label: UPC
                        type: string
                        description: Universal Product Code
                        group: Identifiers
                    available_sku_fields:
                      sku:
                        name: sku
                        label: SKU
                        type: string
                      name:
                        name: name
                        label: Name
                        type: string
                      barcode:
                        name: barcode
                        label: Barcode
                        type: string
                    default_mappings:
                    - listing_field: name
                      sku_field: name
                      source: default
                      description: Maps name to name
                    custom_mappings:
                    - listing_field: upc
                      sku_field: barcode
                      parsers: []
                      source: custom
                      description: 'Custom mapping: upc to barcode'
                    effective_mappings:
                    - listing_field: name
                      sku_field: name
                      source: default
                      description: Maps name to name
                    - listing_field: upc
                      sku_field: barcode
                      parsers: []
                      source: custom
                      description: 'Custom mapping: upc to barcode'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-big-commerce-integrationinstance-mappings
    put:
      tags:
      - BigCommerce
      summary: Update Field Mappings
      description: 'Replace the custom product field mappings for a BigCommerce integration
        instance. Each mapping pairs a BigCommerce `listing_field` with a SKU.io `sku_field`,
        with optional `parsers` applied to transform the value. Custom mappings override
        the defaults for the same field.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Route name: big-commerce.mappings.update'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                mappings:
                  type: array
                  items:
                    type: object
                    properties:
                      listing_field:
                        type: string
                      sku_field:
                        type: string
                      parsers:
                        type: array
              example:
                mappings:
                - listing_field: upc
                  sku_field: barcode
                  parsers: []
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: BigCommerce integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      integration_instance_id:
                        type: integer
                      integration_name:
                        type: string
                      mappings:
                        type: array
                        items:
                          type: object
                          properties:
                            listing_field:
                              type: string
                            sku_field:
                              type: string
                            source:
                              type: string
                            description:
                              type: string
                      effective_mappings:
                        type: array
                        items:
                          type: object
                          properties:
                            listing_field:
                              type: string
                            sku_field:
                              type: string
                            source:
                              type: string
                            description:
                              type: string
                  message:
                    type: string
                example:
                  data:
                    integration_instance_id: 1
                    integration_name: My BigCommerce Store
                    mappings:
                    - listing_field: name
                      sku_field: name
                      source: default
                      description: Maps name to name
                    - listing_field: upc
                      sku_field: barcode
                      parsers: []
                      source: custom
                      description: 'Custom mapping: upc to barcode'
                    effective_mappings:
                    - listing_field: name
                      sku_field: name
                      source: default
                      description: Maps name to name
                    - listing_field: upc
                      sku_field: barcode
                      parsers: []
                      source: custom
                      description: 'Custom mapping: upc to barcode'
                  message: Field mappings updated successfully
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      mappings.0.sku_field:
                        type: array
                        items:
                          type: string
                example:
                  message: The mappings.0.sku_field field is required.
                  errors:
                    mappings.0.sku_field:
                    - The mappings.0.sku_field field is required.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: put-api-big-commerce-integrationinstance-mappings
  /api/big-commerce/{integrationInstance}/fulfillments:
    get:
      tags:
      - BigCommerce
      summary: List Fulfillments
      description: 'Get a paginated list of fulfilled shipments for sales orders that
        originated from this BigCommerce store. Each item shows whether it has been
        submitted to BigCommerce (`sync_status` of submitted or pending).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Allowed sorts: id, fulfilled_at, created_at, submitted_to_sales_channel_at
        (default -id).


        Route name: big-commerce.fulfillments.index'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: BigCommerce integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        fulfillment_number:
                          type: string
                        fulfillment_type:
                          type: string
                        status:
                          type: string
                        tracking_number:
                          type: string
                        cost:
                          type: string
                        fulfilled_at:
                          type: string
                        submitted_to_sales_channel_at:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                        carrier:
                          type: string
                        shipping_method_display:
                          type: string
                        sales_order:
                          type: object
                          properties:
                            id:
                              type: integer
                            sales_order_number:
                              type: string
                        bigcommerce_order:
                          type: object
                          properties:
                            id:
                              type: integer
                            big_commerce_id:
                              type: string
                        warehouse:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        shipping_method:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        sync_status:
                          type: string
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                    items:
                      type: object
                      properties:
                        url:
                          type: string
                          nullable: true
                        label:
                          type: string
                        active:
                          type: boolean
                  next_page_url:
                    type: string
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 3120
                    fulfillment_number: F-3120
                    fulfillment_type: shipment
                    status: FULFILLED
                    tracking_number: 1Z999AA10123456784
                    cost: '8.45'
                    fulfilled_at: '2026-06-18T14:22:05+00:00'
                    submitted_to_sales_channel_at: null
                    created_at: '2026-06-18T14:22:06+00:00'
                    carrier: UPS
                    shipping_method_display: UPS Ground
                    sales_order:
                      id: 887
                      sales_order_number: SO-1042
                    bigcommerce_order:
                      id: 4512
                      big_commerce_id: '118'
                    warehouse:
                      id: 2
                      name: Main Warehouse
                    shipping_method:
                      id: 14
                      name: UPS Ground
                    sync_status: pending
                  first_page_url: '{{base_url}}/api/big-commerce/1/fulfillments?page=1'
                  from: 1
                  last_page: 5
                  last_page_url: '{{base_url}}/api/big-commerce/1/fulfillments?page=5'
                  links:
                  - url: null
                    label: '&laquo; Previous'
                    active: false
                  - url: '{{base_url}}/api/big-commerce/1/fulfillments?page=1'
                    label: '1'
                    active: true
                  - url: '{{base_url}}/api/big-commerce/1/fulfillments?page=2'
                    label: Next &raquo;
                    active: false
                  next_page_url: '{{base_url}}/api/big-commerce/1/fulfillments?page=2'
                  path: '{{base_url}}/api/big-commerce/1/fulfillments'
                  per_page: 10
                  prev_page_url: null
                  to: 10
                  total: 48
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-big-commerce-integrationinstance-fulfillments
  /api/big-commerce/{integrationInstance}/fulfillments/pending:
    get:
      tags:
      - BigCommerce
      summary: List Pending Fulfillments
      description: 'Get a paginated list of fulfilled shipments that have not yet
        been submitted to BigCommerce. Pickup fulfillments and fulfillments on cancelled
        orders are excluded.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Route name: big-commerce.fulfillments.pending'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: BigCommerce integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        fulfillment_number:
                          type: string
                        fulfillment_type:
                          type: string
                        status:
                          type: string
                        tracking_number:
                          type: string
                        cost:
                          type: string
                        fulfilled_at:
                          type: string
                        submitted_to_sales_channel_at:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                        carrier:
                          type: string
                        shipping_method_display:
                          type: string
                        sales_order:
                          type: object
                          properties:
                            id:
                              type: integer
                            sales_order_number:
                              type: string
                        bigcommerce_order:
                          type: object
                          properties:
                            id:
                              type: integer
                            big_commerce_id:
                              type: string
                        warehouse:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        shipping_method:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        sync_status:
                          type: string
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                    items:
                      type: object
                      properties:
                        url:
                          type: string
                          nullable: true
                        label:
                          type: string
                        active:
                          type: boolean
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 3120
                    fulfillment_number: F-3120
                    fulfillment_type: shipment
                    status: FULFILLED
                    tracking_number: 1Z999AA10123456784
                    cost: '8.45'
                    fulfilled_at: '2026-06-18T14:22:05+00:00'
                    submitted_to_sales_channel_at: null
                    created_at: '2026-06-18T14:22:06+00:00'
                    carrier: UPS
                    shipping_method_display: UPS Ground
                    sales_order:
                      id: 887
                      sales_order_number: SO-1042
                    bigcommerce_order:
                      id: 4512
                      big_commerce_id: '118'
                    warehouse:
                      id: 2
                      name: Main Warehouse
                    shipping_method:
                      id: 14
                      name: UPS Ground
                    sync_status: pending
                  first_page_url: '{{base_url}}/api/big-commerce/1/fulfillments/pending?page=1'
                  from: 1
                  last_page: 1
                  last_page_url: '{{base_url}}/api/big-commerce/1/fulfillments/pending?page=1'
                  links:
                  - url: null
                    label: '&laquo; Previous'
                    active: false
                  - url: '{{base_url}}/api/big-commerce/1/fulfillments/pending?page=1'
                    label: '1'
                    active: true
                  - url: '{{base_url}}/api/big-commerce/1/fulfillments/pending?page=2'
                    label: Next &raquo;
                    active: false
                  next_page_url: null
                  path: '{{base_url}}/api/big-commerce/1/fulfillments/pending'
                  per_page: 10
                  prev_page_url: null
                  to: 3
                  total: 3
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-big-commerce-integrationinstance-fulfillments-pending
  /api/big-commerce/{integrationInstance}/fulfillments/stats:
    get:
      tags:
      - BigCommerce
      summary: Get Fulfillment Stats
      description: 'Get the count of fulfillments waiting to be submitted to BigCommerce,
        plus the automatic sync schedule. Pending fulfillments are submitted automatically
        every 10 minutes.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Route name: big-commerce.fulfillments.stats'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: BigCommerce integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      pending_sync_count:
                        type: integer
                      sync_schedule:
                        type: object
                        properties:
                          interval:
                            type: integer
                          unit:
                            type: string
                          description:
                            type: string
                example:
                  data:
                    pending_sync_count: 3
                    sync_schedule:
                      interval: 10
                      unit: minutes
                      description: Fulfillments are automatically synced every 10
                        minutes
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-big-commerce-integrationinstance-fulfillments-stats
  /api/big-commerce/{integrationInstance}/fulfillments/{salesOrderFulfillment}/submit:
    post:
      tags:
      - BigCommerce
      summary: Submit Fulfillment
      description: 'Submit a single fulfillment to BigCommerce, creating the shipment
        on the BigCommerce order with its tracking details.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Route name: big-commerce.fulfillments.submit-single'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties: {}
              example: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: BigCommerce integration instance ID
        example: '1'
      - name: salesOrderFulfillment
        in: path
        schema:
          type: integer
        required: true
        description: Sales order fulfillment ID
        example: '3120'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                example:
                  success: true
                  message: The fulfillment submitted successfully
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                example:
                  success: false
                  message: Fulfillment submission failed
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-big-commerce-integrationinstance-fulfillments-salesorderfulfillment-submit
  /api/big-commerce/{integrationInstance}/fulfillments/submit-bulk:
    post:
      tags:
      - BigCommerce
      summary: Bulk Submit Fulfillments
      description: 'Submit multiple fulfillments to BigCommerce by their IDs. The
        response reports how many were submitted and how many failed, with per-fulfillment
        error details.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Route name: big-commerce.fulfillments.submit-bulk'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 3120
                - 3121
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: BigCommerce integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      submitted:
                        type: integer
                      failed:
                        type: integer
                  errors:
                    type: array
                  message:
                    type: string
                example:
                  success: true
                  data:
                    submitted: 2
                    failed: 0
                  errors: []
                  message: 2 fulfillment(s) submitted, 0 failed
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-big-commerce-integrationinstance-fulfillments-submit-bulk
  /api/big-commerce/{integrationInstance}/fulfillments/submit-all:
    post:
      tags:
      - BigCommerce
      summary: Submit All Pending Fulfillments
      description: 'Submit every pending fulfillment for the integration instance
        to BigCommerce in one call. The response reports how many were submitted and
        how many failed, with per-fulfillment error details.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Route name: big-commerce.fulfillments.submit-all'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties: {}
              example: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: BigCommerce integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      submitted:
                        type: integer
                      failed:
                        type: integer
                  errors:
                    type: array
                  message:
                    type: string
                example:
                  success: true
                  data:
                    submitted: 3
                    failed: 0
                  errors: []
                  message: 3 fulfillment(s) submitted, 0 failed
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-big-commerce-integrationinstance-fulfillments-submit-all
  /api/big-commerce/{integrationInstance}/inventory:
    get:
      tags:
      - BigCommerce
      summary: List Inventory Comparison
      description: 'Get a paginated side-by-side comparison of SKU.io quantities vs
        BigCommerce quantities, one row per product listing per BigCommerce inventory
        location. Each row includes the variance and a status of synced, variance,
        or needs_recalc.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Allowed sorts: id, sku_quantity, sales_channel_quantity, created_at, updated_at
        (default -id).


        Route name: big-commerce.inventory.index'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: BigCommerce integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        product_listing_id:
                          type: integer
                        document_id:
                          type: integer
                        listing_sku:
                          type: string
                        title:
                          type: string
                        product:
                          type: object
                          properties:
                            id:
                              type: integer
                            sku:
                              type: string
                            name:
                              type: string
                        subscription_offering:
                          type: string
                          nullable: true
                        location_id:
                          type: string
                        location_name:
                          type: string
                        location_is_active:
                          type: boolean
                        sku_quantity:
                          type: integer
                        sales_channel_quantity:
                          type: integer
                        variance:
                          type: integer
                        status:
                          type: string
                        is_sku_recalculation_needed:
                          type: boolean
                        sku_quantity_updated_at:
                          type: string
                        sales_channel_quantity_updated_at:
                          type: string
                        sales_channel_quantity_synced_at:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                    items:
                      type: object
                      properties:
                        url:
                          type: string
                          nullable: true
                        label:
                          type: string
                        active:
                          type: boolean
                  next_page_url:
                    type: string
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 9021
                    product_listing_id: 977
                    document_id: 231
                    listing_sku: WB-750-SS
                    title: Stainless Water Bottle 750ml
                    product:
                      id: 55
                      sku: WB-750-SS
                      name: Stainless Water Bottle 750ml
                    subscription_offering: null
                    location_id: '1'
                    location_name: Main Location
                    location_is_active: true
                    sku_quantity: 132
                    sales_channel_quantity: 128
                    variance: 4
                    status: variance
                    is_sku_recalculation_needed: false
                    sku_quantity_updated_at: '2026-06-20T04:00:11+00:00'
                    sales_channel_quantity_updated_at: '2026-06-20T04:05:32+00:00'
                    sales_channel_quantity_synced_at: '2026-06-19T04:05:30+00:00'
                    created_at: '2026-05-01T00:00:00+00:00'
                    updated_at: '2026-06-20T04:05:32+00:00'
                  first_page_url: '{{base_url}}/api/big-commerce/1/inventory?page=1'
                  from: 1
                  last_page: 5
                  last_page_url: '{{base_url}}/api/big-commerce/1/inventory?page=5'
                  links:
                  - url: null
                    label: '&laquo; Previous'
                    active: false
                  - url: '{{base_url}}/api/big-commerce/1/inventory?page=1'
                    label: '1'
                    active: true
                  - url: '{{base_url}}/api/big-commerce/1/inventory?page=2'
                    label: Next &raquo;
                    active: false
                  next_page_url: '{{base_url}}/api/big-commerce/1/inventory?page=2'
                  path: '{{base_url}}/api/big-commerce/1/inventory'
                  per_page: 10
                  prev_page_url: null
                  to: 10
                  total: 48
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-big-commerce-integrationinstance-inventory
  /api/big-commerce/{integrationInstance}/inventory/summary:
    get:
      tags:
      - BigCommerce
      summary: Get Inventory Summary
      description: 'Get aggregate inventory sync statistics for the integration instance:
        total SKU/location rows, how many are in sync, how many have a variance, how
        many need recalculation, and the timestamps of the last fetch from BigCommerce
        and last sync to BigCommerce.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Route name: big-commerce.inventory.summary'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: BigCommerce integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      total_items:
                        type: integer
                      in_sync:
                        type: integer
                      with_variance:
                        type: integer
                      needs_recalculation:
                        type: integer
                      last_fetch_at:
                        type: string
                      last_sync_at:
                        type: string
                example:
                  data:
                    total_items: 480
                    in_sync: 440
                    with_variance: 32
                    needs_recalculation: 8
                    last_fetch_at: '2026-06-20T04:05:32.000000Z'
                    last_sync_at: '2026-06-19T04:05:30.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-big-commerce-integrationinstance-inventory-summary
  /api/big-commerce/{integrationInstance}/inventory/locations:
    get:
      tags:
      - BigCommerce
      summary: List Inventory Locations
      description: 'Get the BigCommerce inventory locations known for the integration
        instance, with each location''s ID, name, and active state. Location IDs can
        be used with the inventory comparison filter.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Route name: big-commerce.inventory.locations'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: BigCommerce integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: string
                        name:
                          type: string
                        is_active:
                          type: boolean
                example:
                  data:
                  - id: '1'
                    name: Main Location
                    is_active: true
                  - id: '2'
                    name: West Coast Warehouse
                    is_active: false
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-big-commerce-integrationinstance-inventory-locations
  /api/big-commerce/{integrationInstance}/inventory/recache:
    post:
      tags:
      - BigCommerce
      summary: Recache Inventory Quantities
      description: 'Start a background job that recalculates SKU.io inventory quantities
        for every product listing mapped to this BigCommerce store. Run this when
        the comparison shows rows needing recalculation.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        The job runs asynchronously. Use the returned `tracked_job_log_id` with the
        recache progress endpoint to poll for completion.


        Route name: big-commerce.inventory.recache'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties: {}
              example: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: BigCommerce integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                example:
                  message: Inventory recache job has been queued
                  data:
                    tracked_job_log_id: 5120
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-big-commerce-integrationinstance-inventory-recache
  /api/big-commerce/{integrationInstance}/inventory/recache-progress/{trackedJobLogId}:
    get:
      tags:
      - BigCommerce
      summary: Get Recache Progress
      description: 'Poll the progress of an inventory recache job using the `tracked_job_log_id`
        returned when the job was queued. The response includes the job status, item
        counts, and completion percentage.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Route name: big-commerce.inventory.recache-progress'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: BigCommerce integration instance ID
        example: '1'
      - name: trackedJobLogId
        in: path
        schema:
          type: integer
        required: true
        description: Tracked job log ID returned when the job was queued
        example: '5120'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      job_type:
                        type: string
                      queue:
                        type: string
                      job_name:
                        type: string
                      status:
                        type: string
                      related_model:
                        type: object
                        properties:
                          id:
                            type: integer
                          type:
                            type: string
                            nullable: true
                          reference:
                            type: string
                            nullable: true
                      related_model_reference:
                        type: string
                        nullable: true
                      messages:
                        type: array
                      attempted_at:
                        type: string
                      completed_at:
                        type: string
                        nullable: true
                      duration:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      results:
                        type: string
                        nullable: true
                      total_items:
                        type: integer
                      processed_items:
                        type: integer
                      progress_percentage:
                        type: integer
                      progress_mode:
                        type: string
                      stages:
                        type: string
                        nullable: true
                example:
                  data:
                    id: 5120
                    job_type: integration
                    queue: serial
                    job_name: BigCommerce Inventory Recache
                    status: in_progress
                    related_model:
                      id: 1
                      type: null
                      reference: null
                    related_model_reference: null
                    messages: []
                    attempted_at: '2026-06-20T04:00:01.000000Z'
                    completed_at: null
                    duration: null
                    created_at: '2026-06-20T04:00:00.000000Z'
                    updated_at: '2026-06-20T04:01:12.000000Z'
                    results: null
                    total_items: 480
                    processed_items: 120
                    progress_percentage: 25
                    progress_mode: batch
                    stages: null
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Record not found
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-big-commerce-integrationinstance-inventory-recache-progress-trackedjoblogid
  /api/big-commerce/{integrationInstance}/inventory/sync:
    post:
      tags:
      - BigCommerce
      summary: Sync Inventory to BigCommerce
      description: 'Start a background job that pushes SKU.io inventory quantities
        to BigCommerce for every mapped product listing, updating quantities at each
        mapped location.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        The job runs asynchronously. Use the returned `tracked_job_log_id` with the
        sync progress endpoint to poll for completion.


        Route name: big-commerce.inventory.sync'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties: {}
              example: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: BigCommerce integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                example:
                  message: Inventory sync job has been queued
                  data:
                    tracked_job_log_id: 5122
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-big-commerce-integrationinstance-inventory-sync
  /api/big-commerce/{integrationInstance}/inventory/sync-progress/{trackedJobLogId}:
    get:
      tags:
      - BigCommerce
      summary: Get Inventory Sync Progress
      description: 'Poll the progress of an inventory sync job using the `tracked_job_log_id`
        returned when the job was queued.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Route name: big-commerce.inventory.sync-progress'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: BigCommerce integration instance ID
        example: '1'
      - name: trackedJobLogId
        in: path
        schema:
          type: integer
        required: true
        description: Tracked job log ID returned when the job was queued
        example: '5122'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      job_type:
                        type: string
                      queue:
                        type: string
                      job_name:
                        type: string
                      status:
                        type: string
                      related_model:
                        type: object
                        properties:
                          id:
                            type: integer
                          type:
                            type: string
                            nullable: true
                          reference:
                            type: string
                            nullable: true
                      related_model_reference:
                        type: string
                        nullable: true
                      messages:
                        type: array
                      attempted_at:
                        type: string
                      completed_at:
                        type: string
                        nullable: true
                      duration:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      results:
                        type: string
                        nullable: true
                      total_items:
                        type: integer
                      processed_items:
                        type: integer
                      progress_percentage:
                        type: integer
                      progress_mode:
                        type: string
                      stages:
                        type: string
                        nullable: true
                example:
                  data:
                    id: 5122
                    job_type: integration
                    queue: serial
                    job_name: BigCommerce Inventory Sync
                    status: in_progress
                    related_model:
                      id: 1
                      type: null
                      reference: null
                    related_model_reference: null
                    messages: []
                    attempted_at: '2026-06-20T04:00:01.000000Z'
                    completed_at: null
                    duration: null
                    created_at: '2026-06-20T04:00:00.000000Z'
                    updated_at: '2026-06-20T04:01:12.000000Z'
                    results: null
                    total_items: 480
                    processed_items: 120
                    progress_percentage: 25
                    progress_mode: batch
                    stages: null
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Record not found
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-big-commerce-integrationinstance-inventory-sync-progress-trackedjoblogid
  /api/big-commerce/{integrationInstance}/inventory/fetch-live:
    post:
      tags:
      - BigCommerce
      summary: Fetch Live Inventory
      description: 'Start a background job that fetches current inventory quantities
        from BigCommerce for every mapped product listing and refreshes the local
        comparison cache.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        The job runs asynchronously. Use the returned `tracked_job_log_id` with the
        fetch progress endpoint to poll for completion.


        Route name: big-commerce.inventory.fetch-live'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties: {}
              example: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: BigCommerce integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                example:
                  message: Fetch live inventory job has been queued
                  data:
                    tracked_job_log_id: 5123
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-big-commerce-integrationinstance-inventory-fetch-live
  /api/big-commerce/{integrationInstance}/inventory/fetch-live-progress/{trackedJobLogId}:
    get:
      tags:
      - BigCommerce
      summary: Get Live Inventory Fetch Progress
      description: 'Poll the progress of a live inventory fetch job using the `tracked_job_log_id`
        returned when the job was queued.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Route name: big-commerce.inventory.fetch-live-progress'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: BigCommerce integration instance ID
        example: '1'
      - name: trackedJobLogId
        in: path
        schema:
          type: integer
        required: true
        description: Tracked job log ID returned when the job was queued
        example: '5123'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      job_type:
                        type: string
                      queue:
                        type: string
                      job_name:
                        type: string
                      status:
                        type: string
                      related_model:
                        type: object
                        properties:
                          id:
                            type: integer
                          type:
                            type: string
                            nullable: true
                          reference:
                            type: string
                            nullable: true
                      related_model_reference:
                        type: string
                        nullable: true
                      messages:
                        type: array
                      attempted_at:
                        type: string
                      completed_at:
                        type: string
                        nullable: true
                      duration:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      results:
                        type: string
                        nullable: true
                      total_items:
                        type: integer
                      processed_items:
                        type: integer
                      progress_percentage:
                        type: integer
                      progress_mode:
                        type: string
                      stages:
                        type: string
                        nullable: true
                example:
                  data:
                    id: 5123
                    job_type: integration
                    queue: serial
                    job_name: BigCommerce Live Inventory Fetch
                    status: in_progress
                    related_model:
                      id: 1
                      type: null
                      reference: null
                    related_model_reference: null
                    messages: []
                    attempted_at: '2026-06-20T04:00:01.000000Z'
                    completed_at: null
                    duration: null
                    created_at: '2026-06-20T04:00:00.000000Z'
                    updated_at: '2026-06-20T04:01:12.000000Z'
                    results: null
                    total_items: 480
                    processed_items: 120
                    progress_percentage: 25
                    progress_mode: batch
                    stages: null
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Record not found
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-big-commerce-integrationinstance-inventory-fetch-live-progress-trackedjoblogid
  /api/big-commerce/{integrationInstance}/activity-log:
    get:
      tags:
      - BigCommerce
      summary: Get Integration Activity Log
      description: 'Get the paginated activity history for a BigCommerce integration
        instance - covering the instance itself plus its orders, products, locations,
        and transactions - with the user who caused each change.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Route name: big-commerce.activity-log'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: BigCommerce integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        description:
                          type: string
                        event:
                          type: string
                        subject_type:
                          type: string
                        subject_id:
                          type: integer
                        properties:
                          type: object
                          properties:
                            attributes:
                              type: object
                              properties:
                                status:
                                  type: string
                            old:
                              type: object
                              properties:
                                status:
                                  type: string
                        causer_name:
                          type: string
                        created_at:
                          type: string
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                    items:
                      type: object
                      properties:
                        url:
                          type: string
                          nullable: true
                        label:
                          type: string
                        active:
                          type: boolean
                  next_page_url:
                    type: string
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 88213
                    description: updated
                    event: updated
                    subject_type: BigCommerceOrder
                    subject_id: 4512
                    properties:
                      attributes:
                        status: Shipped
                      old:
                        status: Awaiting Fulfillment
                    causer_name: Jane Smith
                    created_at: '2026-06-18T14:25:00.000000Z'
                  first_page_url: '{{base_url}}/api/big-commerce/1/activity-log?page=1'
                  from: 1
                  last_page: 3
                  last_page_url: '{{base_url}}/api/big-commerce/1/activity-log?page=3'
                  links:
                  - url: null
                    label: '&laquo; Previous'
                    active: false
                  - url: '{{base_url}}/api/big-commerce/1/activity-log?page=1'
                    label: '1'
                    active: true
                  - url: '{{base_url}}/api/big-commerce/1/activity-log?page=2'
                    label: Next &raquo;
                    active: false
                  next_page_url: '{{base_url}}/api/big-commerce/1/activity-log?page=2'
                  path: '{{base_url}}/api/big-commerce/1/activity-log'
                  per_page: 15
                  prev_page_url: null
                  to: 15
                  total: 42
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-big-commerce-integrationinstance-activity-log
  /api/big-commerce/{id}/transactions:
    get:
      tags:
      - BigCommerce
      summary: List Transactions
      description: 'Get paginated list of BigCommerce order transactions for a specific
        integration instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Supports Spatie QueryBuilder filters for search, event type, status, and date
        range.


        Route name: big-commerce.transactions.index'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      - name: filter[search]
        in: query
        schema:
          type: string
        description: Optional. Search by order number or gateway.
      - name: filter[event]
        in: query
        schema:
          type: string
        description: Optional. Filter by transaction event type (e.g. purchase, capture,
          refund).
      - name: filter[status]
        in: query
        schema:
          type: string
        description: Optional. Filter by transaction status (e.g. ok, error).
      - name: filter[date_from]
        in: query
        schema:
          type: string
        description: Optional. Filter transactions from this date (YYYY-MM-DD).
      - name: filter[date_to]
        in: query
        schema:
          type: string
        description: Optional. Filter transactions up to this date (YYYY-MM-DD).
      - name: page
        in: query
        schema:
          type: integer
        description: Page number for pagination.
        example: '1'
      - name: per_page
        in: query
        schema:
          type: integer
        description: Number of results per page (default 10).
        example: '10'
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-big-commerce-id-transactions
  /api/big-commerce/{id}/transactions/refresh:
    post:
      tags:
      - BigCommerce
      summary: Refresh Transactions
      description: 'Dispatch a background job to re-fetch transactions from BigCommerce
        for the given integration instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Responds immediately with a success message. The job runs asynchronously on
        the salesOrderProcessing queue.


        Route name: big-commerce.transactions.refresh'
      requestBody:
        content: {}
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-big-commerce-id-transactions-refresh
  /api/big-commerce/{id}/webhooks:
    get:
      tags:
      - BigCommerce
      summary: Get Webhook Configurations
      description: 'Get webhook configurations for all available BigCommerce topics
        for the given integration instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Returns the registration status (enabled/disabled) for each webhook scope.


        Route name: big-commerce.webhooks.index'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-big-commerce-id-webhooks
  /api/big-commerce/{id}/webhooks/enable:
    post:
      tags:
      - BigCommerce
      summary: Enable Webhook
      description: 'Register a webhook with BigCommerce for the given scope on the
        integration instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Required fields:

        - scope (string): The BigCommerce webhook scope to enable, e.g. store/order/created


        Route name: big-commerce.webhooks.enable'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                scope:
                  type: string
              example:
                scope: store/order/created
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-big-commerce-id-webhooks-enable
  /api/big-commerce/{id}/webhooks/disable:
    post:
      tags:
      - BigCommerce
      summary: Disable Webhook
      description: 'Delete a registered webhook from BigCommerce for the given scope
        on the integration instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Required fields:

        - scope (string): The BigCommerce webhook scope to disable, e.g. store/order/created


        Route name: big-commerce.webhooks.disable'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                scope:
                  type: string
              example:
                scope: store/order/created
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-big-commerce-id-webhooks-disable
  /api/big-commerce/{id}/webhooks/create-all:
    post:
      tags:
      - BigCommerce
      summary: Create All Webhooks
      description: 'Create all supported webhooks at once for the integration instance.
        Skips scopes that are already registered.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Route name: big-commerce.webhooks.create-all'
      requestBody:
        content: {}
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-big-commerce-id-webhooks-create-all
  /api/big-commerce/{id}/webhook-events:
    get:
      tags:
      - BigCommerce
      summary: List Webhook Events
      description: 'Get a paginated list of webhook events for a specific BigCommerce
        integration instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Route name: big-commerce.webhook-events.index'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      - name: page
        in: query
        schema:
          type: integer
        description: Page number for pagination.
        example: '1'
      - name: per_page
        in: query
        schema:
          type: integer
        description: Number of results per page.
        example: '10'
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-big-commerce-id-webhook-events
  /api/big-commerce/{id}/webhook-events/stats:
    get:
      tags:
      - BigCommerce
      summary: Get Webhook Processing Stats
      description: 'Get processing statistics for webhook events on the integration
        instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Returns counts by status (pending, processing, completed, failed).


        Route name: big-commerce.webhook-events.stats'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-big-commerce-id-webhook-events-stats
  /api/big-commerce/{id}/webhook-events/process:
    post:
      tags:
      - BigCommerce
      summary: Process Pending Webhook Events
      description: 'Trigger manual processing of pending webhook events for the integration
        instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Optional fields:

        - scope (string): Filter to a specific webhook scope

        - limit (integer): Maximum number of events to process (0 = no limit)


        Route name: big-commerce.webhook-events.process'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                scope:
                  type: string
                limit:
                  type: integer
              example:
                scope: store/order/created
                limit: 50
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-big-commerce-id-webhook-events-process
  /api/big-commerce/{id}/webhook-events/retry-failed:
    post:
      tags:
      - BigCommerce
      summary: Retry Failed Webhook Events
      description: 'Retry all failed webhook events for the integration instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Optional fields:

        - limit (integer): Maximum number of events to retry (0 = no limit)


        Route name: big-commerce.webhook-events.retry-failed'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                limit:
                  type: integer
              example:
                limit: 25
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-big-commerce-id-webhook-events-retry-failed
  /api/big-commerce/{id}/webhook-events/delete-all:
    delete:
      tags:
      - BigCommerce
      summary: Delete All Webhook Events
      description: 'Delete all webhook events for the given integration instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        This is a destructive action — all event records for the instance will be
        removed.


        Route name: big-commerce.webhook-events.delete-all'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-big-commerce-id-webhook-events-delete-all
  /api/webhooks/bc-webhook/{id}/order-created:
    post:
      tags:
      - BigCommerce
      summary: Order Created Webhook
      description: 'Inbound webhook endpoint called by BigCommerce when a new order
        is created.


        Requires BigCommerce webhook signature verification (VerifyBigCommerceWebhook
        middleware).

        Dispatches a background job for async processing.


        Route name: bigcommerce.order_created'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                scope:
                  type: string
                store_id:
                  type: string
                data:
                  type: object
                  properties:
                    type:
                      type: string
                    id:
                      type: integer
                hash:
                  type: string
                created_at:
                  type: integer
                producer:
                  type: string
              example:
                scope: store/order/created
                store_id: '12345'
                data:
                  type: order
                  id: 100
                hash: abcdef1234567890
                created_at: 1617000000
                producer: stores/abcde
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      - name: X-Webhook-Signature
        in: header
        schema:
          type: string
        description: BigCommerce webhook HMAC-SHA256 signature for payload verification.
        example: '{{bc_webhook_signature}}'
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '404': *id004
        '422': *id005
      security: []
      operationId: post-api-webhooks-bc-webhook-id-order-created
  /api/webhooks/bc-webhook/{id}/order-updated:
    post:
      tags:
      - BigCommerce
      summary: Order Updated Webhook
      description: 'Inbound webhook endpoint called by BigCommerce when an order is
        updated.


        Route name: bigcommerce.order_updated'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                scope:
                  type: string
                store_id:
                  type: string
                data:
                  type: object
                  properties:
                    type:
                      type: string
                    id:
                      type: integer
                    status:
                      type: object
                      properties:
                        previous_status_id:
                          type: integer
                        new_status_id:
                          type: integer
                hash:
                  type: string
                created_at:
                  type: integer
                producer:
                  type: string
              example:
                scope: store/order/updated
                store_id: '12345'
                data:
                  type: order
                  id: 100
                  status:
                    previous_status_id: 7
                    new_status_id: 2
                hash: abcdef1234567890
                created_at: 1617000000
                producer: stores/abcde
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      - name: X-Webhook-Signature
        in: header
        schema:
          type: string
        example: '{{bc_webhook_signature}}'
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '404': *id004
        '422': *id005
      security: []
      operationId: post-api-webhooks-bc-webhook-id-order-updated
  /api/webhooks/bc-webhook/{id}/product-created:
    post:
      tags:
      - BigCommerce
      summary: Product Created Webhook
      description: 'Inbound webhook endpoint called by BigCommerce when a product
        is created.


        Route name: bigcommerce.product_created'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                scope:
                  type: string
                store_id:
                  type: string
                data:
                  type: object
                  properties:
                    type:
                      type: string
                    id:
                      type: integer
                hash:
                  type: string
                created_at:
                  type: integer
                producer:
                  type: string
              example:
                scope: store/product/created
                store_id: '12345'
                data:
                  type: product
                  id: 500
                hash: abcdef1234567890
                created_at: 1617000000
                producer: stores/abcde
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      - name: X-Webhook-Signature
        in: header
        schema:
          type: string
        example: '{{bc_webhook_signature}}'
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '404': *id004
        '422': *id005
      security: []
      operationId: post-api-webhooks-bc-webhook-id-product-created
  /api/webhooks/bc-webhook/{id}/product-updated:
    post:
      tags:
      - BigCommerce
      summary: Product Updated Webhook
      description: 'Inbound webhook endpoint called by BigCommerce when a product
        is updated.


        Route name: bigcommerce.product_updated'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                scope:
                  type: string
                store_id:
                  type: string
                data:
                  type: object
                  properties:
                    type:
                      type: string
                    id:
                      type: integer
                hash:
                  type: string
                created_at:
                  type: integer
                producer:
                  type: string
              example:
                scope: store/product/updated
                store_id: '12345'
                data:
                  type: product
                  id: 500
                hash: abcdef1234567890
                created_at: 1617000000
                producer: stores/abcde
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      - name: X-Webhook-Signature
        in: header
        schema:
          type: string
        example: '{{bc_webhook_signature}}'
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '404': *id004
        '422': *id005
      security: []
      operationId: post-api-webhooks-bc-webhook-id-product-updated
  /api/webhooks/bc-webhook/{id}/shipment-created:
    post:
      tags:
      - BigCommerce
      summary: Shipment Created Webhook
      description: 'Inbound webhook endpoint called by BigCommerce when a shipment
        is created.


        Route name: bigcommerce.shipment_created'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                scope:
                  type: string
                store_id:
                  type: string
                data:
                  type: object
                  properties:
                    type:
                      type: string
                    id:
                      type: integer
                    orderId:
                      type: integer
                hash:
                  type: string
                created_at:
                  type: integer
                producer:
                  type: string
              example:
                scope: store/shipment/created
                store_id: '12345'
                data:
                  type: shipment
                  id: 200
                  orderId: 100
                hash: abcdef1234567890
                created_at: 1617000000
                producer: stores/abcde
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      - name: X-Webhook-Signature
        in: header
        schema:
          type: string
        example: '{{bc_webhook_signature}}'
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '404': *id004
        '422': *id005
      security: []
      operationId: post-api-webhooks-bc-webhook-id-shipment-created
  /api/webhooks/bc-webhook/{id}/shipment-updated:
    post:
      tags:
      - BigCommerce
      summary: Shipment Updated Webhook
      description: 'Inbound webhook endpoint called by BigCommerce when a shipment
        is updated.


        Route name: bigcommerce.shipment_updated'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                scope:
                  type: string
                store_id:
                  type: string
                data:
                  type: object
                  properties:
                    type:
                      type: string
                    id:
                      type: integer
                    orderId:
                      type: integer
                hash:
                  type: string
                created_at:
                  type: integer
                producer:
                  type: string
              example:
                scope: store/shipment/updated
                store_id: '12345'
                data:
                  type: shipment
                  id: 200
                  orderId: 100
                hash: abcdef1234567890
                created_at: 1617000000
                producer: stores/abcde
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      - name: X-Webhook-Signature
        in: header
        schema:
          type: string
        example: '{{bc_webhook_signature}}'
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '404': *id004
        '422': *id005
      security: []
      operationId: post-api-webhooks-bc-webhook-id-shipment-updated
  /api/customers/{customer}/payment-methods:
    get:
      tags:
      - Card on File
      summary: List Cards On File
      description: 'List a customer''s saved (tokenized) cards on file. Returns only
        safe display metadata — brand, last four, expiry, cardholder name, the default
        flag, and the consent timestamp. The processor-vaulted reusable token is NEVER
        serialized and does not appear in the response.


        :::info[Required scope: `customers:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token (PAT).


        Returns 200 with `{ data: [ ... ] }` — an array of card-on-file records (no
        token field).'
      parameters:
      - name: customer
        in: path
        schema:
          type: string
        required: true
        description: The customer id.
        example: '{{customer}}'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        processor:
                          type: string
                        brand:
                          type: string
                        last_four:
                          type: string
                        exp_month:
                          type: integer
                        exp_year:
                          type: integer
                        cardholder_name:
                          type: string
                        is_default:
                          type: boolean
                        label:
                          type: string
                        consent_given_at:
                          type: string
                        created_at:
                          type: string
                example:
                  data:
                  - id: 42
                    processor: square
                    brand: Visa
                    last_four: '4242'
                    exp_month: 12
                    exp_year: 2028
                    cardholder_name: Alex Rivera
                    is_default: true
                    label: Visa ••••4242
                    consent_given_at: '2026-07-06T14:30:00+00:00'
                    created_at: '2026-07-06T14:30:00+00:00'
                  - id: 43
                    processor: stripe
                    brand: Mastercard
                    last_four: '4444'
                    exp_month: 3
                    exp_year: 2027
                    cardholder_name: Alex Rivera
                    is_default: false
                    label: Mastercard ••••4444
                    consent_given_at: '2026-06-01T09:15:00+00:00'
                    created_at: '2026-06-01T09:15:00+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: customers:read
      operationId: get-api-customers-customer-payment-methods
    post:
      tags:
      - Card on File
      summary: Save Card On File
      description: 'Save a tokenized card on file for a customer. The client tokenizes
        the card with the processor SDK (Square / Stripe) and sends ONLY the resulting
        reusable token — a raw card number (PAN) or CVV is never accepted. Requires
        explicit, affirmative customer consent.


        :::info[Required scope: `customers:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token (PAT).

        Permission: `customers.update`.


        Request body fields:

        - `processor` (string, required) — the tokenizing processor. One of: `square`,
        `stripe`.

        - `processor_token` (string, required, max 255) — the processor''s reusable
        card token from client-side SDK vaulting (e.g. a Square card nonce or Stripe
        PaymentMethod id). NEVER a raw PAN or CVV.

        - `processor_customer_id` (string, nullable, max 255) — the processor''s customer/vault
        id the token is attached to.

        - `consent_given` (required, must be accepted — `true`, `1`, `"yes"`, or `"on"`)
        — explicit customer consent to store the card. Error when missing/false: "Explicit
        customer consent is required to store a card on file."

        - `brand` (string, nullable, max 50) — safe display card brand (e.g. Visa,
        Mastercard).

        - `last_four` (nullable, exactly 4 digits) — safe display last four of the
        card.

        - `exp_month` (integer, nullable, 1–12) — card expiry month.

        - `exp_year` (integer, nullable, 2020–2100) — card expiry year.

        - `cardholder_name` (string, nullable, max 255) — name on the card.

        - `is_default` (boolean, nullable) — make this the customer''s default card.
        Defaults to false.


        Returns 201 with `{ data: <card on file>, message: "Card saved on file." }`
        (no token field).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                processor:
                  type: string
                processor_token:
                  type: string
                processor_customer_id:
                  type: string
                consent_given:
                  type: boolean
                brand:
                  type: string
                last_four:
                  type: string
                exp_month:
                  type: integer
                exp_year:
                  type: integer
                cardholder_name:
                  type: string
                is_default:
                  type: boolean
              example:
                processor: square
                processor_token: cnon:card-nonce-vaulted
                processor_customer_id: sq_cust_9f3a2b
                consent_given: true
                brand: Visa
                last_four: '4242'
                exp_month: 12
                exp_year: 2028
                cardholder_name: Alex Rivera
                is_default: true
      parameters:
      - name: customer
        in: path
        schema:
          type: string
        required: true
        description: The customer id.
        example: '{{customer}}'
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      processor:
                        type: string
                      brand:
                        type: string
                      last_four:
                        type: string
                      exp_month:
                        type: integer
                      exp_year:
                        type: integer
                      cardholder_name:
                        type: string
                      is_default:
                        type: boolean
                      label:
                        type: string
                      consent_given_at:
                        type: string
                      created_at:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 42
                    processor: square
                    brand: Visa
                    last_four: '4242'
                    exp_month: 12
                    exp_year: 2028
                    cardholder_name: Alex Rivera
                    is_default: true
                    label: Visa ••••4242
                    consent_given_at: '2026-07-06T14:30:00+00:00'
                    created_at: '2026-07-06T14:30:00+00:00'
                  message: Card saved on file.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      consent_given:
                        type: array
                        items:
                          type: string
                example:
                  message: Explicit customer consent is required to store a card on
                    file.
                  errors:
                    consent_given:
                    - Explicit customer consent is required to store a card on file.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: customers:write
      operationId: post-api-customers-customer-payment-methods
  /api/customers/{customer}/payment-methods/{paymentMethod}/default:
    put:
      tags:
      - Card on File
      summary: Set Default Card
      description: 'Make a saved card the customer''s default. Clears the default
        flag on the customer''s other cards and sets it on this one.


        :::info[Required scope: `customers:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token (PAT).

        Permission: `customers.update`.


        No request body. The card must belong to the customer in the path, otherwise
        a 422 is returned.


        Returns 200 with `{ data: <card on file>, message: "Default card updated."
        }` (no token field).'
      requestBody:
        content: {}
      parameters:
      - name: customer
        in: path
        schema:
          type: string
        required: true
        description: The customer id.
        example: '{{customer}}'
      - name: paymentMethod
        in: path
        schema:
          type: string
        required: true
        description: The saved card (payment method) id.
        example: '{{paymentMethod}}'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      processor:
                        type: string
                      brand:
                        type: string
                      last_four:
                        type: string
                      exp_month:
                        type: integer
                      exp_year:
                        type: integer
                      cardholder_name:
                        type: string
                      is_default:
                        type: boolean
                      label:
                        type: string
                      consent_given_at:
                        type: string
                      created_at:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 42
                    processor: square
                    brand: Visa
                    last_four: '4242'
                    exp_month: 12
                    exp_year: 2028
                    cardholder_name: Alex Rivera
                    is_default: true
                    label: Visa ••••4242
                    consent_given_at: '2026-07-06T14:30:00+00:00'
                    created_at: '2026-07-06T14:30:00+00:00'
                  message: Default card updated.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      payment_method:
                        type: array
                        items:
                          type: string
                example:
                  message: That card does not belong to this customer.
                  errors:
                    payment_method:
                    - That card does not belong to this customer.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: customers:write
      operationId: put-api-customers-customer-payment-methods-paymentmethod-default
  /api/customers/{customer}/payment-methods/{paymentMethod}:
    delete:
      tags:
      - Card on File
      summary: Remove Card On File
      description: 'Remove a saved card from the customer''s file. Deletes the stored
        token reference and its display metadata.


        :::info[Required scope: `customers:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token (PAT).

        Permission: `customers.update`.


        No request body. The card must belong to the customer in the path, otherwise
        a 422 is returned.


        Returns 200 with `{ message: "Card removed." }`.'
      parameters:
      - name: customer
        in: path
        schema:
          type: string
        required: true
        description: The customer id.
        example: '{{customer}}'
      - name: paymentMethod
        in: path
        schema:
          type: string
        required: true
        description: The saved card (payment method) id.
        example: '{{paymentMethod}}'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Card removed.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: customers:write
      operationId: delete-api-customers-customer-payment-methods-paymentmethod
  /api/v2/stores/{store}:
    get:
      tags:
      - Stores
      summary: Get Store
      description: 'Returns a single store (the Store detail page''s header/overview),
        including its address fields and associated sales channels. `is_default` indicates
        whether this store is the tenant''s default outbound-email sender. Archived
        stores are resolvable by this endpoint.


        Authentication: Requires Bearer token (PAT).'
      parameters:
      - name: store
        in: path
        schema:
          type: string
        required: true
        description: The store ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      is_default:
                        type: boolean
                      name:
                        type: string
                      logo_url:
                        type: string
                      custom_jrxml_file:
                        type: string
                        nullable: true
                      custom_message:
                        type: string
                      company:
                        type: string
                      company_name:
                        type: string
                      email:
                        type: string
                      po_email:
                        type: string
                      phone:
                        type: string
                      fax:
                        type: string
                        nullable: true
                      address1:
                        type: string
                      address2:
                        type: string
                      address3:
                        type: string
                        nullable: true
                      city:
                        type: string
                      province:
                        type: string
                      province_code:
                        type: string
                      zip:
                        type: string
                      country:
                        type: string
                      country_code:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      sales_channels:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                example:
                  data:
                    id: 1
                    is_default: false
                    name: Main Store
                    logo_url: https://cdn.example.com/logos/main-store.png
                    custom_jrxml_file: null
                    custom_message: Thank you for your order!
                    company: Acme Corporation
                    company_name: Acme Corporation
                    email: orders@acme.com
                    po_email: purchasing@acme.com
                    phone: +1-555-123-4567
                    fax: null
                    address1: 123 Main Street
                    address2: Suite 400
                    address3: null
                    city: New York
                    province: New York
                    province_code: NY
                    zip: '10001'
                    country: United States
                    country_code: US
                    archived_at: null
                    created_at: '2024-01-01T00:00:00.000000Z'
                    updated_at: '2024-01-15T10:00:00.000000Z'
                    sales_channels:
                    - id: 1
                      name: Amazon US
                    - id: 2
                      name: Shopify
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No query results for model [App\Models\Store] 999
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-v2-stores-store
  /api/v2/stores/{store}/stats:
    get:
      tags:
      - Stores
      summary: Get Store Stats
      description: 'Dashboard KPIs for the Store detail page: connected sales-channel
        count, assigned-customer count, 90-day order count and revenue, the store''s
        outbound-sending identity (email/PO email, sender domain and its verification
        status), and the store''s linked sales channels, email templates (each with
        a friendly `context_label`, e.g. "Bulk Sales Order"), and PDF templates.


        `sending.domain_verification_status` is one of `pending`, `verifying`, `verified`,
        `failed` (null when the store has no email). `sending.is_default_sender` is
        true when this store is the tenant default sender.


        Authentication: Requires Bearer token (PAT).'
      parameters:
      - name: store
        in: path
        schema:
          type: string
        required: true
        description: The store ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      sales_channels_count:
                        type: integer
                      customers_count:
                        type: integer
                      orders:
                        type: object
                        properties:
                          count_90d:
                            type: integer
                          revenue_90d:
                            type: number
                      sending:
                        type: object
                        properties:
                          email:
                            type: string
                          po_email:
                            type: string
                          domain:
                            type: string
                          domain_verification_status:
                            type: string
                          domain_verified:
                            type: boolean
                          domain_usable:
                            type: boolean
                          is_default_sender:
                            type: boolean
                      sales_channels:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            integration_instance_id:
                              type: integer
                            integration_name:
                              type: string
                            status:
                              type: string
                            status_label:
                              type: string
                      email_templates:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            type:
                              type: string
                            context:
                              type: string
                            context_label:
                              type: string
                            event:
                              type: string
                            enabled:
                              type: boolean
                            is_system_template:
                              type: boolean
                      pdf_templates:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            type:
                              type: string
                            description:
                              type: string
                example:
                  data:
                    sales_channels_count: 3
                    customers_count: 128
                    orders:
                      count_90d: 342
                      revenue_90d: 45230.75
                    sending:
                      email: orders@acme.com
                      po_email: purchasing@acme.com
                      domain: acme.com
                      domain_verification_status: verified
                      domain_verified: true
                      domain_usable: true
                      is_default_sender: true
                    sales_channels:
                    - id: 1
                      name: Amazon US
                      integration_instance_id: 10
                      integration_name: Amazon
                      status: synced
                      status_label: Synced
                    - id: 2
                      name: Shopify
                      integration_instance_id: 11
                      integration_name: Shopify
                      status: pending
                      status_label: Pending
                    email_templates:
                    - id: 5
                      name: Order Confirmation
                      type: order
                      context: sales_order
                      context_label: Sales Order
                      event: order_placed
                      enabled: true
                      is_system_template: false
                    pdf_templates:
                    - id: 8
                      name: Acme Invoice
                      type: invoice
                      description: Branded invoice layout for Acme storefront
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-v2-stores-store-stats
  /api/v2/stores/{store}/activity-log:
    get:
      tags:
      - Stores
      summary: Get Store Activity Log
      description: 'Paginated, filterable audit log of the store''s own events (create,
        edit, archive, restore). Each entry records the event, the changed attributes,
        and the user who made the change.


        Supports `filter[event]`, `filter[source]`, `filter[batch_uuid]`, and `filter[search]`
        (searches causer name, event, subject type, and change properties). Paginated
        with `page` and `per_page` (default 15).


        Authentication: Requires Bearer token (PAT).'
      parameters:
      - name: store
        in: path
        schema:
          type: string
        required: true
        description: The store ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        description:
                          type: string
                        event:
                          type: string
                        subject_type:
                          type: string
                        subject_id:
                          type: integer
                        properties:
                          type: object
                          properties:
                            attributes:
                              type: object
                              properties:
                                email:
                                  type: string
                            old:
                              type: object
                              properties:
                                email:
                                  type: string
                        causer_name:
                          type: string
                        created_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                  first_page_url:
                    type: string
                  last_page_url:
                    type: string
                  next_page_url:
                    type: string
                    nullable: true
                  prev_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                example:
                  data:
                  - id: 9012
                    description: updated
                    event: updated
                    subject_type: Store
                    subject_id: 1
                    properties:
                      attributes:
                        email: orders@acme.com
                      old:
                        email: hello@acme.com
                    causer_name: Jane Merchant
                    created_at: '2026-07-18T14:05:00.000000Z'
                  - id: 9008
                    description: created
                    event: created
                    subject_type: Store
                    subject_id: 1
                    properties:
                      attributes:
                        name: Main Store
                    causer_name: Jane Merchant
                    created_at: '2026-07-01T09:00:00.000000Z'
                  current_page: 1
                  last_page: 1
                  per_page: 15
                  total: 2
                  from: 1
                  to: 2
                  first_page_url: '{{protocol}}{{domain}}/api/v2/stores/1/activity-log?page=1'
                  last_page_url: '{{protocol}}{{domain}}/api/v2/stores/1/activity-log?page=1'
                  next_page_url: null
                  prev_page_url: null
                  path: '{{protocol}}{{domain}}/api/v2/stores/1/activity-log'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-v2-stores-store-activity-log
  /api/stores:
    post:
      tags:
      - Stores
      summary: Create Store
      description: 'Creates a new store. Also creates an associated address record.


        :::info[Required scope: `settings:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Fields:

        - name (required, string, max:255, unique)

        - email (required, valid email, max:255)

        - po_email (optional, comma-separated email addresses, max:255)

        - company_name (optional, string, max:255)

        - logo_url (optional)

        - download_logo (optional, boolean — download logo from logo_url)

        - custom_jrxml_file (optional — custom packing slip template)

        - custom_message (optional — message printed on packing slips)

        - address1 (optional, string, max:255)

        - address2 (optional, string, max:255)

        - address3 (optional, string, max:255)

        - city (optional, string, max:255)

        - province (optional, string, max:255)

        - province_code (optional, string, max:255)

        - zip (optional, string, max:255)

        - country (optional, string, max:255)

        - country_code (optional, string, max:2)

        - phone (optional, string, max:255)

        - fax (optional, string, max:255)


        **Requires permission:** `stores.create`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                email:
                  type: string
                po_email:
                  type: string
                company_name:
                  type: string
                logo_url:
                  type: string
                  nullable: true
                download_logo:
                  type: boolean
                custom_jrxml_file:
                  type: string
                  nullable: true
                custom_message:
                  type: string
                address1:
                  type: string
                address2:
                  type: string
                  nullable: true
                address3:
                  type: string
                  nullable: true
                city:
                  type: string
                province:
                  type: string
                province_code:
                  type: string
                zip:
                  type: string
                country:
                  type: string
                country_code:
                  type: string
                phone:
                  type: string
                fax:
                  type: string
                  nullable: true
              example:
                name: West Coast Store
                email: west@acme.com
                po_email: west-purchasing@acme.com
                company_name: Acme West LLC
                logo_url: null
                download_logo: false
                custom_jrxml_file: null
                custom_message: Thank you for shopping with us!
                address1: 456 Pacific Ave
                address2: null
                address3: null
                city: Los Angeles
                province: California
                province_code: CA
                zip: '90001'
                country: United States
                country_code: US
                phone: +1-310-555-0100
                fax: null
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      is_default:
                        type: boolean
                      name:
                        type: string
                      logo_url:
                        type: string
                        nullable: true
                      company_name:
                        type: string
                      email:
                        type: string
                      po_email:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 2
                    is_default: false
                    name: West Coast Store
                    logo_url: null
                    company_name: Acme West LLC
                    email: west@acme.com
                    po_email: west-purchasing@acme.com
                    archived_at: null
                    created_at: '2024-03-01T12:00:00.000000Z'
                    updated_at: '2024-03-01T12:00:00.000000Z'
                  message: store created successfully
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      name:
                        type: array
                        items:
                          type: string
                      email:
                        type: array
                        items:
                          type: string
                example:
                  message: The given data was invalid.
                  errors:
                    name:
                    - The name has already been taken.
                    email:
                    - The email field is required.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: settings:write
      operationId: post-api-stores
    delete:
      tags:
      - Stores
      summary: Bulk Delete Stores
      description: 'Bulk deletes multiple stores by IDs.


        :::info[Required scope: `settings:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `stores.delete`'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 2 stores deleted successfully
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: settings:write
      operationId: delete-api-stores
  /api/stores/{id}:
    put:
      tags:
      - Stores
      summary: Update Store
      description: 'Updates an existing store and its address.


        :::info[Required scope: `settings:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        All fields from Create are accepted. For PUT requests, name and email use
        ''sometimes|required'' validation.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                email:
                  type: string
                phone:
                  type: string
                city:
                  type: string
                province:
                  type: string
                province_code:
                  type: string
                zip:
                  type: string
                country:
                  type: string
                country_code:
                  type: string
              example:
                name: West Coast Store Updated
                email: west-updated@acme.com
                phone: +1-310-555-9999
                city: San Francisco
                province: California
                province_code: CA
                zip: '94105'
                country: United States
                country_code: US
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      is_default:
                        type: boolean
                      name:
                        type: string
                      email:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                      updated_at:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 2
                    is_default: false
                    name: West Coast Store Updated
                    email: west-updated@acme.com
                    archived_at: null
                    updated_at: '2024-03-01T14:00:00.000000Z'
                  message: store West Coast Store Updated updated successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: settings:write
      operationId: put-api-stores-id
    delete:
      tags:
      - Stores
      summary: Delete Store
      description: 'Deletes a store. Returns an error if the store is linked to other
        records.


        :::info[Required scope: `settings:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: store West Coast Store Updated deleted successfully
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: array
                    items:
                      type: object
                      properties:
                        message:
                          type: string
                        code:
                          type: string
                        field:
                          type: string
                  message:
                    type: string
                example:
                  errors:
                  - message: This store is currently linked to sales channels.
                    code: SalesChannelRESOURCE_LINKED
                    field: sales_channels
                  message: store Main Store could not be deleted
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: settings:write
      operationId: delete-api-stores-id
  /api/stores/{id}/archive:
    put:
      tags:
      - Stores
      summary: Archive Store
      description: 'Archives a store. Returns a warning if already archived.


        :::info[Required scope: `settings:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      archived_at:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 1
                    name: Main Store
                    archived_at: '2024-03-01T15:00:00.000000Z'
                  message: store Main Store archived successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: settings:write
      operationId: put-api-stores-id-archive
  /api/stores/{id}/unarchive:
    put:
      tags:
      - Stores
      summary: Unarchive Store
      description: 'Unarchives a store. Returns a warning if not currently archived.


        :::info[Required scope: `settings:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                  message:
                    type: string
                example:
                  data:
                    id: 1
                    name: Main Store
                    archived_at: null
                  message: store Main Store unarchived successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: settings:write
      operationId: put-api-stores-id-unarchive
  /api/stores/{id}/set-default:
    put:
      tags:
      - Stores
      summary: Set Default Store
      description: 'Set this store as the tenant default. It becomes the fallback
        From/sender for outbound email whose context has no store of its own (e.g.
        an account-level customer statement); a store carried by the order or customer
        still takes precedence. Returns the updated store.


        Authentication: Requires Bearer token (PAT).'
      requestBody:
        content: {}
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      archived_at:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 1
                    name: Main Store
                    archived_at: '2024-03-01T15:00:00.000000Z'
                  message: store Main Store archived successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-stores-id-set-default
  /api/stores/archive:
    put:
      tags:
      - Stores
      summary: Bulk Archive Stores
      description: 'Bulk archives multiple stores by IDs.


        :::info[Required scope: `settings:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `stores.archive`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1
                - 2
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 2 stores archived successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: settings:write
      operationId: put-api-stores-archive
  /api/stores/unarchive:
    put:
      tags:
      - Stores
      summary: Bulk Unarchive Stores
      description: 'Bulk unarchives multiple stores by IDs.


        :::info[Required scope: `settings:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `stores.archive`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1
                - 2
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 2 stores unarchived successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: settings:write
      operationId: put-api-stores-unarchive
  /api/stores/deletable:
    post:
      tags:
      - Stores
      summary: Check Stores Deletable
      description: 'Checks which stores can be safely deleted.


        :::info[Required scope: `settings:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `stores.delete`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1
                - 2
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        deletable:
                          type: boolean
                        reason:
                          type: object
                          properties:
                            sales_channels:
                              type: string
                example:
                  data:
                  - id: 1
                    name: Main Store
                    deletable: false
                    reason:
                      sales_channels: This store is used by sales channels.
                  - id: 2
                    name: West Coast Store
                    deletable: true
                    reason: null
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: settings:write
      operationId: post-api-stores-deletable
  /api/stores/import:
    post:
      tags:
      - Stores
      summary: Import Stores
      description: 'Imports stores in bulk from JSON data.


        :::info[Required scope: `settings:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `stores.import`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                data:
                  type: array
                  items:
                    type: object
                    properties:
                      name:
                        type: string
                      email:
                        type: string
              example:
                data:
                - name: Import Store 1
                  email: store1@acme.com
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Stores imported successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: settings:write
      operationId: post-api-stores-import
  /api/stores/import/preview:
    post:
      tags:
      - Stores
      summary: Preview Import Stores
      description: 'Previews a store import without committing changes.


        :::info[Required scope: `settings:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `stores.import`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                data:
                  type: array
                  items:
                    type: object
                    properties:
                      name:
                        type: string
                      email:
                        type: string
              example:
                data:
                - name: Preview Store 1
                  email: preview1@acme.com
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        name:
                          type: string
                        action:
                          type: string
                        email:
                          type: string
                example:
                  data:
                  - name: Preview Store 1
                    action: create
                    email: preview1@acme.com
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: settings:write
      operationId: post-api-stores-import-preview
  /api/channel-partners/{id}/inbound-events:
    get:
      tags:
      - Sales Channels
      summary: List Inbound Events
      description: 'Returns paginated inbound API events for a channel partner instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      - name: page
        in: query
        schema:
          type: integer
        example: '1'
        description: Page number (default 1).
      - name: per_page
        in: query
        schema:
          type: integer
        example: '15'
        description: Results per page (default 10).
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        endpoint:
                          type: string
                        http_method:
                          type: string
                        processing_status:
                          type: string
                        processing_error:
                          type: string
                          nullable: true
                        processing_attempts:
                          type: integer
                        ip_address:
                          type: string
                        user_agent:
                          type: string
                        linked_resource_type:
                          type: string
                        linked_resource_id:
                          type: integer
                        unique_id:
                          type: string
                        created_at:
                          type: string
                        processed_at:
                          type: string
                        processing_started_at:
                          type: string
                        processing_completed_at:
                          type: string
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 100
                    integration_instance_id: 1
                    endpoint: channel.orders.store
                    http_method: POST
                    processing_status: processed
                    processing_error: null
                    processing_attempts: 1
                    ip_address: 203.0.113.5
                    user_agent: MyStorefront/1.0
                    linked_resource_type: App\Models\SalesOrder
                    linked_resource_id: 500
                    unique_id: order-ext-123
                    created_at: '2024-06-01T08:00:00.000000Z'
                    processed_at: '2024-06-01T08:00:01.000000Z'
                    processing_started_at: '2024-06-01T08:00:00.500000Z'
                    processing_completed_at: '2024-06-01T08:00:01.000000Z'
                  per_page: 15
                  total: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-channel-partners-id-inbound-events
  /api/channel-partners/{id}/inbound-events/stats:
    get:
      tags:
      - Sales Channels
      summary: Get Inbound Event Stats
      description: 'Returns event processing statistics and distinct endpoint list
        for a channel partner.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      total:
                        type: integer
                      processed:
                        type: integer
                      failed:
                        type: integer
                      processing:
                        type: integer
                      pending:
                        type: integer
                      endpoints:
                        type: array
                        items:
                          type: string
                example:
                  data:
                    total: 142
                    processed: 138
                    failed: 4
                    processing: 0
                    pending: 0
                    endpoints:
                    - channel.orders.store
                    - channel.orders.update
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-channel-partners-id-inbound-events-stats
  /api/channel-partners/inbound-events/{id}:
    get:
      tags:
      - Sales Channels
      summary: Get Inbound Event
      description: 'Returns a single inbound event with full request/response payloads
        and headers.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      integration_instance_name:
                        type: string
                      endpoint:
                        type: string
                      http_method:
                        type: string
                      processing_status:
                        type: string
                      processing_error:
                        type: string
                        nullable: true
                      processing_attempts:
                        type: integer
                      ip_address:
                        type: string
                      user_agent:
                        type: string
                      request_payload:
                        type: object
                        properties:
                          sales_order_number:
                            type: string
                          order_date:
                            type: string
                      response_payload:
                        type: object
                        properties:
                          message:
                            type: string
                      request_headers:
                        type: object
                        properties:
                          content-type:
                            type: string
                      linked_resource_type:
                        type: string
                      linked_resource_id:
                        type: integer
                      unique_id:
                        type: string
                      created_at:
                        type: string
                      processed_at:
                        type: string
                example:
                  data:
                    id: 100
                    integration_instance_id: 1
                    integration_instance_name: My Storefront API
                    endpoint: channel.orders.store
                    http_method: POST
                    processing_status: processed
                    processing_error: null
                    processing_attempts: 1
                    ip_address: 203.0.113.5
                    user_agent: MyStorefront/1.0
                    request_payload:
                      sales_order_number: EXT-001
                      order_date: '2024-06-01'
                    response_payload:
                      message: sales order created successfully.
                    request_headers:
                      content-type: application/json
                    linked_resource_type: App\Models\SalesOrder
                    linked_resource_id: 500
                    unique_id: order-ext-123
                    created_at: '2024-06-01T08:00:00.000000Z'
                    processed_at: '2024-06-01T08:00:01.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-channel-partners-inbound-events-id
  /api/channel-partners/inbound-events/{id}/reprocess:
    post:
      tags:
      - Sales Channels
      summary: Reprocess Inbound Event
      description: 'Reprocesses a single failed inbound event. Cannot reprocess already-processed
        events.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      processing_status:
                        type: string
                      processing_attempts:
                        type: integer
                example:
                  message: Event queued for reprocessing.
                  data:
                    id: 100
                    processing_status: processing
                    processing_attempts: 2
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Event has already been processed.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-channel-partners-inbound-events-id-reprocess
  /api/channel-partners/inbound-events/bulk-reprocess:
    post:
      tags:
      - Sales Channels
      summary: Bulk Reprocess Events
      description: 'Bulk reprocesses multiple inbound events by ID.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Body:

        - ids (required): Array of event IDs to reprocess (min 1)'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 100
                - 101
                - 102
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 3 event(s) queued for reprocessing.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-channel-partners-inbound-events-bulk-reprocess
  /api/channel-partners/inbound-events/bulk-delete:
    delete:
      tags:
      - Sales Channels
      summary: Bulk Delete Events
      description: 'Bulk deletes inbound events by ID.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Body:

        - ids (required): Array of event IDs to delete (min 1)'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 3 event(s) deleted.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: delete-api-channel-partners-inbound-events-bulk-delete
  /api/channel-partners/{id}/inbound-events/delete-all:
    delete:
      tags:
      - Channel Partners
      summary: Delete All Inbound Events
      description: 'Delete ALL inbound events for a channel partner instance. Use
        with caution.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 97 event(s) deleted.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-channel-partners-id-inbound-events-delete-all
  /api/channel/orders:
    get:
      tags:
      - Sales Channels
      summary: List Orders
      description: 'Lists sales orders for the authenticated channel (filtered to
        the integration instance''s sales channel).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires channel integration token (channel:read ability).
        Use {{channel-token}} variable.


        Rate limits: 500 requests per 60 seconds.'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        example: '1'
        description: Page number (default 1).
      - name: per_page
        in: query
        schema:
          type: integer
        example: '15'
        description: Results per page (default 10).
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        sales_order_number:
                          type: string
                        customer_po_number:
                          type: string
                        order_status:
                          type: string
                        fulfillment_status:
                          type: string
                        customer_name:
                          type: string
                        order_date:
                          type: string
                        ship_by_date:
                          type: string
                        deliver_by_date:
                          type: string
                          nullable: true
                        product_subtotal:
                          type: number
                        requested_shipping_method:
                          type: string
                        sales_channel_id:
                          type: integer
                        fulfillment_channel:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 500
                    sales_order_number: SO-2024-500
                    customer_po_number: EXT-001
                    order_status: open
                    fulfillment_status: unfulfilled
                    customer_name: John Doe
                    order_date: '2024-06-01T08:00:00.000000Z'
                    ship_by_date: '2024-06-05T00:00:00.000000Z'
                    deliver_by_date: null
                    product_subtotal: 150.0
                    requested_shipping_method: standard
                    sales_channel_id: 3
                    fulfillment_channel: null
                    created_at: '2024-06-01T08:00:00.000000Z'
                    updated_at: '2024-06-01T08:00:00.000000Z'
                  per_page: 15
                  total: 142
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-channel-orders
    post:
      tags:
      - Sales Channels
      summary: Create Order
      description: "Creates a new sales order from a channel integration.\n\n:::info[Authorization]\n\
        Any valid API token can call this endpoint — no specific scope required. [Manage\
        \ tokens](https://app.sku.io/settings/api).\n:::\n\nAuthentication: Requires\
        \ channel integration token (channel:write ability).\n\nRate limits: 500 requests\
        \ per 60 seconds.\n\nAll inbound events are automatically captured for audit/replay.\n\
        \nFields:\n- sales_order_number (required, unique per channel): External order\
        \ identifier\n- order_date (required): Order date\n- ship_by_date (optional):\
        \ Must be >= order_date\n- hold_until_date (optional): \"Do not ship before\"\
        \ release date for preorders / scheduled holds. Must be >= order_date.\n-\
        \ deliver_by_date (optional): Must be >= order_date\n- customer_po_number\
        \ (optional): Customer's PO reference\n- requested_shipping_method (optional):\
        \ Requested shipping service\n- shipping_charge (optional): Shipping amount\n\
        - customer (optional): Customer info — must have EITHER id OR name, not both\n\
        \  - customer.id: Existing customer ID\n  - customer.name: Customer name\n\
        \  - customer.email: Email\n  - customer.phone: Phone\n  - customer.company:\
        \ Company name\n- billing_address (optional): Billing address object\n- shipping_address\
        \ (optional): Shipping address object\n  - *.name, *.company, *.address1,\
        \ *.address2, *.city, *.province_code, *.zip, *.country_code, *.phone\n- sales_order_lines\
        \ (required, min 1): Order lines\n  - lines.*.sku (required): Product SKU\
        \ (must exist)\n  - lines.*.quantity (required): Quantity (min 1)\n  - lines.*.unit_price\
        \ (optional): Unit price\n  - lines.*.description (optional): Line description\n\
        - notes (optional): Array of note strings\n- tags (optional): Array of tag\
        \ strings\n- sales_rep (optional): Sales rep — must have EITHER id OR name,\
        \ not both\n  - sales_rep.id: Existing active sales rep ID\n  - sales_rep.name:\
        \ Sales rep name"
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                sales_order_number:
                  type: string
                order_date:
                  type: string
                ship_by_date:
                  type: string
                hold_until_date:
                  type: string
                deliver_by_date:
                  type: string
                customer_po_number:
                  type: string
                requested_shipping_method:
                  type: string
                shipping_charge:
                  type: number
                customer:
                  type: object
                  properties:
                    name:
                      type: string
                    email:
                      type: string
                    company:
                      type: string
                billing_address:
                  type: object
                  properties:
                    name:
                      type: string
                    address1:
                      type: string
                    address2:
                      type: string
                    city:
                      type: string
                    province_code:
                      type: string
                    zip:
                      type: string
                    country_code:
                      type: string
                    phone:
                      type: string
                shipping_address:
                  type: object
                  properties:
                    name:
                      type: string
                    address1:
                      type: string
                    city:
                      type: string
                    province_code:
                      type: string
                    zip:
                      type: string
                    country_code:
                      type: string
                sales_order_lines:
                  type: array
                  items:
                    type: object
                    properties:
                      sku:
                        type: string
                      quantity:
                        type: integer
                      unit_price:
                        type: integer
                      description:
                        type: string
                notes:
                  type: array
                  items:
                    type: string
                tags:
                  type: array
                  items:
                    type: string
                sales_rep:
                  type: object
                  properties:
                    name:
                      type: string
                    email:
                      type: string
              example:
                sales_order_number: EXT-ORDER-2024-001
                order_date: '2024-06-01'
                ship_by_date: '2024-06-05'
                hold_until_date: '2024-06-03'
                deliver_by_date: '2024-06-07'
                customer_po_number: CUST-PO-001
                requested_shipping_method: standard
                shipping_charge: 9.99
                customer:
                  name: John Doe
                  email: john.doe@example.com
                  company: Acme Corp
                billing_address:
                  name: John Doe
                  address1: 123 Main St
                  address2: Apt 4B
                  city: New York
                  province_code: NY
                  zip: '10001'
                  country_code: US
                  phone: +1-212-555-0100
                shipping_address:
                  name: John Doe
                  address1: 123 Main St
                  city: New York
                  province_code: NY
                  zip: '10001'
                  country_code: US
                sales_order_lines:
                - sku: WIDGET-PRO-001
                  quantity: 2
                  unit_price: 75
                  description: Widget Pro x2
                notes:
                - Please ship as soon as possible
                tags:
                - vip
                - priority
                sales_rep:
                  name: Jane Smith
                  email: jane@sku.io
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      sales_order_number:
                        type: string
                      order_status:
                        type: string
                      fulfillment_status:
                        type: string
                      order_date:
                        type: string
                      sales_order_lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            product:
                              type: object
                              properties:
                                id:
                                  type: integer
                                name:
                                  type: string
                                sku:
                                  type: string
                            quantity:
                              type: integer
                            unit_price:
                              type: number
                      tags:
                        type: array
                        items:
                          type: string
                example:
                  message: sales order created successfully.
                  data:
                    id: 501
                    sales_order_number: EXT-ORDER-2024-001
                    order_status: open
                    fulfillment_status: unfulfilled
                    order_date: '2024-06-01T00:00:00.000000Z'
                    sales_order_lines:
                    - id: 1002
                      product:
                        id: 10
                        name: Widget Pro
                        sku: WIDGET-PRO-001
                      quantity: 2
                      unit_price: 75.0
                    tags:
                    - vip
                    - priority
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      sales_order_number:
                        type: array
                        items:
                          type: string
                      sales_order_lines.0.sku:
                        type: array
                        items:
                          type: string
                example:
                  message: The given data was invalid.
                  errors:
                    sales_order_number:
                    - The sales order number has already been taken.
                    sales_order_lines.0.sku:
                    - The selected sales_order_lines.0.sku is invalid.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-channel-orders
  /api/channel/orders/{id}:
    get:
      tags:
      - Sales Channels
      summary: Get Order
      description: 'Returns a single sales order for the authenticated channel with
        fulfillment and address details.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires channel integration token.


        Returns 403 if the order does not belong to the authenticated channel.'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      sales_order_number:
                        type: string
                      order_status:
                        type: string
                      fulfillment_status:
                        type: string
                      order_date:
                        type: string
                      billing_address:
                        type: object
                        properties:
                          name:
                            type: string
                          address1:
                            type: string
                          city:
                            type: string
                          zip:
                            type: string
                          country_code:
                            type: string
                      shipping_address:
                        type: object
                        properties:
                          name:
                            type: string
                          address1:
                            type: string
                          city:
                            type: string
                          zip:
                            type: string
                          country_code:
                            type: string
                      sales_order_lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            product:
                              type: object
                              properties:
                                id:
                                  type: integer
                                name:
                                  type: string
                                sku:
                                  type: string
                            quantity:
                              type: integer
                            unit_price:
                              type: number
                      tags:
                        type: array
                example:
                  data:
                    id: 500
                    sales_order_number: SO-2024-500
                    order_status: open
                    fulfillment_status: unfulfilled
                    order_date: '2024-06-01T08:00:00.000000Z'
                    billing_address:
                      name: John Doe
                      address1: 123 Main St
                      city: New York
                      zip: '10001'
                      country_code: US
                    shipping_address:
                      name: John Doe
                      address1: 123 Main St
                      city: New York
                      zip: '10001'
                      country_code: US
                    sales_order_lines:
                    - id: 1001
                      product:
                        id: 10
                        name: Widget Pro
                        sku: WIDGET-PRO-001
                      quantity: 2
                      unit_price: 75.0
                    tags: []
        '403':
          description: Forbidden
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Order does not belong to this channel
        '429': *id001
        '401': *id002
        '404': *id004
      operationId: get-api-channel-orders-id
    put:
      tags:
      - Sales Channels
      summary: Update Order
      description: 'Updates a sales order for the authenticated channel.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires channel integration token.


        Returns 403 if the order does not belong to the authenticated channel.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ship_by_date:
                  type: string
                hold_until_date:
                  type: string
                requested_shipping_method:
                  type: string
              example:
                ship_by_date: '2024-06-06'
                hold_until_date: '2024-06-03'
                requested_shipping_method: express
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      sales_order_number:
                        type: string
                      order_status:
                        type: string
                      requested_shipping_method:
                        type: string
                      ship_by_date:
                        type: string
                example:
                  message: sales order updated successfully.
                  data:
                    id: 500
                    sales_order_number: SO-2024-500
                    order_status: open
                    requested_shipping_method: express
                    ship_by_date: '2024-06-06T00:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-channel-orders-id
  /api/channel/products:
    get:
      tags:
      - Sales Channels
      summary: List Products
      description: 'Returns paginated products visible to the authenticated channel.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires channel integration token.


        Rate limits: 2000 requests per 60 minutes.'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        example: '1'
        description: Page number (default 1).
      - name: per_page
        in: query
        schema:
          type: integer
        example: '15'
        description: Results per page (default 10).
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        sku:
                          type: string
                        barcode:
                          type: string
                        price:
                          type: number
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 10
                    name: Widget Pro
                    sku: WIDGET-PRO-001
                    barcode: '123456789012'
                    price: 75.0
                  per_page: 15
                  total: 50
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-channel-products
  /api/channel/products/{id}:
    get:
      tags:
      - Sales Channels
      summary: Get Product
      description: 'Returns a single product by ID for the authenticated channel.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires channel integration token.


        Rate limits: 2000 requests per 60 minutes.'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      sku:
                        type: string
                      barcode:
                        type: string
                      price:
                        type: number
                      description:
                        type: string
                      weight:
                        type: number
                example:
                  data:
                    id: 10
                    name: Widget Pro
                    sku: WIDGET-PRO-001
                    barcode: '123456789012'
                    price: 75.0
                    description: The best widget
                    weight: 0.5
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-channel-products-id
  /api/channel/inventory:
    get:
      tags:
      - Sales Channels
      summary: List Inventory
      description: 'Returns paginated inventory levels for the authenticated channel.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires channel integration token.


        Rate limits: 2000 requests per 60 minutes.'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        example: '1'
        description: Page number (default 1).
      - name: per_page
        in: query
        schema:
          type: integer
        example: '15'
        description: Results per page (default 10).
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        sku:
                          type: string
                        available_quantity:
                          type: integer
                        on_hand_quantity:
                          type: integer
                        allocated_quantity:
                          type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - sku: WIDGET-PRO-001
                    available_quantity: 85
                    on_hand_quantity: 100
                    allocated_quantity: 15
                  per_page: 15
                  total: 50
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-channel-inventory
  /api/channel/customers:
    get:
      tags:
      - Sales Channels
      summary: List Customers
      description: 'Returns paginated customers for the authenticated channel.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires channel integration token.


        Rate limits: 2000 requests per 60 minutes.'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        example: '1'
        description: Page number (default 1).
      - name: per_page
        in: query
        schema:
          type: integer
        example: '15'
        description: Results per page (default 10).
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        email:
                          type: string
                        company:
                          type: string
                        channel_id:
                          type: integer
                        created_at:
                          type: string
                        updated_at:
                          type: string
                        archived_at:
                          type: string
                          nullable: true
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 50
                    name: John Doe
                    email: john.doe@example.com
                    company: Acme Corp
                    channel_id: 1
                    created_at: '2024-01-01T00:00:00.000000Z'
                    updated_at: '2024-01-15T10:00:00.000000Z'
                    archived_at: null
                  per_page: 15
                  total: 30
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-channel-customers
  /api/channel/customers/{id}:
    get:
      tags:
      - Sales Channels
      summary: Get Customer
      description: 'Returns a single customer with addresses and default sales rep.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires channel integration token.


        Rate limits: 2000 requests per 60 minutes.'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      email:
                        type: string
                      company:
                        type: string
                      channel_id:
                        type: integer
                      billing_address:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          address1:
                            type: string
                          city:
                            type: string
                          province:
                            type: string
                          zip:
                            type: string
                          country_code:
                            type: string
                          phone:
                            type: string
                      shipping_address:
                        type: string
                        nullable: true
                      addresses:
                        type: array
                      default_pricing_tier:
                        type: string
                        nullable: true
                      default_sales_rep:
                        type: string
                        nullable: true
                example:
                  data:
                    id: 50
                    name: John Doe
                    email: john.doe@example.com
                    company: Acme Corp
                    channel_id: 1
                    billing_address:
                      id: 200
                      name: John Doe
                      address1: 123 Main St
                      city: New York
                      province: NY
                      zip: '10001'
                      country_code: US
                      phone: +1-212-555-0100
                    shipping_address: null
                    addresses: []
                    default_pricing_tier: null
                    default_sales_rep: null
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Customer not found
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-channel-customers-id
  /api/channel-partners:
    get:
      tags:
      - Channel Partners
      summary: List Channel Partners
      description: 'Returns all API Sales Channel integration instances (channel partners).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token (Sanctum user session).'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        integration_id:
                          type: integer
                        connection_settings:
                          type: object
                          properties: {}
                        integration_settings:
                          type: object
                          properties: {}
                        sync_status:
                          type: string
                          nullable: true
                        is_automatic_sync_enabled:
                          type: boolean
                        sales_channel:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            store_id:
                              type: integer
                        orders_count:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                        updated_at:
                          type: string
                example:
                  data:
                  - id: 1
                    name: My Storefront API
                    integration_id: 5
                    connection_settings: {}
                    integration_settings: {}
                    sync_status: null
                    is_automatic_sync_enabled: false
                    sales_channel:
                      id: 3
                      name: My Storefront
                      store_id: 1
                    orders_count: null
                    created_at: '2024-01-15T10:00:00.000000Z'
                    updated_at: '2024-01-15T10:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-channel-partners
    post:
      tags:
      - Channel Partners
      summary: Create Channel Partner
      description: 'Create a new API Sales Channel integration instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Request body fields:

        - `name` (required, string, max:255)

        - `store_id` (optional, integer)'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                store_id:
                  type: integer
              example:
                name: B2B Portal Integration
                store_id: 1
      parameters: []
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                example:
                  data:
                    id: 2
                    name: B2B Portal Integration
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      name:
                        type: array
                        items:
                          type: string
                example:
                  message: The given data was invalid.
                  errors:
                    name:
                    - The name field is required.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-channel-partners
  /api/channel-partners/{id}:
    get:
      tags:
      - Channel Partners
      summary: Get Channel Partner
      description: 'Returns a single channel partner integration instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      integration_id:
                        type: integer
                      connection_settings:
                        type: object
                        properties: {}
                      integration_settings:
                        type: object
                        properties: {}
                      sync_status:
                        type: string
                        nullable: true
                      is_automatic_sync_enabled:
                        type: boolean
                      sales_channel:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          store_id:
                            type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 1
                    name: My Storefront API
                    integration_id: 5
                    connection_settings: {}
                    integration_settings: {}
                    sync_status: null
                    is_automatic_sync_enabled: false
                    sales_channel:
                      id: 3
                      name: My Storefront
                      store_id: 1
                    created_at: '2024-01-15T10:00:00.000000Z'
                    updated_at: '2024-01-15T10:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-channel-partners-id
    put:
      tags:
      - Channel Partners
      summary: Update Channel Partner
      description: 'Updates a channel partner integration instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Fields (all optional):

        - name: Updated name (max 255 chars)

        - store_id: Updated store ID (nullable)'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                store_id:
                  type: integer
              example:
                name: Updated Storefront API
                store_id: 2
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      integration_id:
                        type: integer
                example:
                  data:
                    id: 1
                    name: Updated Storefront API
                    integration_id: 5
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-channel-partners-id
    delete:
      tags:
      - Channel Partners
      summary: Delete Channel Partner
      description: 'Deletes a channel partner integration instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Returns 204 No Content.'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '204':
          description: No Content
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            text/plain:
              schema:
                type: string
                example: ''
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-channel-partners-id
  /api/channel-partners/{id}/dashboard:
    get:
      tags:
      - Channel Partners
      summary: Get Channel Partner Dashboard
      description: 'Returns dashboard stats and recent orders for a channel partner.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      instance:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      stats:
                        type: object
                        properties:
                          total_orders:
                            type: integer
                          pending_orders:
                            type: integer
                          fulfilled_orders:
                            type: integer
                          last_order_at:
                            type: string
                      recent_orders:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            sales_order_number:
                              type: string
                            order_status:
                              type: string
                            fulfillment_status:
                              type: string
                            order_date:
                              type: string
                example:
                  data:
                    instance:
                      id: 1
                      name: My Storefront API
                    stats:
                      total_orders: 142
                      pending_orders: 12
                      fulfilled_orders: 130
                      last_order_at: '2024-06-01T09:00:00.000000Z'
                    recent_orders:
                    - id: 500
                      sales_order_number: SO-2024-500
                      order_status: open
                      fulfillment_status: unfulfilled
                      order_date: '2024-06-01T08:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-channel-partners-id-dashboard
  /api/channel-partners/{id}/orders:
    get:
      tags:
      - Channel Partners
      summary: List Channel Partner Orders
      description: 'Returns paginated sales orders for a channel partner''s sales
        channel.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      - name: page
        in: query
        schema:
          type: integer
        example: '1'
        description: Page number (default 1).
      - name: per_page
        in: query
        schema:
          type: integer
        example: '15'
        description: Results per page (default 10).
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        sales_order_number:
                          type: string
                        order_status:
                          type: string
                        fulfillment_status:
                          type: string
                        customer_name:
                          type: string
                        order_date:
                          type: string
                        created_at:
                          type: string
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 500
                    sales_order_number: SO-2024-500
                    order_status: open
                    fulfillment_status: unfulfilled
                    customer_name: John Doe
                    order_date: '2024-06-01T08:00:00.000000Z'
                    created_at: '2024-06-01T08:00:00.000000Z'
                  per_page: 15
                  total: 142
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-channel-partners-id-orders
  /api/channel-partners/{id}/tokens:
    post:
      tags:
      - Channel Partners
      summary: Generate API Token
      description: 'Generates a new API token for a channel partner. The plain text
        token is only shown once.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Fields:

        - name (required): Token name/label (max 255 chars)'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
              example:
                name: Production Token
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      token:
                        type: string
                      name:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    token: 3|abc123def456ghi789jkl012mno345pqr678|channel:read|channel:write
                    name: Production Token
                  message: Token generated. Please copy it now — it won't be shown
                    again.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-channel-partners-id-tokens
    get:
      tags:
      - Channel Partners
      summary: List API Tokens
      description: 'Lists all active API tokens for a channel partner.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        abilities:
                          type: array
                          items:
                            type: string
                        created_at:
                          type: string
                        last_used_at:
                          type: string
                example:
                  data:
                  - id: 3
                    name: Production Token
                    abilities:
                    - channel:read
                    - channel:write
                    created_at: '2024-06-01T12:00:00.000000Z'
                    last_used_at: '2024-06-01T14:30:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-channel-partners-id-tokens
  /api/channel-partners/{id}/tokens/{id2}:
    delete:
      tags:
      - Channel Partners
      summary: Revoke API Token
      description: 'Revokes a specific API token for a channel partner.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      - name: id2
        in: path
        required: true
        schema:
          type: string
        description: The id2 identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Token revoked successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-channel-partners-id-tokens-id2
  /api/channel/tokens:
    post:
      tags:
      - Channel Partners
      summary: Create Channel API Token
      description: 'Creates a new Sanctum token with channel:read and channel:write
        abilities for a sales channel integration instance. If a token with these
        abilities already exists, it will be replaced.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Fields:

        - name (required): Token name (max 255 chars)

        - integration_instance_id (required): ID of the integration instance'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                integration_instance_id:
                  type: integer
              example:
                name: channel-token-production
                integration_instance_id: 1
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      token:
                        type: string
                      integration_instance_id:
                        type: integer
                      name:
                        type: string
                      abilities:
                        type: array
                        items:
                          type: string
                      created_at:
                        type: string
                      replaced_existing:
                        type: boolean
                example:
                  data:
                    token: 4|channeltoken123abc456def789ghi012jkl
                    integration_instance_id: 1
                    name: channel-token-production
                    abilities:
                    - channel:read
                    - channel:write
                    created_at: '2024-06-01T12:00:00.000000Z'
                    replaced_existing: false
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-channel-tokens
  /api/store-email-templates:
    get:
      tags:
      - Store Email Templates
      summary: List Store Email Templates
      description: 'Returns a paginated listing of store email templates.


        :::info[Required scope: `settings:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Sort fields: subject, type, store_id, enabled, sent_type, is_system_template,
        created_at, updated_at, archived_at'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        description: Page number
        example: '1'
      - name: limit
        in: query
        schema:
          type: integer
        description: Records per page
        example: '15'
      - name: sort
        in: query
        schema:
          type: string
        description: Sort field (prefix with - for descending)
        example: subject
      - name: search
        in: query
        schema:
          type: string
        description: Search by subject or type
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        store_id:
                          type: integer
                        type:
                          type: string
                        subject:
                          type: string
                        title:
                          type: string
                        enabled:
                          type: boolean
                        attach_pdf:
                          type: boolean
                        sent_type:
                          type: string
                        is_system_template:
                          type: boolean
                        cc:
                          type: array
                          items:
                            type: string
                        archived_at:
                          type: string
                          nullable: true
                        updated_at:
                          type: string
                        created_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  status: success
                  data:
                  - id: 1
                    store_id: 3
                    type: purchase_order
                    subject: 'Your Purchase Order #{{order_number}}'
                    title: 'Your Purchase Order #{{order_number}}'
                    enabled: true
                    attach_pdf: true
                    sent_type: automatically
                    is_system_template: true
                    cc:
                    - purchasing@company.com
                    archived_at: null
                    updated_at: '2024-05-15T09:00:00.000000Z'
                    created_at: '2024-01-01T00:00:00.000000Z'
                  current_page: 1
                  last_page: 1
                  per_page: 15
                  total: 5
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: settings:read
      operationId: get-api-store-email-templates
    post:
      tags:
      - Store Email Templates
      summary: Create Store Email Template
      description: 'Creates a new store email template (always non-system).


        :::info[Required scope: `settings:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Fields:

        - store_id (required): store ID (must exist)

        - context (required): bound entity — one of sales_order, purchase_order, sales_credit,
        vendor_credit, bulk_purchase_order, warehouse_transfer. Determines available
        variables and attachable documents.

        - event (required): trigger within the context (e.g. confirmation, updated,
        fulfilled, submitted, issued, manual). The legacy `type` column is derived
        from context+event server-side.

        - name (optional): human label for the template

        - subject (required): subject line, max 255

        - html_body (required): HTML body (supports {{ }} merge variables)

        - enabled (optional): boolean. For automatic events only one template per
        (store, context, event) stays enabled.

        - sent_type (optional): automatically | manually

        - cc (optional): array of email addresses

        - attachments (optional): array of document keys valid for the context (e.g.
        po_pdf, po_csv, po_xlsx, invoice_pdf, credit_note_pdf, vendor_credit_pdf)


        **Requires permission:** `email_templates.create`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                store_id:
                  type: integer
                context:
                  type: string
                event:
                  type: string
                name:
                  type: string
                subject:
                  type: string
                html_body:
                  type: string
                enabled:
                  type: boolean
                sent_type:
                  type: string
                cc:
                  type: array
                  items:
                    type: string
                attachments:
                  type: array
                  items:
                    type: string
              example:
                store_id: 3
                context: purchase_order
                event: manual
                name: Standard supplier PO email
                subject: Order {{purchase_order_number}} from {{company_name}}
                html_body: <html><body><p>Dear {{supplier_name}}, please find our
                  order attached.</p></body></html>
                enabled: true
                sent_type: manually
                cc:
                - ops@example.com
                attachments:
                - po_pdf
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      store_id:
                        type: integer
                      type:
                        type: string
                      context:
                        type: string
                      event:
                        type: string
                      name:
                        type: string
                      subject:
                        type: string
                      title:
                        type: string
                      enabled:
                        type: boolean
                      attach_pdf:
                        type: boolean
                      attachments:
                        type: array
                        items:
                          type: string
                      sent_type:
                        type: string
                      html_body:
                        type: string
                      is_system_template:
                        type: boolean
                      cc:
                        type: array
                        items:
                          type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  status: success
                  data:
                    id: 12
                    store_id: 3
                    type: user_purchase_order
                    context: purchase_order
                    event: manual
                    name: Standard supplier PO email
                    subject: Order {{purchase_order_number}} from {{company_name}}
                    title: Order {{purchase_order_number}} from {{company_name}}
                    enabled: true
                    attach_pdf: false
                    attachments:
                    - po_pdf
                    sent_type: manually
                    html_body: <html><body><p>Dear {{supplier_name}}, please find
                      our order attached.</p></body></html>
                    is_system_template: false
                    cc:
                    - ops@example.com
                    created_at: '2026-05-28T12:00:00.000000Z'
                    updated_at: '2026-05-28T12:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: settings:write
      operationId: post-api-store-email-templates
    delete:
      tags:
      - Store Email Templates
      summary: Bulk Delete Store Email Templates
      description: 'Bulk deletes multiple store email templates by ID array or current
        list view filters.


        :::info[Required scope: `settings:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `email_templates.delete`'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                example:
                  status: success
                  message: Templates deleted successfully
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: settings:write
      operationId: delete-api-store-email-templates
  /api/store-email-templates/user-templates:
    get:
      tags:
      - Store Email Templates
      summary: List User Templates
      description: 'Returns only non-system (user-created) email templates. Excludes
        system templates that are managed by the application.


        :::info[Required scope: `settings:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        store_id:
                          type: integer
                        type:
                          type: string
                        subject:
                          type: string
                        title:
                          type: string
                        enabled:
                          type: boolean
                        attach_pdf:
                          type: boolean
                        sent_type:
                          type: string
                        is_system_template:
                          type: boolean
                        cc:
                          type: array
                        archived_at:
                          type: string
                          nullable: true
                        updated_at:
                          type: string
                        created_at:
                          type: string
                example:
                  status: success
                  data:
                  - id: 8
                    store_id: 3
                    type: purchase_order
                    subject: Custom PO Template
                    title: Custom PO Template
                    enabled: true
                    attach_pdf: false
                    sent_type: manually
                    is_system_template: false
                    cc: []
                    archived_at: null
                    updated_at: '2024-06-01T10:00:00.000000Z'
                    created_at: '2024-06-01T10:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: settings:read
      operationId: get-api-store-email-templates-user-templates
  /api/store-email-templates/contexts:
    get:
      tags:
      - Store Email Templates
      summary: List Template Contexts
      description: 'Returns the email-template context catalog: for each context (bound
        entity) its label, available events (automatic/manual), merge variables, and
        attachable documents. The editor and send dialogs use this as the single source
        of truth for what a template can contain.


        :::info[Required scope: `settings:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      purchase_order:
                        type: object
                        properties:
                          label:
                            type: string
                          events:
                            type: array
                            items:
                              type: object
                              properties:
                                key:
                                  type: string
                                label:
                                  type: string
                                trigger:
                                  type: string
                                description:
                                  type: string
                          variables:
                            type: array
                            items:
                              type: object
                              properties:
                                token:
                                  type: string
                                label:
                                  type: string
                                group:
                                  type: string
                                is_table:
                                  type: boolean
                          documents:
                            type: array
                            items:
                              type: object
                              properties:
                                key:
                                  type: string
                                label:
                                  type: string
                                mime:
                                  type: string
                example:
                  data:
                    purchase_order:
                      label: Purchase Order
                      events:
                      - key: submitted
                        label: PO Submitted
                        trigger: automatic
                        description: Sends automatically to the supplier every time
                          a purchase order is submitted.
                      - key: updated
                        label: PO Updated
                        trigger: automatic
                        description: Sends automatically every time a submitted purchase
                          order is changed.
                      - key: manual
                        label: Manual Send
                        trigger: manual
                        description: Never sends on its own. You choose this template
                          from the purchase order screen when you want to email the
                          supplier.
                      variables:
                      - token: '{{purchase_order_number}}'
                        label: Purchase Order ID
                        group: Details
                        is_table: false
                      - token: '{{purchase_order_lines}}'
                        label: Order Item List
                        group: Line Items
                        is_table: true
                      documents:
                      - key: po_pdf
                        label: PO PDF
                        mime: application/pdf
                      - key: po_csv
                        label: PO CSV
                        mime: text/csv
                      - key: po_xlsx
                        label: PO XLSX
                        mime: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: settings:read
      operationId: get-api-store-email-templates-contexts
  /api/store-email-templates/{id}:
    get:
      tags:
      - Store Email Templates
      summary: Get Store Email Template
      description: 'Returns a single store email template with its HTML body.


        :::info[Required scope: `settings:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      store_id:
                        type: integer
                      type:
                        type: string
                      subject:
                        type: string
                      title:
                        type: string
                      enabled:
                        type: boolean
                      attach_pdf:
                        type: boolean
                      sent_type:
                        type: string
                      html_body:
                        type: string
                      is_system_template:
                        type: boolean
                      cc:
                        type: array
                        items:
                          type: string
                      archived_at:
                        type: string
                        nullable: true
                      updated_at:
                        type: string
                      created_at:
                        type: string
                example:
                  status: success
                  data:
                    id: 1
                    store_id: 3
                    type: purchase_order
                    subject: 'Your Purchase Order #{{order_number}}'
                    title: 'Your Purchase Order #{{order_number}}'
                    enabled: true
                    attach_pdf: true
                    sent_type: automatically
                    html_body: <html><body><h1>Purchase Order</h1><p>Dear {{supplier_name}},</p></body></html>
                    is_system_template: true
                    cc:
                    - purchasing@company.com
                    archived_at: null
                    updated_at: '2024-05-15T09:00:00.000000Z'
                    created_at: '2024-01-01T00:00:00.000000Z'
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                example:
                  status: error
                  message: Not Found
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: settings:read
      operationId: get-api-store-email-templates-id
    put:
      tags:
      - Store Email Templates
      summary: Update Store Email Template
      description: 'Updates an existing store email template.


        :::info[Required scope: `settings:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Accepts the same fields as create (context, event, name, subject, html_body,
        enabled, sent_type, cc, attachments). Enabling an automatic-event template
        disables any other enabled template in the same (store, context, event) slot.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                context:
                  type: string
                event:
                  type: string
                name:
                  type: string
                subject:
                  type: string
                html_body:
                  type: string
                enabled:
                  type: boolean
                attachments:
                  type: array
                  items:
                    type: string
              example:
                context: purchase_order
                event: manual
                name: Standard supplier PO email
                subject: Updated subject {{purchase_order_number}}
                html_body: <html><body><p>Updated body.</p></body></html>
                enabled: true
                attachments:
                - po_pdf
                - po_csv
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      subject:
                        type: string
                      enabled:
                        type: boolean
                      sent_type:
                        type: string
                      updated_at:
                        type: string
                example:
                  status: success
                  data:
                    id: 1
                    subject: 'Updated: Your PO #{{order_number}}'
                    enabled: false
                    sent_type: manually
                    updated_at: '2024-06-15T14:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: settings:write
      operationId: put-api-store-email-templates-id
    delete:
      tags:
      - Store Email Templates
      summary: Delete Store Email Template
      description: 'Deletes a single store email template.


        :::info[Required scope: `settings:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                example:
                  status: success
                  message: Deleted successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: settings:write
      operationId: delete-api-store-email-templates-id
  /api/store-email-templates/{id}/archive:
    put:
      tags:
      - Store Email Templates
      summary: Archive Store Email Template
      description: 'Archives a single store email template. Idempotent — returns a
        warning if already archived.


        :::info[Required scope: `settings:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      archived_at:
                        type: string
                example:
                  status: success
                  message: StoreEmailTemplate archived successfully
                  data:
                    id: 1
                    archived_at: '2024-06-15T10:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: settings:write
      operationId: put-api-store-email-templates-id-archive
  /api/store-email-templates/{id}/unarchived:
    put:
      tags:
      - Store Email Templates
      summary: Unarchive Store Email Template
      description: 'Unarchives a single store email template.


        :::info[Required scope: `settings:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      archived_at:
                        type: string
                        nullable: true
                example:
                  status: success
                  message: StoreEmailTemplate unarchived successfully
                  data:
                    id: 1
                    archived_at: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: settings:write
      operationId: put-api-store-email-templates-id-unarchived
  /api/store-email-templates/archive:
    put:
      tags:
      - Store Email Templates
      summary: Bulk Archive Store Email Templates
      description: 'Bulk archives multiple store email templates by ID array or current
        list view filters.


        :::info[Required scope: `settings:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `email_templates.archive`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1
                - 2
                - 3
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                example:
                  status: success
                  message: Templates archived successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: settings:write
      operationId: put-api-store-email-templates-archive
  /api/store-email-templates/unarchive:
    put:
      tags:
      - Store Email Templates
      summary: Bulk Unarchive Store Email Templates
      description: 'Bulk unarchives multiple store email templates by ID array or
        current list view filters.


        :::info[Required scope: `settings:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `email_templates.archive`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1
                - 2
                - 3
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                example:
                  status: success
                  message: Templates unarchived successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: settings:write
      operationId: put-api-store-email-templates-unarchive
  /api/store-email-templates/deletable:
    post:
      tags:
      - Store Email Templates
      summary: Check Templates Deletable
      description: 'Checks whether each provided store email template ID can be safely
        deleted.


        :::info[Required scope: `settings:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `email_templates.delete`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1
                - 2
                - 3
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        deletable:
                          type: boolean
                        reason:
                          type: string
                          nullable: true
                example:
                  status: success
                  data:
                  - id: 1
                    deletable: true
                    reason: null
                  - id: 2
                    deletable: false
                    reason: System template
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: settings:write
      operationId: post-api-store-email-templates-deletable
  /api/store-email-templates/preview:
    post:
      tags:
      - Store Email Templates
      summary: Preview Template
      description: 'Previews a template with rendered variable substitutions. For
        bulk_purchase_order type, uses the bulk preview renderer.


        :::info[Required scope: `settings:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Body fields:

        - id: Order or entity ID to use for variable substitution

        - type: Template type (e.g. purchase_order, purchase_order_updated, bulk_purchase_order)

        - subject: Subject line template string

        - body: HTML body template string

        - variables (optional): Boolean — if true, returns variable placeholders instead
        of rendered values'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                id:
                  type: integer
                type:
                  type: string
                subject:
                  type: string
                body:
                  type: string
                variables:
                  type: boolean
              example:
                id: 42
                type: purchase_order
                subject: 'Your PO #{{order_number}}'
                body: <p>Dear {{supplier_name}},</p><p>Your PO is attached.</p>
                variables: false
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  subject:
                    type: string
                  body:
                    type: string
                example:
                  subject: 'Your PO #PO-2024-0042'
                  body: <p>Dear ACME Supplies,</p><p>Your PO is attached.</p>
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: settings:write
      operationId: post-api-store-email-templates-preview
  /api/store-email-templates/send:
    post:
      tags:
      - Store Email Templates
      summary: Send Templated Email
      description: 'Send an email to the customer (sales order) or supplier (purchase
        order, vendor credit) using a store email template.


        :::info[Required scope: `settings:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Body fields:

        - order_type (required): SalesOrder | PurchaseOrder | VendorCredit

        - order_id (required): ID of the record to email

        - subject (required): rendered subject line

        - html_body (required): rendered HTML email body

        - cc (optional): array of CC email addresses (null/blank entries are dropped)

        - attachments (optional): array of document keys to attach (resolved per the
        entity''s attachable-documents registry)

        - store_id (optional): ID of the store whose email address is used as the
        sender ("from"). When omitted, falls back to the record''s own store, then
        the tenant''s default (oldest active) store.


        Errors:

        - 422 store_sender_missing: no store with a sender email address is configured.
        The error payload includes errors.store[0].data.configure_route pointing to
        where stores are managed.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                order_type:
                  type: string
                order_id:
                  type: integer
                subject:
                  type: string
                html_body:
                  type: string
                cc:
                  type: array
                  items:
                    type: string
                attachments:
                  type: array
                  items:
                    type: string
                store_id:
                  type: integer
              example:
                order_type: VendorCredit
                order_id: 11
                subject: Message regarding vendor credit VC-00009
                html_body: <html><body><p>Please find the credit attached.</p></body></html>
                cc:
                - buyer@example.com
                attachments:
                - vendor_credit_pdf
                store_id: 1
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                example:
                  status: success
                  message: Email sent successfully
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                example:
                  status: error
                  message: Order type not supported
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            text/plain:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      order_type:
                        type: array
                        items:
                          type: string
                      subject:
                        type: array
                        items:
                          type: string
                example:
                  message: The order type field is required.
                  errors:
                    order_type:
                    - The order type field is required.
                    subject:
                    - The subject field is required.
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      store:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: object
                              properties:
                                configure_route:
                                  type: string
                example:
                  message: This email can't be sent because no store has a sender
                    email address set up. Add an email address to a store, then choose
                    it as the sender and try again.
                  errors:
                    store:
                    - message: This email can't be sent because no store has a sender
                        email address set up. Add an email address to a store, then
                        choose it as the sender and try again.
                      code: store_sender_missing
                      data:
                        configure_route: /settings/general/stores
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: settings:write
      operationId: post-api-store-email-templates-send
  /api/sales-channel-product-templates:
    get:
      tags:
      - Sales Channel Product Templates
      summary: List Sales Channel Product Templates
      description: 'Returns all sales channel product templates. Supports filtering
        by sales channel.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.


        Available filters:

        - filter[sales_channel_id]: Filter to templates for a specific sales channel
        (exact match)'
      parameters: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: array
                items:
                  type: object
                  properties:
                    id:
                      type: integer
                    sales_channel_id:
                      type: integer
                    name:
                      type: string
                    template_data:
                      type: object
                      properties:
                        vendor:
                          type: string
                        product_type:
                          type: string
                        tags:
                          type: array
                          items:
                            type: string
                    created_at:
                      type: string
                    updated_at:
                      type: string
                example:
                - id: 1
                  sales_channel_id: 5
                  name: Standard Shopify Template
                  template_data:
                    vendor: My Brand
                    product_type: Physical
                    tags:
                    - new
                    - featured
                  created_at: '2024-01-10T09:00:00.000000Z'
                  updated_at: '2024-01-10T09:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: get-api-sales-channel-product-templates
    post:
      tags:
      - Sales Channel Product Templates
      summary: Create Sales Channel Product Template
      description: 'Creates a new sales channel product template that can be applied
        when pushing products to a sales channel.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                sales_channel_id:
                  type: integer
                name:
                  type: string
                template_data:
                  type: object
                  properties:
                    vendor:
                      type: string
                    product_type:
                      type: string
              example:
                sales_channel_id: 5
                name: Standard Shopify Template
                template_data:
                  vendor: My Brand
                  product_type: Physical
      parameters: []
      responses:
        '201':
          description: Created
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: integer
                  sales_channel_id:
                    type: integer
                  name:
                    type: string
                  template_data:
                    type: object
                    properties:
                      vendor:
                        type: string
                      product_type:
                        type: string
                  created_at:
                    type: string
                  updated_at:
                    type: string
                example:
                  id: 2
                  sales_channel_id: 5
                  name: Standard Shopify Template
                  template_data:
                    vendor: My Brand
                    product_type: Physical
                  created_at: '2024-01-20T14:00:00.000000Z'
                  updated_at: '2024-01-20T14:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-session-only: true
      operationId: post-api-sales-channel-product-templates
  /api/sales-channel-product-templates/{sales_channel_product_template}:
    get:
      tags:
      - Sales Channel Product Templates
      summary: Get Sales Channel Product Template
      description: 'Returns a single sales channel product template.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: sales_channel_product_template
        in: path
        schema:
          type: integer
        required: true
        description: Template ID
        example: '1'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: integer
                  sales_channel_id:
                    type: integer
                  name:
                    type: string
                  template_data:
                    type: object
                    properties:
                      vendor:
                        type: string
                      product_type:
                        type: string
                      tags:
                        type: array
                        items:
                          type: string
                  created_at:
                    type: string
                  updated_at:
                    type: string
                example:
                  id: 1
                  sales_channel_id: 5
                  name: Standard Shopify Template
                  template_data:
                    vendor: My Brand
                    product_type: Physical
                    tags:
                    - new
                  created_at: '2024-01-10T09:00:00.000000Z'
                  updated_at: '2024-01-10T09:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-session-only: true
      operationId: get-api-sales-channel-product-templates-sales-channel-product-template
    put:
      tags:
      - Sales Channel Product Templates
      summary: Update Sales Channel Product Template
      description: 'Updates a sales channel product template.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                template_data:
                  type: object
                  properties:
                    vendor:
                      type: string
                    product_type:
                      type: string
              example:
                name: Updated Template Name
                template_data:
                  vendor: New Brand
                  product_type: Digital
      parameters:
      - name: sales_channel_product_template
        in: path
        schema:
          type: integer
        required: true
        description: Template ID
        example: '1'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: integer
                  sales_channel_id:
                    type: integer
                  name:
                    type: string
                  template_data:
                    type: object
                    properties:
                      vendor:
                        type: string
                      product_type:
                        type: string
                  created_at:
                    type: string
                  updated_at:
                    type: string
                example:
                  id: 1
                  sales_channel_id: 5
                  name: Updated Template Name
                  template_data:
                    vendor: New Brand
                    product_type: Digital
                  created_at: '2024-01-10T09:00:00.000000Z'
                  updated_at: '2024-01-20T15:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-session-only: true
      operationId: put-api-sales-channel-product-templates-sales-channel-product-template
    delete:
      tags:
      - Sales Channel Product Templates
      summary: Delete Sales Channel Product Template
      description: 'Permanently deletes a sales channel product template.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: sales_channel_product_template
        in: path
        schema:
          type: integer
        required: true
        description: Template ID
        example: '1'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: string
                    nullable: true
                example:
                  data: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-session-only: true
      operationId: delete-api-sales-channel-product-templates-sales-channel-product-template
  /api/v2/sales-channels/{salesChannel}/product-templates/preview:
    post:
      tags:
      - Sales Channel Product Templates
      summary: Preview Sales Channel Product Template Against Product
      description: 'Resolves a set of field mappings against a specific product and
        returns the value each channel field would receive — without saving a template.
        Use it to preview how a template will map a product''s data (fields, attributes,
        static values, and expressions) before you create or update it.


        Body fields:

        - product_id (required, integer) — the product to resolve values for.

        - sales_channel_category_id (required, integer) — the channel category whose
        fields are being mapped. Must belong to the sales channel in the path.

        - field_mappings (optional, array) — the in-progress mappings to resolve.
        Each item: sales_channel_category_field_id (integer), source_type (one of
        product_field, product_attribute, static, expression), source_value (string),
        OR core_field_name (string) to target a core listing field (Title/Description/Price)
        by name. Blank or empty mappings are ignored and fall through to any existing
        channel mapping or default.


        The response `values` object is keyed by channel field name; each entry has
        the resolved value and its provenance (override, template, channel_mapping,
        integration_mapping, channel_default, or blank).


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                product_id:
                  type: integer
                sales_channel_category_id:
                  type: integer
                field_mappings:
                  type: array
                  items:
                    type: object
                    properties:
                      sales_channel_category_field_id:
                        type: integer
                      source_type:
                        type: string
                      source_value:
                        type: string
              example:
                product_id: 42
                sales_channel_category_id: 88
                field_mappings:
                - sales_channel_category_field_id: 501
                  source_type: product_field
                  source_value: brand
                - sales_channel_category_field_id: 503
                  source_type: static
                  source_value: Clear
                - core_field_name: Description
                  source_type: static
                  source_value: Durable, water-resistant, built to last.
      parameters:
      - name: salesChannel
        in: path
        schema:
          type: integer
        required: true
        description: Sales channel ID the category belongs to.
        example: '1'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      product:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          sku:
                            type: string
                      values:
                        type: object
                        properties:
                          Brand:
                            type: object
                            properties:
                              value:
                                type: string
                              provenance:
                                type: string
                          Color:
                            type: object
                            properties:
                              value:
                                type: string
                              provenance:
                                type: string
                          Title:
                            type: object
                            properties:
                              value:
                                type: string
                              provenance:
                                type: string
                          Material:
                            type: object
                            properties:
                              value:
                                type: string
                                nullable: true
                              provenance:
                                type: string
                example:
                  data:
                    product:
                      id: 42
                      name: Gel Strengthener Base Coat
                      sku: LL-GSB-15
                    values:
                      Brand:
                        value: Lumen Lab
                        provenance: override
                      Color:
                        value: Clear
                        provenance: override
                      Title:
                        value: Lumen Lab - Gel Strengthener Base Coat
                        provenance: override
                      Material:
                        value: null
                        provenance: blank
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-v2-sales-channels-saleschannel-product-templates-preview
  /api/v2/sales-channel-listing-profiles:
    get:
      tags:
      - Sales Channel Listing Profiles
      summary: List Listing Profiles
      description: 'Cross-channel paginated list of listing profiles, with the owning
        sales channel and "used by" template/draft counts. Requires the listing-publishing
        feature to be enabled (403 otherwise).


        Authentication: Requires Bearer token.


        Available filters:

        - filter[sales_channel_id]: exact match on channel

        - filter[is_default]: exact match on the default flag (1/0)

        - filter[name]: partial match on name

        - filter[search]: search by name or exact id

        - filter[created_at] / filter[updated_at]: date filters


        Allowed sorts: id, name, sales_channel_id, is_default, created_at, updated_at
        (default: name).


        Pagination: page (default 1), per_page (default 20, max 100).'
      parameters: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        sales_channel_id:
                          type: integer
                        name:
                          type: string
                        is_default:
                          type: boolean
                        settings:
                          type: object
                          properties:
                            condition:
                              type: string
                            handling_time:
                              type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                        templates_count:
                          type: integer
                        drafts_count:
                          type: integer
                        sales_channel:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            integration_id:
                              type: integer
                            integration_name:
                              type: string
                            integration_image_url:
                              type: string
                            integration_instance_id:
                              type: integer
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - id: 12
                    sales_channel_id: 5
                    name: Standard
                    is_default: true
                    settings:
                      condition: NEW
                      handling_time: '1'
                    created_at: '2026-07-18T09:00:00+00:00'
                    updated_at: '2026-07-20T14:30:00+00:00'
                    templates_count: 2
                    drafts_count: 5
                    sales_channel:
                      id: 5
                      name: eBay US
                      integration_id: 3
                      integration_name: Ebay
                      integration_image_url: https://cdn.sku.io/integrations/ebay.png
                      integration_instance_id: 9
                  current_page: 1
                  last_page: 1
                  per_page: 20
                  total: 1
                  from: 1
                  to: 1
        '403':
          description: Forbidden
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: This feature is not enabled.
        '429': *id001
        '401': *id002
      operationId: get-api-v2-sales-channel-listing-profiles
  /api/v2/sales-channel-listing-profiles/bulk-destroy:
    post:
      tags:
      - Sales Channel Listing Profiles
      summary: Bulk Delete Listing Profiles
      description: 'Bulk delete listing profiles. Provide either an explicit `ids`
        array, or set `apply_to_all` to true with a `filters` object to delete every
        profile matching the current filter set. Requires the listing-publishing feature
        to be enabled (403 otherwise).


        Authentication: Requires Bearer token.


        Request body (one of):

        - ids: array of profile IDs to delete (required unless apply_to_all is true)

        - apply_to_all: when true, delete all profiles matching filters

        - filters: filter object (e.g. { "sales_channel_id": 5 }) applied when apply_to_all
        is true'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 12
                - 13
                - 14
      parameters: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      deleted:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    deleted: 3
                  message: Deleted 3 profiles.
        '422':
          description: Unprocessable Content
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      ids:
                        type: array
                        items:
                          type: string
                example:
                  message: The ids field is required when apply to all is not present.
                  errors:
                    ids:
                    - The ids field is required when apply to all is not present.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-v2-sales-channel-listing-profiles-bulk-destroy
  /api/sub-sales-channels:
    get:
      tags:
      - Sub Sales Channels
      summary: List Sub Sales Channels
      description: 'Returns a paginated list of sub sales channels. Each row carries
        its classified `source_type` (online, point_of_sale, marketplace, draft, other),
        a human `source_type_label`, an `is_point_of_sale` convenience flag, and `source_type_locked`
        (true once an operator has manually reclassified it). Authenticate with a
        Personal Access Token.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Allowed sorts: id, name, created_at, updated_at.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        sales_channel_id:
                          type: integer
                        name:
                          type: string
                        external_identifier:
                          type: string
                        source_type:
                          type: string
                        source_type_label:
                          type: string
                        source_type_locked:
                          type: boolean
                        is_point_of_sale:
                          type: boolean
                        sales_nominal_code_id:
                          type: string
                          nullable: true
                        cogs_nominal_code_id:
                          type: string
                          nullable: true
                        shipping_revenue_nominal_code_id:
                          type: string
                          nullable: true
                        shipping_refund_nominal_code_id:
                          type: string
                          nullable: true
                        sales_returns_allowances_nominal_code_id:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                  path:
                    type: string
                example:
                  data:
                  - id: 12
                    sales_channel_id: 3
                    name: POS
                    external_identifier: pos
                    source_type: point_of_sale
                    source_type_label: Point of Sale
                    source_type_locked: false
                    is_point_of_sale: true
                    sales_nominal_code_id: null
                    cogs_nominal_code_id: null
                    shipping_revenue_nominal_code_id: null
                    shipping_refund_nominal_code_id: null
                    sales_returns_allowances_nominal_code_id: null
                    created_at: '2026-06-17T09:15:00.000000Z'
                    updated_at: '2026-06-17T09:15:00.000000Z'
                  current_page: 1
                  last_page: 1
                  per_page: 10
                  total: 1
                  from: 1
                  to: 1
                  path: '{{protocol}}{{domain}}/api/sub-sales-channels'
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: get-api-sub-sales-channels
    post:
      tags:
      - Sub Sales Channels
      summary: Create Sub Sales Channel
      description: 'Creates a new sub sales channel.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.


        Power user access required.


        Fields:

        - sales_channel_id (required): ID of the parent sales channel

        - name (required): Name of the sub sales channel (max 255 chars)

        - sales_nominal_code_id (optional): Nominal code ID for sales revenue

        - cogs_nominal_code_id (optional): Nominal code ID for cost of goods sold'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                sales_channel_id:
                  type: integer
                name:
                  type: string
                sales_nominal_code_id:
                  type: integer
                cogs_nominal_code_id:
                  type: integer
                shipping_revenue_nominal_code_id:
                  type: integer
                shipping_refund_nominal_code_id:
                  type: integer
                sales_returns_allowances_nominal_code_id:
                  type: integer
              example:
                sales_channel_id: 5
                name: Amazon US
                sales_nominal_code_id: 10
                cogs_nominal_code_id: 11
                shipping_revenue_nominal_code_id: 12
                shipping_refund_nominal_code_id: 13
                sales_returns_allowances_nominal_code_id: 14
      parameters: []
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                example:
                  message: Sub Sales Channel created successfully.
                  data:
                    id: 2
                    name: Amazon US
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      sales_channel_id:
                        type: array
                        items:
                          type: string
                      name:
                        type: array
                        items:
                          type: string
                example:
                  message: The given data was invalid.
                  errors:
                    sales_channel_id:
                    - The sales channel id field is required.
                    name:
                    - The name field is required.
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: post-api-sub-sales-channels
  /api/sub-sales-channels/{subSalesChannel}/source-type:
    patch:
      tags:
      - Sub Sales Channels
      summary: Reclassify Source Type
      description: 'Manually reclassify a sub sales channel''s source type (e.g. mark
        an in-store source as Point of Sale). Sets `source_type_locked = true` so
        future integration syncs never revert the operator''s choice.


        Request body:

        - `source_type` (required) — one of: online, point_of_sale, marketplace, draft,
        other.


        Returns the updated sub sales channel.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                source_type:
                  type: string
              example:
                source_type: point_of_sale
      parameters:
      - name: subSalesChannel
        in: path
        schema:
          type: integer
        required: true
        description: Sub sales channel ID
        example: '12'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      sales_channel_id:
                        type: integer
                      name:
                        type: string
                      external_identifier:
                        type: string
                      source_type:
                        type: string
                      source_type_label:
                        type: string
                      source_type_locked:
                        type: boolean
                      is_point_of_sale:
                        type: boolean
                      sales_nominal_code_id:
                        type: string
                        nullable: true
                      cogs_nominal_code_id:
                        type: string
                        nullable: true
                      shipping_revenue_nominal_code_id:
                        type: string
                        nullable: true
                      shipping_refund_nominal_code_id:
                        type: string
                        nullable: true
                      sales_returns_allowances_nominal_code_id:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 12
                    sales_channel_id: 3
                    name: POS
                    external_identifier: pos
                    source_type: point_of_sale
                    source_type_label: Point of Sale
                    source_type_locked: true
                    is_point_of_sale: true
                    sales_nominal_code_id: null
                    cogs_nominal_code_id: null
                    shipping_revenue_nominal_code_id: null
                    shipping_refund_nominal_code_id: null
                    sales_returns_allowances_nominal_code_id: null
                    created_at: '2026-06-17T09:15:00.000000Z'
                    updated_at: '2026-06-17T09:15:00.000000Z'
                  message: Sub Sales Channel POS updated successfully.
        '422':
          description: Unprocessable Content
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      source_type:
                        type: array
                        items:
                          type: string
                example:
                  message: The selected source type is invalid.
                  errors:
                    source_type:
                    - The selected source type is invalid.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: patch-api-sub-sales-channels-subsaleschannel-source-type
  /api/customers:
    post:
      tags:
      - Customers
      summary: Create Customer
      description: 'Create a new customer. Automatically creates a default shipping
        address from the root address fields. Optionally provide a separate billing
        address.


        :::info[Required scope: `customers:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Optional fields:

        - tags: Customer tags (array of tag names, max 64 chars each). Omit to leave
        existing tags unchanged; send an array to replace them. Unknown names are
        created automatically.


        Validation notes:

        - Email must be unique across all customer addresses

        - If a customer with the same name/zip/address1 already exists, returns a
        422 with CODE_CUSTOMER_EXISTS'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                company:
                  type: string
                email:
                  type: string
                phone:
                  type: string
                fax:
                  type: string
                  nullable: true
                address1:
                  type: string
                address2:
                  type: string
                address3:
                  type: string
                  nullable: true
                city:
                  type: string
                province:
                  type: string
                province_code:
                  type: string
                zip:
                  type: string
                country:
                  type: string
                country_code:
                  type: string
                integration_instance_id:
                  type: string
                  nullable: true
                default_sales_rep_id:
                  type: string
                  nullable: true
                default_billing_address:
                  type: object
                  properties:
                    name:
                      type: string
                    company:
                      type: string
                    email:
                      type: string
                    phone:
                      type: string
                    address1:
                      type: string
                    city:
                      type: string
                    province:
                      type: string
                    province_code:
                      type: string
                    zip:
                      type: string
                    country:
                      type: string
                    country_code:
                      type: string
                billing_email:
                  type: string
                payment_terms_days:
                  type: integer
                tags:
                  type: array
                  items:
                    type: string
              example:
                name: Jane Smith
                company: Smith Industries
                email: jane.smith@smithindustries.com
                phone: +1-555-0200
                fax: null
                address1: 456 Commerce Ave
                address2: Suite 100
                address3: null
                city: Los Angeles
                province: California
                province_code: CA
                zip: '90001'
                country: United States
                country_code: US
                integration_instance_id: null
                default_sales_rep_id: null
                default_billing_address:
                  name: Jane Smith
                  company: Smith Industries
                  email: billing@smithindustries.com
                  phone: +1-555-0201
                  address1: 789 Billing Blvd
                  city: Los Angeles
                  province: California
                  province_code: CA
                  zip: '90002'
                  country: United States
                  country_code: US
                billing_email: ap@acme-wholesale.com
                payment_terms_days: 30
                tags:
                - VIP
                - Wholesale
      parameters: []
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      email:
                        type: string
                      company:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 42
                    name: Jane Smith
                    email: jane.smith@smithindustries.com
                    company: Smith Industries
                  message: customer created successfully
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      address:
                        type: array
                        items:
                          type: object
                          properties:
                            code:
                              type: string
                            message:
                              type: string
                            data:
                              type: object
                              properties:
                                existing_customer_id:
                                  type: integer
                example:
                  message: Customer already exists.
                  errors:
                    address:
                    - code: CUSTOMER_EXISTS
                      message: Customer already exists.
                      data:
                        existing_customer_id: 15
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: customers:write
      operationId: post-api-customers
    delete:
      tags:
      - Customers
      summary: Bulk Delete Customers
      description: 'Bulk delete customers by IDs or by applying to all filtered results.


        :::info[Required scope: `customers:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token. Requires IsPowerUserAccess middleware.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 3 customers deleted successfully.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: customers:write
      operationId: delete-api-customers
  /api/customers/{customer}:
    get:
      tags:
      - Customers
      summary: Get Customer
      description: 'Get a single customer with all related data including addresses,
        billing/shipping addresses, default settings, and lifetime value.


        :::info[Required scope: `customers:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: customer
        in: path
        schema:
          type: integer
        required: true
        description: Customer ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      email:
                        type: string
                      lifetime_value:
                        type: number
                      tags:
                        type: array
                        items:
                          type: string
                example:
                  data:
                    id: 1
                    name: John Doe
                    email: john.doe@example.com
                    lifetime_value: 12500.0
                    tags:
                    - VIP
                    - Wholesale
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: customers:read
      operationId: get-api-customers-customer
    put:
      tags:
      - Customers
      summary: Update Customer
      description: 'Update an existing customer. All fields are optional. Default
        settings (pricing tier, store, shipping methods, warehouse) can only be set
        on update.


        :::info[Required scope: `customers:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Optional fields:

        - tags: Customer tags (array of tag names, max 64 chars each). Omit to leave
        existing tags unchanged; send an array to replace them. Unknown names are
        created automatically.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                company:
                  type: string
                email:
                  type: string
                phone:
                  type: string
                product_pricing_tier_id:
                  type: integer
                store_id:
                  type: integer
                shipping_method_domestic_id:
                  type: integer
                shipping_method_international_id:
                  type: integer
                warehouse_id:
                  type: integer
                billing_email:
                  type: string
                payment_terms_days:
                  type: integer
                tags:
                  type: array
                  items:
                    type: string
              example:
                name: John Doe Updated
                company: Acme Corp International
                email: john.doe@acmecorp.com
                phone: +1-555-0101
                product_pricing_tier_id: 2
                store_id: 1
                shipping_method_domestic_id: 3
                shipping_method_international_id: 5
                warehouse_id: 1
                billing_email: ap@acme-wholesale.com
                payment_terms_days: 30
                tags:
                - VIP
                - Wholesale
      parameters:
      - name: customer
        in: path
        schema:
          type: integer
        required: true
        description: Customer ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 1
                    name: John Doe Updated
                  message: customer John Doe Updated updated successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: customers:write
      operationId: put-api-customers-customer
    delete:
      tags:
      - Customers
      summary: Delete Customer
      description: 'Delete a customer. Returns 400 if the customer is linked to sales
        orders or other records.


        :::info[Required scope: `customers:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token. Requires IsPowerUserAccess middleware.'
      parameters:
      - name: customer
        in: path
        schema:
          type: integer
        required: true
        description: Customer ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: customer deleted successfully
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      sales_orders:
                        type: array
                        items:
                          type: object
                          properties:
                            code:
                              type: string
                            message:
                              type: string
                example:
                  message: Failed to delete customer John Doe.
                  errors:
                    sales_orders:
                    - code: RESOURCE_LINKED
                      message: Customer is linked to sales orders.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: customers:write
      operationId: delete-api-customers-customer
  /api/customers/{customer}/addresses:
    get:
      tags:
      - Customers
      summary: Get Customer Addresses
      description: 'Retrieve all addresses associated with a customer including default
        shipping, billing, and other addresses.


        :::info[Required scope: `customers:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token. Requires IsPowerUserAccess middleware.'
      parameters:
      - name: customer
        in: path
        schema:
          type: integer
        required: true
        description: Customer ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      addresses:
                        type: array
                example:
                  data:
                    id: 1
                    name: John Doe
                    addresses: []
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: customers:read
      operationId: get-api-customers-customer-addresses
    post:
      tags:
      - Customers
      summary: Add Customer Address
      description: 'Add a new address to a customer. Address deduplication is applied.


        :::info[Required scope: `customers:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token. Requires IsPowerUserAccess middleware.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                label:
                  type: string
                name:
                  type: string
                company:
                  type: string
                email:
                  type: string
                phone:
                  type: string
                address1:
                  type: string
                city:
                  type: string
                province:
                  type: string
                province_code:
                  type: string
                zip:
                  type: string
                country:
                  type: string
                country_code:
                  type: string
                is_default_shipping:
                  type: boolean
                is_default_billing:
                  type: boolean
              example:
                label: Warehouse Address
                name: John Doe
                company: Acme Corp
                email: warehouse@acmecorp.com
                phone: +1-555-0102
                address1: 500 Industrial Way
                city: Glendale
                province: California
                province_code: CA
                zip: '91201'
                country: United States
                country_code: US
                is_default_shipping: false
                is_default_billing: false
      parameters:
      - name: customer
        in: path
        schema:
          type: integer
        required: true
        description: Customer ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      addresses:
                        type: array
                example:
                  data:
                    id: 1
                    name: John Doe
                    addresses: []
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: customers:write
      operationId: post-api-customers-customer-addresses
  /api/customers/{customer}/set-default-shipping-address/{address_id}:
    put:
      tags:
      - Customers
      summary: Set Default Shipping Address
      description: 'Set a specific address as the customer''s default shipping address.


        :::info[Required scope: `customers:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: customer
        in: path
        schema:
          type: integer
        required: true
        description: Customer ID
        example: '1'
      - name: address_id
        in: path
        schema:
          type: integer
        required: true
        description: Address ID
        example: '2'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Default shipping address set.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: customers:write
      operationId: put-api-customers-customer-set-default-shipping-address-address-id
  /api/customers/{customer}/set-default-billing-address/{address_id}:
    put:
      tags:
      - Customers
      summary: Set Default Billing Address
      description: 'Set a specific address as the customer''s default billing address.


        :::info[Required scope: `customers:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: customer
        in: path
        schema:
          type: integer
        required: true
        description: Customer ID
        example: '1'
      - name: address_id
        in: path
        schema:
          type: integer
        required: true
        description: Address ID
        example: '2'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Default billing address set.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: customers:write
      operationId: put-api-customers-customer-set-default-billing-address-address-id
  /api/customers/{customer}/addresses/{address}:
    delete:
      tags:
      - Customers
      summary: Delete Customer Address
      description: 'Remove an address from a customer''s address book. If the removed
        address was the customer''s default shipping or billing address, the most
        recently added remaining address is automatically promoted as the new default
        (or the default is cleared when no other address exists). The underlying address
        record is permanently deleted only when no other records (other customers,
        sales orders, etc.) still reference it; otherwise only the customer''s link
        to it is removed.


        :::info[Required scope: `customers:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Returns the customer''s refreshed address book.


        Authentication: Requires Bearer token with the customers read/write scope.'
      parameters:
      - name: customer
        in: path
        schema:
          type: integer
        required: true
        description: Customer ID
        example: '1'
      - name: address
        in: path
        schema:
          type: integer
        required: true
        description: Address ID to remove from the customer
        example: '10'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      email:
                        type: string
                      zip:
                        type: string
                      address1:
                        type: string
                      addresses:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            label:
                              type: string
                            name:
                              type: string
                            company:
                              type: string
                            email:
                              type: string
                            phone:
                              type: string
                            address1:
                              type: string
                            address2:
                              type: string
                              nullable: true
                            city:
                              type: string
                            province:
                              type: string
                            province_code:
                              type: string
                            zip:
                              type: string
                            country:
                              type: string
                            country_code:
                              type: string
                            is_default_shipping:
                              type: boolean
                            is_default_billing:
                              type: boolean
                  message:
                    type: string
                  status:
                    type: string
                example:
                  data:
                    id: 1
                    name: John Doe
                    email: john.doe@acmecorp.com
                    zip: '91201'
                    address1: 500 Industrial Way
                    addresses:
                    - id: 12
                      label: Head Office
                      name: John Doe
                      company: Acme Corp
                      email: john.doe@acmecorp.com
                      phone: +1-555-0102
                      address1: 500 Industrial Way
                      address2: null
                      city: Glendale
                      province: California
                      province_code: CA
                      zip: '91201'
                      country: United States
                      country_code: US
                      is_default_shipping: true
                      is_default_billing: true
                  message: The address Warehouse Address deleted successfully
                  status: success
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Address is not linked to this customer.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: customers:write
      operationId: delete-api-customers-customer-addresses-address
  /api/customers/archive:
    put:
      tags:
      - Customers
      summary: Bulk Archive Customers
      description: 'Bulk archive customers by IDs or by applying to all filtered results.


        :::info[Required scope: `customers:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
                apply_to_all:
                  type: boolean
                filters:
                  type: object
                  properties: {}
              example:
                ids:
                - 4
                - 5
                - 6
                apply_to_all: false
                filters: {}
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 3 customers archived successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: customers:write
      operationId: put-api-customers-archive
  /api/customers/unarchive:
    put:
      tags:
      - Customers
      summary: Bulk Unarchive Customers
      description: 'Bulk unarchive customers by IDs or by applying to all filtered
        results.


        :::info[Required scope: `customers:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
                apply_to_all:
                  type: boolean
                filters:
                  type: object
                  properties: {}
              example:
                ids:
                - 4
                - 5
                - 6
                apply_to_all: false
                filters: {}
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 3 customers unarchived successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: customers:write
      operationId: put-api-customers-unarchive
  /api/customers/deletable:
    post:
      tags:
      - Customers
      summary: Check Deletable Customers
      description: 'Check which customers can be deleted. Returns deletability status
        for each customer.


        :::info[Required scope: `customers:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token. Requires IsPowerUserAccess middleware.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
                scope:
                  type: string
              example:
                ids:
                - 1
                - 2
                - 3
                scope: ids
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        deletable:
                          type: boolean
                        reason:
                          type: string
                example:
                  data:
                  - id: 1
                    name: John Doe
                    deletable: false
                    reason: Linked to sales orders
                  - id: 2
                    name: Jane Smith
                    deletable: true
                    reason: null
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: customers:write
      operationId: post-api-customers-deletable
  /api/customers/{customer}/archive:
    put:
      tags:
      - Customers
      summary: Archive Customer
      description: 'Archive a single customer.


        :::info[Required scope: `customers:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: customer
        in: path
        schema:
          type: integer
        required: true
        description: Customer ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: customer John Doe archived successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: customers:write
      operationId: put-api-customers-customer-archive
  /api/customers/{customer}/unarchived:
    put:
      tags:
      - Customers
      summary: Unarchive Customer
      description: 'Unarchive a previously archived customer.


        :::info[Required scope: `customers:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: customer
        in: path
        schema:
          type: integer
        required: true
        description: Customer ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: customer John Doe unarchived successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: customers:write
      operationId: put-api-customers-customer-unarchived
  /api/customers/import/preview:
    post:
      tags:
      - Customers
      summary: Preview Customers Import
      description: 'Preview a customer import from a CSV file before committing.


        :::info[Required scope: `customers:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token. Requires IsPowerUserAccess middleware.'
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                file:
                  type: string
                  description: CSV file containing customers to import
                  format: binary
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      total:
                        type: integer
                      valid:
                        type: integer
                      errors:
                        type: integer
                example:
                  data:
                    total: 50
                    valid: 48
                    errors: 2
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: customers:write
      operationId: post-api-customers-import-preview
  /api/customers/import:
    post:
      tags:
      - Customers
      summary: Import Customers
      description: 'Import customers from a CSV file.


        :::info[Required scope: `customers:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token. Requires IsPowerUserAccess middleware.'
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                file:
                  type: string
                  description: CSV file containing customers to import
                  format: binary
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      imported:
                        type: integer
                      skipped:
                        type: integer
                      errors:
                        type: array
                  message:
                    type: string
                example:
                  data:
                    imported: 48
                    skipped: 2
                    errors: []
                  message: Import completed successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: customers:write
      operationId: post-api-customers-import
  /api/customers/find-match:
    get:
      tags:
      - Customers
      summary: Find Customer Match
      description: 'Find customer matches based on name, ZIP code, and address. Uses
        approximate matching (90% match on address1).


        :::info[Required scope: `customers:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token. Requires IsPowerUserAccess middleware.'
      parameters:
      - name: name
        in: query
        schema:
          type: string
        description: Customer name (required)
        example: John Doe
      - name: zip
        in: query
        schema:
          type: integer
        description: ZIP code (required)
        example: '90210'
      - name: address1
        in: query
        schema:
          type: string
        description: Address line 1 (required) — uses 90% fuzzy match
        example: 123 Main St
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                  status:
                    type: string
                example:
                  data:
                  - id: 1
                    name: John Doe
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: customers:read
      operationId: get-api-customers-find-match
  /api/customers/{customer}/open-sales-credits:
    get:
      tags:
      - Customers
      summary: Get Open Sales Credits
      description: 'Get all open (un-fully-allocated) sales credits for a customer.


        :::info[Required scope: `customers:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: customer
        in: path
        schema:
          type: integer
        required: true
        description: Customer ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        sales_credit_number:
                          type: string
                        total_credit:
                          type: number
                        status:
                          type: string
                example:
                  data:
                  - id: 5
                    sales_credit_number: SC-0005
                    total_credit: 250.0
                    status: open
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: customers:read
      operationId: get-api-customers-customer-open-sales-credits
  /api/customers/{customer}/unpaid-orders:
    get:
      tags:
      - Customers
      summary: Get Unpaid Orders
      description: 'Get all unpaid sales orders for a customer.


        :::info[Required scope: `customers:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: customer
        in: path
        schema:
          type: integer
        required: true
        description: Customer ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        sales_order_number:
                          type: string
                        total:
                          type: number
                        total_paid:
                          type: number
                example:
                  data:
                  - id: 10
                    sales_order_number: SO-0010
                    total: 500.0
                    total_paid: 0.0
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: customers:read
      operationId: get-api-customers-customer-unpaid-orders
  /api/customers/{customer}/sales-credits/{salesCredit}/allocate:
    post:
      tags:
      - Customers
      summary: Allocate Sales Credit to Orders
      description: 'Allocate an open sales credit to one or more sales orders.


        :::info[Required scope: `customers:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                sales_orders:
                  type: array
                  items:
                    type: object
                    properties:
                      id:
                        type: integer
                      amount:
                        type: integer
              example:
                sales_orders:
                - id: 10
                  amount: 250
                - id: 11
                  amount: 100
      parameters:
      - name: customer
        in: path
        schema:
          type: integer
        required: true
        description: Customer ID
        example: '1'
      - name: salesCredit
        in: path
        schema:
          type: integer
        required: true
        description: Sales Credit ID
        example: '5'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Sales credit allocated successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: customers:write
      operationId: post-api-customers-customer-sales-credits-salescredit-allocate
  /api/customers/{customer}/sales-credits/{salesCredit}/allocations/{allocation}:
    delete:
      tags:
      - Customers
      summary: Unallocate Sales Credit from Order
      description: 'Reverse a single sales credit allocation. Deletes the allocation
        row, reverses the corresponding Credit-type Payment recorded against the sales
        order, and recalculates the credit''s payment_status (paid → partially_paid
        or open).


        :::info[Required scope: `customers:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        If the allocation was previously synced to QuickBooks Online, a background
        job is dispatched after the local DB transaction commits to delete the paired
        QBO Payment.


        Scoping behavior:

        - Returns 404 if the credit does not belong to the customer in the URL

        - Returns 404 if the allocation does not belong to the credit in the URL


        Validation:

        - Returns 422 if the sales credit is archived (unarchive before reversing
        allocations)

        - Returns 422 if the allocation has already been synced to Xero (Xero CreditNote
        Allocations are functionally immutable once accepted — unallocate in Xero
        first, then refresh)


        Authentication: Requires Bearer token.'
      parameters:
      - name: customer
        in: path
        schema:
          type: integer
        required: true
        description: Customer ID
        example: '1'
      - name: salesCredit
        in: path
        schema:
          type: integer
        required: true
        description: Sales Credit ID
        example: '5'
      - name: allocation
        in: path
        schema:
          type: integer
        required: true
        description: Sales Credit Allocation ID
        example: '12'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: sales credit allocation 12 was deleted.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 422 Archived Credit
                  value:
                    message: This credit is archived. Unarchive it before reversing
                      allocations.
                    errors:
                      allocation:
                      - This credit is archived. Unarchive it before reversing allocations.
                example-1:
                  summary: 422 Locked by Xero
                  value:
                    message: This credit application has already been synced to Xero.
                      Xero credit-note allocations cannot be undone via SKU.io — please
                      unallocate the credit inside Xero first, then refresh this page.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: customers:write
      operationId: delete-api-customers-customer-sales-credits-salescredit-allocations-allocation
  /api/customers/starshipit/submit-orders:
    get:
      tags:
      - Customers
      summary: Submit Orders to Starshipit
      description: '**This GET dispatches a background job** (queues a bulk submit
        of every open Starshipit fulfillment).


        :::info[Required scope: `customers:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Submit pending orders to Starshipit shipping integration.


        Authentication: Requires Bearer token. Requires IsPowerUserAccess middleware.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      submitted:
                        type: integer
                      failed:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    submitted: 5
                    failed: 0
                  message: Orders submitted to Starshipit.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: customers:read
      operationId: get-api-customers-starshipit-submit-orders
  /api/customers/starshipit/update-order/{sales_order_fulfillment}:
    put:
      tags:
      - Customers
      summary: Update Starshipit Order from Fulfillment
      description: 'Update an existing order in Starshipit from a sales order fulfillment.


        :::info[Required scope: `customers:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token. Requires IsPowerUserAccess middleware.'
      requestBody:
        content: {}
      parameters:
      - name: sales_order_fulfillment
        in: path
        schema:
          type: integer
        required: true
        description: Sales Order Fulfillment ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Starshipit order updated.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: customers:write
      operationId: put-api-customers-starshipit-update-order-sales-order-fulfillment
  /api/customers/starshipit/view-order/{sales_order_fulfillment}:
    get:
      tags:
      - Customers
      summary: View Starshipit Order
      description: 'View the Starshipit order for a sales order fulfillment.


        :::info[Required scope: `customers:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token. Requires IsPowerUserAccess middleware.'
      parameters:
      - name: sales_order_fulfillment
        in: path
        schema:
          type: integer
        required: true
        description: Sales Order Fulfillment ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      order_number:
                        type: string
                      status:
                        type: string
                      carrier:
                        type: string
                example:
                  data:
                    order_number: SF-1001
                    status: pending
                    carrier: Australia Post
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: customers:read
      operationId: get-api-customers-starshipit-view-order-sales-order-fulfillment
  /api/customers/{customer_id}/sku-mappings:
    get:
      tags:
      - Customers
      summary: List SKU Mappings
      description: 'Return a paginated list of SKU mappings for the specified customer.
        Each mapping links a customer-facing SKU code to an internal product.


        :::info[Required scope: `customers:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: customer_id
        in: path
        schema:
          type: string
        required: true
        description: The customer ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: customers:read
      operationId: get-api-customers-customer-id-sku-mappings
    post:
      tags:
      - Customers
      summary: Create / Upsert SKU Mapping
      description: 'Create a new SKU mapping or update an existing one (upsert) for
        the given customer. If a mapping for customer_sku already exists, it is updated
        with the new product_id.


        :::info[Required scope: `customers:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                customer_sku:
                  type: string
                product_id:
                  type: integer
              example:
                customer_sku: CUST-SKU-001
                product_id: 1
      parameters:
      - name: customer_id
        in: path
        schema:
          type: string
        required: true
        description: The customer ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: customers:write
      operationId: post-api-customers-customer-id-sku-mappings
  /api/customers/{customer_id}/sku-mappings/{mapping_id}:
    delete:
      tags:
      - Customers
      summary: Delete SKU Mapping
      description: 'Delete a specific SKU mapping by ID for the given customer.


        :::info[Required scope: `customers:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: customer_id
        in: path
        schema:
          type: string
        required: true
        description: The customer ID.
      - name: mapping_id
        in: path
        schema:
          type: string
        required: true
        description: The mapping ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: customers:write
      operationId: delete-api-customers-customer-id-sku-mappings-mapping-id
  /api/customers/{customer_id}/sku-mappings/import:
    post:
      tags:
      - Customers
      summary: Import SKU Mappings from CSV
      description: 'Bulk-import SKU mappings for a customer from a CSV file. The CSV
        must have a header row with columns customer_sku and product_id. Existing
        mappings for the same customer_sku are updated (upsert behaviour).


        :::info[Required scope: `customers:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                file:
                  type: string
                  description: 'CSV file with columns: customer_sku, product_id (required)'
                  format: binary
      parameters:
      - name: customer_id
        in: path
        schema:
          type: string
        required: true
        description: The customer ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: customers:write
      operationId: post-api-customers-customer-id-sku-mappings-import
  /api/customers/{customer_id}/sku-mappings/export:
    get:
      tags:
      - Customers
      summary: Export SKU Mappings as CSV
      description: 'Export all SKU mappings for a customer as a CSV file download.
        The response is a CSV with columns customer_sku and product_id. Use this as
        a template for the import endpoint.


        :::info[Required scope: `customers:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: customer_id
        in: path
        schema:
          type: string
        required: true
        description: The customer ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: customers:read
      operationId: get-api-customers-customer-id-sku-mappings-export
  /api/v2/customers/{customer}/contacts:
    get:
      tags:
      - Customers
      summary: List Customer Contacts
      description: 'List all contacts attached to a customer, paginated. Supports
        search (title/notes), role/primary/has-email filters, advanced per-column
        filters, and sorting.


        Authentication: Requires Bearer token.'
      parameters:
      - name: customer
        in: path
        schema:
          type: integer
        required: true
        description: Customer ID
        example: '12'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        email:
                          type: string
                        phone:
                          type: string
                        role:
                          type: string
                        role_label:
                          type: string
                        title:
                          type: string
                        is_primary:
                          type: boolean
                        is_messaging:
                          type: boolean
                        notes:
                          type: string
                        link_type:
                          type: string
                        link_id:
                          type: integer
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - id: 42
                    name: Jane Buyer
                    email: jane.buyer@example.com
                    phone: +1 415-555-0100
                    role: accounts_payable
                    role_label: Accounts Payable
                    title: AP Specialist
                    is_primary: true
                    is_messaging: false
                    notes: Prefers email over phone.
                    link_type: customer
                    link_id: 12
                    created_at: '2026-07-13T14:22:05+00:00'
                    updated_at: '2026-07-13T14:22:05+00:00'
                  - id: 43
                    name: Sam Sales
                    email: sam.sales@example.com
                    phone: +1 415-555-0100
                    role: sales_rep
                    role_label: Sales Rep
                    title: Account Executive
                    is_primary: false
                    is_messaging: false
                    notes: Prefers email over phone.
                    link_type: customer
                    link_id: 12
                    created_at: '2026-07-13T14:22:05+00:00'
                    updated_at: '2026-07-13T14:22:05+00:00'
                  current_page: 1
                  last_page: 1
                  per_page: 10
                  total: 2
                  from: 1
                  to: 2
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-v2-customers-customer-contacts
    post:
      tags:
      - Customers
      summary: Create Customer Contact
      description: 'Add a new contact to a customer. Fields: name (required), email,
        phone, role (default general), title, is_primary, notes (max 500). The first
        contact added to a customer automatically becomes primary; setting is_primary
        demotes the previous primary.


        Role options: general, sales_rep, account_manager, customer_service, accounts_payable,
        accounts_receivable, purchasing, shipping_receiving, warehouse_manager, operations,
        billing, owner, other.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                email:
                  type: string
                phone:
                  type: string
                role:
                  type: string
                title:
                  type: string
                is_primary:
                  type: boolean
                is_messaging:
                  type: boolean
                notes:
                  type: string
              example:
                name: Jane Buyer
                email: jane.buyer@example.com
                phone: +1 415-555-0100
                role: accounts_payable
                title: AP Specialist
                is_primary: true
                is_messaging: false
                notes: Prefers email over phone.
      parameters:
      - name: customer
        in: path
        schema:
          type: integer
        required: true
        description: Customer ID
        example: '12'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      email:
                        type: string
                      phone:
                        type: string
                      role:
                        type: string
                      role_label:
                        type: string
                      title:
                        type: string
                      is_primary:
                        type: boolean
                      is_messaging:
                        type: boolean
                      notes:
                        type: string
                      link_type:
                        type: string
                      link_id:
                        type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 42
                    name: Jane Buyer
                    email: jane.buyer@example.com
                    phone: +1 415-555-0100
                    role: accounts_payable
                    role_label: Accounts Payable
                    title: AP Specialist
                    is_primary: true
                    is_messaging: false
                    notes: Prefers email over phone.
                    link_type: customer
                    link_id: 12
                    created_at: '2026-07-13T14:22:05+00:00'
                    updated_at: '2026-07-13T14:22:05+00:00'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      name:
                        type: array
                        items:
                          type: string
                example:
                  message: The name field is required.
                  errors:
                    name:
                    - A contact name (or inbox label) is required.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-v2-customers-customer-contacts
  /api/v2/customers/{customer}/contacts/export:
    get:
      tags:
      - Customers
      summary: Export Contacts
      description: 'Download all contacts belonging to the customer as a CSV or XLSX
        file. Columns: Contact ID, Name, Email, Phone, Role, Title, Primary, Notes,
        Created At, Updated At. The file mirrors the contacts bulk-import template,
        so an exported file can be edited and re-imported (rows with a Contact ID
        or a matching email update the existing contact; others are created).


        Optional comma-separated column keys (`name,role,title,email,phone,notes,created_at`)
        to narrow the exported fields; `Contact ID` is always included so the file
        can round-trip as an update. Omit for the full field set.


        Optional. `filtered` applies the request''s filter/sort parameters (same syntax
        as the list endpoint) instead of exporting every contact.'
      parameters:
      - name: format
        in: query
        schema:
          type: string
        description: 'Export format: csv (default) or xlsx'
        example: csv
      - name: customer
        in: path
        schema:
          type: integer
        required: true
        description: Customer ID
        example: '1'
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-v2-customers-customer-contacts-export
  /api/v2/customers/{customer}/contacts/{contact}:
    get:
      tags:
      - Customers
      summary: Get Customer Contact
      description: 'Get a single contact belonging to the customer. A contact id that
        belongs to a different customer returns 404.


        Authentication: Requires Bearer token.'
      parameters:
      - name: customer
        in: path
        schema:
          type: integer
        required: true
        description: Customer ID
        example: '12'
      - name: contact
        in: path
        schema:
          type: integer
        required: true
        description: Contact ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      email:
                        type: string
                      phone:
                        type: string
                      role:
                        type: string
                      role_label:
                        type: string
                      title:
                        type: string
                      is_primary:
                        type: boolean
                      is_messaging:
                        type: boolean
                      notes:
                        type: string
                      link_type:
                        type: string
                      link_id:
                        type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 42
                    name: Jane Buyer
                    email: jane.buyer@example.com
                    phone: +1 415-555-0100
                    role: accounts_payable
                    role_label: Accounts Payable
                    title: AP Specialist
                    is_primary: true
                    is_messaging: false
                    notes: Prefers email over phone.
                    link_type: customer
                    link_id: 12
                    created_at: '2026-07-13T14:22:05+00:00'
                    updated_at: '2026-07-13T14:22:05+00:00'
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Contact not found.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-v2-customers-customer-contacts-contact
    put:
      tags:
      - Customers
      summary: Update Customer Contact
      description: 'Update a contact belonging to the customer. Full update — name
        is required. Setting is_primary promotes this contact and demotes the previous
        primary.


        Role options: general, sales_rep, account_manager, customer_service, accounts_payable,
        accounts_receivable, purchasing, shipping_receiving, warehouse_manager, operations,
        billing, owner, other.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                email:
                  type: string
                phone:
                  type: string
                role:
                  type: string
                title:
                  type: string
                is_primary:
                  type: boolean
                is_messaging:
                  type: boolean
                notes:
                  type: string
              example:
                name: Jane Buyer
                email: jane.buyer@example.com
                phone: +1 415-555-0100
                role: accounts_payable
                title: AP Specialist
                is_primary: true
                is_messaging: false
                notes: Prefers email over phone.
      parameters:
      - name: customer
        in: path
        schema:
          type: integer
        required: true
        description: Customer ID
        example: '12'
      - name: contact
        in: path
        schema:
          type: integer
        required: true
        description: Contact ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      email:
                        type: string
                      phone:
                        type: string
                      role:
                        type: string
                      role_label:
                        type: string
                      title:
                        type: string
                      is_primary:
                        type: boolean
                      is_messaging:
                        type: boolean
                      notes:
                        type: string
                      link_type:
                        type: string
                      link_id:
                        type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 42
                    name: Jane Buyer
                    email: jane.buyer@example.com
                    phone: +1 415-555-0100
                    role: accounts_payable
                    role_label: Accounts Payable
                    title: AP Specialist
                    is_primary: true
                    is_messaging: false
                    notes: Prefers email over phone.
                    link_type: customer
                    link_id: 12
                    created_at: '2026-07-13T14:22:05+00:00'
                    updated_at: '2026-07-13T14:22:05+00:00'
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Contact not found.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      name:
                        type: array
                        items:
                          type: string
                example:
                  message: The name field is required.
                  errors:
                    name:
                    - A contact name (or inbox label) is required.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: put-api-v2-customers-customer-contacts-contact
    delete:
      tags:
      - Customers
      summary: Delete Customer Contact
      description: 'Delete a contact from the customer. If the deleted contact was
        primary and other contacts remain, the oldest remaining contact is promoted
        to primary.


        Authentication: Requires Bearer token.'
      parameters:
      - name: customer
        in: path
        schema:
          type: integer
        required: true
        description: Customer ID
        example: '12'
      - name: contact
        in: path
        schema:
          type: integer
        required: true
        description: Contact ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                example:
                  success: true
                  message: Contact deleted.
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Contact not found.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: delete-api-v2-customers-customer-contacts-contact
  /api/v2/customers/{customer}/contacts/{contact}/make-primary:
    post:
      tags:
      - Customers
      summary: Set Customer Contact as Primary
      description: 'Promote a contact to be the customer''s primary contact, demoting
        the previous primary.


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: customer
        in: path
        schema:
          type: integer
        required: true
        description: Customer ID
        example: '12'
      - name: contact
        in: path
        schema:
          type: integer
        required: true
        description: Contact ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      email:
                        type: string
                      phone:
                        type: string
                      role:
                        type: string
                      role_label:
                        type: string
                      title:
                        type: string
                      is_primary:
                        type: boolean
                      is_messaging:
                        type: boolean
                      notes:
                        type: string
                      link_type:
                        type: string
                      link_id:
                        type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 42
                    name: Jane Buyer
                    email: jane.buyer@example.com
                    phone: +1 415-555-0100
                    role: accounts_payable
                    role_label: Accounts Payable
                    title: AP Specialist
                    is_primary: true
                    is_messaging: false
                    notes: Prefers email over phone.
                    link_type: customer
                    link_id: 12
                    created_at: '2026-07-13T14:22:05+00:00'
                    updated_at: '2026-07-13T14:22:05+00:00'
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Contact not found.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-v2-customers-customer-contacts-contact-make-primary
  /api/customers/{customer}/store-credit:
    get:
      tags:
      - Customers
      summary: Get Store Credit Balance
      description: 'Returns the customer''s current store-credit wallet balance —
        the running sum of every ledger entry.


        :::info[Required scope: `customers:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token (PAT).'
      parameters:
      - name: customer
        in: path
        schema:
          type: integer
        required: true
        description: Customer ID
        example: '501'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      customer_id:
                        type: integer
                      balance:
                        type: number
                example:
                  data:
                    customer_id: 501
                    balance: 42.5
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: customers:read
      operationId: get-api-customers-customer-store-credit
    post:
      tags:
      - Customers
      summary: Issue Store Credit
      description: 'Manually issue (or adjust) store credit for a customer.


        :::info[Required scope: `customers:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Request body:

        • `amount` (required, numeric, non-zero) — magnitude for signed reasons (goodwill/top_up
        add, expiry removes); for an `adjustment` the sign is honored, so a negative
        value removes credit.

        • `reason` (required) — one of the human-selectable reasons: `goodwill`, `top_up`,
        `adjustment`, `expiry`. System reasons (`refund`, `overpayment`, `redemption`,
        `reversal`) are rejected here.

        • `notes` (optional, string) — free-text note.

        • `reference` (optional, string) — external reference; defaults to an auto-generated
        SC-###### code.


        An adjustment/expiry that would drive the wallet below zero returns 422.


        Authentication: Requires Bearer token (PAT).

        Requires permission: customers.update.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                amount:
                  type: integer
                reason:
                  type: string
                notes:
                  type: string
                reference:
                  type: string
                  nullable: true
              example:
                amount: 25
                reason: goodwill
                notes: Apology for the mixed-up order
                reference: null
      parameters:
      - name: customer
        in: path
        schema:
          type: integer
        required: true
        description: Customer ID
        example: '501'
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      customer_id:
                        type: integer
                      reference:
                        type: string
                      amount:
                        type: integer
                      balance_after:
                        type: integer
                      reason:
                        type: string
                      reason_label:
                        type: string
                      is_credit:
                        type: boolean
                      currency_id:
                        type: integer
                      notes:
                        type: string
                      source_type:
                        type: string
                        nullable: true
                      source_id:
                        type: string
                        nullable: true
                      created_by_user_id:
                        type: integer
                      created_by_name:
                        type: string
                      created_at:
                        type: string
                  balance:
                    type: number
                  message:
                    type: string
                example:
                  data:
                    id: 123
                    customer_id: 501
                    reference: SC-000123
                    amount: 25
                    balance_after: 25
                    reason: goodwill
                    reason_label: Goodwill
                    is_credit: true
                    currency_id: 1
                    notes: Apology for the mixed-up order
                    source_type: null
                    source_id: null
                    created_by_user_id: 1
                    created_by_name: Jane Cashier
                    created_at: '2026-07-06T14:15:43.000000Z'
                  balance: 42.5
                  message: Store credit issued.
        '422':
          description: Unprocessable Content
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      reason:
                        type: array
                        items:
                          type: string
                example:
                  message: The selected reason cannot be issued manually.
                  errors:
                    reason:
                    - The selected reason cannot be issued manually.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: customers:write
      operationId: post-api-customers-customer-store-credit
  /api/customers/{customer}/store-credit/history:
    get:
      tags:
      - Customers
      summary: Get Store Credit History
      description: 'Paginated ledger history for the customer''s store-credit wallet,
        newest first. Each entry records a signed movement (`amount`), the running
        `balance_after`, the reason, and — for system-driven entries — the polymorphic
        source (e.g. a POS transaction for a refund-to-credit).


        :::info[Required scope: `customers:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token (PAT).'
      parameters:
      - name: customer
        in: path
        schema:
          type: integer
        required: true
        description: Customer ID
        example: '501'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        customer_id:
                          type: integer
                        reference:
                          type: string
                        amount:
                          type: integer
                        balance_after:
                          type: integer
                        reason:
                          type: string
                        reason_label:
                          type: string
                        is_credit:
                          type: boolean
                        currency_id:
                          type: integer
                        notes:
                          type: string
                        source_type:
                          type: string
                          nullable: true
                        source_id:
                          type: string
                          nullable: true
                        created_by_user_id:
                          type: integer
                        created_by_name:
                          type: string
                        created_at:
                          type: string
                  links:
                    type: object
                    properties:
                      first:
                        type: string
                      last:
                        type: string
                      prev:
                        type: string
                        nullable: true
                      next:
                        type: string
                        nullable: true
                  meta:
                    type: object
                    properties:
                      current_page:
                        type: integer
                      from:
                        type: integer
                      last_page:
                        type: integer
                      per_page:
                        type: integer
                      to:
                        type: integer
                      total:
                        type: integer
                example:
                  data:
                  - id: 123
                    customer_id: 501
                    reference: SC-000123
                    amount: 25
                    balance_after: 25
                    reason: goodwill
                    reason_label: Goodwill
                    is_credit: true
                    currency_id: 1
                    notes: Apology for the mixed-up order
                    source_type: null
                    source_id: null
                    created_by_user_id: 1
                    created_by_name: Jane Cashier
                    created_at: '2026-07-06T14:15:43.000000Z'
                  - id: 120
                    customer_id: 501
                    reference: SC-000120
                    amount: -17.5
                    balance_after: 17.5
                    reason: redemption
                    reason_label: Redemption
                    is_credit: false
                    currency_id: 1
                    notes: null
                    source_type: App\Models\SalesOrder
                    source_id: 5012
                    created_by_user_id: 1
                    created_by_name: Jane Cashier
                    created_at: '2026-07-05T10:00:00.000000Z'
                  links:
                    first: '...'
                    last: '...'
                    prev: null
                    next: null
                  meta:
                    current_page: 1
                    from: 1
                    last_page: 1
                    per_page: 10
                    to: 2
                    total: 2
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: customers:read
      operationId: get-api-customers-customer-store-credit-history
  /api/customers/{customer}/ar-summary:
    get:
      tags:
      - Customers
      summary: Get Customer AR Summary
      description: 'Returns the customer''s accounts-receivable summary in one call:
        outstanding and overdue totals, aging buckets, open credits, net receivable,
        credit headroom, informational wallet balances, the most recent payment, and
        the head of the overdue worklist.


        All amounts are in the account''s base currency (`currency`).


        Response fields:

        - `outstanding_total` — sum of balance due across the customer''s open sales
        orders.

        - `overdue` — `amount`, `count`, and `oldest_due_date` of orders past their
        due date.

        - `aging` — outstanding amount bucketed by days past due: `current` (not yet
        due), `d1_30`, `d31_60`, `d61_90`, `d90_plus`.

        - `open_credits` — `amount` and `count` of open sales credits with an unallocated
        balance.

        - `net_receivable` — `outstanding_total` minus `open_credits.amount`. Negative
        means you owe the customer.

        - `credit_limit` / `available_credit` — `available_credit` is `credit_limit`
        minus `outstanding_total`; both null when no credit limit is set.

        - `house_account_balance` / `store_credit_balance` — informational wallet
        balances. Store credit is a prepaid liability and is never netted into `net_receivable`.

        - `last_payment` — `date`, `amount`, and `id` of the most recent payment against
        the customer''s orders (a convenience hint, not an accounting figure); null
        when the customer has never paid.

        - `last_statement_sent_at` — when a statement email was last sent to this
        customer (ISO 8601, or null).

        - `overdue_items` — up to 5 overdue receivable rows, oldest due date first
        (same row shape as the receivables list).

        - `open_count` — number of open receivable rows.

        - `payment_terms_days` — payment terms used to derive due dates (customer
        override, else the account default).


        Due dates are derived as order date + payment terms.


        Authentication: Requires Bearer token (PAT). Requires permissions `customers.show`
        and `sales_orders.index`, and a token with the orders scope.'
      parameters:
      - name: customer
        in: path
        schema:
          type: integer
        required: true
        description: Customer ID
        example: '501'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      currency:
                        type: string
                      outstanding_total:
                        type: number
                      overdue:
                        type: object
                        properties:
                          amount:
                            type: number
                          count:
                            type: integer
                          oldest_due_date:
                            type: string
                      aging:
                        type: object
                        properties:
                          current:
                            type: number
                          d1_30:
                            type: integer
                          d31_60:
                            type: number
                          d61_90:
                            type: integer
                          d90_plus:
                            type: integer
                      open_credits:
                        type: object
                        properties:
                          amount:
                            type: integer
                          count:
                            type: integer
                      net_receivable:
                        type: number
                      credit_limit:
                        type: integer
                      available_credit:
                        type: number
                      house_account_balance:
                        type: integer
                      store_credit_balance:
                        type: number
                      last_payment:
                        type: object
                        properties:
                          date:
                            type: string
                          amount:
                            type: number
                          id:
                            type: integer
                      last_statement_sent_at:
                        type: string
                      overdue_items:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            number:
                              type: string
                            date:
                              type: string
                            due_date:
                              type: string
                            days_until_due:
                              type: integer
                            payment_due_status:
                              type: string
                            order_status:
                              type: string
                            payment_status:
                              type: string
                            total:
                              type: number
                            total_paid:
                              type: integer
                            balance_due:
                              type: number
                            balance_due_in_tenant_currency:
                              type: number
                            currency:
                              type: string
                      open_count:
                        type: integer
                      payment_terms_days:
                        type: integer
                example:
                  data:
                    currency: USD
                    outstanding_total: 764.38
                    overdue:
                      amount: 219.88
                      count: 1
                      oldest_due_date: '2026-06-01'
                    aging:
                      current: 544.5
                      d1_30: 0
                      d31_60: 219.88
                      d61_90: 0
                      d90_plus: 0
                    open_credits:
                      amount: 30
                      count: 1
                    net_receivable: 734.38
                    credit_limit: 5000
                    available_credit: 4235.62
                    house_account_balance: 120
                    store_credit_balance: 42.5
                    last_payment:
                      date: '2026-07-02'
                      amount: 95.5
                      id: 9911
                    last_statement_sent_at: '2026-07-01T15:04:05+00:00'
                    overdue_items:
                    - id: 8123
                      number: SO-01021
                      date: '2026-05-02'
                      due_date: '2026-06-01'
                      days_until_due: -46
                      payment_due_status: overdue
                      order_status: open
                      payment_status: unpaid
                      total: 219.88
                      total_paid: 0
                      balance_due: 219.88
                      balance_due_in_tenant_currency: 219.88
                      currency: USD
                    open_count: 2
                    payment_terms_days: 30
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-customers-customer-ar-summary
  /api/customers/{customer}/receivables:
    get:
      tags:
      - Customers
      summary: List Customer Receivables
      description: 'Paginated receivables worklist for one customer — each row is
        a sales order reduced to its receivable shape.


        Row fields: `number`, `date`, `due_date` (order date + payment terms), `days_until_due`
        (negative when past due), `payment_due_status` (`overdue`, `due_soon` — due
        within 7 days, `current`, or `no_due_date`), `order_status`, `payment_status`,
        `total`, `total_paid`, and `balance_due` in the order''s own currency, `balance_due_in_tenant_currency`
        converted to the account''s base currency at the order''s exchange rate, and
        `currency`.


        Filtering:

        - `filter[status]` — `open` (default: any order with a balance due), `overdue`
        (balance due and past the due date), `due_7d` (balance due within the next
        7 days), `paid` (settled orders), `all`.

        - `filter[search]` — matches the order number.


        Sorting: `sort` accepts `due_date` (default), `-due_date`, `date`, `-date`.


        Pagination: `page` (default 1) and `per_page` (default 10, max 100).


        Authentication: Requires Bearer token (PAT). Requires permissions `customers.show`
        and `sales_orders.index`, and a token with the orders scope.'
      parameters:
      - name: customer
        in: path
        schema:
          type: integer
        required: true
        description: Customer ID
        example: '501'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        number:
                          type: string
                        date:
                          type: string
                        due_date:
                          type: string
                        days_until_due:
                          type: integer
                        payment_due_status:
                          type: string
                        order_status:
                          type: string
                        payment_status:
                          type: string
                        total:
                          type: number
                        total_paid:
                          type: integer
                        balance_due:
                          type: number
                        balance_due_in_tenant_currency:
                          type: number
                        currency:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - id: 8123
                    number: SO-01021
                    date: '2026-05-02'
                    due_date: '2026-06-01'
                    days_until_due: -46
                    payment_due_status: overdue
                    order_status: open
                    payment_status: unpaid
                    total: 219.88
                    total_paid: 0
                    balance_due: 219.88
                    balance_due_in_tenant_currency: 219.88
                    currency: USD
                  - id: 8156
                    number: SO-01044
                    date: '2026-07-06'
                    due_date: '2026-07-20'
                    days_until_due: 3
                    payment_due_status: due_soon
                    order_status: open
                    payment_status: partially_paid
                    total: 640
                    total_paid: 95.5
                    balance_due: 544.5
                    balance_due_in_tenant_currency: 544.5
                    currency: USD
                  current_page: 1
                  last_page: 1
                  per_page: 10
                  total: 2
                  from: 1
                  to: 2
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-customers-customer-receivables
  /api/customers/{customer}/statement:
    get:
      tags:
      - Customers
      summary: Get Customer Statement
      description: 'Returns the customer''s statement of account as JSON, in one of
        two views selected by `type`:


        - `open_item` (default) — every open sales order plus open sales credits with
        an unallocated balance, and a `totals` block (`open`, `credits`, `net_receivable`).
        `as_at` optionally limits the statement to documents dated on or before that
        date (balances remain current values).

        - `activity` — a chronological ledger for the `from`/`to` window (both required
        for this view): an opening balance carried from before the period, then every
        receivable-affecting event with a running balance — orders (debits), payments
        (credits), refunds (debits), and issued sales credits (credits) — satisfying
        opening + debits - credits = closing. Line `type` is one of `order`, `payment`,
        `refund`, `credit_issued`; each line links its source document via `link.entity`
        (`sales_order` or `sales_credit`) and `link.id`.


        All amounts are in the account''s base currency; foreign-currency documents
        are converted at each order''s snapshot exchange rate. Both views also include
        the customer header, the aging buckets, and the account''s configured `payment_instructions`.


        Use the export endpoint for a PDF or CSV download of the same statement.


        Authentication: Requires Bearer token (PAT). Requires permissions `customers.show`
        and `sales_orders.index`, and a token with the orders scope.'
      parameters:
      - name: customer
        in: path
        schema:
          type: integer
        required: true
        description: Customer ID
        example: '501'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 Open-Item Statement
                  value:
                    data:
                      customer:
                        id: 501
                        name: Jane Smith
                        company: Acme Retail LLC
                        email: ap@acmeretail.com
                      as_of: '2026-07-17'
                      currency: USD
                      open_items:
                      - id: 8123
                        number: SO-01021
                        date: '2026-05-02'
                        due_date: '2026-06-01'
                        days_until_due: -46
                        payment_due_status: overdue
                        order_status: open
                        payment_status: unpaid
                        total: 219.88
                        total_paid: 0
                        balance_due: 219.88
                        balance_due_in_tenant_currency: 219.88
                        currency: USD
                      - id: 8156
                        number: SO-01044
                        date: '2026-07-06'
                        due_date: '2026-07-20'
                        days_until_due: 3
                        payment_due_status: due_soon
                        order_status: open
                        payment_status: partially_paid
                        total: 640
                        total_paid: 95.5
                        balance_due: 544.5
                        balance_due_in_tenant_currency: 544.5
                        currency: USD
                      credits:
                      - id: 55
                        number: SC-00055
                        date: '2026-06-18'
                        available: 30
                      totals:
                        open: 764.38
                        credits: 30
                        net_receivable: 734.38
                      aging:
                        current: 544.5
                        d1_30: 0
                        d31_60: 219.88
                        d61_90: 0
                        d90_plus: 0
                      payment_instructions: Pay by ACH to routing 021000021, account
                        1234567. Please reference your order number.
                example-1:
                  summary: 200 Activity Statement
                  value:
                    data:
                      customer:
                        id: 501
                        name: Jane Smith
                        company: Acme Retail LLC
                        email: ap@acmeretail.com
                      period:
                        from: '2026-06-01'
                        to: '2026-06-30'
                      currency: USD
                      opening_balance: 544.5
                      lines:
                      - date: '2026-06-03'
                        type: order
                        reference: SO-01021
                        description: Sales order SO-01021
                        link:
                          entity: sales_order
                          id: 8123
                        debit: 219.88
                        credit: null
                        running_balance: 764.38
                      - date: '2026-06-10'
                        type: payment
                        reference: PAY-9911
                        description: Payment against SO-01021
                        link:
                          entity: sales_order
                          id: 8123
                        debit: null
                        credit: 95.5
                        running_balance: 668.88
                      - date: '2026-06-18'
                        type: credit_issued
                        reference: SC-00055
                        description: Sales credit SC-00055 issued
                        link:
                          entity: sales_credit
                          id: 55
                        debit: null
                        credit: 30
                        running_balance: 638.88
                      closing_balance: 638.88
                      totals:
                        debits: 219.88
                        credits: 125.5
                        ordered: 219.88
                        paid: 95.5
                        refunded: 0
                        credits_issued: 30
                      aging:
                        current: 544.5
                        d1_30: 0
                        d31_60: 219.88
                        d61_90: 0
                        d90_plus: 0
                      payment_instructions: Pay by ACH to routing 021000021, account
                        1234567. Please reference your order number.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      from:
                        type: array
                        items:
                          type: string
                      to:
                        type: array
                        items:
                          type: string
                example:
                  message: A start date is required for the activity statement type.
                    (and 1 more error)
                  errors:
                    from:
                    - A start date is required for the activity statement type.
                    to:
                    - An end date is required for the activity statement type.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-customers-customer-statement
  /api/customers/{customer}/statement/export:
    get:
      tags:
      - Customers
      summary: Export Customer Statement
      description: 'Downloads the customer''s statement of account as a file. `format=pdf`
        (default) returns a branded PDF document (`application/pdf`); `format=csv`
        returns comma-separated rows (`text/csv`).


        Accepts the same statement parameters as the JSON statement endpoint: `type`
        (`open_item` default, or `activity`), `from`/`to` (required when `type=activity`),
        and `as_at` (`open_item` only).


        The response is a file download named `customer-statement-{customer-name}-{date}.pdf`
        (or `.csv`) — not JSON.


        CSV columns:

        - `activity`: Date, Type, Reference, Description, Debit, Credit, Running Balance
        — with opening and closing balance rows.

        - `open_item`: Type, Document, Date, Due Date, Status, Document Currency,
        Total (Document Currency), Outstanding (base currency) — one row per open
        order, one negative row per open credit, and a final net_receivable row.


        Authentication: Requires Bearer token (PAT). Requires permissions `customers.show`
        and `sales_orders.index`, and a token with the orders scope.'
      parameters:
      - name: customer
        in: path
        schema:
          type: integer
        required: true
        description: Customer ID
        example: '501'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: text/csv
          content:
            text/plain:
              schema:
                type: string
                example: 'Type,Document,Date,"Due Date",Status,"Document Currency","Total
                  (Document Currency)","Outstanding (USD)"

                  sales_order,SO-01021,2026-05-02,2026-06-01,unpaid,USD,219.88,219.88

                  sales_order,SO-01044,2026-07-06,2026-07-20,partially_paid,USD,640.00,544.50

                  sales_credit,SC-00055,2026-06-18,,open,USD,,-30

                  net_receivable,,,,,USD,,734.38

                  '
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-customers-customer-statement-export
  /api/customers/{customer}/statement/preview:
    post:
      tags:
      - Customers
      summary: Preview Customer Statement Email
      description: 'Preview the statement email that a send would produce — the exact
        From and Reply-To addresses, resolved recipient, subject and body — WITHOUT
        sending it or logging anything. Use it to show the sender and content before
        committing to send.


        Body is identical to Send Customer Statement: `type` (required — `open_item`
        or `activity`); for `activity`, `from` and `to` (Y-m-d) are required; `as_at`
        (Y-m-d) optionally dates an open-item statement; `recipient` overrides the
        customer''s billing email; `subject` and `body` override the defaults and
        support the placeholders {customer_name}, {total_due}, {payment_instructions}.


        Authentication: Requires Bearer token (PAT).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                type:
                  type: string
                as_at:
                  type: string
                recipient:
                  type: string
                subject:
                  type: string
                body:
                  type: string
              example:
                type: open_item
                as_at: '2026-06-30'
                recipient: ap@acmeretail.com
                subject: Statement of Account — {customer_name}
                body: 'Dear {customer_name},


                  Please find your statement of account attached. Your current balance
                  is {total_due}.


                  {payment_instructions}'
      parameters:
      - name: customer
        in: path
        schema:
          type: integer
        required: true
        description: Customer ID
        example: '501'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      from:
                        type: object
                        properties:
                          address:
                            type: string
                          name:
                            type: string
                      reply_to:
                        type: object
                        properties:
                          address:
                            type: string
                          name:
                            type: string
                      recipient:
                        type: string
                      subject:
                        type: string
                      body:
                        type: string
                      attachment_filename:
                        type: string
                example:
                  data:
                    from:
                      address: billing@acme-wholesale.example
                      name: Acme Wholesale
                    reply_to:
                      address: ar@acme-wholesale.example
                      name: Acme Wholesale AR
                    recipient: ap@acmeretail.com
                    subject: Statement of Account — Acme Retail
                    body: 'Dear Acme Retail,


                      Please find your statement of account attached. Your current
                      balance is $764.38.


                      To pay, reply to this email or contact our accounts team.'
                    attachment_filename: customer-statement-acme-retail-2026-07-18.pdf
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-customers-customer-statement-preview
  /api/customers/{customer}/send-statement:
    post:
      tags:
      - Customers
      summary: Send Customer Statement
      description: 'Emails the customer a statement of account with the PDF attached,
        and records the send in the communications log.


        The statement is generated with the same parameters as the statement endpoints:
        `type` (required — `open_item` or `activity`), `from`/`to` (required when
        `type=activity`), and `as_at` (`open_item` only).


        The recipient defaults to the customer''s billing email, falling back to their
        primary email; pass `recipient` to override. `subject` and `body` are optional
        templates; these placeholders are replaced before sending: `{customer_name}`,
        `{total_due}` (the statement''s closing balance or net receivable, formatted
        with currency), `{days_overdue}`, and `{payment_instructions}` (the account''s
        configured payment instructions). When omitted, a default subject and body
        are used.


        Returns the logged communication entry.


        Body parameters:

        - type (string, required): `open_item` or `activity`.

        - from (date): Period start. Required when type is `activity`.

        - to (date): Period end, on or after `from`. Required when type is `activity`.

        - as_at (date, optional): `open_item` only — include only documents dated
        on or before this date.

        - recipient (string, email, optional): Override the destination email address.

        - subject (string, max 255, optional): Email subject template.

        - body (string, max 10000, optional): Email body template.


        Errors:

        - 422 when `type` is missing, `from`/`to` are missing for the activity view,
        or no recipient email can be resolved (the customer has no billing or primary
        email and no `recipient` was supplied).


        Authentication: Requires Bearer token (PAT). Requires permission `customers.send_communications`
        and a token with the orders scope. Rate limited to 60 requests per minute.


        The activity statement date range cannot exceed 366 days.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                type:
                  type: string
                as_at:
                  type: string
                recipient:
                  type: string
                subject:
                  type: string
                body:
                  type: string
              example:
                type: open_item
                as_at: '2026-06-30'
                recipient: ap@acmeretail.com
                subject: Statement of Account — {customer_name}
                body: 'Dear {customer_name},


                  Please find your statement of account attached. Your current balance
                  is {total_due}.


                  {payment_instructions}'
      parameters:
      - name: customer
        in: path
        schema:
          type: integer
        required: true
        description: Customer ID
        example: '501'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      customer_id:
                        type: integer
                      sales_order_id:
                        type: string
                        nullable: true
                      sales_order_number:
                        type: string
                        nullable: true
                      type:
                        type: string
                      scope:
                        type: string
                      statement_type:
                        type: string
                      params:
                        type: object
                        properties:
                          as_at:
                            type: string
                          total_due:
                            type: number
                      recipient:
                        type: string
                      subject:
                        type: string
                      sent_by:
                        type: integer
                      sender_name:
                        type: string
                      created_at:
                        type: string
                example:
                  message: Statement sent to ap@acmeretail.com.
                  data:
                    id: 87
                    customer_id: 501
                    sales_order_id: null
                    sales_order_number: null
                    type: statement
                    scope: account
                    statement_type: open_item
                    params:
                      as_at: '2026-06-30'
                      total_due: 734.38
                    recipient: ap@acmeretail.com
                    subject: Statement of Account — Acme Retail LLC
                    sent_by: 3
                    sender_name: Alex Rivera
                    created_at: '2026-07-01T15:04:05+00:00'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      recipient:
                        type: array
                        items:
                          type: string
                example:
                  message: This customer has no billing email or email address. Add
                    one, or provide a recipient.
                  errors:
                    recipient:
                    - This customer has no billing email or email address. Add one,
                      or provide a recipient.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-customers-customer-send-statement
  /api/customers/{customer}/request-payment:
    post:
      tags:
      - Customers
      summary: Request Customer Payment
      description: 'Emails the customer an account-level payment request for their
        outstanding balance, and records the send in the communications log. To request
        payment for a single order instead, use the request-payment action on that
        sales order (Orders collection).


        The recipient defaults to the customer''s billing email, falling back to their
        primary email; pass `recipient` to override. `subject` and `body` are optional
        templates; these placeholders are replaced before sending: `{customer_name}`,
        `{total_due}` (the customer''s outstanding balance, formatted with currency),
        `{days_overdue}` (days since the oldest overdue due date), and `{payment_instructions}`
        (the account''s configured payment instructions). When omitted, a default
        subject and body are used.


        Set `attach_statement` to true to attach the customer''s current open-item
        statement as a PDF.


        Returns the logged communication entry.


        Body parameters (all optional):

        - recipient (string, email): Override the destination email address.

        - subject (string, max 255): Email subject template.

        - body (string, max 10000): Email body template.

        - attach_statement (boolean): Attach the open-item statement PDF. Default
        false.


        Errors:

        - 422 when no recipient email can be resolved (the customer has no billing
        or primary email and no `recipient` was supplied).


        Authentication: Requires Bearer token (PAT). Requires permission `customers.send_communications`
        and a token with the orders scope. Rate limited to 60 requests per minute.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                recipient:
                  type: string
                subject:
                  type: string
                body:
                  type: string
                attach_statement:
                  type: boolean
              example:
                recipient: ap@acmeretail.com
                subject: Payment Request — {customer_name}
                body: 'Dear {customer_name},


                  Our records show an outstanding balance of {total_due} on your account.
                  Please arrange payment at your earliest convenience.


                  {payment_instructions}'
                attach_statement: true
      parameters:
      - name: customer
        in: path
        schema:
          type: integer
        required: true
        description: Customer ID
        example: '501'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      customer_id:
                        type: integer
                      sales_order_id:
                        type: string
                        nullable: true
                      sales_order_number:
                        type: string
                        nullable: true
                      type:
                        type: string
                      scope:
                        type: string
                      statement_type:
                        type: string
                        nullable: true
                      params:
                        type: object
                        properties:
                          total_due:
                            type: number
                          attach_statement:
                            type: boolean
                      recipient:
                        type: string
                      subject:
                        type: string
                      sent_by:
                        type: integer
                      sender_name:
                        type: string
                      created_at:
                        type: string
                example:
                  message: Payment request sent to ap@acmeretail.com.
                  data:
                    id: 89
                    customer_id: 501
                    sales_order_id: null
                    sales_order_number: null
                    type: payment_request
                    scope: account
                    statement_type: null
                    params:
                      total_due: 764.38
                      attach_statement: true
                    recipient: ap@acmeretail.com
                    subject: Payment Request — Acme Retail LLC
                    sent_by: 3
                    sender_name: Alex Rivera
                    created_at: '2026-07-17T09:12:03+00:00'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      recipient:
                        type: array
                        items:
                          type: string
                example:
                  message: This customer has no billing email or email address. Add
                    one, or provide a recipient.
                  errors:
                    recipient:
                    - This customer has no billing email or email address. Add one,
                      or provide a recipient.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-customers-customer-request-payment
  /api/customers/{customer}/ar-communications:
    get:
      tags:
      - Customers
      summary: List Customer AR Communications
      description: 'Paginated log of outbound receivables emails sent to this customer,
        newest first. Entries are created by the send-statement and request-payment
        actions (both the account-level actions here and the per-order request-payment
        action in the Orders collection).


        Entry fields: `type` (`statement` or `payment_request`), `scope` (`account`,
        or `order` with `sales_order_id` / `sales_order_number` set), `statement_type`
        (`open_item` or `activity` for statement sends, null otherwise), `params`
        (send parameters and amounts captured at send time, e.g. `total_due`, `amount_due`,
        `days_overdue`, `as_at`, `attach_statement`, `attach_invoice`), `recipient`,
        `subject`, `sent_by` / `sender_name` (the user who sent it), and `created_at`.


        Pagination: `page` (default 1) and `per_page` (default 10).


        Authentication: Requires Bearer token (PAT). Requires permissions `customers.show`
        and `sales_orders.index`, and a token with the orders scope.'
      parameters:
      - name: customer
        in: path
        schema:
          type: integer
        required: true
        description: Customer ID
        example: '501'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        customer_id:
                          type: integer
                        sales_order_id:
                          type: integer
                        sales_order_number:
                          type: string
                        type:
                          type: string
                        scope:
                          type: string
                        statement_type:
                          type: string
                          nullable: true
                        params:
                          type: object
                          properties:
                            amount_due:
                              type: number
                            days_overdue:
                              type: integer
                            attach_invoice:
                              type: boolean
                        recipient:
                          type: string
                        subject:
                          type: string
                        sent_by:
                          type: integer
                        sender_name:
                          type: string
                        created_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - id: 88
                    customer_id: 501
                    sales_order_id: 8123
                    sales_order_number: SO-01021
                    type: payment_request
                    scope: order
                    statement_type: null
                    params:
                      amount_due: 219.88
                      days_overdue: 46
                      attach_invoice: true
                    recipient: ap@acmeretail.com
                    subject: Payment Request — Order SO-01021
                    sent_by: 3
                    sender_name: Alex Rivera
                    created_at: '2026-07-16T18:22:41+00:00'
                  - id: 87
                    customer_id: 501
                    sales_order_id: null
                    sales_order_number: null
                    type: statement
                    scope: account
                    statement_type: open_item
                    params:
                      as_at: '2026-06-30'
                      total_due: 734.38
                    recipient: ap@acmeretail.com
                    subject: Statement of Account — Acme Retail LLC
                    sent_by: 3
                    sender_name: Alex Rivera
                    created_at: '2026-07-01T15:04:05+00:00'
                  current_page: 1
                  last_page: 1
                  per_page: 10
                  total: 2
                  from: 1
                  to: 2
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-customers-customer-ar-communications
  /api/sales-reps/{salesRep}/activity-log:
    get:
      tags:
      - Sales Reps
      summary: Get Sales Rep Activity Log
      description: 'Get the activity log for a specific sales rep. Returns a paginated
        list of audit events with the causer and changed properties.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: salesRep
        in: path
        schema:
          type: integer
        required: true
        description: Sales rep ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        event:
                          type: string
                        causer_name:
                          type: string
                        created_at:
                          type: string
                  current_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 1001
                    event: updated
                    causer_name: Admin User
                    created_at: '2024-06-15T10:30:00.000000Z'
                  current_page: 1
                  total: 22
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-session-only: true
      operationId: get-api-sales-reps-salesrep-activity-log
  /api/sales-reps/list:
    get:
      tags:
      - Sales Reps
      summary: Get Sales Reps for Dropdown
      description: 'Get a simplified list of all sales reps (id and name only) for
        use in dropdown/combo box lookups. Returns all reps ordered by name without
        pagination.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                  status:
                    type: string
                example:
                  data:
                  - id: 1
                    name: Jane Smith
                  - id: 2
                    name: Bob Johnson
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: get-api-sales-reps-list
  /api/sub-sales-channels/{id}:
    get:
      tags:
      - Sub Sales Channels
      summary: Get Sub Sales Channel
      description: 'Returns a single sub sales channel by ID with all related data
        loaded.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.


        Power user access required.'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      sales_channel_id:
                        type: integer
                example:
                  data:
                    id: 1
                    name: Amazon US
                    sales_channel_id: 5
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No query results for model [App\Models\SubSalesChannel]
                    999
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: get-api-sub-sales-channels-id
    put:
      tags:
      - Sub Sales Channels
      summary: Update Sub Sales Channel
      description: 'Updates an existing sub sales channel. All fields are optional
        (partial update supported).


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.


        Power user access required.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                sales_nominal_code_id:
                  type: integer
                cogs_nominal_code_id:
                  type: integer
              example:
                name: Amazon US Updated
                sales_nominal_code_id: 10
                cogs_nominal_code_id: 11
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                example:
                  message: Sub Sales Channel 'Amazon US Updated' updated successfully.
                  data:
                    id: 1
                    name: Amazon US Updated
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-session-only: true
      operationId: put-api-sub-sales-channels-id
    delete:
      tags:
      - Sub Sales Channels
      summary: Delete Sub Sales Channel
      description: 'Deletes a sub sales channel.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.


        Power user access required.'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Sub Sales Channel 'Amazon US' deleted successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-session-only: true
      operationId: delete-api-sub-sales-channels-id
  /api/sub-sales-channels/by-sales-channel/{id}:
    get:
      tags:
      - Sub Sales Channels
      summary: Get Sub Sales Channels by Sales Channel
      description: 'Returns all sub sales channels that belong to a specific sales
        channel.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.


        Power user access required.'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                example:
                  data:
                  - id: 1
                    name: Amazon US
                  - id: 2
                    name: Amazon CA
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-session-only: true
      operationId: get-api-sub-sales-channels-by-sales-channel-id
  /api/sub-sales-channels/list:
    get:
      tags:
      - Sub Sales Channels
      summary: List Sub Sales Channel Options (id/name)
      description: 'Returns a minimal list of sub sales channels (id and name only)
        for use in dropdown/combo box controls. Ordered by name.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.


        Power user access required.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                example:
                  data:
                  - id: 1
                    name: Amazon CA
                  - id: 2
                    name: Amazon US
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: get-api-sub-sales-channels-list
  /api/sub-sales-channels/lookup/sales-channels:
    get:
      tags:
      - Sub Sales Channels
      summary: Lookup Sales Channels
      description: 'Returns all sales channels for use in dropdowns when creating/editing
        sub sales channels.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.


        Power user access required.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                example:
                  data:
                  - id: 1
                    name: Shopify Main Store
                  - id: 2
                    name: Amazon Seller Central
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: get-api-sub-sales-channels-lookup-sales-channels
  /api/sub-sales-channels/lookup/nominal-codes:
    get:
      tags:
      - Sub Sales Channels
      summary: Lookup Nominal Codes
      description: 'Returns all nominal codes for use in dropdowns when assigning
        accounting codes to sub sales channels. Ordered by code.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.


        Power user access required.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        code:
                          type: string
                example:
                  data:
                  - id: 10
                    name: Sales Revenue
                    code: '4000'
                  - id: 11
                    name: Cost of Goods Sold
                    code: '5000'
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: get-api-sub-sales-channels-lookup-nominal-codes
  /api/v2/report-builder/metadata:
    get:
      tags:
      - Custom Report Builder
      summary: Get Metadata (Domains, Entities, Columns)
      description: 'Returns all available domains, entities, and columns that can
        be used to build a report definition. Use this to populate the report builder
        UI with selectable fields.


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        The response contains the full schema of reportable data: which domains are
        available (e.g., inventory, sales), which entities exist within each domain,
        and which columns (dimensions and measures) can be selected for each entity.'
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:read
      operationId: get-api-v2-report-builder-metadata
  /api/v2/report-builder/run:
    post:
      tags:
      - Custom Report Builder
      summary: Run Ad-Hoc Report
      description: 'Run a report definition without saving it. Use this for previewing
        results before saving a custom report.


        :::info[Required scope: `reports:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        The definition object must include:

        - `base_entity` (string, required): The primary entity to query

        - `columns` (array, required, min 1): Columns to include. Each column needs
        `id`, `kind` (dimension|measure), `entity`, and `field`. Optional: `label`,
        `granularity`, `aggregation`

        - `filters` (object, optional): Filter tree with `conjunction` (and|or) and
        `children` array of conditions/groups

        - `sorts` (array, optional): Sort rules with `column_id` and `direction` (asc|desc)

        - `limit` (integer, optional): Max rows (1-5000)


        The top-level `limit` parameter also caps the result set (1-5000).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                definition:
                  type: object
                  properties:
                    base_entity:
                      type: string
                    columns:
                      type: array
                      items:
                        type: object
                        properties:
                          id:
                            type: string
                          kind:
                            type: string
                          entity:
                            type: string
                          field:
                            type: string
                    filters:
                      type: object
                      properties:
                        conjunction:
                          type: string
                        children:
                          type: array
                          items:
                            type: object
                            properties:
                              type:
                                type: string
                              condition:
                                type: object
                                properties:
                                  column:
                                    type: string
                                  operator:
                                    type: string
                                  value:
                                    type: string
                    sorts:
                      type: array
                      items:
                        type: object
                        properties:
                          column_id:
                            type: string
                          direction:
                            type: string
                    limit:
                      type: integer
                limit:
                  type: integer
              example:
                definition:
                  base_entity: sales_orders
                  columns:
                  - id: sales_orders.order_number
                    kind: dimension
                    entity: sales_orders
                    field: order_number
                  - id: sales_orders.total
                    kind: measure
                    entity: sales_orders
                    field: total
                    aggregation: sum
                  filters:
                    conjunction: and
                    children:
                    - type: condition
                      condition:
                        column: sales_orders.status
                        operator: '='
                        value: shipped
                  sorts:
                  - column_id: sales_orders.total
                    direction: desc
                  limit: 100
                limit: 100
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: reports:write
      operationId: post-api-v2-report-builder-run
  /api/v2/custom-reports:
    get:
      tags:
      - Custom Report Builder
      summary: List Custom Reports
      description: 'List all custom reports for the authenticated user. Supports pagination,
        search by name, and filtering by domain.


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Response uses standard Laravel pagination with `data`, `current_page`, `last_page`,
        `per_page`, `total`, etc. Each item in `data` is a custom report object.'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        description: Page number for pagination
        example: '1'
      - name: per_page
        in: query
        schema:
          type: integer
        description: 'Items per page (default: 20)'
        example: '20'
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:read
      operationId: get-api-v2-custom-reports
    post:
      tags:
      - Custom Report Builder
      summary: Create Custom Report
      description: 'Create a new saved custom report.


        :::info[Required scope: `reports:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Required fields:

        - `name` (string, max 255): Report name

        - `domain` (string, max 50): Domain category (e.g., sales, inventory)

        - `base_entity` (string, max 100): Primary entity for the report

        - `definition` (object): Full report definition containing columns, filters,
        sorts, etc.


        Optional fields:

        - `description` (string, max 1000): Report description

        - `visibility` (string): "private" (default) or "shared"

        - `definition.version` (integer): Schema version number

        - `definition.domain` (string): Domain within the definition

        - `definition.filters` (object): Filter tree with conjunction and children

        - `definition.sorts` (array): Sort rules

        - `definition.limit` (integer, 1-5000): Default row limit


        Column requirements:

        - `id` (string, required): Unique column identifier (e.g., "entity.field")

        - `kind` (string, required): "dimension" or "measure"

        - `entity` (string, required): Entity the column belongs to

        - `field` (string, required): Field name on the entity

        - `label` (string, optional): Display label

        - `granularity` (string, optional): Time granularity for date dimensions (e.g.,
        day, month, year)

        - `aggregation` (string, optional): Aggregation function for measures (e.g.,
        sum, count, avg)


        Returns 201 with the created custom report object.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                description:
                  type: string
                domain:
                  type: string
                base_entity:
                  type: string
                definition:
                  type: object
                  properties:
                    base_entity:
                      type: string
                    domain:
                      type: string
                    version:
                      type: integer
                    columns:
                      type: array
                      items:
                        type: object
                        properties:
                          id:
                            type: string
                          kind:
                            type: string
                          entity:
                            type: string
                          field:
                            type: string
                          label:
                            type: string
                          granularity:
                            type: string
                    filters:
                      type: object
                      properties:
                        conjunction:
                          type: string
                        children:
                          type: array
                          items:
                            type: object
                            properties:
                              type:
                                type: string
                              condition:
                                type: object
                                properties:
                                  column:
                                    type: string
                                  operator:
                                    type: string
                                  value:
                                    type: string
                    sorts:
                      type: array
                      items:
                        type: object
                        properties:
                          column_id:
                            type: string
                          direction:
                            type: string
                    limit:
                      type: integer
                visibility:
                  type: string
              example:
                name: Monthly Sales by Product
                description: Aggregated sales totals grouped by product and month
                domain: sales
                base_entity: sales_orders
                definition:
                  base_entity: sales_orders
                  domain: sales
                  version: 1
                  columns:
                  - id: sales_orders.order_date
                    kind: dimension
                    entity: sales_orders
                    field: order_date
                    label: Order Month
                    granularity: month
                  - id: products.name
                    kind: dimension
                    entity: products
                    field: name
                    label: Product Name
                  - id: sales_orders.total
                    kind: measure
                    entity: sales_orders
                    field: total
                    label: Total Sales
                    aggregation: sum
                  filters:
                    conjunction: and
                    children:
                    - type: condition
                      condition:
                        column: sales_orders.status
                        operator: '!='
                        value: cancelled
                  sorts:
                  - column_id: sales_orders.order_date
                    direction: desc
                  limit: 500
                visibility: private
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: reports:write
      operationId: post-api-v2-custom-reports
  /api/v2/custom-reports/{id}:
    get:
      tags:
      - Custom Report Builder
      summary: Get Custom Report
      description: 'Get a single custom report by ID. The report must belong to or
        be shared with the authenticated user.


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Returns the full custom report object including the user name (eager-loaded).
        Returns 404 if the report is not found or not accessible.'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: reports:read
      operationId: get-api-v2-custom-reports-id
    put:
      tags:
      - Custom Report Builder
      summary: Update Custom Report
      description: 'Update an existing custom report. Only the report owner can update
        it (returns 403 otherwise).


        :::info[Required scope: `reports:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        All fields are optional (uses `sometimes` validation). When `definition` is
        provided, `definition.base_entity` and `definition.columns` become required.


        Returns 404 if the report is not found or not accessible. Returns 403 if the
        authenticated user is not the owner.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                description:
                  type: string
                definition:
                  type: object
                  properties:
                    base_entity:
                      type: string
                    domain:
                      type: string
                    version:
                      type: integer
                    columns:
                      type: array
                      items:
                        type: object
                        properties:
                          id:
                            type: string
                          kind:
                            type: string
                          entity:
                            type: string
                          field:
                            type: string
                          label:
                            type: string
                          granularity:
                            type: string
                    filters:
                      type: object
                      properties:
                        conjunction:
                          type: string
                        children:
                          type: array
                          items:
                            type: object
                            properties:
                              type:
                                type: string
                              condition:
                                type: object
                                properties:
                                  column:
                                    type: string
                                  operator:
                                    type: string
                                  value:
                                    type: string
                    sorts:
                      type: array
                      items:
                        type: object
                        properties:
                          column_id:
                            type: string
                          direction:
                            type: string
                    limit:
                      type: integer
                visibility:
                  type: string
              example:
                name: Monthly Sales by Product (Updated)
                description: Updated description for monthly sales report
                definition:
                  base_entity: sales_orders
                  domain: sales
                  version: 1
                  columns:
                  - id: sales_orders.order_date
                    kind: dimension
                    entity: sales_orders
                    field: order_date
                    label: Order Month
                    granularity: month
                  - id: products.sku
                    kind: dimension
                    entity: products
                    field: sku
                    label: SKU
                  - id: products.name
                    kind: dimension
                    entity: products
                    field: name
                    label: Product Name
                  - id: sales_orders.total
                    kind: measure
                    entity: sales_orders
                    field: total
                    label: Total Sales
                    aggregation: sum
                  - id: sales_orders.id
                    kind: measure
                    entity: sales_orders
                    field: id
                    label: Order Count
                    aggregation: count
                  filters:
                    conjunction: and
                    children:
                    - type: condition
                      condition:
                        column: sales_orders.status
                        operator: '!='
                        value: cancelled
                  sorts:
                  - column_id: sales_orders.order_date
                    direction: desc
                  limit: 1000
                visibility: shared
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: reports:write
      operationId: put-api-v2-custom-reports-id
    delete:
      tags:
      - Custom Report Builder
      summary: Delete Custom Report
      description: 'Delete a custom report. Only the report owner can delete it (returns
        403 otherwise). Also deletes associated shares.


        :::info[Required scope: `reports:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Returns 204 No Content on success. Returns 404 if not found. Returns 403 if
        not the owner.'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: reports:write
      operationId: delete-api-v2-custom-reports-id
  /api/v2/custom-reports/{id}/run:
    post:
      tags:
      - Custom Report Builder
      summary: Run Saved Report
      description: 'Execute a saved custom report by ID. The report must belong to
        or be shared with the authenticated user.


        :::info[Required scope: `reports:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Optional body parameter:

        - `limit` (integer, default 500): Maximum number of rows to return


        Returns 404 if the report is not found. Returns 422 if the report definition
        is invalid (e.g., references unknown entities or columns).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                limit:
                  type: integer
              example:
                limit: 500
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: reports:write
      operationId: post-api-v2-custom-reports-id-run
  /api/v2/report-builder/drill-down:
    post:
      tags:
      - Custom Report Builder
      summary: Drill Down Into Aggregated Row
      description: 'Execute a drill-down query for a row in an aggregated report.
        Pass the same `definition` used to produce the parent row along with a `drill_values`
        map of {dimension_alias: value} pairs to isolate the underlying detail records.


        :::info[Required scope: `reports:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Returns rows from the base entity that match all supplied drill values, respecting
        the definition''s filters and tenant isolation. Use for powering drill-down
        drawers in the UI.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                definition:
                  type: object
                  properties:
                    base_entity:
                      type: string
                    columns:
                      type: array
                      items:
                        type: object
                        properties:
                          id:
                            type: string
                          kind:
                            type: string
                          entity:
                            type: string
                          field:
                            type: string
                drill_values:
                  type: object
                  properties:
                    sales_orders__order_status:
                      type: string
                limit:
                  type: integer
              example:
                definition:
                  base_entity: sales_orders
                  columns:
                  - id: sales_orders.order_status
                    kind: dimension
                    entity: sales_orders
                    field: order_status
                  - id: sales_orders.id
                    kind: measure
                    entity: sales_orders
                    field: id
                    aggregation: count
                drill_values:
                  sales_orders__order_status: shipped
                limit: 100
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: reports:write
      operationId: post-api-v2-report-builder-drill-down
  /api/v2/report-builder/validate-formula:
    post:
      tags:
      - Custom Report Builder
      summary: Validate Formula Expression
      description: 'Validate a user-entered formula expression before saving. The
        formula is parsed via Symfony ExpressionLanguage against a whitelist of functions
        (IF, COALESCE, ROUND, NULLIF, etc.) and field references (`{field_name}`).


        :::info[Required scope: `reports:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Request body:

        - `formula` (string, required, max 2000): The expression to validate

        - `base_entity` (string, optional): Entity context for field reference resolution

        - `available_columns` (array, optional): Available columns in the current
        report for reference validation


        Returns `{ valid: true }` or `{ valid: false, error: ''...'' }`. Rejects SQL-injection
        attempts and unknown field references.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                formula:
                  type: string
                base_entity:
                  type: string
                available_columns:
                  type: array
                  items:
                    type: object
                    properties:
                      id:
                        type: string
                      kind:
                        type: string
              example:
                formula: '{revenue} / NULLIF({units_sold}, 0)'
                base_entity: sales_order_lines
                available_columns:
                - id: sales_order_lines.revenue
                  kind: measure
                - id: sales_order_lines.units_sold
                  kind: measure
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: reports:write
      operationId: post-api-v2-report-builder-validate-formula
  /api/v2/report-builder/field-values/sales_orders/order_status:
    get:
      tags:
      - Custom Report Builder
      summary: Get Distinct Field Values (Autocomplete)
      description: 'Return distinct values for a given entity/field. Used to populate
        autocomplete dropdowns in the filter builder UI (e.g., distinct `order_status`
        values).


        Respects tenant isolation. Supports an optional `search` query param for LIKE
        matching and a `limit` param to cap results.'
      parameters:
      - name: search
        in: query
        schema:
          type: string
        description: Optional search term for autocomplete
      - name: limit
        in: query
        schema:
          type: integer
        description: Max distinct values to return (default 50)
        example: '50'
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-v2-report-builder-field-values-sales-orders-order-status
  /api/v2/report-builder/users:
    get:
      tags:
      - Custom Report Builder
      summary: Search Share Recipients
      description: 'Search for users that can be added as share recipients on a custom
        report. Limited to users in the same tenant. Returns up to 20 matches. Used
        to power the share dialog''s user picker.


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: search
        in: query
        schema:
          type: string
        description: Search by name or email
        example: alice
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:read
      operationId: get-api-v2-report-builder-users
  /api/v2/custom-reports/{id}/duplicate:
    post:
      tags:
      - Custom Report Builder
      summary: Duplicate Custom Report
      description: 'Create a personal copy of a report. The duplicate is always owned
        by the authenticated caller with visibility=''private'' regardless of the
        original''s visibility. Works on shared reports too (lets a user fork a shared
        report into their own workspace).


        :::info[Required scope: `reports:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Request body:

        - `name` (string, required, max 255): Name for the new copy


        Returns 201 with the new custom report object.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
              example:
                name: My Copy of Monthly Sales
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: reports:write
      operationId: post-api-v2-custom-reports-id-duplicate
  /api/v2/custom-reports/{id}/toggle-favorite:
    post:
      tags:
      - Custom Report Builder
      summary: Toggle Favorite
      description: 'Toggle the `is_favorited` flag on a report. Only the owner can
        toggle favorites on their own report (returns 403 otherwise). The Favorites
        tab on the Reports Hub filters by this flag.


        :::info[Required scope: `reports:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: reports:write
      operationId: post-api-v2-custom-reports-id-toggle-favorite
  /api/v2/custom-reports/{id}/export:
    post:
      tags:
      - Custom Report Builder
      summary: Export Custom Report
      description: 'Export a saved custom report. The response is a streamed/binary
        download in the requested format.


        :::info[Required scope: `reports:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Request body:

        - `format` (string, required): One of `csv`, `xlsx`, `pdf`


        Returns 200 with a file download. Returns 404 if the report is not owned by
        or shared with the caller.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                format:
                  type: string
              example:
                format: xlsx
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: reports:write
      operationId: post-api-v2-custom-reports-id-export
  /api/v2/custom-reports/{id}/shares:
    get:
      tags:
      - Custom Report Builder
      summary: List Shares
      description: 'List all explicit share grants for a report. Each entry includes
        the recipient user (eager-loaded) and the permission (`view` or `edit`). Returns
        403 if the caller is not the report owner.


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: reports:read
      operationId: get-api-v2-custom-reports-id-shares
    post:
      tags:
      - Custom Report Builder
      summary: Add Share
      description: 'Add a user as an explicit share recipient. Upserts (updateOrCreate)
        so calling twice with a different permission updates the existing record.


        :::info[Required scope: `reports:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Request body:

        - `user_id` (integer, required): Recipient user ID (cannot be self)

        - `permission` (string, required): `view` or `edit`


        Returns 403 if the caller is not the report owner. Returns 422 if sharing
        with self or invalid permission.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                user_id:
                  type: integer
                permission:
                  type: string
              example:
                user_id: 2
                permission: view
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: reports:write
      operationId: post-api-v2-custom-reports-id-shares
  /api/v2/custom-reports/{id}/shares/{id2}:
    delete:
      tags:
      - Custom Report Builder
      summary: Remove Share
      description: 'Revoke an explicit share grant for a specific user. Returns 204
        on success. Returns 403 if the caller is not the report owner.


        :::info[Required scope: `reports:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      - name: id2
        in: path
        required: true
        schema:
          type: string
        description: The id2 identifier
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: reports:write
      operationId: delete-api-v2-custom-reports-id-shares-id2
  /api/v2/custom-reports/{id}/schedules:
    get:
      tags:
      - Custom Report Builder
      summary: List Schedules
      description: 'List all schedules for a report. Each entry includes the creating
        user (eager-loaded), frequency, time_of_day (H:i:s), timezone, export_format,
        recipients, is_active, last_sent_at, and next_run_at. Accessible to anyone
        who can read the report.


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: reports:read
      operationId: get-api-v2-custom-reports-id-schedules
    post:
      tags:
      - Custom Report Builder
      summary: Create Schedule
      description: 'Create a new schedule.


        :::info[Required scope: `reports:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Required fields:

        - `frequency` (string): `daily`, `weekly`, or `monthly`

        - `time_of_day` (string): `H:i` or `H:i:s`

        - `recipients` (array of valid emails, min 1)


        Optional fields:

        - `day_of_week` (0-6) when frequency is `weekly`

        - `day_of_month` (1-31) when frequency is `monthly`

        - `timezone` (string, default `UTC`)

        - `export_format` (`csv`, `xlsx`, `pdf`, default `csv`)

        - `is_active` (boolean, default true)


        Returns 201 with the schedule resource. Returns 403 if the caller is not the
        report owner.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                frequency:
                  type: string
                day_of_week:
                  type: integer
                time_of_day:
                  type: string
                timezone:
                  type: string
                export_format:
                  type: string
                recipients:
                  type: array
                  items:
                    type: string
                is_active:
                  type: boolean
              example:
                frequency: weekly
                day_of_week: 1
                time_of_day: 09:00
                timezone: America/New_York
                export_format: xlsx
                recipients:
                - alice@example.com
                - bob@example.com
                is_active: true
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: reports:write
      operationId: post-api-v2-custom-reports-id-schedules
  /api/v2/custom-reports/{id}/schedules/{id2}:
    put:
      tags:
      - Custom Report Builder
      summary: Update Schedule
      description: 'Update an existing schedule. All fields are optional (`sometimes`
        validation). `time_of_day` accepts both `H:i` and `H:i:s`; the server round-trips
        the value as `H:i:s` on reads, so re-submitting an unchanged time_of_day value
        from a prior GET works without 422 errors.


        :::info[Required scope: `reports:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Returns 404 if the schedule does not belong to the URL''s report. Returns
        403 if the caller is not the report owner.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                time_of_day:
                  type: string
                is_active:
                  type: boolean
              example:
                time_of_day: '10:30:00'
                is_active: false
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      - name: id2
        in: path
        required: true
        schema:
          type: string
        description: The id2 identifier
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: reports:write
      operationId: put-api-v2-custom-reports-id-schedules-id2
    delete:
      tags:
      - Custom Report Builder
      summary: Delete Schedule
      description: 'Delete a schedule. Returns 204 on success. Returns 404 if the
        schedule does not belong to the URL''s report. Returns 403 if the caller is
        not the report owner.


        :::info[Required scope: `reports:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      - name: id2
        in: path
        required: true
        schema:
          type: string
        description: The id2 identifier
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: reports:write
      operationId: delete-api-v2-custom-reports-id-schedules-id2
  /api/ebay:
    get:
      tags:
      - eBay
      summary: List eBay Integrations
      description: 'List every connected eBay integration instance on the account.
        Returns the full instance record for each connection, including its settings
        and sync state.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: requires a Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        environment:
                          type: string
                        name:
                          type: string
                        integration_id:
                          type: integer
                        connection_settings:
                          type: object
                          properties:
                            access_token:
                              type: string
                            refresh_token:
                              type: string
                        integration_settings:
                          type: object
                          properties:
                            start_date:
                              type: string
                            store_id:
                              type: integer
                            auto_link_products:
                              type: boolean
                            auto_create_products:
                              type: boolean
                            sales_nominal_code_id:
                              type: integer
                            cogs_nominal_code_id:
                              type: integer
                            shipping_revenue_nominal_code_id:
                              type: integer
                            shipping_refund_nominal_code_id:
                              type: integer
                            sales_returns_allowances_nominal_code_id:
                              type: integer
                            emailCustomers:
                              type: boolean
                            proforma_marketplace_cost_percentage:
                              type: number
                            proforma_payment_cost_percentage:
                              type: number
                            sync_sales_order_invoices_to_accounting:
                              type: boolean
                            sync_sales_credit_to_accounting:
                              type: boolean
                            pricing:
                              type: object
                              properties:
                                masterOfPrice:
                                  type: object
                                  properties:
                                    id:
                                      type: string
                                    name:
                                      type: string
                            inventory:
                              type: object
                              properties:
                                masterOfStock:
                                  type: string
                                selectedWarehouses:
                                  type: array
                        is_automatic_sync_enabled:
                          type: boolean
                        created_at:
                          type: string
                        updated_at:
                          type: string
                example:
                  data:
                  - id: 3
                    environment: production
                    name: eBay US Store
                    integration_id: 4
                    connection_settings:
                      access_token: v^1.1#i^1#p^3#EXAMPLE
                      refresh_token: v^1.1#i^1#r^1#EXAMPLE
                    integration_settings:
                      start_date: '2026-01-01 00:00:00'
                      store_id: 2
                      auto_link_products: true
                      auto_create_products: false
                      sales_nominal_code_id: 12
                      cogs_nominal_code_id: 15
                      shipping_revenue_nominal_code_id: 18
                      shipping_refund_nominal_code_id: 19
                      sales_returns_allowances_nominal_code_id: 21
                      emailCustomers: false
                      proforma_marketplace_cost_percentage: 12.9
                      proforma_payment_cost_percentage: 2.9
                      sync_sales_order_invoices_to_accounting: true
                      sync_sales_credit_to_accounting: true
                      pricing:
                        masterOfPrice:
                          id: neither
                          name: Neither
                      inventory:
                        masterOfStock: Neither
                        selectedWarehouses: []
                    is_automatic_sync_enabled: true
                    created_at: '2026-01-05T10:00:00.000000Z'
                    updated_at: '2026-07-06T18:15:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-ebay
    post:
      tags:
      - eBay
      summary: Create eBay Integration
      description: 'Create a new eBay integration instance. The response includes
        a redirect_url pointing to the eBay consent page; open it to authorize the
        connection. After authorization completes, listings and orders are automatically
        imported in the background.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Body fields:

        - name (string, required): Unique display name for the connection.

        - integration_id (integer, required): ID of the eBay integration definition.

        - integration_settings (object, required): Channel settings. Required keys:
        start_date (date string - orders created before this date are not imported),
        store_id (integer), auto_link_products (boolean), auto_create_products (boolean),
        sales_nominal_code_id, cogs_nominal_code_id, shipping_revenue_nominal_code_id,
        shipping_refund_nominal_code_id, sales_returns_allowances_nominal_code_id
        (integers or null). Optional keys: pricing (object with masterOfPrice {id,
        name} and pricing_tier_id), inventory (object with masterOfStock, selectedWarehouses),
        emailCustomers (boolean, default false), proforma_marketplace_cost_percentage
        (number or null), proforma_payment_cost_percentage (number or null), sync_sales_order_invoices_to_accounting
        (boolean, default true), sync_sales_credit_to_accounting (boolean, default
        true), batch_period_sales_order_fulfillments (string or null), batch_period_customer_returns
        (string or null).

        - connection_settings (object, optional): OAuth tokens (access_token, refresh_token,
        expiresAccessToken, expiresRefreshToken). Normally omitted - tokens are stored
        automatically when the OAuth authorization completes.

        - is_automatic_sync_enabled (boolean, optional, default false).

        - environment (string, optional): "production" or "sandbox".'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                integration_id:
                  type: integer
                is_automatic_sync_enabled:
                  type: boolean
                environment:
                  type: string
                integration_settings:
                  type: object
                  properties:
                    start_date:
                      type: string
                    store_id:
                      type: integer
                    auto_link_products:
                      type: boolean
                    auto_create_products:
                      type: boolean
                    sales_nominal_code_id:
                      type: integer
                    cogs_nominal_code_id:
                      type: integer
                    shipping_revenue_nominal_code_id:
                      type: integer
                    shipping_refund_nominal_code_id:
                      type: integer
                    sales_returns_allowances_nominal_code_id:
                      type: integer
                    emailCustomers:
                      type: boolean
                    sync_sales_order_invoices_to_accounting:
                      type: boolean
                    sync_sales_credit_to_accounting:
                      type: boolean
                    pricing:
                      type: object
                      properties:
                        masterOfPrice:
                          type: object
                          properties:
                            id:
                              type: string
                            name:
                              type: string
                    inventory:
                      type: object
                      properties:
                        masterOfStock:
                          type: string
                        selectedWarehouses:
                          type: array
              example:
                name: eBay US Store
                integration_id: 4
                is_automatic_sync_enabled: false
                environment: production
                integration_settings:
                  start_date: '2026-01-01'
                  store_id: 2
                  auto_link_products: true
                  auto_create_products: false
                  sales_nominal_code_id: 12
                  cogs_nominal_code_id: 15
                  shipping_revenue_nominal_code_id: 18
                  shipping_refund_nominal_code_id: 19
                  sales_returns_allowances_nominal_code_id: 21
                  emailCustomers: false
                  sync_sales_order_invoices_to_accounting: true
                  sync_sales_credit_to_accounting: true
                  pricing:
                    masterOfPrice:
                      id: neither
                      name: Neither
                  inventory:
                    masterOfStock: Neither
                    selectedWarehouses: []
      parameters: []
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      environment:
                        type: string
                      name:
                        type: string
                      integration_id:
                        type: integer
                      connection_settings:
                        type: object
                        properties:
                          access_token:
                            type: string
                          refresh_token:
                            type: string
                      integration_settings:
                        type: object
                        properties:
                          start_date:
                            type: string
                          store_id:
                            type: integer
                          auto_link_products:
                            type: boolean
                          auto_create_products:
                            type: boolean
                          sales_nominal_code_id:
                            type: integer
                          cogs_nominal_code_id:
                            type: integer
                          shipping_revenue_nominal_code_id:
                            type: integer
                          shipping_refund_nominal_code_id:
                            type: integer
                          sales_returns_allowances_nominal_code_id:
                            type: integer
                          emailCustomers:
                            type: boolean
                          proforma_marketplace_cost_percentage:
                            type: number
                          proforma_payment_cost_percentage:
                            type: number
                          sync_sales_order_invoices_to_accounting:
                            type: boolean
                          sync_sales_credit_to_accounting:
                            type: boolean
                          pricing:
                            type: object
                            properties:
                              masterOfPrice:
                                type: object
                                properties:
                                  id:
                                    type: string
                                  name:
                                    type: string
                          inventory:
                            type: object
                            properties:
                              masterOfStock:
                                type: string
                              selectedWarehouses:
                                type: array
                      is_automatic_sync_enabled:
                        type: boolean
                      created_at:
                        type: string
                      updated_at:
                        type: string
                  redirect_url:
                    type: string
                  status:
                    type: string
                example:
                  data:
                    id: 3
                    environment: production
                    name: eBay US Store
                    integration_id: 4
                    connection_settings:
                      access_token: v^1.1#i^1#p^3#EXAMPLE
                      refresh_token: v^1.1#i^1#r^1#EXAMPLE
                    integration_settings:
                      start_date: '2026-01-01 00:00:00'
                      store_id: 2
                      auto_link_products: true
                      auto_create_products: false
                      sales_nominal_code_id: 12
                      cogs_nominal_code_id: 15
                      shipping_revenue_nominal_code_id: 18
                      shipping_refund_nominal_code_id: 19
                      sales_returns_allowances_nominal_code_id: 21
                      emailCustomers: false
                      proforma_marketplace_cost_percentage: 12.9
                      proforma_payment_cost_percentage: 2.9
                      sync_sales_order_invoices_to_accounting: true
                      sync_sales_credit_to_accounting: true
                      pricing:
                        masterOfPrice:
                          id: neither
                          name: Neither
                      inventory:
                        masterOfStock: Neither
                        selectedWarehouses: []
                    is_automatic_sync_enabled: true
                    created_at: '2026-01-05T10:00:00.000000Z'
                    updated_at: '2026-07-06T18:15:00.000000Z'
                  redirect_url: https://auth.ebay.com/oauth2/authorize?client_id=EXAMPLE&redirect_uri=EXAMPLE&response_type=code&scope=https%3A%2F%2Fapi.ebay.com%2Foauth%2Fapi_scope&state=abc123
                  status: success
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      name:
                        type: array
                        items:
                          type: string
                example:
                  message: The name has already been taken.
                  errors:
                    name:
                    - The name has already been taken.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-ebay
  /api/ebay/{integrationInstance}:
    get:
      tags:
      - eBay
      summary: Get eBay Integration
      description: 'Get a single eBay integration instance, including its sales channel,
        store, and settings.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Path parameters:

        - integrationInstance (integer): The eBay integration instance ID.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_name:
                        type: string
                      sales_channel_id:
                        type: integer
                      store:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      environment:
                        type: string
                      name:
                        type: string
                      integration_id:
                        type: integer
                      connection_settings:
                        type: object
                        properties:
                          access_token:
                            type: string
                          refresh_token:
                            type: string
                          expiresAccessToken:
                            type: integer
                          expiresRefreshToken:
                            type: integer
                      integration_settings:
                        type: object
                        properties:
                          start_date:
                            type: string
                          store_id:
                            type: integer
                          auto_link_products:
                            type: boolean
                          auto_create_products:
                            type: boolean
                          sales_nominal_code_id:
                            type: integer
                          cogs_nominal_code_id:
                            type: integer
                          shipping_revenue_nominal_code_id:
                            type: integer
                          shipping_refund_nominal_code_id:
                            type: integer
                          sales_returns_allowances_nominal_code_id:
                            type: integer
                          emailCustomers:
                            type: boolean
                          proforma_marketplace_cost_percentage:
                            type: number
                          proforma_payment_cost_percentage:
                            type: number
                          sync_sales_order_invoices_to_accounting:
                            type: boolean
                          sync_sales_credit_to_accounting:
                            type: boolean
                          pricing:
                            type: object
                            properties:
                              masterOfPrice:
                                type: object
                                properties:
                                  id:
                                    type: string
                                  name:
                                    type: string
                          inventory:
                            type: object
                            properties:
                              masterOfStock:
                                type: string
                              selectedWarehouses:
                                type: array
                      is_automatic_sync_enabled:
                        type: boolean
                      created_at:
                        type: string
                      updated_at:
                        type: string
                  status:
                    type: string
                example:
                  data:
                    id: 3
                    integration_name: eBay
                    sales_channel_id: 9
                    store:
                      id: 2
                      name: Main Store
                    environment: production
                    name: eBay US Store
                    integration_id: 4
                    connection_settings:
                      access_token: v^1.1#i^1#p^3#EXAMPLE
                      refresh_token: v^1.1#i^1#r^1#EXAMPLE
                      expiresAccessToken: 1751851200
                      expiresRefreshToken: 1799942400
                    integration_settings:
                      start_date: '2026-01-01 00:00:00'
                      store_id: 2
                      auto_link_products: true
                      auto_create_products: false
                      sales_nominal_code_id: 12
                      cogs_nominal_code_id: 15
                      shipping_revenue_nominal_code_id: 18
                      shipping_refund_nominal_code_id: 19
                      sales_returns_allowances_nominal_code_id: 21
                      emailCustomers: false
                      proforma_marketplace_cost_percentage: 12.9
                      proforma_payment_cost_percentage: 2.9
                      sync_sales_order_invoices_to_accounting: true
                      sync_sales_credit_to_accounting: true
                      pricing:
                        masterOfPrice:
                          id: neither
                          name: Neither
                      inventory:
                        masterOfStock: Neither
                        selectedWarehouses: []
                    is_automatic_sync_enabled: true
                    created_at: '2026-01-05T10:00:00.000000Z'
                    updated_at: '2026-07-06T18:15:00.000000Z'
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-ebay-integrationinstance
    put:
      tags:
      - eBay
      summary: Update eBay Integration
      description: 'Update an eBay integration instance. With PUT, a provided integration_settings
        object replaces the stored settings; use PATCH for merge semantics.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        All body fields are optional:

        - name (string): New display name.

        - integration_settings (object): Same shape as on create; every key is optional.

        - connection_settings (object): OAuth token fields.

        - is_automatic_sync_enabled (boolean): Toggle scheduled background sync.


        Side effects: changing start_date re-normalizes the stored date; changing
        store_id updates the linked sales channel; changing the pricing master triggers
        a price re-cache; changing inventory settings invalidates the inventory cache
        so quantities are recalculated.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                is_automatic_sync_enabled:
                  type: boolean
                integration_settings:
                  type: object
                  properties:
                    start_date:
                      type: string
                    store_id:
                      type: integer
                    auto_link_products:
                      type: boolean
                    auto_create_products:
                      type: boolean
                    sales_nominal_code_id:
                      type: integer
                    cogs_nominal_code_id:
                      type: integer
                    shipping_revenue_nominal_code_id:
                      type: integer
                    shipping_refund_nominal_code_id:
                      type: integer
                    sales_returns_allowances_nominal_code_id:
                      type: integer
                    inventory:
                      type: object
                      properties:
                        masterOfStock:
                          type: string
                        selectedWarehouses:
                          type: array
                          items:
                            type: integer
              example:
                name: eBay US Store
                is_automatic_sync_enabled: true
                integration_settings:
                  start_date: '2026-01-01'
                  store_id: 2
                  auto_link_products: true
                  auto_create_products: false
                  sales_nominal_code_id: 12
                  cogs_nominal_code_id: 15
                  shipping_revenue_nominal_code_id: 18
                  shipping_refund_nominal_code_id: 19
                  sales_returns_allowances_nominal_code_id: 21
                  inventory:
                    masterOfStock: SKU
                    selectedWarehouses:
                    - 1
                    - 2
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_name:
                        type: string
                      sales_channel_id:
                        type: integer
                      store:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      environment:
                        type: string
                      name:
                        type: string
                      integration_id:
                        type: integer
                      connection_settings:
                        type: object
                        properties:
                          access_token:
                            type: string
                          refresh_token:
                            type: string
                          expiresAccessToken:
                            type: integer
                          expiresRefreshToken:
                            type: integer
                      integration_settings:
                        type: object
                        properties:
                          start_date:
                            type: string
                          store_id:
                            type: integer
                          auto_link_products:
                            type: boolean
                          auto_create_products:
                            type: boolean
                          sales_nominal_code_id:
                            type: integer
                          cogs_nominal_code_id:
                            type: integer
                          shipping_revenue_nominal_code_id:
                            type: integer
                          shipping_refund_nominal_code_id:
                            type: integer
                          sales_returns_allowances_nominal_code_id:
                            type: integer
                          emailCustomers:
                            type: boolean
                          proforma_marketplace_cost_percentage:
                            type: number
                          proforma_payment_cost_percentage:
                            type: number
                          sync_sales_order_invoices_to_accounting:
                            type: boolean
                          sync_sales_credit_to_accounting:
                            type: boolean
                          pricing:
                            type: object
                            properties:
                              masterOfPrice:
                                type: object
                                properties:
                                  id:
                                    type: string
                                  name:
                                    type: string
                          inventory:
                            type: object
                            properties:
                              masterOfStock:
                                type: string
                              selectedWarehouses:
                                type: array
                      is_automatic_sync_enabled:
                        type: boolean
                      created_at:
                        type: string
                      updated_at:
                        type: string
                  status:
                    type: string
                example:
                  data:
                    id: 3
                    integration_name: eBay
                    sales_channel_id: 9
                    store:
                      id: 2
                      name: Main Store
                    environment: production
                    name: eBay US Store
                    integration_id: 4
                    connection_settings:
                      access_token: v^1.1#i^1#p^3#EXAMPLE
                      refresh_token: v^1.1#i^1#r^1#EXAMPLE
                      expiresAccessToken: 1751851200
                      expiresRefreshToken: 1799942400
                    integration_settings:
                      start_date: '2026-01-01 00:00:00'
                      store_id: 2
                      auto_link_products: true
                      auto_create_products: false
                      sales_nominal_code_id: 12
                      cogs_nominal_code_id: 15
                      shipping_revenue_nominal_code_id: 18
                      shipping_refund_nominal_code_id: 19
                      sales_returns_allowances_nominal_code_id: 21
                      emailCustomers: false
                      proforma_marketplace_cost_percentage: 12.9
                      proforma_payment_cost_percentage: 2.9
                      sync_sales_order_invoices_to_accounting: true
                      sync_sales_credit_to_accounting: true
                      pricing:
                        masterOfPrice:
                          id: neither
                          name: Neither
                      inventory:
                        masterOfStock: Neither
                        selectedWarehouses: []
                    is_automatic_sync_enabled: true
                    created_at: '2026-01-05T10:00:00.000000Z'
                    updated_at: '2026-07-06T18:15:00.000000Z'
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-ebay-integrationinstance
    patch:
      tags:
      - eBay
      summary: Partially Update eBay Integration
      description: 'Partially update an eBay integration instance using merge semantics:
        provided integration_settings and connection_settings keys are deep-merged
        into the stored values, so nested settings you omit are preserved. Exception:
        the inventory object is always replaced in full when provided (its warehouse
        and location lists are positional arrays).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Accepts the same body fields as the PUT update; all fields are optional.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                integration_settings:
                  type: object
                  properties:
                    inventory:
                      type: object
                      properties:
                        masterOfStock:
                          type: string
                        selectedWarehouses:
                          type: array
                          items:
                            type: integer
              example:
                integration_settings:
                  inventory:
                    masterOfStock: SKU
                    selectedWarehouses:
                    - 1
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_name:
                        type: string
                      sales_channel_id:
                        type: integer
                      store:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      environment:
                        type: string
                      name:
                        type: string
                      integration_id:
                        type: integer
                      connection_settings:
                        type: object
                        properties:
                          access_token:
                            type: string
                          refresh_token:
                            type: string
                          expiresAccessToken:
                            type: integer
                          expiresRefreshToken:
                            type: integer
                      integration_settings:
                        type: object
                        properties:
                          start_date:
                            type: string
                          store_id:
                            type: integer
                          auto_link_products:
                            type: boolean
                          auto_create_products:
                            type: boolean
                          sales_nominal_code_id:
                            type: integer
                          cogs_nominal_code_id:
                            type: integer
                          shipping_revenue_nominal_code_id:
                            type: integer
                          shipping_refund_nominal_code_id:
                            type: integer
                          sales_returns_allowances_nominal_code_id:
                            type: integer
                          emailCustomers:
                            type: boolean
                          proforma_marketplace_cost_percentage:
                            type: number
                          proforma_payment_cost_percentage:
                            type: number
                          sync_sales_order_invoices_to_accounting:
                            type: boolean
                          sync_sales_credit_to_accounting:
                            type: boolean
                          pricing:
                            type: object
                            properties:
                              masterOfPrice:
                                type: object
                                properties:
                                  id:
                                    type: string
                                  name:
                                    type: string
                          inventory:
                            type: object
                            properties:
                              masterOfStock:
                                type: string
                              selectedWarehouses:
                                type: array
                      is_automatic_sync_enabled:
                        type: boolean
                      created_at:
                        type: string
                      updated_at:
                        type: string
                  status:
                    type: string
                example:
                  data:
                    id: 3
                    integration_name: eBay
                    sales_channel_id: 9
                    store:
                      id: 2
                      name: Main Store
                    environment: production
                    name: eBay US Store
                    integration_id: 4
                    connection_settings:
                      access_token: v^1.1#i^1#p^3#EXAMPLE
                      refresh_token: v^1.1#i^1#r^1#EXAMPLE
                      expiresAccessToken: 1751851200
                      expiresRefreshToken: 1799942400
                    integration_settings:
                      start_date: '2026-01-01 00:00:00'
                      store_id: 2
                      auto_link_products: true
                      auto_create_products: false
                      sales_nominal_code_id: 12
                      cogs_nominal_code_id: 15
                      shipping_revenue_nominal_code_id: 18
                      shipping_refund_nominal_code_id: 19
                      sales_returns_allowances_nominal_code_id: 21
                      emailCustomers: false
                      proforma_marketplace_cost_percentage: 12.9
                      proforma_payment_cost_percentage: 2.9
                      sync_sales_order_invoices_to_accounting: true
                      sync_sales_credit_to_accounting: true
                      pricing:
                        masterOfPrice:
                          id: neither
                          name: Neither
                      inventory:
                        masterOfStock: Neither
                        selectedWarehouses: []
                    is_automatic_sync_enabled: true
                    created_at: '2026-01-05T10:00:00.000000Z'
                    updated_at: '2026-07-06T18:15:00.000000Z'
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: patch-api-ebay-integrationinstance
    delete:
      tags:
      - eBay
      summary: Delete eBay Integration
      description: 'Delete an eBay integration instance. The deletion runs as a background
        job that removes the connection and its channel data. Returns 204 immediately
        after the job is queued.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Path parameters:

        - integrationInstance (integer): The eBay integration instance ID.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '204':
          description: No Content
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties: {}
                example: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-ebay-integrationinstance
  /api/ebay/{integrationInstance}/get-authorization-url:
    get:
      tags:
      - eBay
      summary: Get eBay Authorization URL
      description: 'Get the eBay OAuth consent URL for this integration instance.
        Open the returned URL in a browser to grant (or re-grant) access. Use this
        to reconnect an integration whose refresh token has expired or been revoked.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      authorization_url:
                        type: string
                  status:
                    type: string
                example:
                  data:
                    authorization_url: https://auth.ebay.com/oauth2/authorize?client_id=EXAMPLE&redirect_uri=EXAMPLE&response_type=code&scope=https%3A%2F%2Fapi.ebay.com%2Foauth%2Fapi_scope&state=abc123
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-ebay-integrationinstance-get-authorization-url
  /api/ebay/{integrationInstance}/activity-log:
    get:
      tags:
      - eBay
      summary: List eBay Integration Activity Log
      description: 'List the audit history of eBay order records belonging to this
        integration instance, most recent first. Each entry describes a create/update
        event, the changed attributes, and who (or what) caused it.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Filters:

        - filter[search]: matches the causer name, event name, or recorded properties.

        - filter[event]: exact event name (e.g. created, updated).

        - filter[source]: origin of the change (e.g. sync).

        - filter[batch_uuid]: all entries recorded by one batch operation.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        description:
                          type: string
                        event:
                          type: string
                        subject_type:
                          type: string
                        subject_id:
                          type: integer
                        properties:
                          type: object
                          properties:
                            attributes:
                              type: object
                              properties:
                                orderFulfillmentStatus:
                                  type: string
                            old:
                              type: object
                              properties:
                                orderFulfillmentStatus:
                                  type: string
                            source:
                              type: string
                        causer_name:
                          type: string
                        created_at:
                          type: string
                        batch_uuid:
                          type: string
                          nullable: true
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                    items:
                      type: object
                      properties:
                        url:
                          type: string
                          nullable: true
                        label:
                          type: string
                        active:
                          type: boolean
                  next_page_url:
                    type: string
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 90211
                    description: updated
                    event: updated
                    subject_type: EbayOrder
                    subject_id: 9101
                    properties:
                      attributes:
                        orderFulfillmentStatus: FULFILLED
                      old:
                        orderFulfillmentStatus: IN_PROGRESS
                      source: sync
                    causer_name: Jane Smith
                    created_at: '2026-06-29T10:11:02.000000Z'
                    batch_uuid: null
                  first_page_url: '{{base_url}}/api/ebay/3/activity-log?page=1'
                  from: 1
                  last_page: 5
                  last_page_url: '{{base_url}}/api/ebay/3/activity-log?page=5'
                  links:
                  - url: null
                    label: '&laquo; Previous'
                    active: false
                  - url: '{{base_url}}/api/ebay/3/activity-log?page=1'
                    label: '1'
                    active: true
                  - url: '{{base_url}}/api/ebay/3/activity-log?page=2'
                    label: Next &raquo;
                    active: false
                  next_page_url: '{{base_url}}/api/ebay/3/activity-log?page=2'
                  path: '{{base_url}}/api/ebay/3/activity-log'
                  per_page: 15
                  prev_page_url: null
                  to: 1
                  total: 48
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-ebay-integrationinstance-activity-log
  /api/ebay/{integrationInstance}/products/{product}:
    get:
      tags:
      - eBay
      summary: Get eBay Listing
      description: 'Get a single locally-synced eBay listing, including its mapped
        product (when mapped) and the raw listing payload as last fetched from eBay.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Path parameters:

        - integrationInstance (integer): The eBay integration instance ID.

        - product (integer): The eBay listing record ID.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: product
        in: path
        schema:
          type: string
        required: true
        description: The product ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      product_listing_id:
                        type: integer
                      product:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          sku:
                            type: string
                          default_financial_line_type_id:
                            type: integer
                          default_financial_line_type:
                            type: object
                            properties:
                              id:
                                type: integer
                              name:
                                type: string
                              classification:
                                type: string
                          listing_id:
                            type: integer
                      subscription_offering:
                        type: string
                        nullable: true
                      mapped_at:
                        type: string
                      mapped_sku:
                        type: string
                      json_object:
                        type: object
                        properties:
                          ItemID:
                            type: string
                          Title:
                            type: string
                          PictureDetails:
                            type: object
                            properties:
                              GalleryURL:
                                type: string
                      image_url:
                        type: string
                      ItemID:
                        type: string
                      SKU:
                        type: string
                      ListingDuration:
                        type: string
                      ListingType:
                        type: string
                      Title:
                        type: string
                      QuantityAvailable:
                        type: integer
                      CurrentPriceValue:
                        type: number
                      CurrentPriceCurrency:
                        type: string
                      ListingStatus:
                        type: string
                      BidCount:
                        type: string
                        nullable: true
                      EndingReason:
                        type: string
                        nullable: true
                      WatchCount:
                        type: integer
                      StartTime:
                        type: string
                      StartTimeUtc:
                        type: string
                      EndTime:
                        type: string
                        nullable: true
                      EndTimeUtc:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                  status:
                    type: string
                example:
                  data:
                    id: 8121
                    integration_instance_id: 3
                    product_listing_id: 452
                    product:
                      id: 501
                      name: Acme Widget - Blue
                      sku: WIDGET-BLUE
                      default_financial_line_type_id: 2
                      default_financial_line_type:
                        id: 2
                        name: Product Sales
                        classification: revenue
                      listing_id: 452
                    subscription_offering: null
                    mapped_at: '2026-05-20T09:12:44.000000Z'
                    mapped_sku: WIDGET-BLUE
                    json_object:
                      ItemID: '110552983245'
                      Title: Acme Widget - Blue
                      PictureDetails:
                        GalleryURL: https://i.ebayimg.com/images/g/abc/s-l500.jpg
                    image_url: https://i.ebayimg.com/images/g/abc/s-l500.jpg
                    ItemID: '110552983245'
                    SKU: WIDGET-BLUE
                    ListingDuration: GTC
                    ListingType: FixedPriceItem
                    Title: Acme Widget - Blue
                    QuantityAvailable: 25
                    CurrentPriceValue: 19.99
                    CurrentPriceCurrency: USD
                    ListingStatus: Active
                    BidCount: null
                    EndingReason: null
                    WatchCount: 12
                    StartTime: '2026-02-01T00:00:00.000Z'
                    StartTimeUtc: '2026-02-01T00:00:00.000000Z'
                    EndTime: null
                    EndTimeUtc: null
                    created_at: '2026-02-01T00:05:00.000000Z'
                    updated_at: '2026-07-05T00:05:00.000000Z'
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-ebay-integrationinstance-products-product
  /api/ebay/{integrationInstance}/products/{product}/orders:
    get:
      tags:
      - eBay
      summary: List Orders for eBay Listing
      description: 'List eBay orders that contain the given listing, most recent first.
        Returns 403 when the listing does not belong to the integration instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: product
        in: path
        schema:
          type: string
        required: true
        description: The product ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        sku_sales_order:
                          type: object
                          properties:
                            id:
                              type: integer
                            number:
                              type: string
                            order_status:
                              type: string
                            fulfillment_status:
                              type: string
                            payment_status:
                              type: string
                        json_object:
                          type: object
                          properties:
                            orderId:
                              type: string
                            buyer:
                              type: object
                              properties:
                                username:
                                  type: string
                        orderId:
                          type: string
                        salesRecordReference:
                          type: string
                        orderPaymentStatus:
                          type: string
                        orderFulfillmentStatus:
                          type: string
                        totalValue:
                          type: number
                        totalCurrency:
                          type: string
                        totalMarketplaceFeeValue:
                          type: number
                        totalMarketplaceFeeCurrency:
                          type: string
                        creationDateUtc:
                          type: string
                        lastModifiedDateUtc:
                          type: string
                        error_log:
                          type: string
                          nullable: true
                        archived_at:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - id: 9101
                    integration_instance_id: 3
                    sku_sales_order:
                      id: 7788
                      number: SO-10234
                      order_status: completed
                      fulfillment_status: fulfilled
                      payment_status: paid
                    json_object:
                      orderId: 12-34567-89012
                      buyer:
                        username: acme_buyer
                    orderId: 12-34567-89012
                    salesRecordReference: '1287'
                    orderPaymentStatus: PAID
                    orderFulfillmentStatus: FULFILLED
                    totalValue: 45.98
                    totalCurrency: USD
                    totalMarketplaceFeeValue: 5.98
                    totalMarketplaceFeeCurrency: USD
                    creationDateUtc: '2026-06-28T15:04:11.000000Z'
                    lastModifiedDateUtc: '2026-06-29T10:11:00.000000Z'
                    error_log: null
                    archived_at: null
                    created_at: '2026-06-28T15:10:00.000000Z'
                    updated_at: '2026-06-29T10:12:00.000000Z'
                  current_page: 1
                  last_page: 2
                  per_page: 10
                  total: 14
                  from: 1
                  to: 10
        '403':
          description: Forbidden
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: Product does not belong to this integration instance
        '429': *id001
        '401': *id002
        '404': *id004
      operationId: get-api-ebay-integrationinstance-products-product-orders
  /api/ebay/{integrationInstance}/legacy-products/latest-sync-info:
    get:
      tags:
      - eBay
      summary: Get eBay Listing Sync Status
      description: 'Get summary statistics about the locally-synced eBay listings
        for an integration instance: the most recently updated listing, total listing
        count, and how many listings are mapped to products.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      latest_product_title:
                        type: string
                      latest_product_date:
                        type: string
                      total_products:
                        type: integer
                      mapped_products:
                        type: integer
                      unmapped_products:
                        type: integer
                example:
                  data:
                    latest_product_title: Acme Widget - Blue
                    latest_product_date: '2026-07-05T00:05:00.000000Z'
                    total_products: 1245
                    mapped_products: 1100
                    unmapped_products: 145
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-ebay-integrationinstance-legacy-products-latest-sync-info
  /api/ebay/{integrationInstance}/products/refresh:
    post:
      tags:
      - eBay
      summary: Refresh eBay Listings
      description: 'Queue a background refresh that re-fetches listings from eBay
        for this integration instance. Returns immediately; listings are updated as
        the queued work completes. For a refresh whose progress can be polled, use
        the tracked refresh endpoint instead.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  status:
                    type: string
                example:
                  message: Added to queue, products will be refreshed shortly.
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-ebay-integrationinstance-products-refresh
  /api/ebay/{integrationInstance}/legacy-products/refresh-tracked:
    post:
      tags:
      - eBay
      summary: Start Tracked eBay Listing Refresh
      description: 'Start a tracked background refresh of listings from eBay. Returns
        a tracked_job_log_id whose progress can be polled while the refresh runs.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                  status:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 2210
                  message: Product refresh job has been queued
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-ebay-integrationinstance-legacy-products-refresh-tracked
  /api/ebay/{integrationInstance}/products/{product}/map:
    post:
      tags:
      - eBay
      summary: Map eBay Listing to Product
      description: 'Map a single eBay listing to an existing product or subscription
        offering. Creates (or updates) the product listing link and automatically
        queues re-mapping of any historical order lines that referenced the listing.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Body fields (exactly one of the two is required):

        - product_id (integer): ID of the product to map to. Required without subscription_offering_id.

        - subscription_offering_id (integer): ID of the subscription offering to map
        to. Required without product_id.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                product_id:
                  type: integer
              example:
                product_id: 501
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: product
        in: path
        schema:
          type: string
        required: true
        description: The product ID.
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      product_listing_id:
                        type: integer
                      product:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          sku:
                            type: string
                          default_financial_line_type_id:
                            type: integer
                          default_financial_line_type:
                            type: object
                            properties:
                              id:
                                type: integer
                              name:
                                type: string
                              classification:
                                type: string
                          listing_id:
                            type: integer
                      subscription_offering:
                        type: string
                        nullable: true
                      mapped_at:
                        type: string
                      mapped_sku:
                        type: string
                      json_object:
                        type: object
                        properties:
                          ItemID:
                            type: string
                          Title:
                            type: string
                          PictureDetails:
                            type: object
                            properties:
                              GalleryURL:
                                type: string
                      image_url:
                        type: string
                      ItemID:
                        type: string
                      SKU:
                        type: string
                      ListingDuration:
                        type: string
                      ListingType:
                        type: string
                      Title:
                        type: string
                      QuantityAvailable:
                        type: integer
                      CurrentPriceValue:
                        type: number
                      CurrentPriceCurrency:
                        type: string
                      ListingStatus:
                        type: string
                      BidCount:
                        type: string
                        nullable: true
                      EndingReason:
                        type: string
                        nullable: true
                      WatchCount:
                        type: integer
                      StartTime:
                        type: string
                      StartTimeUtc:
                        type: string
                      EndTime:
                        type: string
                        nullable: true
                      EndTimeUtc:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 8121
                    integration_instance_id: 3
                    product_listing_id: 452
                    product:
                      id: 501
                      name: Acme Widget - Blue
                      sku: WIDGET-BLUE
                      default_financial_line_type_id: 2
                      default_financial_line_type:
                        id: 2
                        name: Product Sales
                        classification: revenue
                      listing_id: 452
                    subscription_offering: null
                    mapped_at: '2026-05-20T09:12:44.000000Z'
                    mapped_sku: WIDGET-BLUE
                    json_object:
                      ItemID: '110552983245'
                      Title: Acme Widget - Blue
                      PictureDetails:
                        GalleryURL: https://i.ebayimg.com/images/g/abc/s-l500.jpg
                    image_url: https://i.ebayimg.com/images/g/abc/s-l500.jpg
                    ItemID: '110552983245'
                    SKU: WIDGET-BLUE
                    ListingDuration: GTC
                    ListingType: FixedPriceItem
                    Title: Acme Widget - Blue
                    QuantityAvailable: 25
                    CurrentPriceValue: 19.99
                    CurrentPriceCurrency: USD
                    ListingStatus: Active
                    BidCount: null
                    EndingReason: null
                    WatchCount: 12
                    StartTime: '2026-02-01T00:00:00.000Z'
                    StartTimeUtc: '2026-02-01T00:00:00.000000Z'
                    EndTime: null
                    EndTimeUtc: null
                    created_at: '2026-02-01T00:05:00.000000Z'
                    updated_at: '2026-07-05T00:05:00.000000Z'
                  message: Product mapped successfully.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      product_id:
                        type: array
                        items:
                          type: string
                example:
                  message: The product id field is required when subscription offering
                    id is not present.
                  errors:
                    product_id:
                    - The product id field is required when subscription offering
                      id is not present.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-ebay-integrationinstance-products-product-map
    delete:
      tags:
      - eBay
      summary: Unmap eBay Listing
      description: 'Remove the product mapping from an eBay listing. The listing itself
        is untouched; only the link to the product is deleted. Returns 422 when the
        listing is not currently mapped.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: product
        in: path
        schema:
          type: string
        required: true
        description: The product ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      product_listing_id:
                        type: string
                        nullable: true
                      product:
                        type: string
                        nullable: true
                      subscription_offering:
                        type: string
                        nullable: true
                      mapped_at:
                        type: string
                        nullable: true
                      mapped_sku:
                        type: string
                        nullable: true
                      json_object:
                        type: object
                        properties:
                          ItemID:
                            type: string
                          Title:
                            type: string
                          PictureDetails:
                            type: object
                            properties:
                              GalleryURL:
                                type: string
                      image_url:
                        type: string
                      ItemID:
                        type: string
                      SKU:
                        type: string
                      ListingDuration:
                        type: string
                      ListingType:
                        type: string
                      Title:
                        type: string
                      QuantityAvailable:
                        type: integer
                      CurrentPriceValue:
                        type: number
                      CurrentPriceCurrency:
                        type: string
                      ListingStatus:
                        type: string
                      BidCount:
                        type: string
                        nullable: true
                      EndingReason:
                        type: string
                        nullable: true
                      WatchCount:
                        type: integer
                      StartTime:
                        type: string
                      StartTimeUtc:
                        type: string
                      EndTime:
                        type: string
                        nullable: true
                      EndTimeUtc:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 8121
                    integration_instance_id: 3
                    product_listing_id: null
                    product: null
                    subscription_offering: null
                    mapped_at: null
                    mapped_sku: null
                    json_object:
                      ItemID: '110552983245'
                      Title: Acme Widget - Blue
                      PictureDetails:
                        GalleryURL: https://i.ebayimg.com/images/g/abc/s-l500.jpg
                    image_url: https://i.ebayimg.com/images/g/abc/s-l500.jpg
                    ItemID: '110552983245'
                    SKU: WIDGET-BLUE
                    ListingDuration: GTC
                    ListingType: FixedPriceItem
                    Title: Acme Widget - Blue
                    QuantityAvailable: 25
                    CurrentPriceValue: 19.99
                    CurrentPriceCurrency: USD
                    ListingStatus: Active
                    BidCount: null
                    EndingReason: null
                    WatchCount: 12
                    StartTime: '2026-02-01T00:00:00.000Z'
                    StartTimeUtc: '2026-02-01T00:00:00.000000Z'
                    EndTime: null
                    EndTimeUtc: null
                    created_at: '2026-02-01T00:05:00.000000Z'
                    updated_at: '2026-07-05T00:05:00.000000Z'
                  message: Product unmapped successfully.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: Product is not mapped.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-ebay-integrationinstance-products-product-map
  /api/ebay/{integrationInstance}/products/map:
    put:
      tags:
      - eBay
      summary: Bulk Map eBay Listings
      description: "Map multiple eBay listings to products in one call by SKU.\n\n\
        :::info[Authorization]\nAny valid API token can call this endpoint — no specific\
        \ scope required. [Manage tokens](https://app.sku.io/settings/api).\n:::\n\
        \nBody fields:\n- mapping (array, required, min 1): One entry per listing\
        \ to map. Each entry:\n  - sales_channel_listing_id (string, required): The\
        \ eBay item ID of the listing.\n  - mapped_sku (string or null): SKU of the\
        \ product to map to. Pass null to leave unmapped.\n  - product_listing_id\
        \ (integer, optional): Existing listing-link ID to update.\n  - subscription_offering_id\
        \ (integer, optional): Map to a subscription offering instead of a product."
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                mapping:
                  type: array
                  items:
                    type: object
                    properties:
                      sales_channel_listing_id:
                        type: string
                      mapped_sku:
                        type: string
              example:
                mapping:
                - sales_channel_listing_id: '110552983245'
                  mapped_sku: WIDGET-BLUE
                - sales_channel_listing_id: '110552983299'
                  mapped_sku: WIDGET-RED
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: string
                  status:
                    type: string
                example:
                  data: Successfully mapped sales channel products to sku products
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-ebay-integrationinstance-products-map
  /api/ebay/{integrationInstance}/products/import-mappings:
    post:
      tags:
      - eBay
      summary: Import eBay Listing Mappings
      description: 'Queue a background import of listing-to-product mappings from
        a previously uploaded CSV file. The CSV must contain the eBay item identifier
        column and the SKU to map each listing to.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Body fields:

        - original_name (string, required): The original file name of the uploaded
        CSV.

        - stored_name (string, required): The storage name returned by the file upload.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                original_name:
                  type: string
                stored_name:
                  type: string
              example:
                original_name: ebay-mappings.csv
                stored_name: imports/tmp/ebay-mappings-8f3a.csv
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  status:
                    type: string
                example:
                  message: Added to queue, mappings will be imported shortly.
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-ebay-integrationinstance-products-import-mappings
  /api/ebay/{integrationInstance}/products/{product}/create-sku-product:
    post:
      tags:
      - eBay
      summary: Create Product from eBay Listing
      description: 'Create a product from a single eBay listing and map the listing
        to it. If a product with the listing SKU already exists, the listing is linked
        to that product instead of creating a duplicate (linked_existing is true in
        the response). Returns 422 when the listing is already mapped.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: product
        in: path
        schema:
          type: string
        required: true
        description: The product ID.
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      product_listing_id:
                        type: integer
                      product:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          sku:
                            type: string
                          default_financial_line_type_id:
                            type: integer
                          default_financial_line_type:
                            type: object
                            properties:
                              id:
                                type: integer
                              name:
                                type: string
                              classification:
                                type: string
                          listing_id:
                            type: integer
                      subscription_offering:
                        type: string
                        nullable: true
                      mapped_at:
                        type: string
                      mapped_sku:
                        type: string
                      json_object:
                        type: object
                        properties:
                          ItemID:
                            type: string
                          Title:
                            type: string
                          PictureDetails:
                            type: object
                            properties:
                              GalleryURL:
                                type: string
                      image_url:
                        type: string
                      ItemID:
                        type: string
                      SKU:
                        type: string
                      ListingDuration:
                        type: string
                      ListingType:
                        type: string
                      Title:
                        type: string
                      QuantityAvailable:
                        type: integer
                      CurrentPriceValue:
                        type: number
                      CurrentPriceCurrency:
                        type: string
                      ListingStatus:
                        type: string
                      BidCount:
                        type: string
                        nullable: true
                      EndingReason:
                        type: string
                        nullable: true
                      WatchCount:
                        type: integer
                      StartTime:
                        type: string
                      StartTimeUtc:
                        type: string
                      EndTime:
                        type: string
                        nullable: true
                      EndTimeUtc:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                  linked_existing:
                    type: boolean
                  message:
                    type: string
                example:
                  data:
                    id: 8121
                    integration_instance_id: 3
                    product_listing_id: 452
                    product:
                      id: 501
                      name: Acme Widget - Blue
                      sku: WIDGET-BLUE
                      default_financial_line_type_id: 2
                      default_financial_line_type:
                        id: 2
                        name: Product Sales
                        classification: revenue
                      listing_id: 452
                    subscription_offering: null
                    mapped_at: '2026-05-20T09:12:44.000000Z'
                    mapped_sku: WIDGET-BLUE
                    json_object:
                      ItemID: '110552983245'
                      Title: Acme Widget - Blue
                      PictureDetails:
                        GalleryURL: https://i.ebayimg.com/images/g/abc/s-l500.jpg
                    image_url: https://i.ebayimg.com/images/g/abc/s-l500.jpg
                    ItemID: '110552983245'
                    SKU: WIDGET-BLUE
                    ListingDuration: GTC
                    ListingType: FixedPriceItem
                    Title: Acme Widget - Blue
                    QuantityAvailable: 25
                    CurrentPriceValue: 19.99
                    CurrentPriceCurrency: USD
                    ListingStatus: Active
                    BidCount: null
                    EndingReason: null
                    WatchCount: 12
                    StartTime: '2026-02-01T00:00:00.000Z'
                    StartTimeUtc: '2026-02-01T00:00:00.000000Z'
                    EndTime: null
                    EndTimeUtc: null
                    created_at: '2026-02-01T00:05:00.000000Z'
                    updated_at: '2026-07-05T00:05:00.000000Z'
                  linked_existing: false
                  message: SKU product created and mapped successfully.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: Product is already mapped. Unmap it first.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-ebay-integrationinstance-products-product-create-sku-product
  /api/ebay/{integrationInstance}/products/create-sku-products:
    post:
      tags:
      - eBay
      summary: Bulk Create Products from eBay Listings
      description: 'Queue background creation of products from eBay listings. Each
        targeted listing that resolves to a new SKU creates a product and maps the
        listing to it.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Body fields:

        - create_all_products (boolean, required): When true, targets every unmapped
        listing on the instance.

        - ids (array of integers): Listing IDs to create products for. Required when
        create_all_products is false and no filters are given.

        - mappings (array, optional): Field mappings used to build the new products.
        Each entry: listing_field (string), sku_field (string), parsers (array).

        - initial_mapping (boolean, optional, default false).


        Returns 400 when a targeted listing has no SKU to build a product from.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                create_all_products:
                  type: boolean
                ids:
                  type: array
                  items:
                    type: integer
                initial_mapping:
                  type: boolean
              example:
                create_all_products: false
                ids:
                - 8121
                - 8122
                initial_mapping: false
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  status:
                    type: string
                example:
                  message: Added to queue, products will be created shortly.
                  status: success
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: object
                    properties:
                      apiErrors:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: string
                              nullable: true
                  message:
                    type: string
                  status:
                    type: string
                example:
                  errors:
                    apiErrors:
                    - message: The listing 110552983245 has no SKU.
                      code: Missing SKU
                      data: null
                  message: The listing 110552983245 has no SKU.
                  status: failure
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-ebay-integrationinstance-products-create-sku-products
  /api/ebay/{integrationInstance}/products/archive:
    put:
      tags:
      - eBay
      summary: Bulk Archive eBay Listings
      description: 'Archive eBay listings. Listings that have channel orders are silently
        skipped (use the archiveable check to find out which ones qualify first).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Body fields:

        - ids (array of integers): Listing IDs to target. Required unless mode is
        "all".

        - mode (string): Pass "all" to target every listing on the integration instance
        instead of an explicit ID list.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 8121
                - 8122
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  status:
                    type: string
                example:
                  message: Products archived successfully.
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-ebay-integrationinstance-products-archive
  /api/ebay/{integrationInstance}/products/unarchive:
    put:
      tags:
      - eBay
      summary: Bulk Unarchive eBay Listings
      description: 'Restore previously archived eBay listings.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Body fields:

        - ids (array of integers): Listing IDs to target. Required unless mode is
        "all".

        - mode (string): Pass "all" to target every listing on the integration instance
        instead of an explicit ID list.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 8121
                - 8122
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  status:
                    type: string
                example:
                  message: Products unarchived successfully.
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-ebay-integrationinstance-products-unarchive
  /api/ebay/{integrationInstance}/products/archiveable:
    post:
      tags:
      - eBay
      summary: Check eBay Listings Archiveable
      description: 'Check which eBay listings can be archived. A listing with channel
        orders cannot be archived; the response gives a per-listing verdict and reason.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Body fields:

        - ids (array of integers): Listing IDs to target. Required unless mode is
        "all".

        - mode (string): Pass "all" to target every listing on the integration instance
        instead of an explicit ID list.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 8121
                - 8122
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        archiveable:
                          type: boolean
                        reason:
                          type: boolean
                  status:
                    type: string
                example:
                  data:
                  - id: 8121
                    archiveable: true
                    reason: false
                  - id: 8122
                    archiveable: false
                    reason: Sales Channel Product has Sales Channel Orders
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-ebay-integrationinstance-products-archiveable
  /api/ebay/{integrationInstance}/products/delete:
    put:
      tags:
      - eBay
      summary: Bulk Delete eBay Listings
      description: 'Delete eBay listing records from the local catalog, together with
        their product mapping links. This does not end or modify the live listing
        on eBay.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Body fields:

        - ids (array of integers): Listing IDs to target. Required unless mode is
        "all".

        - mode (string): Pass "all" to target every listing on the integration instance
        instead of an explicit ID list.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 8121
                - 8122
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  status:
                    type: string
                example:
                  message: Products deleted successfully.
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-ebay-integrationinstance-products-delete
  /api/ebay/{integrationInstance}/products/deleteable:
    put:
      tags:
      - eBay
      summary: Check eBay Listings Deleteable
      description: 'Check which eBay listings can be deleted. The response gives a
        per-listing verdict and reason.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Body fields:

        - ids (array of integers): Listing IDs to target. Required unless mode is
        "all".

        - mode (string): Pass "all" to target every listing on the integration instance
        instead of an explicit ID list.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 8121
                - 8122
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        deleteable:
                          type: boolean
                        reason:
                          type: boolean
                  status:
                    type: string
                example:
                  data:
                  - id: 8121
                    deleteable: true
                    reason: false
                  - id: 8122
                    deleteable: true
                    reason: false
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-ebay-integrationinstance-products-deleteable
  /api/ebay/{integrationInstance}/products/sync-inventory:
    post:
      tags:
      - eBay
      summary: Sync eBay Listing Inventory
      description: 'Push current stock quantities to eBay for the given listings.
        Quantities are computed from the warehouses selected in the integration inventory
        settings.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Body fields:

        - ids (array of integers, optional): Listing IDs to sync. Omit to sync every
        eligible listing.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 8121
                - 8122
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  status:
                    type: string
                example:
                  message: Successfully submitted to sales channel.
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-ebay-integrationinstance-products-sync-inventory
  /api/ebay/{integrationInstance}/products/hydrate-product-template:
    post:
      tags:
      - eBay
      summary: Hydrate eBay Listing Template
      description: 'Fill an eBay listing template with values from a product. Static
        template fields keep their configured value; dynamic fields are evaluated
        against the product. Returns both the resolved field list and the generated
        listing payload ready for publishing.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Body fields:

        - product_id (integer, required): The product to pull values from.

        - sales_channel_product_template_id (integer, required): The listing template
        to hydrate.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                product_id:
                  type: integer
                sales_channel_product_template_id:
                  type: integer
              example:
                product_id: 501
                sales_channel_product_template_id: 7
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      fields:
                        type: array
                        items:
                          type: object
                          properties:
                            name:
                              type: string
                            value:
                              type: string
                            data_type:
                              type: string
                            validation_rules:
                              type: string
                            sort_order:
                              type: integer
                      payload:
                        type: string
                  status:
                    type: string
                example:
                  data:
                    fields:
                    - name: Title
                      value: Acme Widget - Blue
                      data_type: string
                      validation_rules: required|max:80
                      sort_order: 1
                    - name: StartPrice
                      value: '19.99'
                      data_type: decimal
                      validation_rules: required
                      sort_order: 2
                    payload: <?xml version="1.0" encoding="utf-8"?><AddItemRequest>...</AddItemRequest>
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-ebay-integrationinstance-products-hydrate-product-template
  /api/ebay/{integrationInstance}/mappings:
    get:
      tags:
      - eBay
      summary: Get eBay Field Mappings
      description: 'Get the field mappings used when creating products from eBay listings.
        Returns the built-in default mappings, any custom overrides saved for this
        integration instance, and the effective (merged) mapping set, along with the
        catalogs of available eBay listing fields and product fields.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      integration_instance_id:
                        type: integer
                      integration_name:
                        type: string
                      mappings:
                        type: array
                        items:
                          type: object
                          properties:
                            listing_field:
                              type: string
                            sku_field:
                              type: string
                            parsers:
                              type: array
                      available_ebay_fields:
                        type: object
                        properties:
                          title:
                            type: object
                            properties:
                              name:
                                type: string
                              label:
                                type: string
                              type:
                                type: string
                              description:
                                type: string
                              group:
                                type: string
                      available_sku_fields:
                        type: object
                        properties:
                          name:
                            type: object
                            properties:
                              name:
                                type: string
                              label:
                                type: string
                              type:
                                type: string
                      default_mappings:
                        type: array
                        items:
                          type: object
                          properties:
                            listing_field:
                              type: string
                            sku_field:
                              type: string
                            parsers:
                              type: array
                      custom_mappings:
                        type: array
                        items:
                          type: object
                          properties:
                            listing_field:
                              type: string
                            sku_field:
                              type: string
                            parsers:
                              type: array
                      effective_mappings:
                        type: array
                        items:
                          type: object
                          properties:
                            listing_field:
                              type: string
                            sku_field:
                              type: string
                            parsers:
                              type: array
                example:
                  data:
                    integration_instance_id: 3
                    integration_name: eBay US Store
                    mappings:
                    - listing_field: title
                      sku_field: name
                      parsers: []
                    - listing_field: sku
                      sku_field: sku
                      parsers: []
                    available_ebay_fields:
                      title:
                        name: title
                        label: Product Title
                        type: string
                        description: eBay listing title
                        group: Product Info
                    available_sku_fields:
                      name:
                        name: name
                        label: Product Name
                        type: string
                    default_mappings:
                    - listing_field: title
                      sku_field: name
                      parsers: []
                    custom_mappings:
                    - listing_field: sku
                      sku_field: sku
                      parsers: []
                    effective_mappings:
                    - listing_field: title
                      sku_field: name
                      parsers: []
                    - listing_field: sku
                      sku_field: sku
                      parsers: []
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-ebay-integrationinstance-mappings
    put:
      tags:
      - eBay
      summary: Update eBay Field Mappings
      description: "Replace the custom field mappings for this integration instance.\
        \ Each mapping pairs an eBay listing field with the product field it populates;\
        \ optional parsers transform the value on the way in.\n\n:::info[Authorization]\n\
        Any valid API token can call this endpoint — no specific scope required. [Manage\
        \ tokens](https://app.sku.io/settings/api).\n:::\n\nBody fields:\n- mappings\
        \ (array, required): Each entry:\n  - listing_field (string, required): eBay\
        \ listing field name.\n  - sku_field (string, required): Product field to\
        \ populate.\n  - parsers (array, optional): Ordered transforms, each with\
        \ a rule and args."
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                mappings:
                  type: array
                  items:
                    type: object
                    properties:
                      listing_field:
                        type: string
                      sku_field:
                        type: string
                      parsers:
                        type: array
              example:
                mappings:
                - listing_field: title
                  sku_field: name
                  parsers: []
                - listing_field: sku
                  sku_field: sku
                  parsers:
                  - rule: trim
                    args: []
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      integration_instance_id:
                        type: integer
                      integration_name:
                        type: string
                      mappings:
                        type: array
                        items:
                          type: object
                          properties:
                            listing_field:
                              type: string
                            sku_field:
                              type: string
                            parsers:
                              type: array
                      effective_mappings:
                        type: array
                        items:
                          type: object
                          properties:
                            listing_field:
                              type: string
                            sku_field:
                              type: string
                            parsers:
                              type: array
                  message:
                    type: string
                example:
                  data:
                    integration_instance_id: 3
                    integration_name: eBay US Store
                    mappings:
                    - listing_field: title
                      sku_field: name
                      parsers: []
                    effective_mappings:
                    - listing_field: title
                      sku_field: name
                      parsers: []
                  message: Field mappings updated successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-ebay-integrationinstance-mappings
  /api/ebay/{integrationInstance}/orders/refresh-tracked:
    post:
      tags:
      - eBay
      summary: Start Tracked eBay Order Refresh
      description: 'Start a tracked background refresh of orders from eBay. Returns
        a tracked_job_log_id whose progress can be polled while the refresh runs.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Body fields (all optional):

        - mode (string): One of latest, from_start_date, date_range, all. Defaults
        to latest (fetch orders updated since the last sync). from_start_date fetches
        all orders created since the integration start date; date_range fetches orders
        created between date_from and date_to; all fetches everything.

        - date_from (date): Start of the creation-date window. Required in practice
        when mode is date_range.

        - date_to (date): End of the creation-date window (inclusive; extends to end
        of day).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                mode:
                  type: string
                date_from:
                  type: string
                date_to:
                  type: string
              example:
                mode: date_range
                date_from: '2026-06-01'
                date_to: '2026-06-30'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                  status:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 2211
                  message: Order refresh job has been queued
                  status: success
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      mode:
                        type: array
                        items:
                          type: string
                example:
                  message: The selected mode is invalid.
                  errors:
                    mode:
                    - The selected mode is invalid.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-ebay-integrationinstance-orders-refresh-tracked
  /api/ebay/{integrationInstance}/orders/latest-sync-info:
    get:
      tags:
      - eBay
      summary: Get eBay Order Sync Status
      description: 'Get summary statistics about the locally-synced eBay orders for
        an integration instance: the most recent order, total order count, and how
        many are linked to sales orders.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      latest_order_id:
                        type: string
                      latest_order_date:
                        type: string
                      latest_order_status:
                        type: string
                      total_orders:
                        type: integer
                      with_sku_order:
                        type: integer
                      without_sku_order:
                        type: integer
                example:
                  data:
                    latest_order_id: 12-34567-89012
                    latest_order_date: '2026-06-28T15:04:11.000000Z'
                    latest_order_status: PAID
                    total_orders: 5230
                    with_sku_order: 5100
                    without_sku_order: 130
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-ebay-integrationinstance-orders-latest-sync-info
  /api/ebay/{integrationInstance}/orders/refresh-order:
    post:
      tags:
      - eBay
      summary: Refresh eBay Order
      description: 'Re-fetch a single order from eBay and update the local record.
        Returns the refreshed order.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Body fields:

        - uniqueId (string, required): The eBay order ID (e.g. 12-34567-89012).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                uniqueId:
                  type: string
              example:
                uniqueId: 12-34567-89012
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      sku_sales_order:
                        type: object
                        properties:
                          id:
                            type: integer
                          number:
                            type: string
                          order_status:
                            type: string
                          fulfillment_status:
                            type: string
                          payment_status:
                            type: string
                      json_object:
                        type: object
                        properties:
                          orderId:
                            type: string
                          buyer:
                            type: object
                            properties:
                              username:
                                type: string
                      orderId:
                        type: string
                      salesRecordReference:
                        type: string
                      orderPaymentStatus:
                        type: string
                      orderFulfillmentStatus:
                        type: string
                      totalValue:
                        type: number
                      totalCurrency:
                        type: string
                      totalMarketplaceFeeValue:
                        type: number
                      totalMarketplaceFeeCurrency:
                        type: string
                      creationDateUtc:
                        type: string
                      lastModifiedDateUtc:
                        type: string
                      error_log:
                        type: string
                        nullable: true
                      archived_at:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                  status:
                    type: string
                example:
                  data:
                    id: 9101
                    integration_instance_id: 3
                    sku_sales_order:
                      id: 7788
                      number: SO-10234
                      order_status: completed
                      fulfillment_status: fulfilled
                      payment_status: paid
                    json_object:
                      orderId: 12-34567-89012
                      buyer:
                        username: acme_buyer
                    orderId: 12-34567-89012
                    salesRecordReference: '1287'
                    orderPaymentStatus: PAID
                    orderFulfillmentStatus: FULFILLED
                    totalValue: 45.98
                    totalCurrency: USD
                    totalMarketplaceFeeValue: 5.98
                    totalMarketplaceFeeCurrency: USD
                    creationDateUtc: '2026-06-28T15:04:11.000000Z'
                    lastModifiedDateUtc: '2026-06-29T10:11:00.000000Z'
                    error_log: null
                    archived_at: null
                    created_at: '2026-06-28T15:10:00.000000Z'
                    updated_at: '2026-06-29T10:12:00.000000Z'
                  status: success
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Order not found
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-ebay-integrationinstance-orders-refresh-order
  /api/ebay/{integrationInstance}/orders/{order}/raw:
    get:
      tags:
      - eBay
      summary: Get Raw eBay Order
      description: 'Fetch the order directly from the eBay Fulfillment API and return
        the live payload as eBay serves it (not the locally cached copy). Useful for
        verifying what eBay currently reports for the order.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Path parameters:

        - integrationInstance (integer): The eBay integration instance ID.

        - order (integer): The local eBay order record ID.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: order
        in: path
        schema:
          type: string
        required: true
        description: The order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      order:
                        type: object
                        properties:
                          orderId:
                            type: string
                          creationDate:
                            type: string
                          orderFulfillmentStatus:
                            type: string
                          orderPaymentStatus:
                            type: string
                          buyer:
                            type: object
                            properties:
                              username:
                                type: string
                          pricingSummary:
                            type: object
                            properties:
                              total:
                                type: object
                                properties:
                                  value:
                                    type: string
                                  currency:
                                    type: string
                          lineItems:
                            type: array
                            items:
                              type: object
                              properties:
                                lineItemId:
                                  type: string
                                legacyItemId:
                                  type: string
                                sku:
                                  type: string
                                title:
                                  type: string
                                quantity:
                                  type: integer
                  fetched_at:
                    type: string
                example:
                  data:
                    order:
                      orderId: 12-34567-89012
                      creationDate: '2026-06-28T15:04:11.000Z'
                      orderFulfillmentStatus: FULFILLED
                      orderPaymentStatus: PAID
                      buyer:
                        username: acme_buyer
                      pricingSummary:
                        total:
                          value: '45.98'
                          currency: USD
                      lineItems:
                      - lineItemId: '10045678901234'
                        legacyItemId: '110552983245'
                        sku: WIDGET-BLUE
                        title: Acme Widget - Blue
                        quantity: 2
                  fetched_at: '2026-07-06T18:30:00+00:00'
        '403':
          description: Forbidden
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Order does not belong to this integration instance
        '500':
          description: Internal Server Error
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: The eBay integration needs to be reconnected — its refresh
                    token is no longer valid.
        '429': *id001
        '401': *id002
        '404': *id004
      operationId: get-api-ebay-integrationinstance-orders-order-raw
  /api/ebay/{integrationInstance}/orders/{order}/activity-log:
    get:
      tags:
      - eBay
      summary: List eBay Order Activity Log
      description: 'List the audit history of a single eBay order, most recent first.
        Each entry describes an event, the changed attributes, and who (or what) caused
        it.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Filters:

        - filter[search]: matches the causer name, event name, or recorded properties.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: order
        in: path
        schema:
          type: string
        required: true
        description: The order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        description:
                          type: string
                        event:
                          type: string
                        subject_type:
                          type: string
                        subject_id:
                          type: integer
                        properties:
                          type: object
                          properties:
                            attributes:
                              type: object
                              properties:
                                orderFulfillmentStatus:
                                  type: string
                            old:
                              type: object
                              properties:
                                orderFulfillmentStatus:
                                  type: string
                            source:
                              type: string
                        causer_name:
                          type: string
                        created_at:
                          type: string
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                    items:
                      type: object
                      properties:
                        url:
                          type: string
                          nullable: true
                        label:
                          type: string
                        active:
                          type: boolean
                  next_page_url:
                    type: string
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 90211
                    description: updated
                    event: updated
                    subject_type: EbayOrder
                    subject_id: 9101
                    properties:
                      attributes:
                        orderFulfillmentStatus: FULFILLED
                      old:
                        orderFulfillmentStatus: IN_PROGRESS
                      source: sync
                    causer_name: Jane Smith
                    created_at: '2026-06-29T10:11:02.000000Z'
                  first_page_url: '{{base_url}}/api/ebay/3/orders/9101/activity-log?page=1'
                  from: 1
                  last_page: 1
                  last_page_url: '{{base_url}}/api/ebay/3/orders/9101/activity-log?page=1'
                  links:
                  - url: null
                    label: '&laquo; Previous'
                    active: false
                  - url: '{{base_url}}/api/ebay/3/orders/9101/activity-log?page=1'
                    label: '1'
                    active: true
                  - url: '{{base_url}}/api/ebay/3/orders/9101/activity-log?page=2'
                    label: Next &raquo;
                    active: false
                  next_page_url: '{{base_url}}/api/ebay/3/orders/9101/activity-log?page=2'
                  path: '{{base_url}}/api/ebay/3/orders/9101/activity-log'
                  per_page: 15
                  prev_page_url: null
                  to: 1
                  total: 6
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-ebay-integrationinstance-orders-order-activity-log
  /api/ebay/{integrationInstance}/orders/{order}/archive:
    put:
      tags:
      - eBay
      summary: Archive eBay Order
      description: 'Archive an eBay order record. Archived orders are excluded from
        listings and bulk operations by default. Returns whether the order was newly
        archived (archived: false means it was already archived).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: order
        in: path
        schema:
          type: string
        required: true
        description: The order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  archived:
                    type: boolean
                example:
                  message: Order archived successfully
                  archived: true
        '403':
          description: Forbidden
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: Order does not belong to this integration instance
        '429': *id001
        '401': *id002
        '404': *id004
        '422': *id005
      operationId: put-api-ebay-integrationinstance-orders-order-archive
  /api/ebay/{integrationInstance}/orders/{order}/unarchive:
    put:
      tags:
      - eBay
      summary: Unarchive eBay Order
      description: 'Restore an archived eBay order record. Returns whether the order
        was newly restored (unarchived: false means it was already active).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: order
        in: path
        schema:
          type: string
        required: true
        description: The order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  unarchived:
                    type: boolean
                example:
                  message: Order unarchived successfully
                  unarchived: true
        '403':
          description: Forbidden
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: Order does not belong to this integration instance
        '429': *id001
        '401': *id002
        '404': *id004
        '422': *id005
      operationId: put-api-ebay-integrationinstance-orders-order-unarchive
  /api/ebay/{integrationInstance}/orders/{order}:
    delete:
      tags:
      - eBay
      summary: Delete eBay Order
      description: 'Delete a single eBay order record from the local store. This does
        not affect the order on eBay, and any linked sales order is not removed by
        this call.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: order
        in: path
        schema:
          type: string
        required: true
        description: The order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Order deleted successfully
        '403':
          description: Forbidden
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: Order does not belong to this integration instance
        '429': *id001
        '401': *id002
        '404': *id004
      operationId: delete-api-ebay-integrationinstance-orders-order
    get:
      tags:
      - eBay
      summary: Show Order
      description: 'Retrieve a single Ebay order by its database ID. Requires Bearer
        token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '42'
      - name: order
        in: path
        schema:
          type: integer
        required: true
        description: Order ID
        example: '501'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      orderId:
                        type: string
                      legacyOrderId:
                        type: string
                      creationDateUtc:
                        type: string
                      lastModifiedDateUtc:
                        type: string
                      orderPaymentStatus:
                        type: string
                      orderFulfillmentStatus:
                        type: string
                      totalValue:
                        type: number
                      totalCurrency:
                        type: string
                      salesRecordReference:
                        type: string
                      totalMarketplaceFeeValue:
                        type: number
                      totalMarketplaceFeeCurrency:
                        type: string
                      json_object:
                        type: object
                        properties:
                          orderId:
                            type: string
                          buyer:
                            type: object
                            properties:
                              buyerRegistrationAddress:
                                type: object
                                properties:
                                  fullName:
                                    type: string
                          pricingSummary:
                            type: object
                            properties:
                              total:
                                type: object
                                properties:
                                  value:
                                    type: string
                                  currency:
                                    type: string
                      archived_at:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 501
                    integration_instance_id: 42
                    orderId: 12-34567-89012
                    legacyOrderId: '987654321'
                    creationDateUtc: '2024-06-01T14:00:00.000Z'
                    lastModifiedDateUtc: '2024-06-02T09:00:00.000Z'
                    orderPaymentStatus: PAID
                    orderFulfillmentStatus: NOT_STARTED
                    totalValue: 49.99
                    totalCurrency: USD
                    salesRecordReference: SR-001
                    totalMarketplaceFeeValue: 2.5
                    totalMarketplaceFeeCurrency: USD
                    json_object:
                      orderId: 12-34567-89012
                      buyer:
                        buyerRegistrationAddress:
                          fullName: John Doe
                      pricingSummary:
                        total:
                          value: '49.99'
                          currency: USD
                    archived_at: null
                    created_at: '2024-06-01T14:00:00.000Z'
                    updated_at: '2024-06-02T09:00:00.000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-ebay-integrationinstance-orders-order
  /api/ebay/{integrationInstance}/orders/{order}/sku-order:
    delete:
      tags:
      - eBay
      summary: Delete Linked Sales Order
      description: 'Delete the sales order linked to an eBay order, keeping the eBay
        order record itself. Optionally archives the eBay order afterwards so it will
        not be re-created by order automation.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Query parameters:

        - archive_order (boolean, default false): Archive the eBay order after deleting
        the linked sales order.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: order
        in: path
        schema:
          type: string
        required: true
        description: The order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  archived_order:
                    type: boolean
                example:
                  message: SKU order deleted successfully and eBay order archived
                  archived_order: true
        '403':
          description: Forbidden
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: Order does not belong to this integration instance
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: No SKU order linked to this eBay order
        '429': *id001
        '401': *id002
      operationId: delete-api-ebay-integrationinstance-orders-order-sku-order
  /api/ebay/{integrationInstance}/orders/bulk-delete:
    post:
      tags:
      - eBay
      summary: Bulk Delete eBay Orders
      description: 'Delete multiple eBay order records from the local store in one
        call. Orders on eBay are unaffected.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Body fields:

        - ids (array of integers, required): Local eBay order record IDs to delete.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 9101
                - 9102
                - 9103
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  count:
                    type: integer
                example:
                  message: 3 orders deleted successfully
                  count: 3
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-ebay-integrationinstance-orders-bulk-delete
  /api/ebay/{integrationInstance}/pre-start-date-orders:
    get:
      tags:
      - eBay
      summary: List Pre-Start-Date eBay Orders
      description: 'Query eBay live for orders created before the account inventory
        start date, within a creation-date window. Returns lightweight order data
        with per-order eligibility flags so eligible orders can be selected for import.
        An inventory start date must be configured before using this endpoint.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Query parameters:

        - created_at_min (date, required): Start of the creation-date window. Must
        be before the inventory start date.

        - created_at_max (date, optional): End of the window. Must be before the inventory
        start date; defaults to the day before the inventory start date.

        - fulfillment_status (string, optional): One of NOT_STARTED, IN_PROGRESS,
        FULFILLED, any.


        Up to 2000 orders are scanned per query.'
      parameters:
      - name: created_at_min
        in: query
        schema:
          type: string
        description: Start of creation-date window (required, before inventory start
          date)
        example: '2025-11-01'
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        ebay_order_id:
                          type: string
                        name:
                          type: string
                        buyer_username:
                          type: string
                        created_at:
                          type: string
                        fulfillment_status:
                          type: string
                        payment_status:
                          type: string
                        total_price:
                          type: string
                        currency:
                          type: string
                        fulfillments:
                          type: array
                          items:
                            type: object
                            properties:
                              id:
                                type: integer
                              created_at:
                                type: string
                                nullable: true
                              status:
                                type: string
                              tracking_number:
                                type: string
                                nullable: true
                        line_items:
                          type: array
                          items:
                            type: object
                            properties:
                              title:
                                type: string
                              sku:
                                type: string
                              quantity:
                                type: integer
                              current_quantity:
                                type: integer
                              price:
                                type: string
                              variant_title:
                                type: string
                                nullable: true
                        eligible:
                          type: boolean
                        eligibility_reason:
                          type: string
                          nullable: true
                        already_imported:
                          type: boolean
                  inventory_start_date:
                    type: string
                  meta:
                    type: object
                    properties:
                      total_queried:
                        type: integer
                      eligible_count:
                        type: integer
                      already_imported_count:
                        type: integer
                example:
                  data:
                  - ebay_order_id: 12-34567-89012
                    name: '1287'
                    buyer_username: acme_buyer
                    created_at: '2025-12-15T10:22:00.000Z'
                    fulfillment_status: FULFILLED
                    payment_status: PAID
                    total_price: '45.98'
                    currency: USD
                    fulfillments:
                    - id: 0
                      created_at: null
                      status: SHIP_TO
                      tracking_number: null
                    line_items:
                    - title: Acme Widget - Blue
                      sku: WIDGET-BLUE
                      quantity: 2
                      current_quantity: 2
                      price: '19.99'
                      variant_title: null
                    eligible: true
                    eligibility_reason: null
                    already_imported: false
                  inventory_start_date: '2026-01-01'
                  meta:
                    total_queried: 12
                    eligible_count: 10
                    already_imported_count: 2
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      created_at_min:
                        type: array
                        items:
                          type: string
                example:
                  message: Created at min must be before the inventory start date.
                  errors:
                    created_at_min:
                    - Created at min must be before the inventory start date.
        '500':
          description: Internal Server Error
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                  message:
                    type: string
                example:
                  error: Failed to query eBay for pre-start-date orders
                  message: Request timed out.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-ebay-integrationinstance-pre-start-date-orders
  /api/ebay/{integrationInstance}/pre-start-date-orders/search:
    get:
      tags:
      - eBay
      summary: Search Pre-Start-Date eBay Orders
      description: 'Search eBay live for specific pre-start-date orders by order ID
        or buyer username. Returns the same shape as the windowed query, filtered
        to orders created before the inventory start date.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Query parameters:

        - search_by (string, required): One of order_id, ebay_order_id, buyer_username.

        - search_term (string, required, max 255): The value to search for. Buyer-username
        search scans up to one year of orders before the inventory start date and
        matches partial usernames.'
      parameters:
      - name: search_by
        in: query
        schema:
          type: string
        description: order_id, ebay_order_id, or buyer_username (required)
        example: ebay_order_id
      - name: search_term
        in: query
        schema:
          type: string
        description: Value to search for (required)
        example: 12-34567-89012
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        ebay_order_id:
                          type: string
                        name:
                          type: string
                        buyer_username:
                          type: string
                        created_at:
                          type: string
                        fulfillment_status:
                          type: string
                        payment_status:
                          type: string
                        total_price:
                          type: string
                        currency:
                          type: string
                        fulfillments:
                          type: array
                          items:
                            type: object
                            properties:
                              id:
                                type: integer
                              created_at:
                                type: string
                                nullable: true
                              status:
                                type: string
                              tracking_number:
                                type: string
                                nullable: true
                        line_items:
                          type: array
                          items:
                            type: object
                            properties:
                              title:
                                type: string
                              sku:
                                type: string
                              quantity:
                                type: integer
                              current_quantity:
                                type: integer
                              price:
                                type: string
                              variant_title:
                                type: string
                                nullable: true
                        eligible:
                          type: boolean
                        eligibility_reason:
                          type: string
                          nullable: true
                        already_imported:
                          type: boolean
                  inventory_start_date:
                    type: string
                  meta:
                    type: object
                    properties:
                      total_queried:
                        type: integer
                      eligible_count:
                        type: integer
                      already_imported_count:
                        type: integer
                example:
                  data:
                  - ebay_order_id: 12-34567-89012
                    name: '1287'
                    buyer_username: acme_buyer
                    created_at: '2025-12-15T10:22:00.000Z'
                    fulfillment_status: FULFILLED
                    payment_status: PAID
                    total_price: '45.98'
                    currency: USD
                    fulfillments:
                    - id: 0
                      created_at: null
                      status: SHIP_TO
                      tracking_number: null
                    line_items:
                    - title: Acme Widget - Blue
                      sku: WIDGET-BLUE
                      quantity: 2
                      current_quantity: 2
                      price: '19.99'
                      variant_title: null
                    eligible: true
                    eligibility_reason: null
                    already_imported: false
                  inventory_start_date: '2026-01-01'
                  meta:
                    total_queried: 1
                    eligible_count: 1
                    already_imported_count: 0
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      search_by:
                        type: array
                        items:
                          type: string
                example:
                  message: The selected search by is invalid.
                  errors:
                    search_by:
                    - The selected search by is invalid.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-ebay-integrationinstance-pre-start-date-orders-search
  /api/ebay/{integrationInstance}/pre-start-date-orders/import:
    post:
      tags:
      - eBay
      summary: Import Pre-Start-Date eBay Orders
      description: 'Import selected pre-start-date orders from eBay. Each order is
        fetched with its own throttled API call, so the import runs as a queued background
        job rather than synchronously. Downloads the full order data for each ID and
        stores it locally; orders that already exist locally, were cancelled, or cannot
        be found on eBay are skipped with a per-order reason. Returns a tracked_job_log_id
        whose progress can be polled while the import runs.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Body fields:

        - ebay_order_ids (array of strings, required, 1-10000 items): eBay order IDs
        to import.


        Returns 422 if the inventory start date has not been set.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ebay_order_ids:
                  type: array
                  items:
                    type: string
              example:
                ebay_order_ids:
                - 12-34567-89012
                - 12-34567-89013
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 2212
                  message: Importing 2 pre-start-date orders — track progress in the
                    job tray.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: Inventory start date must be set before importing pre-start-date
                    orders.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-ebay-integrationinstance-pre-start-date-orders-import
  /api/ebay/{integrationInstance}/fulfillments:
    get:
      tags:
      - eBay
      summary: List eBay Fulfillments
      description: 'List fulfilled shipments for sales orders that originated from
        this eBay integration, most recent first. Each row includes its eBay submission
        state (sync_status: submitted or pending).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Filters:

        - filter[search]: matches tracking number or sales order number.

        - filter[sync_status]: submitted (already pushed to eBay) or pending (not
        yet pushed).

        - filter[fulfillment_type]: fulfillment type (e.g. warehouse, dropship).

        - filter[date_from] / filter[date_to] (Y-m-d): fulfilled-at date range.

        - filter[warehouse_id]: fulfilling warehouse ID.


        Allowed sorts: id, fulfilled_at, created_at, submitted_to_sales_channel_at.
        Prefix with - for descending. Default sort: -id.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        fulfillment_number:
                          type: string
                        fulfillment_type:
                          type: string
                        status:
                          type: string
                        tracking_number:
                          type: string
                        cost:
                          type: number
                        fulfilled_at:
                          type: string
                        submitted_to_sales_channel_at:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                        carrier:
                          type: string
                        sales_order:
                          type: object
                          properties:
                            id:
                              type: integer
                            sales_order_number:
                              type: string
                        ebay_order:
                          type: object
                          properties:
                            id:
                              type: integer
                            orderId:
                              type: string
                        warehouse:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        sync_status:
                          type: string
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                    items:
                      type: object
                      properties:
                        url:
                          type: string
                          nullable: true
                        label:
                          type: string
                        active:
                          type: boolean
                  next_page_url:
                    type: string
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 3312
                    fulfillment_number: F-10234-1
                    fulfillment_type: warehouse
                    status: fulfilled
                    tracking_number: '9400111899223197428490'
                    cost: 7.45
                    fulfilled_at: '2026-07-01T16:20:00+00:00'
                    submitted_to_sales_channel_at: null
                    created_at: '2026-07-01T16:21:03+00:00'
                    carrier: USPS
                    sales_order:
                      id: 7788
                      sales_order_number: SO-10234
                    ebay_order:
                      id: 9101
                      orderId: 12-34567-89012
                    warehouse:
                      id: 1
                      name: Main Warehouse
                    sync_status: pending
                  first_page_url: '{{base_url}}/api/ebay/3/fulfillments?page=1'
                  from: 1
                  last_page: 5
                  last_page_url: '{{base_url}}/api/ebay/3/fulfillments?page=5'
                  links:
                  - url: null
                    label: '&laquo; Previous'
                    active: false
                  - url: '{{base_url}}/api/ebay/3/fulfillments?page=1'
                    label: '1'
                    active: true
                  - url: '{{base_url}}/api/ebay/3/fulfillments?page=2'
                    label: Next &raquo;
                    active: false
                  next_page_url: '{{base_url}}/api/ebay/3/fulfillments?page=2'
                  path: '{{base_url}}/api/ebay/3/fulfillments'
                  per_page: 10
                  prev_page_url: null
                  to: 1
                  total: 48
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-ebay-integrationinstance-fulfillments
  /api/ebay/{integrationInstance}/fulfillments/pending:
    get:
      tags:
      - eBay
      summary: List Pending eBay Fulfillments
      description: 'List fulfilled shipments that are waiting to be submitted to eBay
        (not yet pushed, order not cancelled, and not pickup-type). These are the
        fulfillments the automatic sync will submit next.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Filters:

        - filter[search]: matches tracking number or sales order number.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        fulfillment_number:
                          type: string
                        fulfillment_type:
                          type: string
                        status:
                          type: string
                        tracking_number:
                          type: string
                        cost:
                          type: number
                        fulfilled_at:
                          type: string
                        submitted_to_sales_channel_at:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                        carrier:
                          type: string
                        sales_order:
                          type: object
                          properties:
                            id:
                              type: integer
                            sales_order_number:
                              type: string
                        ebay_order:
                          type: object
                          properties:
                            id:
                              type: integer
                            orderId:
                              type: string
                        warehouse:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        sync_status:
                          type: string
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                    items:
                      type: object
                      properties:
                        url:
                          type: string
                          nullable: true
                        label:
                          type: string
                        active:
                          type: boolean
                  next_page_url:
                    type: string
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 3312
                    fulfillment_number: F-10234-1
                    fulfillment_type: warehouse
                    status: fulfilled
                    tracking_number: '9400111899223197428490'
                    cost: 7.45
                    fulfilled_at: '2026-07-01T16:20:00+00:00'
                    submitted_to_sales_channel_at: null
                    created_at: '2026-07-01T16:21:03+00:00'
                    carrier: USPS
                    sales_order:
                      id: 7788
                      sales_order_number: SO-10234
                    ebay_order:
                      id: 9101
                      orderId: 12-34567-89012
                    warehouse:
                      id: 1
                      name: Main Warehouse
                    sync_status: pending
                  first_page_url: '{{base_url}}/api/ebay/3/fulfillments/pending?page=1'
                  from: 1
                  last_page: 1
                  last_page_url: '{{base_url}}/api/ebay/3/fulfillments/pending?page=1'
                  links:
                  - url: null
                    label: '&laquo; Previous'
                    active: false
                  - url: '{{base_url}}/api/ebay/3/fulfillments/pending?page=1'
                    label: '1'
                    active: true
                  - url: '{{base_url}}/api/ebay/3/fulfillments/pending?page=2'
                    label: Next &raquo;
                    active: false
                  next_page_url: '{{base_url}}/api/ebay/3/fulfillments/pending?page=2'
                  path: '{{base_url}}/api/ebay/3/fulfillments/pending'
                  per_page: 10
                  prev_page_url: null
                  to: 1
                  total: 4
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-ebay-integrationinstance-fulfillments-pending
  /api/ebay/{integrationInstance}/fulfillments/stats:
    get:
      tags:
      - eBay
      summary: Get eBay Fulfillment Stats
      description: 'Get fulfillment submission statistics for the integration instance:
        how many fulfillments are pending submission to eBay and the automatic submission
        schedule.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      pending_sync_count:
                        type: integer
                      sync_schedule:
                        type: object
                        properties:
                          interval:
                            type: integer
                          unit:
                            type: string
                          description:
                            type: string
                example:
                  data:
                    pending_sync_count: 4
                    sync_schedule:
                      interval: 10
                      unit: minutes
                      description: Fulfillments are automatically synced every 10
                        minutes
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-ebay-integrationinstance-fulfillments-stats
  /api/ebay/{integrationInstance}/fulfillments/{salesOrderFulfillment}/submit:
    post:
      tags:
      - eBay
      summary: Submit eBay Fulfillment
      description: 'Submit a single fulfillment to eBay, uploading its tracking number
        and carrier so the buyer is notified. The fulfillment must be in fulfilled
        status and not yet submitted.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Path parameters:

        - integrationInstance (integer): The eBay integration instance ID.

        - salesOrderFulfillment (integer): The fulfillment ID to submit.'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: salesOrderFulfillment
        in: path
        schema:
          type: string
        required: true
        description: The sales order fulfillment ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                example:
                  success: true
                  message: 'Fulfillment #F-10234-1 submitted successfully'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                example:
                  success: false
                  message: Sales order is not linked to an eBay order
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-ebay-integrationinstance-fulfillments-salesorderfulfillment-submit
  /api/ebay/{integrationInstance}/fulfillments/submit-bulk:
    post:
      tags:
      - eBay
      summary: Bulk Submit eBay Fulfillments
      description: 'Submit multiple fulfillments to eBay in one call. Fulfillments
        that are already submitted, cancelled, or pickup-type are skipped. The response
        reports per-fulfillment failures.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Body fields:

        - ids (array of integers, required): Fulfillment IDs to submit.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 3312
                - 3313
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      submitted:
                        type: integer
                      failed:
                        type: integer
                  errors:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        message:
                          type: string
                  message:
                    type: string
                example:
                  success: false
                  data:
                    submitted: 1
                    failed: 1
                  errors:
                  - id: 3313
                    message: Sales order is not linked to an eBay order
                  message: 1 fulfillment(s) submitted, 1 failed
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-ebay-integrationinstance-fulfillments-submit-bulk
  /api/ebay/{integrationInstance}/fulfillments/submit-all:
    post:
      tags:
      - eBay
      summary: Submit All Pending eBay Fulfillments
      description: 'Submit every pending fulfillment for this integration instance
        to eBay. Equivalent to bulk-submitting the full pending list.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      submitted:
                        type: integer
                      failed:
                        type: integer
                  errors:
                    type: array
                  message:
                    type: string
                example:
                  success: true
                  data:
                    submitted: 4
                    failed: 0
                  errors: []
                  message: 4 fulfillment(s) submitted, 0 failed
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-ebay-integrationinstance-fulfillments-submit-all
  /api/ebay/{integrationInstance}/fulfill:
    post:
      tags:
      - eBay
      summary: Submit Sales Order Fulfillment
      description: 'Submit a sales order fulfillment to eBay by ID, uploading its
        tracking information. Body-based alternative to the path-based submit endpoint.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Body fields:

        - sales_order_fulfillment_id (integer, required): The fulfillment ID to submit.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                sales_order_fulfillment_id:
                  type: integer
              example:
                sales_order_fulfillment_id: 3312
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  status:
                    type: string
                example:
                  message: Successfully submitted to sales channel.
                  status: success
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 'eBay rejected the shipment: tracking number is invalid
                    for the selected carrier.'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-ebay-integrationinstance-fulfill
  /api/ebay/{integrationInstance}/inventory:
    get:
      tags:
      - eBay
      summary: List eBay Inventory Comparison
      description: 'List the inventory comparison for this eBay integration: one row
        per mapped listing, showing the locally computed quantity (sku_quantity),
        the quantity eBay currently reports (sales_channel_quantity), the variance,
        and a sync status of synced, variance, or needs_recalc. eBay has a single
        stock pool, so every row belongs to one synthetic location whose ID equals
        the integration instance ID.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Filters:

        - filter[search]: matches listing SKU, listing title, product SKU, or offering
        name/SKU.

        - filter[status] (or status.is / status.is_one_of / status.is_not): synced,
        variance, or needs_recalc.

        - Operator filters use the form filter[column.operator]=value. Numeric operators
        (sku_quantity, sales_channel_quantity): is, is_not, is_one_of, is_not_one_of,
        greater_than, less_than, greater_than_or_equal, less_than_or_equal, between,
        is_empty, is_not_empty. Text operators (listing_sku, title, location_id):
        contains, does_not_contain, is, is_not, is_one_of, is_not_one_of, starts_with,
        does_not_start_with, ends_with, does_not_end_with, is_empty, is_not_empty.
        Date operators (sales_channel_quantity_updated_at, sales_channel_quantity_synced_at,
        created_at, updated_at): is, is_not, before, after, on_or_before, on_or_after,
        between, is_empty, is_not_empty, today, yesterday, past_week, past_month,
        past_year, days_ago, past_days. A bare filter[column]=value acts as an implicit
        "is".


        Allowed sorts: id, sku_quantity, sales_channel_quantity, created_at, updated_at.
        Default sort: -id.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        product_listing_id:
                          type: integer
                        document_id:
                          type: integer
                        listing_sku:
                          type: string
                        title:
                          type: string
                        product:
                          type: object
                          properties:
                            id:
                              type: integer
                            sku:
                              type: string
                            name:
                              type: string
                        subscription_offering:
                          type: string
                          nullable: true
                        location_id:
                          type: integer
                        location_name:
                          type: string
                        location_is_active:
                          type: boolean
                        sku_quantity:
                          type: integer
                        sales_channel_quantity:
                          type: integer
                        variance:
                          type: integer
                        status:
                          type: string
                        is_sku_recalculation_needed:
                          type: boolean
                        sku_quantity_updated_at:
                          type: string
                        sales_channel_quantity_updated_at:
                          type: string
                        sales_channel_quantity_synced_at:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                    items:
                      type: object
                      properties:
                        url:
                          type: string
                          nullable: true
                        label:
                          type: string
                        active:
                          type: boolean
                  next_page_url:
                    type: string
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 5521
                    product_listing_id: 452
                    document_id: 8121
                    listing_sku: WIDGET-BLUE
                    title: Acme Widget - Blue
                    product:
                      id: 501
                      sku: WIDGET-BLUE
                      name: Acme Widget - Blue
                    subscription_offering: null
                    location_id: 3
                    location_name: eBay Store
                    location_is_active: true
                    sku_quantity: 25
                    sales_channel_quantity: 23
                    variance: 2
                    status: variance
                    is_sku_recalculation_needed: false
                    sku_quantity_updated_at: '2026-07-06T02:00:00+00:00'
                    sales_channel_quantity_updated_at: '2026-07-06T02:05:00+00:00'
                    sales_channel_quantity_synced_at: '2026-07-05T02:05:00+00:00'
                    created_at: '2026-03-01T00:00:00+00:00'
                    updated_at: '2026-07-06T02:05:00+00:00'
                  first_page_url: '{{base_url}}/api/ebay/3/inventory?page=1'
                  from: 1
                  last_page: 82
                  last_page_url: '{{base_url}}/api/ebay/3/inventory?page=82'
                  links:
                  - url: null
                    label: '&laquo; Previous'
                    active: false
                  - url: '{{base_url}}/api/ebay/3/inventory?page=1'
                    label: '1'
                    active: true
                  - url: '{{base_url}}/api/ebay/3/inventory?page=2'
                    label: Next &raquo;
                    active: false
                  next_page_url: '{{base_url}}/api/ebay/3/inventory?page=2'
                  path: '{{base_url}}/api/ebay/3/inventory'
                  per_page: 10
                  prev_page_url: null
                  to: 1
                  total: 812
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-ebay-integrationinstance-inventory
  /api/ebay/{integrationInstance}/inventory/summary:
    get:
      tags:
      - eBay
      summary: Get eBay Inventory Summary
      description: 'Get aggregate inventory-sync statistics for the integration instance:
        total tracked listings, how many are in sync with eBay, how many have a quantity
        variance, how many need local recalculation, and the timestamps of the last
        live fetch and the last push to eBay.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      total_items:
                        type: integer
                      in_sync:
                        type: integer
                      with_variance:
                        type: integer
                      needs_recalculation:
                        type: integer
                      last_fetch_at:
                        type: string
                      last_sync_at:
                        type: string
                example:
                  data:
                    total_items: 812
                    in_sync: 640
                    with_variance: 152
                    needs_recalculation: 20
                    last_fetch_at: '2026-07-06T02:05:00.000000Z'
                    last_sync_at: '2026-07-05T02:05:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-ebay-integrationinstance-inventory-summary
  /api/ebay/{integrationInstance}/inventory/locations:
    get:
      tags:
      - eBay
      summary: List eBay Inventory Locations
      description: 'List inventory locations for this integration. eBay has no multi-location
        inventory, so this always returns a single synthetic location whose ID equals
        the integration instance ID; it exists so eBay responses share the same shape
        as multi-location channels.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        is_active:
                          type: boolean
                example:
                  data:
                  - id: 3
                    name: eBay Store
                    is_active: true
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-ebay-integrationinstance-inventory-locations
  /api/ebay/{integrationInstance}/inventory/recache:
    post:
      tags:
      - eBay
      summary: Start eBay Inventory Recache
      description: 'Start a tracked background job that recalculates the local (SKU.io
        side) quantities for every mapped listing on this integration. Run this when
        local quantities are flagged as needing recalculation. Returns a tracked_job_log_id
        to poll for progress.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                example:
                  message: Inventory recache job has been queued
                  data:
                    tracked_job_log_id: 2210
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-ebay-integrationinstance-inventory-recache
  /api/ebay/{integrationInstance}/inventory/recache-progress/{trackedJobLogId}:
    get:
      tags:
      - eBay
      summary: Get eBay Inventory Recache Progress
      description: 'Get the progress of a previously started inventory recache job.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Path parameters:

        - integrationInstance (integer): The eBay integration instance ID.

        - trackedJobLogId (integer): The tracked_job_log_id returned when the job
        was started.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: trackedJobLogId
        in: path
        schema:
          type: string
        required: true
        description: The tracked job log ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      job_type:
                        type: string
                      queue:
                        type: string
                      job_name:
                        type: string
                      status:
                        type: string
                      related_model:
                        type: object
                        properties:
                          id:
                            type: integer
                          type:
                            type: string
                          reference:
                            type: string
                      related_model_reference:
                        type: string
                      messages:
                        type: array
                      attempted_at:
                        type: string
                      completed_at:
                        type: string
                        nullable: true
                      duration:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      results:
                        type: string
                        nullable: true
                      total_items:
                        type: integer
                      processed_items:
                        type: integer
                      progress_percentage:
                        type: number
                      progress_mode:
                        type: string
                      stages:
                        type: string
                        nullable: true
                example:
                  data:
                    id: 2210
                    job_type: ebay
                    queue: default
                    job_name: 'Recache eBay Inventory: eBay US Store'
                    status: processing
                    related_model:
                      id: 3
                      type: integration_instance
                      reference: eBay US Store
                    related_model_reference: eBay US Store
                    messages: []
                    attempted_at: '2026-07-06T18:20:01.000000Z'
                    completed_at: null
                    duration: null
                    created_at: '2026-07-06T18:20:00.000000Z'
                    updated_at: '2026-07-06T18:20:30.000000Z'
                    results: null
                    total_items: 120
                    processed_items: 45
                    progress_percentage: 37.5
                    progress_mode: items
                    stages: null
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Not found.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-ebay-integrationinstance-inventory-recache-progress-trackedjoblogid
  /api/ebay/{integrationInstance}/inventory/sync:
    post:
      tags:
      - eBay
      summary: Start eBay Inventory Sync
      description: 'Start a tracked background job that pushes local quantities to
        eBay for every mapped listing on this integration. Returns a tracked_job_log_id
        to poll for progress.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                example:
                  message: Inventory sync job has been queued
                  data:
                    tracked_job_log_id: 2211
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-ebay-integrationinstance-inventory-sync
  /api/ebay/{integrationInstance}/inventory/sync-progress/{trackedJobLogId}:
    get:
      tags:
      - eBay
      summary: Get eBay Inventory Sync Progress
      description: 'Get the progress of a previously started inventory sync job.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Path parameters:

        - integrationInstance (integer): The eBay integration instance ID.

        - trackedJobLogId (integer): The tracked_job_log_id returned when the job
        was started.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: trackedJobLogId
        in: path
        schema:
          type: string
        required: true
        description: The tracked job log ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      job_type:
                        type: string
                      queue:
                        type: string
                      job_name:
                        type: string
                      status:
                        type: string
                      related_model:
                        type: object
                        properties:
                          id:
                            type: integer
                          type:
                            type: string
                          reference:
                            type: string
                      related_model_reference:
                        type: string
                      messages:
                        type: array
                      attempted_at:
                        type: string
                      completed_at:
                        type: string
                      duration:
                        type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      results:
                        type: string
                        nullable: true
                      total_items:
                        type: integer
                      processed_items:
                        type: integer
                      progress_percentage:
                        type: integer
                      progress_mode:
                        type: string
                      stages:
                        type: string
                        nullable: true
                example:
                  data:
                    id: 2210
                    job_type: ebay
                    queue: default
                    job_name: 'Sync eBay Inventory: eBay US Store'
                    status: completed
                    related_model:
                      id: 3
                      type: integration_instance
                      reference: eBay US Store
                    related_model_reference: eBay US Store
                    messages: []
                    attempted_at: '2026-07-06T18:20:01.000000Z'
                    completed_at: '2026-07-06T18:26:40.000000Z'
                    duration: 399
                    created_at: '2026-07-06T18:20:00.000000Z'
                    updated_at: '2026-07-06T18:20:30.000000Z'
                    results: null
                    total_items: 120
                    processed_items: 120
                    progress_percentage: 100
                    progress_mode: items
                    stages: null
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Not found.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-ebay-integrationinstance-inventory-sync-progress-trackedjoblogid
  /api/ebay/{integrationInstance}/inventory/fetch-live:
    post:
      tags:
      - eBay
      summary: Start eBay Live Inventory Fetch
      description: 'Start a tracked background job that fetches current live quantities
        from eBay and stores them for comparison against local quantities. Returns
        a tracked_job_log_id to poll for progress.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                example:
                  message: Fetch live inventory job has been queued
                  data:
                    tracked_job_log_id: 2212
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-ebay-integrationinstance-inventory-fetch-live
  /api/ebay/{integrationInstance}/inventory/fetch-live-progress/{trackedJobLogId}:
    get:
      tags:
      - eBay
      summary: Get eBay Live Inventory Fetch Progress
      description: 'Get the progress of a previously started live inventory fetch
        job.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Path parameters:

        - integrationInstance (integer): The eBay integration instance ID.

        - trackedJobLogId (integer): The tracked_job_log_id returned when the job
        was started.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: trackedJobLogId
        in: path
        schema:
          type: string
        required: true
        description: The tracked job log ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      job_type:
                        type: string
                      queue:
                        type: string
                      job_name:
                        type: string
                      status:
                        type: string
                      related_model:
                        type: object
                        properties:
                          id:
                            type: integer
                          type:
                            type: string
                          reference:
                            type: string
                      related_model_reference:
                        type: string
                      messages:
                        type: array
                      attempted_at:
                        type: string
                      completed_at:
                        type: string
                        nullable: true
                      duration:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      results:
                        type: string
                        nullable: true
                      total_items:
                        type: integer
                      processed_items:
                        type: integer
                      progress_percentage:
                        type: number
                      progress_mode:
                        type: string
                      stages:
                        type: string
                        nullable: true
                example:
                  data:
                    id: 2210
                    job_type: ebay
                    queue: default
                    job_name: 'Fetch Live eBay Inventory: eBay US Store'
                    status: processing
                    related_model:
                      id: 3
                      type: integration_instance
                      reference: eBay US Store
                    related_model_reference: eBay US Store
                    messages: []
                    attempted_at: '2026-07-06T18:20:01.000000Z'
                    completed_at: null
                    duration: null
                    created_at: '2026-07-06T18:20:00.000000Z'
                    updated_at: '2026-07-06T18:20:30.000000Z'
                    results: null
                    total_items: 120
                    processed_items: 45
                    progress_percentage: 37.5
                    progress_mode: items
                    stages: null
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Not found.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-ebay-integrationinstance-inventory-fetch-live-progress-trackedjoblogid
  /api/faire/instances:
    get:
      tags:
      - Faire
      summary: List Faire Instances
      description: 'List all Faire integration instances for this account.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Response:**

        Returns a collection of Faire integration instances. Each instance includes:

        - `id` - Internal instance ID

        - `name` - Display name for the instance

        - `is_active` - Whether the instance is active

        - `fulfillment_mode` - Fulfillment mode: `fbm` (fulfilled by merchant) or
        `fbf` (fulfilled by Faire)

        - `order_import_start_date` - Date from which orders are imported

        - `warehouse_id` - Linked internal warehouse ID

        - `last_orders_sync` - ISO timestamp of last order sync

        - `last_products_sync` - ISO timestamp of last product sync

        - `created_at` / `updated_at` - ISO timestamps'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        is_authorized:
                          type: boolean
                        auth_method:
                          type: string
                        granted_scopes:
                          type: array
                          items:
                            type: string
                        is_automatic_sync_enabled:
                          type: boolean
                        fulfillment_mode:
                          type: string
                        order_import_start_date:
                          type: string
                        auto_create_products:
                          type: boolean
                        default_shipping_method_id:
                          type: integer
                        default_shipping_method:
                          type: object
                          properties:
                            id:
                              type: integer
                            method_name:
                              type: string
                            full_name:
                              type: string
                            carrier_name:
                              type: string
                        inventory:
                          type: object
                          properties:
                            masterOfStock:
                              type: string
                            selectedWarehouses:
                              type: array
                              items:
                                type: integer
                            inventoryModificationRules:
                              type: string
                              nullable: true
                        last_orders_sync:
                          type: string
                        last_products_sync:
                          type: string
                        orders_count:
                          type: integer
                        products_count:
                          type: integer
                        created_at:
                          type: string
                        updated_at:
                          type: string
                example:
                  data:
                  - id: 1
                    name: Faire Main Store
                    is_authorized: true
                    auth_method: oauth
                    granted_scopes:
                    - READ_PRODUCTS
                    - WRITE_PRODUCTS
                    - READ_ORDERS
                    - WRITE_ORDERS
                    - READ_BRAND
                    - READ_RETAILER
                    - READ_INVENTORIES
                    - WRITE_INVENTORIES
                    - READ_SHIPMENTS
                    - READ_REVIEWS
                    is_automatic_sync_enabled: true
                    fulfillment_mode: fbm
                    order_import_start_date: '2024-01-01'
                    auto_create_products: false
                    default_shipping_method_id: 12
                    default_shipping_method:
                      id: 12
                      method_name: UPS Ground
                      full_name: UPS — Ground
                      carrier_name: UPS
                    inventory:
                      masterOfStock: sku.io
                      selectedWarehouses:
                      - 3
                      inventoryModificationRules: null
                    last_orders_sync: '2026-04-24T10:00:00+00:00'
                    last_products_sync: '2026-04-24T09:00:00+00:00'
                    orders_count: 142
                    products_count: 27
                    created_at: '2026-01-15T12:00:00+00:00'
                    updated_at: '2026-04-24T10:00:00+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-faire-instances
    post:
      tags:
      - Faire
      summary: Create Faire Instance
      description: 'Create a new Faire integration instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Required Fields:**

        - `name` - Display name for this instance (max 255 chars)

        - `fulfillment_mode` - `fbm` (fulfilled by merchant) or `fbf` (fulfilled by
        Faire)


        **Optional Fields:**

        - `order_import_start_date` - Only import orders created on or after this
        date

        - `warehouse_id` - Link to an internal warehouse for inventory and fulfillment


        **OAuth Authorization:**

        After creation, the instance is unauthorized (`is_authorized: false`). The
        frontend must:

        1. Call `GET /api/faire/instances/{id}/authorization-url` to obtain the Faire
        OAuth redirect URL.

        2. Redirect the user (who **must be a Faire brand admin**) to that URL.

        3. Faire redirects back to `GET /faire/callback`, which exchanges the authorization
        code for a long-lived access token and persists it.


        **Response:**

        Returns the created integration instance with `is_authorized: false` and `granted_scopes:
        []`.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                fulfillment_mode:
                  type: string
                order_import_start_date:
                  type: string
                warehouse_id:
                  type: integer
              example:
                name: Faire Main Store
                fulfillment_mode: fbm
                order_import_start_date: '2024-01-01'
                warehouse_id: 3
      parameters: []
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      is_authorized:
                        type: boolean
                      auth_method:
                        type: string
                        nullable: true
                      granted_scopes:
                        type: array
                      is_automatic_sync_enabled:
                        type: boolean
                      fulfillment_mode:
                        type: string
                      order_import_start_date:
                        type: string
                      auto_create_products:
                        type: boolean
                      inventory:
                        type: object
                        properties:
                          masterOfStock:
                            type: string
                          selectedWarehouses:
                            type: array
                          inventoryModificationRules:
                            type: string
                            nullable: true
                      last_orders_sync:
                        type: string
                        nullable: true
                      last_products_sync:
                        type: string
                        nullable: true
                      orders_count:
                        type: integer
                      products_count:
                        type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 1
                    name: Faire Main Store
                    is_authorized: false
                    auth_method: null
                    granted_scopes: []
                    is_automatic_sync_enabled: false
                    fulfillment_mode: fbm
                    order_import_start_date: '2024-01-01'
                    auto_create_products: false
                    inventory:
                      masterOfStock: sku.io
                      selectedWarehouses: []
                      inventoryModificationRules: null
                    last_orders_sync: null
                    last_products_sync: null
                    orders_count: 0
                    products_count: 0
                    created_at: '2026-04-30T12:00:00+00:00'
                    updated_at: '2026-04-30T12:00:00+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-faire-instances
  /api/faire/instances/{integrationInstance}:
    get:
      tags:
      - Faire
      summary: Get Faire Instance
      description: 'Retrieve details of a specific Faire integration instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Path Parameters:**

        - `integrationInstance` - The ID of the integration instance


        **Response:**

        Returns full integration instance details including sync timestamps and configuration.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Faire Integration Instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      is_authorized:
                        type: boolean
                      auth_method:
                        type: string
                      granted_scopes:
                        type: array
                        items:
                          type: string
                      is_automatic_sync_enabled:
                        type: boolean
                      fulfillment_mode:
                        type: string
                      order_import_start_date:
                        type: string
                      auto_create_products:
                        type: boolean
                      default_shipping_method_id:
                        type: integer
                      default_shipping_method:
                        type: object
                        properties:
                          id:
                            type: integer
                          method_name:
                            type: string
                          full_name:
                            type: string
                          carrier_name:
                            type: string
                      inventory:
                        type: object
                        properties:
                          masterOfStock:
                            type: string
                          selectedWarehouses:
                            type: array
                            items:
                              type: integer
                          inventoryModificationRules:
                            type: string
                            nullable: true
                      last_orders_sync:
                        type: string
                      last_products_sync:
                        type: string
                      orders_count:
                        type: integer
                      products_count:
                        type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 1
                    name: Faire Main Store
                    is_authorized: true
                    auth_method: oauth
                    granted_scopes:
                    - READ_PRODUCTS
                    - WRITE_PRODUCTS
                    - READ_ORDERS
                    - WRITE_ORDERS
                    - READ_BRAND
                    - READ_RETAILER
                    - READ_INVENTORIES
                    - WRITE_INVENTORIES
                    - READ_SHIPMENTS
                    - READ_REVIEWS
                    is_automatic_sync_enabled: true
                    fulfillment_mode: fbm
                    order_import_start_date: '2024-01-01'
                    auto_create_products: false
                    default_shipping_method_id: 12
                    default_shipping_method:
                      id: 12
                      method_name: UPS Ground
                      full_name: UPS — Ground
                      carrier_name: UPS
                    inventory:
                      masterOfStock: sku.io
                      selectedWarehouses:
                      - 3
                      inventoryModificationRules: null
                    last_orders_sync: '2026-04-24T10:00:00+00:00'
                    last_products_sync: '2026-04-24T09:00:00+00:00'
                    orders_count: 142
                    products_count: 27
                    created_at: '2026-01-15T12:00:00+00:00'
                    updated_at: '2026-04-24T10:00:00+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-faire-instances-integrationinstance
    put:
      tags:
      - Faire
      summary: Update Faire Instance
      description: "Update an existing Faire integration instance.\n\n:::info[Authorization]\n\
        Any valid API token can call this endpoint — no specific scope required. [Manage\
        \ tokens](https://app.sku.io/settings/api).\n:::\n\n**Path Parameters:**\n\
        - `integrationInstance` - The ID of the integration instance\n\n**Partial\
        \ Updates:**\nAll fields are optional (use `sometimes` validation). Only the\
        \ fields you provide will be updated:\n- `name` - New display name (max 255\
        \ chars)\n- `order_import_start_date` - New import start date (or null to\
        \ remove)\n- `is_automatic_sync_enabled` - Toggle automatic background sync\
        \ (boolean)\n- `auto_create_products` - Auto-create local products from Faire\
        \ feed (boolean)\n- `default_shipping_method_id` - ID of the shipping method\
        \ applied to every sales order imported from Faire. Faire never provides a\
        \ shipping method on its orders, so this default is used for all imports.\
        \ Pass `null` to clear the default. The response includes a hydrated `default_shipping_method`\
        \ object (id, method_name, full_name, carrier_name) when set.\n- `inventory.masterOfStock`\
        \ - `sku.io` or `Neither`\n- `inventory.selectedWarehouses[]` - Array of warehouse\
        \ IDs whose stock contributes to the Faire inventory feed\n- `inventory.inventoryModificationRules`\
        \ - Min/max/buffer rules for the published inventory quantities\n- `financial_line_type_overrides`\
        \ - Optional object overriding the FinancialLineType used for the Faire-specific\
        \ lines created on each imported order. All keys are optional; pass `null`\
        \ to clear an override. **Classification is enforced** on each branch — see\
        \ below:\n  - `commission` - FinancialLineType ID (must be a `cost` type).\
        \ Applied to the marketplace fee Faire deducts on each order. Default branch\
        \ creates/uses `Faire Commission` (cost).\n  - `payout_fee` - FinancialLineType\
        \ ID (must be a `cost` type). Applied to the per-payout processing fee Faire\
        \ takes. Default branch creates/uses `Faire Payout Fee` (cost).\n  - `payout_protection_fee`\
        \ - FinancialLineType ID (must be a `cost` type). Applied when Faire deducts\
        \ a payout-protection insurance charge on an order. Default branch creates/uses\
        \ `Faire Payout Protection Fee` (cost).\n  - `damaged_and_missing_items` -\
        \ FinancialLineType ID (must be a `cost` type). Applied when Faire deducts\
        \ an adjustment for damaged or missing items on a delivered order. Default\
        \ branch creates/uses `Faire Damaged & Missing Items` (cost).\n  - `covered_shipping`\
        \ - FinancialLineType ID (must be a `revenue` type). Applied when Faire reimburses\
        \ shipping cost on covered orders. Default branch creates/uses `Faire-Covered\
        \ Shipping` (revenue).\n  - **Validation:** Mismatched classification (e.g.,\
        \ a revenue type passed for `commission`) returns `422` with `errors.financial_line_type_overrides.<branch>`.\n\
        \n**Note:** `fulfillment_mode` is fixed at creation time and ignored on update.\n\
        \n**Response:**\nReturns the updated integration instance, including the resolved\
        \ `financial_line_type_overrides` object (each branch is either `null` if\
        \ no override is configured, or `{ id, name, classification }`)."
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                order_import_start_date:
                  type: string
                is_automatic_sync_enabled:
                  type: boolean
                auto_create_products:
                  type: boolean
                default_shipping_method_id:
                  type: integer
                inventory:
                  type: object
                  properties:
                    masterOfStock:
                      type: string
                    selectedWarehouses:
                      type: array
                      items:
                        type: integer
                financial_line_type_overrides:
                  type: object
                  properties:
                    commission:
                      type: integer
                    payout_fee:
                      type: string
                      nullable: true
                    payout_protection_fee:
                      type: integer
                    damaged_and_missing_items:
                      type: integer
                    covered_shipping:
                      type: integer
              example:
                name: Faire Main Store - Updated
                order_import_start_date: '2024-03-01'
                is_automatic_sync_enabled: true
                auto_create_products: false
                default_shipping_method_id: 12
                inventory:
                  masterOfStock: sku.io
                  selectedWarehouses:
                  - 3
                  - 5
                financial_line_type_overrides:
                  commission: 12
                  payout_fee: null
                  payout_protection_fee: 14
                  damaged_and_missing_items: 15
                  covered_shipping: 17
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Faire Integration Instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      is_authorized:
                        type: boolean
                      auth_method:
                        type: string
                      granted_scopes:
                        type: array
                        items:
                          type: string
                      is_automatic_sync_enabled:
                        type: boolean
                      fulfillment_mode:
                        type: string
                      order_import_start_date:
                        type: string
                      auto_create_products:
                        type: boolean
                      default_shipping_method_id:
                        type: integer
                      default_shipping_method:
                        type: object
                        properties:
                          id:
                            type: integer
                          method_name:
                            type: string
                          full_name:
                            type: string
                          carrier_name:
                            type: string
                      inventory:
                        type: object
                        properties:
                          masterOfStock:
                            type: string
                          selectedWarehouses:
                            type: array
                            items:
                              type: integer
                          inventoryModificationRules:
                            type: string
                            nullable: true
                      financial_line_type_overrides:
                        type: object
                        properties:
                          commission:
                            type: object
                            properties:
                              id:
                                type: integer
                              name:
                                type: string
                              classification:
                                type: string
                          payout_fee:
                            type: string
                            nullable: true
                          payout_protection_fee:
                            type: object
                            properties:
                              id:
                                type: integer
                              name:
                                type: string
                              classification:
                                type: string
                          damaged_and_missing_items:
                            type: object
                            properties:
                              id:
                                type: integer
                              name:
                                type: string
                              classification:
                                type: string
                          covered_shipping:
                            type: object
                            properties:
                              id:
                                type: integer
                              name:
                                type: string
                              classification:
                                type: string
                      last_orders_sync:
                        type: string
                      last_products_sync:
                        type: string
                      orders_count:
                        type: integer
                      products_count:
                        type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 1
                    name: Faire Main Store
                    is_authorized: true
                    auth_method: oauth
                    granted_scopes:
                    - READ_PRODUCTS
                    - WRITE_PRODUCTS
                    - READ_ORDERS
                    - WRITE_ORDERS
                    - READ_BRAND
                    - READ_RETAILER
                    - READ_INVENTORIES
                    - WRITE_INVENTORIES
                    - READ_SHIPMENTS
                    - READ_REVIEWS
                    is_automatic_sync_enabled: true
                    fulfillment_mode: fbm
                    order_import_start_date: '2024-01-01'
                    auto_create_products: false
                    default_shipping_method_id: 12
                    default_shipping_method:
                      id: 12
                      method_name: UPS Ground
                      full_name: UPS — Ground
                      carrier_name: UPS
                    inventory:
                      masterOfStock: sku.io
                      selectedWarehouses:
                      - 3
                      inventoryModificationRules: null
                    financial_line_type_overrides:
                      commission:
                        id: 12
                        name: Marketplace Commissions
                        classification: cost
                      payout_fee: null
                      payout_protection_fee:
                        id: 14
                        name: Marketplace Insurance
                        classification: cost
                      damaged_and_missing_items:
                        id: 15
                        name: Order Adjustments
                        classification: cost
                      covered_shipping:
                        id: 17
                        name: Shipping Income
                        classification: revenue
                    last_orders_sync: '2026-04-24T10:00:00+00:00'
                    last_products_sync: '2026-04-24T09:00:00+00:00'
                    orders_count: 142
                    products_count: 27
                    created_at: '2026-01-15T12:00:00+00:00'
                    updated_at: '2026-04-24T10:00:00+00:00'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      financial_line_type_overrides.commission:
                        type: array
                        items:
                          type: string
                example:
                  message: The selected financial line type for commission must be
                    a Cost type.
                  errors:
                    financial_line_type_overrides.commission:
                    - The selected financial line type for commission must be a Cost
                      type.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: put-api-faire-instances-integrationinstance
    delete:
      tags:
      - Faire
      summary: Delete Faire Instance
      description: 'Delete a Faire integration instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Path Parameters:**

        - `integrationInstance` - The ID of the integration instance to delete


        **Important:**

        - This action permanently deletes the instance and all associated data

        - Cannot be undone


        **Response:**

        Returns a success message.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Faire Integration Instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Integration deleted successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-faire-instances-integrationinstance
  /api/faire/instances/{integrationInstance}/financial-line-overrides/preview-backfill:
    post:
      tags:
      - Faire
      summary: Preview Financial Line Backfill
      description: "Preview how many past Faire-imported FinancialLine rows would\
        \ be re-keyed if the supplied override map were applied. **Does not modify\
        \ any data.**\n\n:::info[Authorization]\nAny valid API token can call this\
        \ endpoint — no specific scope required. [Manage tokens](https://app.sku.io/settings/api).\n\
        :::\n\n**Request Body:**\n- `overrides` (object, required) - Same shape as\
        \ the `financial_line_type_overrides` field on the update endpoint. Each branch\
        \ is optional; pass `null` to indicate \"no override\" for that branch.\n\
        \  - `commission` (int|null) - FinancialLineType ID, must be a `cost` type\
        \ when supplied.\n  - `payout_fee` (int|null) - FinancialLineType ID, must\
        \ be a `cost` type when supplied.\n  - `payout_protection_fee` (int|null)\
        \ - FinancialLineType ID, must be a `cost` type when supplied.\n  - `damaged_and_missing_items`\
        \ (int|null) - FinancialLineType ID, must be a `cost` type when supplied.\n\
        \  - `covered_shipping` (int|null) - FinancialLineType ID, must be a `revenue`\
        \ type when supplied.\n\n**Validation:**\nClassification mismatch returns\
        \ `422` with `errors.overrides.<branch>` — same guard as the update endpoint.\n\
        \n**Use case:**\nThe Faire settings UI calls this when the user changes any\
        \ override and presses Save, so the confirmation modal can show \"X record(s)\
        \ will be backfilled\" before they decide whether to run the backfill or just\
        \ save the new override forward.\n\n**Response:**\nReturns a `{ commission,\
        \ payout_fee, payout_protection_fee, damaged_and_missing_items, covered_shipping,\
        \ total }` object. Each number is the count of past Faire FinancialLine rows\
        \ that would be re-keyed for that branch under the supplied overrides; `total`\
        \ is their sum. Branches not present in the overrides map (or sent as `null`)\
        \ report `0`."
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                overrides:
                  type: object
                  properties:
                    commission:
                      type: integer
                    payout_fee:
                      type: string
                      nullable: true
                    payout_protection_fee:
                      type: integer
                    damaged_and_missing_items:
                      type: integer
                    covered_shipping:
                      type: integer
              example:
                overrides:
                  commission: 12
                  payout_fee: null
                  payout_protection_fee: 14
                  damaged_and_missing_items: 15
                  covered_shipping: 17
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Faire Integration Instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      commission:
                        type: integer
                      payout_fee:
                        type: integer
                      payout_protection_fee:
                        type: integer
                      damaged_and_missing_items:
                        type: integer
                      covered_shipping:
                        type: integer
                      total:
                        type: integer
                example:
                  data:
                    commission: 142
                    payout_fee: 0
                    payout_protection_fee: 87
                    damaged_and_missing_items: 6
                    covered_shipping: 19
                    total: 254
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      overrides.covered_shipping:
                        type: array
                        items:
                          type: string
                example:
                  message: The selected financial line type for covered_shipping must
                    be a Revenue type.
                  errors:
                    overrides.covered_shipping:
                    - The selected financial line type for covered_shipping must be
                      a Revenue type.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-faire-instances-integrationinstance-financial-line-overrides-preview-backfill
  /api/faire/instances/{integrationInstance}/financial-line-overrides/backfill:
    post:
      tags:
      - Faire
      summary: Apply Financial Line Backfill
      description: 'Re-key past Faire-imported FinancialLine rows to the override
        types that are **already persisted** on the integration instance. **No request
        body** — the overrides are read off `integration_settings.financial_line_type_overrides`,
        which is set via the Update Faire Instance endpoint.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Branches covered:**

        `commission`, `payout_fee`, `payout_protection_fee`, `damaged_and_missing_items`
        (all `cost`), `covered_shipping` (`revenue`).


        **Behavior per row:**

        - Updates `financial_line_type_id` to the override''s ID.

        - Copies the override''s `nominal_code_id` onto the row (so accounting export
        reflects the new mapping).

        - Does **not** change line `amount`, `currency`, or any other monetary field.

        - Branches with no override configured (or set to `null`) are skipped entirely
        — those past rows keep their existing default Faire types.


        **Typical flow:**

        1. User changes overrides in the Faire settings UI.

        2. UI calls `PUT /api/faire/instances/{id}` with the new `financial_line_type_overrides`
        (this also passes the classification guard).

        3. UI calls `POST .../financial-line-overrides/preview-backfill` to show the
        count to the user.

        4. If the user confirms, UI calls **this** endpoint to apply the change to
        historical rows.


        **Response:**

        Returns a `{ commission, payout_fee, payout_protection_fee, damaged_and_missing_items,
        covered_shipping, total }` object where each number is the count of rows actually
        updated (i.e., rows whose existing type differed from the override). `total`
        is the sum across branches.'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Faire Integration Instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      commission:
                        type: integer
                      payout_fee:
                        type: integer
                      payout_protection_fee:
                        type: integer
                      damaged_and_missing_items:
                        type: integer
                      covered_shipping:
                        type: integer
                      total:
                        type: integer
                example:
                  data:
                    commission: 142
                    payout_fee: 0
                    payout_protection_fee: 87
                    damaged_and_missing_items: 6
                    covered_shipping: 19
                    total: 254
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-faire-instances-integrationinstance-financial-line-overrides-backfill
  /api/faire/oauth/config:
    get:
      tags:
      - Faire
      summary: Get OAuth Config
      description: 'Return the public OAuth metadata used by the frontend to render
        the authorization flow.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Response fields:**

        - `scopes` - Faire OAuth scopes the app requests

        - `redirect_url` - The redirect URL registered with Faire (where Faire sends
        users back after authorization)

        - `authorize_url` - Faire''s authorization endpoint base URL


        **Auth:** Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      scopes:
                        type: array
                        items:
                          type: string
                      redirect_url:
                        type: string
                      authorize_url:
                        type: string
                example:
                  data:
                    scopes:
                    - READ_PRODUCTS
                    - WRITE_PRODUCTS
                    - READ_ORDERS
                    - WRITE_ORDERS
                    - READ_BRAND
                    - READ_RETAILER
                    - READ_INVENTORIES
                    - WRITE_INVENTORIES
                    - READ_SHIPMENTS
                    - READ_REVIEWS
                    redirect_url: https://app.sku.io/faire/callback
                    authorize_url: https://faire.com/oauth2/authorize
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-faire-oauth-config
  /api/faire/instances/{integrationInstance}/authorization-url:
    get:
      tags:
      - Faire
      summary: Get Authorization URL
      description: 'Generate the Faire OAuth authorization URL for this integration
        instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Generates a CSRF state token (format: `{app.url}_{instance_id}`), stores it
        in the user''s session, and returns the fully-formed Faire authorization URL.


        **Path Parameters:**

        - `integrationInstance` - The ID of the integration instance to authorize


        **Response field:**

        - `authorization_url` - URL to redirect the user to. The user must be a Faire
        brand admin.


        **Auth:** Requires Bearer token. CSRF state is bound to the user''s session,
        so the same session must complete the callback.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Faire integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      authorization_url:
                        type: string
                example:
                  data:
                    authorization_url: https://faire.com/oauth2/authorize?applicationId=test-app-id&scope=READ_PRODUCTS%2CWRITE_PRODUCTS%2CREAD_ORDERS%2CWRITE_ORDERS%2CREAD_BRAND%2CREAD_RETAILER%2CREAD_INVENTORIES%2CWRITE_INVENTORIES%2CREAD_SHIPMENTS%2CREAD_REVIEWS&state=https%3A%2F%2Fapp.sku.io_1&redirectUrl=https%3A%2F%2Fapp.sku.io%2Ffaire%2Fcallback
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-faire-instances-integrationinstance-authorization-url
  /faire/callback:
    get:
      tags:
      - Faire
      summary: OAuth Callback (Faire → SKU)
      description: 'OAuth callback hit by Faire after the user authorizes the app.
        **Not called manually** — Faire redirects the user''s browser to this URL.


        **Flow:**

        1. Validates the `state` parameter against the value stored in the user''s
        session (CSRF protection).

        2. Calls Faire''s token endpoint to exchange `authorization_code` for a long-lived
        `access_token`.

        3. Persists the access token + granted scopes on the integration instance.

        4. Redirects to `/v2/integrations/faire/{id}/dashboard` on success, or `/v2/integrations/faire/{id}/settings?oauth_error=...`
        on failure.


        **Query Parameters:**

        - `state` (required) - CSRF state, format `{app.url}_{instance_id}`

        - `authorization_code` (required, alias `code`) - One-time auth code from
        Faire


        **Auth:** Web session (no Bearer token). Faire redirects the user''s browser,
        so the call lands on the `web` middleware group, not `auth:sanctum`.


        **Errors:**

        - `400 State mismatch` - The state in the request doesn''t match the session

        - `404 Faire integration not found` - Instance referenced by state has been
        deleted

        - Redirect with `?oauth_error=...` - Token exchange failed at Faire''s side'
      parameters:
      - name: state
        in: query
        schema:
          type: string
        description: 'CSRF state token returned by Faire. Format: `{app.url}_{integration_instance_id}`.
          Must match the value stored in the session by the Get Authorization URL
          endpoint.'
        example: https%3A%2F%2Fapp.sku.io_1
      - name: authorization_code
        in: query
        schema:
          type: string
        description: One-time authorization code from Faire (also accepted as `code`).
        example: auth-code-123
      responses:
        '302':
          description: Found
          headers:
            Location:
              schema:
                type: string
                example: /v2/integrations/faire/1/dashboard
          content:
            text/plain:
              schema:
                type: string
                example: ''
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-faire-callback
  /api/faire/instances/{integrationInstance}/revoke:
    post:
      tags:
      - Faire
      summary: Revoke Authorization
      description: 'Revoke the stored Faire access token both at Faire (`POST /api/external-api-oauth2/revoke`)
        and locally on the integration instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        After revocation, `is_authorized` will be `false` and `granted_scopes` will
        be empty. The instance must be re-authorized via the OAuth flow before it
        can sync again.


        **Path Parameters:**

        - `integrationInstance` - The ID of the integration instance


        **Auth:** Requires Bearer token.


        **Errors:**

        - `422` - Faire returned an error during revocation (e.g., already revoked,
        invalid token). The local token is still cleared.'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Faire integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Faire authorization revoked
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-faire-instances-integrationinstance-revoke
  /api/faire/instances/{integrationInstance}/access-token:
    post:
      tags:
      - Faire
      summary: Set Access Token Manually
      description: 'Persist a Faire long-lived access token directly onto the integration
        instance — an alternative to the OAuth Authorization Code flow.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Why this exists:** Faire only allows **one live OAuth token per brand**
        at a time, and the brand admin app does **not** expose a way to revoke an
        existing OAuth token. Tenants who already have a long-lived token (e.g., issued
        for a previous integration) can paste it here instead of running the browser-driven
        OAuth flow.


        **What it does:**

        - Stores the token on the integration instance''s `connection_settings.access_token`

        - Tags `connection_settings.auth_method = "manual"` so the UI and revoke flow
        can differentiate this from OAuth-issued tokens

        - Sets `granted_scopes` to the full default set from `config(''faire.scopes'')`
        (we cannot introspect a user-supplied token to determine its actual scopes)

        - After saving, `is_authorized` becomes `true` immediately — the instance
        is ready to sync


        **Revocation behavior:** When `auth_method = "manual"`, the `POST /revoke`
        endpoint clears the token locally without calling Faire''s revoke endpoint
        — we did not issue this token so we have no business revoking it at Faire
        (the user may still be using it elsewhere).


        **Path Parameters:**

        - `integrationInstance` (required) - The ID of the Faire integration instance


        **Request Body:**

        - `access_token` (required, string, min:10, max:4096) - The Faire long-lived
        access token


        **Auth:** Requires Bearer token.


        **Errors:**

        - `422` - `access_token` is missing, too short (<10 chars), or longer than
        4096 chars'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                access_token:
                  type: string
              example:
                access_token: fa_live_long_lived_token_xyz123abc456def789ghi
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Faire integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      is_authorized:
                        type: boolean
                      auth_method:
                        type: string
                      granted_scopes:
                        type: array
                        items:
                          type: string
                      is_automatic_sync_enabled:
                        type: boolean
                      fulfillment_mode:
                        type: string
                      order_import_start_date:
                        type: string
                      auto_create_products:
                        type: boolean
                      default_shipping_method_id:
                        type: integer
                      default_shipping_method:
                        type: object
                        properties:
                          id:
                            type: integer
                          method_name:
                            type: string
                          full_name:
                            type: string
                          carrier_name:
                            type: string
                      inventory:
                        type: object
                        properties:
                          masterOfStock:
                            type: string
                          selectedWarehouses:
                            type: array
                            items:
                              type: integer
                          inventoryModificationRules:
                            type: string
                            nullable: true
                      last_orders_sync:
                        type: string
                      last_products_sync:
                        type: string
                      orders_count:
                        type: integer
                      products_count:
                        type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 1
                    name: Faire Main Store
                    is_authorized: true
                    auth_method: manual
                    granted_scopes:
                    - READ_PRODUCTS
                    - WRITE_PRODUCTS
                    - READ_ORDERS
                    - WRITE_ORDERS
                    - READ_INVENTORIES
                    - WRITE_INVENTORIES
                    - READ_SHIPMENTS
                    is_automatic_sync_enabled: true
                    fulfillment_mode: fbm
                    order_import_start_date: '2024-01-01'
                    auto_create_products: false
                    default_shipping_method_id: 12
                    default_shipping_method:
                      id: 12
                      method_name: UPS Ground
                      full_name: UPS — Ground
                      carrier_name: UPS
                    inventory:
                      masterOfStock: sku.io
                      selectedWarehouses:
                      - 3
                      inventoryModificationRules: null
                    last_orders_sync: '2026-04-24T10:00:00+00:00'
                    last_products_sync: '2026-04-24T09:00:00+00:00'
                    orders_count: 142
                    products_count: 27
                    created_at: '2026-01-15T12:00:00+00:00'
                    updated_at: '2026-05-10T08:00:00+00:00'
                  message: Faire access token saved
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      access_token:
                        type: array
                        items:
                          type: string
                example:
                  message: The access token field is required.
                  errors:
                    access_token:
                    - The access token field is required.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-faire-instances-integrationinstance-access-token
  /api/faire/instances/{integrationInstance}/reuse-connection:
    post:
      tags:
      - Faire
      summary: Reuse Existing Connection
      description: 'Reuse the connection from another authorized Faire integration
        instance instead of authorizing again.


        **Why this exists:** Faire allows only **one live access token per brand**,
        and the brand portal does not let you revoke or re-issue it. When you add
        a second Faire integration for the same brand — typically a Fulfilled-by-Faire
        (FBF) integration alongside an existing Fulfilled-by-Merchant (FBM) one —
        authorizing again could invalidate the first integration''s token. Reuse copies
        the existing integration''s long-lived token onto this one so both work on
        the same Faire account.


        **What it does:**

        - Copies the source integration''s access token and scopes onto this integration

        - Verifies the copied token against Faire before saving it (an invalid source
        connection is rejected, nothing is persisted)

        - Records the Faire brand so both integrations are grouped as one shared connection

        - After success, `is_authorized` becomes `true` and `auth_method` is `reused`


        **Requirements:** the source integration must be authorized and must have
        the **opposite** fulfillment mode (FBM ↔ FBF). Reusing from a same-mode integration
        is rejected, because one Faire account can only be one mode at a time.


        **Disconnecting a shared connection** clears the token from that one integration
        only — it does not sign the shared Faire login out, so the other integration
        keeps working.


        **Path Parameters:**

        - `integrationInstance` (required) — the integration receiving the reused
        connection


        **Request Body:**

        - `source_instance_id` (required, integer) — the authorized, opposite-mode
        integration to copy the connection from


        **Auth:** Requires Bearer token.


        **Errors:**

        - `422` — the source does not exist, is not authorized, is the same integration,
        is the same fulfillment mode, or its token failed verification with Faire'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                source_instance_id:
                  type: integer
              example:
                source_instance_id: 1
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Faire integration instance ID (the new instance receiving the
          reused connection)
        example: '2'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      is_authorized:
                        type: boolean
                      auth_method:
                        type: string
                      granted_scopes:
                        type: array
                        items:
                          type: string
                      brand_id:
                        type: string
                      brand_name:
                        type: string
                      reused_from_instance_id:
                        type: integer
                      shared_connection:
                        type: boolean
                      connection_group_member_ids:
                        type: array
                        items:
                          type: integer
                      is_automatic_sync_enabled:
                        type: boolean
                      fulfillment_mode:
                        type: string
                      order_import_start_date:
                        type: string
                        nullable: true
                      effective_order_import_start_date:
                        type: string
                      auto_create_products:
                        type: boolean
                      default_shipping_method_id:
                        type: string
                        nullable: true
                      default_shipping_method:
                        type: string
                        nullable: true
                      inventory:
                        type: object
                        properties:
                          auto_sync:
                            type: boolean
                      financial_line_type_overrides:
                        type: object
                        properties:
                          commission:
                            type: string
                            nullable: true
                          payout_fee:
                            type: string
                            nullable: true
                          payout_protection_fee:
                            type: string
                            nullable: true
                          damaged_and_missing_items:
                            type: string
                            nullable: true
                          covered_shipping:
                            type: string
                            nullable: true
                      last_orders_sync:
                        type: string
                        nullable: true
                      last_products_sync:
                        type: string
                        nullable: true
                      orders_count:
                        type: integer
                      products_count:
                        type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 2
                    name: A Bar Above — FBF
                    is_authorized: true
                    auth_method: reused
                    granted_scopes:
                    - READ_PRODUCTS
                    - WRITE_PRODUCTS
                    - READ_ORDERS
                    - WRITE_ORDERS
                    - READ_BRAND
                    - READ_INVENTORIES
                    brand_id: b_abcd1234
                    brand_name: A Bar Above
                    reused_from_instance_id: 1
                    shared_connection: true
                    connection_group_member_ids:
                    - 2
                    - 1
                    is_automatic_sync_enabled: false
                    fulfillment_mode: fbf
                    order_import_start_date: null
                    effective_order_import_start_date: '2026-06-23'
                    auto_create_products: false
                    default_shipping_method_id: null
                    default_shipping_method: null
                    inventory:
                      auto_sync: false
                    financial_line_type_overrides:
                      commission: null
                      payout_fee: null
                      payout_protection_fee: null
                      damaged_and_missing_items: null
                      covered_shipping: null
                    last_orders_sync: null
                    last_products_sync: null
                    orders_count: 0
                    products_count: 0
                    created_at: '2026-07-23T14:05:00+00:00'
                    updated_at: '2026-07-23T14:05:12+00:00'
                  message: Connection reused from A Bar Above — FBM
        '422':
          description: Unprocessable Content
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: Validation Error (Same Mode / Not Authorized)
                  value:
                    message: The selected connection is not authorized.
                    errors:
                      source_instance_id:
                      - Reuse is only available between opposite fulfillment modes
                        (FBM ↔ FBF).
                example-1:
                  summary: Verification Failed (Dead Source Token)
                  value:
                    message: The selected connection is no longer valid — reconnect
                      it first.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-faire-instances-integrationinstance-reuse-connection
  /api/faire/instances/{integrationInstance}/validate-connection:
    post:
      tags:
      - Faire
      summary: Validate Connection
      description: 'Verify this integration''s stored access token against Faire and
        capture the brand it belongs to.


        Calls Faire to confirm the token is live and reads the brand name/id, which
        is stored on the integration. Use it to re-check a connection''s health or
        to populate the brand before grouping two integrations that share one Faire
        account.


        **Path Parameters:**

        - `integrationInstance` (required) — the integration to verify


        **Auth:** Requires Bearer token.


        **Errors:**

        - `422` — the token could not be verified with Faire (missing, revoked, or
        unreachable)'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Faire integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      valid:
                        type: boolean
                      brand_id:
                        type: string
                      brand_name:
                        type: string
                example:
                  data:
                    valid: true
                    brand_id: b_abcd1234
                    brand_name: A Bar Above
        '422':
          description: Unprocessable Content
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      valid:
                        type: boolean
                  message:
                    type: string
                example:
                  data:
                    valid: false
                  message: Could not verify this connection with Faire.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-faire-instances-integrationinstance-validate-connection
  /api/faire/instances/{integrationInstance}/sync-orders:
    post:
      tags:
      - Faire
      summary: Sync Orders
      description: 'Trigger an order sync from Faire for a specific integration instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Path Parameters:**

        - `integrationInstance` - The ID of the integration instance


        **Behavior:**

        - Dispatches a background job immediately

        - The job pulls all new/updated orders from the Faire API since the last sync
        cursor

        - **Multi-tenant safety:** Each order''s top-level `is_fulfilled_by_faire`
        flag is compared against the instance''s `fulfillment_mode` setting before
        persisting. FBM instances skip orders flagged `is_fulfilled_by_faire=true`;
        FBF instances skip orders flagged `is_fulfilled_by_faire=false`. This prevents
        a brand that shares an OAuth token across an FBM and FBF instance from cross-contaminating
        either side. The skipped count is recorded in the sync log.

        - Combined with the composite-unique constraint on `(integration_instance_id,
        faire_order_id)`, two sibling instances can safely sync the same brand simultaneously
        without stomping each other''s rows.

        - Progress can be tracked via the returned `tracked_job_log_id`


        **Response:**

        Returns immediately with a tracked job log ID. Use the tracked job log endpoints
        to monitor completion.'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Faire Integration Instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 142
                  message: Order sync started
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-faire-instances-integrationinstance-sync-orders
  /api/faire/instances/{integrationInstance}/sync-products:
    post:
      tags:
      - Faire
      summary: Sync Products
      description: 'Trigger a product catalog sync from Faire for a specific integration
        instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Path Parameters:**

        - `integrationInstance` - The ID of the integration instance


        **Behavior:**

        - Dispatches a background job immediately

        - The job pulls the full product catalog from the Faire API, including product
        options (variants) and current inventory levels

        - **Multi-tenant safety:** Products and variants are upserted on the composite
        `(integration_instance_id, faire_product_id)` / `(faire_product_id, faire_variant_id)`
        keys, so two sibling instances on the same brand cannot stomp each other''s
        rows.

        - Progress can be tracked via the returned `tracked_job_log_id`


        **Response:**

        Returns immediately with a tracked job log ID.'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Faire Integration Instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 143
                  message: Product sync started
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-faire-instances-integrationinstance-sync-products
  /api/faire/instances/{integrationInstance}/sync-inventory:
    post:
      tags:
      - Faire
      summary: Sync Inventory
      description: 'Trigger an inventory sync to push current inventory levels to
        Faire for a specific integration instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Path Parameters:**

        - `integrationInstance` - The ID of the integration instance


        **Behavior:**

        - Dispatches a background job immediately

        - The job reads current inventory from the linked warehouse and pushes levels
        to the Faire API for each product variant

        - Progress can be tracked via the returned `tracked_job_log_id`


        **Response:**

        Returns immediately with a tracked job log ID.'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Faire Integration Instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 144
                  message: Inventory sync started
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-faire-instances-integrationinstance-sync-inventory
  /api/faire/orders:
    get:
      tags:
      - Faire
      summary: List Faire Orders
      description: "List Faire orders for a specific integration instance.\n\n:::info[Authorization]\n\
        Any valid API token can call this endpoint — no specific scope required. [Manage\
        \ tokens](https://app.sku.io/settings/api).\n:::\n\n**Tenant resolution (multi-instance\
        \ safety):**\nBoth shapes are accepted, in priority order:\n- `filter[integration_instance_ids]`\
        \ (preferred, Amazon-unified plural form; comma-separated CSV — first ID wins)\n\
        - `filter[instance_id]` (legacy singular)\n- `?instance_id=` query string\
        \ fallback\n- body `instance_id` (POST/PUT only)\n\nIf none resolve to an\
        \ existing FaireIntegrationInstance the endpoint returns an empty/zeroed payload\
        \ — it does NOT silently fall back to the first tenant's data.\n\n**Empty-paginator\
        \ response shape** (when no instance can be resolved):\n```json\n{\n  \"current_page\"\
        : 1,\n  \"data\": [],\n  \"total\": 0,\n  \"per_page\": 15\n}\n```\n\n---\n\
        \nList Faire orders with rich Spatie QueryBuilder filtering, sorting and pagination.\
        \ Defaults to **Active** orders (excludes archived) — mirrors the Purchase\
        \ Orders bottom-bar pattern. Use `filter[archived]=only` for archived rows,\
        \ `filter[archived]=all` for both.\n\n**Query Parameters — Pagination & Sort:**\n\
        - `instance_id` (optional) — Filter to a specific integration instance. Defaults\
        \ to the first instance.\n- `page` (default `1`), `per_page` (default `10`)\n\
        - `sort` — Prefix with `-` for DESC. Default `-ordered_at`. Allowed: `id`,\
        \ `ordered_at`, `shipped_at`, `delivered_at`, `created_at`, `updated_at`,\
        \ `total`, `subtotal`, `discount_amount`, `status`, `retailer_name`, `retailer_country_code`.\n\
        \n**Search:**\n- `filter[search]` — AdvancedSearchFilter across `display_id`,\
        \ `faire_order_id`, `retailer_name`.\n\n**Archived Toggle (default-active):**\n\
        - `filter[archived]=` (or omitted) — Active only\n- `filter[archived]=only`\
        \ — Archived only\n- `filter[archived]=all` — Both\n\n**Identity / Display:**\n\
        - `filter[status]`, `filter[display_id]`, `filter[faire_order_id]`\n\n**Retailer:**\n\
        - `filter[retailer_name]`, `filter[retailer_country_code]`, `filter[retailer_state]`\n\
        \n**Money (numeric operators):**\n- `filter[total]`, `filter[subtotal]`, `filter[discount_amount]`,\
        \ `filter[currency_code]`\n\n**Dates (datetime operators — `[between]`, `[gte]`,\
        \ `[lte]`, `[eq]`):**\n- `filter[ordered_at]`, `filter[shipped_at]`, `filter[delivered_at]`,\
        \ `filter[updated_at]`, `filter[created_at]`\n\n**Tracking:**\n- `filter[tracking_number]`,\
        \ `filter[tracking_carrier]`, `filter[tracking_submission_status]` (`pending`,\
        \ `submitted`, `failed`)\n\n**Boolean callbacks:**\n- `filter[has_sku_order]=true|false`\
        \ — Has a linked SKU.io sales order.\n- `filter[has_unmapped_items]=true|false`\
        \ — Has at least one line item without a SKU mapping.\n- `filter[pre_start_date_import]=true|false`\
        \ — Order was imported via the pre-start-date flow.\n\n**Operator suffixes:**\
        \ combine any text/numeric/datetime filter with operator suffixes via `filter[column][operator]=value`\
        \ (e.g. `filter[status][is_one_of]=NEW,PROCESSING`, `filter[total][gte]=100`,\
        \ `filter[ordered_at][between]=2026-04-01,2026-05-01`).\n\n**Response Fields\
        \ per Order:**\n- `id`, `integration_instance_id`, `faire_order_id`, `display_id`,\
        \ `status`\n- `retailer_id`, `retailer_name`, `retailer_state`, `retailer_country_code`\n\
        - `subtotal`, `discount_amount`, `total`, `currency_code` (monetary fields\
        \ are stored as integers in cents)\n- `ordered_at`, `shipped_at`, `delivered_at`,\
        \ `archived_at`, `created_at`\n- `tracking_number`, `tracking_carrier`, `tracking_submission_status`\n\
        - `line_items` — Loaded via eager-load (see Show Order for the full shape)\n\
        \n**Linked SKU.io product on each line item:**\nThe per-line `sku_product_id`,\
        \ `sku_product_route`, and `sku_product` fields resolve through the `FaireProductOption\
        \ → ProductListing → Product` chain (matched on `faire_variant_id`). They\
        \ are populated **only when the variant has been explicitly mapped** — either\
        \ via the Variants Listing page \"Map\" button, Smart Match, or Bulk Map.\
        \ String-based SKU matching is intentionally NOT used. A line whose `sku`\
        \ happens to match a Product's `sku` but whose variant has never been mapped\
        \ will return `sku_product_id: null` (\"Unlinked\" in the UI) — the same behaviour\
        \ as the Shopify line item resource and the Variants Listing page itself."
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        faire_order_id:
                          type: string
                        display_id:
                          type: string
                        status:
                          type: string
                        retailer_id:
                          type: string
                        retailer_name:
                          type: string
                        retailer_state:
                          type: string
                        retailer_country_code:
                          type: string
                        subtotal:
                          type: integer
                        discount_amount:
                          type: integer
                        total:
                          type: integer
                        currency_code:
                          type: string
                        ordered_at:
                          type: string
                        shipped_at:
                          type: string
                          nullable: true
                        delivered_at:
                          type: string
                          nullable: true
                        tracking_number:
                          type: string
                          nullable: true
                        tracking_carrier:
                          type: string
                          nullable: true
                        tracking_submission_status:
                          type: string
                          nullable: true
                        tracking_submitted_at:
                          type: string
                          nullable: true
                        tracking_submission_error:
                          type: string
                          nullable: true
                        tracking_submission_attempts:
                          type: integer
                        line_items:
                          type: array
                          items:
                            type: object
                            properties:
                              id:
                                type: integer
                              faire_line_item_id:
                                type: string
                              faire_product_id:
                                type: string
                              faire_variant_id:
                                type: string
                              sku:
                                type: string
                              name:
                                type: string
                              option_values:
                                type: string
                                nullable: true
                              quantity:
                                type: integer
                              unit_price:
                                type: number
                              total_price:
                                type: integer
                              sku_product_id:
                                type: integer
                              sku_product_route:
                                type: string
                              sku_product:
                                type: object
                                properties:
                                  id:
                                    type: integer
                                  sku:
                                    type: string
                                  name:
                                    type: string
                                  type:
                                    type: string
                        sales_order:
                          type: object
                          properties:
                            id:
                              type: integer
                            sales_order_number:
                              type: string
                            order_status:
                              type: string
                            fulfillment_status:
                              type: string
                            payment_status:
                              type: string
                        created_at:
                          type: string
                        archived_at:
                          type: string
                          nullable: true
                        is_archived:
                          type: boolean
                        faire_admin_url:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - id: 101
                    integration_instance_id: 1
                    faire_order_id: bo_abc123xyz
                    display_id: FO-0001
                    status: PROCESSING
                    retailer_id: b_xyz789
                    retailer_name: The Boutique Shop
                    retailer_state: CA
                    retailer_country_code: US
                    subtotal: 15000
                    discount_amount: 0
                    total: 15000
                    currency_code: USD
                    ordered_at: '2026-04-20T08:30:00+00:00'
                    shipped_at: null
                    delivered_at: null
                    tracking_number: null
                    tracking_carrier: null
                    tracking_submission_status: null
                    tracking_submitted_at: null
                    tracking_submission_error: null
                    tracking_submission_attempts: 0
                    line_items:
                    - id: 451
                      faire_line_item_id: li_a1b2c3d4
                      faire_product_id: p_xyz123
                      faire_variant_id: opt_qr789
                      sku: WIDGET-RED-LG
                      name: Widget — Red, Large
                      option_values: null
                      quantity: 2
                      unit_price: 24.5
                      total_price: 49
                      sku_product_id: 89
                      sku_product_route: /products/89
                      sku_product:
                        id: 89
                        sku: WIDGET-RED-LG
                        name: Red Widget — Large
                        type: standard
                    - id: 452
                      faire_line_item_id: li_e5f6g7h8
                      faire_product_id: p_abc456
                      faire_variant_id: opt_st012
                      sku: FAIRE-ONLY-SKU
                      name: Item not yet mapped to SKU.io
                      option_values: null
                      quantity: 1
                      unit_price: 18
                      total_price: 18
                      sku_product_id: null
                      sku_product_route: null
                      sku_product: null
                    sales_order:
                      id: 57520
                      sales_order_number: FO-0001
                      order_status: open
                      fulfillment_status: unfulfilled
                      payment_status: paid
                    created_at: '2026-04-20T08:32:00+00:00'
                    archived_at: null
                    is_archived: false
                    faire_admin_url: https://www.faire.com/brand-portal/orders/bo_abc123xyz/order-fulfilment
                  current_page: 1
                  last_page: 5
                  per_page: 10
                  total: 47
                  from: 1
                  to: 10
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-faire-orders
  /api/faire/orders/{order}:
    get:
      tags:
      - Faire
      summary: Get Faire Order
      description: 'Get details of a specific Faire order including its line items.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Path Parameters:**

        - `order` — The internal Faire order ID (`faire_orders.id`)


        **Response:**

        Returns the full FaireOrderDetail (Faire order object on show) including `raw_data`,
        `sales_order`, `is_archived`, `archived_at`, `faire_admin_url`, and the `line_items`
        array. Each line item includes:

        - `id`, `faire_line_item_id`, `faire_product_id`, `faire_variant_id` — Faire-side
        identifiers

        - `sku`, `name`, `option_values` — Product details from Faire

        - `quantity`, `unit_price`, `total_price`

        - `sku_product_id` — The matched SKU.io `products.id` (null when the variant
        is unmapped)

        - `sku_product_route` — application UI route path to the matched product (null
        when unmapped)

        - `sku_product` — Mapped SKU.io product block `{ id, sku, name, type }` for
        the "Linked Product" column on the order detail page (null when unmapped).
        Mirrors the Shopify line-item shape.


        **Linked product resolution:** All three `sku_product*` fields are resolved
        via the explicit `FaireProductOption → ProductListing → Product` chain (joined
        on `faire_variant_id`), populated by the Variants Listing page "Map" button
        / Smart Match / Bulk Map. String-based SKU matching is NOT used. If a variant
        has never been mapped, the fields are null even when the line’s `sku` happens
        to match a Product’s `sku` — same behaviour as the Shopify order line resource.


        **Error Responses:**

        - `404 Not Found` — Order not found'
      parameters:
      - name: order
        in: path
        schema:
          type: integer
        required: true
        description: Internal Faire Order ID
        example: '101'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      faire_order_id:
                        type: string
                      display_id:
                        type: string
                      status:
                        type: string
                      retailer_id:
                        type: string
                      retailer_name:
                        type: string
                      retailer_state:
                        type: string
                      retailer_country_code:
                        type: string
                      subtotal:
                        type: integer
                      discount_amount:
                        type: integer
                      total:
                        type: integer
                      currency_code:
                        type: string
                      ordered_at:
                        type: string
                      shipped_at:
                        type: string
                        nullable: true
                      delivered_at:
                        type: string
                        nullable: true
                      tracking_number:
                        type: string
                        nullable: true
                      tracking_carrier:
                        type: string
                        nullable: true
                      tracking_submission_status:
                        type: string
                        nullable: true
                      tracking_submitted_at:
                        type: string
                        nullable: true
                      tracking_submission_error:
                        type: string
                        nullable: true
                      tracking_submission_attempts:
                        type: integer
                      raw_data:
                        type: object
                        properties:
                          id:
                            type: string
                          state:
                            type: string
                          items:
                            type: array
                      line_items:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            faire_line_item_id:
                              type: string
                            faire_product_id:
                              type: string
                            faire_variant_id:
                              type: string
                            sku:
                              type: string
                            name:
                              type: string
                            option_values:
                              type: string
                              nullable: true
                            quantity:
                              type: integer
                            unit_price:
                              type: number
                            total_price:
                              type: integer
                            sku_product_id:
                              type: integer
                            sku_product_route:
                              type: string
                            sku_product:
                              type: object
                              properties:
                                id:
                                  type: integer
                                sku:
                                  type: string
                                name:
                                  type: string
                                type:
                                  type: string
                      sales_order:
                        type: object
                        properties:
                          id:
                            type: integer
                          sales_order_number:
                            type: string
                          order_status:
                            type: string
                          fulfillment_status:
                            type: string
                          payment_status:
                            type: string
                      created_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                      is_archived:
                        type: boolean
                      faire_admin_url:
                        type: string
                example:
                  data:
                    id: 101
                    integration_instance_id: 1
                    faire_order_id: bo_abc123xyz
                    display_id: FO-0001
                    status: PROCESSING
                    retailer_id: b_xyz789
                    retailer_name: The Boutique Shop
                    retailer_state: CA
                    retailer_country_code: US
                    subtotal: 15000
                    discount_amount: 0
                    total: 15000
                    currency_code: USD
                    ordered_at: '2026-04-20T08:30:00+00:00'
                    shipped_at: null
                    delivered_at: null
                    tracking_number: null
                    tracking_carrier: null
                    tracking_submission_status: null
                    tracking_submitted_at: null
                    tracking_submission_error: null
                    tracking_submission_attempts: 0
                    raw_data:
                      id: bo_abc123xyz
                      state: PROCESSING
                      items: []
                    line_items:
                    - id: 451
                      faire_line_item_id: li_a1b2c3d4
                      faire_product_id: p_xyz123
                      faire_variant_id: opt_qr789
                      sku: WIDGET-RED-LG
                      name: Widget — Red, Large
                      option_values: null
                      quantity: 2
                      unit_price: 24.5
                      total_price: 49
                      sku_product_id: 89
                      sku_product_route: /products/89
                      sku_product:
                        id: 89
                        sku: WIDGET-RED-LG
                        name: Red Widget — Large
                        type: standard
                    sales_order:
                      id: 57520
                      sales_order_number: FO-0001
                      order_status: open
                      fulfillment_status: unfulfilled
                      payment_status: paid
                    created_at: '2026-04-20T08:32:00+00:00'
                    archived_at: null
                    is_archived: false
                    faire_admin_url: https://www.faire.com/brand-portal/orders/bo_abc123xyz/order-fulfilment
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-faire-orders-order
  /api/faire/orders/{order}/refetch:
    post:
      tags:
      - Faire
      summary: Refetch Order from Faire
      description: 'Re-fetch the order from the Faire API. Updates local data and
        (if a linked SKU sales order exists) refreshes the SKU sales order to mirror
        Faire''s latest state. Returns the updated Faire order object (with line_items,
        sales_order, faire_admin_url).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Linked SKU.io product on line items:** The `sku_product_id`, `sku_product_route`,
        and `sku_product` fields on each line item resolve via the explicit `FaireProductOption
        → ProductListing → Product` chain (joined on `faire_variant_id`). They populate
        only when the variant has been explicitly mapped via the Variants Listing
        page (Map / Smart Match / Bulk Map). String-based SKU matching is NOT used.'
      requestBody:
        content: {}
      parameters:
      - name: order
        in: path
        schema:
          type: integer
        required: true
        description: Faire order ID (DB primary key)
        example: '101'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      faire_order_id:
                        type: string
                      display_id:
                        type: string
                      status:
                        type: string
                      retailer_id:
                        type: string
                      retailer_name:
                        type: string
                      retailer_state:
                        type: string
                      retailer_country_code:
                        type: string
                      subtotal:
                        type: integer
                      discount_amount:
                        type: integer
                      total:
                        type: integer
                      currency_code:
                        type: string
                      ordered_at:
                        type: string
                      shipped_at:
                        type: string
                        nullable: true
                      delivered_at:
                        type: string
                        nullable: true
                      tracking_number:
                        type: string
                        nullable: true
                      tracking_carrier:
                        type: string
                        nullable: true
                      tracking_submission_status:
                        type: string
                        nullable: true
                      tracking_submitted_at:
                        type: string
                        nullable: true
                      tracking_submission_error:
                        type: string
                        nullable: true
                      tracking_submission_attempts:
                        type: integer
                      line_items:
                        type: array
                      sales_order:
                        type: object
                        properties:
                          id:
                            type: integer
                          sales_order_number:
                            type: string
                          order_status:
                            type: string
                          fulfillment_status:
                            type: string
                          payment_status:
                            type: string
                      created_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                      is_archived:
                        type: boolean
                      faire_admin_url:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 101
                    integration_instance_id: 1
                    faire_order_id: bo_abc123xyz
                    display_id: FO-0001
                    status: PROCESSING
                    retailer_id: b_xyz789
                    retailer_name: The Boutique Shop
                    retailer_state: CA
                    retailer_country_code: US
                    subtotal: 15000
                    discount_amount: 0
                    total: 15000
                    currency_code: USD
                    ordered_at: '2026-04-20T08:30:00+00:00'
                    shipped_at: null
                    delivered_at: null
                    tracking_number: null
                    tracking_carrier: null
                    tracking_submission_status: null
                    tracking_submitted_at: null
                    tracking_submission_error: null
                    tracking_submission_attempts: 0
                    line_items: []
                    sales_order:
                      id: 57520
                      sales_order_number: FO-0001
                      order_status: open
                      fulfillment_status: unfulfilled
                      payment_status: paid
                    created_at: '2026-04-20T08:32:00+00:00'
                    archived_at: null
                    is_archived: false
                    faire_admin_url: https://www.faire.com/brand-portal/orders/bo_abc123xyz/order-fulfilment
                  message: Order refetched from Faire successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-faire-orders-order-refetch
  /api/faire/orders/filter-options:
    get:
      tags:
      - Faire
      summary: Get Order Filter Options (Distinct Values)
      description: "**Tenant resolution (multi-instance safety):**\nBoth shapes are\
        \ accepted, in priority order:\n- `filter[integration_instance_ids]` (preferred,\
        \ Amazon-unified plural form; comma-separated CSV — first ID wins)\n- `filter[instance_id]`\
        \ (legacy singular)\n- `?instance_id=` query string fallback\n- body `instance_id`\
        \ (POST/PUT only)\n\n:::info[Authorization]\nAny valid API token can call\
        \ this endpoint — no specific scope required. [Manage tokens](https://app.sku.io/settings/api).\n\
        :::\n\nIf none resolve to an existing FaireIntegrationInstance the endpoint\
        \ returns an empty/zeroed payload — it does NOT silently fall back to the\
        \ first tenant's data.\n\n**Empty-options response** (when no instance can\
        \ be resolved):\n```json\n{\n  \"data\": {\n    \"statuses\": [],\n    \"\
        currencies\": [],\n    \"country_codes\": [],\n    \"tracking_carriers\":\
        \ [],\n    \"tracking_submission_statuses\": []\n  }\n}\n```\n\n---\n\nReturns\
        \ distinct values for the Faire orders list view filter dropdowns. Mirrors\
        \ the Shopify pattern — only values that actually appear in the data for the\
        \ given integration instance are surfaced.\n\n**Query Parameters:**\n- `instance_id`\
        \ (optional) — Faire integration instance to scope the distinct query. Defaults\
        \ to the first available instance.\n\n**Response Fields (`data`):**\n- `statuses`\
        \ — Distinct `faire_orders.status` values (e.g. `NEW`, `PROCESSING`, `COMPLETE`,\
        \ `CANCELLED`)\n- `currencies` — Distinct `faire_orders.currency_code` values\
        \ (ISO 4217)\n- `country_codes` — Distinct `faire_orders.retailer_country_code`\
        \ values\n- `tracking_carriers` — Distinct `faire_orders.tracking_carrier`\
        \ values\n- `tracking_submission_statuses` — Distinct `faire_orders.tracking_submission_status`\
        \ values (`pending`, `submitted`, `failed`)"
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      statuses:
                        type: array
                        items:
                          type: string
                      currencies:
                        type: array
                        items:
                          type: string
                      country_codes:
                        type: array
                        items:
                          type: string
                      tracking_carriers:
                        type: array
                        items:
                          type: string
                      tracking_submission_statuses:
                        type: array
                        items:
                          type: string
                example:
                  data:
                    statuses:
                    - BACKORDERED
                    - CANCELLED
                    - COMPLETE
                    - NEW
                    - PROCESSING
                    currencies:
                    - CAD
                    - USD
                    country_codes:
                    - CA
                    - US
                    tracking_carriers:
                    - FEDEX
                    - UPS
                    - USPS
                    tracking_submission_statuses:
                    - pending
                    - submitted
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-faire-orders-filter-options
  /api/faire/instances/{integrationInstance}/orders/latest-sync-info:
    get:
      tags:
      - Faire
      summary: Get Orders Latest Sync Info
      description: 'Aggregate stats about the Faire orders previously synced to this
        instance. Powers the **Refresh from Faire** orders modal header card and the
        latest-sync indicator on the orders index.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Path Parameters:**

        - `integrationInstance` — The ID of the integration instance


        **Response Fields (`data`):**

        - `latest_order_display_id` — Display ID of the most-recently-ordered Faire
        order (highest `ordered_at`). `null` when no orders are imported yet.

        - `latest_order_date` — ISO 8601 timestamp of that order''s `ordered_at`.

        - `total_orders` — Count of all Faire orders for this instance (active + archived).

        - `created_count` — Faire orders that have a linked SKU.io sales order (`whereHas(''salesOrder'')`).

        - `pending_count` — Active Faire orders **without** a linked SKU.io sales
        order (the auto-create-SKU-orders queue).

        - `archived_count` — Faire orders with `archived_at` set.

        - `last_synced_at` — ISO 8601 timestamp from `sync_cursors.orders.synced_at`
        (when the cron last completed). `null` until the first sync runs.

        - `cursor_at` — The opaque rolling cursor stored at `sync_cursors.orders.cursor_at`.
        When `null`, the **Fetch Since Latest Sync** mode is unavailable in the refresh
        modal.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Faire integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      latest_order_display_id:
                        type: string
                      latest_order_date:
                        type: string
                      total_orders:
                        type: integer
                      created_count:
                        type: integer
                      pending_count:
                        type: integer
                      archived_count:
                        type: integer
                      last_synced_at:
                        type: string
                      cursor_at:
                        type: string
                example:
                  data:
                    latest_order_display_id: FO-0123
                    latest_order_date: '2026-05-01T10:00:00+00:00'
                    total_orders: 47
                    created_count: 32
                    pending_count: 12
                    archived_count: 3
                    last_synced_at: '2026-05-06T08:00:00+00:00'
                    cursor_at: cursor_abc
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-faire-instances-integrationinstance-orders-latest-sync-info
  /api/faire/instances/{integrationInstance}/orders/refresh-tracked:
    post:
      tags:
      - Faire
      summary: Refresh Orders from Faire (Tracked)
      description: "Dispatches a background job that walks Faire's `/api/v2/orders`\
        \ endpoint and upserts `faire_orders` + `faire_order_line_items`. Returns\
        \ immediately with a tracked job log ID — progress is visible via the tracked\
        \ job log endpoints.\n\n:::info[Authorization]\nAny valid API token can call\
        \ this endpoint — no specific scope required. [Manage tokens](https://app.sku.io/settings/api).\n\
        :::\n\nMirrors the products tracked refresh (`/refresh-tracked` on the products\
        \ endpoint) so the same UX and progress reporting (synced_orders list, orders_fetched/saved\
        \ counters) drives the orders refresh modal.\n\n**Path Parameters:**\n- `integrationInstance`\
        \ — The ID of the integration instance\n\n**Body:**\n- `mode` (required) —\
        \ One of:\n  - `incremental` — Resume from the persisted `sync_cursors.orders.cursor_at`.\
        \ Recommended for routine refreshes; cursor is persisted across runs.\n  -\
        \ `full` — Reset the cursor and walk Faire's full updated_at-min window (slow).\
        \ Cursor is NOT persisted (so the next incremental run still resumes from\
        \ where things left off).\n  - `date_range` — Fetch only orders whose `updated_at`\
        \ falls between `date_from` and `date_to` (inclusive). Cursor is NOT persisted.\n\
        - `date_from` (required when `mode=date_range`) — ISO date string (`YYYY-MM-DD`).\
        \ Sent to Faire as `updated_at_min` (start-of-day UTC).\n- `date_to` (required\
        \ when `mode=date_range`) — ISO date string (`YYYY-MM-DD`). Sent to Faire\
        \ as `updated_at_max` (end-of-day UTC). Must be `>= date_from`.\n\n**Response:**\n\
        - `data.tracked_job_log_id` — ID of the dispatched tracked job. Poll `/api/tracked-job-logs/:id`\
        \ for progress.\n- `message` — Human-readable status string.\n\n**Validation\
        \ Errors (422):**\n- `mode` must be one of `incremental`, `full`, `date_range`\n\
        - `date_from` and `date_to` are required when `mode=date_range`\n- `date_to`\
        \ must be on or after `date_from`"
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                mode:
                  type: string
                date_from:
                  type: string
                  nullable: true
                date_to:
                  type: string
                  nullable: true
              example:
                mode: incremental
                date_from: null
                date_to: null
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Faire integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 8421
                  message: Order refresh job has been queued
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      date_from:
                        type: array
                        items:
                          type: string
                      date_to:
                        type: array
                        items:
                          type: string
                example:
                  message: The date from field is required when mode is date_range.
                    (and 1 more error)
                  errors:
                    date_from:
                    - The date from field is required when mode is date_range.
                    date_to:
                    - The date to field is required when mode is date_range.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-faire-instances-integrationinstance-orders-refresh-tracked
  /api/faire/orders/{order}/submit-tracking:
    post:
      tags:
      - Faire
      summary: Submit Tracking to Faire (FBM)
      description: 'Manually retry tracking submission for an FBM Faire order.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Dispatches a background job for the most recent fulfilled `SalesOrderFulfillment`
        that has a tracking number. The job calls Faire''s per-line-item fulfillment
        endpoint (`POST /api/v2/brand/orders/{order_id}/items/{item_id}/fulfillments`)
        for each item in the shipment, with the carrier, tracking code, shipped-at
        timestamp, and quantity.


        Useful when an automatic submission failed and the user wants to retry. Job
        retries up to 3 times with exponential backoff (1m / 5m / 15m). Final status
        is reflected in `tracking_submission_status` on the order (`pending`, `submitted`,
        or `failed`) along with `tracking_submission_error` and `tracking_submission_attempts`.


        **Errors:**

        - `422` — Instance is FBF (tracking is owned by Faire), no SKU sales order
        linked, or no fulfilled shipment with a tracking number found.'
      requestBody:
        content: {}
      parameters:
      - name: order
        in: path
        schema:
          type: integer
        required: true
        description: Faire order ID (internal SKU.io ID, not Faire's bo_* ID)
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Faire tracking submission queued.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: Rejected — FBF instance
                  value:
                    message: FBF orders are fulfilled by Faire — tracking submission
                      is not applicable.
                example-1:
                  summary: Rejected — No fulfilled shipment
                  value:
                    message: No fulfilled shipment with a tracking number was found
                      for this order.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-faire-orders-order-submit-tracking
  /api/faire/orders/{order}/archive:
    post:
      tags:
      - Faire
      summary: Archive Faire Order
      description: 'Archives a single Faire order — stamps `archived_at = now()` via
        the `Archive` trait. Archived orders are excluded from the auto-create-SKU-orders
        pipelines (see `createSkuOrders`) and from the default orders listing (which
        uses `filter[archived]=` Active by default).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Idempotent: archiving an already-archived order returns `archived: false`
        with a friendly message.


        **Path Parameters:**

        - `order` — The internal Faire order ID (`faire_orders.id`)


        **Response Fields:**

        - `message` — Human-readable result

        - `archived` — `true` when the call flipped the row, `false` if it was already
        archived'
      requestBody:
        content: {}
      parameters:
      - name: order
        in: path
        schema:
          type: integer
        required: true
        description: Internal Faire order ID
        example: '101'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  archived:
                    type: boolean
                example:
                  message: Order archived successfully
                  archived: true
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-faire-orders-order-archive
  /api/faire/orders/{order}/unarchive:
    post:
      tags:
      - Faire
      summary: Unarchive Faire Order
      description: 'Unarchives a single Faire order — clears `archived_at` via the
        `Archive` trait. After unarchiving, the order becomes eligible for auto-create-SKU-orders
        again.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Idempotent: unarchiving an already-active order returns `unarchived: false`.


        **Path Parameters:**

        - `order` — The internal Faire order ID (`faire_orders.id`)


        **Response Fields:**

        - `message` — Human-readable result

        - `unarchived` — `true` when the call flipped the row, `false` if it was already
        active'
      requestBody:
        content: {}
      parameters:
      - name: order
        in: path
        schema:
          type: integer
        required: true
        description: Internal Faire order ID
        example: '101'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  unarchived:
                    type: boolean
                example:
                  message: Order unarchived successfully
                  unarchived: true
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-faire-orders-order-unarchive
  /api/faire/instances/{integrationInstance}/orders/bulk-archive:
    post:
      tags:
      - Faire
      summary: Bulk Archive Faire Orders
      description: 'Archives multiple Faire orders for the given integration instance.
        Scoped to active orders only — already-archived rows are silently skipped,
        and IDs from foreign integration instances are NOT affected (the controller
        filters `where(''integration_instance_id'', $instance->id)`).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Operates in chunks of 100 to keep the query small.


        **Path Parameters:**

        - `integrationInstance` — The ID of the integration instance


        **Body:**

        - `ids` (required, array of integers) — Faire order IDs to archive. Must be
        a non-empty array.


        **Response Fields:**

        - `message` — Human-readable result

        - `archived_count` — Number of rows actually flipped (excludes IDs that were
        already archived or belong to other instances)'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 101
                - 102
                - 103
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Faire integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  archived_count:
                    type: integer
                example:
                  message: 3 orders archived successfully
                  archived_count: 3
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      ids:
                        type: array
                        items:
                          type: string
                example:
                  message: The ids field is required.
                  errors:
                    ids:
                    - The ids field is required.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-faire-instances-integrationinstance-orders-bulk-archive
  /api/faire/instances/{integrationInstance}/orders/bulk-unarchive:
    post:
      tags:
      - Faire
      summary: Bulk Unarchive Faire Orders
      description: 'Unarchives multiple Faire orders for the given integration instance.
        Scoped to archived orders only — already-active rows are silently skipped,
        and IDs from foreign integration instances are NOT affected.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Operates in chunks of 100.


        **Path Parameters:**

        - `integrationInstance` — The ID of the integration instance


        **Body:**

        - `ids` (required, array of integers) — Faire order IDs to unarchive. Must
        be a non-empty array.


        **Response Fields:**

        - `message` — Human-readable result

        - `unarchived_count` — Number of rows actually flipped'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 101
                - 102
                - 103
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Faire integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  unarchived_count:
                    type: integer
                example:
                  message: 3 orders unarchived successfully
                  unarchived_count: 3
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-faire-instances-integrationinstance-orders-bulk-unarchive
  /api/faire/instances/{integrationInstance}/orders/{order}/sku-order:
    delete:
      tags:
      - Faire
      summary: Delete Linked Sales Order
      description: 'Deletes the linked SKU.io sales order for a single Faire order
        while keeping the Faire order itself intact. Optionally archives the Faire
        order in the same call to prevent re-creation on the next sync.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Path Parameters:**

        - `integrationInstance` — The ID of the integration instance

        - `order` — The internal Faire order ID (`faire_orders.id`)


        **Query Parameters:**

        - `archive_faire_order` (optional, boolean) — When `true`, archives the Faire
        order after deleting its linked SKU sales order. Defaults to `false`.


        **Response Fields:**

        - `message` — Human-readable result

        - `archived_faire_order` — `true` if the Faire order was archived as part
        of this call


        **Errors:**

        - `404` when the Faire order has no linked SKU sales order'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Faire integration instance ID
        example: '1'
      - name: order
        in: path
        schema:
          type: integer
        required: true
        description: Internal Faire order ID (`faire_orders.id`)
        example: '101'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  archived_faire_order:
                    type: boolean
                example:
                  message: SKU order deleted successfully
                  archived_faire_order: false
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: No SKU order linked to this Faire order
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: delete-api-faire-instances-integrationinstance-orders-order-sku-order
  /api/faire/instances/{integrationInstance}/orders/bulk-delete-sku-orders:
    post:
      tags:
      - Faire
      summary: Bulk Delete Linked Sales Orders
      description: 'Bulk-deletes the linked SKU.io sales orders for multiple Faire
        orders while keeping the Faire orders themselves intact. Only orders with
        a linked sales order in the targeted integration instance are processed —
        IDs from foreign instances or without a linked SKU order are silently skipped.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        - **0 eligible orders** — returns `tracked_job_log_id: null` synchronously.

        - **1 eligible order** — deletes synchronously and returns `tracked_job_log_id:
        null`.

        - **>1 eligible orders** — dispatches a background job and returns the tracked-job
        ID for progress polling.


        **Path Parameters:**

        - `integrationInstance` — The ID of the integration instance


        **Body:**

        - `ids` (required, array of integers) — Faire order IDs to delete linked SKU
        orders for. Must be a non-empty array.

        - `archive_faire_orders` (optional, boolean) — When `true`, archives each
        Faire order after deleting its linked SKU sales order. Defaults to `false`.


        **Response Fields:**

        - `message` — Human-readable result

        - `tracked_job_log_id` — Tracked-job log ID when a job was dispatched, otherwise
        `null`

        - `total_orders` (only when a tracked job was dispatched) — Number of eligible
        orders queued for deletion


        **Tracked Job Name:** `Bulk Delete SKU Orders: {instance_name}` (frontend
        `lastCompletedJob` watcher matches with `startsWith`)'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
                archive_faire_orders:
                  type: boolean
              example:
                ids:
                - 101
                - 102
                - 103
                archive_faire_orders: false
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Faire integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: Success — Tracked job dispatched
                  value:
                    message: Bulk delete job started
                    tracked_job_log_id: 4521
                    total_orders: 3
                example-1:
                  summary: Success — Single order, synchronous
                  value:
                    message: 1 SKU order deleted successfully
                    tracked_job_log_id: null
        '422':
          description: Unprocessable Content
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      ids:
                        type: array
                        items:
                          type: string
                example:
                  message: The ids field is required.
                  errors:
                    ids:
                    - The ids field is required.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-faire-instances-integrationinstance-orders-bulk-delete-sku-orders
  /api/faire/instances/{integrationInstance}/orders/{order}/update-sku-order:
    post:
      tags:
      - Faire
      summary: Sync Linked Sales Order
      description: 'Refetches the order from Faire and synchronously syncs the linked
        SKU.io sales order''s status fields (`order_status`, `payment_status`, `last_synced_from_sales_channel_at`).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Path Parameters:**

        - `integrationInstance` — The ID of the integration instance

        - `order` — The internal Faire order ID (`faire_orders.id`)


        **Body:** Empty.


        **Response Fields:**

        - `message` — Human-readable result

        - `refetched` — `true` when the latest order state was successfully fetched
        from Faire before the SKU sync


        **Errors:**

        - `403` when the order does not belong to the supplied integration instance

        - `404` when the Faire order has no linked SKU sales order

        - `422` when the SKU sales order update fails (e.g., refetch error or downstream
        validation)'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties: {}
              example: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Faire integration instance ID
        example: '1'
      - name: order
        in: path
        schema:
          type: integer
        required: true
        description: Internal Faire order ID (`faire_orders.id`)
        example: '101'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  refetched:
                    type: boolean
                example:
                  message: SKU order updated successfully
                  refetched: true
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: No SKU order linked to this Faire order
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-faire-instances-integrationinstance-orders-order-update-sku-order
  /api/faire/instances/{integrationInstance}/orders/bulk-update-sku-orders:
    post:
      tags:
      - Faire
      summary: Bulk Sync Linked Sales Orders
      description: 'Bulk-refetches Faire orders and re-syncs each linked SKU.io sales
        order''s status fields (`order_status`, `payment_status`, `last_synced_from_sales_channel_at`).
        Only orders with a linked SKU sales order in the targeted integration instance
        are processed — foreign-instance IDs and orders without a linked SKU order
        are silently skipped.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        - **0 eligible orders** — returns `tracked_job_log_id: null` synchronously.

        - **1 eligible order** — updates synchronously and returns `tracked_job_log_id:
        null`.

        - **>1 eligible orders** — dispatches a background job and returns the tracked-job
        ID for progress polling.


        **Path Parameters:**

        - `integrationInstance` — The ID of the integration instance


        **Body:**

        - `ids` (required, array of integers) — Faire order IDs to update linked SKU
        orders for. Must be a non-empty array.


        **Response Fields:**

        - `message` — Human-readable result

        - `tracked_job_log_id` — Tracked-job log ID when a job was dispatched, otherwise
        `null`

        - `total_orders` (only when a tracked job was dispatched) — Number of eligible
        orders queued for update


        **Tracked Job Name:** `Bulk Update SKU Orders: {instance_name}` (frontend
        `lastCompletedJob` watcher matches with `startsWith`)'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 101
                - 102
                - 103
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Faire integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: Success — Tracked job dispatched
                  value:
                    message: Bulk update job started
                    tracked_job_log_id: 4528
                    total_orders: 3
                example-1:
                  summary: Success — Single order, synchronous
                  value:
                    message: 1 SKU order updated successfully
                    tracked_job_log_id: null
                example-2:
                  summary: No eligible orders
                  value:
                    message: No orders found with linked SKU orders to update
                    tracked_job_log_id: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-faire-instances-integrationinstance-orders-bulk-update-sku-orders
  /api/faire/instances/{integrationInstance}/pre-start-date-orders:
    get:
      tags:
      - Faire
      summary: List Pre-Start-Date Orders
      description: "Query Faire live for orders placed before the instance's order\
        \ import start date, so historical orders can be selectively imported. Results\
        \ come directly from the Faire API — not from the local database — and each\
        \ order carries eligibility flags for import.\n\n:::info[Authorization]\n\
        Any valid API token can call this endpoint — no specific scope required. [Manage\
        \ tokens](https://app.sku.io/settings/api).\n:::\n\n**Requires the instance's\
        \ order import start date to be set** — returns 422 otherwise.\n\n**Path Parameters:**\n\
        - `integrationInstance` - The ID of the integration instance\n\n**Query Parameters:**\n\
        - `created_at_min` (optional, date) - Lower bound for the query window. Defaults\
        \ to one year before the order import start date\n\n**Behavior:**\n- Scans\
        \ up to 10 pages of 50 orders from Faire and keeps only orders created before\
        \ the start date\n- Cancelled orders and orders already imported into SKU.io\
        \ are marked ineligible\n- Order totals are read from Faire payout data, falling\
        \ back to a sum of line item prices when Faire returns zero\n\n**Response:**\n\
        - `data` - The queried orders, each with:\n  - `faire_order_id` - Faire order\
        \ ID (e.g. `bo_abc123xyz`)\n  - `display_id` - Short human-readable Faire\
        \ order number\n  - `status` - Faire order state (e.g. `DELIVERED`, `CANCELED`)\n\
        \  - `retailer_name` - Retailer/company name from the order address\n  - `ordered_at`\
        \ - When the order was placed on Faire\n  - `total` - Order subtotal in minor\
        \ currency units (cents); null when unavailable\n  - `currency_code` - Currency\
        \ of the total (default USD)\n  - `item_count` - Total units across all line\
        \ items\n  - `already_imported` - True when the order already exists in SKU.io\n\
        \  - `eligible` - True when the order can be imported\n  - `ineligible_reason`\
        \ - Why the order cannot be imported (null when eligible)\n  - `items` - Line\
        \ items with `faire_line_item_id`, `sku`, `name`, `quantity`, `unit_price`\
        \ (major units)\n- `order_import_start_date` - The instance's configured start\
        \ date\n- `meta.total_queried` / `meta.eligible_count` / `meta.already_imported_count`\
        \ - Query summary counts"
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Faire integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        faire_order_id:
                          type: string
                        display_id:
                          type: string
                        status:
                          type: string
                        retailer_name:
                          type: string
                        ordered_at:
                          type: string
                        total:
                          type: integer
                        currency_code:
                          type: string
                        item_count:
                          type: integer
                        already_imported:
                          type: boolean
                        eligible:
                          type: boolean
                        ineligible_reason:
                          type: string
                          nullable: true
                        items:
                          type: array
                          items:
                            type: object
                            properties:
                              faire_line_item_id:
                                type: string
                              sku:
                                type: string
                              name:
                                type: string
                              quantity:
                                type: integer
                              unit_price:
                                type: integer
                  order_import_start_date:
                    type: string
                  meta:
                    type: object
                    properties:
                      total_queried:
                        type: integer
                      eligible_count:
                        type: integer
                      already_imported_count:
                        type: integer
                example:
                  data:
                  - faire_order_id: bo_abc123xyz
                    display_id: K3M2ZX
                    status: DELIVERED
                    retailer_name: The Corner Boutique
                    ordered_at: '2025-11-14T18:03:22.000Z'
                    total: 42500
                    currency_code: USD
                    item_count: 18
                    already_imported: false
                    eligible: true
                    ineligible_reason: null
                    items:
                    - faire_line_item_id: oi_5f8d2k
                      sku: CANDLE-SM-RED
                      name: Small Candle
                      quantity: 12
                      unit_price: 15
                    - faire_line_item_id: oi_9c1b7q
                      sku: CANDLE-LG-NAVY
                      name: Large Candle
                      quantity: 6
                      unit_price: 22.5
                  - faire_order_id: bo_def456uvw
                    display_id: H8P4QN
                    status: CANCELED
                    retailer_name: Maple & Main Goods
                    ordered_at: '2025-10-02T11:47:09.000Z'
                    total: 18000
                    currency_code: USD
                    item_count: 8
                    already_imported: false
                    eligible: false
                    ineligible_reason: Order is cancelled
                    items:
                    - faire_line_item_id: oi_2m6x1t
                      sku: CANDLE-SM-BLUE
                      name: Small Candle
                      quantity: 8
                      unit_price: 15
                  order_import_start_date: '2026-01-01'
                  meta:
                    total_queried: 2
                    eligible_count: 1
                    already_imported_count: 0
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: Order import start date is not set for this integration.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-faire-instances-integrationinstance-pre-start-date-orders
  /api/faire/instances/{integrationInstance}/pre-start-date-orders/import:
    post:
      tags:
      - Faire
      summary: Import Pre-Start-Date Orders
      description: 'Import selected pre-start-date orders from Faire into SKU.io.
        Each order is fetched from the Faire API and stored as a Faire order flagged
        as a pre-start-date import.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Because each order requires its own throttled Faire API call, the import runs
        in the background. The request returns immediately with a tracked job log
        ID that can be used to follow the import''s progress.


        **Requires the instance''s order import start date to be set** — returns 422
        otherwise.


        **Path Parameters:**

        - `integrationInstance` - The ID of the integration instance


        **Request Body:**

        - `faire_order_ids` (required, array of strings, 1-10000 entries) - Faire
        order IDs to import (e.g. `bo_abc123xyz`)


        **Behavior:**

        - Runs as a background import — the request returns right away with a tracked
        job log ID; the orders are fetched and stored asynchronously

        - Orders already in SKU.io are marked as pre-start-date imports instead of
        being re-imported

        - Cancelled orders and orders whose fulfillment mode does not match the instance
        are skipped

        - Imported orders do NOT automatically create linked sales orders — use Create
        Linked Sales Orders afterwards


        **Response:**

        - `data.tracked_job_log_id` - ID of the tracked job log; poll it to follow
        import progress

        - `message` - Human-readable confirmation of how many orders are being imported'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                faire_order_ids:
                  type: array
                  items:
                    type: string
              example:
                faire_order_ids:
                - bo_abc123xyz
                - bo_jkl789rst
                - bo_mno012pqr
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Faire integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 8412
                  message: Importing 3 pre-start-date orders — track progress in the
                    job tray.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: Start Date Not Set
                  value:
                    error: Order import start date must be set before importing pre-start-date
                      orders.
                example-1:
                  summary: Validation Error
                  value:
                    message: The faire order ids field is required.
                    errors:
                      faire_order_ids:
                      - The faire order ids field is required.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-faire-instances-integrationinstance-pre-start-date-orders-import
  /api/faire/instances/{integrationInstance}/create-sku-orders:
    post:
      tags:
      - Faire
      summary: Create Linked Sales Orders
      description: 'Create SKU.io sales orders from Faire orders that do not yet have
        a linked sales order.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Path Parameters:**

        - `integrationInstance` - The ID of the integration instance


        **Request Body:**

        - `ids` (required unless `create_all_orders` is true, array of integers) -
        Internal Faire order IDs (the `id` from List Faire Orders, not the Faire order
        ID string)

        - `create_all_orders` (optional, boolean) - When true, targets every eligible
        Faire order on the instance and `ids` is ignored


        **Eligibility:**

        Only Faire orders belonging to this instance, without an existing linked sales
        order, and not archived are processed. Ineligible IDs are silently skipped.


        **Behavior:**

        - Exactly 1 eligible order — the sales order is created synchronously within
        the request

        - 2+ eligible orders — a background job is dispatched and the request returns
        immediately; creation runs asynchronously and progress can be monitored via
        the returned `tracked_job_log_id`

        - 0 eligible orders — returns a `No orders to create` message


        **Response:**

        - `message` - Outcome summary

        - `tracked_job_log_id` - ID for monitoring the background creation (only when
        2+ orders are queued)

        - `total_orders` - Number of orders queued for creation (only when 2+ orders
        are queued)'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
                create_all_orders:
                  type: boolean
              example:
                ids:
                - 101
                - 102
                - 103
                create_all_orders: false
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Faire integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: Success Response (Multiple Orders Queued)
                  value:
                    message: SKU order creation started for 3 orders
                    tracked_job_log_id: 152
                    total_orders: 3
                example-1:
                  summary: Single Order Created Synchronously
                  value:
                    message: 1 SKU order created successfully
                example-2:
                  summary: No Eligible Orders
                  value:
                    message: No orders to create
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      ids:
                        type: array
                        items:
                          type: string
                example:
                  message: The ids field is required when create all orders is not
                    present.
                  errors:
                    ids:
                    - The ids field is required when create all orders is not present.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-faire-instances-integrationinstance-create-sku-orders
  /api/faire/products:
    get:
      tags:
      - Faire
      summary: List Faire Products
      description: 'List Faire products synced for a specific integration instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Tenant resolution (multi-instance safety):**

        Both shapes are accepted, in priority order:

        - `filter[integration_instance_ids]` (preferred, Amazon-unified plural form;
        comma-separated CSV — first ID wins)

        - `filter[instance_id]` (legacy singular)

        - `?instance_id=` query string fallback

        - body `instance_id` (POST/PUT only)


        If none resolve to an existing FaireIntegrationInstance the endpoint returns
        an empty/zeroed payload — it does NOT silently fall back to the first tenant''s
        data.


        **Empty-paginator response** when no instance resolves: `{ data: [], total:
        0, per_page, ... }`.


        ---


        List Faire products synced for a specific integration instance.


        **Query Parameters:**

        - `instance_id` (optional) - Filter products to a specific integration instance.
        Defaults to the first instance.

        - `page` (optional) - Page number (default: 1)

        - `per_page` (optional) - Items per page (default: 10)


        **Response Fields per Product:**

        - `id` - Internal product ID

        - `integration_instance_id` - Integration instance ID

        - `faire_product_id` - Faire''s product ID (e.g. `p_abc123`)

        - `name` - Product name

        - `status` - Product status (`ACTIVE`, `INACTIVE`, `DELETED`)

        - `wholesale_price_minimum` - Minimum wholesale price in cents

        - `currency_code` - ISO 4217 currency code

        - `options` - Loaded when explicitly eager-loaded (variants/SKUs)

        - `created_at` - ISO timestamp'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        description: 'Page number for pagination (default: 1)'
        example: '1'
      - name: per_page
        in: query
        schema:
          type: integer
        description: 'Number of results per page (default: 10)'
        example: '10'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        faire_product_id:
                          type: string
                        name:
                          type: string
                        status:
                          type: string
                        wholesale_price_minimum:
                          type: integer
                        currency_code:
                          type: string
                        options:
                          type: array
                        created_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - id: 50
                    integration_instance_id: 1
                    faire_product_id: p_xyz456abc
                    name: Small Candle
                    status: ACTIVE
                    wholesale_price_minimum: 1200
                    currency_code: USD
                    options: []
                    created_at: '2026-04-10T07:00:00+00:00'
                  current_page: 1
                  last_page: 3
                  per_page: 10
                  total: 28
                  from: 1
                  to: 10
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-faire-products
  /api/faire/instances/{integrationInstance}/products:
    get:
      tags:
      - Faire
      summary: List Products for Instance (Variants Listing)
      description: 'Paginated list of `FaireProductOption` rows (variants) for one
        Faire integration instance. Powers the **Faire → Products** listing page in
        application UI.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Uses Spatie QueryBuilder under the hood with `GroupedFilterSupport`. The advanced-filter
        operator suffix is required for `status` and `product_type` filters (`filter[status][is]=ACTIVE`,
        etc.).


        **Default behavior:** archived variants are hidden unless `filter[archived]`
        is set explicitly.


        **Response shape:** standard Laravel paginator wrapping Faire product option
        object. Each row eager-loads the parent `product` and `productListing.product.defaultFinancialLineType`,
        so `product_name`, `product_status`, `product_type`, `product_image_url`,
        `product_brand_name`, `product_description`, and the mapped sku.io `product`
        block are populated when present.


        **Note:** `product_brand_name` and `product_description` are derived from
        the parent `FaireProduct.raw_data` JSON column via Eloquent accessors — they
        are not dedicated DB columns. They surface in the variant listing (and detail)
        so the mapping modal can display brand context for each variant.


        **Allowed sorts:** `id`, `sku`, `faire_variant_id`, `wholesale_price`, `created_at`
        (default `-created_at`).


        **Note:** `faire_product_id` is the Faire-issued product ID (e.g. `p_3bz2tdhtkq`),
        sourced from the parent FaireProduct. It is NOT the internal `faire_product_options.faire_product_id`
        foreign key.'
      parameters:
      - name: per_page
        in: query
        schema:
          type: integer
        description: Items per page (default 15)
        example: '15'
      - name: sort
        in: query
        schema:
          type: string
        description: 'Allowed: id, sku, faire_variant_id, wholesale_price, created_at.
          Prefix with `-` for descending.'
        example: -created_at
      - name: filter[archived]
        in: query
        schema:
          type: integer
        description: 0 = active variants only (default), 1 = archived only. Omit to
          include both.
        example: '0'
      - name: filter[mapped.is]
        in: query
        schema:
          type: string
        description: 1 = only variants linked to a sku.io product. 0 = only unmapped.
          Operator suffix (`.is`) matches the advanced-filter checkbox convention.
      - name: filter[search]
        in: query
        schema:
          type: string
        description: Free-text search across sku, faire_variant_id, name (uses AdvancedSearchFilter)
      - name: filter[status][is]
        in: query
        schema:
          type: string
        description: 'Faire product status: ACTIVE | INACTIVE | DRAFT | DELETED'
      - name: filter[product_type][is]
        in: query
        schema:
          type: string
        description: Faire taxonomy product_type (e.g. "Bar Tool"). Powered by the
          filter-options endpoint.
      - name: filter[has_sku.is]
        in: query
        schema:
          type: string
        description: 1 = variants with a Faire SKU. 0 = variants missing a SKU. Operator
          suffix (`.is`) matches the advanced-filter checkbox convention.
      - name: filter[date_from]
        in: query
        schema:
          type: string
        description: Created on/after this date (any parseable date string)
      - name: filter[date_to]
        in: query
        schema:
          type: string
        description: Created on/before this date
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Faire integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        faire_product_id:
                          type: string
                        faire_variant_id:
                          type: string
                        sku:
                          type: string
                        name:
                          type: string
                        product_name:
                          type: string
                        product_status:
                          type: string
                        product_type:
                          type: string
                        product_image_url:
                          type: string
                        product_brand_name:
                          type: string
                        product_description:
                          type: string
                        product_wholesale_price_minimum:
                          type: number
                        product_currency_code:
                          type: string
                        inventory_quantity:
                          type: integer
                        faire_inventory_quantity:
                          type: integer
                        wholesale_price:
                          type: number
                        product:
                          type: string
                          nullable: true
                        sibling_options:
                          type: array
                          items:
                            type: object
                            properties:
                              id:
                                type: integer
                              faire_variant_id:
                                type: string
                              sku:
                                type: string
                              name:
                                type: string
                              wholesale_price:
                                type: number
                              inventory_quantity:
                                type: integer
                              product_listing_product:
                                type: string
                                nullable: true
                        archived_at:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                  next_page_url:
                    type: string
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 140
                    integration_instance_id: 7
                    faire_product_id: p_3bz2tdhtkq
                    faire_variant_id: 7c3a2b18-9d4a-4f6e-b211-7a9c84d0f221
                    sku: HAW-STR-CP
                    name: Antique Copper
                    product_name: Hawthorne Strainer
                    product_status: ACTIVE
                    product_type: Bar Tool
                    product_image_url: https://cdn.faire.com/img/abc123/300.jpg
                    product_brand_name: Hawthorne & Co.
                    product_description: Premium 4-prong strainer machined from solid
                      brass.
                    product_wholesale_price_minimum: 8.5
                    product_currency_code: USD
                    inventory_quantity: 12
                    faire_inventory_quantity: 12
                    wholesale_price: 8.5
                    product: null
                    sibling_options:
                    - id: 141
                      faire_variant_id: 9b81…
                      sku: HAW-STR-BLK
                      name: Matte Black
                      wholesale_price: 8.5
                      inventory_quantity: 6
                      product_listing_product: null
                    archived_at: null
                    created_at: '2026-05-04T18:22:31+00:00'
                    updated_at: '2026-05-06T19:14:02+00:00'
                  - id: 132
                    integration_instance_id: 7
                    faire_product_id: p_wvdp6e8v4u
                    faire_variant_id: f0a18…
                    sku: JAR-BELL-CP
                    name: Antique Copper
                    product_name: Bell Jar Cocktail Shaker
                    product_status: ACTIVE
                    product_type: Bar Tool
                    product_image_url: https://cdn.faire.com/img/def456/300.jpg
                    product_brand_name: Bell Jar Co.
                    product_description: null
                    product_wholesale_price_minimum: 22
                    product_currency_code: USD
                    inventory_quantity: 4
                    faire_inventory_quantity: 4
                    wholesale_price: 22
                    product:
                      id: 33421
                      sku: JAR-BELL-CP
                      name: Bell Jar Cocktail Shaker
                      default_financial_line_type_id: null
                      default_financial_line_type: null
                    sibling_options: []
                    archived_at: null
                    created_at: '2026-05-04T18:22:30+00:00'
                    updated_at: '2026-05-06T19:14:01+00:00'
                  current_page: 1
                  first_page_url: https://sku2.test/api/faire/instances/7/products?page=1
                  from: 1
                  last_page: 71
                  last_page_url: https://sku2.test/api/faire/instances/7/products?page=71
                  links: []
                  next_page_url: https://sku2.test/api/faire/instances/7/products?page=2
                  path: https://sku2.test/api/faire/instances/7/products
                  per_page: 2
                  prev_page_url: null
                  to: 2
                  total: 141
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-faire-instances-integrationinstance-products
  /api/faire/instances/{integrationInstance}/products/latest-sync-info:
    get:
      tags:
      - Faire
      summary: Get Faire Products Latest Sync Info
      description: 'Aggregate stats about the products previously synced from Faire.
        Used by the **Refresh from Faire** modal header to show how much data is currently
        cached locally and which mode of refresh is appropriate.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Path Parameters:**

        - `integrationInstance` - The ID of the integration instance


        **Response Fields:**

        - `latest_product_title` - Name of the most recently updated `FaireProduct`
        for this instance (null if none synced yet)

        - `latest_product_date` - ISO timestamp of that product''s `updated_at`

        - `total_products` - Count of distinct `faire_products` rows for this instance

        - `total_variants` - Count of `faire_product_options` rows for this instance

        - `mapped_products` - Number of variants linked to a `product_listings` row

        - `unmapped_products` - Variants without a product listing

        - `last_synced_at` - Latest `updated_at` across all variants

        - `cursor_at` - Stored incremental sync cursor on the integration instance
        (`sync_cursors.products.cursor_at`). When null, the **Fetch Since Latest Sync**
        mode is unavailable and the user is forced to choose **Refetch Entire Catalog**
        or **Custom Date Range**.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Faire integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      latest_product_title:
                        type: string
                      latest_product_date:
                        type: string
                      total_products:
                        type: integer
                      total_variants:
                        type: integer
                      mapped_products:
                        type: integer
                      unmapped_products:
                        type: integer
                      last_synced_at:
                        type: string
                      cursor_at:
                        type: string
                example:
                  data:
                    latest_product_title: Citrus Peeler, Gold & Black
                    latest_product_date: '2026-05-04T18:22:31+00:00'
                    total_products: 127
                    total_variants: 141
                    mapped_products: 0
                    unmapped_products: 141
                    last_synced_at: '2026-05-04T18:22:31+00:00'
                    cursor_at: '2026-05-04T18:22:31+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-faire-instances-integrationinstance-products-latest-sync-info
  /api/faire/instances/{integrationInstance}/products/filter-options:
    get:
      tags:
      - Faire
      summary: Get Variant Filter Options (Distinct Product Types)
      description: 'Returns distinct values for the variant listing''s filter dropdowns.
        Currently only `product_types` (sourced from `faire_products.product_type`,
        populated from Faire''s taxonomy `taxonomy_type.name`).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Used by:** the **Product Type** filter chip on the Faire products listing
        page — calls this endpoint once on mount to populate its autocomplete dropdown.


        Results are sorted alphabetically and exclude blank/null values.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Faire integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      product_types:
                        type: array
                        items:
                          type: string
                example:
                  data:
                    product_types:
                    - Bar Tool
                    - Coffee Maker
                    - Drinkware
                    - Glassware
                    - Kitchen Accessory
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-faire-instances-integrationinstance-products-filter-options
  /api/faire/instances/{integrationInstance}/products/refresh-tracked:
    post:
      tags:
      - Faire
      summary: Refresh Products from Faire (Tracked)
      description: "Dispatches a background job background job that walks the Faire\
        \ catalog and persists `faire_products` + `faire_product_options`. Returns\
        \ immediately with a tracked job log ID — progress is visible via the tracked\
        \ job log endpoints.\n\n:::info[Authorization]\nAny valid API token can call\
        \ this endpoint — no specific scope required. [Manage tokens](https://app.sku.io/settings/api).\n\
        :::\n\n**Path Parameters:**\n- `integrationInstance` - The ID of the integration\
        \ instance\n\n**Body:**\n- `mode` (required) - One of:\n  - `incremental`\
        \ - Resume from the persisted `sync_cursors.products.cursor_at` (skip products\
        \ already imported since the last sync). Recommended for routine refreshes.\n\
        \  - `full` - Reset the cursor and walk the entire catalog (slow). Use to\
        \ rebuild from scratch.\n  - `date_range` - Fetch only products whose `updated_at`\
        \ falls between `date_from` and `date_to` (inclusive). Cursor is NOT persisted\
        \ in this mode.\n- `date_from` (required when `mode=date_range`) - ISO date\
        \ string (`YYYY-MM-DD`). Sent to Faire as `updated_at_min` (start-of-day UTC).\n\
        - `date_to` (required when `mode=date_range`) - ISO date string (`YYYY-MM-DD`).\
        \ Sent to Faire as `updated_at_max` (end-of-day UTC). Must be `>= date_from`.\n\
        \n**Response:**\n- `data.tracked_job_log_id` - The ID of the dispatched tracked\
        \ job. Pass to `/api/tracked-job-logs/:id` to poll progress.\n- `message`\
        \ - Human-readable status string.\n\n**Validation Errors (422):**\n- `mode`\
        \ must be one of `incremental`, `full`, `date_range`\n- `date_from` and `date_to`\
        \ are required when `mode=date_range`\n- `date_to` must be on or after `date_from`"
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                mode:
                  type: string
                date_from:
                  type: string
                  nullable: true
                date_to:
                  type: string
                  nullable: true
              example:
                mode: incremental
                date_from: null
                date_to: null
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Faire integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 4218
                  message: Product refresh job has been queued
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      date_from:
                        type: array
                        items:
                          type: string
                      date_to:
                        type: array
                        items:
                          type: string
                example:
                  message: The date from field is required when mode is date_range.
                    (and 1 more error)
                  errors:
                    date_from:
                    - The date from field is required when mode is date_range.
                    date_to:
                    - The date to field is required when mode is date_range.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-faire-instances-integrationinstance-products-refresh-tracked
  /api/faire/instances/{integrationInstance}/products/bulk:
    post:
      tags:
      - Faire
      summary: Bulk Operation (Synchronous)
      description: "Run a bulk action on Faire product options synchronously and return\
        \ the result inline. Best for **Selected Only** requests where the count is\
        \ small and the operation completes in well under HTTP timeout. For **All\
        \ Filtered** requests that may exceed timeout, use the tracked variant instead.\n\
        \n:::info[Authorization]\nAny valid API token can call this endpoint — no\
        \ specific scope required. [Manage tokens](https://app.sku.io/settings/api).\n\
        :::\n\n**Path Parameters:**\n- `integrationInstance` (required) - The ID of\
        \ the Faire integration instance.\n\n**Body:**\n- `action` (required) - One\
        \ of `archive`, `unarchive`, `delete`, `map`, `unmap`, `create`, `remap`.\
        \ Currently only `archive`, `unarchive`, and `delete` are wired up; mapping\
        \ actions surface as `skipped`.\n- `selection` (required) - object describing\
        \ which records to act on:\n  - `selection.type` (required) - One of `selected`\
        \ (use the explicit `ids` list), `visible` (use the current page's filters),\
        \ `filtered` (use the active filter set across all matching records).\n  -\
        \ `selection.ids` (required when `type=selected`) - Array of `faire_product_options.id`\
        \ values.\n  - `selection.filters` (optional) - Spatie QueryBuilder filter\
        \ map. The same filter shape accepted by `GET /api/faire/instances/:integrationInstance/products`.\
        \ Resolved via `BulkFilterResolver`.\n- `options` (optional) - object reserved\
        \ for action-specific options (currently unused on Faire — placeholder for\
        \ future mapping options).\n\n**Response (200):**\n- `data.processed` - Count\
        \ of records the action successfully ran against.\n- `data.failed` - Count\
        \ of records that errored during the action.\n- `data.skipped` - Count of\
        \ records that were skipped (e.g., already in the target state, or unsupported\
        \ `action`).\n- `message` - Human-readable status string.\n\n**Errors:**\n\
        - `422` when no records resolve from the selection (empty `ids` for `type=selected`,\
        \ or filters returning zero rows).\n- `422` when validation fails on the body\
        \ shape."
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                action:
                  type: string
                selection:
                  type: object
                  properties:
                    type:
                      type: string
                    ids:
                      type: array
                      items:
                        type: integer
              example:
                action: archive
                selection:
                  type: selected
                  ids:
                  - 101
                  - 102
                  - 103
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Faire integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: Success — Archive Selected
                  value:
                    data:
                      processed: 3
                      failed: 0
                      skipped: 0
                    message: 'Bulk archive completed. Processed: 3, Failed: 0, Skipped:
                      0'
                example-1:
                  summary: Success — Unsupported Action (Skipped)
                  value:
                    data:
                      processed: 0
                      failed: 0
                      skipped: 2
                    message: 'Bulk map completed. Processed: 0, Failed: 0, Skipped:
                      2'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: No products found for the given selection.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-faire-instances-integrationinstance-products-bulk
  /api/faire/instances/{integrationInstance}/products/bulk-tracked:
    post:
      tags:
      - Faire
      summary: Bulk Operation (Tracked)
      description: 'Dispatches a background job background job that performs the bulk
        action across the resolved selection. Returns immediately with a tracked job
        log ID — progress is visible via the tracked job log endpoints and pollable
        via the `bulk-progress` endpoint.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Use this variant for **All Filtered** requests where the count may be large
        enough to exceed an HTTP timeout. For **Selected Only** with small counts,
        the synchronous variant is faster.


        **Path Parameters:**

        - `integrationInstance` (required) - The ID of the Faire integration instance.


        **Body:** Same shape as the synchronous `bulk` endpoint. See its description
        for full field-by-field documentation. The selection is resolved server-side
        BEFORE the job is dispatched, so the response includes the tracked-job ID
        only when at least one record matched.


        **Response (200):**

        - `data.tracked_job_log_id` - The ID of the dispatched tracked job. Pass to
        `bulk-progress/:trackedJobLogId` (or the global `/api/tracked-job-logs/:id`)
        to poll progress.

        - `message` - Human-readable status string.


        **Errors:**

        - `422` when no records resolve from the selection.

        - `422` when validation fails on the body shape.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                action:
                  type: string
                selection:
                  type: object
                  properties:
                    type:
                      type: string
                    filters:
                      type: object
                      properties:
                        archived:
                          type: integer
              example:
                action: archive
                selection:
                  type: filtered
                  filters:
                    archived: 0
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Faire integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 5217
                  message: Bulk operation job has been queued
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: No products found for the given selection.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-faire-instances-integrationinstance-products-bulk-tracked
  /api/faire/instances/{integrationInstance}/products/bulk-progress/{trackedJobLogId}:
    get:
      tags:
      - Faire
      summary: Bulk Operation Progress
      description: 'Returns the live progress of a background job. Returns the standard
        tracked job log object shape — same as the tracked job log endpoints polls.
        Poll this endpoint while the job runs; `progress_percentage` and `results`
        update as the job processes batches.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Path Parameters:**

        - `integrationInstance` (required) - The ID of the Faire integration instance.

        - `trackedJobLogId` (required) - The tracked job log ID returned by the `bulk-tracked`
        dispatch.


        **Response (200):** A standard tracked job log object. Key fields for a Faire
        bulk job:

        - `data.id` - Tracked job log ID.

        - `data.status` - One of `pending`, `processing`, `completed`, `failed`, `cancelled`.

        - `data.progress_percentage` - 0-100 (or `null` until the job starts).

        - `data.message` - Latest status message from the job.

        - `data.results` - When completed, contains `{ action, total, processed, failed,
        skipped, started_at, completed_at }`. Errors populate `results.error`.


        **Errors:**

        - `404` when the tracked job log ID does not exist.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Faire integration instance ID
        example: '1'
      - name: trackedJobLogId
        in: path
        schema:
          type: integer
        required: true
        description: ID of the tracked job log returned by the bulk-tracked endpoint
        example: '5217'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: In Progress
                  value:
                    data:
                      id: 5217
                      job_name: 'Bulk Archive: 248 Faire products'
                      status: processing
                      progress_percentage: 47
                      message: Archiving 116 of 248
                      results: null
                      created_at: '2026-05-06T19:55:00.000000Z'
                      updated_at: '2026-05-06T19:55:42.000000Z'
                example-1:
                  summary: Completed
                  value:
                    data:
                      id: 5217
                      job_name: 'Bulk Archive: 248 Faire products'
                      status: completed
                      progress_percentage: 100
                      message: Bulk archive completed
                      results:
                        action: archive
                        total: 248
                        processed: 246
                        failed: 0
                        skipped: 2
                        started_at: '2026-05-06T19:55:00.000000Z'
                        completed_at: '2026-05-06T19:56:14.000000Z'
                      created_at: '2026-05-06T19:55:00.000000Z'
                      updated_at: '2026-05-06T19:56:14.000000Z'
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No query results for model [App\Models\TrackedJobLog] 9999999.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-faire-instances-integrationinstance-products-bulk-progress-trackedjoblogid
  /api/faire/instances/{integrationInstance}/products/{option}/map:
    post:
      tags:
      - Faire
      summary: Map Single Variant to SKU.io Product
      description: 'Maps a single Faire product variant (option) to an existing SKU.io
        product. Used by the per-row Map button on the Faire products page.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        If the variant is already mapped, the existing `product_listings` row is updated
        in place (no duplicate is created) — this powers the Remap flow as well.


        **Path Parameters:**

        - `integrationInstance` - Faire integration instance ID. Returns 404 if the
        variant doesn''t belong to this instance.

        - `option` - Faire product option (variant) ID.


        **Body:**

        - `product_id` (required, integer, exists:products,id) - The SKU.io product
        ID to map this Faire variant to.


        **Response:**

        Returns the updated `FaireProductOptionDetail` resource (same shape as `GET
        .../products/:option`), with `product` populated to the newly-linked SKU.io
        product.


        **Errors:**

        - `404` - The variant does not belong to the given integration instance.

        - `422` - `product_id` is missing or does not exist in `products`.

        - `500` - The Faire integration instance has no associated `sales_channel`
        row (configuration issue).


        **Note:** `faire_product_id` is the Faire-issued product ID (e.g. `p_3bz2tdhtkq`),
        sourced from the parent FaireProduct. It is NOT the internal `faire_product_options.faire_product_id`
        foreign key.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                product_id:
                  type: integer
              example:
                product_id: 12345
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Faire integration instance ID
        example: '1'
      - name: option
        in: path
        schema:
          type: integer
        required: true
        description: Faire product option (variant) ID
        example: '139'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      faire_product_id:
                        type: string
                      faire_variant_id:
                        type: string
                      sku:
                        type: string
                      name:
                        type: string
                      wholesale_price:
                        type: number
                      product:
                        type: object
                        properties:
                          id:
                            type: integer
                          sku:
                            type: string
                          name:
                            type: string
                          default_financial_line_type:
                            type: string
                            nullable: true
                      product_listing:
                        type: object
                        properties:
                          id:
                            type: integer
                          product_id:
                            type: integer
                          sales_channel_id:
                            type: integer
                          listing_sku:
                            type: string
                example:
                  data:
                    id: 139
                    faire_product_id: p_a1b2c3d4e5f
                    faire_variant_id: v_xyz
                    sku: JGR-BELL-CP
                    name: Bell Jigger - 2 ounce, Antique Copper
                    wholesale_price: 18.5
                    product:
                      id: 12345
                      sku: JGR-BELL-CP
                      name: Bell Jigger 2oz Antique Copper
                      default_financial_line_type: null
                    product_listing:
                      id: 9871
                      product_id: 12345
                      sales_channel_id: 88
                      listing_sku: JGR-BELL-CP
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      product_id:
                        type: array
                        items:
                          type: string
                example:
                  message: The product id field is required.
                  errors:
                    product_id:
                    - The product id field is required.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-faire-instances-integrationinstance-products-option-map
    delete:
      tags:
      - Faire
      summary: Unmap Single Variant
      description: 'Removes the SKU.io product link for a single Faire variant by
        deleting the associated `product_listings` row. Idempotent — calling on a
        variant that wasn''t mapped returns `data.unmapped = false` with status 200.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Path Parameters:**

        - `integrationInstance` - Faire integration instance ID. Returns 404 if the
        variant doesn''t belong to this instance.

        - `option` - Faire product option (variant) ID.


        **Response:**

        - `data.unmapped` (boolean) - `true` if a mapping was deleted, `false` if
        the variant wasn''t mapped.

        - `message` (string) - Human-readable status (`Product unmapped` or `Product
        was not mapped`).


        **Errors:**

        - `404` - The variant does not belong to the given integration instance.


        **Note:** `faire_product_id` is the Faire-issued product ID (e.g. `p_3bz2tdhtkq`),
        sourced from the parent FaireProduct. It is NOT the internal `faire_product_options.faire_product_id`
        foreign key.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Faire integration instance ID
        example: '1'
      - name: option
        in: path
        schema:
          type: integer
        required: true
        description: Faire product option (variant) ID
        example: '139'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: Success — Mapping Removed
                  value:
                    data:
                      unmapped: true
                    message: Product unmapped
                example-1:
                  summary: No-Op — Variant Was Not Mapped
                  value:
                    data:
                      unmapped: false
                    message: Product was not mapped
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-faire-instances-integrationinstance-products-option-map
  /api/faire/instances/{integrationInstance}/products/{option}/smart-match:
    post:
      tags:
      - Faire
      summary: Find Smart-Match Candidates
      description: "Suggests SKU.io products to map a Faire variant to. Used by the\
        \ per-row mapping modal to power the **Smart Match** section.\n\n:::info[Authorization]\n\
        Any valid API token can call this endpoint — no specific scope required. [Manage\
        \ tokens](https://app.sku.io/settings/api).\n:::\n\n**Algorithm:**\n1. **Exact\
        \ match** — looks up a SKU.io product whose `sku` exactly matches the Faire\
        \ variant SKU.\n2. **Similar matches** — fuzzy text search using the parent\
        \ Faire product name (preferred) or the variant name/SKU as the search term.\
        \ Returns up to ~10 candidate products by name/SKU similarity.\n\n**Path Parameters:**\n\
        - `integrationInstance` — Faire integration instance ID. Returns 404 if the\
        \ variant doesn't belong to this instance.\n- `option` — Faire product option\
        \ (variant) ID.\n\n**Response shape:**\n```\n{\n    \"data\": {\n        \"\
        exact_match\": { id, sku, name, barcode, type, match_type: \"sku\", price\
        \ } | null,\n        \"similar_matches\": [ { id, sku, name, barcode, type,\
        \ match_type: \"fuzzy\", price } ]\n    }\n}\n```\n\n`price` is the SKU.io\
        \ product's selling price (nullable). Surfaced in the mapping modal so users\
        \ can compare against the Faire wholesale price.\n\n**Note:** Faire variants\
        \ do not carry a barcode column, so `barcode_match` is intentionally absent.\n\
        \n**Errors:**\n- `404` — The variant does not belong to the given integration\
        \ instance."
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Faire integration instance ID
        example: '1'
      - name: option
        in: path
        schema:
          type: integer
        required: true
        description: Faire product option (variant) ID
        example: '139'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: Success — Exact + Similar Matches
                  value:
                    data:
                      exact_match:
                        id: 12345
                        sku: JGR-BELL-CP
                        name: Bell Jigger 2oz Antique Copper
                        barcode: null
                        type: sku
                        match_type: sku
                        price: 12.5
                      similar_matches:
                      - id: 12346
                        sku: JGR-BELL-SS
                        name: Bell Jigger 2oz Stainless Steel
                        barcode: null
                        type: sku
                        match_type: fuzzy
                        price: 11
                      - id: 12347
                        sku: JGR-BELL-GD
                        name: Bell Jigger 2oz Gold
                        barcode: null
                        type: sku
                        match_type: fuzzy
                        price: null
                example-1:
                  summary: Success — No Matches Found
                  value:
                    data:
                      exact_match: null
                      similar_matches: []
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Not Found
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-faire-instances-integrationinstance-products-option-smart-match
  /api/faire/instances/{integrationInstance}/products/{option}/create-sku-product:
    post:
      tags:
      - Faire
      summary: Create SKU.io Product from Variant
      description: 'Creates a new SKU.io product from a Faire variant''s data and
        links the variant to it via a `product_listings` row. Used by the **Create
        New SKU Product** action in the per-row mapping modal.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Behavior:**

        - If a SKU.io product with the same SKU as the Faire variant already exists,
        links to that product instead of creating a duplicate (the response sets `linked_existing:
        true`).

        - Otherwise, creates a fresh `Product` row using the variant''s SKU, name,
        and pricing data, then maps the variant to it.

        - The new product''s SKU is made unique with a numeric suffix if the variant
        SKU collides with an unrelated product.


        **Path Parameters:**

        - `integrationInstance` — Faire integration instance ID. Returns 404 if the
        variant doesn''t belong to this instance.

        - `option` — Faire product option (variant) ID.


        **Body:** None — all data is derived from the Faire variant.


        **Response shape:** Returns the updated Faire product option object (same
        shape as `GET .../products/:option`) with `product` populated, plus:

        - `linked_existing` (bool) — `true` if an existing SKU.io product was reused.

        - `message` (string) — Human-readable status.


        **Errors:**

        - `404` — The variant does not belong to the given integration instance.

        - `422` — The variant is already mapped to a SKU.io product. Unmap it first.


        **Note:** `faire_product_id` is the Faire-issued product ID (e.g. `p_3bz2tdhtkq`),
        sourced from the parent FaireProduct. It is NOT the internal `faire_product_options.faire_product_id`
        foreign key.'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Faire integration instance ID
        example: '1'
      - name: option
        in: path
        schema:
          type: integer
        required: true
        description: Faire product option (variant) ID
        example: '139'
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: Success — New SKU.io Product Created (201)
                  value:
                    data:
                      id: 139
                      faire_product_id: p_a1b2c3d4e5f
                      faire_variant_id: v_xyz
                      sku: JGR-BELL-CP
                      name: Bell Jigger - 2 ounce, Antique Copper
                      wholesale_price: 18.5
                      product:
                        id: 67890
                        sku: JGR-BELL-CP
                        name: Bell Jigger - 2 ounce, Antique Copper
                        default_financial_line_type: null
                      product_listing:
                        id: 9872
                        product_id: 67890
                        sales_channel_id: 88
                        listing_sku: JGR-BELL-CP
                    linked_existing: false
                    message: SKU.io product created and mapped.
                example-1:
                  summary: Success — Linked to Existing SKU.io Product (201)
                  value:
                    data:
                      id: 139
                      faire_product_id: p_a1b2c3d4e5f
                      sku: JGR-BELL-CP
                      name: Bell Jigger - 2 ounce, Antique Copper
                      product:
                        id: 12345
                        sku: JGR-BELL-CP
                        name: Bell Jigger 2oz Antique Copper
                        default_financial_line_type: null
                      product_listing:
                        id: 9871
                        product_id: 12345
                        sales_channel_id: 88
                        listing_sku: JGR-BELL-CP
                    linked_existing: true
                    message: Variant linked to existing SKU.io product.
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Not Found
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: Variant is already mapped. Unmap it first.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-faire-instances-integrationinstance-products-option-create-sku-product
  /api/faire/instances/{integrationInstance}/products/{option}:
    get:
      tags:
      - Faire
      summary: Get Variant Detail
      description: 'Detail view of a single `FaireProductOption` (variant), powering
        the Faire variant detail page in application UI.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Eager-loaded relationships:**

        - `product` — parent `FaireProduct` (status, product_type, image_url, wholesale_price_minimum,
        currency_code, brand_name, description)

        - `product.options.productListing.product.defaultFinancialLineType` — sibling
        variants and their sku.io mapping

        - `productListing.product.defaultFinancialLineType` — the sku.io product this
        variant is mapped to (if any)


        **Response shape:**

        - `id`, `integration_instance_id`, `faire_product_id`, `faire_variant_id`,
        `sku`, `name`

        - `product_name`, `product_status`, `product_type`, `product_image_url` —
        copied from parent product

        - `product_brand_name`, `product_description` — derived from the parent `FaireProduct.raw_data`
        JSON via Eloquent accessors (Faire does not store these as dedicated columns)

        - `product_wholesale_price_minimum`, `product_currency_code`

        - `inventory_quantity`, `faire_inventory_quantity`, `wholesale_price`

        - `product` — `{ id, sku, name, type, default_financial_line_type_id, default_financial_line_type
        }` of the mapped sku.io product (null if unmapped). `type` is the SKU.io `products.type`
        value (`single`, `variation`, etc.).

        - `sibling_options[]` — other variants on the same `FaireProduct`, each with
        their own mapping status; sibling `product_listing_product` now includes `type`
        as well

        - `archived_at` — ISO timestamp; non-null indicates the variant is archived

        - `created_at`, `updated_at` — ISO timestamps


        **Note:** Faire''s full `raw_data` payload is NOT included here for performance
        reasons. Fetch it on-demand via `GET /api/faire/instances/:integrationInstance/products/:option/raw`.


        **Note:** `faire_product_id` is the Faire-issued product ID (e.g. `p_3bz2tdhtkq`),
        sourced from the parent FaireProduct. It is NOT the internal `faire_product_options.faire_product_id`
        foreign key.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Faire integration instance ID
        example: '1'
      - name: option
        in: path
        schema:
          type: integer
        required: true
        description: FaireProductOption ID (variant)
        example: '140'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      faire_product_id:
                        type: string
                      faire_variant_id:
                        type: string
                      sku:
                        type: string
                      name:
                        type: string
                      product_name:
                        type: string
                      product_status:
                        type: string
                      product_type:
                        type: string
                      product_image_url:
                        type: string
                      product_brand_name:
                        type: string
                      product_description:
                        type: string
                      product_wholesale_price_minimum:
                        type: number
                      product_currency_code:
                        type: string
                      inventory_quantity:
                        type: integer
                      faire_inventory_quantity:
                        type: integer
                      wholesale_price:
                        type: number
                      product:
                        type: string
                        nullable: true
                      sibling_options:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            faire_variant_id:
                              type: string
                            sku:
                              type: string
                            name:
                              type: string
                            wholesale_price:
                              type: number
                            inventory_quantity:
                              type: integer
                            product_listing_product:
                              type: string
                              nullable: true
                      archived_at:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 140
                    integration_instance_id: 7
                    faire_product_id: p_3bz2tdhtkq
                    faire_variant_id: 7c3a2b18-9d4a-4f6e-b211-7a9c84d0f221
                    sku: HAW-STR-CP
                    name: Antique Copper
                    product_name: Hawthorne Strainer
                    product_status: ACTIVE
                    product_type: Bar Tool
                    product_image_url: https://cdn.faire.com/img/abc123/300.jpg
                    product_brand_name: Hawthorne & Co.
                    product_description: Premium 4-prong strainer machined from solid
                      brass.
                    product_wholesale_price_minimum: 8.5
                    product_currency_code: USD
                    inventory_quantity: 12
                    faire_inventory_quantity: 12
                    wholesale_price: 8.5
                    product: null
                    sibling_options:
                    - id: 141
                      faire_variant_id: 9b81f27e-30dd-4a8d-9f8c-71a8bf6c0e02
                      sku: HAW-STR-BLK
                      name: Matte Black
                      wholesale_price: 8.5
                      inventory_quantity: 6
                      product_listing_product: null
                    archived_at: null
                    created_at: '2026-05-04T18:22:31+00:00'
                    updated_at: '2026-05-06T19:14:02+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-faire-instances-integrationinstance-products-option
  /api/faire/instances/{integrationInstance}/products/{option}/raw:
    get:
      tags:
      - Faire
      summary: Get Raw Data from Faire (Variant)
      description: 'Lazy-loaded raw payload from Faire for a single variant''s parent
        product. Used by the Faire variant detail page''s collapsible ''Raw Data from
        Faire'' panel — only fetched when the panel is opened.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        The response is the contents of `faire_products.raw_data` (the JSON body as
        Faire returned it during the most recent product sync). This endpoint is intentionally
        separate from the variant detail endpoint to keep the page snappy: `raw_data`
        can be ~50 KB per product.


        **Response:**

        - `data` — the raw JSON object from Faire, or `null` if the product has no
        cached raw data yet


        **404 conditions:**

        - The variant doesn''t belong to the supplied integration instance'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Faire integration instance ID
        example: '1'
      - name: option
        in: path
        schema:
          type: integer
        required: true
        description: FaireProductOption ID (variant) — the parent product's `raw_data`
          is returned
        example: '140'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: Success Response
                  value:
                    data:
                      id: p_abc123
                      name: Hand-Poured Soy Candle
                      description: Brand-supplied long description as returned by
                        Faire
                      brand_id: b_xyz789
                      active: true
                      product_type: Home Goods
                      wholesale_price_minimum:
                        amount_cents: 1500
                        currency: USD
                      options:
                      - id: po_111
                        name: Lavender
                        sku: CANDLE-LAV
                        active: true
                        available_quantity: 12
                      images:
                      - id: im_aaa
                        url: https://cdn.faire.com/example.jpg
                      created_at: '2025-08-01T10:30:00Z'
                      updated_at: '2026-04-22T14:12:00Z'
                example-1:
                  summary: Empty Raw Data
                  value:
                    data: null
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Not Found
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-faire-instances-integrationinstance-products-option-raw
  /api/faire/instances/{integrationInstance}/mappings:
    get:
      tags:
      - Faire
      summary: Get Product Field Mappings
      description: 'Get the product field mappings for a Faire integration instance.
        Mappings control which Faire listing/variant fields populate which SKU.io
        product fields when a SKU.io product is created from a Faire variant.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Default mappings (`sku` → `sku`, `name` → `item_name`, `wholesale_price` →
        the default pricing tier) are merged with per-instance custom mappings; a
        custom mapping targeting the same SKU.io field overrides the default.


        **Path Parameters:**

        - `integrationInstance` - The ID of the integration instance


        **Response:**

        - `integration_instance_id` - The integration instance ID

        - `integration_name` - The integration instance name

        - `mappings` - The effective mapping list (defaults merged with custom overrides)

        - `available_faire_fields` - Faire fields that can be used as a mapping source
        (`name`, `brand_name`, `description`, `sku`, `wholesale_price`), each with
        `name`, `label`, `type`, `description`, and `group`

        - `available_sku_fields` - SKU.io product fields that can be mapped to: static
        fields (`sku`, `name`, `item_name`, `barcode`, `description`, `unit_cost`,
        `weight`, `weight_unit`, `brand`) plus dynamic pricing-tier fields (`price.{tier}.value`)
        and product attribute fields (`attributes.{name}`)

        - `default_mappings` - The built-in defaults (each with `source: "default"`)

        - `custom_mappings` - Per-instance overrides saved via the update endpoint
        (each with `source: "custom"`)

        - `effective_mappings` - Same merged list as `mappings`


        Each mapping entry has:

        - `listing_field` - The Faire source field

        - `sku_field` - The SKU.io destination field

        - `parsers` - Optional value-transformation rules applied in order

        - `source` - `default` or `custom`

        - `description` - Human-readable summary of the mapping'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Faire integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      integration_instance_id:
                        type: integer
                      integration_name:
                        type: string
                      mappings:
                        type: array
                        items:
                          type: object
                          properties:
                            listing_field:
                              type: string
                            sku_field:
                              type: string
                            parsers:
                              type: array
                            source:
                              type: string
                            description:
                              type: string
                      available_faire_fields:
                        type: object
                        properties:
                          name:
                            type: object
                            properties:
                              name:
                                type: string
                              label:
                                type: string
                              type:
                                type: string
                              description:
                                type: string
                              group:
                                type: string
                          brand_name:
                            type: object
                            properties:
                              name:
                                type: string
                              label:
                                type: string
                              type:
                                type: string
                              description:
                                type: string
                              group:
                                type: string
                          description:
                            type: object
                            properties:
                              name:
                                type: string
                              label:
                                type: string
                              type:
                                type: string
                              description:
                                type: string
                              group:
                                type: string
                          sku:
                            type: object
                            properties:
                              name:
                                type: string
                              label:
                                type: string
                              type:
                                type: string
                              description:
                                type: string
                              group:
                                type: string
                          wholesale_price:
                            type: object
                            properties:
                              name:
                                type: string
                              label:
                                type: string
                              type:
                                type: string
                              description:
                                type: string
                              group:
                                type: string
                      available_sku_fields:
                        type: object
                        properties:
                          sku:
                            type: object
                            properties:
                              name:
                                type: string
                              label:
                                type: string
                              type:
                                type: string
                              description:
                                type: string
                              group:
                                type: string
                          name:
                            type: object
                            properties:
                              name:
                                type: string
                              label:
                                type: string
                              type:
                                type: string
                              description:
                                type: string
                              group:
                                type: string
                          item_name:
                            type: object
                            properties:
                              name:
                                type: string
                              label:
                                type: string
                              type:
                                type: string
                              description:
                                type: string
                              group:
                                type: string
                          barcode:
                            type: object
                            properties:
                              name:
                                type: string
                              label:
                                type: string
                              type:
                                type: string
                              description:
                                type: string
                              group:
                                type: string
                          description:
                            type: object
                            properties:
                              name:
                                type: string
                              label:
                                type: string
                              type:
                                type: string
                              description:
                                type: string
                              group:
                                type: string
                          unit_cost:
                            type: object
                            properties:
                              name:
                                type: string
                              label:
                                type: string
                              type:
                                type: string
                              description:
                                type: string
                              group:
                                type: string
                          weight:
                            type: object
                            properties:
                              name:
                                type: string
                              label:
                                type: string
                              type:
                                type: string
                              description:
                                type: string
                              group:
                                type: string
                          weight_unit:
                            type: object
                            properties:
                              name:
                                type: string
                              label:
                                type: string
                              type:
                                type: string
                              description:
                                type: string
                              group:
                                type: string
                          brand:
                            type: object
                            properties:
                              name:
                                type: string
                              label:
                                type: string
                              type:
                                type: string
                              description:
                                type: string
                              group:
                                type: string
                          price.Wholesale.value:
                            type: object
                            properties:
                              name:
                                type: string
                              label:
                                type: string
                              type:
                                type: string
                              description:
                                type: string
                              group:
                                type: string
                          attributes.Color:
                            type: object
                            properties:
                              name:
                                type: string
                              label:
                                type: string
                              type:
                                type: string
                              description:
                                type: string
                              group:
                                type: string
                      default_mappings:
                        type: array
                        items:
                          type: object
                          properties:
                            listing_field:
                              type: string
                            sku_field:
                              type: string
                            parsers:
                              type: array
                            source:
                              type: string
                            description:
                              type: string
                      custom_mappings:
                        type: array
                        items:
                          type: object
                          properties:
                            listing_field:
                              type: string
                            sku_field:
                              type: string
                            parsers:
                              type: array
                            source:
                              type: string
                            description:
                              type: string
                      effective_mappings:
                        type: array
                        items:
                          type: object
                          properties:
                            listing_field:
                              type: string
                            sku_field:
                              type: string
                            parsers:
                              type: array
                            source:
                              type: string
                            description:
                              type: string
                example:
                  data:
                    integration_instance_id: 1
                    integration_name: Faire - Main Brand
                    mappings:
                    - listing_field: sku
                      sku_field: sku
                      parsers: []
                      source: default
                      description: Maps sku to sku
                    - listing_field: name
                      sku_field: item_name
                      parsers: []
                      source: default
                      description: Maps name to item_name
                    - listing_field: wholesale_price
                      sku_field: price.Wholesale.value
                      parsers: []
                      source: default
                      description: Maps wholesale_price to price.Wholesale.value
                    - listing_field: brand_name
                      sku_field: brand
                      parsers: []
                      source: custom
                      description: 'Custom mapping: brand_name → brand'
                    available_faire_fields:
                      name:
                        name: name
                        label: Product Name
                        type: string
                        description: Faire product name (from parent product)
                        group: Product Info
                      brand_name:
                        name: brand_name
                        label: Brand Name
                        type: string
                        description: Brand name from Faire product raw data
                        group: Product Info
                      description:
                        name: description
                        label: Description
                        type: string
                        description: Product description from Faire product raw data
                        group: Product Info
                      sku:
                        name: sku
                        label: SKU
                        type: string
                        description: Faire option SKU
                        group: Variant Details
                      wholesale_price:
                        name: wholesale_price
                        label: Wholesale Price
                        type: decimal
                        description: Faire option wholesale price
                        group: Pricing
                    available_sku_fields:
                      sku:
                        name: sku
                        label: SKU
                        type: string
                        description: Stock Keeping Unit
                        group: Basic Info
                      name:
                        name: name
                        label: Product Name
                        type: string
                        description: Product name/title
                        group: Basic Info
                      item_name:
                        name: item_name
                        label: Item Name
                        type: string
                        description: Item name (alias for product name)
                        group: Basic Info
                      barcode:
                        name: barcode
                        label: Barcode
                        type: string
                        description: Product barcode/UPC
                        group: Basic Info
                      description:
                        name: description
                        label: Description
                        type: string
                        description: Product description
                        group: Basic Info
                      unit_cost:
                        name: unit_cost
                        label: Unit Cost
                        type: decimal
                        description: Product cost price
                        group: Pricing
                      weight:
                        name: weight
                        label: Weight
                        type: decimal
                        description: Product weight
                        group: Physical
                      weight_unit:
                        name: weight_unit
                        label: Weight Unit
                        type: string
                        description: Unit of weight measurement
                        group: Physical
                      brand:
                        name: brand
                        label: Brand
                        type: string
                        description: Product brand name
                        group: Categorization
                      price.Wholesale.value:
                        name: price.Wholesale.value
                        label: 'Pricing: Wholesale'
                        type: decimal
                        description: Price value for Wholesale pricing tier
                        group: Pricing Tiers
                      attributes.Color:
                        name: attributes.Color
                        label: 'Attribute: Color'
                        type: string
                        description: 'Product attribute: Color'
                        group: Product Attributes
                    default_mappings:
                    - listing_field: sku
                      sku_field: sku
                      parsers: []
                      source: default
                      description: Maps sku to sku
                    - listing_field: name
                      sku_field: item_name
                      parsers: []
                      source: default
                      description: Maps name to item_name
                    - listing_field: wholesale_price
                      sku_field: price.Wholesale.value
                      parsers: []
                      source: default
                      description: Maps wholesale_price to price.Wholesale.value
                    custom_mappings:
                    - listing_field: brand_name
                      sku_field: brand
                      parsers: []
                      source: custom
                      description: 'Custom mapping: brand_name → brand'
                    effective_mappings:
                    - listing_field: sku
                      sku_field: sku
                      parsers: []
                      source: default
                      description: Maps sku to sku
                    - listing_field: name
                      sku_field: item_name
                      parsers: []
                      source: default
                      description: Maps name to item_name
                    - listing_field: wholesale_price
                      sku_field: price.Wholesale.value
                      parsers: []
                      source: default
                      description: Maps wholesale_price to price.Wholesale.value
                    - listing_field: brand_name
                      sku_field: brand
                      parsers: []
                      source: custom
                      description: 'Custom mapping: brand_name → brand'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-faire-instances-integrationinstance-mappings
    put:
      tags:
      - Faire
      summary: Update Product Field Mappings
      description: 'Update the custom product field mappings for a Faire integration
        instance. The submitted array replaces the instance''s entire custom mapping
        set — include every custom mapping you want to keep.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Custom mappings override the built-in defaults when they target the same SKU.io
        field; defaults remain in effect for any SKU.io field not covered by a custom
        mapping.


        **Path Parameters:**

        - `integrationInstance` - The ID of the integration instance


        **Request Body:**

        - `mappings` (required, array) - The custom mapping list

        - `mappings[].listing_field` (required, string) - Faire source field: `name`,
        `brand_name`, `description`, `sku`, or `wholesale_price`

        - `mappings[].sku_field` (required, string) - SKU.io destination field: a
        static field (`sku`, `name`, `item_name`, `barcode`, `description`, `unit_cost`,
        `weight`, `weight_unit`, `brand`), a pricing-tier field (`price.{tier}.value`),
        or an attribute field (`attributes.{name}`)

        - `mappings[].parsers` (optional, array) - Value-transformation rules applied
        in order when the mapping is resolved; each entry has a `rule` name and `args`


        **Response:**

        - `data.integration_instance_id` - The integration instance ID

        - `data.integration_name` - The integration instance name

        - `data.mappings` - The new effective mapping list (defaults merged with the
        saved custom mappings)

        - `data.effective_mappings` - Same merged list as `mappings`

        - `message` - Confirmation message'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                mappings:
                  type: array
                  items:
                    type: object
                    properties:
                      listing_field:
                        type: string
                      sku_field:
                        type: string
                      parsers:
                        type: array
              example:
                mappings:
                - listing_field: sku
                  sku_field: sku
                  parsers: []
                - listing_field: name
                  sku_field: item_name
                  parsers: []
                - listing_field: wholesale_price
                  sku_field: price.Wholesale.value
                  parsers: []
                - listing_field: brand_name
                  sku_field: brand
                  parsers: []
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Faire integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      integration_instance_id:
                        type: integer
                      integration_name:
                        type: string
                      mappings:
                        type: array
                        items:
                          type: object
                          properties:
                            listing_field:
                              type: string
                            sku_field:
                              type: string
                            parsers:
                              type: array
                            source:
                              type: string
                            description:
                              type: string
                      effective_mappings:
                        type: array
                        items:
                          type: object
                          properties:
                            listing_field:
                              type: string
                            sku_field:
                              type: string
                            parsers:
                              type: array
                            source:
                              type: string
                            description:
                              type: string
                  message:
                    type: string
                example:
                  data:
                    integration_instance_id: 1
                    integration_name: Faire - Main Brand
                    mappings:
                    - listing_field: sku
                      sku_field: sku
                      parsers: []
                      source: default
                      description: Maps sku to sku
                    - listing_field: name
                      sku_field: item_name
                      parsers: []
                      source: default
                      description: Maps name to item_name
                    - listing_field: wholesale_price
                      sku_field: price.Wholesale.value
                      parsers: []
                      source: default
                      description: Maps wholesale_price to price.Wholesale.value
                    - listing_field: brand_name
                      sku_field: brand
                      parsers: []
                      source: custom
                      description: 'Custom mapping: brand_name → brand'
                    effective_mappings:
                    - listing_field: sku
                      sku_field: sku
                      parsers: []
                      source: default
                      description: Maps sku to sku
                    - listing_field: name
                      sku_field: item_name
                      parsers: []
                      source: default
                      description: Maps name to item_name
                    - listing_field: wholesale_price
                      sku_field: price.Wholesale.value
                      parsers: []
                      source: default
                      description: Maps wholesale_price to price.Wholesale.value
                    - listing_field: brand_name
                      sku_field: brand
                      parsers: []
                      source: custom
                      description: 'Custom mapping: brand_name → brand'
                  message: Field mappings updated successfully
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      mappings:
                        type: array
                        items:
                          type: string
                example:
                  message: The mappings field is required.
                  errors:
                    mappings:
                    - The mappings field is required.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: put-api-faire-instances-integrationinstance-mappings
  /api/faire/inventory:
    get:
      tags:
      - Faire
      summary: List Faire Inventory
      description: '**Legacy** — prefer the per-instance route `GET /api/faire/instances/{integrationInstance}/inventory`.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        List Faire product variant inventory levels (product options) for a specific
        integration instance.


        **Tenant resolution (multi-instance safety):**

        Both shapes are accepted, in priority order:

        - `filter[integration_instance_ids]` (preferred, Amazon-unified plural form;
        comma-separated CSV — first ID wins)

        - `filter[instance_id]` (legacy singular)

        - `?instance_id=` query string fallback

        - body `instance_id` (POST/PUT only)


        If none resolve to an existing FaireIntegrationInstance the endpoint returns
        an empty/zeroed payload — it does NOT silently fall back to the first tenant''s
        data.


        **Empty-paginator response** when no instance resolves.


        ---


        List Faire product variant inventory levels (product options) for a specific
        integration instance.


        This endpoint returns inventory data at the variant/SKU level (FaireProductOption
        records).


        **Query Parameters:**

        - `instance_id` (optional) - Filter to a specific integration instance. Defaults
        to the first instance.

        - `page` (optional) - Page number (default: 1)

        - `per_page` (optional) - Items per page (default: 10)


        **Response Fields per Variant:**

        - `id` - Internal product option ID

        - `faire_product_id` - Faire product ID

        - `faire_variant_id` - Faire variant ID

        - `sku` - SKU code

        - `name` - Variant name

        - `inventory_quantity` - Current inventory quantity in the linked warehouse

        - `faire_inventory_quantity` - Last-pushed inventory quantity on Faire

        - `wholesale_price` - Wholesale price in cents

        - `product_name` - Parent product name (when loaded)'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        description: 'Page number for pagination (default: 1)'
        example: '1'
      - name: per_page
        in: query
        schema:
          type: integer
        description: 'Number of results per page (default: 10)'
        example: '10'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        faire_product_id:
                          type: string
                        faire_variant_id:
                          type: string
                        sku:
                          type: string
                        name:
                          type: string
                        inventory_quantity:
                          type: integer
                        faire_inventory_quantity:
                          type: integer
                        wholesale_price:
                          type: integer
                        product_name:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - id: 301
                    faire_product_id: p_xyz456abc
                    faire_variant_id: pv_var001
                    sku: CANDLE-SM-RED
                    name: Red
                    inventory_quantity: 120
                    faire_inventory_quantity: 115
                    wholesale_price: 1500
                    product_name: Small Candle
                  current_page: 1
                  last_page: 4
                  per_page: 10
                  total: 35
                  from: 1
                  to: 10
        '429': *id001
        '401': *id002
        '403': *id003
      deprecated: true
      operationId: get-api-faire-inventory
  /api/faire/inventory/summary:
    get:
      tags:
      - Faire
      summary: Get Faire Inventory Summary
      description: "**Legacy** — prefer the per-instance route `GET /api/faire/instances/{integrationInstance}/inventory/summary`.\n\
        \n:::info[Authorization]\nAny valid API token can call this endpoint — no\
        \ specific scope required. [Manage tokens](https://app.sku.io/settings/api).\n\
        :::\n\nAggregate inventory comparison metrics for a Faire integration instance\
        \ (total tracked items, count in-sync with Faire, count needing an update,\
        \ count never fetched).\n\n**Tenant resolution (multi-instance safety):**\n\
        Both shapes are accepted, in priority order:\n- `filter[integration_instance_ids]`\
        \ (preferred, Amazon-unified plural form; comma-separated CSV — first ID wins)\n\
        - `filter[instance_id]` (legacy singular)\n- `?instance_id=` query string\
        \ fallback\n- body `instance_id` (POST/PUT only)\n\nIf none resolve to an\
        \ existing FaireIntegrationInstance the endpoint returns an empty/zeroed payload\
        \ — it does NOT silently fall back to the first tenant's data.\n\n**Zeroed\
        \ response** when no instance resolves:\n```json\n{\n  \"data\": {\n    \"\
        total_items\": 0,\n    \"in_sync\": 0,\n    \"needs_update\": 0,\n    \"never_fetched\"\
        : 0\n  }\n}\n```\n"
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: Success Response
                  value:
                    data:
                      total_items: 142
                      in_sync: 120
                      needs_update: 18
                      never_fetched: 4
                example-1:
                  summary: Empty Response (No Instance Resolved)
                  value:
                    data:
                      total_items: 0
                      in_sync: 0
                      needs_update: 0
                      never_fetched: 0
        '429': *id001
        '401': *id002
        '403': *id003
      deprecated: true
      operationId: get-api-faire-inventory-summary
  /api/faire/inventory/push:
    post:
      tags:
      - Faire
      summary: Push Inventory to Faire
      description: 'Push current inventory levels from the linked warehouse to Faire.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Request Body:**

        - `instance_id` (required) - The ID of the integration instance to push inventory
        for


        **Behavior:**

        - Dispatches a background job immediately

        - The job reads inventory quantities from the linked warehouse and updates
        each Faire product variant via the Faire API

        - Useful for an immediate manual push when automatic sync is not running

        - Progress can be tracked via the returned `tracked_job_log_id`


        **Response:**

        Returns immediately with a tracked job log ID.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                instance_id:
                  type: integer
              example:
                instance_id: 1
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 145
                  message: Inventory push started
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      deprecated: true
      operationId: post-api-faire-inventory-push
  /api/faire/inventory/refresh:
    post:
      tags:
      - Faire
      summary: Refresh Inventory Snapshot
      description: 'Refresh the local inventory snapshot by pulling current inventory
        levels from the Faire API.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Request Body:**

        - `instance_id` (required) - The ID of the integration instance to refresh
        inventory for


        **Behavior:**

        - Dispatches a background job immediately

        - The job pulls inventory levels from Faire and updates the local `faire_inventory_quantity`
        field on each product option

        - Use this to reconcile local data against Faire when discrepancies are suspected

        - Progress can be tracked via the returned `tracked_job_log_id`


        **Response:**

        Returns immediately with a tracked job log ID.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                instance_id:
                  type: integer
              example:
                instance_id: 1
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 146
                  message: Inventory refresh started
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-faire-inventory-refresh
  /api/faire/instances/{integrationInstance}/inventory:
    get:
      tags:
      - Faire
      summary: List Faire Inventory
      description: 'List the inventory comparison for a Faire integration instance
        — one row per Faire listing/variant, comparing the SKU.io quantity against
        the last-known quantity on Faire.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Rows come from a locally cached snapshot that is kept current by the fetch,
        push, and recache actions (and by the scheduled inventory sync). Each row''s
        `status` is derived as:

        - `needs_recalc` — the SKU.io quantity is flagged for recalculation and the
        row is excluded from pushes until recached

        - `synced` — quantities match (negative SKU.io quantities are treated as 0
        for the comparison)

        - `variance` — quantities differ; the row will be included in the next push


        **Path Parameters:**

        - `integrationInstance` - The ID of the integration instance


        **Query Parameters:**

        - `page` (optional) - Page number (default: 1)

        - `per_page` (optional) - Results per page (default: 10)

        - `sort` (optional) - Prefix with `-` for descending. Allowed: `id`, `sku_quantity`,
        `sales_channel_quantity`, `sales_channel_quantity_updated_at`, `sales_channel_quantity_synced_at`,
        `created_at`, `updated_at` (default: `-id`)

        - `filter[search]` (optional) - Fuzzy search across listing SKU, listing title,
        and SKU.io product SKU

        - `filter[status.is]` (optional) - `synced`, `variance`, or `needs_recalc`
        (aliases `in_sync`, `needs_update` accepted); `status.is_one_of` takes a comma-separated
        list, `status.is_not` excludes one value

        - `filter[listing_sku.*]` / `filter[title.*]` (optional) - Text filters with
        operators: contains, does_not_contain, is, is_not, is_one_of, is_not_one_of,
        starts_with, does_not_start_with, ends_with, does_not_end_with, is_empty,
        is_not_empty

        - `filter[sku_quantity.*]` / `filter[sales_channel_quantity.*]` (optional)
        - Numeric filters with operators: is, is_not, is_one_of, is_not_one_of, greater_than,
        less_than, greater_than_or_equal, less_than_or_equal, between, is_empty, is_not_empty

        - `filter[sales_channel_quantity_updated_at.*]`, `filter[sales_channel_quantity_synced_at.*]`,
        `filter[created_at.*]`, `filter[updated_at.*]` (optional) - Datetime filters
        with operators: is, is_not, before, after, on_or_before, on_or_after, between,
        is_empty, is_not_empty, today, yesterday, tomorrow, past_week, past_month,
        past_year, next_week, next_month, next_year, days_ago, days_from_now, past_days,
        next_days

        - `filter_groups` (optional) - Base64-encoded JSON tree of nested AND/OR filter
        groups


        **Response:**

        Paginated list. Each row contains:

        - `id` - Inventory cache row ID

        - `product_listing_id` - SKU.io product listing ID

        - `document_id` - Faire variant record ID

        - `sku` - Listing SKU (falls back to the Faire variant SKU)

        - `title` - Listing title (falls back to the Faire product name)

        - `product_sku` - Linked SKU.io product SKU

        - `sku_quantity` - Current SKU.io sellable quantity

        - `sales_channel_quantity` - Last-known quantity on Faire (null if never fetched)

        - `variance` - SKU.io quantity (clamped at 0) minus the Faire quantity

        - `change_needed` - Quantity delta a push would send (null if the Faire quantity
        was never fetched)

        - `status` - `synced`, `variance`, or `needs_recalc`

        - `is_sku_recalculation_needed` - True when the SKU.io quantity is stale and
        pending recalculation

        - `sales_channel_quantity_updated_at` - When the Faire quantity was last fetched

        - `sales_channel_quantity_synced_at` - When a quantity was last pushed to
        Faire

        - `sku_quantity_updated_at` - When the SKU.io quantity was last recalculated

        - `created_at` / `updated_at` - Cache row timestamps

        - `faire_variant_id` - Faire variant ID

        - `faire_listing_url` - Listing URL on Faire (currently always null)'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Faire integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        product_listing_id:
                          type: integer
                        document_id:
                          type: integer
                        sku:
                          type: string
                        title:
                          type: string
                        product_sku:
                          type: string
                        sku_quantity:
                          type: integer
                        sales_channel_quantity:
                          type: integer
                        variance:
                          type: integer
                        change_needed:
                          type: integer
                        status:
                          type: string
                        is_sku_recalculation_needed:
                          type: boolean
                        sales_channel_quantity_updated_at:
                          type: string
                        sales_channel_quantity_synced_at:
                          type: string
                        sku_quantity_updated_at:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                        faire_variant_id:
                          type: string
                        faire_listing_url:
                          type: string
                          nullable: true
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - id: 512
                    product_listing_id: 2048
                    document_id: 301
                    sku: CANDLE-SM-RED
                    title: Small Candle - Red
                    product_sku: CANDLE-SM-RED
                    sku_quantity: 120
                    sales_channel_quantity: 115
                    variance: 5
                    change_needed: 5
                    status: variance
                    is_sku_recalculation_needed: false
                    sales_channel_quantity_updated_at: '2026-07-06T14:22:10.000000Z'
                    sales_channel_quantity_synced_at: '2026-07-05T09:00:03.000000Z'
                    sku_quantity_updated_at: '2026-07-06T13:58:41.000000Z'
                    created_at: '2026-05-01T10:15:00.000000Z'
                    updated_at: '2026-07-06T14:22:10.000000Z'
                    faire_variant_id: pv_var001
                    faire_listing_url: null
                  - id: 511
                    product_listing_id: 2047
                    document_id: 300
                    sku: CANDLE-SM-BLUE
                    title: Small Candle - Blue
                    product_sku: CANDLE-SM-BLUE
                    sku_quantity: 48
                    sales_channel_quantity: 48
                    variance: 0
                    change_needed: 0
                    status: synced
                    is_sku_recalculation_needed: false
                    sales_channel_quantity_updated_at: '2026-07-06T14:22:10.000000Z'
                    sales_channel_quantity_synced_at: '2026-07-06T09:00:02.000000Z'
                    sku_quantity_updated_at: '2026-07-06T08:45:19.000000Z'
                    created_at: '2026-05-01T10:15:00.000000Z'
                    updated_at: '2026-07-06T14:22:10.000000Z'
                    faire_variant_id: pv_var002
                    faire_listing_url: null
                  current_page: 1
                  last_page: 4
                  per_page: 10
                  total: 35
                  from: 1
                  to: 10
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-faire-instances-integrationinstance-inventory
  /api/faire/instances/{integrationInstance}/inventory/summary:
    get:
      tags:
      - Faire
      summary: Get Faire Inventory Summary
      description: 'Get aggregate inventory sync statistics for a Faire integration
        instance, computed from the same cached snapshot as the inventory list.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Path Parameters:**

        - `integrationInstance` - The ID of the integration instance


        **Response:**

        - `total_items` - Total listings tracked for this instance

        - `in_sync` - Listings whose SKU.io and Faire quantities match

        - `with_variance` - Listings whose quantities differ (would be included in
        the next push)

        - `needs_recalculation` - Listings whose SKU.io quantity is flagged as stale

        - `in_stock` - Listings with a positive quantity on Faire (relevant for FBF
        instances)

        - `out_of_stock` - Listings with zero quantity on Faire (relevant for FBF
        instances)

        - `last_fetch_at` - Most recent time a quantity was fetched from Faire (null
        if never)

        - `last_sync_at` - Most recent time a quantity was pushed to Faire (null if
        never)

        - `needs_update` - Legacy alias of `with_variance`

        - `never_fetched` - Listings whose Faire quantity has never been fetched


        If the instance has no sales channel yet, all counts return 0 and the timestamps
        return null.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Faire integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      total_items:
                        type: integer
                      in_sync:
                        type: integer
                      with_variance:
                        type: integer
                      needs_recalculation:
                        type: integer
                      in_stock:
                        type: integer
                      out_of_stock:
                        type: integer
                      last_fetch_at:
                        type: string
                      last_sync_at:
                        type: string
                      needs_update:
                        type: integer
                      never_fetched:
                        type: integer
                example:
                  data:
                    total_items: 35
                    in_sync: 28
                    with_variance: 5
                    needs_recalculation: 2
                    in_stock: 30
                    out_of_stock: 5
                    last_fetch_at: '2026-07-06T14:22:10.000000Z'
                    last_sync_at: '2026-07-06T09:00:02.000000Z'
                    needs_update: 5
                    never_fetched: 3
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-faire-instances-integrationinstance-inventory-summary
  /api/faire/instances/{integrationInstance}/inventory/fetch:
    post:
      tags:
      - Faire
      summary: Refresh Inventory from Faire
      description: 'Pull current inventory quantities from Faire into the local snapshot
        for a Faire integration instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Path Parameters:**

        - `integrationInstance` - The ID of the integration instance


        **Behavior:**

        - Dispatches a background job immediately and returns — the refresh runs asynchronously

        - The job walks Faire''s paginated products feed and reads each variant''s
        available quantity, updating the cached Faire quantity and its fetched-at
        timestamp per listing

        - Works for both FBM and FBF instances

        - Progress can be monitored via the returned `tracked_job_log_id`


        **Response:**

        Returns immediately with a tracked job log ID:

        - `data.tracked_job_log_id` - ID for monitoring the background refresh

        - `message` - Confirmation that the refresh started'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Faire integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 146
                  message: Inventory refresh started
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-faire-instances-integrationinstance-inventory-fetch
  /api/faire/instances/{integrationInstance}/inventory/push:
    post:
      tags:
      - Faire
      summary: Push Inventory to Faire
      description: 'Push SKU.io inventory quantities to Faire for a Faire integration
        instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Path Parameters:**

        - `integrationInstance` - The ID of the integration instance


        **Behavior:**

        - Dispatches a background job immediately and returns — the push runs asynchronously

        - Only listings with a variance between the SKU.io and Faire quantities are
        pushed; rows flagged as needing recalculation are excluded until they are
        recached

        - Quantities are clamped at a minimum of 0 before being sent to Faire

        - Each successfully pushed listing is marked synced with a fresh synced-at
        timestamp

        - Outbound inventory sync must be enabled on the instance — when it is disabled,
        the job pushes nothing

        - Progress can be monitored via the returned `tracked_job_log_id`


        **Not available for FBF instances** — returns 422, since Faire manages inventory
        in FBF (Fulfilled by Faire) mode.


        **Response:**

        Returns immediately with a tracked job log ID:

        - `data.tracked_job_log_id` - ID for monitoring the background push

        - `message` - Confirmation that the push started'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Faire integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 145
                  message: Inventory push started
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Inventory push is not supported for FBF instances. Faire
                    manages inventory in FBF mode.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-faire-instances-integrationinstance-inventory-push
  /api/faire/instances/{integrationInstance}/inventory/recache:
    post:
      tags:
      - Faire
      summary: Recache Inventory Quantities
      description: 'Recalculate the SKU.io sellable quantities cached for every listing
        on a Faire integration instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Path Parameters:**

        - `integrationInstance` - The ID of the integration instance


        **Behavior:**

        - Dispatches a background job immediately and returns — the recache runs asynchronously

        - The job marks every cached row for the instance as needing recalculation,
        then recomputes each listing''s SKU.io quantity and writes fresh values with
        updated timestamps

        - Use this when SKU.io quantities in the inventory comparison look stale,
        or to clear rows stuck in the `needs_recalc` status so the next push can include
        them

        - Progress can be monitored via the returned `tracked_job_log_id`


        **Not available for FBF instances** — returns 422, since Faire manages inventory
        in FBF (Fulfilled by Faire) mode.


        **Response:**

        Returns immediately with a tracked job log ID:

        - `data.tracked_job_log_id` - ID for monitoring the background recache

        - `message` - Confirmation that the recache started'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Faire integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 147
                  message: Inventory recache started
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Inventory recache is not supported for FBF instances. Faire
                    manages inventory in FBF mode.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-faire-instances-integrationinstance-inventory-recache
  /api/webhooks/faire:
    post:
      tags:
      - Faire
      summary: Receive Faire Webhook
      description: 'Single webhook endpoint that receives every Faire event. Faire
        identifies the event via the `X-Faire-Webhook-Topic` header — the request
        body shape varies by topic.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Authentication:** none — Faire calls this endpoint directly. The `X-Faire-Brand-Token`
        header identifies the integration instance.


        **Required headers:**

        - `X-Faire-Webhook-Topic` — one of `ORDER_CREATED`, `ORDER_UPDATED`, `INVENTORY_QUANTITY_UPDATED`
        (Faire also accepts `X-Faire-Topic`)

        - `X-Faire-Brand-Token` — brand token used to look up the integration instance


        **Supported topics:**

        - `ORDER_CREATED` — new order placed; full order payload (default body shown
        here)

        - `ORDER_UPDATED` — order state change, shipments added, etc.

        - `INVENTORY_QUANTITY_UPDATED` — variant-level inventory update from Faire


        Use the saved examples below to see each event''s payload shape.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                id:
                  type: string
                display_id:
                  type: string
                retailer:
                  type: object
                  properties:
                    id:
                      type: string
                    name:
                      type: string
                    state:
                      type: string
                    country_code:
                      type: string
                items:
                  type: array
                  items:
                    type: object
                    properties:
                      id:
                        type: string
                      product_id:
                        type: string
                      variant_id:
                        type: string
                      sku:
                        type: string
                      quantity:
                        type: integer
                      unit_price:
                        type: integer
                subtotal:
                  type: integer
                total:
                  type: integer
                currency_code:
                  type: string
                created_at:
                  type: string
                state:
                  type: string
              example:
                id: bo_abc123xyz
                display_id: FO-0001
                retailer:
                  id: b_xyz789
                  name: The Boutique Shop
                  state: CA
                  country_code: US
                items:
                - id: bi_item001
                  product_id: p_xyz456abc
                  variant_id: pv_var001
                  sku: CANDLE-SM-RED
                  quantity: 10
                  unit_price: 1500
                subtotal: 15000
                total: 15000
                currency_code: USD
                created_at: '2026-04-20T08:30:00Z'
                state: NEW
      parameters:
      - name: X-Faire-Webhook-Topic
        in: header
        schema:
          type: string
        description: Faire webhook topic header
        example: ORDER_CREATED
      - name: X-Faire-Brand-Token
        in: header
        schema:
          type: string
        description: Faire brand token to identify the integration instance
        example: your_faire_brand_token
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: ORDER_CREATED payload
                  value:
                    success: true
                    message: ORDER_CREATED webhook processed
                example-1:
                  summary: ORDER_UPDATED payload
                  value:
                    success: true
                    message: ORDER_UPDATED webhook processed
                example-2:
                  summary: INVENTORY_QUANTITY_UPDATED payload
                  value:
                    success: true
                    message: INVENTORY_QUANTITY_UPDATED webhook processed
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-webhooks-faire
  /api/gift-cards:
    get:
      tags:
      - Gift Cards
      summary: List Gift Cards
      description: 'Paginated list of gift cards with their computed balance (N+1-safe).
        Filterable by status/customer/digital and searchable by code or recipient.
        Requires pos.operate.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token (PAT).'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        code:
                          type: string
                        status:
                          type: string
                        status_label:
                          type: string
                        balance:
                          type: number
                        currency_id:
                          type: integer
                        customer_id:
                          type: integer
                        is_digital:
                          type: boolean
                        recipient_name:
                          type: string
                        recipient_email:
                          type: string
                        expires_at:
                          type: string
                        activated_at:
                          type: string
                        created_at:
                          type: string
                  per_page:
                    type: integer
                  total:
                    type: integer
                  last_page:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 91
                    code: GC-4821-KDical-0097
                    status: active
                    status_label: Active
                    balance: 42.5
                    currency_id: 1
                    customer_id: 88
                    is_digital: true
                    recipient_name: Ada Lovelace
                    recipient_email: ada@example.com
                    expires_at: '2027-07-06T00:00:00+00:00'
                    activated_at: '2026-07-06T14:30:00+00:00'
                    created_at: '2026-07-06T14:30:00+00:00'
                  per_page: 15
                  total: 1
                  last_page: 1
                  from: 1
                  to: 1
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: get-api-gift-cards
    post:
      tags:
      - Gift Cards
      summary: Issue Gift Card
      description: 'Issue (create + fund) a new gift card. The initial `amount` is
        written as an activation ledger entry and becomes the card''s opening balance.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.

        Permission: `pos.manage`.


        Request body fields:

        - `amount` (numeric, required, > 0) — the amount to fund the card with. Error
        message when not > 0: "The gift card amount must be greater than zero."

        - `code` (string, nullable, max 255, unique in `gift_cards.code`) — explicit
        card code; auto-generated (unique) when omitted. Error message on collision:
        "That gift card code is already in use."

        - `security_code` (string, nullable, max 255) — optional PIN / security code.

        - `is_digital` (boolean, nullable) — whether the card is digital (emailed)
        vs a physical card. Defaults to false.

        - `customer_id` (integer, nullable, must exist in `customers`) — owning customer.

        - `recipient_name` (string, nullable, max 255) — gift recipient''s name.

        - `recipient_email` (email, nullable, max 255) — gift recipient''s email.

        - `expires_at` (date, nullable) — expiry date.

        - `notes` (string, nullable, max 2000) — internal note.


        Returns 201 with `{ data: <gift card>, balance: <float>, message: "Gift card
        issued." }`.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                amount:
                  type: integer
                code:
                  type: string
                security_code:
                  type: string
                is_digital:
                  type: boolean
                customer_id:
                  type: integer
                recipient_name:
                  type: string
                recipient_email:
                  type: string
                expires_at:
                  type: string
                notes:
                  type: string
              example:
                amount: 50
                code: GC-7F3A9C2E4B10
                security_code: '4821'
                is_digital: true
                customer_id: 842
                recipient_name: Alex Rivera
                recipient_email: alex.rivera@example.com
                expires_at: '2027-07-06'
                notes: Birthday gift card issued at register.
      parameters: []
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      code:
                        type: string
                      status:
                        type: string
                      status_label:
                        type: string
                      balance:
                        type: integer
                      currency_id:
                        type: integer
                      customer_id:
                        type: integer
                      is_digital:
                        type: boolean
                      recipient_name:
                        type: string
                      recipient_email:
                        type: string
                      expires_at:
                        type: string
                      activated_at:
                        type: string
                      created_at:
                        type: string
                  balance:
                    type: integer
                  message:
                    type: string
                example:
                  data:
                    id: 15
                    code: GC-7F3A9C2E4B10
                    status: active
                    status_label: Active
                    balance: 50
                    currency_id: 1
                    customer_id: 842
                    is_digital: true
                    recipient_name: Alex Rivera
                    recipient_email: alex.rivera@example.com
                    expires_at: '2027-07-06T00:00:00+00:00'
                    activated_at: '2026-07-06T14:30:00+00:00'
                    created_at: '2026-07-06T14:30:00+00:00'
                  balance: 50
                  message: Gift card issued.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 422 Amount must be greater than zero
                  value:
                    message: The gift card amount must be greater than zero.
                    errors:
                      amount:
                      - The gift card amount must be greater than zero.
                example-1:
                  summary: 422 Duplicate code
                  value:
                    message: That gift card code is already in use.
                    errors:
                      code:
                      - That gift card code is already in use.
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: post-api-gift-cards
  /api/gift-cards/lookup:
    get:
      tags:
      - Gift Cards
      summary: Lookup Gift Card by Code
      description: 'Resolve a gift card by its code (POS entry) and return it alongside
        its current balance. Use this when a customer presents a card at checkout.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.

        Permission: `pos.operate`.


        Query parameters:

        - `code` (string, required, max 255) — the gift card code.


        Returns 200 with `{ data: <gift card>, balance: <float> }`, or 404 `{ message
        }` when no card matches the code.'
      parameters:
      - name: code
        in: query
        schema:
          type: string
        description: Required. The gift card code as entered at the register (string,
          max 255).
        example: GC-7F3A9C2E4B10
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      code:
                        type: string
                      status:
                        type: string
                      status_label:
                        type: string
                      balance:
                        type: integer
                      currency_id:
                        type: integer
                      customer_id:
                        type: integer
                      is_digital:
                        type: boolean
                      recipient_name:
                        type: string
                      recipient_email:
                        type: string
                      expires_at:
                        type: string
                      activated_at:
                        type: string
                      created_at:
                        type: string
                  balance:
                    type: integer
                example:
                  data:
                    id: 15
                    code: GC-7F3A9C2E4B10
                    status: active
                    status_label: Active
                    balance: 50
                    currency_id: 1
                    customer_id: 842
                    is_digital: true
                    recipient_name: Alex Rivera
                    recipient_email: alex.rivera@example.com
                    expires_at: '2027-07-06T00:00:00+00:00'
                    activated_at: '2026-07-06T14:30:00+00:00'
                    created_at: '2026-07-06T14:30:00+00:00'
                  balance: 50
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Gift card not found.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      code:
                        type: array
                        items:
                          type: string
                example:
                  message: The code field is required.
                  errors:
                    code:
                    - The code field is required.
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: get-api-gift-cards-lookup
  /api/gift-cards/{giftCard}:
    get:
      tags:
      - Gift Cards
      summary: Get Gift Card
      description: 'Show a single gift card by id, including its current balance and
        lifecycle status.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.

        Permission: `pos.operate`.


        Status values: `active`, `inactive`, `redeemed`, `expired`, `voided`.


        Returns 200 with `{ data: <gift card> }`.'
      parameters:
      - name: giftCard
        in: path
        schema:
          type: integer
        required: true
        description: The gift card id.
        example: '15'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      code:
                        type: string
                      status:
                        type: string
                      status_label:
                        type: string
                      balance:
                        type: integer
                      currency_id:
                        type: integer
                      customer_id:
                        type: integer
                      is_digital:
                        type: boolean
                      recipient_name:
                        type: string
                      recipient_email:
                        type: string
                      expires_at:
                        type: string
                      activated_at:
                        type: string
                      created_at:
                        type: string
                example:
                  data:
                    id: 15
                    code: GC-7F3A9C2E4B10
                    status: active
                    status_label: Active
                    balance: 50
                    currency_id: 1
                    customer_id: 842
                    is_digital: true
                    recipient_name: Alex Rivera
                    recipient_email: alex.rivera@example.com
                    expires_at: '2027-07-06T00:00:00+00:00'
                    activated_at: '2026-07-06T14:30:00+00:00'
                    created_at: '2026-07-06T14:30:00+00:00'
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No query results for model [App\Models\GiftCard] 999999
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: get-api-gift-cards-giftcard
  /api/gift-cards/{giftCard}/history:
    get:
      tags:
      - Gift Cards
      summary: Get Gift Card History
      description: 'Paginated ledger history for a gift card, newest first. Each entry
        records a value movement (activation, reload, redemption, refund, adjustment,
        or void), the resulting balance, and who created it.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.

        Permission: `pos.operate`.


        Entry `type` values: `activation`, `reload`, `redemption`, `refund`, `adjustment`,
        `void`. `is_credit` is true when the entry adds value.


        Pagination: `per_page` (default 10), `page` (default 1). Response includes
        standard Laravel pagination metadata.'
      parameters:
      - name: giftCard
        in: path
        schema:
          type: integer
        required: true
        description: The gift card id.
        example: '15'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        gift_card_id:
                          type: integer
                        reference:
                          type: string
                        amount:
                          type: integer
                        balance_after:
                          type: integer
                        type:
                          type: string
                        type_label:
                          type: string
                        is_credit:
                          type: boolean
                        currency_id:
                          type: integer
                        notes:
                          type: string
                        source_type:
                          type: string
                          nullable: true
                        source_id:
                          type: string
                          nullable: true
                        created_by_user_id:
                          type: integer
                        created_by_name:
                          type: string
                        created_at:
                          type: string
                  current_page:
                    type: integer
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 88
                    gift_card_id: 15
                    reference: GC-TXN-000088
                    amount: 25
                    balance_after: 75
                    type: reload
                    type_label: Reload
                    is_credit: true
                    currency_id: 1
                    notes: Top-up at register.
                    source_type: null
                    source_id: null
                    created_by_user_id: 7
                    created_by_name: Jane Cashier
                    created_at: '2026-07-06T15:10:00+00:00'
                  - id: 84
                    gift_card_id: 15
                    reference: GC-TXN-000084
                    amount: -20
                    balance_after: 50
                    type: redemption
                    type_label: Redemption
                    is_credit: false
                    currency_id: 1
                    notes: null
                    source_type: App\Models\PosTransaction
                    source_id: 1001
                    created_by_user_id: 7
                    created_by_name: Jane Cashier
                    created_at: '2026-07-06T14:45:00+00:00'
                  - id: 80
                    gift_card_id: 15
                    reference: GC-TXN-000080
                    amount: 50
                    balance_after: 70
                    type: activation
                    type_label: Activation
                    is_credit: true
                    currency_id: 1
                    notes: Birthday gift card issued at register.
                    source_type: null
                    source_id: null
                    created_by_user_id: 7
                    created_by_name: Jane Cashier
                    created_at: '2026-07-06T14:30:00+00:00'
                  current_page: 1
                  first_page_url: '{{protocol}}{{domain}}/api/gift-cards/15/history?page=1'
                  from: 1
                  last_page: 1
                  last_page_url: '{{protocol}}{{domain}}/api/gift-cards/15/history?page=1'
                  next_page_url: null
                  path: '{{protocol}}{{domain}}/api/gift-cards/15/history'
                  per_page: 10
                  prev_page_url: null
                  to: 3
                  total: 3
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-session-only: true
      operationId: get-api-gift-cards-giftcard-history
  /api/gift-cards/{giftCard}/reload:
    post:
      tags:
      - Gift Cards
      summary: Reload Gift Card
      description: 'Add value to an existing gift card. Writes a reload ledger entry
        and returns it with the card''s new balance.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.

        Permission: `pos.manage`.


        Request body fields:

        - `amount` (numeric, required, > 0) — the amount to add. Error message when
        not > 0: "The reload amount must be greater than zero."

        - `notes` (string, nullable, max 2000) — internal note.

        - `reference` (string, nullable, max 255) — external reference for the reload
        (e.g. a receipt or payment reference).


        Returns 201 with `{ data: <ledger entry>, balance: <float>, message: "Gift
        card reloaded." }`.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                amount:
                  type: integer
                notes:
                  type: string
                reference:
                  type: string
              example:
                amount: 25
                notes: Top-up at register.
                reference: POS-RELOAD-1042
      parameters:
      - name: giftCard
        in: path
        schema:
          type: integer
        required: true
        description: The gift card id to add value to.
        example: '15'
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      gift_card_id:
                        type: integer
                      reference:
                        type: string
                      amount:
                        type: integer
                      balance_after:
                        type: integer
                      type:
                        type: string
                      type_label:
                        type: string
                      is_credit:
                        type: boolean
                      currency_id:
                        type: integer
                      notes:
                        type: string
                      source_type:
                        type: string
                        nullable: true
                      source_id:
                        type: string
                        nullable: true
                      created_by_user_id:
                        type: integer
                      created_by_name:
                        type: string
                      created_at:
                        type: string
                  balance:
                    type: integer
                  message:
                    type: string
                example:
                  data:
                    id: 90
                    gift_card_id: 15
                    reference: POS-RELOAD-1042
                    amount: 25
                    balance_after: 75
                    type: reload
                    type_label: Reload
                    is_credit: true
                    currency_id: 1
                    notes: Top-up at register.
                    source_type: null
                    source_id: null
                    created_by_user_id: 7
                    created_by_name: Jane Cashier
                    created_at: '2026-07-06T15:10:00+00:00'
                  balance: 75
                  message: Gift card reloaded.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      amount:
                        type: array
                        items:
                          type: string
                example:
                  message: The reload amount must be greater than zero.
                  errors:
                    amount:
                    - The reload amount must be greater than zero.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-session-only: true
      operationId: post-api-gift-cards-giftcard-reload
  /api/gift-cards/{giftCard}/void:
    post:
      tags:
      - Gift Cards
      summary: Void Gift Card
      description: 'Void a gift card. Drains any remaining balance (via a void ledger
        entry) and marks the card `voided` so it can no longer be redeemed. No request
        body.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.

        Permission: `pos.manage`.


        Returns 200 with `{ data: <gift card>, message: "Gift card voided." }`.'
      requestBody:
        content: {}
      parameters:
      - name: giftCard
        in: path
        schema:
          type: integer
        required: true
        description: The gift card id to void.
        example: '15'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      code:
                        type: string
                      status:
                        type: string
                      status_label:
                        type: string
                      balance:
                        type: integer
                      currency_id:
                        type: integer
                      customer_id:
                        type: integer
                      is_digital:
                        type: boolean
                      recipient_name:
                        type: string
                      recipient_email:
                        type: string
                      expires_at:
                        type: string
                      activated_at:
                        type: string
                      created_at:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 15
                    code: GC-7F3A9C2E4B10
                    status: voided
                    status_label: Voided
                    balance: 0
                    currency_id: 1
                    customer_id: 842
                    is_digital: true
                    recipient_name: Alex Rivera
                    recipient_email: alex.rivera@example.com
                    expires_at: '2027-07-06T00:00:00+00:00'
                    activated_at: '2026-07-06T14:30:00+00:00'
                    created_at: '2026-07-06T14:30:00+00:00'
                  message: Gift card voided.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-session-only: true
      operationId: post-api-gift-cards-giftcard-void
  /api/customers/{customer}/house-account:
    get:
      tags:
      - House Accounts
      summary: Get House Account Balance
      description: 'Return the customer''s house-account balance owed, credit limit,
        and remaining headroom.


        :::info[Required scope: `customers:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token (PAT).


        Response fields (under `data`):

        - `customer_id` (integer) — the customer.

        - `house_account_enabled` (boolean) — whether on-account charging is enabled
        for this customer.

        - `balance` (float) — the current balance owed on the account.

        - `credit_limit` (float | null) — the customer''s credit limit, or null when
        uncapped.

        - `available_credit` (float | null) — remaining headroom (credit_limit − balance),
        or null when there is no limit.


        Returns 200 with `{ data: { ... } }`.'
      parameters:
      - name: customer
        in: path
        schema:
          type: integer
        required: true
        description: The customer id (path parameter for every house-account endpoint).
        example: '842'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      customer_id:
                        type: integer
                      house_account_enabled:
                        type: boolean
                      balance:
                        type: integer
                      credit_limit:
                        type: integer
                      available_credit:
                        type: integer
                example:
                  data:
                    customer_id: 842
                    house_account_enabled: true
                    balance: 250
                    credit_limit: 1000
                    available_credit: 750
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: customers:read
      operationId: get-api-customers-customer-house-account
  /api/customers/{customer}/house-account/history:
    get:
      tags:
      - House Accounts
      summary: Get House Account History
      description: 'Paginated house-account ledger history for the customer, newest
        first. Each entry records a value movement (charge, payment, adjustment, or
        write-off), the resulting balance, and who created it.


        :::info[Required scope: `customers:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token (PAT).


        Entry `type` values: `charge`, `payment`, `adjustment`, `write_off`. `is_charge`
        is true when the entry''s amount is positive (increases the balance owed).
        `reference` falls back to an `HA-000123`-style identifier when no explicit
        reference was recorded.


        Pagination: `per_page` (default 10), `page` (default 1). Response includes
        standard Laravel pagination metadata.'
      parameters:
      - name: customer
        in: path
        schema:
          type: integer
        required: true
        description: The customer id (path parameter for every house-account endpoint).
        example: '842'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        customer_id:
                          type: integer
                        reference:
                          type: string
                        amount:
                          type: integer
                        balance_after:
                          type: integer
                        type:
                          type: string
                        type_label:
                          type: string
                        is_charge:
                          type: boolean
                        currency_id:
                          type: integer
                        notes:
                          type: string
                        source_type:
                          type: string
                          nullable: true
                        source_id:
                          type: string
                          nullable: true
                        created_by_user_id:
                          type: integer
                        created_by_name:
                          type: string
                        created_at:
                          type: string
                  current_page:
                    type: integer
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 88
                    customer_id: 842
                    reference: CHK-4021
                    amount: -100
                    balance_after: 250
                    type: payment
                    type_label: Payment
                    is_charge: false
                    currency_id: 1
                    notes: 'Check #4021 applied.'
                    source_type: null
                    source_id: null
                    created_by_user_id: 7
                    created_by_name: Jane Cashier
                    created_at: '2026-07-06T15:10:00+00:00'
                  - id: 84
                    customer_id: 842
                    reference: HA-000084
                    amount: 250
                    balance_after: 350
                    type: charge
                    type_label: Charge
                    is_charge: true
                    currency_id: 1
                    notes: null
                    source_type: App\Models\PosTransaction
                    source_id: 1001
                    created_by_user_id: 7
                    created_by_name: Jane Cashier
                    created_at: '2026-07-06T14:45:00+00:00'
                  - id: 80
                    customer_id: 842
                    reference: HA-000080
                    amount: -25
                    balance_after: 100
                    type: adjustment
                    type_label: Adjustment
                    is_charge: false
                    currency_id: 1
                    notes: Goodwill credit.
                    source_type: null
                    source_id: null
                    created_by_user_id: 7
                    created_by_name: Jane Cashier
                    created_at: '2026-07-06T14:30:00+00:00'
                  current_page: 1
                  first_page_url: '{{protocol}}{{domain}}/api/customers/842/house-account/history?page=1'
                  from: 1
                  last_page: 1
                  last_page_url: '{{protocol}}{{domain}}/api/customers/842/house-account/history?page=1'
                  next_page_url: null
                  path: '{{protocol}}{{domain}}/api/customers/842/house-account/history'
                  per_page: 10
                  prev_page_url: null
                  to: 3
                  total: 3
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: customers:read
      operationId: get-api-customers-customer-house-account-history
  /api/customers/{customer}/house-account/charge:
    post:
      tags:
      - House Accounts
      summary: Charge House Account
      description: 'Manually charge an amount to the customer''s house account, increasing
        the balance owed. Writes a `charge` ledger entry and returns it with the account''s
        new balance.


        :::info[Required scope: `customers:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token (PAT).

        Permission: `customers.update`.


        Request body fields:

        - `amount` (numeric, required, > 0) — the amount to charge. Error message
        when not > 0: "The charge amount must be greater than zero."

        - `notes` (string, nullable, max 2000) — internal note.

        - `reference` (string, nullable, max 255) — external reference (e.g. a PO
        or receipt number).


        The charge is rejected with 422 when the customer has no house account enabled,
        or when it would push the balance owed past the customer''s credit limit.


        Returns 201 with `{ data: <ledger entry>, balance: <float>, message: "Charge
        recorded." }`.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                amount:
                  type: integer
                notes:
                  type: string
                reference:
                  type: string
              example:
                amount: 150
                notes: On-account purchase at the register.
                reference: PO-4821
      parameters:
      - name: customer
        in: path
        schema:
          type: integer
        required: true
        description: The customer id (path parameter for every house-account endpoint).
        example: '842'
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      customer_id:
                        type: integer
                      reference:
                        type: string
                      amount:
                        type: integer
                      balance_after:
                        type: integer
                      type:
                        type: string
                      type_label:
                        type: string
                      is_charge:
                        type: boolean
                      currency_id:
                        type: integer
                      notes:
                        type: string
                      source_type:
                        type: string
                        nullable: true
                      source_id:
                        type: string
                        nullable: true
                      created_by_user_id:
                        type: integer
                      created_by_name:
                        type: string
                      created_at:
                        type: string
                  balance:
                    type: integer
                  message:
                    type: string
                example:
                  data:
                    id: 90
                    customer_id: 842
                    reference: PO-4821
                    amount: 150
                    balance_after: 400
                    type: charge
                    type_label: Charge
                    is_charge: true
                    currency_id: 1
                    notes: On-account purchase at the register.
                    source_type: null
                    source_id: null
                    created_by_user_id: 7
                    created_by_name: Jane Cashier
                    created_at: '2026-07-06T15:30:00+00:00'
                  balance: 400
                  message: Charge recorded.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      amount:
                        type: array
                        items:
                          type: string
                example:
                  message: Charging 250.00 would exceed the 100.00 credit limit (balance
                    owed 0.00).
                  errors:
                    amount:
                    - Charging 250.00 would exceed the 100.00 credit limit (balance
                      owed 0.00).
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: customers:write
      operationId: post-api-customers-customer-house-account-charge
  /api/customers/{customer}/house-account/pay:
    post:
      tags:
      - House Accounts
      summary: Record House Account Payment
      description: 'Record a payment against the customer''s house account, reducing
        the balance owed. Writes a `payment` ledger entry and returns it with the
        account''s new balance.


        :::info[Required scope: `customers:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token (PAT).

        Permission: `customers.update`.


        Request body fields:

        - `amount` (numeric, required, > 0) — the payment amount. Error message when
        not > 0: "The payment amount must be greater than zero."

        - `notes` (string, nullable, max 2000) — internal note.

        - `reference` (string, nullable, max 255) — external reference (e.g. a cheque
        or payment reference).


        Returns 201 with `{ data: <ledger entry>, balance: <float>, message: "Payment
        recorded." }`.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                amount:
                  type: integer
                notes:
                  type: string
                reference:
                  type: string
              example:
                amount: 100
                notes: 'Check #4021.'
                reference: CHK-4021
      parameters:
      - name: customer
        in: path
        schema:
          type: integer
        required: true
        description: The customer id (path parameter for every house-account endpoint).
        example: '842'
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      customer_id:
                        type: integer
                      reference:
                        type: string
                      amount:
                        type: integer
                      balance_after:
                        type: integer
                      type:
                        type: string
                      type_label:
                        type: string
                      is_charge:
                        type: boolean
                      currency_id:
                        type: integer
                      notes:
                        type: string
                      source_type:
                        type: string
                        nullable: true
                      source_id:
                        type: string
                        nullable: true
                      created_by_user_id:
                        type: integer
                      created_by_name:
                        type: string
                      created_at:
                        type: string
                  balance:
                    type: integer
                  message:
                    type: string
                example:
                  data:
                    id: 91
                    customer_id: 842
                    reference: CHK-4021
                    amount: -100
                    balance_after: 300
                    type: payment
                    type_label: Payment
                    is_charge: false
                    currency_id: 1
                    notes: 'Check #4021.'
                    source_type: null
                    source_id: null
                    created_by_user_id: 7
                    created_by_name: Jane Cashier
                    created_at: '2026-07-06T15:40:00+00:00'
                  balance: 300
                  message: Payment recorded.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: customers:write
      operationId: post-api-customers-customer-house-account-pay
  /api/customers/{customer}/house-account/adjust:
    post:
      tags:
      - House Accounts
      summary: Adjust House Account
      description: 'Manually adjust or write off the customer''s house-account balance.
        Writes an `adjustment` or `write_off` ledger entry and returns it with the
        account''s new balance.


        :::info[Required scope: `customers:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token (PAT).

        Permission: `customers.update`.


        Request body fields:

        - `amount` (numeric, required, non-zero) — signed for an adjustment (+ increases
        the balance owed, − decreases it); magnitude for a write-off (always reduces
        the balance). Error message when 0: "The adjustment amount must be non-zero."

        - `type` (string, nullable, one of `adjustment`, `write_off`) — defaults to
        `adjustment` when omitted. Error message on invalid value: "The type must
        be an adjustment or a write-off."

        - `notes` (string, nullable, max 2000) — internal note.


        Returns 201 with `{ data: <ledger entry>, balance: <float>, message: "House
        account adjusted." }`.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                amount:
                  type: integer
                type:
                  type: string
                notes:
                  type: string
              example:
                amount: -50
                type: write_off
                notes: Bad-debt write-off approved by finance.
      parameters:
      - name: customer
        in: path
        schema:
          type: integer
        required: true
        description: The customer id (path parameter for every house-account endpoint).
        example: '842'
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      customer_id:
                        type: integer
                      reference:
                        type: string
                      amount:
                        type: integer
                      balance_after:
                        type: integer
                      type:
                        type: string
                      type_label:
                        type: string
                      is_charge:
                        type: boolean
                      currency_id:
                        type: integer
                      notes:
                        type: string
                      source_type:
                        type: string
                        nullable: true
                      source_id:
                        type: string
                        nullable: true
                      created_by_user_id:
                        type: integer
                      created_by_name:
                        type: string
                      created_at:
                        type: string
                  balance:
                    type: integer
                  message:
                    type: string
                example:
                  data:
                    id: 92
                    customer_id: 842
                    reference: HA-000092
                    amount: -50
                    balance_after: 250
                    type: write_off
                    type_label: Write-off
                    is_charge: false
                    currency_id: 1
                    notes: Bad-debt write-off approved by finance.
                    source_type: null
                    source_id: null
                    created_by_user_id: 7
                    created_by_name: Jane Cashier
                    created_at: '2026-07-06T15:50:00+00:00'
                  balance: 250
                  message: House account adjusted.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      amount:
                        type: array
                        items:
                          type: string
                example:
                  message: The adjustment amount must be non-zero.
                  errors:
                    amount:
                    - The adjustment amount must be non-zero.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: customers:write
      operationId: post-api-customers-customer-house-account-adjust
  /api/reporting/inventory-planning:
    get:
      tags:
      - Reporting
      summary: Get Inventory Planning Report
      description: 'Returns a paginated inventory planning report with replenishment
        data per product. Supports warehouse filtering via filter[warehouse_id], filter[warehouse_id][is],
        or base64-encoded filter_groups tree.


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token


        Pagination: Default per page from request or manager default


        The response also includes `unfiltered_total`, the count of rows in the base
        scope before any user filters are applied — used by the frontend to show export
        totals.'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        description: Page number
        example: '1'
      - name: per_page
        in: query
        schema:
          type: integer
        description: Items per page
        example: '25'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        sku:
                          type: string
                        name:
                          type: string
                        barcode:
                          type: string
                        type:
                          type: string
                        brand:
                          type: string
                        brand_id:
                          type: integer
                        available_qty:
                          type: number
                        available_to_sell:
                          type: number
                        total_stock_qty:
                          type: number
                        reserved_qty:
                          type: number
                        in_transit_qty:
                          type: number
                        inbound_qty:
                          type: number
                        projected_total:
                          type: number
                        active_backorder_qty:
                          type: number
                        net_available:
                          type: number
                        supplier_name:
                          type: string
                        supplier_id:
                          type: integer
                        supplier_sku:
                          type: string
                        supplier_price:
                          type: number
                        supplier_currency_code:
                          type: string
                        average_cost:
                          type: number
                        stock_value:
                          type: number
                        estimated_landed_cost:
                          type: number
                        gross_margin_pct:
                          type: number
                        length:
                          type: number
                        width:
                          type: number
                        height:
                          type: number
                        dimension_unit:
                          type: string
                        weight:
                          type: number
                        weight_unit:
                          type: string
                        cbm:
                          type: number
                        volume:
                          type: number
                        volume_unit:
                          type: string
                        qty_sold_30d:
                          type: integer
                        qty_sold_60d:
                          type: integer
                        qty_sold_90d:
                          type: integer
                        qty_sold_180d:
                          type: integer
                        monthly_avg_sales:
                          type: number
                        daily_avg_sales:
                          type: number
                        revenue_180d:
                          type: number
                        demand_trend_pct:
                          type: number
                        demand_trend_direction:
                          type: string
                        demand_trend_confidence:
                          type: string
                        days_of_stock:
                          type: number
                        days_until_stockout:
                          type: number
                        stockout_risk:
                          type: string
                        stockout_risk_color:
                          type: string
                        abc_classification:
                          type: string
                        xyz_classification:
                          type: string
                        abc_xyz_cell:
                          type: string
                        sell_through_rate:
                          type: number
                        inventory_turnover:
                          type: number
                        revenue_at_risk:
                          type: number
                        overstock_qty:
                          type: number
                        overstock_value:
                          type: number
                        is_dead_stock:
                          type: boolean
                        dead_stock_value:
                          type: string
                          nullable: true
                        lead_time:
                          type: integer
                        avg_actual_lead_time:
                          type: number
                        lead_time_reliability_pct:
                          type: number
                        lead_time_variance:
                          type: number
                        min_order_qty:
                          type: number
                        target_stock_days:
                          type: integer
                        min_stock_level:
                          type: number
                        reorder_point:
                          type: number
                        suggested_reorder_qty:
                          type: number
                        case_quantity:
                          type: number
                        suggested_cases:
                          type: integer
                        adjusted_reorder_qty:
                          type: number
                        reorder_cbm:
                          type: number
                        reorder_cost:
                          type: number
                        reorder_landed_cost:
                          type: number
                        next_po_date:
                          type: string
                        next_po_qty:
                          type: number
                        days_until_relief:
                          type: integer
                        velocity_computed_at:
                          type: string
                  per_page:
                    type: integer
                  total:
                    type: integer
                  unfiltered_total:
                    type: integer
                  last_page:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 42
                    sku: WIDGET-001
                    name: Blue Widget
                    barcode: '1234567890'
                    type: standard
                    brand: Acme
                    brand_id: 5
                    available_qty: 150.0
                    available_to_sell: 150.0
                    total_stock_qty: 180.0
                    reserved_qty: 20.0
                    in_transit_qty: 10.0
                    inbound_qty: 50.0
                    projected_total: 200.0
                    active_backorder_qty: 0.0
                    net_available: 150.0
                    supplier_name: Widget Co
                    supplier_id: 10
                    supplier_sku: WC-WIDGET-001
                    supplier_price: 8.5
                    supplier_currency_code: USD
                    average_cost: 9.25
                    stock_value: 1665.0
                    estimated_landed_cost: 10.2
                    gross_margin_pct: 0.42
                    length: 10.0
                    width: 5.0
                    height: 3.0
                    dimension_unit: cm
                    weight: 0.5
                    weight_unit: kg
                    cbm: 0.00015
                    volume: 0.00015
                    volume_unit: CBM
                    qty_sold_30d: 45
                    qty_sold_60d: 90
                    qty_sold_90d: 135
                    qty_sold_180d: 270
                    monthly_avg_sales: 45.0
                    daily_avg_sales: 1.5
                    revenue_180d: 4050.0
                    demand_trend_pct: 12.5
                    demand_trend_direction: stable
                    demand_trend_confidence: high
                    days_of_stock: 100.0
                    days_until_stockout: 133.3
                    stockout_risk: low
                    stockout_risk_color: success
                    abc_classification: A
                    xyz_classification: X
                    abc_xyz_cell: AX
                    sell_through_rate: 0.643
                    inventory_turnover: 3.0
                    revenue_at_risk: 0.0
                    overstock_qty: 0.0
                    overstock_value: 0.0
                    is_dead_stock: false
                    dead_stock_value: null
                    lead_time: 30
                    avg_actual_lead_time: 28.5
                    lead_time_reliability_pct: 0.92
                    lead_time_variance: 3.2
                    min_order_qty: 50.0
                    target_stock_days: 60
                    min_stock_level: 20.0
                    reorder_point: 65.0
                    suggested_reorder_qty: 50.0
                    case_quantity: 12.0
                    suggested_cases: 5
                    adjusted_reorder_qty: 60.0
                    reorder_cbm: 0.009
                    reorder_cost: 510.0
                    reorder_landed_cost: 612.0
                    next_po_date: '2024-07-15'
                    next_po_qty: 100.0
                    days_until_relief: 21
                    velocity_computed_at: '2024-06-14T08:00:00.000000Z'
                  per_page: 25
                  total: 342
                  unfiltered_total: 2103
                  last_page: 14
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:read
      operationId: get-api-reporting-inventory-planning
  /api/reporting/inventory-planning/summary:
    get:
      tags:
      - Reporting
      summary: Get Inventory Planning Summary
      description: 'Returns summary metrics for the inventory planning report header
        cards (counts of items at risk, overstocked, out of stock, etc.).


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      total_products:
                        type: integer
                      high_risk:
                        type: integer
                      medium_risk:
                        type: integer
                      low_risk:
                        type: integer
                      out_of_stock:
                        type: integer
                      dead_stock:
                        type: integer
                      total_stock_value:
                        type: number
                      total_reorder_cost:
                        type: number
                example:
                  data:
                    total_products: 342
                    high_risk: 12
                    medium_risk: 28
                    low_risk: 302
                    out_of_stock: 5
                    dead_stock: 8
                    total_stock_value: 125400.0
                    total_reorder_cost: 38200.0
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:read
      operationId: get-api-reporting-inventory-planning-summary
  /api/reporting/inventory-planning/export:
    get:
      tags:
      - Reporting
      summary: Export Inventory Planning Report
      description: 'Exports the inventory planning report as CSV or XLSX. Supports
        column selection and warehouse filtering.


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token


        Response: text/csv or application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
        file download'
      parameters:
      - name: format
        in: query
        schema:
          type: string
        description: csv (default) | xlsx
        example: csv
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:read
      operationId: get-api-reporting-inventory-planning-export
  /api/reporting/inventory-planning/refresh-velocity:
    post:
      tags:
      - Reporting
      summary: Refresh Velocity Data
      description: 'Dispatches a tracked background job to recompute product velocity
        cache and supplier lead time reliability. Returns a tracked_job_log_id for
        monitoring via the tracked job log endpoints.


        :::info[Required scope: `reports:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token'
      requestBody:
        content: {}
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 87
                  message: Velocity cache refresh started. Track progress in the job
                    tray.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: reports:write
      operationId: post-api-reporting-inventory-planning-refresh-velocity
  /api/reporting/inventory-planning/refresh-financials:
    post:
      tags:
      - Reporting
      summary: Refresh Sales Financials
      description: 'Dispatches a tracked background job to refresh sales financials
        data used by the inventory planning report. Returns a tracked_job_log_id for
        monitoring via the tracked job log endpoints.


        :::info[Required scope: `reports:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token'
      requestBody:
        content: {}
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 88
                  message: Sales financials refresh started. Track progress in the
                    job tray.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: reports:write
      operationId: post-api-reporting-inventory-planning-refresh-financials
  /api/reporting/inventory-planning/create-po:
    post:
      tags:
      - Reporting
      summary: Create Draft PO from Planning
      description: 'Creates a draft purchase order from reorder suggestions in the
        inventory planning report.


        :::info[Required scope: `reports:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token


        Required fields:

        - supplier_id: integer (must exist)

        - product_ids: array of integers (min 1, must exist)


        Optional fields:

        - quantities: object keyed by product_id with integer values (min 1)

        - use_adjusted_qty: boolean (default: true) — use the adjusted reorder qty

        - order_status: ''draft'' | ''open'' (default: ''draft'')

        - destination_warehouse_id: integer (must exist)'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                supplier_id:
                  type: integer
                product_ids:
                  type: array
                  items:
                    type: integer
                use_adjusted_qty:
                  type: boolean
                order_status:
                  type: string
                destination_warehouse_id:
                  type: integer
                quantities:
                  type: object
                  properties:
                    '42':
                      type: integer
                    '43':
                      type: integer
              example:
                supplier_id: 10
                product_ids:
                - 42
                - 43
                - 44
                use_adjusted_qty: true
                order_status: draft
                destination_warehouse_id: 1
                quantities:
                  '42': 100
                  '43': 50
      parameters: []
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      purchase_order_id:
                        type: integer
                      purchase_order_number:
                        type: string
                      line_count:
                        type: integer
                      total_cost:
                        type: number
                      order_status:
                        type: string
                      destination_warehouse:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    purchase_order_id: 350
                    purchase_order_number: PO-350
                    line_count: 3
                    total_cost: 2550.0
                    order_status: draft
                    destination_warehouse: Main Warehouse
                  message: Purchase order created
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No products selected for reorder
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:write
      operationId: post-api-reporting-inventory-planning-create-po
  /api/reporting/inventory-planning/schedules:
    get:
      tags:
      - Reporting
      summary: List Scheduled Reports
      description: 'Returns all scheduled reports for the authenticated user for the
        inventory_planning report type.


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        report_type:
                          type: string
                        frequency:
                          type: string
                        day_of_week:
                          type: integer
                        day_of_month:
                          type: string
                          nullable: true
                        time:
                          type: string
                        timezone:
                          type: string
                        format:
                          type: string
                        recipients:
                          type: array
                          items:
                            type: string
                        filters:
                          type: object
                          properties:
                            warehouse_id:
                              type: integer
                        columns:
                          type: array
                          items:
                            type: string
                        is_active:
                          type: boolean
                        last_sent_at:
                          type: string
                        next_run_at:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                example:
                  data:
                  - id: 1
                    name: Weekly Inventory Report
                    report_type: inventory_planning
                    frequency: weekly
                    day_of_week: 1
                    day_of_month: null
                    time: 08:00
                    timezone: America/New_York
                    format: xlsx
                    recipients:
                    - manager@example.com
                    filters:
                      warehouse_id: 1
                    columns:
                    - sku
                    - name
                    - available_qty
                    - suggested_reorder_qty
                    is_active: true
                    last_sent_at: '2024-06-10T08:00:00+00:00'
                    next_run_at: '2024-06-17T08:00:00+00:00'
                    created_at: '2024-01-15T10:00:00+00:00'
                    updated_at: '2024-06-10T08:00:00+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:read
      operationId: get-api-reporting-inventory-planning-schedules
    post:
      tags:
      - Reporting
      summary: Create Scheduled Report
      description: 'Creates a new scheduled inventory planning report for the authenticated
        user.


        :::info[Required scope: `reports:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token


        Required fields:

        - name: string (max 255)

        - frequency: daily | weekly | monthly

        - time: HH:MM (24h format)

        - timezone: valid timezone string

        - format: csv | xlsx

        - recipients: array of emails (min 1)


        Conditional required:

        - day_of_week: integer 0-6 (required when frequency=weekly)

        - day_of_month: integer 1-28 (required when frequency=monthly)


        Optional:

        - filters: object of filter values

        - columns: array of column names'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                frequency:
                  type: string
                day_of_week:
                  type: integer
                time:
                  type: string
                timezone:
                  type: string
                format:
                  type: string
                recipients:
                  type: array
                  items:
                    type: string
                filters:
                  type: object
                  properties:
                    warehouse_id:
                      type: integer
                columns:
                  type: array
                  items:
                    type: string
              example:
                name: Weekly Inventory Report
                frequency: weekly
                day_of_week: 1
                time: 08:00
                timezone: America/New_York
                format: xlsx
                recipients:
                - manager@example.com
                - buyer@example.com
                filters:
                  warehouse_id: 1
                columns:
                - sku
                - name
                - available_qty
                - suggested_reorder_qty
      parameters: []
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      report_type:
                        type: string
                      frequency:
                        type: string
                      day_of_week:
                        type: integer
                      time:
                        type: string
                      timezone:
                        type: string
                      format:
                        type: string
                      recipients:
                        type: array
                        items:
                          type: string
                      is_active:
                        type: boolean
                      created_at:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 2
                    name: Weekly Inventory Report
                    report_type: inventory_planning
                    frequency: weekly
                    day_of_week: 1
                    time: 08:00
                    timezone: America/New_York
                    format: xlsx
                    recipients:
                    - manager@example.com
                    is_active: true
                    created_at: '2024-06-15T10:00:00+00:00'
                  message: Scheduled report created
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: reports:write
      operationId: post-api-reporting-inventory-planning-schedules
  /api/reporting/inventory-planning/schedules/{scheduledReport}:
    delete:
      tags:
      - Reporting
      summary: Delete Scheduled Report
      description: 'Deletes a scheduled report. Only the owner can delete their own
        scheduled reports.


        :::info[Required scope: `reports:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token'
      parameters:
      - name: scheduledReport
        in: path
        schema:
          type: integer
        required: true
        description: Scheduled Report ID
        example: '1'
      responses:
        '204':
          description: No Content
          content:
            text/plain:
              schema:
                type: string
                example: ''
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: reports:write
      operationId: delete-api-reporting-inventory-planning-schedules-scheduledreport
  /api/reporting/profitability/trend:
    get:
      tags:
      - Reporting
      summary: Get Profitability Trend
      description: 'Returns trend data (per-interval metrics) grouped by a dimension.
        When indirect costs are included (default), per-interval total cost and profit
        reflect cost-entry allocations; period allocations are day-prorated across
        intervals. Margin-ladder metrics are available: gross_profit / gross_margin
        (revenue minus COGS), contribution_margin / contribution_margin_pct (after
        channel and indirect costs), plus ad_spend and tacos for sku, brand, and supplier
        groupings.


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Rows may include {interval}_indirect_cost keys and a ''Non-Product / Unallocated''
        row (is_unallocated: true) for amounts that cannot be attributed to the chosen
        grouping.


        Authentication: Requires Bearer token'
      parameters:
      - name: group_by
        in: query
        schema:
          type: string
        description: 'Required. Dimension: brand | sku | supplier | sales_channel
          | product_type | sub_sales_channel | customer_tags. customer_tags fans out
          — an order counts toward each of its customer''s tags — and the grand total
          is deduplicated. customer_tags does not require attribute_id.'
        example: brand
      - name: interval
        in: query
        schema:
          type: string
        description: 'Required. Time interval: day | week | month | quarter | year'
        example: month
      - name: limit
        in: query
        schema:
          type: integer
        description: Optional. Number of periods to return
        example: '12'
      - name: sort
        in: query
        schema:
          type: string
        description: 'Optional. Sort order: asc | desc'
        example: desc
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        period:
                          type: string
                        dimension_value:
                          type: string
                        revenue:
                          type: number
                        cogs:
                          type: number
                        total_cost:
                          type: number
                        profit:
                          type: number
                        quantity:
                          type: integer
                        num_orders:
                          type: integer
                        margin:
                          type: number
                example:
                  data:
                  - period: 2024-06
                    dimension_value: Acme Brand
                    revenue: 15200.0
                    cogs: 8500.0
                    total_cost: 9200.0
                    profit: 6000.0
                    quantity: 320
                    num_orders: 45
                    margin: 39.47
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:read
      operationId: get-api-reporting-profitability-trend
  /api/reporting/profitability/cost-breakdown:
    get:
      tags:
      - Reporting
      summary: Get Profitability Cost Breakdown
      description: 'Returns cost breakdown rows per dimension with financial line
        type columns, indirect costs (cost-entry allocations), and the margin ladder:
        gross_profit / gross_margin, contribution_margin / contribution_margin_pct,
        and company-level operating_profit (contribution margin minus unallocated
        indirect costs).


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Indirect costs attribute direct dimension-target allocations plus product-target
        allocations rolled up to the grouping; unattributable amounts appear on the
        ''Non-Product / Unallocated'' row so grand totals cover all allocations in
        range. For sku, brand, and supplier groupings, rows also carry ad_spend, acos,
        and tacos (a breakout of indirect costs — already included in the totals,
        never added twice).


        Authentication: Requires Bearer token'
      parameters:
      - name: group_by
        in: query
        schema:
          type: string
        description: 'Required. Dimension: brand | sku | supplier | sales_channel
          | product_type | sub_sales_channel | customer_tags. customer_tags fans out
          — an order counts toward each of its customer''s tags — and the grand total
          is deduplicated. customer_tags does not require attribute_id.'
        example: brand
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      dimensions:
                        type: array
                        items:
                          type: object
                          properties:
                            rowLabel:
                              type: string
                            revenue:
                              type: number
                            cogs:
                              type: number
                            cost_allocated:
                              type: number
                            indirect_cost:
                              type: number
                            indirect_cost_by_type:
                              type: object
                              properties:
                                '2':
                                  type: number
                                '5':
                                  type: number
                            total_cost:
                              type: number
                            profit:
                              type: number
                            margin:
                              type: number
                            gross_profit:
                              type: number
                            gross_margin:
                              type: number
                            contribution_margin:
                              type: number
                            contribution_margin_pct:
                              type: number
                            flt_values:
                              type: object
                              properties:
                                '1':
                                  type: number
                            is_unallocated:
                              type: boolean
                      financial_line_types:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            classification:
                              type: string
                            total:
                              type: number
                      indirect_cost_types:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            total:
                              type: number
                      grand_totals:
                        type: object
                        properties:
                          revenue:
                            type: number
                          cogs:
                            type: number
                          total_cost:
                            type: number
                          profit:
                            type: number
                          margin:
                            type: number
                          gross_profit:
                            type: number
                          gross_margin:
                            type: number
                          indirect_cost:
                            type: number
                          contribution_margin:
                            type: number
                          contribution_margin_pct:
                            type: number
                          unallocated_indirect_cost:
                            type: number
                          operating_profit:
                            type: number
                      comparison:
                        type: object
                        properties:
                          mode:
                            type: string
                          window:
                            type: object
                            properties:
                              start_date:
                                type: string
                              end_date:
                                type: string
                          revenue:
                            type: number
                          cogs:
                            type: number
                          total_cost:
                            type: number
                          profit:
                            type: number
                          margin:
                            type: number
                          gross_profit:
                            type: number
                          gross_margin:
                            type: number
                          indirect_cost:
                            type: number
                          contribution_margin:
                            type: number
                          contribution_margin_pct:
                            type: number
                          unallocated_indirect_cost:
                            type: number
                          operating_profit:
                            type: number
                          ad_spend:
                            type: number
                example:
                  data:
                    dimensions:
                    - rowLabel: Acme Brand
                      revenue: 45000.0
                      cogs: 25000.0
                      cost_allocated: 3200.0
                      indirect_cost: 1800.0
                      indirect_cost_by_type:
                        '2': 1200.0
                        '5': 600.0
                      total_cost: 30000.0
                      profit: 15000.0
                      margin: 33.33
                      gross_profit: 20000.0
                      gross_margin: 44.44
                      contribution_margin: 15000.0
                      contribution_margin_pct: 33.33
                      flt_values:
                        '1': 3200.0
                      is_unallocated: false
                    - rowLabel: Non-Product / Unallocated
                      revenue: 0.0
                      cogs: 0.0
                      cost_allocated: 0.0
                      indirect_cost: 500.0
                      indirect_cost_by_type:
                        '2': 500.0
                      total_cost: 500.0
                      profit: -500.0
                      margin: null
                      gross_profit: 0.0
                      gross_margin: null
                      contribution_margin: -500.0
                      contribution_margin_pct: null
                      flt_values: {}
                      is_unallocated: true
                    financial_line_types:
                    - id: 1
                      name: Shipping
                      classification: COST
                      total: 3200.0
                    indirect_cost_types:
                    - id: 2
                      name: Marketing
                      total: 1700.0
                    - id: 5
                      name: Software
                      total: 600.0
                    grand_totals:
                      revenue: 45000.0
                      cogs: 25000.0
                      total_cost: 30500.0
                      profit: 14500.0
                      margin: 32.22
                      gross_profit: 20000.0
                      gross_margin: 44.44
                      indirect_cost: 2300.0
                      contribution_margin: 14500.0
                      contribution_margin_pct: 32.22
                      unallocated_indirect_cost: 750.0
                      operating_profit: 13750.0
                    comparison:
                      mode: previous_period
                      window:
                        start_date: '2026-05-01'
                        end_date: '2026-05-31'
                      revenue: 41000.0
                      cogs: 23500.0
                      total_cost: 28100.0
                      profit: 12900.0
                      margin: 31.46
                      gross_profit: 17500.0
                      gross_margin: 42.68
                      indirect_cost: 2100.0
                      contribution_margin: 12900.0
                      contribution_margin_pct: 31.46
                      unallocated_indirect_cost: 600.0
                      operating_profit: 12300.0
                      ad_spend: 900.0
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:read
      operationId: get-api-reporting-profitability-cost-breakdown
  /api/reporting/profitability/drilldown:
    get:
      tags:
      - Reporting
      summary: Get Profitability Drilldown
      description: 'Returns paginated order-level drilldown for a specific dimension
        value, showing revenue, COGS, total cost, profit, and margin per order. Includes
        financial line type column values when flt_ids[] is provided.


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token'
      parameters:
      - name: dimension
        in: query
        schema:
          type: string
        description: 'Dimension: brand | sku | supplier | sales_channel | product_type
          | sub_sales_channel | customer_tags (nullable). customer_tags fans out —
          an order counts toward each of its customer''s tags — and the grand total
          is deduplicated. customer_tags does not require attribute_id.'
        example: brand
      - name: dimension_value
        in: query
        schema:
          type: string
        description: Value of the dimension to filter by (nullable)
        example: Acme
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        sales_order_number:
                          type: string
                        order_date:
                          type: string
                        sales_channel:
                          type: string
                        product_revenue:
                          type: number
                        revenue:
                          type: number
                        cogs:
                          type: number
                        total_cost:
                          type: number
                        profit:
                          type: number
                        margin:
                          type: number
                        flt_values:
                          type: object
                          properties:
                            '1':
                              type: number
                            '2':
                              type: number
                  per_page:
                    type: integer
                  total:
                    type: integer
                  last_page:
                    type: integer
                  totals:
                    type: object
                    properties:
                      revenue:
                        type: number
                      cogs:
                        type: number
                      total_cost:
                        type: number
                      profit:
                        type: number
                      margin:
                        type: number
                  flt_headers:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                example:
                  current_page: 1
                  data:
                  - id: 1001
                    sales_order_number: SO-1001
                    order_date: '2024-06-10'
                    sales_channel: Shopify
                    product_revenue: 150.0
                    revenue: 162.0
                    cogs: 80.0
                    total_cost: 95.0
                    profit: 67.0
                    margin: 41.36
                    flt_values:
                      '1': 12.0
                      '2': 3.0
                  per_page: 25
                  total: 145
                  last_page: 6
                  totals:
                    revenue: 23490.0
                    cogs: 11500.0
                    total_cost: 13775.0
                    profit: 9715.0
                    margin: 41.36
                  flt_headers:
                  - id: 1
                    name: Shipping
                  - id: 2
                    name: Fulfilment Fee
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:read
      operationId: get-api-reporting-profitability-drilldown
  /api/reporting/profitability/drilldown/{salesOrder}/breakdown:
    get:
      tags:
      - Reporting
      summary: Get Order Breakdown
      description: 'Returns a full financial breakdown for a single order, including
        all line items, COGS, allocated costs, and financial line type values.


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token


        Each line''s financials and the order summary include indirect_cost_allocated
        (this order''s revenue-weighted share of cost-entry / overhead allocations)
        and contribution_profit (profit minus that indirect share). These are standalone
        figures layered on top of profit — profit and total_cost are unchanged by
        them.'
      parameters:
      - name: salesOrder
        in: path
        schema:
          type: integer
        required: true
        description: Sales Order ID
        example: '1001'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  order:
                    type: object
                    properties:
                      id:
                        type: integer
                      sales_order_number:
                        type: string
                      order_date:
                        type: string
                      sales_channel:
                        type: string
                  lines:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        product_id:
                          type: integer
                        sku:
                          type: string
                        name:
                          type: string
                        quantity:
                          type: integer
                        financials:
                          type: object
                          properties:
                            revenue:
                              type: number
                            revenue_allocated:
                              type: integer
                            credits:
                              type: integer
                            discount:
                              type: integer
                            total_revenue:
                              type: number
                            cogs:
                              type: number
                            cost_allocated:
                              type: number
                            cogs_returned:
                              type: integer
                            total_cost:
                              type: number
                            profit:
                              type: number
                            profit_margin:
                              type: number
                            indirect_cost_allocated:
                              type: number
                            contribution_profit:
                              type: number
                  financial_lines:
                    type: array
                  summary:
                    type: object
                    properties:
                      total_revenue:
                        type: number
                      total_cogs:
                        type: number
                      revenue_lines_total:
                        type: integer
                      cost_lines_total:
                        type: number
                      total_cost:
                        type: number
                      profit:
                        type: number
                      margin:
                        type: number
                      indirect_cost_allocated:
                        type: number
                      contribution_profit:
                        type: number
                      contribution_margin:
                        type: number
                example:
                  order:
                    id: 123
                    sales_order_number: SO-00123
                    order_date: '2026-06-15'
                    sales_channel: Shopify US
                  lines:
                  - id: 5541
                    product_id: 88
                    sku: WGT-001
                    name: Widget A
                    quantity: 3
                    financials:
                      revenue: 150.0
                      revenue_allocated: 0
                      credits: 0
                      discount: 0
                      total_revenue: 150.0
                      cogs: 60.0
                      cost_allocated: 12.0
                      cogs_returned: 0
                      total_cost: 72.0
                      profit: 78.0
                      profit_margin: 52.0
                      indirect_cost_allocated: 9.5
                      contribution_profit: 68.5
                  financial_lines: []
                  summary:
                    total_revenue: 150.0
                    total_cogs: 60.0
                    revenue_lines_total: 0
                    cost_lines_total: 12.0
                    total_cost: 72.0
                    profit: 78.0
                    margin: 52.0
                    indirect_cost_allocated: 9.5
                    contribution_profit: 68.5
                    contribution_margin: 45.67
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: reports:read
      operationId: get-api-reporting-profitability-drilldown-salesorder-breakdown
  /api/reporting/profitability/financial-line-types:
    get:
      tags:
      - Reporting
      summary: Get Financial Line Types
      description: 'Returns all financial line types configured for the current tenant.
        Used to populate the drilldown column selector.


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        type:
                          type: string
                example:
                  data:
                  - id: 1
                    name: Shipping
                    type: cost
                  - id: 2
                    name: Fulfilment Fee
                    type: cost
                  - id: 3
                    name: Platform Fee
                    type: cost
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:read
      operationId: get-api-reporting-profitability-financial-line-types
  /api/reporting/profitability/indirect-cost-types:
    get:
      tags:
      - Reporting
      summary: List Indirect Cost Types
      description: 'Lists the indirect cost types that have cost-entry allocation
        activity inside the report window, with allocated totals. Drives the per-type
        breakdown columns and the indirect cost type filter. Type id 0 represents
        allocations whose cost entry has no type (Uncategorized).


        Authentication: Requires Bearer token'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        total:
                          type: number
                example:
                  data:
                  - id: 2
                    name: Marketing
                    total: 1700.0
                  - id: 5
                    name: Software
                    total: 600.0
                  - id: 0
                    name: Uncategorized
                    total: 120.0
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-reporting-profitability-indirect-cost-types
  /api/reporting/profitability/indirect-cost-drilldown:
    get:
      tags:
      - Reporting
      summary: Get Indirect Cost Drilldown
      description: 'Itemizes the cost-entry activity behind a Profitability Report
        figure.


        scope=allocated returns the cost allocations attributed to one dimension row
        (matching the row''s indirect cost amount exactly). scope=unallocated returns
        cost entries with an unallocated remainder in the window — the amount deducted
        from Contribution Margin to derive Operating Profit. Draft cost entries are
        excluded.


        Authentication: Requires Bearer token'
      parameters:
      - name: group_by
        in: query
        schema:
          type: string
        description: 'Dimension: brand | sku | supplier | sales_channel | product_type
          | sub_sales_channel | attribute | customer_tags. Required unless scope=unallocated.
          customer_tags fans out — an order counts toward each of its customer''s
          tags — and the grand total is deduplicated. customer_tags does not require
          attribute_id.'
        example: brand
      - name: dimension_value
        in: query
        schema:
          type: string
        description: The dimension row value to drill into (use 'Non-Product / Unallocated'
          for the unattributed row). Required unless scope=unallocated.
        example: Acme Brand
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 OK (scope=allocated)
                  value:
                    data:
                    - cost_allocation_id: 991
                      cost_entry_id: 123
                      description: June Marketing Campaign
                      cost_entry_type:
                        id: 2
                        name: Marketing
                      allocatable_type: Product
                      allocatable_label: WGT-001 — Widget A
                      allocation_date: '2026-06-30'
                      period_start: '2026-06-01'
                      period_end: '2026-06-30'
                      proration_strategy: revenue_based
                      amount_in_tenant_currency: 1200.0
                    current_page: 1
                    per_page: 10
                    total: 3
                    last_page: 1
                example-1:
                  summary: 200 OK (scope=unallocated)
                  value:
                    data:
                    - cost_entry_id: 456
                      description: Office rent June
                      cost_entry_type:
                        id: 7
                        name: Overhead
                      cost_date: '2026-06-01'
                      amount: 5000.0
                      allocated: 1500.0
                      remainder: 3500.0
                    current_page: 1
                    per_page: 10
                    total: 2
                    last_page: 1
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-reporting-profitability-indirect-cost-drilldown
  /api/reporting/contribution-margin/summary:
    get:
      tags:
      - Reporting
      summary: Get Contribution Margin Summary
      description: 'Contribution margin measures profitability after both cost of
        goods sold and allocated operating costs:

        - Gross Profit = Revenue − COGS

        - Contribution Dollars = Gross Profit − Allocated Costs

        - Contribution Margin % = Contribution Dollars ÷ Revenue × 100


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Revenue and COGS come from per-order-line financial records that are kept
        current by background financial calculations. Allocated costs come from the
        cost allocation system (cost entries prorated across products, orders, brands,
        suppliers, or sales channels).


        Returns the account-wide profitability summary as a single `Overall` row:
        total revenue, COGS, allocated costs, gross profit, contribution dollars,
        margin percentages, units sold, and order count. Entity filters (product,
        brand, supplier, sales channel) narrow the underlying sales data; `cost_entry_type_id`
        narrows the allocated-cost figures.


        Date filtering: `date_from` and `date_to` must BOTH be provided for date filtering
        to apply — if either is omitted the report covers all available history. Sales
        figures are filtered by order date; allocated costs are matched by their allocation
        period when one is set (any overlap with the requested range counts), otherwise
        by their allocation date.


        Authentication: Requires Bearer token. Scope: `reports` (read/write).'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      dimension:
                        type: string
                      date_from:
                        type: string
                      date_to:
                        type: string
                      total_revenue:
                        type: number
                      total_cogs:
                        type: number
                      total_allocated_costs:
                        type: number
                      total_gross_profit:
                        type: number
                      total_contribution_dollars:
                        type: number
                      overall_gross_profit_margin:
                        type: number
                      overall_contribution_margin:
                        type: number
                      total_units_sold:
                        type: integer
                      total_order_count:
                        type: integer
                      total_ad_spend:
                        type: number
                      total_attributed_sales:
                        type: number
                      overall_acos:
                        type: string
                        nullable: true
                      overall_tacos:
                        type: number
                      overall_break_even_acos:
                        type: number
                      lines:
                        type: array
                        items:
                          type: object
                          properties:
                            entity_id:
                              type: string
                              nullable: true
                            entity_name:
                              type: string
                            entity_type:
                              type: string
                            revenue:
                              type: number
                            cogs:
                              type: number
                            allocated_costs:
                              type: number
                            gross_profit:
                              type: number
                            contribution_dollars:
                              type: number
                            gross_profit_margin:
                              type: number
                            contribution_margin:
                              type: number
                            units_sold:
                              type: integer
                            order_count:
                              type: integer
                            ad_spend:
                              type: number
                            attributed_sales:
                              type: number
                            acos:
                              type: string
                              nullable: true
                            tacos:
                              type: number
                            break_even_acos:
                              type: number
                            sku:
                              type: string
                              nullable: true
                            brand_name:
                              type: string
                              nullable: true
                            brand_id:
                              type: integer
                            supplier_name:
                              type: string
                              nullable: true
                example:
                  data:
                    dimension: summary
                    date_from: '2026-06-01'
                    date_to: '2026-06-30'
                    total_revenue: 262480.0
                    total_cogs: 141739.2
                    total_allocated_costs: 26248.0
                    total_gross_profit: 120740.8
                    total_contribution_dollars: 94492.8
                    overall_gross_profit_margin: 46.0
                    overall_contribution_margin: 36.0
                    total_units_sold: 10499
                    total_order_count: 8321
                    total_ad_spend: 0.0
                    total_attributed_sales: 0.0
                    overall_acos: null
                    overall_tacos: 0.0
                    overall_break_even_acos: 36.0
                    lines:
                    - entity_id: null
                      entity_name: Overall
                      entity_type: summary
                      revenue: 262480.0
                      cogs: 141739.2
                      allocated_costs: 26248.0
                      gross_profit: 120740.8
                      contribution_dollars: 94492.8
                      gross_profit_margin: 46.0
                      contribution_margin: 36.0
                      units_sold: 10499
                      order_count: 8321
                      ad_spend: 0.0
                      attributed_sales: 0.0
                      acos: null
                      tacos: 0.0
                      break_even_acos: 36.0
                      sku: null
                      brand_name: null
                      brand_id: 3
                      supplier_name: null
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      date_to:
                        type: array
                        items:
                          type: string
                example:
                  message: The date to field must be a date after or equal to date
                    from.
                  errors:
                    date_to:
                    - The date to field must be a date after or equal to date from.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:read
      operationId: get-api-reporting-contribution-margin-summary
  /api/reporting/contribution-margin/by-product:
    get:
      tags:
      - Reporting
      summary: Get Contribution Margin by Product
      description: 'Contribution margin measures profitability after both cost of
        goods sold and allocated operating costs:

        - Gross Profit = Revenue − COGS

        - Contribution Dollars = Gross Profit − Allocated Costs

        - Contribution Margin % = Contribution Dollars ÷ Revenue × 100


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Revenue and COGS come from per-order-line financial records that are kept
        current by background financial calculations. Allocated costs come from the
        cost allocation system (cost entries prorated across products, orders, brands,
        suppliers, or sales channels).


        Returns a profitability breakdown per product. Each row includes the product''s
        SKU, brand, and default supplier alongside revenue, COGS, allocated costs,
        gross profit, contribution dollars, and margin percentages. Products that
        received cost allocations but had no sales in the period also appear, with
        zero revenue and negative contribution — so allocated spend never silently
        disappears from the report.


        With `include_ad_metrics=true`, each row also carries Amazon Ads spend, ad-attributed
        sales, ACoS (ad spend ÷ attributed sales), TACoS (ad spend ÷ total revenue),
        and break-even ACoS (the ACoS at which the product''s contribution reaches
        zero).


        Date filtering: `date_from` and `date_to` must BOTH be provided for date filtering
        to apply — if either is omitted the report covers all available history. Sales
        figures are filtered by order date; allocated costs are matched by their allocation
        period when one is set (any overlap with the requested range counts), otherwise
        by their allocation date.


        Authentication: Requires Bearer token. Scope: `reports` (read/write).'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      dimension:
                        type: string
                      date_from:
                        type: string
                      date_to:
                        type: string
                      total_revenue:
                        type: number
                      total_cogs:
                        type: number
                      total_allocated_costs:
                        type: number
                      total_gross_profit:
                        type: number
                      total_contribution_dollars:
                        type: number
                      overall_gross_profit_margin:
                        type: number
                      overall_contribution_margin:
                        type: number
                      total_units_sold:
                        type: integer
                      total_order_count:
                        type: integer
                      total_ad_spend:
                        type: number
                      total_attributed_sales:
                        type: number
                      overall_acos:
                        type: number
                      overall_tacos:
                        type: number
                      overall_break_even_acos:
                        type: number
                      lines:
                        type: array
                        items:
                          type: object
                          properties:
                            entity_id:
                              type: integer
                            entity_name:
                              type: string
                            entity_type:
                              type: string
                            revenue:
                              type: number
                            cogs:
                              type: number
                            allocated_costs:
                              type: number
                            gross_profit:
                              type: number
                            contribution_dollars:
                              type: number
                            gross_profit_margin:
                              type: number
                            contribution_margin:
                              type: number
                            units_sold:
                              type: integer
                            order_count:
                              type: integer
                            ad_spend:
                              type: number
                            attributed_sales:
                              type: number
                            acos:
                              type: number
                            tacos:
                              type: number
                            break_even_acos:
                              type: number
                            sku:
                              type: string
                            brand_name:
                              type: string
                            brand_id:
                              type: integer
                            supplier_name:
                              type: string
                example:
                  data:
                    dimension: product
                    date_from: '2026-06-01'
                    date_to: '2026-06-30'
                    total_revenue: 78375.0
                    total_cogs: 38281.25
                    total_allocated_costs: 8682.5
                    total_gross_profit: 40093.75
                    total_contribution_dollars: 31411.25
                    overall_gross_profit_margin: 51.16
                    overall_contribution_margin: 40.08
                    total_units_sold: 2532
                    total_order_count: 2302
                    total_ad_spend: 3990.0
                    total_attributed_sales: 31250.0
                    overall_acos: 12.77
                    overall_tacos: 5.09
                    overall_break_even_acos: 45.17
                    lines:
                    - entity_id: 812
                      entity_name: 5m LED Light Strip - RGB
                      entity_type: product
                      revenue: 48250.0
                      cogs: 21712.5
                      allocated_costs: 5430.0
                      gross_profit: 26537.5
                      contribution_dollars: 21107.5
                      gross_profit_margin: 55.0
                      contribution_margin: 43.75
                      units_sold: 1930
                      order_count: 1712
                      ad_spend: 2410.0
                      attributed_sales: 19850.0
                      acos: 12.14
                      tacos: 4.99
                      break_even_acos: 48.74
                      sku: LED-STRIP-5M-RGB
                      brand_name: Lumina
                      brand_id: 3
                      supplier_name: Shenzhen Lumina Electronics
                    - entity_id: 654
                      entity_name: Desk Glow Lamp - Walnut
                      entity_type: product
                      revenue: 30125.0
                      cogs: 16568.75
                      allocated_costs: 3012.5
                      gross_profit: 13556.25
                      contribution_dollars: 10543.75
                      gross_profit_margin: 45.0
                      contribution_margin: 35.0
                      units_sold: 602
                      order_count: 590
                      ad_spend: 1520.0
                      attributed_sales: 11400.0
                      acos: 13.33
                      tacos: 5.05
                      break_even_acos: 40.05
                      sku: GLOW-DESK-WAL
                      brand_name: NovaGlow
                      brand_id: 3
                      supplier_name: Pacific Coast Distributors
                    - entity_id: 977
                      entity_name: Solar Path Light 4-Pack
                      entity_type: product
                      revenue: 0.0
                      cogs: 0.0
                      allocated_costs: 240.0
                      gross_profit: 0.0
                      contribution_dollars: -240.0
                      gross_profit_margin: 0
                      contribution_margin: 0
                      units_sold: 0
                      order_count: 0
                      ad_spend: 60.0
                      attributed_sales: 0.0
                      acos: null
                      tacos: null
                      break_even_acos: null
                      sku: SOLAR-PATH-4PK
                      brand_name: Lumina
                      brand_id: 3
                      supplier_name: Shenzhen Lumina Electronics
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      limit:
                        type: array
                        items:
                          type: string
                example:
                  message: The limit field must not be greater than 500.
                  errors:
                    limit:
                    - The limit field must not be greater than 500.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:read
      operationId: get-api-reporting-contribution-margin-by-product
  /api/reporting/contribution-margin/by-brand:
    get:
      tags:
      - Reporting
      summary: Get Contribution Margin by Brand
      description: 'Contribution margin measures profitability after both cost of
        goods sold and allocated operating costs:

        - Gross Profit = Revenue − COGS

        - Contribution Dollars = Gross Profit − Allocated Costs

        - Contribution Margin % = Contribution Dollars ÷ Revenue × 100


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Revenue and COGS come from per-order-line financial records that are kept
        current by background financial calculations. Allocated costs come from the
        cost allocation system (cost entries prorated across products, orders, brands,
        suppliers, or sales channels).


        Returns a profitability breakdown per brand. Allocated costs include both
        costs allocated directly to a brand and product-level allocations rolled up
        to the product''s brand. Sales of products without a brand are grouped under
        a `No Brand` row with `entity_id: 0`. Brands with cost allocations but no
        sales in the period also appear with zero revenue. `include_ad_metrics=true`
        adds Amazon Ads spend and attributed sales rolled up to brand level.


        Date filtering: `date_from` and `date_to` must BOTH be provided for date filtering
        to apply — if either is omitted the report covers all available history. Sales
        figures are filtered by order date; allocated costs are matched by their allocation
        period when one is set (any overlap with the requested range counts), otherwise
        by their allocation date.


        Authentication: Requires Bearer token. Scope: `reports` (read/write).'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      dimension:
                        type: string
                      date_from:
                        type: string
                      date_to:
                        type: string
                      total_revenue:
                        type: number
                      total_cogs:
                        type: number
                      total_allocated_costs:
                        type: number
                      total_gross_profit:
                        type: number
                      total_contribution_dollars:
                        type: number
                      overall_gross_profit_margin:
                        type: number
                      overall_contribution_margin:
                        type: number
                      total_units_sold:
                        type: integer
                      total_order_count:
                        type: integer
                      total_ad_spend:
                        type: number
                      total_attributed_sales:
                        type: number
                      overall_acos:
                        type: string
                        nullable: true
                      overall_tacos:
                        type: number
                      overall_break_even_acos:
                        type: number
                      lines:
                        type: array
                        items:
                          type: object
                          properties:
                            entity_id:
                              type: integer
                            entity_name:
                              type: string
                            entity_type:
                              type: string
                            revenue:
                              type: number
                            cogs:
                              type: number
                            allocated_costs:
                              type: number
                            gross_profit:
                              type: number
                            contribution_dollars:
                              type: number
                            gross_profit_margin:
                              type: number
                            contribution_margin:
                              type: number
                            units_sold:
                              type: integer
                            order_count:
                              type: integer
                            ad_spend:
                              type: number
                            attributed_sales:
                              type: number
                            acos:
                              type: string
                              nullable: true
                            tacos:
                              type: number
                            break_even_acos:
                              type: number
                            sku:
                              type: string
                              nullable: true
                            brand_name:
                              type: string
                              nullable: true
                            brand_id:
                              type: integer
                            supplier_name:
                              type: string
                              nullable: true
                example:
                  data:
                    dimension: brand
                    date_from: '2026-06-01'
                    date_to: '2026-06-30'
                    total_revenue: 168120.0
                    total_cogs: 85277.2
                    total_allocated_costs: 16288.0
                    total_gross_profit: 82842.8
                    total_contribution_dollars: 66554.8
                    overall_gross_profit_margin: 49.28
                    overall_contribution_margin: 39.59
                    total_units_sold: 5619
                    total_order_count: 5003
                    total_ad_spend: 0.0
                    total_attributed_sales: 0.0
                    overall_acos: null
                    overall_tacos: 0.0
                    overall_break_even_acos: 39.59
                    lines:
                    - entity_id: 14
                      entity_name: Lumina
                      entity_type: brand
                      revenue: 96410.0
                      cogs: 45312.7
                      allocated_costs: 9641.0
                      gross_profit: 51097.3
                      contribution_dollars: 41456.3
                      gross_profit_margin: 53.0
                      contribution_margin: 43.0
                      units_sold: 3960
                      order_count: 3421
                      ad_spend: 0.0
                      attributed_sales: 0.0
                      acos: null
                      tacos: 0.0
                      break_even_acos: 43.0
                      sku: null
                      brand_name: null
                      brand_id: 3
                      supplier_name: null
                    - entity_id: 22
                      entity_name: NovaGlow
                      entity_type: brand
                      revenue: 61230.0
                      cogs: 33676.5
                      allocated_costs: 6123.0
                      gross_profit: 27553.5
                      contribution_dollars: 21430.5
                      gross_profit_margin: 45.0
                      contribution_margin: 35.0
                      units_sold: 1240
                      order_count: 1180
                      ad_spend: 0.0
                      attributed_sales: 0.0
                      acos: null
                      tacos: 0.0
                      break_even_acos: 35.0
                      sku: null
                      brand_name: null
                      brand_id: 3
                      supplier_name: null
                    - entity_id: 0
                      entity_name: No Brand
                      entity_type: brand
                      revenue: 10480.0
                      cogs: 6288.0
                      allocated_costs: 524.0
                      gross_profit: 4192.0
                      contribution_dollars: 3668.0
                      gross_profit_margin: 40.0
                      contribution_margin: 35.0
                      units_sold: 419
                      order_count: 402
                      ad_spend: 0.0
                      attributed_sales: 0.0
                      acos: null
                      tacos: 0.0
                      break_even_acos: 35.0
                      sku: null
                      brand_name: null
                      brand_id: 3
                      supplier_name: null
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      brand_id:
                        type: array
                        items:
                          type: string
                example:
                  message: The selected brand id is invalid.
                  errors:
                    brand_id:
                    - The selected brand id is invalid.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:read
      operationId: get-api-reporting-contribution-margin-by-brand
  /api/reporting/contribution-margin/by-supplier:
    get:
      tags:
      - Reporting
      summary: Get Contribution Margin by Supplier
      description: 'Contribution margin measures profitability after both cost of
        goods sold and allocated operating costs:

        - Gross Profit = Revenue − COGS

        - Contribution Dollars = Gross Profit − Allocated Costs

        - Contribution Margin % = Contribution Dollars ÷ Revenue × 100


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Revenue and COGS come from per-order-line financial records that are kept
        current by background financial calculations. Allocated costs come from the
        cost allocation system (cost entries prorated across products, orders, brands,
        suppliers, or sales channels).


        Returns a profitability breakdown per supplier. Products are attributed to
        their default supplier; sales of products without a default supplier are grouped
        under a `No Supplier` row with `entity_id: 0`. Allocated costs include both
        costs allocated directly to a supplier and product-level allocations rolled
        up via the product''s default supplier. Suppliers with cost allocations but
        no sales in the period also appear with zero revenue. `include_ad_metrics=true`
        adds Amazon Ads spend and attributed sales rolled up to supplier level.


        Date filtering: `date_from` and `date_to` must BOTH be provided for date filtering
        to apply — if either is omitted the report covers all available history. Sales
        figures are filtered by order date; allocated costs are matched by their allocation
        period when one is set (any overlap with the requested range counts), otherwise
        by their allocation date.


        Authentication: Requires Bearer token. Scope: `reports` (read/write).'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      dimension:
                        type: string
                      date_from:
                        type: string
                      date_to:
                        type: string
                      total_revenue:
                        type: number
                      total_cogs:
                        type: number
                      total_allocated_costs:
                        type: number
                      total_gross_profit:
                        type: number
                      total_contribution_dollars:
                        type: number
                      overall_gross_profit_margin:
                        type: number
                      overall_contribution_margin:
                        type: number
                      total_units_sold:
                        type: integer
                      total_order_count:
                        type: integer
                      total_ad_spend:
                        type: number
                      total_attributed_sales:
                        type: number
                      overall_acos:
                        type: string
                        nullable: true
                      overall_tacos:
                        type: number
                      overall_break_even_acos:
                        type: number
                      lines:
                        type: array
                        items:
                          type: object
                          properties:
                            entity_id:
                              type: integer
                            entity_name:
                              type: string
                            entity_type:
                              type: string
                            revenue:
                              type: number
                            cogs:
                              type: number
                            allocated_costs:
                              type: number
                            gross_profit:
                              type: number
                            contribution_dollars:
                              type: number
                            gross_profit_margin:
                              type: number
                            contribution_margin:
                              type: number
                            units_sold:
                              type: integer
                            order_count:
                              type: integer
                            ad_spend:
                              type: number
                            attributed_sales:
                              type: number
                            acos:
                              type: string
                              nullable: true
                            tacos:
                              type: number
                            break_even_acos:
                              type: number
                            sku:
                              type: string
                              nullable: true
                            brand_name:
                              type: string
                              nullable: true
                            brand_id:
                              type: integer
                            supplier_name:
                              type: string
                              nullable: true
                example:
                  data:
                    dimension: supplier
                    date_from: '2026-06-01'
                    date_to: '2026-06-30'
                    total_revenue: 167370.0
                    total_cogs: 85444.7
                    total_allocated_costs: 16274.5
                    total_gross_profit: 81925.3
                    total_contribution_dollars: 65650.8
                    overall_gross_profit_margin: 48.95
                    overall_contribution_margin: 39.22
                    total_units_sold: 5695
                    total_order_count: 5110
                    total_ad_spend: 0.0
                    total_attributed_sales: 0.0
                    overall_acos: null
                    overall_tacos: 0.0
                    overall_break_even_acos: 39.22
                    lines:
                    - entity_id: 31
                      entity_name: Shenzhen Lumina Electronics
                      entity_type: supplier
                      revenue: 102340.0
                      cogs: 49123.2
                      allocated_costs: 10234.0
                      gross_profit: 53216.8
                      contribution_dollars: 42982.8
                      gross_profit_margin: 52.0
                      contribution_margin: 42.0
                      units_sold: 4210
                      order_count: 3688
                      ad_spend: 0.0
                      attributed_sales: 0.0
                      acos: null
                      tacos: 0.0
                      break_even_acos: 42.0
                      sku: null
                      brand_name: null
                      brand_id: 3
                      supplier_name: null
                    - entity_id: 45
                      entity_name: Pacific Coast Distributors
                      entity_type: supplier
                      revenue: 55780.0
                      cogs: 30679.0
                      allocated_costs: 5578.0
                      gross_profit: 25101.0
                      contribution_dollars: 19523.0
                      gross_profit_margin: 45.0
                      contribution_margin: 35.0
                      units_sold: 1115
                      order_count: 1071
                      ad_spend: 0.0
                      attributed_sales: 0.0
                      acos: null
                      tacos: 0.0
                      break_even_acos: 35.0
                      sku: null
                      brand_name: null
                      brand_id: 3
                      supplier_name: null
                    - entity_id: 0
                      entity_name: No Supplier
                      entity_type: supplier
                      revenue: 9250.0
                      cogs: 5642.5
                      allocated_costs: 462.5
                      gross_profit: 3607.5
                      contribution_dollars: 3145.0
                      gross_profit_margin: 39.0
                      contribution_margin: 34.0
                      units_sold: 370
                      order_count: 351
                      ad_spend: 0.0
                      attributed_sales: 0.0
                      acos: null
                      tacos: 0.0
                      break_even_acos: 34.0
                      sku: null
                      brand_name: null
                      brand_id: 3
                      supplier_name: null
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      supplier_id:
                        type: array
                        items:
                          type: string
                example:
                  message: The selected supplier id is invalid.
                  errors:
                    supplier_id:
                    - The selected supplier id is invalid.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:read
      operationId: get-api-reporting-contribution-margin-by-supplier
  /api/reporting/contribution-margin/by-sales-channel:
    get:
      tags:
      - Reporting
      summary: Get Contribution Margin by Sales Channel
      description: 'Contribution margin measures profitability after both cost of
        goods sold and allocated operating costs:

        - Gross Profit = Revenue − COGS

        - Contribution Dollars = Gross Profit − Allocated Costs

        - Contribution Margin % = Contribution Dollars ÷ Revenue × 100


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Revenue and COGS come from per-order-line financial records that are kept
        current by background financial calculations. Allocated costs come from the
        cost allocation system (cost entries prorated across products, orders, brands,
        suppliers, or sales channels).


        Returns a profitability breakdown per sales channel (e.g. Amazon, Shopify,
        eBay). The row name is the channel''s connected store/integration name. Channels
        with cost allocations but no sales in the period also appear with zero revenue.


        Note: ad metrics (ad spend, attributed sales, ACoS/TACoS) are not computed
        for the sales-channel dimension — those fields are always zero/null here.
        Use the by-product or by-brand reports with `include_ad_metrics=true` for
        advertising performance.


        Date filtering: `date_from` and `date_to` must BOTH be provided for date filtering
        to apply — if either is omitted the report covers all available history. Sales
        figures are filtered by order date; allocated costs are matched by their allocation
        period when one is set (any overlap with the requested range counts), otherwise
        by their allocation date.


        Authentication: Requires Bearer token. Scope: `reports` (read/write).'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      dimension:
                        type: string
                      date_from:
                        type: string
                      date_to:
                        type: string
                      total_revenue:
                        type: number
                      total_cogs:
                        type: number
                      total_allocated_costs:
                        type: number
                      total_gross_profit:
                        type: number
                      total_contribution_dollars:
                        type: number
                      overall_gross_profit_margin:
                        type: number
                      overall_contribution_margin:
                        type: number
                      total_units_sold:
                        type: integer
                      total_order_count:
                        type: integer
                      total_ad_spend:
                        type: number
                      total_attributed_sales:
                        type: number
                      overall_acos:
                        type: string
                        nullable: true
                      overall_tacos:
                        type: number
                      overall_break_even_acos:
                        type: number
                      lines:
                        type: array
                        items:
                          type: object
                          properties:
                            entity_id:
                              type: integer
                            entity_name:
                              type: string
                            entity_type:
                              type: string
                            revenue:
                              type: number
                            cogs:
                              type: number
                            allocated_costs:
                              type: number
                            gross_profit:
                              type: number
                            contribution_dollars:
                              type: number
                            gross_profit_margin:
                              type: number
                            contribution_margin:
                              type: number
                            units_sold:
                              type: integer
                            order_count:
                              type: integer
                            ad_spend:
                              type: number
                            attributed_sales:
                              type: number
                            acos:
                              type: string
                              nullable: true
                            tacos:
                              type: number
                            break_even_acos:
                              type: number
                            sku:
                              type: string
                              nullable: true
                            brand_name:
                              type: string
                              nullable: true
                            brand_id:
                              type: integer
                            supplier_name:
                              type: string
                              nullable: true
                example:
                  data:
                    dimension: sales_channel
                    date_from: '2026-06-01'
                    date_to: '2026-06-30'
                    total_revenue: 262480.0
                    total_cogs: 142010.8
                    total_allocated_costs: 26248.0
                    total_gross_profit: 120469.2
                    total_contribution_dollars: 94221.2
                    overall_gross_profit_margin: 45.9
                    overall_contribution_margin: 35.9
                    total_units_sold: 10499
                    total_order_count: 8321
                    total_ad_spend: 0.0
                    total_attributed_sales: 0.0
                    overall_acos: null
                    overall_tacos: 0.0
                    overall_break_even_acos: 35.9
                    lines:
                    - entity_id: 3
                      entity_name: Amazon US
                      entity_type: sales_channel
                      revenue: 152480.0
                      cogs: 83864.0
                      allocated_costs: 15248.0
                      gross_profit: 68616.0
                      contribution_dollars: 53368.0
                      gross_profit_margin: 45.0
                      contribution_margin: 35.0
                      units_sold: 6099
                      order_count: 4881
                      ad_spend: 0.0
                      attributed_sales: 0.0
                      acos: null
                      tacos: 0.0
                      break_even_acos: 35.0
                      sku: null
                      brand_name: null
                      brand_id: 3
                      supplier_name: null
                    - entity_id: 5
                      entity_name: Shopify
                      entity_type: sales_channel
                      revenue: 78440.0
                      cogs: 40788.8
                      allocated_costs: 7844.0
                      gross_profit: 37651.2
                      contribution_dollars: 29807.2
                      gross_profit_margin: 48.0
                      contribution_margin: 38.0
                      units_sold: 3138
                      order_count: 2612
                      ad_spend: 0.0
                      attributed_sales: 0.0
                      acos: null
                      tacos: 0.0
                      break_even_acos: 38.0
                      sku: null
                      brand_name: null
                      brand_id: 3
                      supplier_name: null
                    - entity_id: 8
                      entity_name: eBay
                      entity_type: sales_channel
                      revenue: 31560.0
                      cogs: 17358.0
                      allocated_costs: 3156.0
                      gross_profit: 14202.0
                      contribution_dollars: 11046.0
                      gross_profit_margin: 45.0
                      contribution_margin: 35.0
                      units_sold: 1262
                      order_count: 828
                      ad_spend: 0.0
                      attributed_sales: 0.0
                      acos: null
                      tacos: 0.0
                      break_even_acos: 35.0
                      sku: null
                      brand_name: null
                      brand_id: 3
                      supplier_name: null
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      sales_channel_id:
                        type: array
                        items:
                          type: string
                example:
                  message: The selected sales channel id is invalid.
                  errors:
                    sales_channel_id:
                    - The selected sales channel id is invalid.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:read
      operationId: get-api-reporting-contribution-margin-by-sales-channel
  /api/reporting/contribution-margin/top-products:
    get:
      tags:
      - Reporting
      summary: Get Top Products by Contribution Margin
      description: 'Contribution margin measures profitability after both cost of
        goods sold and allocated operating costs:

        - Gross Profit = Revenue − COGS

        - Contribution Dollars = Gross Profit − Allocated Costs

        - Contribution Margin % = Contribution Dollars ÷ Revenue × 100


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Revenue and COGS come from per-order-line financial records that are kept
        current by background financial calculations. Allocated costs come from the
        cost allocation system (cost entries prorated across products, orders, brands,
        suppliers, or sales channels).


        Returns the products ranked by contribution dollars (gross profit minus allocated
        costs). Use `order=desc` (default) for your biggest profit contributors, or
        `order=asc` to surface the weakest performers. Each product row has the same
        shape as the by-product report lines, including SKU, brand, and default supplier.


        Ranking note: candidates are drawn from the top revenue-generating products
        (twice the requested limit) before being re-ranked by contribution dollars,
        so a low-revenue product with very high margin can occasionally fall outside
        the candidate pool.


        Date filtering: `date_from` and `date_to` must BOTH be provided for date filtering
        to apply — if either is omitted the report covers all available history. Sales
        figures are filtered by order date; allocated costs are matched by their allocation
        period when one is set (any overlap with the requested range counts), otherwise
        by their allocation date.


        Authentication: Requires Bearer token. Scope: `reports` (read/write).'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      date_from:
                        type: string
                      date_to:
                        type: string
                      products:
                        type: array
                        items:
                          type: object
                          properties:
                            entity_id:
                              type: integer
                            entity_name:
                              type: string
                            entity_type:
                              type: string
                            revenue:
                              type: number
                            cogs:
                              type: number
                            allocated_costs:
                              type: number
                            gross_profit:
                              type: number
                            contribution_dollars:
                              type: number
                            gross_profit_margin:
                              type: number
                            contribution_margin:
                              type: number
                            units_sold:
                              type: integer
                            order_count:
                              type: integer
                            ad_spend:
                              type: number
                            attributed_sales:
                              type: number
                            acos:
                              type: string
                              nullable: true
                            tacos:
                              type: number
                            break_even_acos:
                              type: number
                            sku:
                              type: string
                            brand_name:
                              type: string
                            brand_id:
                              type: integer
                            supplier_name:
                              type: string
                example:
                  data:
                    date_from: '2026-06-01'
                    date_to: '2026-06-30'
                    products:
                    - entity_id: 812
                      entity_name: 5m LED Light Strip - RGB
                      entity_type: product
                      revenue: 48250.0
                      cogs: 21712.5
                      allocated_costs: 5430.0
                      gross_profit: 26537.5
                      contribution_dollars: 21107.5
                      gross_profit_margin: 55.0
                      contribution_margin: 43.75
                      units_sold: 1930
                      order_count: 1712
                      ad_spend: 0.0
                      attributed_sales: 0.0
                      acos: null
                      tacos: 0.0
                      break_even_acos: 43.75
                      sku: LED-STRIP-5M-RGB
                      brand_name: Lumina
                      brand_id: 3
                      supplier_name: Shenzhen Lumina Electronics
                    - entity_id: 654
                      entity_name: Desk Glow Lamp - Walnut
                      entity_type: product
                      revenue: 30125.0
                      cogs: 16568.75
                      allocated_costs: 3012.5
                      gross_profit: 13556.25
                      contribution_dollars: 10543.75
                      gross_profit_margin: 45.0
                      contribution_margin: 35.0
                      units_sold: 602
                      order_count: 590
                      ad_spend: 0.0
                      attributed_sales: 0.0
                      acos: null
                      tacos: 0.0
                      break_even_acos: 35.0
                      sku: GLOW-DESK-WAL
                      brand_name: NovaGlow
                      brand_id: 3
                      supplier_name: Pacific Coast Distributors
                    - entity_id: 721
                      entity_name: Smart Plug 2-Pack
                      entity_type: product
                      revenue: 18940.0
                      cogs: 9470.0
                      allocated_costs: 1894.0
                      gross_profit: 9470.0
                      contribution_dollars: 7576.0
                      gross_profit_margin: 50.0
                      contribution_margin: 40.0
                      units_sold: 947
                      order_count: 902
                      ad_spend: 0.0
                      attributed_sales: 0.0
                      acos: null
                      tacos: 0.0
                      break_even_acos: 40.0
                      sku: SMART-PLUG-2PK
                      brand_name: Lumina
                      brand_id: 3
                      supplier_name: Shenzhen Lumina Electronics
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      order:
                        type: array
                        items:
                          type: string
                example:
                  message: The selected order is invalid.
                  errors:
                    order:
                    - The selected order is invalid.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:read
      operationId: get-api-reporting-contribution-margin-top-products
  /api/reporting/contribution-margin/unprofitable-products:
    get:
      tags:
      - Reporting
      summary: List Unprofitable Products
      description: 'Contribution margin measures profitability after both cost of
        goods sold and allocated operating costs:

        - Gross Profit = Revenue − COGS

        - Contribution Dollars = Gross Profit − Allocated Costs

        - Contribution Margin % = Contribution Dollars ÷ Revenue × 100


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Revenue and COGS come from per-order-line financial records that are kept
        current by background financial calculations. Allocated costs come from the
        cost allocation system (cost entries prorated across products, orders, brands,
        suppliers, or sales channels).


        Returns products whose contribution dollars are negative for the period —
        items where COGS plus allocated costs exceed revenue. This includes products
        with cost allocations but no sales at all (zero revenue, negative contribution).
        Each product row has the same shape as the by-product report lines; `count`
        is the number of unprofitable products returned.


        Note: `limit` bounds the revenue-ranked product pool that is scanned, not
        the number of unprofitable rows returned — with a small limit, unprofitable
        products outside the top-revenue pool may be missed.


        Date filtering: `date_from` and `date_to` must BOTH be provided for date filtering
        to apply — if either is omitted the report covers all available history. Sales
        figures are filtered by order date; allocated costs are matched by their allocation
        period when one is set (any overlap with the requested range counts), otherwise
        by their allocation date.


        Authentication: Requires Bearer token. Scope: `reports` (read/write).'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      date_from:
                        type: string
                      date_to:
                        type: string
                      count:
                        type: integer
                      products:
                        type: array
                        items:
                          type: object
                          properties:
                            entity_id:
                              type: integer
                            entity_name:
                              type: string
                            entity_type:
                              type: string
                            revenue:
                              type: number
                            cogs:
                              type: number
                            allocated_costs:
                              type: number
                            gross_profit:
                              type: number
                            contribution_dollars:
                              type: number
                            gross_profit_margin:
                              type: number
                            contribution_margin:
                              type: number
                            units_sold:
                              type: integer
                            order_count:
                              type: integer
                            ad_spend:
                              type: number
                            attributed_sales:
                              type: number
                            acos:
                              type: string
                              nullable: true
                            tacos:
                              type: number
                            break_even_acos:
                              type: number
                            sku:
                              type: string
                            brand_name:
                              type: string
                            brand_id:
                              type: integer
                            supplier_name:
                              type: string
                example:
                  data:
                    date_from: '2026-06-01'
                    date_to: '2026-06-30'
                    count: 2
                    products:
                    - entity_id: 903
                      entity_name: Bluetooth Shower Speaker
                      entity_type: product
                      revenue: 4210.0
                      cogs: 3960.0
                      allocated_costs: 890.0
                      gross_profit: 250.0
                      contribution_dollars: -640.0
                      gross_profit_margin: 5.94
                      contribution_margin: -15.2
                      units_sold: 421
                      order_count: 415
                      ad_spend: 0.0
                      attributed_sales: 0.0
                      acos: null
                      tacos: 0.0
                      break_even_acos: -15.2
                      sku: BT-SHOWER-SPKR
                      brand_name: NovaGlow
                      brand_id: 3
                      supplier_name: Pacific Coast Distributors
                    - entity_id: 977
                      entity_name: Solar Path Light 4-Pack
                      entity_type: product
                      revenue: 0.0
                      cogs: 0.0
                      allocated_costs: 240.0
                      gross_profit: 0.0
                      contribution_dollars: -240.0
                      gross_profit_margin: 0
                      contribution_margin: 0
                      units_sold: 0
                      order_count: 0
                      ad_spend: 0.0
                      attributed_sales: 0.0
                      acos: null
                      tacos: null
                      break_even_acos: null
                      sku: SOLAR-PATH-4PK
                      brand_name: Lumina
                      brand_id: 3
                      supplier_name: Shenzhen Lumina Electronics
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      date_from:
                        type: array
                        items:
                          type: string
                example:
                  message: The date from field must be a valid date.
                  errors:
                    date_from:
                    - The date from field must be a valid date.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:read
      operationId: get-api-reporting-contribution-margin-unprofitable-products
  /api/reporting/contribution-margin/cost-analysis:
    get:
      tags:
      - Reporting
      summary: Get Contribution Margin Cost Analysis
      description: 'Contribution margin measures profitability after both cost of
        goods sold and allocated operating costs:

        - Gross Profit = Revenue − COGS

        - Contribution Dollars = Gross Profit − Allocated Costs

        - Contribution Margin % = Contribution Dollars ÷ Revenue × 100


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Revenue and COGS come from per-order-line financial records that are kept
        current by background financial calculations. Allocated costs come from the
        cost allocation system (cost entries prorated across products, orders, brands,
        suppliers, or sales channels).


        Returns an overview of all allocated costs feeding the contribution margin
        reports: the total amount allocated, how many individual allocations and distinct
        cost entries produced it, and three breakdowns —

        - `by_allocatable_type`: what kind of entity the costs were allocated to (products,
        orders, brands, suppliers, sales channels). `full_type` is the internal type
        identifier; `type` is its short name.

        - `by_cost_entry_type`: the user-defined cost categories (e.g. Amazon Advertising,
        Warehouse Rent). Allocations whose cost entry has no type are grouped under
        `Uncategorized`.

        - `by_proration_strategy`: how each allocation was split (`revenue_based`,
        `cost_based`, `weight_based`, `volume_based`, `quantity_based`, `specific_line`,
        or `manual`).


        Amounts are in the account''s base currency. Breakdown rows are sorted by
        total amount, descending.


        Date filtering: `date_from` and `date_to` must BOTH be provided for date filtering
        to apply — if either is omitted the report covers all available history. Sales
        figures are filtered by order date; allocated costs are matched by their allocation
        period when one is set (any overlap with the requested range counts), otherwise
        by their allocation date.


        Authentication: Requires Bearer token. Scope: `reports` (read/write).'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      date_from:
                        type: string
                      date_to:
                        type: string
                      summary:
                        type: object
                        properties:
                          total_allocated:
                            type: number
                          allocation_count:
                            type: integer
                          cost_entry_count:
                            type: integer
                      by_allocatable_type:
                        type: array
                        items:
                          type: object
                          properties:
                            type:
                              type: string
                            full_type:
                              type: string
                            allocation_count:
                              type: integer
                            total_amount:
                              type: number
                      by_cost_entry_type:
                        type: array
                        items:
                          type: object
                          properties:
                            type_id:
                              type: integer
                            type_name:
                              type: string
                            allocation_count:
                              type: integer
                            total_amount:
                              type: number
                      by_proration_strategy:
                        type: array
                        items:
                          type: object
                          properties:
                            strategy:
                              type: string
                            allocation_count:
                              type: integer
                            total_amount:
                              type: number
                example:
                  data:
                    date_from: '2026-06-01'
                    date_to: '2026-06-30'
                    summary:
                      total_allocated: 26248.0
                      allocation_count: 1842
                      cost_entry_count: 96
                    by_allocatable_type:
                    - type: Product
                      full_type: App\Models\Product
                      allocation_count: 1520
                      total_amount: 19870.5
                    - type: SalesChannel
                      full_type: App\Models\SalesChannel
                      allocation_count: 214
                      total_amount: 4562.25
                    - type: ProductBrand
                      full_type: App\Models\ProductBrand
                      allocation_count: 108
                      total_amount: 1815.25
                    by_cost_entry_type:
                    - type_id: 4
                      type_name: Amazon Advertising
                      allocation_count: 1180
                      total_amount: 14210.0
                    - type_id: 7
                      type_name: Warehouse Rent
                      allocation_count: 402
                      total_amount: 8450.0
                    - type_id: null
                      type_name: Uncategorized
                      allocation_count: 260
                      total_amount: 3588.0
                    by_proration_strategy:
                    - strategy: revenue_based
                      allocation_count: 1102
                      total_amount: 15980.75
                    - strategy: quantity_based
                      allocation_count: 526
                      total_amount: 7412.25
                    - strategy: manual
                      allocation_count: 214
                      total_amount: 2855.0
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      cost_entry_type_id:
                        type: array
                        items:
                          type: string
                example:
                  message: The selected cost entry type id is invalid.
                  errors:
                    cost_entry_type_id:
                    - The selected cost entry type id is invalid.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:read
      operationId: get-api-reporting-contribution-margin-cost-analysis
  /api/reporting/sales-tax/liability:
    get:
      tags:
      - Reporting
      summary: Get Sales Tax Liability
      description: 'Sales Tax Liability Report: tax collected and sales aggregated
        by destination jurisdiction (country + region), with a taxable / non-taxable
        split and Net Tax (tax collected minus refunded tax from credits). Amounts
        are converted to the tenant base currency.


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token (scope rw:reports).


        Required parameters:

        - date_from: report period start

        - date_to: report period end (>= date_from)


        Optional:

        - channel_ids[]: restrict to specific sales channels

        - country_code: destination country ISO code (max 3)

        - order_statuses[]: draft | reserved | open | closed (default open + closed)

        - province_code: destination region/state code (max 10)

        - group_by: state | in_state_out_of_state | responsibility | state_responsibility
        (default state)


        The `responsibility` and `state_responsibility` lenses (Phase 2) split tax
        by who collects & remits it: the seller, or a marketplace facilitator (Amazon/eBay/Walmart/Temu/Faire
        by default). Rows then also carry tax_collection_responsibility, is_default_classification,
        seller_net_tax and marketplace_net_tax. The `is_home_state` flag marks the
        tenant''s resolved home nexus jurisdiction. Rows are sorted by net_tax descending.'
      parameters:
      - name: date_from
        in: query
        schema:
          type: string
        description: Required. Start of the reporting period (date or datetime; treated
          as app timezone).
        example: '2026-01-01'
      - name: date_to
        in: query
        schema:
          type: string
        description: Required. End of the reporting period. Must be on or after date_from.
        example: '2026-03-31'
      - name: group_by
        in: query
        schema:
          type: string
        description: 'Optional. Aggregation lens: state (one row per destination region)
          | in_state_out_of_state (collapses to two rows: In-State home jurisdiction
          vs Out-of-State) | responsibility (two rows: Seller-collected vs Marketplace
          facilitator) | state_responsibility (one row per state, each carrying a
          seller_net_tax / marketplace_net_tax split). Defaults to state.'
        example: state
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        country_code:
                          type: string
                        province_code:
                          type: string
                        province:
                          type: string
                        is_home_state:
                          type: boolean
                        order_count:
                          type: integer
                        gross_sales:
                          type: string
                        taxable_sales:
                          type: string
                        non_taxable_sales:
                          type: string
                        tax_collected:
                          type: string
                        refunded_tax:
                          type: string
                        net_tax:
                          type: string
                  totals:
                    type: object
                    properties:
                      order_count:
                        type: integer
                      gross_sales:
                        type: string
                      taxable_sales:
                        type: string
                      non_taxable_sales:
                        type: string
                      tax_collected:
                        type: string
                      refunded_tax:
                        type: string
                      net_tax:
                        type: string
                  currency:
                    type: string
                  period:
                    type: object
                    properties:
                      date_from:
                        type: string
                      date_to:
                        type: string
                example:
                  data:
                  - country_code: US
                    province_code: CA
                    province: California
                    is_home_state: true
                    order_count: 142
                    gross_sales: '48230.50'
                    taxable_sales: '41200.00'
                    non_taxable_sales: '7030.50'
                    tax_collected: '3502.00'
                    refunded_tax: '120.50'
                    net_tax: '3381.50'
                  - country_code: US
                    province_code: NY
                    province: New York
                    is_home_state: false
                    order_count: 88
                    gross_sales: '26110.00'
                    taxable_sales: '24000.00'
                    non_taxable_sales: '2110.00'
                    tax_collected: '2040.00'
                    refunded_tax: '0.00'
                    net_tax: '2040.00'
                  totals:
                    order_count: 230
                    gross_sales: '74340.50'
                    taxable_sales: '65200.00'
                    non_taxable_sales: '9140.50'
                    tax_collected: '5542.00'
                    refunded_tax: '120.50'
                    net_tax: '5421.50'
                  currency: USD
                  period:
                    date_from: '2026-01-01'
                    date_to: '2026-03-31'
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:read
      operationId: get-api-reporting-sales-tax-liability
  /api/reporting/sales-tax/liability/transactions:
    get:
      tags:
      - Reporting
      summary: Get Sales Tax Transactions (Drill-Down)
      description: 'Paginated transaction drill-down behind a single jurisdiction
        row of the liability report. Returns the underlying orders and credits (credit
        amounts are negative) that compose the aggregated row, filtered by the same
        parameters plus the selected province_code / country_code.


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token (scope rw:reports).


        Required parameters:

        - date_from, date_to


        Optional: channel_ids[], country_code, order_statuses[], province_code, page,
        per_page (1-200).


        Results are a UNION of sales orders and sales credits ordered by transaction
        date descending, returned in the standard Laravel pagination envelope.'
      parameters:
      - name: date_from
        in: query
        schema:
          type: string
        description: Required. Start of the reporting period (date or datetime; treated
          as app timezone).
        example: '2026-01-01'
      - name: date_to
        in: query
        schema:
          type: string
        description: Required. End of the reporting period. Must be on or after date_from.
        example: '2026-03-31'
      - name: page
        in: query
        schema:
          type: integer
        description: Optional. Page number (>= 1). Defaults to 1.
        example: '1'
      - name: per_page
        in: query
        schema:
          type: integer
        description: Optional. Items per page (1-200). Defaults to 15.
        example: '15'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        document_type:
                          type: string
                        order_id:
                          type: integer
                        number:
                          type: string
                        date:
                          type: string
                        channel:
                          type: string
                        customer_name:
                          type: string
                        province_code:
                          type: string
                        taxable_amount:
                          type: string
                        tax:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                  first_page_url:
                    type: string
                  last_page_url:
                    type: string
                  next_page_url:
                    type: string
                  prev_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                example:
                  data:
                  - document_type: order
                    order_id: 33421
                    number: SO-10044
                    date: '2026-03-28'
                    channel: Shopify US
                    customer_name: Jane Doe
                    province_code: CA
                    taxable_amount: '310.00'
                    tax: '26.35'
                  - document_type: credit
                    order_id: 33380
                    number: CN-2051
                    date: '2026-03-20'
                    channel: Shopify US
                    customer_name: John Smith
                    province_code: CA
                    taxable_amount: '-45.00'
                    tax: '-3.83'
                  current_page: 1
                  last_page: 8
                  per_page: 15
                  total: 118
                  from: 1
                  to: 15
                  first_page_url: '{{protocol}}{{domain}}/api/reporting/sales-tax/liability/transactions?page=1'
                  last_page_url: '{{protocol}}{{domain}}/api/reporting/sales-tax/liability/transactions?page=8'
                  next_page_url: '{{protocol}}{{domain}}/api/reporting/sales-tax/liability/transactions?page=2'
                  prev_page_url: null
                  path: '{{protocol}}{{domain}}/api/reporting/sales-tax/liability/transactions'
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:read
      operationId: get-api-reporting-sales-tax-liability-transactions
  /api/reporting/sales-tax/liability/export:
    get:
      tags:
      - Reporting
      summary: Export Sales Tax Liability
      description: 'Exports the Sales Tax Liability Report as a downloadable file
        (CSV, XLSX, or PDF). Accepts the same filter parameters as the liability report.
        The response is a binary file download (Content-Type varies: text/csv, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,
        or application/pdf), not JSON. Columns: Country, Region, Region Code, In-State,
        Orders, Gross Sales, Taxable Sales, Non-Taxable Sales, Tax Collected, Refunded
        Tax, Net Tax, with a trailing TOTAL row.


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token (scope rw:reports).'
      parameters:
      - name: date_from
        in: query
        schema:
          type: string
        description: Required. Start of the reporting period (date or datetime; treated
          as app timezone).
        example: '2026-01-01'
      - name: date_to
        in: query
        schema:
          type: string
        description: Required. End of the reporting period. Must be on or after date_from.
        example: '2026-03-31'
      - name: group_by
        in: query
        schema:
          type: string
        description: Optional. state | in_state_out_of_state (default state).
        example: state
      - name: format
        in: query
        schema:
          type: string
        description: 'Optional. Export format: csv | xlsx | pdf. Defaults to csv.'
        example: csv
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:read
      operationId: get-api-reporting-sales-tax-liability-export
  /api/reporting/sales-tax/channel-responsibility:
    get:
      tags:
      - Reporting
      summary: Get Channel Tax Responsibility
      description: 'Lists every sales channel (integration instance) with its resolved
        tax-collection responsibility for the Sales Tax Liability Report (Phase 2).
        Each channel is classified as `seller` (Seller-collected) or `marketplace_facilitator`
        (Marketplace facilitator).


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        The `source` field indicates how the classification was resolved:

        - override: a manual per-channel override was saved (is_default = false)

        - default: resolved from the built-in marketplace-facilitator map (Amazon,
        eBay, Walmart, Temu, Faire => marketplace_facilitator; Shopify, WooCommerce,
        BigCommerce, API Sales Channel, SKU.io => seller)

        - unclassified: the channel''s integration name is in neither map, so it defaulted
        conservatively to seller and is flagged for review (is_unclassified = true)


        The top-level `has_unclassified` flag is true when at least one channel is
        unclassified, so the UI can surface a review banner.


        Authentication: Requires Bearer token (scope rw:reports).'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        integration_instance_id:
                          type: integer
                        name:
                          type: string
                        integration_name:
                          type: string
                        tax_collection_responsibility:
                          type: string
                        tax_collection_responsibility_label:
                          type: string
                        source:
                          type: string
                        is_default:
                          type: boolean
                        is_unclassified:
                          type: boolean
                  has_unclassified:
                    type: boolean
                example:
                  data:
                  - integration_instance_id: 12
                    name: Amazon US
                    integration_name: Amazon
                    tax_collection_responsibility: marketplace_facilitator
                    tax_collection_responsibility_label: Marketplace facilitator
                    source: default
                    is_default: true
                    is_unclassified: false
                  - integration_instance_id: 8
                    name: Shopify US
                    integration_name: Shopify
                    tax_collection_responsibility: seller
                    tax_collection_responsibility_label: Seller-collected
                    source: default
                    is_default: true
                    is_unclassified: false
                  - integration_instance_id: 21
                    name: TikTok Shop
                    integration_name: TikTok
                    tax_collection_responsibility: seller
                    tax_collection_responsibility_label: Seller-collected
                    source: unclassified
                    is_default: true
                    is_unclassified: true
                  has_unclassified: true
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:read
      operationId: get-api-reporting-sales-tax-channel-responsibility
  /api/reporting/sales-tax/channel-responsibility/{integrationInstance}:
    put:
      tags:
      - Reporting
      summary: Update Channel Tax Responsibility
      description: 'Overrides a single sales channel''s tax-collection responsibility
        (Phase 2). Saving an override sets `source` to override and `is_default` to
        false for that channel; it persists to integration_instances.tax_collection_responsibility
        and immediately affects the responsibility / state_responsibility lenses of
        the Sales Tax Liability Report.


        :::info[Required scope: `reports:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Request body:

        - tax_collection_responsibility (required): seller | marketplace_facilitator


        Authentication: Requires Bearer token (scope rw:reports).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                tax_collection_responsibility:
                  type: string
              example:
                tax_collection_responsibility: marketplace_facilitator
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Required. The integration instance (sales channel) id whose tax-collection
          responsibility is being overridden.
        example: '8'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      integration_instance_id:
                        type: integer
                      name:
                        type: string
                      integration_name:
                        type: string
                      tax_collection_responsibility:
                        type: string
                      tax_collection_responsibility_label:
                        type: string
                      source:
                        type: string
                      is_default:
                        type: boolean
                      is_unclassified:
                        type: boolean
                example:
                  data:
                    integration_instance_id: 8
                    name: Shopify US
                    integration_name: Shopify
                    tax_collection_responsibility: marketplace_facilitator
                    tax_collection_responsibility_label: Marketplace facilitator
                    source: override
                    is_default: false
                    is_unclassified: false
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      tax_collection_responsibility:
                        type: array
                        items:
                          type: string
                example:
                  message: The selected tax collection responsibility is invalid.
                  errors:
                    tax_collection_responsibility:
                    - The selected tax collection responsibility is invalid.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: reports:write
      operationId: put-api-reporting-sales-tax-channel-responsibility-integrationinstance
  /api/reporting/sales-tax/nexus:
    get:
      tags:
      - Reporting
      summary: Get Economic Nexus Exposure
      description: 'Economic Nexus Monitoring dashboard (Phase 3). Returns one row
        per destination jurisdiction (state/region) with measured sales and transaction
        counts compared against that jurisdiction''s configured economic-nexus threshold,
        a computed status, and the percent-of-threshold.


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Measured volume is computed per jurisdiction over that jurisdiction''s own
        measurement window (rolling 12 months, calendar year, or previous-or-current
        calendar year), honouring each threshold''s counts_marketplace_sales and counts_exempt_sales
        flags.


        Status values:

        - registered: tenant is registered in the jurisdiction (reported regardless
        of volume).

        - threshold_met: measured volume meets/exceeds the threshold and the tenant
        is NOT registered.

        - approaching: measured volume is at or above warning_threshold_percent of
        the threshold but below it.

        - not_approaching: measured volume is comfortably below the threshold.

        - no_threshold: no threshold configured for the jurisdiction.


        Results are read from a per-tenant cache populated by the recompute job; computed_at
        is the cache timestamp (null if never computed).


        Authentication: Requires Bearer token (scope rw:reports).'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        country_code:
                          type: string
                        region_code:
                          type: string
                        region:
                          type: string
                        measured_sales:
                          type: string
                        measured_transactions:
                          type: integer
                        threshold_amount:
                          type: string
                        threshold_transaction_count:
                          type: string
                          nullable: true
                        measurement_period:
                          type: string
                        measurement_period_label:
                          type: string
                        percent_of_threshold:
                          type: number
                        is_registered:
                          type: boolean
                        status:
                          type: string
                        status_label:
                          type: string
                  currency:
                    type: string
                  computed_at:
                    type: string
                example:
                  data:
                  - country_code: US
                    region_code: CA
                    region: California
                    measured_sales: '612450.00'
                    measured_transactions: 4120
                    threshold_amount: '500000.00'
                    threshold_transaction_count: null
                    measurement_period: previous_or_current_calendar_year
                    measurement_period_label: Previous or current calendar year
                    percent_of_threshold: 122.49
                    is_registered: false
                    status: threshold_met
                    status_label: Threshold met
                  - country_code: US
                    region_code: TX
                    region: Texas
                    measured_sales: '421000.00'
                    measured_transactions: 1890
                    threshold_amount: '500000.00'
                    threshold_transaction_count: null
                    measurement_period: previous_or_current_calendar_year
                    measurement_period_label: Previous or current calendar year
                    percent_of_threshold: 84.2
                    is_registered: false
                    status: approaching
                    status_label: Approaching
                  - country_code: US
                    region_code: NY
                    region: New York
                    measured_sales: '95300.00'
                    measured_transactions: 540
                    threshold_amount: '500000.00'
                    threshold_transaction_count: 100
                    measurement_period: previous_or_current_calendar_year
                    measurement_period_label: Previous or current calendar year
                    percent_of_threshold: 540.0
                    is_registered: true
                    status: registered
                    status_label: Registered
                  currency: USD
                  computed_at: '2026-06-09T14:05:22+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:read
      operationId: get-api-reporting-sales-tax-nexus
  /api/reporting/sales-tax/nexus/recompute:
    post:
      tags:
      - Reporting
      summary: Recompute Economic Nexus Exposure
      description: 'Dispatches the ''Recompute Nexus Exposure'' tracked background
        job (Phase 3), which measures sales by jurisdiction and refreshes the per-tenant
        nexus exposure cache read by GET /api/reporting/sales-tax/nexus. Progress
        is reported through the tracked job log endpoints.


        :::info[Required scope: `reports:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Request body:

        - country_code (optional): destination country ISO code; uppercased server-side.
        Defaults to US.


        Returns the tracked_job_log_id so the frontend can follow progress. A second
        dispatch is rejected with 409 while a recompute is already queued or running.


        Authentication: Requires Bearer token (scope rw:reports).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                country_code:
                  type: string
              example:
                country_code: US
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 8842
                  message: Nexus exposure recompute started.
        '409':
          description: Conflict
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: A nexus exposure recompute is already in progress.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: reports:write
      operationId: post-api-reporting-sales-tax-nexus-recompute
  /api/reporting/sales-tax/nexus/thresholds:
    get:
      tags:
      - Reporting
      summary: List Economic Nexus Thresholds
      description: 'Lists every configured economic-nexus threshold (Phase 3) — one
        per jurisdiction. Each threshold defines the dollar amount and/or transaction
        count, how they combine (threshold_logic), the measurement window, and whether
        marketplace-facilitated and exempt sales count toward the measured volume.


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token (scope rw:reports).'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        country_code:
                          type: string
                        region_code:
                          type: string
                        threshold_amount:
                          type: string
                        threshold_transaction_count:
                          type: string
                          nullable: true
                        threshold_logic:
                          type: string
                        threshold_logic_label:
                          type: string
                        measurement_period:
                          type: string
                        measurement_period_label:
                          type: string
                        counts_marketplace_sales:
                          type: boolean
                        counts_exempt_sales:
                          type: boolean
                        effective_from:
                          type: string
                        notes:
                          type: string
                example:
                  data:
                  - id: 5
                    country_code: US
                    region_code: CA
                    threshold_amount: '500000.00'
                    threshold_transaction_count: null
                    threshold_logic: or
                    threshold_logic_label: Amount or transactions
                    measurement_period: previous_or_current_calendar_year
                    measurement_period_label: Previous or current calendar year
                    counts_marketplace_sales: false
                    counts_exempt_sales: true
                    effective_from: '2019-04-01'
                    notes: Wayfair economic nexus threshold.
                  - id: 12
                    country_code: US
                    region_code: NY
                    threshold_amount: '500000.00'
                    threshold_transaction_count: 100
                    threshold_logic: and
                    threshold_logic_label: Amount and transactions
                    measurement_period: previous_or_current_calendar_year
                    measurement_period_label: Previous or current calendar year
                    counts_marketplace_sales: false
                    counts_exempt_sales: true
                    effective_from: '2019-06-21'
                    notes: null
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:read
      operationId: get-api-reporting-sales-tax-nexus-thresholds
  /api/reporting/sales-tax/nexus/thresholds/{taxNexusThreshold}:
    put:
      tags:
      - Reporting
      summary: Update Economic Nexus Threshold
      description: 'Updates a single jurisdiction''s economic-nexus threshold config
        (Phase 3). All fields are optional; only the supplied fields change.


        :::info[Required scope: `reports:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Request body:

        - threshold_amount (nullable, numeric >= 0): dollar threshold; null to disable
        the amount test.

        - threshold_transaction_count (nullable, integer >= 0): transaction-count
        threshold; null to disable the count test.

        - threshold_logic (sometimes): and | or — whether both or either test triggers
        nexus.

        - measurement_period (sometimes): rolling_12_months | calendar_year | previous_or_current_calendar_year.

        - counts_marketplace_sales (sometimes, boolean): whether marketplace-facilitated
        sales count toward measured volume.

        - counts_exempt_sales (sometimes, boolean): whether tax-exempt sales count
        toward measured volume.

        - effective_from (nullable, date): when the threshold takes effect.

        - notes (nullable, string <= 255).


        Authentication: Requires Bearer token (scope rw:reports).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                threshold_amount:
                  type: integer
                threshold_transaction_count:
                  type: integer
                threshold_logic:
                  type: string
                measurement_period:
                  type: string
                counts_marketplace_sales:
                  type: boolean
                counts_exempt_sales:
                  type: boolean
                effective_from:
                  type: string
                notes:
                  type: string
              example:
                threshold_amount: 500000
                threshold_transaction_count: 200
                threshold_logic: or
                measurement_period: previous_or_current_calendar_year
                counts_marketplace_sales: false
                counts_exempt_sales: true
                effective_from: '2019-04-01'
                notes: Wayfair economic nexus threshold.
      parameters:
      - name: taxNexusThreshold
        in: path
        schema:
          type: integer
        required: true
        description: Required. The economic-nexus threshold id being updated.
        example: '5'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      country_code:
                        type: string
                      region_code:
                        type: string
                      threshold_amount:
                        type: string
                      threshold_transaction_count:
                        type: integer
                      threshold_logic:
                        type: string
                      threshold_logic_label:
                        type: string
                      measurement_period:
                        type: string
                      measurement_period_label:
                        type: string
                      counts_marketplace_sales:
                        type: boolean
                      counts_exempt_sales:
                        type: boolean
                      effective_from:
                        type: string
                      notes:
                        type: string
                example:
                  data:
                    id: 5
                    country_code: US
                    region_code: CA
                    threshold_amount: '500000.00'
                    threshold_transaction_count: 200
                    threshold_logic: or
                    threshold_logic_label: Amount or transactions
                    measurement_period: previous_or_current_calendar_year
                    measurement_period_label: Previous or current calendar year
                    counts_marketplace_sales: false
                    counts_exempt_sales: true
                    effective_from: '2019-04-01'
                    notes: Wayfair economic nexus threshold.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      threshold_amount:
                        type: array
                        items:
                          type: string
                example:
                  message: The threshold amount field must be at least 0.
                  errors:
                    threshold_amount:
                    - The threshold amount field must be at least 0.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: reports:write
      operationId: put-api-reporting-sales-tax-nexus-thresholds-taxnexusthreshold
  /api/reporting/sales-tax/nexus/registrations:
    get:
      tags:
      - Reporting
      summary: List Sales-Tax Registrations
      description: 'Lists every sales-tax registration record (Phase 3). A registered
        jurisdiction is reported on the nexus dashboard with a ''registered'' status
        regardless of measured volume (registration override).


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token (scope rw:reports).'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        country_code:
                          type: string
                        region_code:
                          type: string
                        is_registered:
                          type: boolean
                        registration_date:
                          type: string
                        registration_number:
                          type: string
                        filing_frequency:
                          type: string
                        filing_frequency_label:
                          type: string
                        notes:
                          type: string
                example:
                  data:
                  - id: 3
                    country_code: US
                    region_code: NY
                    is_registered: true
                    registration_date: '2024-01-15'
                    registration_number: NY-12345678
                    filing_frequency: quarterly
                    filing_frequency_label: Quarterly
                    notes: Registered after crossing threshold in 2023.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:read
      operationId: get-api-reporting-sales-tax-nexus-registrations
    post:
      tags:
      - Reporting
      summary: Create Sales-Tax Registration
      description: 'Creates a sales-tax registration record for a jurisdiction (Phase
        3). The country+region pair must be unique.


        :::info[Required scope: `reports:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Request body:

        - country_code (required, size:2): ISO country code; uppercased server-side.

        - region_code (required, <= 10 chars): state/region code; uppercased server-side.
        Unique per country.

        - is_registered (sometimes, boolean): whether the tenant is registered in
        the jurisdiction.

        - registration_date (nullable, date).

        - registration_number (nullable, <= 100 chars).

        - filing_frequency (nullable): monthly | quarterly | annually.

        - notes (nullable, <= 255 chars).


        Authentication: Requires Bearer token (scope rw:reports).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                country_code:
                  type: string
                region_code:
                  type: string
                is_registered:
                  type: boolean
                registration_date:
                  type: string
                registration_number:
                  type: string
                filing_frequency:
                  type: string
                notes:
                  type: string
              example:
                country_code: US
                region_code: NY
                is_registered: true
                registration_date: '2024-01-15'
                registration_number: NY-12345678
                filing_frequency: quarterly
                notes: Registered after crossing threshold in 2023.
      parameters: []
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      country_code:
                        type: string
                      region_code:
                        type: string
                      is_registered:
                        type: boolean
                      registration_date:
                        type: string
                      registration_number:
                        type: string
                      filing_frequency:
                        type: string
                      filing_frequency_label:
                        type: string
                      notes:
                        type: string
                example:
                  data:
                    id: 3
                    country_code: US
                    region_code: NY
                    is_registered: true
                    registration_date: '2024-01-15'
                    registration_number: NY-12345678
                    filing_frequency: quarterly
                    filing_frequency_label: Quarterly
                    notes: Registered after crossing threshold in 2023.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      region_code:
                        type: array
                        items:
                          type: string
                example:
                  message: The region code has already been taken.
                  errors:
                    region_code:
                    - The region code has already been taken.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:write
      operationId: post-api-reporting-sales-tax-nexus-registrations
  /api/reporting/sales-tax/nexus/registrations/{taxNexusRegistration}:
    put:
      tags:
      - Reporting
      summary: Update Sales-Tax Registration
      description: 'Updates an existing sales-tax registration record (Phase 3). The
        jurisdiction (country + region) is fixed once created; only the registration
        details and status may change. All fields are optional.


        :::info[Required scope: `reports:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Request body:

        - is_registered (sometimes, boolean).

        - registration_date (nullable, date).

        - registration_number (nullable, <= 100 chars).

        - filing_frequency (nullable): monthly | quarterly | annually.

        - notes (nullable, <= 255 chars).


        Authentication: Requires Bearer token (scope rw:reports).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                is_registered:
                  type: boolean
                registration_date:
                  type: string
                registration_number:
                  type: string
                filing_frequency:
                  type: string
                notes:
                  type: string
              example:
                is_registered: true
                registration_date: '2024-01-15'
                registration_number: NY-12345678
                filing_frequency: monthly
                notes: Switched to monthly filing for 2026.
      parameters:
      - name: taxNexusRegistration
        in: path
        schema:
          type: integer
        required: true
        description: Required. The sales-tax registration id being updated. The jurisdiction
          (country + region) is fixed once created.
        example: '3'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      country_code:
                        type: string
                      region_code:
                        type: string
                      is_registered:
                        type: boolean
                      registration_date:
                        type: string
                      registration_number:
                        type: string
                      filing_frequency:
                        type: string
                      filing_frequency_label:
                        type: string
                      notes:
                        type: string
                example:
                  data:
                    id: 3
                    country_code: US
                    region_code: NY
                    is_registered: true
                    registration_date: '2024-01-15'
                    registration_number: NY-12345678
                    filing_frequency: monthly
                    filing_frequency_label: Monthly
                    notes: Switched to monthly filing for 2026.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: reports:write
      operationId: put-api-reporting-sales-tax-nexus-registrations-taxnexusregistration
    delete:
      tags:
      - Reporting
      summary: Delete Sales-Tax Registration
      description: 'Deletes a sales-tax registration record (Phase 3). The jurisdiction
        reverts to volume-based status on the nexus dashboard.


        :::info[Required scope: `reports:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token (scope rw:reports).'
      parameters:
      - name: taxNexusRegistration
        in: path
        schema:
          type: integer
        required: true
        description: Required. The sales-tax registration id being deleted.
        example: '3'
      responses:
        '204':
          description: No Content
          content:
            text/plain:
              schema:
                type: string
                example: ''
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: reports:write
      operationId: delete-api-reporting-sales-tax-nexus-registrations-taxnexusregistration
  /api/reporting/inventory-valuation:
    get:
      tags:
      - Reporting
      summary: Get Inventory Valuation
      description: 'Returns the inventory valuation report summary grouped by warehouse/category.


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      total_valuation:
                        type: number
                      available_valuation:
                        type: number
                      reserved_valuation:
                        type: number
                      in_transit_valuation:
                        type: number
                      groups:
                        type: array
                        items:
                          type: object
                          properties:
                            key:
                              type: object
                              properties:
                                warehouse:
                                  type: string
                            totals:
                              type: object
                              properties:
                                available:
                                  type: integer
                                reserved:
                                  type: integer
                                in_transit:
                                  type: integer
                                total_qty:
                                  type: integer
                                available_valuation:
                                  type: number
                                total_valuation:
                                  type: number
                example:
                  data:
                    total_valuation: 125400.0
                    available_valuation: 98500.0
                    reserved_valuation: 12800.0
                    in_transit_valuation: 14100.0
                    groups:
                    - key:
                        warehouse: Main Warehouse
                      totals:
                        available: 1200
                        reserved: 150
                        in_transit: 200
                        total_qty: 1550
                        available_valuation: 98500.0
                        total_valuation: 125400.0
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:read
      operationId: get-api-reporting-inventory-valuation
  /api/reporting/inventory-valuation/export:
    get:
      tags:
      - Reporting
      summary: Export Inventory Valuation
      description: 'Streams the inventory valuation report as a CSV file download
        (Content-Type text/csv, attachment inventory-valuation.csv).


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token


        Columns: the selected group_by dimensions (SKU, Warehouse, Supplier, Brand,
        COGS Nominal Code) followed by quantity/valuation pairs — Available, Allocated,
        On Hold, On Hand, On Hand Average Cost, In Transit, Inbound, Prepaid, and
        Average Cost. On Hand / On Hand Valuation are the physical on-hand position
        as of the report date (on_hand_active_qty x average cost) and include allocated
        & on-hold stock but exclude In Transit.


        Response: CSV file download (not JSON).'
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:read
      operationId: get-api-reporting-inventory-valuation-export
  /api/reporting/inventory-valuation/drilldown/category:
    get:
      tags:
      - Reporting
      summary: Get Inventory Valuation Drilldown by Category
      description: 'Returns inventory valuation broken down by category.


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        category:
                          type: string
                        total_qty:
                          type: integer
                        total_valuation:
                          type: number
                        available_valuation:
                          type: number
                example:
                  data:
                  - category: Electronics
                    total_qty: 450
                    total_valuation: 42500.0
                    available_valuation: 35000.0
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:read
      operationId: get-api-reporting-inventory-valuation-drilldown-category
  /api/reporting/inventory-valuation/drilldown/sources:
    get:
      tags:
      - Reporting
      summary: Get Inventory Valuation Drilldown by Source
      description: 'Returns inventory valuation broken down by source (purchase order,
        initial inventory, etc.).


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        source:
                          type: string
                        total_qty:
                          type: integer
                        total_valuation:
                          type: number
                example:
                  data:
                  - source: Purchase Order
                    total_qty: 1200
                    total_valuation: 98000.0
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:read
      operationId: get-api-reporting-inventory-valuation-drilldown-sources
  /api/reporting/inventory-valuation/drilldown/transactions:
    get:
      tags:
      - Reporting
      summary: Get Inventory Valuation Drilldown by Transactions
      description: 'Returns inventory valuation broken down by individual inventory
        transactions.


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        type:
                          type: string
                        quantity:
                          type: integer
                        cost:
                          type: number
                        valuation:
                          type: number
                        date:
                          type: string
                example:
                  data:
                  - id: 5001
                    type: receipt
                    quantity: 100
                    cost: 9.25
                    valuation: 925.0
                    date: '2024-05-01'
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:read
      operationId: get-api-reporting-inventory-valuation-drilldown-transactions
  /api/reporting/realtime-inventory:
    get:
      tags:
      - Reporting
      summary: Get Realtime Inventory
      description: 'Returns real-time inventory levels per product per warehouse.
        Supports both application UI format (filter[search], filter[warehouse_id])
        and legacy Vue 2 format (search, warehouse_id) — both are auto-normalized.


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        product:
                          type: object
                          properties:
                            id:
                              type: integer
                            sku:
                              type: string
                            name:
                              type: string
                        warehouse:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        inventory:
                          type: object
                          properties:
                            available:
                              type: integer
                            allocated:
                              type: integer
                            on_hold:
                              type: integer
                            in_transit:
                              type: integer
                            total:
                              type: integer
                            inbound:
                              type: integer
                            projected_total:
                              type: integer
                example:
                  data:
                  - product:
                      id: 42
                      sku: WIDGET-001
                      name: Blue Widget
                    warehouse:
                      id: 1
                      name: Main Warehouse
                    inventory:
                      available: 150
                      allocated: 20
                      on_hold: 5
                      in_transit: 10
                      total: 185
                      inbound: 50
                      projected_total: 235
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:read
      operationId: get-api-reporting-realtime-inventory
  /api/reporting/realtime-inventory/summary:
    get:
      tags:
      - Reporting
      summary: Get Realtime Inventory Summary
      description: 'Returns aggregate summary totals for the realtime inventory report.


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      total_available:
                        type: integer
                      total_allocated:
                        type: integer
                      total_in_transit:
                        type: integer
                      total_inbound:
                        type: integer
                      total_projected:
                        type: integer
                example:
                  data:
                    total_available: 12500
                    total_allocated: 850
                    total_in_transit: 1200
                    total_inbound: 3400
                    total_projected: 17950
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:read
      operationId: get-api-reporting-realtime-inventory-summary
  /api/reporting/realtime-inventory/export:
    get:
      tags:
      - Reporting
      summary: Export Realtime Inventory
      description: 'Exports real-time inventory data as a CSV file. Columns: SKU,
        Product Name, Warehouse, Available, Allocated, On Hold, In Transit, Total,
        Inbound, Projected Total.


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token


        Response: text/csv file download (realtime-inventory.csv)'
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:read
      operationId: get-api-reporting-realtime-inventory-export
  /api/reporting/financials-by-brand:
    get:
      tags:
      - Reporting
      summary: Get Financials by Brand
      description: 'Returns financial summary data grouped by brand.


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token


        Required: interval (day|week|month|quarter|year), metric (revenue|profit|profit
        margin|units sold|# of orders)'
      parameters:
      - name: interval
        in: query
        schema:
          type: string
        description: 'Required. Time interval: day | week | month | quarter | year'
        example: month
      - name: metric
        in: query
        schema:
          type: string
        description: 'Required. Metric: revenue | profit | profit margin | units sold
          | # of orders'
        example: revenue
      - name: limit
        in: query
        schema:
          type: integer
        description: Optional. Number of results
        example: '10'
      - name: sort
        in: query
        schema:
          type: string
        description: 'Optional. Sort: asc | desc'
        example: desc
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        brand:
                          type: string
                        period:
                          type: string
                        revenue:
                          type: number
                        profit:
                          type: number
                        units_sold:
                          type: integer
                        num_orders:
                          type: integer
                example:
                  data:
                  - brand: Acme
                    period: 2024-06
                    revenue: 15200.0
                    profit: 6080.0
                    units_sold: 320
                    num_orders: 45
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:read
      operationId: get-api-reporting-financials-by-brand
  /api/reporting/financials-by-sku:
    get:
      tags:
      - Reporting
      summary: Get Financials by SKU
      description: 'Returns financial summary data grouped by SKU/product.


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token'
      parameters:
      - name: interval
        in: query
        schema:
          type: string
        description: 'Required: day | week | month | quarter | year'
        example: month
      - name: metric
        in: query
        schema:
          type: string
        description: 'Required: revenue | profit | profit margin | units sold | #
          of orders'
        example: profit
      - name: limit
        in: query
        schema:
          type: integer
        description: Optional
        example: '20'
      - name: sort
        in: query
        schema:
          type: string
        description: 'Optional: asc | desc'
        example: desc
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        sku:
                          type: string
                        period:
                          type: string
                        revenue:
                          type: number
                        profit:
                          type: number
                example:
                  data:
                  - sku: WIDGET-001
                    period: 2024-06
                    revenue: 4500.0
                    profit: 1800.0
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:read
      operationId: get-api-reporting-financials-by-sku
  /api/reporting/financials-by-supplier:
    get:
      tags:
      - Reporting
      summary: Get Financials by Supplier
      description: 'Returns financial summary data grouped by supplier.


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token'
      parameters:
      - name: interval
        in: query
        schema:
          type: string
        description: 'Required: day | week | month | quarter | year'
        example: month
      - name: metric
        in: query
        schema:
          type: string
        description: 'Required: revenue | profit | profit margin | units sold | #
          of orders'
        example: revenue
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        supplier:
                          type: string
                        period:
                          type: string
                        revenue:
                          type: number
                        units_sold:
                          type: integer
                example:
                  data:
                  - supplier: Widget Co
                    period: 2024-06
                    revenue: 28000.0
                    units_sold: 600
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:read
      operationId: get-api-reporting-financials-by-supplier
  /api/reporting/financials-by-sales-channel:
    get:
      tags:
      - Reporting
      summary: Get Financials by Sales Channel
      description: 'Returns financial summary data grouped by sales channel.


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token'
      parameters:
      - name: interval
        in: query
        schema:
          type: string
        description: 'Required: day | week | month | quarter | year'
        example: month
      - name: metric
        in: query
        schema:
          type: string
        description: 'Required: revenue | profit | profit margin | units sold | #
          of orders'
        example: revenue
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        sales_channel:
                          type: string
                        period:
                          type: string
                        revenue:
                          type: number
                        num_orders:
                          type: integer
                example:
                  data:
                  - sales_channel: Shopify
                    period: 2024-06
                    revenue: 12000.0
                    num_orders: 85
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:read
      operationId: get-api-reporting-financials-by-sales-channel
  /api/reporting/financials-by-sub-sales-channel:
    get:
      tags:
      - Reporting
      summary: Get Financials by Sub-Sales Channel
      description: 'Returns financial summary data grouped by sub-sales channel.


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token'
      parameters:
      - name: interval
        in: query
        schema:
          type: string
        description: 'Required: day | week | month | quarter | year'
        example: month
      - name: metric
        in: query
        schema:
          type: string
        description: 'Required: revenue | profit | profit margin | units sold | #
          of orders'
        example: revenue
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        sub_sales_channel:
                          type: string
                        period:
                          type: string
                        revenue:
                          type: number
                example:
                  data:
                  - sub_sales_channel: Shopify US
                    period: 2024-06
                    revenue: 8500.0
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:read
      operationId: get-api-reporting-financials-by-sub-sales-channel
  /api/reporting/financials-by-product-type:
    get:
      tags:
      - Reporting
      summary: Get Financials by Product Type
      description: 'Returns financial summary data grouped by product type (standard,
        blemished, kit).


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token'
      parameters:
      - name: interval
        in: query
        schema:
          type: string
        description: 'Required: day | week | month | quarter | year'
        example: month
      - name: metric
        in: query
        schema:
          type: string
        description: 'Required: revenue | profit | profit margin | units sold | #
          of orders'
        example: revenue
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        product_type:
                          type: string
                        period:
                          type: string
                        revenue:
                          type: number
                        units_sold:
                          type: integer
                example:
                  data:
                  - product_type: standard
                    period: 2024-06
                    revenue: 35000.0
                    units_sold: 780
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:read
      operationId: get-api-reporting-financials-by-product-type
  /api/reporting/cogs:
    get:
      tags:
      - Reporting
      summary: Get Monthly COGS
      description: 'Returns monthly COGS (cost of goods sold) data for a specific
        year.


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token'
      parameters:
      - name: year
        in: query
        schema:
          type: integer
        description: 'Year to get COGS data for (default: current year)'
        example: '2024'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        month:
                          type: string
                        total_cost:
                          type: number
                  status:
                    type: string
                example:
                  data:
                  - month: 2024-06
                    total_cost: 45200.0
                  - month: 2024-05
                    total_cost: 38900.0
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:read
      operationId: get-api-reporting-cogs
  /api/reporting/purchases/summary-by-period:
    get:
      tags:
      - Reporting
      summary: Get Purchase Summary by Period
      description: 'Returns a summary of purchases grouped by period (month or year).


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token


        Required: period (month|year)

        Optional: trailing_days (integer)'
      parameters:
      - name: period
        in: query
        schema:
          type: string
        description: 'Required. Period grouping: month | year'
        example: month
      - name: trailing_days
        in: query
        schema:
          type: integer
        description: Optional. Number of trailing days to include
        example: '90'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        period_date:
                          type: string
                        total:
                          type: number
                        count:
                          type: integer
                  status:
                    type: string
                example:
                  data:
                  - period_date: 2024-06
                    total: 18500.0
                    count: 12
                  - period_date: 2024-05
                    total: 22100.0
                    count: 15
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:read
      operationId: get-api-reporting-purchases-summary-by-period
  /api/reporting/accounting-cogs:
    get:
      tags:
      - Reporting
      summary: Get Accounting COGS
      description: 'Returns accounting COGS report data including average cost, quantities
        sold/returned/adjusted, and COGS totals (gross, returned, adjusted, net).


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        avg_cost:
                          type: number
                        qty_sold:
                          type: integer
                        qty_returned:
                          type: integer
                        qty_adjusted:
                          type: integer
                        net_qty:
                          type: integer
                        gross_cogs:
                          type: number
                        returned_cogs:
                          type: number
                        adjusted_cogs:
                          type: number
                        net_cogs:
                          type: number
                example:
                  data:
                  - avg_cost: 9.25
                    qty_sold: 450
                    qty_returned: 12
                    qty_adjusted: -5
                    net_qty: 433
                    gross_cogs: 4162.5
                    returned_cogs: 111.0
                    adjusted_cogs: -46.25
                    net_cogs: 4005.25
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:read
      operationId: get-api-reporting-accounting-cogs
  /api/reporting/accounting-cogs/drilldown:
    get:
      tags:
      - Reporting
      summary: Get Accounting COGS Drilldown
      description: 'Underlying movements behind one COGS report row — the individual
        `accounting_cogs` view rows (sales fulfillments, customer returns, inventory
        adjustments, FBA movements) that compose the clicked group/SKU aggregate.
        Paginated, sortable, searchable, with a `totals` block that reconciles to
        the report row that opened it (same 9 metrics).


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Identify the clicked row with `dimensions[<group_by>]=<value>` for each active
        group-by dimension down to that row''s level (e.g. sales_channel, then sku).
        Pass the same `filter[date_range_from]`/`filter[date_range_to]` the report
        was generated with. Each row includes a `product_link` to the product detail
        page and a `source_label`/`src_id` for the originating accounting record.


        Authentication: Requires Bearer token. Scope: reports.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        transaction_date:
                          type: string
                        type:
                          type: string
                        type_label:
                          type: string
                        category:
                          type: string
                        sales_channel_name:
                          type: string
                        brand:
                          type: string
                        brand_id:
                          type: integer
                        country:
                          type: string
                        sku:
                          type: string
                        product_id:
                          type: integer
                        product_link:
                          type: string
                        raw_qty:
                          type: integer
                        sign:
                          type: integer
                        unit_cost:
                          type: number
                        ext_cost:
                          type: number
                        cogs_impact:
                          type: number
                        src_id:
                          type: integer
                        src_type:
                          type: string
                        source_label:
                          type: string
                  current_page:
                    type: integer
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  next_page_url:
                    type: string
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                  totals:
                    type: object
                    properties:
                      count:
                        type: integer
                      qty_sold:
                        type: integer
                      qty_returned:
                        type: integer
                      qty_adjusted:
                        type: integer
                      net_qty:
                        type: integer
                      gross_cogs:
                        type: number
                      returned_cogs:
                        type: number
                      adjusted_cogs:
                        type: number
                      net_cogs:
                        type: number
                      avg_cost:
                        type: number
                example:
                  data:
                  - transaction_date: '2026-05-20T14:03:00.000000Z'
                    type: sales_order_fulfillment
                    type_label: Sale
                    category: sold
                    sales_channel_name: Shopify US
                    brand: Acme
                    brand_id: 3
                    country: US
                    sku: ACM-001
                    product_id: 42
                    product_link: /products/42
                    raw_qty: 10
                    sign: -1
                    unit_cost: 9.25
                    ext_cost: 92.5
                    cogs_impact: 92.5
                    src_id: 1187
                    src_type: App\Models\BatchAccountingTransaction
                    source_label: Batch Transaction
                  current_page: 1
                  first_page_url: '...'
                  from: 1
                  last_page: 3
                  last_page_url: '...'
                  next_page_url: '...'
                  path: '...'
                  per_page: 15
                  prev_page_url: null
                  to: 15
                  total: 42
                  totals:
                    count: 42
                    qty_sold: 450
                    qty_returned: 12
                    qty_adjusted: -5
                    net_qty: 433
                    gross_cogs: 4162.5
                    returned_cogs: 111.0
                    adjusted_cogs: -46.25
                    net_cogs: 4005.25
                    avg_cost: 9.25
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:read
      operationId: get-api-reporting-accounting-cogs-drilldown
  /api/reporting/accounting-cogs/export:
    get:
      tags:
      - Reporting
      summary: Export Accounting COGS
      description: 'Exports accounting COGS report as a CSV file. group_by[] determines
        which extra columns appear before the metric columns (Avg Cost, Qty Sold,
        Qty Returned, Qty Adjusted, Net Qty, Gross COGS, Returned COGS, Adjusted COGS,
        Net COGS).


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token


        Response: text/csv file download (accounting-cogs.csv)'
      parameters:
      - name: group_by[]
        in: query
        schema:
          type: string
        description: 'Grouping dimensions: sales_channel | country | brand | sku'
        example: sales_channel
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:read
      operationId: get-api-reporting-accounting-cogs-export
  /api/reporting/ginr:
    get:
      tags:
      - Reporting
      summary: Get GINR Report (Prepaid Inventory)
      description: 'Returns the Goods In Not Received (GINR) / prepaid inventory report
        — purchase invoices paid but not yet received into inventory.


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token'
      parameters:
      - name: start_date
        in: query
        schema:
          type: string
        description: Optional. Report start date
        example: '2024-01-01'
      - name: end_date
        in: query
        schema:
          type: string
        description: Optional. Report end date
        example: '2024-06-30'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        purchase_order_number:
                          type: string
                        supplier:
                          type: string
                        invoice_date:
                          type: string
                        total_invoiced:
                          type: number
                        total_received:
                          type: number
                        outstanding:
                          type: number
                example:
                  data:
                  - purchase_order_number: PO-350
                    supplier: Widget Co
                    invoice_date: '2024-05-01'
                    total_invoiced: 5000.0
                    total_received: 2500.0
                    outstanding: 2500.0
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:read
      operationId: get-api-reporting-ginr
  /api/reporting/ginr/balance:
    get:
      tags:
      - Reporting
      summary: Get GINR Balance
      description: 'GINR (Goods Invoiced, Not Received) — also called Accrued Purchases
        or GRNI — tracks the value of goods that suppliers have invoiced but that
        have not yet been received into inventory. The balance is calculated as: invoiced
        − received + discrepancies − adjustments, accumulated from the account''s
        inventory start date (so it behaves like a balance-sheet figure, not a period
        movement).


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Returns the single cumulative GINR balance as of an arbitrary date, broken
        into its four components (invoiced, received, discrepancy, adjustments) plus
        the resulting `unreceived` balance. Figures are computed live from purchasing
        and receiving records at request time.


        Authentication: Requires Bearer token. Scope: `reports` (read/write).'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      as_of_date:
                        type: string
                      invoiced:
                        type: number
                      received:
                        type: number
                      discrepancy:
                        type: number
                      adjustments:
                        type: number
                      unreceived:
                        type: number
                example:
                  data:
                    as_of_date: '2026-06-30'
                    invoiced: 148230.5
                    received: 121480.25
                    discrepancy: -350.75
                    adjustments: 1200.0
                    unreceived: 25199.5
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      as_of_date:
                        type: array
                        items:
                          type: string
                example:
                  message: The as of date field must be a valid date.
                  errors:
                    as_of_date:
                    - The as of date field must be a valid date.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:read
      operationId: get-api-reporting-ginr-balance
  /api/reporting/ginr/trend:
    get:
      tags:
      - Reporting
      summary: Get GINR Trend
      description: 'GINR (Goods Invoiced, Not Received) — also called Accrued Purchases
        or GRNI — tracks the value of goods that suppliers have invoiced but that
        have not yet been received into inventory. The balance is calculated as: invoiced
        − received + discrepancies − adjustments, accumulated from the account''s
        inventory start date (so it behaves like a balance-sheet figure, not a period
        movement).


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Returns the end-of-month unreceived (GINR) balance for the last N months —
        one point per month — suitable for rendering a sparkline or trend chart. The
        final point is the current in-flight month, measured as of today, and is flagged
        with `is_current: true`.


        Data freshness: closed months are served from precomputed month-end snapshots
        that are refreshed nightly (the trailing three months are recomputed each
        night to absorb backdated entries). If a closed month has no snapshot yet,
        it is computed live as a fallback. The current month is always computed live.


        Authentication: Requires Bearer token. Scope: `reports` (read/write).'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      points:
                        type: array
                        items:
                          type: object
                          properties:
                            period_end_date:
                              type: string
                            unreceived:
                              type: number
                            is_current:
                              type: boolean
                example:
                  data:
                    points:
                    - period_end_date: '2026-02-28'
                      unreceived: 19875.1
                      is_current: false
                    - period_end_date: '2026-03-31'
                      unreceived: 22140.85
                      is_current: false
                    - period_end_date: '2026-04-30'
                      unreceived: 18320.0
                      is_current: false
                    - period_end_date: '2026-05-31'
                      unreceived: 27410.6
                      is_current: false
                    - period_end_date: '2026-06-30'
                      unreceived: 25199.5
                      is_current: false
                    - period_end_date: '2026-07-31'
                      unreceived: 23847.25
                      is_current: true
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      months:
                        type: array
                        items:
                          type: string
                example:
                  message: The months field must not be greater than 36.
                  errors:
                    months:
                    - The months field must not be greater than 36.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:read
      operationId: get-api-reporting-ginr-trend
  /api/reporting/ginr/breakdown:
    get:
      tags:
      - Reporting
      summary: Get GINR Breakdown
      description: 'GINR (Goods Invoiced, Not Received) — also called Accrued Purchases
        or GRNI — tracks the value of goods that suppliers have invoiced but that
        have not yet been received into inventory. The balance is calculated as: invoiced
        − received + discrepancies − adjustments, accumulated from the account''s
        inventory start date (so it behaves like a balance-sheet figure, not a period
        movement).


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Returns the per-purchase-order breakdown of the GINR balance as of a given
        month''s end (or an arbitrary date). Each row carries that PO''s cumulative
        invoiced/received/discrepancy/adjustments values and resulting balance; the
        rows sum to the same balance reported by the balance endpoint for the same
        date. Rows are sorted by descending absolute balance. By default, settled
        and fully-received purchase orders are hidden to reduce noise. Figures are
        computed live at request time.


        Authentication: Requires Bearer token. Scope: `reports` (read/write).'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      as_of_date:
                        type: string
                      items:
                        type: array
                        items:
                          type: object
                          properties:
                            purchase_order_id:
                              type: integer
                            purchase_order_number:
                              type: string
                            purchase_order_date:
                              type: string
                            supplier_name:
                              type: string
                            invoiced:
                              type: number
                            received:
                              type: number
                            discrepancy:
                              type: number
                            adjustments:
                              type: number
                            balance:
                              type: number
                            is_fully_received:
                              type: boolean
                      totals:
                        type: object
                        properties:
                          invoiced:
                            type: number
                          received:
                            type: number
                          discrepancy:
                            type: number
                          adjustments:
                            type: number
                          balance:
                            type: number
                example:
                  data:
                    as_of_date: '2026-06-30'
                    items:
                    - purchase_order_id: 412
                      purchase_order_number: PO-2041
                      purchase_order_date: '2026-04-12 00:00:00'
                      supplier_name: Shenzhen Lumina Electronics
                      invoiced: 42800.0
                      received: 21400.0
                      discrepancy: 0.0
                      adjustments: 0.0
                      balance: 21400.0
                      is_fully_received: false
                    - purchase_order_id: 448
                      purchase_order_number: PO-2087
                      purchase_order_date: '2026-05-03 00:00:00'
                      supplier_name: Pacific Coast Distributors
                      invoiced: 6120.0
                      received: 2295.0
                      discrepancy: -75.5
                      adjustments: 0.0
                      balance: 3749.5
                      is_fully_received: false
                    - purchase_order_id: 395
                      purchase_order_number: PO-1998
                      purchase_order_date: '2026-03-20 00:00:00'
                      supplier_name: Nordic Textiles AB
                      invoiced: 980.0
                      received: 890.0
                      discrepancy: 0.0
                      adjustments: 40.0
                      balance: 50.0
                      is_fully_received: false
                    totals:
                      invoiced: 49900.0
                      received: 24585.0
                      discrepancy: -75.5
                      adjustments: 40.0
                      balance: 25199.5
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      period:
                        type: array
                        items:
                          type: string
                example:
                  message: The period field format is invalid.
                  errors:
                    period:
                    - The period field format is invalid.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:read
      operationId: get-api-reporting-ginr-breakdown
  /api/reporting/ginr/aging:
    get:
      tags:
      - Reporting
      summary: Get GINR Aging
      description: 'GINR (Goods Invoiced, Not Received) — also called Accrued Purchases
        or GRNI — tracks the value of goods that suppliers have invoiced but that
        have not yet been received into inventory. The balance is calculated as: invoiced
        − received + discrepancies − adjustments, accumulated from the account''s
        inventory start date (so it behaves like a balance-sheet figure, not a period
        movement).


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Returns the aging breakdown of purchase orders that still carry a non-zero
        GINR balance as of the given date. Each PO''s age is measured in days from
        its earliest activity (first supplier invoice or first receipt) to the as-of
        date, and POs are grouped into fixed buckets: 0-30, 31-60, 61-90, 91-180,
        181-365, and 365+ days. Each bucket reports the PO count, the net balance,
        and the sum of absolute balances (so offsetting positive/negative balances
        remain visible). Figures are computed live at request time.


        Authentication: Requires Bearer token. Scope: `reports` (read/write).'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      as_of_date:
                        type: string
                      buckets:
                        type: array
                        items:
                          type: object
                          properties:
                            label:
                              type: string
                            min_days:
                              type: integer
                            max_days:
                              type: integer
                            po_count:
                              type: integer
                            total_balance:
                              type: number
                            absolute_balance:
                              type: number
                      totals:
                        type: object
                        properties:
                          po_count:
                            type: integer
                          total_balance:
                            type: number
                          absolute_balance:
                            type: number
                example:
                  data:
                    as_of_date: '2026-06-30'
                    buckets:
                    - label: 0-30 days
                      min_days: 0
                      max_days: 30
                      po_count: 4
                      total_balance: 8210.25
                      absolute_balance: 8210.25
                    - label: 31-60 days
                      min_days: 31
                      max_days: 60
                      po_count: 3
                      total_balance: 6485.0
                      absolute_balance: 6485.0
                    - label: 61-90 days
                      min_days: 61
                      max_days: 90
                      po_count: 2
                      total_balance: 5320.75
                      absolute_balance: 5320.75
                    - label: 91-180 days
                      min_days: 91
                      max_days: 180
                      po_count: 2
                      total_balance: 4890.5
                      absolute_balance: 4890.5
                    - label: 181-365 days
                      min_days: 181
                      max_days: 365
                      po_count: 1
                      total_balance: 293.0
                      absolute_balance: 293.0
                    - label: 365+ days
                      min_days: 366
                      max_days: null
                      po_count: 0
                      total_balance: 0.0
                      absolute_balance: 0.0
                    totals:
                      po_count: 12
                      total_balance: 25199.5
                      absolute_balance: 25199.5
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      as_of_date:
                        type: array
                        items:
                          type: string
                example:
                  message: The as of date field must be a valid date.
                  errors:
                    as_of_date:
                    - The as of date field must be a valid date.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:read
      operationId: get-api-reporting-ginr-aging
  /api/reporting/ginr/aging/drilldown:
    get:
      tags:
      - Reporting
      summary: Get GINR Aging Drilldown
      description: 'GINR (Goods Invoiced, Not Received) — also called Accrued Purchases
        or GRNI — tracks the value of goods that suppliers have invoiced but that
        have not yet been received into inventory. The balance is calculated as: invoiced
        − received + discrepancies − adjustments, accumulated from the account''s
        inventory start date (so it behaves like a balance-sheet figure, not a period
        movement).


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Lists the purchase orders that fall into a specific aging bucket as of a given
        date — the drill-through for a bucket returned by the aging endpoint. Each
        row includes the PO''s earliest activity date, its age in days, and the full
        per-metric breakdown (invoiced, received, discrepancy, adjustments, balance).
        Rows are sorted oldest first. Figures are computed live at request time.


        Authentication: Requires Bearer token. Scope: `reports` (read/write).'
      parameters:
      - name: min_days
        in: query
        schema:
          type: integer
        description: Required. Minimum age in days (inclusive, integer ≥ 0) of the
          bucket to drill into.
        example: '91'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      as_of_date:
                        type: string
                      bucket:
                        type: object
                        properties:
                          label:
                            type: string
                          min_days:
                            type: integer
                          max_days:
                            type: integer
                      items:
                        type: array
                        items:
                          type: object
                          properties:
                            purchase_order_id:
                              type: integer
                            purchase_order_number:
                              type: string
                            supplier_name:
                              type: string
                            earliest_activity_date:
                              type: string
                            age_days:
                              type: integer
                            invoiced:
                              type: number
                            received:
                              type: number
                            discrepancy:
                              type: number
                            adjustments:
                              type: number
                            balance:
                              type: number
                      totals:
                        type: object
                        properties:
                          po_count:
                            type: integer
                          total_balance:
                            type: number
                          absolute_balance:
                            type: number
                example:
                  data:
                    as_of_date: '2026-06-30'
                    bucket:
                      label: 91-180 days
                      min_days: 91
                      max_days: 180
                    items:
                    - purchase_order_id: 361
                      purchase_order_number: PO-1912
                      supplier_name: Nordic Textiles AB
                      earliest_activity_date: '2026-02-18 08:15:42'
                      age_days: 132
                      invoiced: 3200.0
                      received: 0.0
                      discrepancy: 0.0
                      adjustments: 0.0
                      balance: 3200.0
                    - purchase_order_id: 372
                      purchase_order_number: PO-1935
                      supplier_name: Guangzhou Homeware Co
                      earliest_activity_date: '2026-03-08 11:40:03'
                      age_days: 114
                      invoiced: 2140.5
                      received: 450.0
                      discrepancy: 0.0
                      adjustments: 0.0
                      balance: 1690.5
                    totals:
                      po_count: 2
                      total_balance: 4890.5
                      absolute_balance: 4890.5
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      min_days:
                        type: array
                        items:
                          type: string
                example:
                  message: The min days field is required.
                  errors:
                    min_days:
                    - The min days field is required.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:read
      operationId: get-api-reporting-ginr-aging-drilldown
  /api/reporting/ginr/drilldown:
    get:
      tags:
      - Reporting
      summary: Get GINR Drilldown
      description: 'GINR (Goods Invoiced, Not Received) — also called Accrued Purchases
        or GRNI — tracks the value of goods that suppliers have invoiced but that
        have not yet been received into inventory. The balance is calculated as: invoiced
        − received + discrepancies − adjustments, accumulated from the account''s
        inventory start date (so it behaves like a balance-sheet figure, not a period
        movement).


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Returns the raw backing records for one GINR component (metric) through a
        given date, optionally scoped to a single purchase order. Records cover the
        cumulative window from the account''s inventory start date through the as-of
        date, so the sum of each item''s `value` equals the matching aggregate figure
        from the balance/breakdown endpoints.


        The fields of each item vary by metric:

        - `invoiced` — supplier invoice lines (invoice reference, quantities, unit
        price, discount).

        - `received` — receipt lines from both warehouse receipts and Amazon FBA inbound
        ledger events (`receipt_source` is `warehouse_receipt` or `fba_ledger`), with
        the cost proration inputs used to value each receipt.

        - `discrepancy` — receiving-discrepancy journal postings (credit/debit lines).

        - `adjustments` — PO-linked inventory adjustment movements with the cost layer
        used to value them.


        Figures are computed live at request time.


        Authentication: Requires Bearer token. Scope: `reports` (read/write).'
      parameters:
      - name: metric
        in: query
        schema:
          type: string
        description: 'Required. Which GINR component to list the backing records for.
          One of: `invoiced`, `received`, `discrepancy`, `adjustments`.'
        example: invoiced
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 OK (metric=invoiced)
                  value:
                    data:
                      metric: invoiced
                      as_of_date: '2026-06-30'
                      purchase_order_id: null
                      items:
                      - invoice_line_id: 5211
                        purchase_invoice_id: 1287
                        invoice_reference: INV-88213
                        date: '2026-04-15 00:00:00'
                        purchase_order_id: 412
                        purchase_order_number: PO-2041
                        supplier_name: Shenzhen Lumina Electronics
                        purchase_order_line_id: 3320
                        product_sku: LED-STRIP-5M-RGB
                        product_name: 5m LED Light Strip - RGB
                        quantity_invoiced: 2000.0
                        unit_price: 21.4
                        po_line_amount: 21.4
                        po_line_quantity: 2000.0
                        discount_rate: 0.0
                        value: 42800.0
                      - invoice_line_id: 5304
                        purchase_invoice_id: 1301
                        invoice_reference: INV-88790
                        date: '2026-05-06 00:00:00'
                        purchase_order_id: 448
                        purchase_order_number: PO-2087
                        supplier_name: Pacific Coast Distributors
                        purchase_order_line_id: 3391
                        product_sku: GLOW-DESK-WAL
                        product_name: Desk Glow Lamp - Walnut
                        quantity_invoiced: 360.0
                        unit_price: 17.0
                        po_line_amount: 17.0
                        po_line_quantity: 360.0
                        discount_rate: 0.0
                        value: 6120.0
                      total: 48920.0
                example-1:
                  summary: 200 OK (metric=received)
                  value:
                    data:
                      metric: received
                      as_of_date: '2026-06-30'
                      purchase_order_id: 412
                      items:
                      - receipt_source: warehouse_receipt
                        receipt_line_id: 2210
                        receipt_id: 887
                        date: '2026-05-14 09:32:11'
                        purchase_order_id: 412
                        purchase_order_number: PO-2041
                        supplier_name: Shenzhen Lumina Electronics
                        purchase_order_line_id: 3320
                        product_sku: LED-STRIP-5M-RGB
                        product_name: 5m LED Light Strip - RGB
                        quantity_received: 500.0
                        po_line_quantity: 2000.0
                        po_line_amount: 21.4
                        discount_rate: 0.0
                        currency_rate: 1.0
                        is_tax_included: 0
                        tax_allocation: 0.0
                        product_total: 42800.0
                        additional_cost: 0.0
                        value: 10700.0
                      - receipt_source: fba_ledger
                        receipt_line_id: 91234
                        receipt_id: 91234
                        date: '2026-06-02 00:00:00'
                        purchase_order_id: 412
                        purchase_order_number: PO-2041
                        supplier_name: Shenzhen Lumina Electronics
                        purchase_order_line_id: 3320
                        product_sku: LED-STRIP-5M-RGB
                        product_name: 5m LED Light Strip - RGB
                        quantity_received: 500.0
                        po_line_quantity: 2000.0
                        po_line_amount: 21.4
                        discount_rate: 0.0
                        currency_rate: 1.0
                        is_tax_included: 0
                        tax_allocation: 0.0
                        product_total: 42800.0
                        additional_cost: 0.0
                        value: 10700.0
                      total: 21400.0
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      metric:
                        type: array
                        items:
                          type: string
                example:
                  message: The selected metric is invalid.
                  errors:
                    metric:
                    - The selected metric is invalid.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:read
      operationId: get-api-reporting-ginr-drilldown
  /api/reporting/ginr/po-receipts:
    get:
      tags:
      - Reporting
      summary: Get GINR PO Receipts
      description: 'GINR (Goods Invoiced, Not Received) — also called Accrued Purchases
        or GRNI — tracks the value of goods that suppliers have invoiced but that
        have not yet been received into inventory. The balance is calculated as: invoiced
        − received + discrepancies − adjustments, accumulated from the account''s
        inventory start date (so it behaves like a balance-sheet figure, not a period
        movement).


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Returns the full lifetime receiving history for a single purchase order, grouped
        by receipt date. Unlike the other GINR endpoints this is not bounded by an
        as-of date — it shows every receipt so you can see when and how much of the
        PO arrived. Each row includes the quantity and value received that day plus
        its share of the PO''s total value and quantity. Both warehouse receipts and
        Amazon FBA inbound receipts are included. Figures are computed live at request
        time.


        Authentication: Requires Bearer token. Scope: `reports` (read/write).'
      parameters:
      - name: purchase_order_id
        in: query
        schema:
          type: integer
        description: Required. The purchase order to list receipts for (must be an
          existing purchase order ID).
        example: '412'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      purchase_order_id:
                        type: integer
                      purchase_order_number:
                        type: string
                      supplier_name:
                        type: string
                      po_total_value:
                        type: number
                      po_total_quantity:
                        type: number
                      items:
                        type: array
                        items:
                          type: object
                          properties:
                            date:
                              type: string
                            received_at:
                              type: string
                            quantity_received:
                              type: number
                            value:
                              type: number
                            percent_of_po_value:
                              type: number
                            percent_of_po_quantity:
                              type: number
                      total_value:
                        type: number
                      total_quantity:
                        type: number
                example:
                  data:
                    purchase_order_id: 412
                    purchase_order_number: PO-2041
                    supplier_name: Shenzhen Lumina Electronics
                    po_total_value: 42800.0
                    po_total_quantity: 2000.0
                    items:
                    - date: '2026-05-14'
                      received_at: '2026-05-14 09:32:11'
                      quantity_received: 500.0
                      value: 10700.0
                      percent_of_po_value: 25.0
                      percent_of_po_quantity: 25.0
                    - date: '2026-06-02'
                      received_at: '2026-06-02 00:00:00'
                      quantity_received: 500.0
                      value: 10700.0
                      percent_of_po_value: 25.0
                      percent_of_po_quantity: 25.0
                    total_value: 21400.0
                    total_quantity: 1000.0
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      purchase_order_id:
                        type: array
                        items:
                          type: string
                example:
                  message: The selected purchase order id is invalid.
                  errors:
                    purchase_order_id:
                    - The selected purchase order id is invalid.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:read
      operationId: get-api-reporting-ginr-po-receipts
  /api/reporting/accounting/income-statement:
    get:
      tags:
      - Reporting
      summary: Get Accounting Income Statement
      description: 'Returns an income statement grouped by accounting nominal codes
        and period. Supports date filtering and period granularity.


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token'
      parameters:
      - name: period
        in: query
        schema:
          type: string
        description: 'Period grouping: month | year'
        example: month
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        nominal_code_id:
                          type: integer
                        nominal_code:
                          type: string
                        nominal_code_name:
                          type: string
                        nominal_code_type:
                          type: string
                        period_date:
                          type: string
                        total:
                          type: number
                example:
                  data:
                  - nominal_code_id: 10
                    nominal_code: '4000'
                    nominal_code_name: Sales Revenue
                    nominal_code_type: income
                    period_date: 2024-06
                    total: 45200.0
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:read
      operationId: get-api-reporting-accounting-income-statement
  /api/reporting/accounting/balance-sheet:
    get:
      tags:
      - Reporting
      summary: Get Accounting Balance Sheet
      description: 'Returns a balance sheet snapshot as of a date, built from the
        same accounting_transaction_lines data source as the income statement so the
        two reconcile.


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Accounts are grouped into assets (reported as net debit balance), liabilities
        and equity (reported as net credit balance). Cumulative net income is appended
        to equity as a computed "Retained Earnings" line so the statement balances
        (Assets = Liabilities + Equity).


        Also scoped by scope by object:reports`.


        Authentication: Requires Bearer token'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      as_of_date:
                        type: string
                      assets:
                        type: array
                        items:
                          type: object
                          properties:
                            nominal_code_id:
                              type: integer
                            nominal_code:
                              type: string
                            nominal_code_name:
                              type: string
                            nominal_code_type:
                              type: string
                            balance:
                              type: number
                            is_computed:
                              type: boolean
                      liabilities:
                        type: array
                        items:
                          type: object
                          properties:
                            nominal_code_id:
                              type: integer
                            nominal_code:
                              type: string
                            nominal_code_name:
                              type: string
                            nominal_code_type:
                              type: string
                            balance:
                              type: number
                            is_computed:
                              type: boolean
                      equity:
                        type: array
                        items:
                          type: object
                          properties:
                            nominal_code_id:
                              type: string
                              nullable: true
                            nominal_code:
                              type: string
                              nullable: true
                            nominal_code_name:
                              type: string
                            nominal_code_type:
                              type: string
                            balance:
                              type: number
                            is_computed:
                              type: boolean
                      totals:
                        type: object
                        properties:
                          assets:
                            type: number
                          liabilities:
                            type: number
                          equity:
                            type: number
                          liabilities_and_equity:
                            type: number
                          retained_earnings:
                            type: number
                          difference:
                            type: number
                          is_balanced:
                            type: boolean
                example:
                  data:
                    as_of_date: '2024-06-30'
                    assets:
                    - nominal_code_id: 1
                      nominal_code: '1000'
                      nominal_code_name: Bank
                      nominal_code_type: Bank
                      balance: 1000.0
                      is_computed: false
                    - nominal_code_id: 2
                      nominal_code: '1200'
                      nominal_code_name: Inventory
                      nominal_code_type: Inventory
                      balance: 200.0
                      is_computed: false
                    liabilities:
                    - nominal_code_id: 3
                      nominal_code: '2100'
                      nominal_code_name: Accounts Payable
                      nominal_code_type: Currliab
                      balance: 600.0
                      is_computed: false
                    equity:
                    - nominal_code_id: null
                      nominal_code: null
                      nominal_code_name: Retained Earnings
                      nominal_code_type: Equity
                      balance: 600.0
                      is_computed: true
                    totals:
                      assets: 1200.0
                      liabilities: 600.0
                      equity: 600.0
                      liabilities_and_equity: 1200.0
                      retained_earnings: 600.0
                      difference: 0.0
                      is_balanced: true
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Not Found
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:read
      operationId: get-api-reporting-accounting-balance-sheet
  /api/reporting/sales-channel-coverage/paginated:
    get:
      tags:
      - Reporting
      summary: Get Sales Channel Coverage
      description: 'Returns paginated sales channel coverage data per product using
        Spatie QueryBuilder. Shows which products are listed on which sales channels.


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token


        Filters: filter[search] (matches SKU OR supplier name), filter[product_types]
        (comma-separated: standard|blemished|kit), filter[integration_ids] (comma-separated),
        filter[instance_ids] (comma-separated)


        Flags:

        - by_integration (1/0) — group coverage by integration vs instance

        - show_count (1/0) — return numeric coverage counts vs boolean 0/1

        - in_stock_only (1/0) — restrict to products with on-hand stock at warehouse
        0 (default 1)


        Sort: sku, type, id'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        description: Page number
        example: '1'
      - name: per_page
        in: query
        schema:
          type: integer
        description: 'Items per page (default: 25)'
        example: '25'
      - name: by_integration
        in: query
        schema:
          type: integer
        description: '1 = group by integration, 0 = group by instance (default: 1)'
        example: '1'
      - name: show_count
        in: query
        schema:
          type: integer
        description: '1 = show coverage count, 0 = show boolean (default: 0)'
        example: '0'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        sku:
                          type: string
                        name:
                          type: string
                        supplier:
                          type: object
                          properties:
                            name:
                              type: string
                        type:
                          type: string
                        stock:
                          type: integer
                        valuation:
                          type: number
                        coverage:
                          type: object
                          properties:
                            Shopify:
                              type: integer
                            Amazon:
                              type: integer
                            WooCommerce:
                              type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 42
                    sku: WIDGET-001
                    name: Blue Widget
                    supplier:
                      name: Widget Co
                    type: standard
                    stock: 150
                    valuation: 1387.5
                    coverage:
                      Shopify: 1
                      Amazon: 0
                      WooCommerce: 1
                  per_page: 25
                  total: 342
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:read
      operationId: get-api-reporting-sales-channel-coverage-paginated
  /api/reporting/sales-channel-coverage:
    post:
      tags:
      - Reporting
      summary: Get Full Sales Channel Coverage
      description: 'Returns listing coverage for every product across the selected
        sales channels in a single unpaginated response. For each product you get
        its stock on hand, inventory valuation, default supplier, and a coverage map
        keyed by channel name plus a Total.


        :::info[Required scope: `reports:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Request fields (all required):

        - `byIntegration` (boolean) — true groups coverage by integration (e.g. all
        Amazon instances combined); false groups by individual integration instance.

        - `showNumberOfCoverages` (boolean) — true returns the count of active listings
        per channel; false returns a binary indicator (1 = listed, 0 = not listed).

        - `ids` (array of integers) — the integration IDs (when `byIntegration` is
        true) or integration instance IDs (when false) to include in the coverage
        calculation.


        Coverage for kit/bundle products includes listings of their parent products.
        This endpoint computes coverage for the entire catalog in one request and
        can be slow on large catalogs — prefer `GET /api/reporting/sales-channel-coverage/paginated`
        for interactive use.


        Authentication: Requires Bearer token. Scope: `reports` (read/write).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                byIntegration:
                  type: boolean
                showNumberOfCoverages:
                  type: boolean
                ids:
                  type: array
                  items:
                    type: integer
              example:
                byIntegration: true
                showNumberOfCoverages: false
                ids:
                - 1
                - 3
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        sku:
                          type: string
                        type:
                          type: string
                        stock:
                          type: integer
                        valuation:
                          type: number
                        supplier:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        coverage:
                          type: object
                          properties:
                            Amazon:
                              type: integer
                            Shopify:
                              type: integer
                            Total:
                              type: integer
                example:
                  data:
                  - id: 101
                    sku: TSHIRT-BLK-M
                    type: standard
                    stock: 240
                    valuation: 1820.5
                    supplier:
                      id: 3
                      name: Acme Apparel Co
                    coverage:
                      Amazon: 1
                      Shopify: 1
                      Total: 2
                  - id: 102
                    sku: TSHIRT-BLK-L
                    type: standard
                    stock: 0
                    valuation: 0
                    supplier:
                      id: 3
                      name: Acme Apparel Co
                    coverage:
                      Amazon: 0
                      Shopify: 1
                      Total: 1
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      byIntegration:
                        type: array
                        items:
                          type: string
                      showNumberOfCoverages:
                        type: array
                        items:
                          type: string
                      ids:
                        type: array
                        items:
                          type: string
                example:
                  message: The by integration field is required. (and 2 more errors)
                  errors:
                    byIntegration:
                    - The by integration field is required.
                    showNumberOfCoverages:
                    - The show number of coverages field is required.
                    ids:
                    - The ids field is required.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:write
      operationId: post-api-reporting-sales-channel-coverage
  /api/reporting/sales-channel-coverage/export:
    get:
      tags:
      - Reporting
      summary: Export Sales Channel Coverage (Async)
      description: 'Dispatches an async job (a background job) that builds the full
        unpaginated sales channel coverage CSV in the background. Returns immediately
        with a tracked_job_log_id that the frontend uses to poll progress via the
        tracked job log endpoints.


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token


        Flow:

        1. Client calls this endpoint with the same filters/flags supported by the
        paginated endpoint.

        2. Server queues the job and returns { data: { tracked_job_log_id }, message
        }.

        3. Frontend subscribes via the tracked job log endpoints; when job completes,
        log.results.file contains the filename on the model-exports disk.

        4. Client downloads the file via GET /api/export/download?file={filename}.


        CSV columns: SKU, Product Name, Supplier, Type, Stock, Valuation, Total Coverage,
        plus one column per integration (or instance when by_integration=0) covering
        the union of channels across all returned rows. Channel columns are computed
        from the union of all rows in the result set.'
      parameters:
      - name: by_integration
        in: query
        schema:
          type: integer
        description: '1 = group by integration, 0 = group by instance (default: 1)'
        example: '1'
      - name: show_count
        in: query
        schema:
          type: integer
        description: '1 = show coverage count, 0 = show boolean (default: 0)'
        example: '0'
      - name: in_stock_only
        in: query
        schema:
          type: integer
        description: 1 = only include products with stock at warehouse 0 (default),
          0 = include all products
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                  status:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 1234
                  message: Export started
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:read
      operationId: get-api-reporting-sales-channel-coverage-export
  /api/v2/reporting/release-schedule:
    get:
      tags:
      - Reporting
      summary: Get Release Schedule
      description: 'Forward-looking release schedule for held sales orders. Returns
        held orders (those with a future hold_until_date — a "do not ship before"
        release date, used for preorders and scheduled holds) grouped by the application-timezone
        date on which they become shippable.


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Orders are excluded if they have no hold, the hold has already passed, are
        cancelled (canceled_at set), or are closed. Buckets are ordered by hold_until_date
        ascending.


        This differs from Ship By Schedule: ship_by_date is a deadline ("ship no later
        than"), whereas hold_until_date is a floor ("do not ship before").


        Authentication: Requires Bearer token. Scope: reports (read/write).'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        hold_until_date:
                          type: string
                        order_count:
                          type: integer
                        orders:
                          type: array
                          items:
                            type: object
                            properties:
                              id:
                                type: integer
                              order_number:
                                type: string
                              channel:
                                type: string
                              order_status:
                                type: string
                              hold_until_date:
                                type: string
                              ship_by_date:
                                type: string
                              item_count:
                                type: integer
                example:
                  data:
                  - hold_until_date: '2026-05-23'
                    order_count: 2
                    orders:
                    - id: 10432
                      order_number: SO-10432
                      channel: Acme Shopify Store
                      order_status: reserved
                      hold_until_date: '2026-05-23T00:00:00+00:00'
                      ship_by_date: '2026-05-25T00:00:00+00:00'
                      item_count: 3
                    - id: 10455
                      order_number: SO-10455
                      channel: Acme Shopify Store
                      order_status: reserved
                      hold_until_date: '2026-05-23T00:00:00+00:00'
                      ship_by_date: '2026-05-26T00:00:00+00:00'
                      item_count: 1
                  - hold_until_date: '2026-06-01'
                    order_count: 1
                    orders:
                    - id: 10501
                      order_number: SO-10501
                      channel: Acme Shopify Store
                      order_status: reserved
                      hold_until_date: '2026-06-01T00:00:00+00:00'
                      ship_by_date: '2026-06-03T00:00:00+00:00'
                      item_count: 5
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:read
      operationId: get-api-v2-reporting-release-schedule
  /api/reporting/suppliers/overview:
    get:
      tags:
      - Reporting
      summary: Get Supplier Overview
      description: 'Macro supplier dashboard for the resolved period: headline KPIs
        (purchase volume, sales volume, profit, active suppliers), the hottest/coldest
        movers, a 12-month growth heatmap, and the full leaderboard. KPIs and trends
        are read from monthly supplier metric snapshots.


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token (scope: reports)


        Required parameters:

        - period_mode: yoy | qoq | mom | custom


        When period_mode=custom, date_from and date_to (YYYY-MM-DD or m/d/Y) are both
        required and date_to must be on or after date_from.


        Optional:

        - growth_basis: spend | sales | profit | margin (default: sales) — the basis
        used to rank movers and the heatmap

        - min_volume: numeric — minimum purchase volume before a supplier qualifies
        as a mover (default: 1000)

        - include_archived: boolean — include archived suppliers (default: false)'
      parameters:
      - name: period_mode
        in: query
        schema:
          type: string
        description: 'Required. Period comparison model: yoy | qoq | mom | custom'
        example: yoy
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      kpis:
                        type: object
                        properties:
                          purchase_volume:
                            type: object
                            properties:
                              current:
                                type: number
                              previous:
                                type: number
                              delta_pct:
                                type: number
                          sales_volume:
                            type: object
                            properties:
                              current:
                                type: number
                              previous:
                                type: number
                              delta_pct:
                                type: number
                          profit:
                            type: object
                            properties:
                              current:
                                type: number
                              previous:
                                type: number
                              delta_pct:
                                type: number
                          active_suppliers:
                            type: object
                            properties:
                              current:
                                type: integer
                              previous:
                                type: integer
                              delta_pct:
                                type: number
                      hottest:
                        type: array
                        items:
                          type: object
                          properties:
                            supplier_id:
                              type: integer
                            name:
                              type: string
                            value:
                              type: number
                            delta_pct:
                              type: number
                            spark:
                              type: array
                              items:
                                type: number
                      coldest:
                        type: array
                        items:
                          type: object
                          properties:
                            supplier_id:
                              type: integer
                            name:
                              type: string
                            value:
                              type: number
                            delta_pct:
                              type: number
                            spark:
                              type: array
                              items:
                                type: number
                      heatmap:
                        type: object
                        properties:
                          columns:
                            type: array
                            items:
                              type: string
                          rows:
                            type: array
                            items:
                              type: object
                              properties:
                                supplier_id:
                                  type: integer
                                name:
                                  type: string
                                cells:
                                  type: array
                                  items:
                                    type: string
                                    nullable: true
                      leaderboard:
                        type: array
                        items:
                          type: object
                          properties:
                            supplier_id:
                              type: integer
                            name:
                              type: string
                            purchase_volume:
                              type: number
                            sales_volume:
                              type: number
                            units_purchased:
                              type: integer
                            units_sold:
                              type: integer
                            profit:
                              type: number
                            margin_pct:
                              type: number
                            growth_pct:
                              type: number
                            active_po_count:
                              type: integer
                            po_count:
                              type: integer
                            is_low_volume:
                              type: boolean
                      meta:
                        type: object
                        properties:
                          data_as_of:
                            type: string
                          period_label:
                            type: string
                          current_range:
                            type: array
                            items:
                              type: string
                          previous_range:
                            type: array
                            items:
                              type: string
                          is_partial:
                            type: boolean
                          is_live_query:
                            type: boolean
                example:
                  data:
                    kpis:
                      purchase_volume:
                        current: 1842500.5
                        previous: 1640200.0
                        delta_pct: 12.3
                      sales_volume:
                        current: 3120900.0
                        previous: 2890400.0
                        delta_pct: 8.0
                      profit:
                        current: 961000.25
                        previous: 905100.0
                        delta_pct: 6.2
                      active_suppliers:
                        current: 48
                        previous: 45
                        delta_pct: 6.7
                    hottest:
                    - supplier_id: 42
                      name: Acme Components Ltd
                      value: 184250.5
                      delta_pct: 31.5
                      spark:
                      - 12000.0
                      - 13400.0
                      - 15600.0
                      - 14200.0
                      - 16800.0
                      - 17100.0
                      - 18900.0
                      - 16400.0
                      - 19200.0
                      - 21000.0
                      - 20400.0
                      - 22300.0
                    coldest:
                    - supplier_id: 71
                      name: Borealis Supply Co
                      value: 22400.0
                      delta_pct: -18.7
                      spark:
                      - 9100.0
                      - 8700.0
                      - 8200.0
                      - 7600.0
                      - 6900.0
                      - 6400.0
                      - 5800.0
                      - 5100.0
                      - 4700.0
                      - 4200.0
                      - 3900.0
                      - 3400.0
                    heatmap:
                      columns:
                      - 2025-06
                      - 2025-07
                      - 2025-08
                      - 2025-09
                      - 2025-10
                      - 2025-11
                      - 2025-12
                      - 2026-01
                      - 2026-02
                      - 2026-03
                      - 2026-04
                      - 2026-05
                      rows:
                      - supplier_id: 42
                        name: Acme Components Ltd
                        cells:
                        - null
                        - 8.2
                        - 12.4
                        - -3.1
                        - 6.7
                        - 9.0
                        - 14.2
                        - -2.4
                        - 5.5
                        - 11.0
                        - 7.8
                        - 12.4
                    leaderboard:
                    - supplier_id: 42
                      name: Acme Components Ltd
                      purchase_volume: 184250.5
                      sales_volume: 312900.0
                      units_purchased: 8400
                      units_sold: 7950
                      profit: 96100.25
                      margin_pct: 30.7
                      growth_pct: 12.4
                      active_po_count: 23
                      po_count: 21
                      is_low_volume: false
                    meta:
                      data_as_of: '2026-05-14T03:12:08+00:00'
                      period_label: YoY — May 2025 – May 2026 vs May 2024 – May 2025
                      current_range:
                      - '2025-05-16'
                      - '2026-05-15'
                      previous_range:
                      - '2024-05-16'
                      - '2025-05-15'
                      is_partial: false
                      is_live_query: false
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      period_mode:
                        type: array
                        items:
                          type: string
                      date_from:
                        type: array
                        items:
                          type: string
                example:
                  message: The given data was invalid.
                  errors:
                    period_mode:
                    - 'Period mode must be one of: yoy, qoq, mom, custom.'
                    date_from:
                    - A start date is required for a custom period.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:read
      operationId: get-api-reporting-suppliers-overview
  /api/reporting/suppliers/leaderboard:
    get:
      tags:
      - Reporting
      summary: Get Supplier Leaderboard
      description: 'Leaderboard rows only — a lightweight endpoint for table page/sort
        changes on the macro supplier view, without recomputing KPIs, movers, or the
        heatmap. Rows are computed in-memory from snapshots, then filtered, sorted
        and sliced; low-volume suppliers are flagged via is_low_volume.


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Server-paginated (PRD edge case 15: 500+ suppliers) — returns the standard
        Laravel pagination envelope (data, current_page, last_page, per_page, total,
        etc.).


        Authentication: Requires Bearer token (scope: reports)


        Required parameters:

        - period_mode: yoy | qoq | mom | custom


        When period_mode=custom, date_from and date_to (YYYY-MM-DD or m/d/Y) are both
        required.


        Optional:

        - growth_basis: spend | sales | profit | margin (default: sales)

        - min_volume: numeric — low-volume threshold (default: 1000)

        - include_archived: boolean (default: false)

        - sort: sort key, prefix - for DESC. Allowed: name, purchase_volume, sales_volume,
        units_purchased, units_sold, profit, margin_pct, growth_pct, active_po_count
        (default: -purchase_volume)

        - page: page number (default: 1)

        - per_page: rows per page (default: 10)

        - filter[search]: substring match on supplier name

        - filter[volume]: above | low — volume band filter'
      parameters:
      - name: period_mode
        in: query
        schema:
          type: string
        description: 'Required. Period comparison model: yoy | qoq | mom | custom'
        example: yoy
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        supplier_id:
                          type: integer
                        name:
                          type: string
                        purchase_volume:
                          type: number
                        sales_volume:
                          type: number
                        units_purchased:
                          type: integer
                        units_sold:
                          type: integer
                        profit:
                          type: number
                        margin_pct:
                          type: number
                        growth_pct:
                          type: number
                        active_po_count:
                          type: integer
                        po_count:
                          type: integer
                        is_low_volume:
                          type: boolean
                  current_page:
                    type: integer
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  next_page_url:
                    type: string
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - supplier_id: 42
                    name: Acme Components Ltd
                    purchase_volume: 184250.5
                    sales_volume: 312900.0
                    units_purchased: 8400
                    units_sold: 7950
                    profit: 96100.25
                    margin_pct: 30.7
                    growth_pct: 12.4
                    active_po_count: 23
                    po_count: 21
                    is_low_volume: false
                  - supplier_id: 71
                    name: Borealis Supply Co
                    purchase_volume: 22400.0
                    sales_volume: 41200.0
                    units_purchased: 980
                    units_sold: 910
                    profit: 9100.5
                    margin_pct: 22.1
                    growth_pct: -18.7
                    active_po_count: 4
                    po_count: 5
                    is_low_volume: false
                  current_page: 1
                  first_page_url: '{{protocol}}{{domain}}/api/reporting/suppliers/leaderboard?page=1'
                  from: 1
                  last_page: 5
                  last_page_url: '{{protocol}}{{domain}}/api/reporting/suppliers/leaderboard?page=5'
                  next_page_url: '{{protocol}}{{domain}}/api/reporting/suppliers/leaderboard?page=2'
                  path: '{{protocol}}{{domain}}/api/reporting/suppliers/leaderboard'
                  per_page: 10
                  prev_page_url: null
                  to: 10
                  total: 48
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      period_mode:
                        type: array
                        items:
                          type: string
                      date_from:
                        type: array
                        items:
                          type: string
                example:
                  message: The given data was invalid.
                  errors:
                    period_mode:
                    - 'Period mode must be one of: yoy, qoq, mom, custom.'
                    date_from:
                    - A start date is required for a custom period.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:read
      operationId: get-api-reporting-suppliers-leaderboard
  /api/reporting/suppliers/rebuild-snapshots:
    post:
      tags:
      - Reporting
      summary: Rebuild Supplier Metric Snapshots
      description: 'Dispatches the supplier-metric snapshot rebuild as a tracked background
        job and returns its tracked job log ID for progress polling via the tracked
        job log endpoints. Rejects a second dispatch with 409 while a rebuild is already
        queued or running.


        :::info[Required scope: `reports:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token (scope: reports)


        This endpoint takes no request body.


        Note: no request body is required.'
      requestBody:
        content:
          application/json:
            schema:
              type: string
              example: ''
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 90871
                  message: Supplier metric rebuild started.
        '409':
          description: Conflict
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: A supplier metric rebuild is already in progress.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: reports:write
      operationId: post-api-reporting-suppliers-rebuild-snapshots
  /api/reporting/suppliers/scorecard-settings:
    get:
      tags:
      - Reporting
      summary: Get Supplier Scorecard Settings
      description: 'Returns the tenant-global supplier scorecard configuration: the
        six dimension weights (sum to 100), the ordered {min, score} threshold bands
        per dimension, and the minimum in-period PO count required before a supplier
        is scored. A default row is created on first access if none exists.


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token (scope: reports)'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      weights:
                        type: object
                        properties:
                          on_time_delivery:
                            type: integer
                          lead_time_reliability:
                            type: integer
                          fill_rate:
                            type: integer
                          defect_rate:
                            type: integer
                          cost_competitiveness:
                            type: integer
                          price_stability:
                            type: integer
                      thresholds:
                        type: object
                        properties:
                          on_time_delivery:
                            type: array
                            items:
                              type: object
                              properties:
                                min:
                                  type: integer
                                score:
                                  type: integer
                          lead_time_reliability:
                            type: array
                            items:
                              type: object
                              properties:
                                min:
                                  type: integer
                                score:
                                  type: integer
                          fill_rate:
                            type: array
                            items:
                              type: object
                              properties:
                                min:
                                  type: integer
                                score:
                                  type: integer
                          defect_rate:
                            type: array
                            items:
                              type: object
                              properties:
                                min:
                                  type: integer
                                score:
                                  type: integer
                          cost_competitiveness:
                            type: array
                            items:
                              type: object
                              properties:
                                min:
                                  type: integer
                                score:
                                  type: integer
                          price_stability:
                            type: array
                            items:
                              type: object
                              properties:
                                min:
                                  type: integer
                                score:
                                  type: integer
                      min_po_count:
                        type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 1
                    weights:
                      on_time_delivery: 25
                      lead_time_reliability: 15
                      fill_rate: 15
                      defect_rate: 15
                      cost_competitiveness: 25
                      price_stability: 5
                    thresholds:
                      on_time_delivery:
                      - min: 97
                        score: 5
                      - min: 90
                        score: 4
                      - min: 80
                        score: 3
                      - min: 60
                        score: 2
                      - min: 0
                        score: 1
                      lead_time_reliability:
                      - min: 97
                        score: 5
                      - min: 90
                        score: 4
                      - min: 80
                        score: 3
                      - min: 60
                        score: 2
                      - min: 0
                        score: 1
                      fill_rate:
                      - min: 97
                        score: 5
                      - min: 90
                        score: 4
                      - min: 80
                        score: 3
                      - min: 60
                        score: 2
                      - min: 0
                        score: 1
                      defect_rate:
                      - min: 97
                        score: 5
                      - min: 90
                        score: 4
                      - min: 80
                        score: 3
                      - min: 60
                        score: 2
                      - min: 0
                        score: 1
                      cost_competitiveness:
                      - min: 97
                        score: 5
                      - min: 90
                        score: 4
                      - min: 80
                        score: 3
                      - min: 60
                        score: 2
                      - min: 0
                        score: 1
                      price_stability:
                      - min: 97
                        score: 5
                      - min: 90
                        score: 4
                      - min: 80
                        score: 3
                      - min: 60
                        score: 2
                      - min: 0
                        score: 1
                    min_po_count: 3
                    created_at: '2026-01-04T09:00:00.000000Z'
                    updated_at: '2026-05-10T14:22:31.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:read
      operationId: get-api-reporting-suppliers-scorecard-settings
    put:
      tags:
      - Reporting
      summary: Update Supplier Scorecard Settings
      description: 'Updates the tenant-global supplier scorecard configuration. The
        six weights must each be present and sum to exactly 100; every threshold band
        needs a numeric min and an integer 1-5 score.


        :::info[Required scope: `reports:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token (scope: reports)


        Request body fields:

        - weights: object (required) — must contain all six metric keys; values numeric
        0-100, summing to exactly 100

        - weights.on_time_delivery: numeric, 0-100 (required)

        - weights.lead_time_reliability: numeric, 0-100 (required)

        - weights.fill_rate: numeric, 0-100 (required)

        - weights.defect_rate: numeric, 0-100 (required)

        - weights.cost_competitiveness: numeric, 0-100 (required)

        - weights.price_stability: numeric, 0-100 (required)

        - thresholds: object (required) — must contain all six metric keys

        - thresholds.{metric}: array, min 1 item (required) — ordered {min, score}
        bands

        - thresholds.{metric}.*.min: numeric (required) — lower bound of the band

        - thresholds.{metric}.*.score: integer 1-5 (required) — score awarded for
        the band

        - min_po_count: integer, min 1 (required)'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                weights:
                  type: object
                  properties:
                    on_time_delivery:
                      type: integer
                    lead_time_reliability:
                      type: integer
                    fill_rate:
                      type: integer
                    defect_rate:
                      type: integer
                    cost_competitiveness:
                      type: integer
                    price_stability:
                      type: integer
                thresholds:
                  type: object
                  properties:
                    on_time_delivery:
                      type: array
                      items:
                        type: object
                        properties:
                          min:
                            type: integer
                          score:
                            type: integer
                    lead_time_reliability:
                      type: array
                      items:
                        type: object
                        properties:
                          min:
                            type: integer
                          score:
                            type: integer
                    fill_rate:
                      type: array
                      items:
                        type: object
                        properties:
                          min:
                            type: integer
                          score:
                            type: integer
                    defect_rate:
                      type: array
                      items:
                        type: object
                        properties:
                          min:
                            type: integer
                          score:
                            type: integer
                    cost_competitiveness:
                      type: array
                      items:
                        type: object
                        properties:
                          min:
                            type: integer
                          score:
                            type: integer
                    price_stability:
                      type: array
                      items:
                        type: object
                        properties:
                          min:
                            type: integer
                          score:
                            type: integer
                min_po_count:
                  type: integer
              example:
                weights:
                  on_time_delivery: 25
                  lead_time_reliability: 15
                  fill_rate: 15
                  defect_rate: 15
                  cost_competitiveness: 25
                  price_stability: 5
                thresholds:
                  on_time_delivery:
                  - min: 97
                    score: 5
                  - min: 90
                    score: 4
                  - min: 80
                    score: 3
                  - min: 60
                    score: 2
                  - min: 0
                    score: 1
                  lead_time_reliability:
                  - min: 97
                    score: 5
                  - min: 90
                    score: 4
                  - min: 80
                    score: 3
                  - min: 60
                    score: 2
                  - min: 0
                    score: 1
                  fill_rate:
                  - min: 97
                    score: 5
                  - min: 90
                    score: 4
                  - min: 80
                    score: 3
                  - min: 60
                    score: 2
                  - min: 0
                    score: 1
                  defect_rate:
                  - min: 97
                    score: 5
                  - min: 90
                    score: 4
                  - min: 80
                    score: 3
                  - min: 60
                    score: 2
                  - min: 0
                    score: 1
                  cost_competitiveness:
                  - min: 97
                    score: 5
                  - min: 90
                    score: 4
                  - min: 80
                    score: 3
                  - min: 60
                    score: 2
                  - min: 0
                    score: 1
                  price_stability:
                  - min: 97
                    score: 5
                  - min: 90
                    score: 4
                  - min: 80
                    score: 3
                  - min: 60
                    score: 2
                  - min: 0
                    score: 1
                min_po_count: 3
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      weights:
                        type: object
                        properties:
                          on_time_delivery:
                            type: integer
                          lead_time_reliability:
                            type: integer
                          fill_rate:
                            type: integer
                          defect_rate:
                            type: integer
                          cost_competitiveness:
                            type: integer
                          price_stability:
                            type: integer
                      thresholds:
                        type: object
                        properties:
                          on_time_delivery:
                            type: array
                            items:
                              type: object
                              properties:
                                min:
                                  type: integer
                                score:
                                  type: integer
                          lead_time_reliability:
                            type: array
                            items:
                              type: object
                              properties:
                                min:
                                  type: integer
                                score:
                                  type: integer
                          fill_rate:
                            type: array
                            items:
                              type: object
                              properties:
                                min:
                                  type: integer
                                score:
                                  type: integer
                          defect_rate:
                            type: array
                            items:
                              type: object
                              properties:
                                min:
                                  type: integer
                                score:
                                  type: integer
                          cost_competitiveness:
                            type: array
                            items:
                              type: object
                              properties:
                                min:
                                  type: integer
                                score:
                                  type: integer
                          price_stability:
                            type: array
                            items:
                              type: object
                              properties:
                                min:
                                  type: integer
                                score:
                                  type: integer
                      min_po_count:
                        type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 1
                    weights:
                      on_time_delivery: 25
                      lead_time_reliability: 15
                      fill_rate: 15
                      defect_rate: 15
                      cost_competitiveness: 25
                      price_stability: 5
                    thresholds:
                      on_time_delivery:
                      - min: 97
                        score: 5
                      - min: 90
                        score: 4
                      - min: 80
                        score: 3
                      - min: 60
                        score: 2
                      - min: 0
                        score: 1
                      lead_time_reliability:
                      - min: 97
                        score: 5
                      - min: 90
                        score: 4
                      - min: 80
                        score: 3
                      - min: 60
                        score: 2
                      - min: 0
                        score: 1
                      fill_rate:
                      - min: 97
                        score: 5
                      - min: 90
                        score: 4
                      - min: 80
                        score: 3
                      - min: 60
                        score: 2
                      - min: 0
                        score: 1
                      defect_rate:
                      - min: 97
                        score: 5
                      - min: 90
                        score: 4
                      - min: 80
                        score: 3
                      - min: 60
                        score: 2
                      - min: 0
                        score: 1
                      cost_competitiveness:
                      - min: 97
                        score: 5
                      - min: 90
                        score: 4
                      - min: 80
                        score: 3
                      - min: 60
                        score: 2
                      - min: 0
                        score: 1
                      price_stability:
                      - min: 97
                        score: 5
                      - min: 90
                        score: 4
                      - min: 80
                        score: 3
                      - min: 60
                        score: 2
                      - min: 0
                        score: 1
                    min_po_count: 3
                    created_at: '2026-01-04T09:00:00.000000Z'
                    updated_at: '2026-05-10T14:22:31.000000Z'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      weights:
                        type: array
                        items:
                          type: string
                      min_po_count:
                        type: array
                        items:
                          type: string
                      thresholds.fill_rate:
                        type: array
                        items:
                          type: string
                example:
                  message: The given data was invalid.
                  errors:
                    weights:
                    - Scorecard weights must sum to exactly 100 (currently 95).
                    min_po_count:
                    - The minimum PO count must be at least 1.
                    thresholds.fill_rate:
                    - Threshold bands are required for every scorecard metric.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:write
      operationId: put-api-reporting-suppliers-scorecard-settings
  /api/reporting/suppliers/{supplier}/scorecard-summary:
    get:
      tags:
      - Reporting
      summary: Get Supplier Scorecard Summary
      description: 'Lightweight scorecard + volume sparklines for the supplier Profile
        chip. Returns the composite scorecard with its dimension breakdown, a directional
        composite trend hint (up | down | flat), and trailing-12-month purchase/sales
        volume sparklines. The period is fixed to YoY.


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token (scope: reports)


        Path parameters:

        - supplier: the Supplier ID'
      parameters:
      - name: supplier
        in: path
        schema:
          type: string
        required: true
        description: The supplier ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      supplier:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      scorecard:
                        type: object
                        properties:
                          composite:
                            type: number
                          band:
                            type: string
                          is_sufficient:
                            type: boolean
                          po_count:
                            type: integer
                          dimensions:
                            type: array
                            items:
                              type: object
                              properties:
                                key:
                                  type: string
                                label:
                                  type: string
                                raw:
                                  type: number
                                raw_display:
                                  type: string
                                score:
                                  type: integer
                                weight:
                                  type: number
                      composite_trend:
                        type: string
                      purchase_volume:
                        type: object
                        properties:
                          current:
                            type: number
                          previous:
                            type: number
                          delta_pct:
                            type: number
                          spark:
                            type: array
                            items:
                              type: number
                      sales_volume:
                        type: object
                        properties:
                          current:
                            type: number
                          previous:
                            type: number
                          delta_pct:
                            type: number
                          spark:
                            type: array
                            items:
                              type: number
                      meta:
                        type: object
                        properties:
                          data_as_of:
                            type: string
                          period_label:
                            type: string
                          current_range:
                            type: array
                            items:
                              type: string
                          previous_range:
                            type: array
                            items:
                              type: string
                          is_partial:
                            type: boolean
                          is_live_query:
                            type: boolean
                example:
                  data:
                    supplier:
                      id: 42
                      name: Acme Components Ltd
                    scorecard:
                      composite: 4.15
                      band: good
                      is_sufficient: true
                      po_count: 18
                      dimensions:
                      - key: on_time_delivery
                        label: On-Time Delivery
                        raw: 92.3
                        raw_display: 92.3%
                        score: 4
                        weight: 25.0
                      - key: lead_time_reliability
                        label: Lead-Time Reliability
                        raw: 88.0
                        raw_display: 88.0%
                        score: 3
                        weight: 15.0
                      - key: fill_rate
                        label: Fill Rate
                        raw: 98.6
                        raw_display: 98.6%
                        score: 5
                        weight: 15.0
                      - key: defect_rate
                        label: Defect / RTV Rate
                        raw: 1.2
                        raw_display: 1.2%
                        score: 5
                        weight: 15.0
                      - key: cost_competitiveness
                        label: Cost Competitiveness
                        raw: 74.5
                        raw_display: 74.5 / 100
                        score: 3
                        weight: 25.0
                      - key: price_stability
                        label: Price Stability
                        raw: 0.18
                        raw_display: 18% price increases
                        score: 4
                        weight: 5.0
                    composite_trend: up
                    purchase_volume:
                      current: 184250.5
                      previous: 158900.0
                      delta_pct: 16.0
                      spark:
                      - 12000.0
                      - 13400.0
                      - 15600.0
                      - 14200.0
                      - 16800.0
                      - 17100.0
                      - 18900.0
                      - 16400.0
                      - 19200.0
                      - 21000.0
                      - 20400.0
                      - 22300.0
                    sales_volume:
                      current: 312900.0
                      previous: 289400.0
                      delta_pct: 8.1
                      spark:
                      - 22000.0
                      - 23100.0
                      - 24800.0
                      - 25600.0
                      - 26100.0
                      - 27400.0
                      - 26900.0
                      - 28200.0
                      - 29400.0
                      - 30100.0
                      - 31200.0
                      - 32400.0
                    meta:
                      data_as_of: '2026-05-14T03:12:08+00:00'
                      period_label: YoY — May 2025 – May 2026 vs May 2024 – May 2025
                      current_range:
                      - '2025-05-16'
                      - '2026-05-15'
                      previous_range:
                      - '2024-05-16'
                      - '2025-05-15'
                      is_partial: false
                      is_live_query: false
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No query results for model [App\Models\Supplier].
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:read
      operationId: get-api-reporting-suppliers-supplier-scorecard-summary
  /api/reporting/suppliers/{supplier}/analytics:
    get:
      tags:
      - Reporting
      summary: Get Supplier Analytics
      description: 'Full per-supplier analytics for the Analytics tab: headline KPIs
        (purchase volume, sales volume, units purchased/sold, profit, margin %), the
        composite scorecard, a dual-line current-vs-previous trend chart, and the
        hottest/coolest products ranked by growth.


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token (scope: reports)


        Path parameters:

        - supplier: the Supplier ID


        Required parameters:

        - period_mode: yoy | qoq | mom | custom


        When period_mode=custom, date_from and date_to (YYYY-MM-DD or m/d/Y) are both
        required.


        Optional:

        - growth_basis: spend | sales | profit | margin (default: sales) — drives
        the trend metric and product mover ranking

        - min_volume: numeric (default: 1000)

        - include_archived: boolean (default: false)


        The response also includes `product_heatmap` (a period-aware per-product growth
        heatmap — the supplier''s top products by volume, each cell a period-over-period
        change that follows the `period_mode` selector) and `calendar_year_volume`
        (per calendar year for the trailing 5 years: non-draft PO spend with units/PO
        counts plus non-draft sales revenue with units/order counts; the current year
        is year-to-date and is independent of `period_mode`).'
      parameters:
      - name: period_mode
        in: query
        schema:
          type: string
        description: 'Required. Period comparison model: yoy | qoq | mom | custom'
        example: yoy
      - name: supplier
        in: path
        schema:
          type: string
        required: true
        description: The supplier ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      supplier:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      kpis:
                        type: object
                        properties:
                          purchase_volume:
                            type: object
                            properties:
                              current:
                                type: number
                              previous:
                                type: number
                              delta_pct:
                                type: number
                          sales_volume:
                            type: object
                            properties:
                              current:
                                type: number
                              previous:
                                type: number
                              delta_pct:
                                type: number
                          units_purchased:
                            type: object
                            properties:
                              current:
                                type: integer
                              previous:
                                type: integer
                              delta_pct:
                                type: number
                          units_sold:
                            type: object
                            properties:
                              current:
                                type: integer
                              previous:
                                type: integer
                              delta_pct:
                                type: number
                          profit:
                            type: object
                            properties:
                              current:
                                type: number
                              previous:
                                type: number
                              delta_pct:
                                type: number
                          margin_pct:
                            type: object
                            properties:
                              current:
                                type: number
                              previous:
                                type: number
                              delta_pct:
                                type: number
                      scorecard:
                        type: object
                        properties:
                          composite:
                            type: number
                          band:
                            type: string
                          is_sufficient:
                            type: boolean
                          po_count:
                            type: integer
                          dimensions:
                            type: array
                            items:
                              type: object
                              properties:
                                key:
                                  type: string
                                label:
                                  type: string
                                raw:
                                  type: number
                                raw_display:
                                  type: string
                                score:
                                  type: integer
                                weight:
                                  type: number
                      trend:
                        type: object
                        properties:
                          metric:
                            type: string
                          buckets:
                            type: array
                            items:
                              type: string
                          current:
                            type: array
                            items:
                              type: number
                          previous:
                            type: array
                            items:
                              type: number
                      hottest_products:
                        type: array
                        items:
                          type: object
                          properties:
                            product_id:
                              type: integer
                            sku:
                              type: string
                            name:
                              type: string
                            value:
                              type: number
                            delta_pct:
                              type: number
                      coolest_products:
                        type: array
                        items:
                          type: object
                          properties:
                            product_id:
                              type: integer
                            sku:
                              type: string
                            name:
                              type: string
                            value:
                              type: number
                            delta_pct:
                              type: number
                      product_heatmap:
                        type: object
                        properties:
                          columns:
                            type: array
                            items:
                              type: string
                          rows:
                            type: array
                            items:
                              type: object
                              properties:
                                product_id:
                                  type: integer
                                sku:
                                  type: string
                                name:
                                  type: string
                                cells:
                                  type: array
                                  items:
                                    type: object
                                    properties:
                                      delta:
                                        type: string
                                        nullable: true
                                      current_value:
                                        type: number
                                      previous_value:
                                        type: string
                                        nullable: true
                                      compare_period:
                                        type: string
                      calendar_year_volume:
                        type: array
                        items:
                          type: object
                          properties:
                            year:
                              type: integer
                            purchase_volume:
                              type: number
                            units_purchased:
                              type: integer
                            po_count:
                              type: integer
                            sales_volume:
                              type: number
                            units_sold:
                              type: integer
                            so_count:
                              type: integer
                      meta:
                        type: object
                        properties:
                          data_as_of:
                            type: string
                          period_label:
                            type: string
                          current_range:
                            type: array
                            items:
                              type: string
                          previous_range:
                            type: array
                            items:
                              type: string
                          is_partial:
                            type: boolean
                          is_live_query:
                            type: boolean
                example:
                  data:
                    supplier:
                      id: 42
                      name: Acme Components Ltd
                    kpis:
                      purchase_volume:
                        current: 184250.5
                        previous: 158900.0
                        delta_pct: 16.0
                      sales_volume:
                        current: 312900.0
                        previous: 289400.0
                        delta_pct: 8.1
                      units_purchased:
                        current: 8400
                        previous: 7600
                        delta_pct: 10.5
                      units_sold:
                        current: 7950
                        previous: 7400
                        delta_pct: 7.4
                      profit:
                        current: 96100.25
                        previous: 88200.0
                        delta_pct: 9.0
                      margin_pct:
                        current: 30.7
                        previous: 30.5
                        delta_pct: 0.2
                    scorecard:
                      composite: 4.15
                      band: good
                      is_sufficient: true
                      po_count: 18
                      dimensions:
                      - key: on_time_delivery
                        label: On-Time Delivery
                        raw: 92.3
                        raw_display: 92.3%
                        score: 4
                        weight: 25.0
                      - key: lead_time_reliability
                        label: Lead-Time Reliability
                        raw: 88.0
                        raw_display: 88.0%
                        score: 3
                        weight: 15.0
                      - key: fill_rate
                        label: Fill Rate
                        raw: 98.6
                        raw_display: 98.6%
                        score: 5
                        weight: 15.0
                      - key: defect_rate
                        label: Defect / RTV Rate
                        raw: 1.2
                        raw_display: 1.2%
                        score: 5
                        weight: 15.0
                      - key: cost_competitiveness
                        label: Cost Competitiveness
                        raw: 74.5
                        raw_display: 74.5 / 100
                        score: 3
                        weight: 25.0
                      - key: price_stability
                        label: Price Stability
                        raw: 0.18
                        raw_display: 18% price increases
                        score: 4
                        weight: 5.0
                    trend:
                      metric: sales
                      buckets:
                      - 2025-05
                      - 2025-06
                      - 2025-07
                      - 2025-08
                      - 2025-09
                      - 2025-10
                      - 2025-11
                      - 2025-12
                      - 2026-01
                      - 2026-02
                      - 2026-03
                      - 2026-04
                      current:
                      - 14200.0
                      - 15600.0
                      - 16800.0
                      - 17100.0
                      - 18900.0
                      - 16400.0
                      - 19200.0
                      - 21000.0
                      - 20400.0
                      - 22300.0
                      - 21800.0
                      - 23400.0
                      previous:
                      - 12100.0
                      - 13400.0
                      - 14000.0
                      - 14900.0
                      - 15600.0
                      - 14100.0
                      - 16800.0
                      - 18200.0
                      - 17900.0
                      - 19400.0
                      - 18800.0
                      - 20100.0
                    hottest_products:
                    - product_id: 9001
                      sku: ACM-WIDGET-01
                      name: Widget Assembly Type A
                      value: 42100.0
                      delta_pct: 34.2
                    coolest_products:
                    - product_id: 9044
                      sku: ACM-BRACKET-12
                      name: Mounting Bracket XL
                      value: 6200.0
                      delta_pct: -21.8
                    product_heatmap:
                      columns:
                      - 2025-05
                      - 2025-06
                      - 2025-07
                      - 2025-08
                      - 2025-09
                      - 2025-10
                      - 2025-11
                      - 2025-12
                      - 2026-01
                      - 2026-02
                      - 2026-03
                      - 2026-04
                      rows:
                      - product_id: 9001
                        sku: ACM-WIDGET-01
                        name: Widget Assembly Type A
                        cells:
                        - delta: null
                          current_value: 11800.0
                          previous_value: null
                          compare_period: 2024-05
                        - delta: 12.4
                          current_value: 13300.0
                          previous_value: 11830.0
                          compare_period: 2024-06
                        - delta: 8.1
                          current_value: 14380.0
                          previous_value: 13300.0
                          compare_period: 2024-07
                        - delta: -3.2
                          current_value: 13920.0
                          previous_value: 14380.0
                          compare_period: 2024-08
                        - delta: 19.5
                          current_value: 16640.0
                          previous_value: 13920.0
                          compare_period: 2024-09
                        - delta: -6.7
                          current_value: 15520.0
                          previous_value: 16640.0
                          compare_period: 2024-10
                        - delta: 22.0
                          current_value: 18940.0
                          previous_value: 15520.0
                          compare_period: 2024-11
                        - delta: 9.3
                          current_value: 20700.0
                          previous_value: 18940.0
                          compare_period: 2024-12
                        - delta: -2.4
                          current_value: 20200.0
                          previous_value: 20700.0
                          compare_period: 2025-01
                        - delta: 10.4
                          current_value: 22300.0
                          previous_value: 20200.0
                          compare_period: 2025-02
                        - delta: -2.2
                          current_value: 21800.0
                          previous_value: 22300.0
                          compare_period: 2025-03
                        - delta: 7.3
                          current_value: 23400.0
                          previous_value: 21800.0
                          compare_period: 2025-04
                    calendar_year_volume:
                    - year: 2022
                      purchase_volume: 142300.0
                      units_purchased: 6100
                      po_count: 12
                      sales_volume: 238700.0
                      units_sold: 5840
                      so_count: 214
                    - year: 2023
                      purchase_volume: 168900.0
                      units_purchased: 7050
                      po_count: 14
                      sales_volume: 281400.0
                      units_sold: 6720
                      so_count: 248
                    - year: 2024
                      purchase_volume: 191450.0
                      units_purchased: 7780
                      po_count: 16
                      sales_volume: 309600.0
                      units_sold: 7410
                      so_count: 271
                    - year: 2025
                      purchase_volume: 224800.0
                      units_purchased: 8640
                      po_count: 19
                      sales_volume: 352100.0
                      units_sold: 8190
                      so_count: 305
                    - year: 2026
                      purchase_volume: 86200.0
                      units_purchased: 3320
                      po_count: 7
                      sales_volume: 131900.0
                      units_sold: 3040
                      so_count: 118
                    meta:
                      data_as_of: '2026-05-14T03:12:08+00:00'
                      period_label: YoY — May 2025 – May 2026 vs May 2024 – May 2025
                      current_range:
                      - '2025-05-16'
                      - '2026-05-15'
                      previous_range:
                      - '2024-05-16'
                      - '2025-05-15'
                      is_partial: false
                      is_live_query: false
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No query results for model [App\Models\Supplier].
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      period_mode:
                        type: array
                        items:
                          type: string
                      date_from:
                        type: array
                        items:
                          type: string
                example:
                  message: The given data was invalid.
                  errors:
                    period_mode:
                    - 'Period mode must be one of: yoy, qoq, mom, custom.'
                    date_from:
                    - A start date is required for a custom period.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:read
      operationId: get-api-reporting-suppliers-supplier-analytics
  /api/reporting/suppliers/{supplier}/products:
    get:
      tags:
      - Reporting
      summary: Get Supplier Product Breakdown
      description: 'Paginated, sortable per-product breakdown for one supplier (Analytics-tab
        product table). Each row carries units, purchase/sales volume, profit, margin
        %, sell-through %, landed unit cost, the landed-cost trend direction (cost_trend),
        and period-over-period growth %.


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token (scope: reports)


        Path parameters:

        - supplier: the Supplier ID


        Required parameters:

        - period_mode: yoy | qoq | mom | custom


        When period_mode=custom, date_from and date_to (YYYY-MM-DD or m/d/Y) are both
        required.


        Filters (Spatie QueryBuilder):

        - filter[search]: partial match on product SKU or name

        - filter[cost_trend]: landed-unit-cost trend direction — up | down | flat

        - filter[margin]: margin sign — positive (margin > 0) | negative (margin <
        0)


        Sort (sort param, prefix - for DESC). Allowed: units_purchased, units_sold,
        purchase_volume, sales_volume, profit, margin_pct, sell_through_pct, growth_pct.
        Default: -purchase_volume


        Pagination: page (default 1), per_page (default 10).


        Optional:

        - growth_basis: spend | sales | profit | margin (default: sales) — drives
        the growth_pct column

        - min_volume, include_archived


        Response field cost_trend: up | down | flat — direction of the landed unit
        cost vs the prior period (always present, defaults to flat).'
      parameters:
      - name: period_mode
        in: query
        schema:
          type: string
        description: 'Required. Period comparison model: yoy | qoq | mom | custom'
        example: yoy
      - name: supplier
        in: path
        schema:
          type: string
        required: true
        description: The supplier ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        product_id:
                          type: integer
                        sku:
                          type: string
                        name:
                          type: string
                        units_purchased:
                          type: integer
                        units_sold:
                          type: integer
                        purchase_volume:
                          type: number
                        sales_volume:
                          type: number
                        profit:
                          type: number
                        margin_pct:
                          type: number
                        sell_through_pct:
                          type: number
                        landed_unit_cost:
                          type: number
                        cost_trend:
                          type: string
                        growth_pct:
                          type: number
                  current_page:
                    type: integer
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  next_page_url:
                    type: string
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - product_id: 9001
                    sku: ACM-WIDGET-01
                    name: Widget Assembly Type A
                    units_purchased: 3200
                    units_sold: 3050
                    purchase_volume: 42100.0
                    sales_volume: 78900.0
                    profit: 24600.0
                    margin_pct: 31.2
                    sell_through_pct: 95.3
                    landed_unit_cost: 13.16
                    cost_trend: up
                    growth_pct: 34.2
                  - product_id: 9044
                    sku: ACM-BRACKET-12
                    name: Mounting Bracket XL
                    units_purchased: 540
                    units_sold: 410
                    purchase_volume: 6200.0
                    sales_volume: 9800.0
                    profit: 2100.0
                    margin_pct: 21.4
                    sell_through_pct: 75.9
                    landed_unit_cost: 11.48
                    cost_trend: down
                    growth_pct: -21.8
                  current_page: 1
                  first_page_url: '{{protocol}}{{domain}}/api/reporting/suppliers/42/products?page=1'
                  from: 1
                  last_page: 5
                  last_page_url: '{{protocol}}{{domain}}/api/reporting/suppliers/42/products?page=5'
                  next_page_url: '{{protocol}}{{domain}}/api/reporting/suppliers/42/products?page=2'
                  path: '{{protocol}}{{domain}}/api/reporting/suppliers/42/products'
                  per_page: 10
                  prev_page_url: null
                  to: 10
                  total: 47
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No query results for model [App\Models\Supplier].
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      period_mode:
                        type: array
                        items:
                          type: string
                      date_from:
                        type: array
                        items:
                          type: string
                example:
                  message: The given data was invalid.
                  errors:
                    period_mode:
                    - 'Period mode must be one of: yoy, qoq, mom, custom.'
                    date_from:
                    - A start date is required for a custom period.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:read
      operationId: get-api-reporting-suppliers-supplier-products
  /api/reporting/suppliers/{supplier}/products/{product}:
    get:
      tags:
      - Reporting
      summary: Get Supplier Product Drilldown
      description: 'Single-product drill-down for one supplier: current vs previous
        purchase/sales totals, a landed-cost-per-receipt trend, and the list of alternate
        suppliers carrying the same SKU with their cost, lead time and reliability.


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token (scope: reports)


        Path parameters:

        - supplier: the Supplier ID

        - product: the Product ID


        Required parameters:

        - period_mode: yoy | qoq | mom | custom


        When period_mode=custom, date_from and date_to (YYYY-MM-DD or m/d/Y) are both
        required.


        Optional:

        - growth_basis: spend | sales | profit | margin (default: sales)

        - min_volume, include_archived'
      parameters:
      - name: period_mode
        in: query
        schema:
          type: string
        description: 'Required. Period comparison model: yoy | qoq | mom | custom'
        example: yoy
      - name: supplier
        in: path
        schema:
          type: string
        required: true
        description: The supplier ID.
      - name: product
        in: path
        schema:
          type: string
        required: true
        description: The product ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      current:
                        type: object
                        properties:
                          product_id:
                            type: integer
                          sku:
                            type: string
                          name:
                            type: string
                          purchase_volume:
                            type: number
                          units_purchased:
                            type: number
                          sales_volume:
                            type: number
                          units_sold:
                            type: number
                          profit:
                            type: number
                          margin:
                            type: number
                      previous:
                        type: object
                        properties:
                          product_id:
                            type: integer
                          sku:
                            type: string
                          name:
                            type: string
                          purchase_volume:
                            type: number
                          units_purchased:
                            type: number
                          sales_volume:
                            type: number
                          units_sold:
                            type: number
                          profit:
                            type: number
                          margin:
                            type: number
                      landed_cost_trend:
                        type: array
                        items:
                          type: object
                          properties:
                            date:
                              type: string
                            po_number:
                              type: string
                            unit_cost:
                              type: number
                      alternate_suppliers:
                        type: array
                        items:
                          type: object
                          properties:
                            supplier_id:
                              type: integer
                            name:
                              type: string
                            landed_unit_cost:
                              type: number
                            leadtime:
                              type: integer
                            lead_time_reliability_pct:
                              type: number
                            is_default:
                              type: boolean
                      supplier:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      product:
                        type: object
                        properties:
                          id:
                            type: integer
                          sku:
                            type: string
                      meta:
                        type: object
                        properties:
                          data_as_of:
                            type: string
                          period_label:
                            type: string
                          current_range:
                            type: array
                            items:
                              type: string
                          previous_range:
                            type: array
                            items:
                              type: string
                          is_partial:
                            type: boolean
                          is_live_query:
                            type: boolean
                example:
                  data:
                    current:
                      product_id: 9001
                      sku: ACM-WIDGET-01
                      name: Widget Assembly Type A
                      purchase_volume: 42100.0
                      units_purchased: 3200.0
                      sales_volume: 78900.0
                      units_sold: 3050.0
                      profit: 24600.0
                      margin: 0.0
                    previous:
                      product_id: 9001
                      sku: ACM-WIDGET-01
                      name: Widget Assembly Type A
                      purchase_volume: 31400.0
                      units_purchased: 2400.0
                      sales_volume: 58200.0
                      units_sold: 2280.0
                      profit: 17900.0
                      margin: 0.0
                    landed_cost_trend:
                    - date: '2025-07-12'
                      po_number: PO-100482
                      unit_cost: 13.4
                    - date: '2025-11-03'
                      po_number: PO-101655
                      unit_cost: 13.16
                    - date: '2026-02-21'
                      po_number: PO-103120
                      unit_cost: 12.95
                    alternate_suppliers:
                    - supplier_id: 58
                      name: Globex Manufacturing
                      landed_unit_cost: 12.1
                      leadtime: 21
                      lead_time_reliability_pct: 91.5
                      is_default: false
                    - supplier_id: 73
                      name: Initech Hardware
                      landed_unit_cost: 14.05
                      leadtime: 35
                      lead_time_reliability_pct: null
                      is_default: false
                    supplier:
                      id: 42
                      name: Acme Components Ltd
                    product:
                      id: 9001
                      sku: ACM-WIDGET-01
                    meta:
                      data_as_of: '2026-05-14T03:12:08+00:00'
                      period_label: YoY — May 2025 – May 2026 vs May 2024 – May 2025
                      current_range:
                      - '2025-05-16'
                      - '2026-05-15'
                      previous_range:
                      - '2024-05-16'
                      - '2025-05-15'
                      is_partial: false
                      is_live_query: false
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No query results for model [App\Models\Supplier].
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      period_mode:
                        type: array
                        items:
                          type: string
                      date_from:
                        type: array
                        items:
                          type: string
                example:
                  message: The given data was invalid.
                  errors:
                    period_mode:
                    - 'Period mode must be one of: yoy, qoq, mom, custom.'
                    date_from:
                    - A start date is required for a custom period.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:read
      operationId: get-api-reporting-suppliers-supplier-products-product
  /api/reporting/suppliers/{supplier}/po-history:
    get:
      tags:
      - Reporting
      summary: Get Supplier PO History
      description: 'Recent purchase orders for one supplier — backs the "Recent Purchase
        Orders" mini-table on the supplier Analytics tab. Returns up to the 10 most
        recent non-draft purchase orders ordered by purchase order date (DESC), each
        with its receipt status and an on-time flag.


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token (scope: reports)


        Path parameters:

        - supplier: the Supplier ID


        This endpoint is period-independent — it always returns the most recent purchase
        orders and takes no query parameters. Draft purchase orders are excluded.


        Response fields per row:

        - id: purchase order ID

        - po_number: human-readable purchase order number

        - purchase_order_date: order date (Y-m-d)

        - total_cost: total purchase order cost

        - receipt_status: receipt status of the PO (e.g. unreceived, partially_received,
        fully_received)

        - on_time: true if fully received on or before the estimated delivery date,
        false if late, null if not yet fully received'
      parameters:
      - name: supplier
        in: path
        schema:
          type: integer
        required: true
        description: The Supplier ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        po_number:
                          type: string
                        purchase_order_date:
                          type: string
                        total_cost:
                          type: number
                        receipt_status:
                          type: string
                        on_time:
                          type: boolean
                example:
                  data:
                  - id: 8821
                    po_number: PO-2025-0142
                    purchase_order_date: '2025-05-08'
                    total_cost: 42100.0
                    receipt_status: fully_received
                    on_time: true
                  - id: 8790
                    po_number: PO-2025-0118
                    purchase_order_date: '2025-04-22'
                    total_cost: 6200.5
                    receipt_status: partially_received
                    on_time: null
                  - id: 8755
                    po_number: PO-2025-0091
                    purchase_order_date: '2025-03-30'
                    total_cost: 18750.0
                    receipt_status: fully_received
                    on_time: false
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No query results for model [App\Models\Supplier].
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:read
      operationId: get-api-reporting-suppliers-supplier-po-history
  /api/reporting/suppliers/{supplier}/scorecard:
    get:
      tags:
      - Reporting
      summary: Get Supplier Scorecard
      description: 'Standalone composite scorecard for a supplier over the resolved
        period — the composite, its band, and the per-dimension breakdown.


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        The band is one of: excellent, good, needs_attention, poor. When the supplier
        has fewer received POs than the configured minimum (is_sufficient=false),
        the band is not_rated and composite is 0.


        Live preview: when the optional preview_weights, preview_thresholds and preview_min_po_count
        parameters are supplied (all three together), the score is computed against
        a transient, non-persisted settings instance built from those values. Nothing
        is written to the scorecard settings table. preview_weights must contain all
        six metric keys and sum to exactly 100.


        Authentication: Requires Bearer token (scope: reports)


        Path parameters:

        - supplier: the Supplier ID


        Required parameters:

        - period_mode: yoy | qoq | mom | custom


        When period_mode=custom, date_from and date_to (YYYY-MM-DD or m/d/Y) are both
        required.


        Optional period params:

        - growth_basis: spend | sales | profit | margin (default: sales)

        - min_volume, include_archived


        Optional live-preview params (all three required together when previewing):

        - preview_weights[{metric}]: numeric 0-100 — one per metric, summing to 100

        - preview_thresholds[{metric}][{i}][min]: numeric; preview_thresholds[{metric}][{i}][score]:
        integer 1-5

        - preview_min_po_count: integer, min 1


        preview_weights and preview_thresholds may be passed either as bracketed array
        params (shown above) or as a single URL-encoded JSON string — the live-preview
        UI sends them as JSON strings.'
      parameters:
      - name: period_mode
        in: query
        schema:
          type: string
        description: 'Required. Period comparison model: yoy | qoq | mom | custom'
        example: yoy
      - name: supplier
        in: path
        schema:
          type: string
        required: true
        description: The supplier ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 OK
                  value:
                    data:
                      composite: 4.15
                      band: good
                      is_sufficient: true
                      po_count: 18
                      dimensions:
                      - key: on_time_delivery
                        label: On-Time Delivery
                        raw: 92.3
                        raw_display: 92.3%
                        score: 4
                        weight: 25.0
                      - key: lead_time_reliability
                        label: Lead-Time Reliability
                        raw: 88.0
                        raw_display: 88.0%
                        score: 3
                        weight: 15.0
                      - key: fill_rate
                        label: Fill Rate
                        raw: 98.6
                        raw_display: 98.6%
                        score: 5
                        weight: 15.0
                      - key: defect_rate
                        label: Defect / RTV Rate
                        raw: 1.2
                        raw_display: 1.2%
                        score: 5
                        weight: 15.0
                      - key: cost_competitiveness
                        label: Cost Competitiveness
                        raw: 74.5
                        raw_display: 74.5 / 100
                        score: 3
                        weight: 25.0
                      - key: price_stability
                        label: Price Stability
                        raw: 0.18
                        raw_display: 18% price increases
                        score: 4
                        weight: 5.0
                example-1:
                  summary: 200 OK (Insufficient Data)
                  value:
                    data:
                      composite: 0.0
                      band: not_rated
                      is_sufficient: false
                      po_count: 1
                      dimensions: []
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No query results for model [App\Models\Supplier].
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      preview_weights:
                        type: array
                        items:
                          type: string
                      preview:
                        type: array
                        items:
                          type: string
                example:
                  message: The given data was invalid.
                  errors:
                    preview_weights:
                    - Preview scorecard weights must sum to exactly 100 (currently
                      90).
                    preview:
                    - A scorecard preview requires preview_weights, preview_thresholds
                      and preview_min_po_count together.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:read
      operationId: get-api-reporting-suppliers-supplier-scorecard
  /api/reporting/products/overview:
    get:
      tags:
      - Reporting
      summary: Get Product Overview
      description: 'Macro product dashboard for the resolved period: headline KPIs
        (sales volume, units sold, profit, active products), the hottest/coldest movers,
        a 12-month growth heatmap, and the full leaderboard. KPIs and trends are read
        from monthly product metric snapshots.


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token (scope: reports)


        Required parameters:

        - period_mode: yoy | qoq | mom | custom


        When period_mode=custom, date_from and date_to (YYYY-MM-DD or m/d/Y) are both
        required and date_to must be on or after date_from.


        Optional:

        - growth_basis: sales | units | profit | margin (default: sales) — the basis
        used to rank movers and the heatmap

        - min_volume: numeric — minimum sales volume before a product qualifies as
        a mover

        - sales_channel_id: integer — restrict the dashboard to a single sales channel

        - include_archived: boolean — include archived products (default: false)'
      parameters:
      - name: period_mode
        in: query
        schema:
          type: string
        description: 'Required. Period comparison model: yoy | qoq | mom | custom'
        example: yoy
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      kpis:
                        type: object
                        properties:
                          sales_volume:
                            type: object
                            properties:
                              current:
                                type: number
                              previous:
                                type: number
                              delta_pct:
                                type: number
                          units_sold:
                            type: object
                            properties:
                              current:
                                type: integer
                              previous:
                                type: integer
                              delta_pct:
                                type: number
                          profit:
                            type: object
                            properties:
                              current:
                                type: number
                              previous:
                                type: number
                              delta_pct:
                                type: number
                          active_products:
                            type: object
                            properties:
                              current:
                                type: integer
                              previous:
                                type: integer
                              delta_pct:
                                type: number
                      hottest:
                        type: array
                        items:
                          type: object
                          properties:
                            product_id:
                              type: integer
                            sku:
                              type: string
                            name:
                              type: string
                            value:
                              type: number
                            delta_pct:
                              type: number
                            spark:
                              type: array
                              items:
                                type: number
                      coldest:
                        type: array
                        items:
                          type: object
                          properties:
                            product_id:
                              type: integer
                            sku:
                              type: string
                            name:
                              type: string
                            value:
                              type: number
                            delta_pct:
                              type: number
                            spark:
                              type: array
                              items:
                                type: number
                      heatmap:
                        type: object
                        properties:
                          columns:
                            type: array
                            items:
                              type: string
                          rows:
                            type: array
                            items:
                              type: object
                              properties:
                                product_id:
                                  type: integer
                                sku:
                                  type: string
                                name:
                                  type: string
                                cells:
                                  type: array
                                  items:
                                    type: string
                                    nullable: true
                      leaderboard:
                        type: array
                        items:
                          type: object
                          properties:
                            product_id:
                              type: integer
                            sku:
                              type: string
                            name:
                              type: string
                            sales_volume:
                              type: number
                            units_sold:
                              type: integer
                            cogs:
                              type: number
                            profit:
                              type: number
                            margin_pct:
                              type: number
                            return_rate_pct:
                              type: number
                            growth_pct:
                              type: number
                            so_count:
                              type: integer
                            is_low_volume:
                              type: boolean
                      meta:
                        type: object
                        properties:
                          data_as_of:
                            type: string
                          period_label:
                            type: string
                          current_range:
                            type: array
                            items:
                              type: string
                          previous_range:
                            type: array
                            items:
                              type: string
                          is_partial:
                            type: boolean
                          is_live_query:
                            type: boolean
                example:
                  data:
                    kpis:
                      sales_volume:
                        current: 3120900.0
                        previous: 2890400.0
                        delta_pct: 8.0
                      units_sold:
                        current: 41200
                        previous: 39800
                        delta_pct: 3.5
                      profit:
                        current: 961000.25
                        previous: 905100.0
                        delta_pct: 6.2
                      active_products:
                        current: 612
                        previous: 588
                        delta_pct: 4.1
                    hottest:
                    - product_id: 1042
                      sku: WIDGET-RED-L
                      name: Red Widget Large
                      value: 184250.5
                      delta_pct: 31.5
                      spark:
                      - 12000.0
                      - 13400.0
                      - 15600.0
                      - 14200.0
                      - 16800.0
                      - 17100.0
                      - 18900.0
                      - 16400.0
                      - 19200.0
                      - 21000.0
                      - 20400.0
                      - 22300.0
                    coldest:
                    - product_id: 871
                      sku: GADGET-BLU-S
                      name: Blue Gadget Small
                      value: 22400.0
                      delta_pct: -18.7
                      spark:
                      - 9100.0
                      - 8700.0
                      - 8200.0
                      - 7600.0
                      - 6900.0
                      - 6400.0
                      - 5800.0
                      - 5100.0
                      - 4700.0
                      - 4200.0
                      - 3900.0
                      - 3400.0
                    heatmap:
                      columns:
                      - 2025-06
                      - 2025-07
                      - 2025-08
                      - 2025-09
                      - 2025-10
                      - 2025-11
                      - 2025-12
                      - 2026-01
                      - 2026-02
                      - 2026-03
                      - 2026-04
                      - 2026-05
                      rows:
                      - product_id: 1042
                        sku: WIDGET-RED-L
                        name: Red Widget Large
                        cells:
                        - null
                        - 8.2
                        - 12.4
                        - -3.1
                        - 6.7
                        - 9.0
                        - 14.2
                        - -2.4
                        - 5.5
                        - 11.0
                        - 7.8
                        - 12.4
                    leaderboard:
                    - product_id: 1042
                      sku: WIDGET-RED-L
                      name: Red Widget Large
                      sales_volume: 312900.0
                      units_sold: 7950
                      cogs: 216800.0
                      profit: 96100.25
                      margin_pct: 30.7
                      return_rate_pct: 2.1
                      growth_pct: 12.4
                      so_count: 421
                      is_low_volume: false
                    meta:
                      data_as_of: '2026-05-14T03:12:08+00:00'
                      period_label: YoY — May 2025 – May 2026 vs May 2024 – May 2025
                      current_range:
                      - '2025-05-16'
                      - '2026-05-15'
                      previous_range:
                      - '2024-05-16'
                      - '2025-05-15'
                      is_partial: false
                      is_live_query: false
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      period_mode:
                        type: array
                        items:
                          type: string
                      date_from:
                        type: array
                        items:
                          type: string
                example:
                  message: The given data was invalid.
                  errors:
                    period_mode:
                    - 'Period mode must be one of: yoy, qoq, mom, custom.'
                    date_from:
                    - A start date is required for a custom period.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:read
      operationId: get-api-reporting-products-overview
  /api/reporting/products/leaderboard:
    get:
      tags:
      - Reporting
      summary: Get Product Leaderboard
      description: 'Server-paginated, sortable product leaderboard for the resolved
        period — used when the macro dashboard''s leaderboard table changes page or
        sort. Returns the standard Laravel pagination envelope.


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token (scope: reports)


        Accepts the same period parameters as Get Product Overview, plus:

        - sort: column to sort by, prefix with - for descending

        - page / per_page: standard pagination controls (per_page default 25)'
      parameters:
      - name: period_mode
        in: query
        schema:
          type: string
        description: 'Required. Period comparison model: yoy | qoq | mom | custom'
        example: yoy
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        product_id:
                          type: integer
                        sku:
                          type: string
                        name:
                          type: string
                        sales_volume:
                          type: number
                        units_sold:
                          type: integer
                        cogs:
                          type: number
                        profit:
                          type: number
                        margin_pct:
                          type: number
                        return_rate_pct:
                          type: number
                        growth_pct:
                          type: number
                        so_count:
                          type: integer
                        is_low_volume:
                          type: boolean
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                  path:
                    type: string
                example:
                  data:
                  - product_id: 1042
                    sku: WIDGET-RED-L
                    name: Red Widget Large
                    sales_volume: 312900.0
                    units_sold: 7950
                    cogs: 216800.0
                    profit: 96100.25
                    margin_pct: 30.7
                    return_rate_pct: 2.1
                    growth_pct: 12.4
                    so_count: 421
                    is_low_volume: false
                  current_page: 1
                  last_page: 25
                  per_page: 25
                  total: 612
                  from: 1
                  to: 25
                  path: '{{protocol}}{{domain}}/api/reporting/products/leaderboard'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      period_mode:
                        type: array
                        items:
                          type: string
                      date_from:
                        type: array
                        items:
                          type: string
                example:
                  message: The given data was invalid.
                  errors:
                    period_mode:
                    - 'Period mode must be one of: yoy, qoq, mom, custom.'
                    date_from:
                    - A start date is required for a custom period.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:read
      operationId: get-api-reporting-products-leaderboard
  /api/reporting/products/rebuild-snapshots:
    post:
      tags:
      - Reporting
      summary: Rebuild Product Metric Snapshots
      description: 'Dispatches the product-metric snapshot rebuild as a tracked background
        job and returns its tracked job log ID for progress polling via the tracked
        job log endpoints. The rebuild recomputes per-channel sales snapshots first,
        then derives the per-product snapshots by summation. Rejects a second dispatch
        with 409 while a rebuild is already queued or running.


        :::info[Required scope: `reports:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token (scope: reports)


        This endpoint takes no request body.'
      requestBody:
        content:
          application/json:
            schema:
              type: string
              example: ''
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 90871
                  message: Product metric rebuild started.
        '409':
          description: Conflict
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: A product metric rebuild is already in progress.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: reports:write
      operationId: post-api-reporting-products-rebuild-snapshots
  /api/reporting/products/scorecard-settings:
    get:
      tags:
      - Reporting
      summary: Get Product Scorecard Settings
      description: 'Returns the tenant''s product scorecard configuration: the six
        dimension weights (must sum to 100), the threshold bands that map a raw metric
        value to a 1–5 score, and min_so_count — the minimum sales-order count before
        a product is scored.


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token (scope: reports)'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      weights:
                        type: object
                        properties:
                          gross_margin:
                            type: integer
                          gmroi:
                            type: integer
                          sales_growth:
                            type: integer
                          sell_through:
                            type: integer
                          stock_cover:
                            type: integer
                          return_rate:
                            type: integer
                      thresholds:
                        type: object
                        properties:
                          gross_margin:
                            type: array
                            items:
                              type: object
                              properties:
                                min:
                                  type: integer
                                score:
                                  type: integer
                          gmroi:
                            type: array
                            items:
                              type: object
                              properties:
                                min:
                                  type: integer
                                score:
                                  type: integer
                          sales_growth:
                            type: array
                            items:
                              type: object
                              properties:
                                min:
                                  type: integer
                                score:
                                  type: integer
                          sell_through:
                            type: array
                            items:
                              type: object
                              properties:
                                min:
                                  type: integer
                                score:
                                  type: integer
                          stock_cover:
                            type: array
                            items:
                              type: object
                              properties:
                                min:
                                  type: integer
                                score:
                                  type: integer
                          return_rate:
                            type: array
                            items:
                              type: object
                              properties:
                                min:
                                  type: integer
                                score:
                                  type: integer
                      min_so_count:
                        type: integer
                example:
                  data:
                    weights:
                      gross_margin: 25
                      gmroi: 15
                      sales_growth: 20
                      sell_through: 15
                      stock_cover: 15
                      return_rate: 10
                    thresholds:
                      gross_margin:
                      - min: 40
                        score: 5
                      - min: 30
                        score: 4
                      - min: 20
                        score: 3
                      - min: 10
                        score: 2
                      - min: 0
                        score: 1
                      gmroi:
                      - min: 4
                        score: 5
                      - min: 3
                        score: 4
                      - min: 2
                        score: 3
                      - min: 1
                        score: 2
                      - min: 0
                        score: 1
                      sales_growth:
                      - min: 25
                        score: 5
                      - min: 10
                        score: 4
                      - min: 0
                        score: 3
                      - min: -15
                        score: 2
                      - min: -100
                        score: 1
                      sell_through:
                      - min: 90
                        score: 5
                      - min: 75
                        score: 4
                      - min: 60
                        score: 3
                      - min: 40
                        score: 2
                      - min: 0
                        score: 1
                      stock_cover:
                      - min: 30
                        score: 5
                      - min: 21
                        score: 4
                      - min: 14
                        score: 3
                      - min: 7
                        score: 2
                      - min: 0
                        score: 1
                      return_rate:
                      - min: 98
                        score: 5
                      - min: 95
                        score: 4
                      - min: 90
                        score: 3
                      - min: 85
                        score: 2
                      - min: 0
                        score: 1
                    min_so_count: 3
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:read
      operationId: get-api-reporting-products-scorecard-settings
    put:
      tags:
      - Reporting
      summary: Update Product Scorecard Settings
      description: 'Updates the tenant''s product scorecard configuration.


        :::info[Required scope: `reports:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token (scope: reports)


        Request body (all fields required):

        - weights: object — a numeric weight (0–100) for each of the six dimensions
        (gross_margin, gmroi, sales_growth, sell_through, stock_cover, return_rate).
        The six weights must sum to exactly 100.

        - thresholds: object — for each dimension, an array of at least one band;
        each band has a numeric `min` and an integer `score` between 1 and 5.

        - min_so_count: integer — minimum sales-order count before a product is scored
        (at least 1).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                weights:
                  type: object
                  properties:
                    gross_margin:
                      type: integer
                    gmroi:
                      type: integer
                    sales_growth:
                      type: integer
                    sell_through:
                      type: integer
                    stock_cover:
                      type: integer
                    return_rate:
                      type: integer
                thresholds:
                  type: object
                  properties:
                    gross_margin:
                      type: array
                      items:
                        type: object
                        properties:
                          min:
                            type: integer
                          score:
                            type: integer
                    gmroi:
                      type: array
                      items:
                        type: object
                        properties:
                          min:
                            type: integer
                          score:
                            type: integer
                    sales_growth:
                      type: array
                      items:
                        type: object
                        properties:
                          min:
                            type: integer
                          score:
                            type: integer
                    sell_through:
                      type: array
                      items:
                        type: object
                        properties:
                          min:
                            type: integer
                          score:
                            type: integer
                    stock_cover:
                      type: array
                      items:
                        type: object
                        properties:
                          min:
                            type: integer
                          score:
                            type: integer
                    return_rate:
                      type: array
                      items:
                        type: object
                        properties:
                          min:
                            type: integer
                          score:
                            type: integer
                min_so_count:
                  type: integer
              example:
                weights:
                  gross_margin: 25
                  gmroi: 15
                  sales_growth: 20
                  sell_through: 15
                  stock_cover: 15
                  return_rate: 10
                thresholds:
                  gross_margin:
                  - min: 40
                    score: 5
                  - min: 30
                    score: 4
                  - min: 20
                    score: 3
                  - min: 10
                    score: 2
                  - min: 0
                    score: 1
                  gmroi:
                  - min: 4
                    score: 5
                  - min: 3
                    score: 4
                  - min: 2
                    score: 3
                  - min: 1
                    score: 2
                  - min: 0
                    score: 1
                  sales_growth:
                  - min: 25
                    score: 5
                  - min: 10
                    score: 4
                  - min: 0
                    score: 3
                  - min: -15
                    score: 2
                  - min: -100
                    score: 1
                  sell_through:
                  - min: 90
                    score: 5
                  - min: 75
                    score: 4
                  - min: 60
                    score: 3
                  - min: 40
                    score: 2
                  - min: 0
                    score: 1
                  stock_cover:
                  - min: 30
                    score: 5
                  - min: 21
                    score: 4
                  - min: 14
                    score: 3
                  - min: 7
                    score: 2
                  - min: 0
                    score: 1
                  return_rate:
                  - min: 98
                    score: 5
                  - min: 95
                    score: 4
                  - min: 90
                    score: 3
                  - min: 85
                    score: 2
                  - min: 0
                    score: 1
                min_so_count: 3
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      weights:
                        type: object
                        properties:
                          gross_margin:
                            type: integer
                          gmroi:
                            type: integer
                          sales_growth:
                            type: integer
                          sell_through:
                            type: integer
                          stock_cover:
                            type: integer
                          return_rate:
                            type: integer
                      thresholds:
                        type: object
                        properties:
                          gross_margin:
                            type: array
                            items:
                              type: object
                              properties:
                                min:
                                  type: integer
                                score:
                                  type: integer
                          gmroi:
                            type: array
                            items:
                              type: object
                              properties:
                                min:
                                  type: integer
                                score:
                                  type: integer
                          sales_growth:
                            type: array
                            items:
                              type: object
                              properties:
                                min:
                                  type: integer
                                score:
                                  type: integer
                          sell_through:
                            type: array
                            items:
                              type: object
                              properties:
                                min:
                                  type: integer
                                score:
                                  type: integer
                          stock_cover:
                            type: array
                            items:
                              type: object
                              properties:
                                min:
                                  type: integer
                                score:
                                  type: integer
                          return_rate:
                            type: array
                            items:
                              type: object
                              properties:
                                min:
                                  type: integer
                                score:
                                  type: integer
                      min_so_count:
                        type: integer
                example:
                  data:
                    weights:
                      gross_margin: 25
                      gmroi: 15
                      sales_growth: 20
                      sell_through: 15
                      stock_cover: 15
                      return_rate: 10
                    thresholds:
                      gross_margin:
                      - min: 40
                        score: 5
                      - min: 30
                        score: 4
                      - min: 20
                        score: 3
                      - min: 10
                        score: 2
                      - min: 0
                        score: 1
                      gmroi:
                      - min: 4
                        score: 5
                      - min: 3
                        score: 4
                      - min: 2
                        score: 3
                      - min: 1
                        score: 2
                      - min: 0
                        score: 1
                      sales_growth:
                      - min: 25
                        score: 5
                      - min: 10
                        score: 4
                      - min: 0
                        score: 3
                      - min: -15
                        score: 2
                      - min: -100
                        score: 1
                      sell_through:
                      - min: 90
                        score: 5
                      - min: 75
                        score: 4
                      - min: 60
                        score: 3
                      - min: 40
                        score: 2
                      - min: 0
                        score: 1
                      stock_cover:
                      - min: 30
                        score: 5
                      - min: 21
                        score: 4
                      - min: 14
                        score: 3
                      - min: 7
                        score: 2
                      - min: 0
                        score: 1
                      return_rate:
                      - min: 98
                        score: 5
                      - min: 95
                        score: 4
                      - min: 90
                        score: 3
                      - min: 85
                        score: 2
                      - min: 0
                        score: 1
                    min_so_count: 3
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      weights:
                        type: array
                        items:
                          type: string
                example:
                  message: The given data was invalid.
                  errors:
                    weights:
                    - Scorecard weights must sum to exactly 100 (currently 125).
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:write
      operationId: put-api-reporting-products-scorecard-settings
  /api/reporting/products/{product}/scorecard-summary:
    get:
      tags:
      - Reporting
      summary: Get Product Scorecard Summary
      description: 'Lightweight scorecard payload for the product Profile-tab performance
        chip: the composite scorecard, a directional trend hint (up | flat | down)
        and two short volume sparklines (sales volume and units sold).


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token (scope: reports)


        Path parameter:

        - product: the product ID'
      parameters:
      - name: product
        in: path
        schema:
          type: string
        required: true
        description: The product ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      product:
                        type: object
                        properties:
                          id:
                            type: integer
                          sku:
                            type: string
                          name:
                            type: string
                      scorecard:
                        type: object
                        properties:
                          composite:
                            type: number
                          band:
                            type: string
                          is_sufficient:
                            type: boolean
                          so_count:
                            type: integer
                          dimensions:
                            type: array
                            items:
                              type: object
                              properties:
                                key:
                                  type: string
                                label:
                                  type: string
                                raw:
                                  type: number
                                raw_display:
                                  type: string
                                score:
                                  type: integer
                                weight:
                                  type: integer
                      composite_trend:
                        type: string
                      sales_volume:
                        type: array
                        items:
                          type: number
                      units_sold:
                        type: array
                        items:
                          type: integer
                      meta:
                        type: object
                        properties:
                          data_as_of:
                            type: string
                          period_label:
                            type: string
                example:
                  data:
                    product:
                      id: 1042
                      sku: WIDGET-RED-L
                      name: Red Widget Large
                    scorecard:
                      composite: 3.85
                      band: good
                      is_sufficient: true
                      so_count: 421
                      dimensions:
                      - key: gross_margin
                        label: Gross Margin
                        raw: 30.7
                        raw_display: 30.7%
                        score: 4
                        weight: 25
                      - key: gmroi
                        label: GMROI
                        raw: 3.2
                        raw_display: '3.2'
                        score: 4
                        weight: 15
                      - key: sales_growth
                        label: Sales Growth
                        raw: 12.4
                        raw_display: +12.4%
                        score: 4
                        weight: 20
                      - key: sell_through
                        label: Sell-Through
                        raw: 78.0
                        raw_display: 78%
                        score: 4
                        weight: 15
                      - key: stock_cover
                        label: Stock Cover
                        raw: 18.5
                        raw_display: 18.5 days
                        score: 3
                        weight: 15
                      - key: return_rate
                        label: Return Rate
                        raw: 2.1
                        raw_display: 2.1%
                        score: 5
                        weight: 10
                    composite_trend: up
                    sales_volume:
                    - 22100.0
                    - 24300.0
                    - 23800.0
                    - 26100.0
                    - 27400.0
                    - 28900.0
                    units_sold:
                    - 560
                    - 612
                    - 598
                    - 651
                    - 683
                    - 720
                    meta:
                      data_as_of: '2026-05-14T03:12:08+00:00'
                      period_label: Trailing 6 months
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No query results for model [App\\Models\\Product].
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:read
      operationId: get-api-reporting-products-product-scorecard-summary
  /api/reporting/products/{product}/stock-coverage:
    get:
      tags:
      - Reporting
      summary: Get Product Stock Coverage
      description: 'Daily Average Consumption (DAC) and Days of Stock reconstructed
        as a 12-month monthly time series for a product. No history is stored for
        either metric, so both are rebuilt from source ledgers: DAC at each month
        is gross units sold over the trailing sales-history window divided by that
        window length; on-hand at each month is the running balance of stock movements
        up to that month; Days of Stock is on-hand divided by DAC (null when DAC is
        0, i.e. coverage is effectively infinite).


        Authentication: Requires Bearer token (scope: reports)


        Path parameter:

        - product: the product ID


        Query parameter:

        - months: span of the series - an integer count of trailing months (e.g. 12,
        24) or ''all'' for the product''s full ledger history (capped at 60 months).
        Default: 12.


        Response fields:

        - buckets: 12 month labels (YYYY-MM), oldest first

        - window_days: the trailing DAC window length in days

        - dac / units_sold / on_hand / days_of_stock: parallel arrays aligned to buckets
        (units_sold is the raw units sold that calendar month; dac is the trailing-window
        daily average) (days_of_stock entries are null where DAC is 0)

        - current: the latest bucket''s dac, on_hand and days_of_stock'
      parameters:
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: The product ID
        example: '1042'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      buckets:
                        type: array
                        items:
                          type: string
                      window_days:
                        type: integer
                      dac:
                        type: array
                        items:
                          type: number
                      units_sold:
                        type: array
                        items:
                          type: integer
                      on_hand:
                        type: array
                        items:
                          type: number
                      days_of_stock:
                        type: array
                        items:
                          type: string
                          nullable: true
                      current:
                        type: object
                        properties:
                          dac:
                            type: number
                          units_sold:
                            type: integer
                          on_hand:
                            type: number
                          days_of_stock:
                            type: number
                example:
                  data:
                    buckets:
                    - 2025-08
                    - 2025-09
                    - 2025-10
                    - 2025-11
                    - 2025-12
                    - 2026-01
                    - 2026-02
                    - 2026-03
                    - 2026-04
                    - 2026-05
                    - 2026-06
                    - 2026-07
                    window_days: 90
                    dac:
                    - 0.0
                    - 0.0
                    - 0.12
                    - 0.18
                    - 0.2
                    - 0.26
                    - 0.3
                    - 0.34
                    - 0.4
                    - 0.46
                    - 0.52
                    - 0.6
                    units_sold:
                    - 0
                    - 0
                    - 14
                    - 18
                    - 20
                    - 26
                    - 30
                    - 34
                    - 40
                    - 46
                    - 52
                    - 60
                    on_hand:
                    - 0.0
                    - 0.0
                    - 120.0
                    - 118.0
                    - 150.0
                    - 210.0
                    - 190.0
                    - 175.0
                    - 160.0
                    - 140.0
                    - 120.0
                    - 100.0
                    days_of_stock:
                    - null
                    - null
                    - 1000.0
                    - 655.6
                    - 750.0
                    - 807.7
                    - 633.3
                    - 514.7
                    - 400.0
                    - 304.3
                    - 230.8
                    - 166.7
                    current:
                      dac: 0.6
                      units_sold: 60
                      on_hand: 100.0
                      days_of_stock: 166.7
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-reporting-products-product-stock-coverage
  /api/reporting/products/{product}/stock-coverage/export:
    get:
      tags:
      - Reporting
      summary: Export Product Stock Coverage
      description: 'Download the month-by-month Stock Coverage series as a spreadsheet.
        Columns: Month, Units Sold (that calendar month), DAC (units/day, trailing-window
        daily average), On Hand (month-end), Days of Stock (on-hand / DAC). Honors
        the same ''months'' span as the JSON endpoint.


        Authentication: Requires Bearer token (scope: reports)


        Path parameter:

        - product: the product ID


        Query parameters:

        - months: trailing-month count or ''all'' (default 12)

        - format: ''xlsx'' or ''csv'' (default xlsx)


        Returns a file download (Content-Type application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
        for xlsx, text/csv for csv), not JSON. Filename: stock-coverage-{sku}-{timestamp}.{format}.'
      parameters:
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: The product ID
        example: '1042'
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-reporting-products-product-stock-coverage-export
  /api/reporting/products/{product}/analytics:
    get:
      tags:
      - Reporting
      summary: Get Product Analytics
      description: 'Full per-product analytics for the Analytics tab: period KPIs
        (sales volume, units sold, profit, margin), the computed scorecard, a monthly
        trend series, the hottest/coolest sales channels, a per-channel growth heatmap
        and recent orders.


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token (scope: reports)


        Path parameter:

        - product: the product ID


        Accepts the same period parameters as Get Product Overview.'
      parameters:
      - name: period_mode
        in: query
        schema:
          type: string
        description: 'Required. Period comparison model: yoy | qoq | mom | custom'
        example: yoy
      - name: product
        in: path
        schema:
          type: string
        required: true
        description: The product ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      product:
                        type: object
                        properties:
                          id:
                            type: integer
                          sku:
                            type: string
                          name:
                            type: string
                      kpis:
                        type: object
                        properties:
                          sales_volume:
                            type: object
                            properties:
                              current:
                                type: number
                              previous:
                                type: number
                              delta_pct:
                                type: number
                          units_sold:
                            type: object
                            properties:
                              current:
                                type: integer
                              previous:
                                type: integer
                              delta_pct:
                                type: number
                          profit:
                            type: object
                            properties:
                              current:
                                type: number
                              previous:
                                type: number
                              delta_pct:
                                type: number
                          margin_pct:
                            type: object
                            properties:
                              current:
                                type: number
                              previous:
                                type: number
                              delta_pct:
                                type: number
                      scorecard:
                        type: object
                        properties:
                          composite:
                            type: number
                          band:
                            type: string
                          is_sufficient:
                            type: boolean
                          so_count:
                            type: integer
                          dimensions:
                            type: array
                            items:
                              type: object
                              properties:
                                key:
                                  type: string
                                label:
                                  type: string
                                raw:
                                  type: number
                                raw_display:
                                  type: string
                                score:
                                  type: integer
                                weight:
                                  type: integer
                      trend:
                        type: object
                        properties:
                          columns:
                            type: array
                            items:
                              type: string
                          sales_volume:
                            type: array
                            items:
                              type: number
                          units_sold:
                            type: array
                            items:
                              type: integer
                      hottest_channels:
                        type: array
                        items:
                          type: object
                          properties:
                            sales_channel_id:
                              type: integer
                            name:
                              type: string
                            value:
                              type: number
                            delta_pct:
                              type: number
                      coolest_channels:
                        type: array
                        items:
                          type: object
                          properties:
                            sales_channel_id:
                              type: integer
                            name:
                              type: string
                            value:
                              type: number
                            delta_pct:
                              type: number
                      hottest_customers:
                        type: array
                        items:
                          type: object
                          properties:
                            customer_id:
                              type: integer
                            name:
                              type: string
                            value:
                              type: number
                            delta_pct:
                              type: number
                      coolest_customers:
                        type: array
                        items:
                          type: object
                          properties:
                            customer_id:
                              type: integer
                            name:
                              type: string
                            value:
                              type: number
                            delta_pct:
                              type: number
                      channel_heatmap:
                        type: object
                        properties:
                          columns:
                            type: array
                            items:
                              type: string
                          rows:
                            type: array
                            items:
                              type: object
                              properties:
                                sales_channel_id:
                                  type: integer
                                name:
                                  type: string
                                cells:
                                  type: array
                                  items:
                                    type: number
                      recent_orders:
                        type: array
                        items:
                          type: object
                          properties:
                            sales_order_id:
                              type: integer
                            order_number:
                              type: string
                            sales_channel:
                              type: string
                            ordered_at:
                              type: string
                            units:
                              type: integer
                            sales_volume:
                              type: number
                      meta:
                        type: object
                        properties:
                          data_as_of:
                            type: string
                          period_label:
                            type: string
                          current_range:
                            type: array
                            items:
                              type: string
                          previous_range:
                            type: array
                            items:
                              type: string
                          is_partial:
                            type: boolean
                          is_live_query:
                            type: boolean
                example:
                  data:
                    product:
                      id: 1042
                      sku: WIDGET-RED-L
                      name: Red Widget Large
                    kpis:
                      sales_volume:
                        current: 312900.0
                        previous: 278400.0
                        delta_pct: 12.4
                      units_sold:
                        current: 7950
                        previous: 7420
                        delta_pct: 7.1
                      profit:
                        current: 96100.25
                        previous: 88200.0
                        delta_pct: 9.0
                      margin_pct:
                        current: 30.7
                        previous: 31.7
                        delta_pct: -3.2
                    scorecard:
                      composite: 3.85
                      band: good
                      is_sufficient: true
                      so_count: 421
                      dimensions:
                      - key: gross_margin
                        label: Gross Margin
                        raw: 30.7
                        raw_display: 30.7%
                        score: 4
                        weight: 25
                      - key: gmroi
                        label: GMROI
                        raw: 3.2
                        raw_display: '3.2'
                        score: 4
                        weight: 15
                      - key: sales_growth
                        label: Sales Growth
                        raw: 12.4
                        raw_display: +12.4%
                        score: 4
                        weight: 20
                      - key: sell_through
                        label: Sell-Through
                        raw: 78.0
                        raw_display: 78%
                        score: 4
                        weight: 15
                      - key: stock_cover
                        label: Stock Cover
                        raw: 18.5
                        raw_display: 18.5 days
                        score: 3
                        weight: 15
                      - key: return_rate
                        label: Return Rate
                        raw: 2.1
                        raw_display: 2.1%
                        score: 5
                        weight: 10
                    trend:
                      columns:
                      - 2025-12
                      - 2026-01
                      - 2026-02
                      - 2026-03
                      - 2026-04
                      - 2026-05
                      sales_volume:
                      - 48200.0
                      - 51100.0
                      - 49800.0
                      - 53400.0
                      - 55900.0
                      - 54500.0
                      units_sold:
                      - 1210
                      - 1280
                      - 1250
                      - 1340
                      - 1410
                      - 1460
                    hottest_channels:
                    - sales_channel_id: 3
                      name: Amazon US
                      value: 142800.0
                      delta_pct: 24.1
                    coolest_channels:
                    - sales_channel_id: 7
                      name: eBay
                      value: 18400.0
                      delta_pct: -12.6
                    hottest_customers:
                    - customer_id: 5521
                      name: Acme Distributors
                      value: 48200.0
                      delta_pct: 31.7
                    coolest_customers:
                    - customer_id: 4310
                      name: Bright Retail Co
                      value: 9100.0
                      delta_pct: -18.4
                    channel_heatmap:
                      columns:
                      - 2025-12
                      - 2026-01
                      - 2026-02
                      - 2026-03
                      - 2026-04
                      - 2026-05
                      rows:
                      - sales_channel_id: 3
                        name: Amazon US
                        cells:
                        - 6.2
                        - -1.4
                        - 8.1
                        - 11.0
                        - 4.5
                        - 9.3
                    recent_orders:
                    - sales_order_id: 88213
                      order_number: SO-88213
                      sales_channel: Amazon US
                      ordered_at: '2026-05-12'
                      units: 24
                      sales_volume: 940.0
                    meta:
                      data_as_of: '2026-05-14T03:12:08+00:00'
                      period_label: YoY — May 2025 – May 2026 vs May 2024 – May 2025
                      current_range:
                      - '2025-05-16'
                      - '2026-05-15'
                      previous_range:
                      - '2024-05-16'
                      - '2025-05-15'
                      is_partial: false
                      is_live_query: false
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      period_mode:
                        type: array
                        items:
                          type: string
                      date_from:
                        type: array
                        items:
                          type: string
                example:
                  message: The given data was invalid.
                  errors:
                    period_mode:
                    - 'Period mode must be one of: yoy, qoq, mom, custom.'
                    date_from:
                    - A start date is required for a custom period.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: reports:read
      operationId: get-api-reporting-products-product-analytics
  /api/reporting/products/{product}/channels:
    get:
      tags:
      - Reporting
      summary: Get Product Channel Breakdown
      description: 'Server-paginated, sortable per-sales-channel breakdown for one
        product — the Channels tab table. Each row carries the channel''s units, sales
        volume, profit, order count, average order value, margin, return rate, share
        of the product''s sales and period-over-period growth. Channel-grain data
        is sales-side only (purchasing is not channel-attributable).


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token (scope: reports)


        Path parameter:

        - product: the product ID


        Accepts the same period parameters as Get Product Overview, plus sort / page
        / per_page.'
      parameters:
      - name: period_mode
        in: query
        schema:
          type: string
        description: 'Required. Period comparison model: yoy | qoq | mom | custom'
        example: yoy
      - name: product
        in: path
        schema:
          type: string
        required: true
        description: The product ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        sales_channel_id:
                          type: integer
                        name:
                          type: string
                        units_sold:
                          type: integer
                        sales_volume:
                          type: number
                        profit:
                          type: number
                        order_count:
                          type: integer
                        avg_order_value:
                          type: number
                        margin_pct:
                          type: number
                        return_rate_pct:
                          type: number
                        sales_share_pct:
                          type: number
                        growth_pct:
                          type: number
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                  path:
                    type: string
                example:
                  data:
                  - sales_channel_id: 3
                    name: Amazon US
                    units_sold: 4820
                    sales_volume: 142800.0
                    profit: 44100.0
                    order_count: 412
                    avg_order_value: 346.6
                    margin_pct: 30.9
                    return_rate_pct: 1.8
                    sales_share_pct: 45.6
                    growth_pct: 24.1
                  current_page: 1
                  last_page: 1
                  per_page: 25
                  total: 6
                  from: 1
                  to: 6
                  path: '{{protocol}}{{domain}}/api/reporting/products/1042/channels'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      period_mode:
                        type: array
                        items:
                          type: string
                      date_from:
                        type: array
                        items:
                          type: string
                example:
                  message: The given data was invalid.
                  errors:
                    period_mode:
                    - 'Period mode must be one of: yoy, qoq, mom, custom.'
                    date_from:
                    - A start date is required for a custom period.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: reports:read
      operationId: get-api-reporting-products-product-channels
  /api/reporting/products/{product}/channels/{salesChannel}:
    get:
      tags:
      - Reporting
      summary: Get Product Channel Drilldown
      description: 'Single-channel drill-down for one product: the channel''s current
        and previous-period totals, the product''s whole-period totals for a share
        comparison, and recent orders placed on that channel.


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token (scope: reports)


        Path parameters:

        - product: the product ID

        - salesChannel: the sales channel ID


        Accepts the same period parameters as Get Product Overview.'
      parameters:
      - name: period_mode
        in: query
        schema:
          type: string
        description: 'Required. Period comparison model: yoy | qoq | mom | custom'
        example: yoy
      - name: product
        in: path
        schema:
          type: string
        required: true
        description: The product ID.
      - name: salesChannel
        in: path
        schema:
          type: string
        required: true
        description: The sales channel ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      product:
                        type: object
                        properties:
                          id:
                            type: integer
                          sku:
                            type: string
                          name:
                            type: string
                      sales_channel_id:
                        type: integer
                      current:
                        type: object
                        properties:
                          units_sold:
                            type: integer
                          sales_volume:
                            type: number
                          cogs:
                            type: number
                          profit:
                            type: number
                          margin_pct:
                            type: number
                          returned_units:
                            type: integer
                          so_count:
                            type: integer
                      previous:
                        type: object
                        properties:
                          units_sold:
                            type: integer
                          sales_volume:
                            type: number
                          cogs:
                            type: number
                          profit:
                            type: number
                          margin_pct:
                            type: number
                          returned_units:
                            type: integer
                          so_count:
                            type: integer
                      product_current:
                        type: object
                        properties:
                          units_sold:
                            type: integer
                          sales_volume:
                            type: number
                          profit:
                            type: number
                      recent_orders:
                        type: array
                        items:
                          type: object
                          properties:
                            sales_order_id:
                              type: integer
                            order_number:
                              type: string
                            ordered_at:
                              type: string
                            units:
                              type: integer
                            sales_volume:
                              type: number
                      meta:
                        type: object
                        properties:
                          data_as_of:
                            type: string
                          period_label:
                            type: string
                          current_range:
                            type: array
                            items:
                              type: string
                          previous_range:
                            type: array
                            items:
                              type: string
                          is_partial:
                            type: boolean
                          is_live_query:
                            type: boolean
                example:
                  data:
                    product:
                      id: 1042
                      sku: WIDGET-RED-L
                      name: Red Widget Large
                    sales_channel_id: 3
                    current:
                      units_sold: 4820
                      sales_volume: 142800.0
                      cogs: 98700.0
                      profit: 44100.0
                      margin_pct: 30.9
                      returned_units: 87
                      so_count: 198
                    previous:
                      units_sold: 3910
                      sales_volume: 115100.0
                      cogs: 80200.0
                      profit: 34900.0
                      margin_pct: 30.3
                      returned_units: 71
                      so_count: 162
                    product_current:
                      units_sold: 7950
                      sales_volume: 312900.0
                      profit: 96100.25
                    recent_orders:
                    - sales_order_id: 88213
                      order_number: SO-88213
                      ordered_at: '2026-05-12'
                      units: 24
                      sales_volume: 940.0
                    meta:
                      data_as_of: '2026-05-14T03:12:08+00:00'
                      period_label: YoY — May 2025 – May 2026 vs May 2024 – May 2025
                      current_range:
                      - '2025-05-16'
                      - '2026-05-15'
                      previous_range:
                      - '2024-05-16'
                      - '2025-05-15'
                      is_partial: false
                      is_live_query: false
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      period_mode:
                        type: array
                        items:
                          type: string
                      date_from:
                        type: array
                        items:
                          type: string
                example:
                  message: The given data was invalid.
                  errors:
                    period_mode:
                    - 'Period mode must be one of: yoy, qoq, mom, custom.'
                    date_from:
                    - A start date is required for a custom period.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: reports:read
      operationId: get-api-reporting-products-product-channels-saleschannel
  /api/reporting/products/{product}/scorecard:
    get:
      tags:
      - Reporting
      summary: Get Product Scorecard
      description: 'Standalone computed scorecard for one product — the composite,
        its band and the per-dimension breakdown. Used by the Scorecard Settings live
        preview.


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token (scope: reports)


        Path parameter:

        - product: the product ID


        Accepts the same period parameters as Get Product Overview. When the optional
        preview_weights, preview_thresholds and preview_min_so_count parameters are
        supplied together, the score is computed against a transient, non-persisted
        settings configuration built from those values — nothing is written to the
        scorecard settings table. Supplying any one of the three without the others
        returns a 422.'
      parameters:
      - name: period_mode
        in: query
        schema:
          type: string
        description: 'Required. Period comparison model: yoy | qoq | mom | custom'
        example: yoy
      - name: product
        in: path
        schema:
          type: string
        required: true
        description: The product ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      composite:
                        type: number
                      band:
                        type: string
                      is_sufficient:
                        type: boolean
                      so_count:
                        type: integer
                      dimensions:
                        type: array
                        items:
                          type: object
                          properties:
                            key:
                              type: string
                            label:
                              type: string
                            raw:
                              type: number
                            raw_display:
                              type: string
                            score:
                              type: integer
                            weight:
                              type: integer
                example:
                  data:
                    composite: 3.85
                    band: good
                    is_sufficient: true
                    so_count: 421
                    dimensions:
                    - key: gross_margin
                      label: Gross Margin
                      raw: 30.7
                      raw_display: 30.7%
                      score: 4
                      weight: 25
                    - key: gmroi
                      label: GMROI
                      raw: 3.2
                      raw_display: '3.2'
                      score: 4
                      weight: 15
                    - key: sales_growth
                      label: Sales Growth
                      raw: 12.4
                      raw_display: +12.4%
                      score: 4
                      weight: 20
                    - key: sell_through
                      label: Sell-Through
                      raw: 78.0
                      raw_display: 78%
                      score: 4
                      weight: 15
                    - key: stock_cover
                      label: Stock Cover
                      raw: 18.5
                      raw_display: 18.5 days
                      score: 3
                      weight: 15
                    - key: return_rate
                      label: Return Rate
                      raw: 2.1
                      raw_display: 2.1%
                      score: 5
                      weight: 10
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      period_mode:
                        type: array
                        items:
                          type: string
                      date_from:
                        type: array
                        items:
                          type: string
                example:
                  message: The given data was invalid.
                  errors:
                    period_mode:
                    - 'Period mode must be one of: yoy, qoq, mom, custom.'
                    date_from:
                    - A start date is required for a custom period.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: reports:read
      operationId: get-api-reporting-products-product-scorecard
  /api/reporting/brands/overview:
    get:
      tags:
      - Reporting
      summary: Get Brand Overview
      description: 'Macro brand dashboard for the resolved period: headline KPIs (purchase
        volume, sales volume, profit, active brands), the hottest/coldest movers,
        a 12-month growth heatmap, and the full leaderboard. KPIs and trends are read
        from monthly brand metric snapshots.


        Authentication: Requires Bearer token (scope: reports)


        Required parameters:

        - period_mode: yoy | qoq | mom | custom


        When period_mode=custom, date_from and date_to (YYYY-MM-DD or m/d/Y) are both
        required and date_to must be on or after date_from.


        Optional:

        - growth_basis: spend | sales | profit | margin (default: sales) — the basis
        used to rank movers and the heatmap

        - min_volume: numeric — minimum purchase volume before a brand qualifies as
        a mover (default: 1000)

        - include_archived: boolean — include archived brands (default: false)'
      parameters:
      - name: period_mode
        in: query
        schema:
          type: string
        description: 'Required. Period comparison model: yoy | qoq | mom | custom'
        example: yoy
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      kpis:
                        type: object
                        properties:
                          purchase_volume:
                            type: object
                            properties:
                              current:
                                type: number
                              previous:
                                type: number
                              delta_pct:
                                type: number
                          sales_volume:
                            type: object
                            properties:
                              current:
                                type: number
                              previous:
                                type: number
                              delta_pct:
                                type: number
                          profit:
                            type: object
                            properties:
                              current:
                                type: number
                              previous:
                                type: number
                              delta_pct:
                                type: number
                          active_brands:
                            type: object
                            properties:
                              current:
                                type: integer
                              previous:
                                type: integer
                              delta_pct:
                                type: number
                      hottest:
                        type: array
                        items:
                          type: object
                          properties:
                            brand_id:
                              type: integer
                            name:
                              type: string
                            value:
                              type: number
                            delta_pct:
                              type: number
                            spark:
                              type: array
                              items:
                                type: number
                      coldest:
                        type: array
                        items:
                          type: object
                          properties:
                            brand_id:
                              type: integer
                            name:
                              type: string
                            value:
                              type: number
                            delta_pct:
                              type: number
                            spark:
                              type: array
                              items:
                                type: number
                      heatmap:
                        type: object
                        properties:
                          columns:
                            type: array
                            items:
                              type: string
                          rows:
                            type: array
                            items:
                              type: object
                              properties:
                                brand_id:
                                  type: integer
                                name:
                                  type: string
                                cells:
                                  type: array
                                  items:
                                    type: string
                                    nullable: true
                      leaderboard:
                        type: array
                        items:
                          type: object
                          properties:
                            brand_id:
                              type: integer
                            name:
                              type: string
                            purchase_volume:
                              type: number
                            sales_volume:
                              type: number
                            units_purchased:
                              type: integer
                            units_sold:
                              type: integer
                            profit:
                              type: number
                            margin_pct:
                              type: number
                            growth_pct:
                              type: number
                            active_po_count:
                              type: integer
                            po_count:
                              type: integer
                            is_low_volume:
                              type: boolean
                      meta:
                        type: object
                        properties:
                          data_as_of:
                            type: string
                          period_label:
                            type: string
                          current_range:
                            type: array
                            items:
                              type: string
                          previous_range:
                            type: array
                            items:
                              type: string
                          is_partial:
                            type: boolean
                          is_live_query:
                            type: boolean
                example:
                  data:
                    kpis:
                      purchase_volume:
                        current: 1842500.5
                        previous: 1640200.0
                        delta_pct: 12.3
                      sales_volume:
                        current: 3120900.0
                        previous: 2890400.0
                        delta_pct: 8.0
                      profit:
                        current: 961000.25
                        previous: 905100.0
                        delta_pct: 6.2
                      active_brands:
                        current: 48
                        previous: 45
                        delta_pct: 6.7
                    hottest:
                    - brand_id: 42
                      name: Acme Housewares
                      value: 184250.5
                      delta_pct: 31.5
                      spark:
                      - 12000.0
                      - 13400.0
                      - 15600.0
                      - 14200.0
                      - 16800.0
                      - 17100.0
                      - 18900.0
                      - 16400.0
                      - 19200.0
                      - 21000.0
                      - 20400.0
                      - 22300.0
                    coldest:
                    - brand_id: 71
                      name: Borealis Home
                      value: 22400.0
                      delta_pct: -18.7
                      spark:
                      - 9100.0
                      - 8700.0
                      - 8200.0
                      - 7600.0
                      - 6900.0
                      - 6400.0
                      - 5800.0
                      - 5100.0
                      - 4700.0
                      - 4200.0
                      - 3900.0
                      - 3400.0
                    heatmap:
                      columns:
                      - 2025-06
                      - 2025-07
                      - 2025-08
                      - 2025-09
                      - 2025-10
                      - 2025-11
                      - 2025-12
                      - 2026-01
                      - 2026-02
                      - 2026-03
                      - 2026-04
                      - 2026-05
                      rows:
                      - brand_id: 42
                        name: Acme Housewares
                        cells:
                        - null
                        - 8.2
                        - 12.4
                        - -3.1
                        - 6.7
                        - 9.0
                        - 14.2
                        - -2.4
                        - 5.5
                        - 11.0
                        - 7.8
                        - 12.4
                    leaderboard:
                    - brand_id: 42
                      name: Acme Housewares
                      purchase_volume: 184250.5
                      sales_volume: 312900.0
                      units_purchased: 8400
                      units_sold: 7950
                      profit: 96100.25
                      margin_pct: 30.7
                      growth_pct: 12.4
                      active_po_count: 23
                      po_count: 21
                      is_low_volume: false
                    meta:
                      data_as_of: '2026-05-14T03:12:08+00:00'
                      period_label: YoY — May 2025 – May 2026 vs May 2024 – May 2025
                      current_range:
                      - '2025-05-16'
                      - '2026-05-15'
                      previous_range:
                      - '2024-05-16'
                      - '2025-05-15'
                      is_partial: false
                      is_live_query: false
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      period_mode:
                        type: array
                        items:
                          type: string
                      date_from:
                        type: array
                        items:
                          type: string
                example:
                  message: The given data was invalid.
                  errors:
                    period_mode:
                    - 'Period mode must be one of: yoy, qoq, mom, custom.'
                    date_from:
                    - A start date is required for a custom period.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-reporting-brands-overview
  /api/reporting/brands/leaderboard:
    get:
      tags:
      - Reporting
      summary: Get Brand Leaderboard
      description: 'Leaderboard rows only — a lightweight endpoint for table page/sort
        changes on the macro brand view, without recomputing KPIs, movers, or the
        heatmap. Rows are computed in-memory from snapshots, then filtered, sorted
        and sliced; low-volume brands are flagged via is_low_volume.


        Server-paginated (PRD edge case 15: 500+ brands) — returns the standard Laravel
        pagination envelope (data, current_page, last_page, per_page, total, etc.).


        Authentication: Requires Bearer token (scope: reports)


        Required parameters:

        - period_mode: yoy | qoq | mom | custom


        When period_mode=custom, date_from and date_to (YYYY-MM-DD or m/d/Y) are both
        required.


        Optional:

        - growth_basis: spend | sales | profit | margin (default: sales)

        - min_volume: numeric — low-volume threshold (default: 1000)

        - include_archived: boolean (default: false)

        - sort: sort key, prefix - for DESC. Allowed: name, purchase_volume, sales_volume,
        units_purchased, units_sold, profit, margin_pct, growth_pct, active_po_count
        (default: -purchase_volume)

        - page: page number (default: 1)

        - per_page: rows per page (default: 10)

        - filter[search]: substring match on brand name

        - filter[volume]: above | low — volume band filter'
      parameters:
      - name: period_mode
        in: query
        schema:
          type: string
        description: 'Required. Period comparison model: yoy | qoq | mom | custom'
        example: yoy
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        brand_id:
                          type: integer
                        name:
                          type: string
                        purchase_volume:
                          type: number
                        sales_volume:
                          type: number
                        units_purchased:
                          type: integer
                        units_sold:
                          type: integer
                        profit:
                          type: number
                        margin_pct:
                          type: number
                        growth_pct:
                          type: number
                        active_po_count:
                          type: integer
                        po_count:
                          type: integer
                        is_low_volume:
                          type: boolean
                  current_page:
                    type: integer
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  next_page_url:
                    type: string
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - brand_id: 42
                    name: Acme Housewares
                    purchase_volume: 184250.5
                    sales_volume: 312900.0
                    units_purchased: 8400
                    units_sold: 7950
                    profit: 96100.25
                    margin_pct: 30.7
                    growth_pct: 12.4
                    active_po_count: 23
                    po_count: 21
                    is_low_volume: false
                  - brand_id: 71
                    name: Borealis Home
                    purchase_volume: 22400.0
                    sales_volume: 41200.0
                    units_purchased: 980
                    units_sold: 910
                    profit: 9100.5
                    margin_pct: 22.1
                    growth_pct: -18.7
                    active_po_count: 4
                    po_count: 5
                    is_low_volume: false
                  current_page: 1
                  first_page_url: '{{protocol}}{{domain}}/api/reporting/brands/leaderboard?page=1'
                  from: 1
                  last_page: 5
                  last_page_url: '{{protocol}}{{domain}}/api/reporting/brands/leaderboard?page=5'
                  next_page_url: '{{protocol}}{{domain}}/api/reporting/brands/leaderboard?page=2'
                  path: '{{protocol}}{{domain}}/api/reporting/brands/leaderboard'
                  per_page: 10
                  prev_page_url: null
                  to: 10
                  total: 48
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      period_mode:
                        type: array
                        items:
                          type: string
                      date_from:
                        type: array
                        items:
                          type: string
                example:
                  message: The given data was invalid.
                  errors:
                    period_mode:
                    - 'Period mode must be one of: yoy, qoq, mom, custom.'
                    date_from:
                    - A start date is required for a custom period.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-reporting-brands-leaderboard
  /api/reporting/brands/rebuild-snapshots:
    post:
      tags:
      - Reporting
      summary: Rebuild Brand Metric Snapshots
      description: 'Dispatches the brand-metric snapshot rebuild as a tracked background
        job and returns its tracked job log ID for progress polling via the tracked
        job log endpoints. Rejects a second dispatch with 409 while a rebuild is already
        queued or running.


        Authentication: Requires Bearer token (scope: reports)


        This endpoint takes no request body.


        Note: no request body is required.'
      requestBody:
        content:
          application/json:
            schema:
              type: string
              example: ''
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 90871
                  message: Brand metric rebuild started.
        '409':
          description: Conflict
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: A brand metric rebuild is already in progress.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-reporting-brands-rebuild-snapshots
  /api/reporting/brands/scorecard-settings:
    get:
      tags:
      - Reporting
      summary: Get Brand Scorecard Settings
      description: 'Returns the tenant-global brand scorecard configuration: the six
        dimension weights (sum to 100), the ordered {min, score} threshold bands per
        dimension, and the minimum in-period PO count required before a brand is scored.
        A default row is created on first access if none exists.


        Authentication: Requires Bearer token (scope: reports)'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      weights:
                        type: object
                        properties:
                          on_time_delivery:
                            type: integer
                          lead_time_reliability:
                            type: integer
                          fill_rate:
                            type: integer
                          defect_rate:
                            type: integer
                          cost_competitiveness:
                            type: integer
                          price_stability:
                            type: integer
                      thresholds:
                        type: object
                        properties:
                          on_time_delivery:
                            type: array
                            items:
                              type: object
                              properties:
                                min:
                                  type: integer
                                score:
                                  type: integer
                          lead_time_reliability:
                            type: array
                            items:
                              type: object
                              properties:
                                min:
                                  type: integer
                                score:
                                  type: integer
                          fill_rate:
                            type: array
                            items:
                              type: object
                              properties:
                                min:
                                  type: integer
                                score:
                                  type: integer
                          defect_rate:
                            type: array
                            items:
                              type: object
                              properties:
                                min:
                                  type: integer
                                score:
                                  type: integer
                          cost_competitiveness:
                            type: array
                            items:
                              type: object
                              properties:
                                min:
                                  type: integer
                                score:
                                  type: integer
                          price_stability:
                            type: array
                            items:
                              type: object
                              properties:
                                min:
                                  type: integer
                                score:
                                  type: integer
                      min_po_count:
                        type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 1
                    weights:
                      on_time_delivery: 25
                      lead_time_reliability: 15
                      fill_rate: 15
                      defect_rate: 15
                      cost_competitiveness: 25
                      price_stability: 5
                    thresholds:
                      on_time_delivery:
                      - min: 97
                        score: 5
                      - min: 90
                        score: 4
                      - min: 80
                        score: 3
                      - min: 60
                        score: 2
                      - min: 0
                        score: 1
                      lead_time_reliability:
                      - min: 97
                        score: 5
                      - min: 90
                        score: 4
                      - min: 80
                        score: 3
                      - min: 60
                        score: 2
                      - min: 0
                        score: 1
                      fill_rate:
                      - min: 97
                        score: 5
                      - min: 90
                        score: 4
                      - min: 80
                        score: 3
                      - min: 60
                        score: 2
                      - min: 0
                        score: 1
                      defect_rate:
                      - min: 97
                        score: 5
                      - min: 90
                        score: 4
                      - min: 80
                        score: 3
                      - min: 60
                        score: 2
                      - min: 0
                        score: 1
                      cost_competitiveness:
                      - min: 97
                        score: 5
                      - min: 90
                        score: 4
                      - min: 80
                        score: 3
                      - min: 60
                        score: 2
                      - min: 0
                        score: 1
                      price_stability:
                      - min: 97
                        score: 5
                      - min: 90
                        score: 4
                      - min: 80
                        score: 3
                      - min: 60
                        score: 2
                      - min: 0
                        score: 1
                    min_po_count: 3
                    created_at: '2026-01-04T09:00:00.000000Z'
                    updated_at: '2026-05-10T14:22:31.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-reporting-brands-scorecard-settings
    put:
      tags:
      - Reporting
      summary: Update Brand Scorecard Settings
      description: 'Updates the tenant-global brand scorecard configuration. The six
        weights must each be present and sum to exactly 100; every threshold band
        needs a numeric min and an integer 1-5 score.


        Authentication: Requires Bearer token (scope: reports)


        Request body fields:

        - weights: object (required) — must contain all six metric keys; values numeric
        0-100, summing to exactly 100

        - weights.on_time_delivery: numeric, 0-100 (required)

        - weights.lead_time_reliability: numeric, 0-100 (required)

        - weights.fill_rate: numeric, 0-100 (required)

        - weights.defect_rate: numeric, 0-100 (required)

        - weights.cost_competitiveness: numeric, 0-100 (required)

        - weights.price_stability: numeric, 0-100 (required)

        - thresholds: object (required) — must contain all six metric keys

        - thresholds.{metric}: array, min 1 item (required) — ordered {min, score}
        bands

        - thresholds.{metric}.*.min: numeric (required) — lower bound of the band

        - thresholds.{metric}.*.score: integer 1-5 (required) — score awarded for
        the band

        - min_po_count: integer, min 1 (required)'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                weights:
                  type: object
                  properties:
                    on_time_delivery:
                      type: integer
                    lead_time_reliability:
                      type: integer
                    fill_rate:
                      type: integer
                    defect_rate:
                      type: integer
                    cost_competitiveness:
                      type: integer
                    price_stability:
                      type: integer
                thresholds:
                  type: object
                  properties:
                    on_time_delivery:
                      type: array
                      items:
                        type: object
                        properties:
                          min:
                            type: integer
                          score:
                            type: integer
                    lead_time_reliability:
                      type: array
                      items:
                        type: object
                        properties:
                          min:
                            type: integer
                          score:
                            type: integer
                    fill_rate:
                      type: array
                      items:
                        type: object
                        properties:
                          min:
                            type: integer
                          score:
                            type: integer
                    defect_rate:
                      type: array
                      items:
                        type: object
                        properties:
                          min:
                            type: integer
                          score:
                            type: integer
                    cost_competitiveness:
                      type: array
                      items:
                        type: object
                        properties:
                          min:
                            type: integer
                          score:
                            type: integer
                    price_stability:
                      type: array
                      items:
                        type: object
                        properties:
                          min:
                            type: integer
                          score:
                            type: integer
                min_po_count:
                  type: integer
              example:
                weights:
                  on_time_delivery: 25
                  lead_time_reliability: 15
                  fill_rate: 15
                  defect_rate: 15
                  cost_competitiveness: 25
                  price_stability: 5
                thresholds:
                  on_time_delivery:
                  - min: 97
                    score: 5
                  - min: 90
                    score: 4
                  - min: 80
                    score: 3
                  - min: 60
                    score: 2
                  - min: 0
                    score: 1
                  lead_time_reliability:
                  - min: 97
                    score: 5
                  - min: 90
                    score: 4
                  - min: 80
                    score: 3
                  - min: 60
                    score: 2
                  - min: 0
                    score: 1
                  fill_rate:
                  - min: 97
                    score: 5
                  - min: 90
                    score: 4
                  - min: 80
                    score: 3
                  - min: 60
                    score: 2
                  - min: 0
                    score: 1
                  defect_rate:
                  - min: 97
                    score: 5
                  - min: 90
                    score: 4
                  - min: 80
                    score: 3
                  - min: 60
                    score: 2
                  - min: 0
                    score: 1
                  cost_competitiveness:
                  - min: 97
                    score: 5
                  - min: 90
                    score: 4
                  - min: 80
                    score: 3
                  - min: 60
                    score: 2
                  - min: 0
                    score: 1
                  price_stability:
                  - min: 97
                    score: 5
                  - min: 90
                    score: 4
                  - min: 80
                    score: 3
                  - min: 60
                    score: 2
                  - min: 0
                    score: 1
                min_po_count: 3
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      weights:
                        type: object
                        properties:
                          on_time_delivery:
                            type: integer
                          lead_time_reliability:
                            type: integer
                          fill_rate:
                            type: integer
                          defect_rate:
                            type: integer
                          cost_competitiveness:
                            type: integer
                          price_stability:
                            type: integer
                      thresholds:
                        type: object
                        properties:
                          on_time_delivery:
                            type: array
                            items:
                              type: object
                              properties:
                                min:
                                  type: integer
                                score:
                                  type: integer
                          lead_time_reliability:
                            type: array
                            items:
                              type: object
                              properties:
                                min:
                                  type: integer
                                score:
                                  type: integer
                          fill_rate:
                            type: array
                            items:
                              type: object
                              properties:
                                min:
                                  type: integer
                                score:
                                  type: integer
                          defect_rate:
                            type: array
                            items:
                              type: object
                              properties:
                                min:
                                  type: integer
                                score:
                                  type: integer
                          cost_competitiveness:
                            type: array
                            items:
                              type: object
                              properties:
                                min:
                                  type: integer
                                score:
                                  type: integer
                          price_stability:
                            type: array
                            items:
                              type: object
                              properties:
                                min:
                                  type: integer
                                score:
                                  type: integer
                      min_po_count:
                        type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 1
                    weights:
                      on_time_delivery: 25
                      lead_time_reliability: 15
                      fill_rate: 15
                      defect_rate: 15
                      cost_competitiveness: 25
                      price_stability: 5
                    thresholds:
                      on_time_delivery:
                      - min: 97
                        score: 5
                      - min: 90
                        score: 4
                      - min: 80
                        score: 3
                      - min: 60
                        score: 2
                      - min: 0
                        score: 1
                      lead_time_reliability:
                      - min: 97
                        score: 5
                      - min: 90
                        score: 4
                      - min: 80
                        score: 3
                      - min: 60
                        score: 2
                      - min: 0
                        score: 1
                      fill_rate:
                      - min: 97
                        score: 5
                      - min: 90
                        score: 4
                      - min: 80
                        score: 3
                      - min: 60
                        score: 2
                      - min: 0
                        score: 1
                      defect_rate:
                      - min: 97
                        score: 5
                      - min: 90
                        score: 4
                      - min: 80
                        score: 3
                      - min: 60
                        score: 2
                      - min: 0
                        score: 1
                      cost_competitiveness:
                      - min: 97
                        score: 5
                      - min: 90
                        score: 4
                      - min: 80
                        score: 3
                      - min: 60
                        score: 2
                      - min: 0
                        score: 1
                      price_stability:
                      - min: 97
                        score: 5
                      - min: 90
                        score: 4
                      - min: 80
                        score: 3
                      - min: 60
                        score: 2
                      - min: 0
                        score: 1
                    min_po_count: 3
                    created_at: '2026-01-04T09:00:00.000000Z'
                    updated_at: '2026-05-10T14:22:31.000000Z'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      weights:
                        type: array
                        items:
                          type: string
                      min_po_count:
                        type: array
                        items:
                          type: string
                      thresholds.fill_rate:
                        type: array
                        items:
                          type: string
                example:
                  message: The given data was invalid.
                  errors:
                    weights:
                    - Scorecard weights must sum to exactly 100 (currently 95).
                    min_po_count:
                    - The minimum PO count must be at least 1.
                    thresholds.fill_rate:
                    - Threshold bands are required for every scorecard metric.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: put-api-reporting-brands-scorecard-settings
  /api/reporting/brands/{brand}/scorecard-summary:
    get:
      tags:
      - Reporting
      summary: Get Brand Scorecard Summary
      description: 'Lightweight scorecard + volume sparklines for the brand Profile
        chip. Returns the composite scorecard with its dimension breakdown, a directional
        composite trend hint (up | down | flat), and trailing-12-month purchase/sales
        volume sparklines. The period is fixed to YoY.


        Authentication: Requires Bearer token (scope: reports)


        Path parameters:

        - brand: the Brand ID'
      parameters:
      - name: brand
        in: path
        schema:
          type: string
        required: true
        description: The brand ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      brand:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      scorecard:
                        type: object
                        properties:
                          composite:
                            type: number
                          band:
                            type: string
                          is_sufficient:
                            type: boolean
                          po_count:
                            type: integer
                          dimensions:
                            type: array
                            items:
                              type: object
                              properties:
                                key:
                                  type: string
                                label:
                                  type: string
                                raw:
                                  type: number
                                raw_display:
                                  type: string
                                score:
                                  type: integer
                                weight:
                                  type: number
                      composite_trend:
                        type: string
                      purchase_volume:
                        type: object
                        properties:
                          current:
                            type: number
                          previous:
                            type: number
                          delta_pct:
                            type: number
                          spark:
                            type: array
                            items:
                              type: number
                      sales_volume:
                        type: object
                        properties:
                          current:
                            type: number
                          previous:
                            type: number
                          delta_pct:
                            type: number
                          spark:
                            type: array
                            items:
                              type: number
                      meta:
                        type: object
                        properties:
                          data_as_of:
                            type: string
                          period_label:
                            type: string
                          current_range:
                            type: array
                            items:
                              type: string
                          previous_range:
                            type: array
                            items:
                              type: string
                          is_partial:
                            type: boolean
                          is_live_query:
                            type: boolean
                example:
                  data:
                    brand:
                      id: 42
                      name: Acme Housewares
                    scorecard:
                      composite: 4.15
                      band: good
                      is_sufficient: true
                      po_count: 18
                      dimensions:
                      - key: on_time_delivery
                        label: On-Time Delivery
                        raw: 92.3
                        raw_display: 92.3%
                        score: 4
                        weight: 25.0
                      - key: lead_time_reliability
                        label: Lead-Time Reliability
                        raw: 88.0
                        raw_display: 88.0%
                        score: 3
                        weight: 15.0
                      - key: fill_rate
                        label: Fill Rate
                        raw: 98.6
                        raw_display: 98.6%
                        score: 5
                        weight: 15.0
                      - key: defect_rate
                        label: Defect / RTV Rate
                        raw: 1.2
                        raw_display: 1.2%
                        score: 5
                        weight: 15.0
                      - key: cost_competitiveness
                        label: Cost Competitiveness
                        raw: 74.5
                        raw_display: 74.5 / 100
                        score: 3
                        weight: 25.0
                      - key: price_stability
                        label: Price Stability
                        raw: 0.18
                        raw_display: 18% price increases
                        score: 4
                        weight: 5.0
                    composite_trend: up
                    purchase_volume:
                      current: 184250.5
                      previous: 158900.0
                      delta_pct: 16.0
                      spark:
                      - 12000.0
                      - 13400.0
                      - 15600.0
                      - 14200.0
                      - 16800.0
                      - 17100.0
                      - 18900.0
                      - 16400.0
                      - 19200.0
                      - 21000.0
                      - 20400.0
                      - 22300.0
                    sales_volume:
                      current: 312900.0
                      previous: 289400.0
                      delta_pct: 8.1
                      spark:
                      - 22000.0
                      - 23100.0
                      - 24800.0
                      - 25600.0
                      - 26100.0
                      - 27400.0
                      - 26900.0
                      - 28200.0
                      - 29400.0
                      - 30100.0
                      - 31200.0
                      - 32400.0
                    meta:
                      data_as_of: '2026-05-14T03:12:08+00:00'
                      period_label: YoY — May 2025 – May 2026 vs May 2024 – May 2025
                      current_range:
                      - '2025-05-16'
                      - '2026-05-15'
                      previous_range:
                      - '2024-05-16'
                      - '2025-05-15'
                      is_partial: false
                      is_live_query: false
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No query results for model [App\Models\ProductBrand].
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-reporting-brands-brand-scorecard-summary
  /api/reporting/brands/{brand}/analytics:
    get:
      tags:
      - Reporting
      summary: Get Brand Analytics
      description: 'Full per-brand analytics for the Analytics tab: headline KPIs
        (purchase volume, sales volume, units purchased/sold, profit, margin %), the
        composite scorecard, a dual-line current-vs-previous trend chart, and the
        hottest/coolest products ranked by growth.


        Authentication: Requires Bearer token (scope: reports)


        Path parameters:

        - brand: the Brand ID


        Required parameters:

        - period_mode: yoy | qoq | mom | custom


        When period_mode=custom, date_from and date_to (YYYY-MM-DD or m/d/Y) are both
        required.


        Optional:

        - growth_basis: spend | sales | profit | margin (default: sales) — drives
        the trend metric and product mover ranking

        - min_volume: numeric (default: 1000)

        - include_archived: boolean (default: false)


        The response also includes `product_heatmap` (a period-aware per-product growth
        heatmap — the brand''s top products by volume, each cell a period-over-period
        change that follows the `period_mode` selector) and `calendar_year_volume`
        (per calendar year for the trailing 5 years: non-draft PO spend with units/PO
        counts plus non-draft sales revenue with units/order counts; the current year
        is year-to-date and is independent of `period_mode`).'
      parameters:
      - name: period_mode
        in: query
        schema:
          type: string
        description: 'Required. Period comparison model: yoy | qoq | mom | custom'
        example: yoy
      - name: brand
        in: path
        schema:
          type: string
        required: true
        description: The brand ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      brand:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      kpis:
                        type: object
                        properties:
                          purchase_volume:
                            type: object
                            properties:
                              current:
                                type: number
                              previous:
                                type: number
                              delta_pct:
                                type: number
                          sales_volume:
                            type: object
                            properties:
                              current:
                                type: number
                              previous:
                                type: number
                              delta_pct:
                                type: number
                          units_purchased:
                            type: object
                            properties:
                              current:
                                type: integer
                              previous:
                                type: integer
                              delta_pct:
                                type: number
                          units_sold:
                            type: object
                            properties:
                              current:
                                type: integer
                              previous:
                                type: integer
                              delta_pct:
                                type: number
                          profit:
                            type: object
                            properties:
                              current:
                                type: number
                              previous:
                                type: number
                              delta_pct:
                                type: number
                          margin_pct:
                            type: object
                            properties:
                              current:
                                type: number
                              previous:
                                type: number
                              delta_pct:
                                type: number
                      scorecard:
                        type: object
                        properties:
                          composite:
                            type: number
                          band:
                            type: string
                          is_sufficient:
                            type: boolean
                          po_count:
                            type: integer
                          dimensions:
                            type: array
                            items:
                              type: object
                              properties:
                                key:
                                  type: string
                                label:
                                  type: string
                                raw:
                                  type: number
                                raw_display:
                                  type: string
                                score:
                                  type: integer
                                weight:
                                  type: number
                      trend:
                        type: object
                        properties:
                          metric:
                            type: string
                          buckets:
                            type: array
                            items:
                              type: string
                          current:
                            type: array
                            items:
                              type: number
                          previous:
                            type: array
                            items:
                              type: number
                      hottest_products:
                        type: array
                        items:
                          type: object
                          properties:
                            product_id:
                              type: integer
                            sku:
                              type: string
                            name:
                              type: string
                            value:
                              type: number
                            delta_pct:
                              type: number
                      coolest_products:
                        type: array
                        items:
                          type: object
                          properties:
                            product_id:
                              type: integer
                            sku:
                              type: string
                            name:
                              type: string
                            value:
                              type: number
                            delta_pct:
                              type: number
                      product_heatmap:
                        type: object
                        properties:
                          columns:
                            type: array
                            items:
                              type: string
                          rows:
                            type: array
                            items:
                              type: object
                              properties:
                                product_id:
                                  type: integer
                                sku:
                                  type: string
                                name:
                                  type: string
                                cells:
                                  type: array
                                  items:
                                    type: object
                                    properties:
                                      delta:
                                        type: string
                                        nullable: true
                                      current_value:
                                        type: number
                                      previous_value:
                                        type: string
                                        nullable: true
                                      compare_period:
                                        type: string
                      calendar_year_volume:
                        type: array
                        items:
                          type: object
                          properties:
                            year:
                              type: integer
                            purchase_volume:
                              type: number
                            units_purchased:
                              type: integer
                            po_count:
                              type: integer
                            sales_volume:
                              type: number
                            units_sold:
                              type: integer
                            so_count:
                              type: integer
                      meta:
                        type: object
                        properties:
                          data_as_of:
                            type: string
                          period_label:
                            type: string
                          current_range:
                            type: array
                            items:
                              type: string
                          previous_range:
                            type: array
                            items:
                              type: string
                          is_partial:
                            type: boolean
                          is_live_query:
                            type: boolean
                example:
                  data:
                    brand:
                      id: 42
                      name: Acme Housewares
                    kpis:
                      purchase_volume:
                        current: 184250.5
                        previous: 158900.0
                        delta_pct: 16.0
                      sales_volume:
                        current: 312900.0
                        previous: 289400.0
                        delta_pct: 8.1
                      units_purchased:
                        current: 8400
                        previous: 7600
                        delta_pct: 10.5
                      units_sold:
                        current: 7950
                        previous: 7400
                        delta_pct: 7.4
                      profit:
                        current: 96100.25
                        previous: 88200.0
                        delta_pct: 9.0
                      margin_pct:
                        current: 30.7
                        previous: 30.5
                        delta_pct: 0.2
                    scorecard:
                      composite: 4.15
                      band: good
                      is_sufficient: true
                      po_count: 18
                      dimensions:
                      - key: on_time_delivery
                        label: On-Time Delivery
                        raw: 92.3
                        raw_display: 92.3%
                        score: 4
                        weight: 25.0
                      - key: lead_time_reliability
                        label: Lead-Time Reliability
                        raw: 88.0
                        raw_display: 88.0%
                        score: 3
                        weight: 15.0
                      - key: fill_rate
                        label: Fill Rate
                        raw: 98.6
                        raw_display: 98.6%
                        score: 5
                        weight: 15.0
                      - key: defect_rate
                        label: Defect / RTV Rate
                        raw: 1.2
                        raw_display: 1.2%
                        score: 5
                        weight: 15.0
                      - key: cost_competitiveness
                        label: Cost Competitiveness
                        raw: 74.5
                        raw_display: 74.5 / 100
                        score: 3
                        weight: 25.0
                      - key: price_stability
                        label: Price Stability
                        raw: 0.18
                        raw_display: 18% price increases
                        score: 4
                        weight: 5.0
                    trend:
                      metric: sales
                      buckets:
                      - 2025-05
                      - 2025-06
                      - 2025-07
                      - 2025-08
                      - 2025-09
                      - 2025-10
                      - 2025-11
                      - 2025-12
                      - 2026-01
                      - 2026-02
                      - 2026-03
                      - 2026-04
                      current:
                      - 14200.0
                      - 15600.0
                      - 16800.0
                      - 17100.0
                      - 18900.0
                      - 16400.0
                      - 19200.0
                      - 21000.0
                      - 20400.0
                      - 22300.0
                      - 21800.0
                      - 23400.0
                      previous:
                      - 12100.0
                      - 13400.0
                      - 14000.0
                      - 14900.0
                      - 15600.0
                      - 14100.0
                      - 16800.0
                      - 18200.0
                      - 17900.0
                      - 19400.0
                      - 18800.0
                      - 20100.0
                    hottest_products:
                    - product_id: 9001
                      sku: ACM-WIDGET-01
                      name: Widget Assembly Type A
                      value: 42100.0
                      delta_pct: 34.2
                    coolest_products:
                    - product_id: 9044
                      sku: ACM-BRACKET-12
                      name: Mounting Bracket XL
                      value: 6200.0
                      delta_pct: -21.8
                    product_heatmap:
                      columns:
                      - 2025-05
                      - 2025-06
                      - 2025-07
                      - 2025-08
                      - 2025-09
                      - 2025-10
                      - 2025-11
                      - 2025-12
                      - 2026-01
                      - 2026-02
                      - 2026-03
                      - 2026-04
                      rows:
                      - product_id: 9001
                        sku: ACM-WIDGET-01
                        name: Widget Assembly Type A
                        cells:
                        - delta: null
                          current_value: 11800.0
                          previous_value: null
                          compare_period: 2024-05
                        - delta: 12.4
                          current_value: 13300.0
                          previous_value: 11830.0
                          compare_period: 2024-06
                        - delta: 8.1
                          current_value: 14380.0
                          previous_value: 13300.0
                          compare_period: 2024-07
                        - delta: -3.2
                          current_value: 13920.0
                          previous_value: 14380.0
                          compare_period: 2024-08
                        - delta: 19.5
                          current_value: 16640.0
                          previous_value: 13920.0
                          compare_period: 2024-09
                        - delta: -6.7
                          current_value: 15520.0
                          previous_value: 16640.0
                          compare_period: 2024-10
                        - delta: 22.0
                          current_value: 18940.0
                          previous_value: 15520.0
                          compare_period: 2024-11
                        - delta: 9.3
                          current_value: 20700.0
                          previous_value: 18940.0
                          compare_period: 2024-12
                        - delta: -2.4
                          current_value: 20200.0
                          previous_value: 20700.0
                          compare_period: 2025-01
                        - delta: 10.4
                          current_value: 22300.0
                          previous_value: 20200.0
                          compare_period: 2025-02
                        - delta: -2.2
                          current_value: 21800.0
                          previous_value: 22300.0
                          compare_period: 2025-03
                        - delta: 7.3
                          current_value: 23400.0
                          previous_value: 21800.0
                          compare_period: 2025-04
                    calendar_year_volume:
                    - year: 2022
                      purchase_volume: 142300.0
                      units_purchased: 6100
                      po_count: 12
                      sales_volume: 238700.0
                      units_sold: 5840
                      so_count: 214
                    - year: 2023
                      purchase_volume: 168900.0
                      units_purchased: 7050
                      po_count: 14
                      sales_volume: 281400.0
                      units_sold: 6720
                      so_count: 248
                    - year: 2024
                      purchase_volume: 191450.0
                      units_purchased: 7780
                      po_count: 16
                      sales_volume: 309600.0
                      units_sold: 7410
                      so_count: 271
                    - year: 2025
                      purchase_volume: 224800.0
                      units_purchased: 8640
                      po_count: 19
                      sales_volume: 352100.0
                      units_sold: 8190
                      so_count: 305
                    - year: 2026
                      purchase_volume: 86200.0
                      units_purchased: 3320
                      po_count: 7
                      sales_volume: 131900.0
                      units_sold: 3040
                      so_count: 118
                    meta:
                      data_as_of: '2026-05-14T03:12:08+00:00'
                      period_label: YoY — May 2025 – May 2026 vs May 2024 – May 2025
                      current_range:
                      - '2025-05-16'
                      - '2026-05-15'
                      previous_range:
                      - '2024-05-16'
                      - '2025-05-15'
                      is_partial: false
                      is_live_query: false
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No query results for model [App\Models\ProductBrand].
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      period_mode:
                        type: array
                        items:
                          type: string
                      date_from:
                        type: array
                        items:
                          type: string
                example:
                  message: The given data was invalid.
                  errors:
                    period_mode:
                    - 'Period mode must be one of: yoy, qoq, mom, custom.'
                    date_from:
                    - A start date is required for a custom period.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-reporting-brands-brand-analytics
  /api/reporting/brands/{brand}/products:
    get:
      tags:
      - Reporting
      summary: Get Brand Product Breakdown
      description: 'Paginated, sortable per-product breakdown for one brand (Analytics-tab
        product table). Each row carries units, purchase/sales volume, profit, margin
        %, sell-through %, landed unit cost, the landed-cost trend direction (cost_trend),
        and period-over-period growth %.


        Authentication: Requires Bearer token (scope: reports)


        Path parameters:

        - brand: the Brand ID


        Required parameters:

        - period_mode: yoy | qoq | mom | custom


        When period_mode=custom, date_from and date_to (YYYY-MM-DD or m/d/Y) are both
        required.


        Filters (Spatie QueryBuilder):

        - filter[search]: partial match on product SKU or name

        - filter[cost_trend]: landed-unit-cost trend direction — up | down | flat

        - filter[margin]: margin sign — positive (margin > 0) | negative (margin <
        0)


        Sort (sort param, prefix - for DESC). Allowed: units_purchased, units_sold,
        purchase_volume, sales_volume, profit, margin_pct, sell_through_pct, growth_pct.
        Default: -purchase_volume


        Pagination: page (default 1), per_page (default 10).


        Optional:

        - growth_basis: spend | sales | profit | margin (default: sales) — drives
        the growth_pct column

        - min_volume, include_archived


        Response field cost_trend: up | down | flat — direction of the landed unit
        cost vs the prior period (always present, defaults to flat).'
      parameters:
      - name: period_mode
        in: query
        schema:
          type: string
        description: 'Required. Period comparison model: yoy | qoq | mom | custom'
        example: yoy
      - name: brand
        in: path
        schema:
          type: string
        required: true
        description: The brand ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        product_id:
                          type: integer
                        sku:
                          type: string
                        name:
                          type: string
                        units_purchased:
                          type: integer
                        units_sold:
                          type: integer
                        purchase_volume:
                          type: number
                        sales_volume:
                          type: number
                        profit:
                          type: number
                        margin_pct:
                          type: number
                        sell_through_pct:
                          type: number
                        landed_unit_cost:
                          type: number
                        cost_trend:
                          type: string
                        growth_pct:
                          type: number
                  current_page:
                    type: integer
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  next_page_url:
                    type: string
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - product_id: 9001
                    sku: ACM-WIDGET-01
                    name: Widget Assembly Type A
                    units_purchased: 3200
                    units_sold: 3050
                    purchase_volume: 42100.0
                    sales_volume: 78900.0
                    profit: 24600.0
                    margin_pct: 31.2
                    sell_through_pct: 95.3
                    landed_unit_cost: 13.16
                    cost_trend: up
                    growth_pct: 34.2
                  - product_id: 9044
                    sku: ACM-BRACKET-12
                    name: Mounting Bracket XL
                    units_purchased: 540
                    units_sold: 410
                    purchase_volume: 6200.0
                    sales_volume: 9800.0
                    profit: 2100.0
                    margin_pct: 21.4
                    sell_through_pct: 75.9
                    landed_unit_cost: 11.48
                    cost_trend: down
                    growth_pct: -21.8
                  current_page: 1
                  first_page_url: '{{protocol}}{{domain}}/api/reporting/brands/42/products?page=1'
                  from: 1
                  last_page: 5
                  last_page_url: '{{protocol}}{{domain}}/api/reporting/brands/42/products?page=5'
                  next_page_url: '{{protocol}}{{domain}}/api/reporting/brands/42/products?page=2'
                  path: '{{protocol}}{{domain}}/api/reporting/brands/42/products'
                  per_page: 10
                  prev_page_url: null
                  to: 10
                  total: 47
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No query results for model [App\Models\ProductBrand].
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      period_mode:
                        type: array
                        items:
                          type: string
                      date_from:
                        type: array
                        items:
                          type: string
                example:
                  message: The given data was invalid.
                  errors:
                    period_mode:
                    - 'Period mode must be one of: yoy, qoq, mom, custom.'
                    date_from:
                    - A start date is required for a custom period.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-reporting-brands-brand-products
  /api/reporting/brands/{brand}/products/{product}:
    get:
      tags:
      - Reporting
      summary: Get Brand Product Drilldown
      description: 'Single-product drill-down for one brand: current vs previous purchase/sales
        totals, a landed-cost-per-receipt trend, and the list of suppliers carrying
        the same SKU with their cost, lead time and reliability.


        Authentication: Requires Bearer token (scope: reports)


        Path parameters:

        - brand: the Brand ID

        - product: the Product ID


        Required parameters:

        - period_mode: yoy | qoq | mom | custom


        When period_mode=custom, date_from and date_to (YYYY-MM-DD or m/d/Y) are both
        required.


        Optional:

        - growth_basis: spend | sales | profit | margin (default: sales)

        - min_volume, include_archived'
      parameters:
      - name: period_mode
        in: query
        schema:
          type: string
        description: 'Required. Period comparison model: yoy | qoq | mom | custom'
        example: yoy
      - name: brand
        in: path
        schema:
          type: string
        required: true
        description: The brand ID.
      - name: product
        in: path
        schema:
          type: string
        required: true
        description: The product ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      current:
                        type: object
                        properties:
                          product_id:
                            type: integer
                          sku:
                            type: string
                          name:
                            type: string
                          purchase_volume:
                            type: number
                          units_purchased:
                            type: number
                          sales_volume:
                            type: number
                          units_sold:
                            type: number
                          profit:
                            type: number
                          margin:
                            type: number
                      previous:
                        type: object
                        properties:
                          product_id:
                            type: integer
                          sku:
                            type: string
                          name:
                            type: string
                          purchase_volume:
                            type: number
                          units_purchased:
                            type: number
                          sales_volume:
                            type: number
                          units_sold:
                            type: number
                          profit:
                            type: number
                          margin:
                            type: number
                      landed_cost_trend:
                        type: array
                        items:
                          type: object
                          properties:
                            date:
                              type: string
                            po_number:
                              type: string
                            unit_cost:
                              type: number
                      suppliers:
                        type: array
                        items:
                          type: object
                          properties:
                            supplier_id:
                              type: integer
                            name:
                              type: string
                            landed_unit_cost:
                              type: number
                            leadtime:
                              type: integer
                            lead_time_reliability_pct:
                              type: number
                            is_default:
                              type: boolean
                      brand:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      product:
                        type: object
                        properties:
                          id:
                            type: integer
                          sku:
                            type: string
                      meta:
                        type: object
                        properties:
                          data_as_of:
                            type: string
                          period_label:
                            type: string
                          current_range:
                            type: array
                            items:
                              type: string
                          previous_range:
                            type: array
                            items:
                              type: string
                          is_partial:
                            type: boolean
                          is_live_query:
                            type: boolean
                example:
                  data:
                    current:
                      product_id: 9001
                      sku: ACM-WIDGET-01
                      name: Widget Assembly Type A
                      purchase_volume: 42100.0
                      units_purchased: 3200.0
                      sales_volume: 78900.0
                      units_sold: 3050.0
                      profit: 24600.0
                      margin: 0.0
                    previous:
                      product_id: 9001
                      sku: ACM-WIDGET-01
                      name: Widget Assembly Type A
                      purchase_volume: 31400.0
                      units_purchased: 2400.0
                      sales_volume: 58200.0
                      units_sold: 2280.0
                      profit: 17900.0
                      margin: 0.0
                    landed_cost_trend:
                    - date: '2025-07-12'
                      po_number: PO-100482
                      unit_cost: 13.4
                    - date: '2025-11-03'
                      po_number: PO-101655
                      unit_cost: 13.16
                    - date: '2026-02-21'
                      po_number: PO-103120
                      unit_cost: 12.95
                    suppliers:
                    - supplier_id: 58
                      name: Globex Manufacturing
                      landed_unit_cost: 12.1
                      leadtime: 21
                      lead_time_reliability_pct: 91.5
                      is_default: false
                    - supplier_id: 73
                      name: Initech Hardware
                      landed_unit_cost: 14.05
                      leadtime: 35
                      lead_time_reliability_pct: null
                      is_default: false
                    brand:
                      id: 42
                      name: Acme Housewares
                    product:
                      id: 9001
                      sku: ACM-WIDGET-01
                    meta:
                      data_as_of: '2026-05-14T03:12:08+00:00'
                      period_label: YoY — May 2025 – May 2026 vs May 2024 – May 2025
                      current_range:
                      - '2025-05-16'
                      - '2026-05-15'
                      previous_range:
                      - '2024-05-16'
                      - '2025-05-15'
                      is_partial: false
                      is_live_query: false
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No query results for model [App\Models\ProductBrand].
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      period_mode:
                        type: array
                        items:
                          type: string
                      date_from:
                        type: array
                        items:
                          type: string
                example:
                  message: The given data was invalid.
                  errors:
                    period_mode:
                    - 'Period mode must be one of: yoy, qoq, mom, custom.'
                    date_from:
                    - A start date is required for a custom period.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-reporting-brands-brand-products-product
  /api/reporting/brands/{brand}/po-history:
    get:
      tags:
      - Reporting
      summary: Get Brand PO History
      description: 'Recent purchase orders containing one brand''s products — backs
        the "Recent Purchase Orders" mini-table on the brand Analytics tab. Returns
        up to the 10 most recent non-draft purchase orders ordered by purchase order
        date (DESC), each with its receipt status and an on-time flag.


        Authentication: Requires Bearer token (scope: reports)


        Path parameters:

        - brand: the Brand ID


        This endpoint is period-independent — it always returns the most recent purchase
        orders and takes no query parameters. Draft purchase orders are excluded.


        Response fields per row:

        - id: purchase order ID

        - po_number: human-readable purchase order number

        - purchase_order_date: order date (Y-m-d)

        - total_cost: total purchase order cost

        - receipt_status: receipt status of the PO (e.g. unreceived, partially_received,
        fully_received)

        - on_time: true if fully received on or before the estimated delivery date,
        false if late, null if not yet fully received'
      parameters:
      - name: brand
        in: path
        schema:
          type: integer
        required: true
        description: The Brand ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        po_number:
                          type: string
                        purchase_order_date:
                          type: string
                        total_cost:
                          type: number
                        receipt_status:
                          type: string
                        on_time:
                          type: boolean
                example:
                  data:
                  - id: 8821
                    po_number: PO-2025-0142
                    purchase_order_date: '2025-05-08'
                    total_cost: 42100.0
                    receipt_status: fully_received
                    on_time: true
                  - id: 8790
                    po_number: PO-2025-0118
                    purchase_order_date: '2025-04-22'
                    total_cost: 6200.5
                    receipt_status: partially_received
                    on_time: null
                  - id: 8755
                    po_number: PO-2025-0091
                    purchase_order_date: '2025-03-30'
                    total_cost: 18750.0
                    receipt_status: fully_received
                    on_time: false
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No query results for model [App\Models\ProductBrand].
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-reporting-brands-brand-po-history
  /api/reporting/brands/{brand}/scorecard:
    get:
      tags:
      - Reporting
      summary: Get Brand Scorecard
      description: 'Standalone composite scorecard for a brand over the resolved period
        — the composite, its band, and the per-dimension breakdown.


        The band is one of: excellent, good, needs_attention, poor. When the brand
        has fewer received POs than the configured minimum (is_sufficient=false),
        the band is not_rated and composite is 0.


        Live preview: when the optional preview_weights, preview_thresholds and preview_min_po_count
        parameters are supplied (all three together), the score is computed against
        a transient, non-persisted settings instance built from those values. Nothing
        is written to the scorecard settings table. preview_weights must contain all
        six metric keys and sum to exactly 100.


        Authentication: Requires Bearer token (scope: reports)


        Path parameters:

        - brand: the Brand ID


        Required parameters:

        - period_mode: yoy | qoq | mom | custom


        When period_mode=custom, date_from and date_to (YYYY-MM-DD or m/d/Y) are both
        required.


        Optional period params:

        - growth_basis: spend | sales | profit | margin (default: sales)

        - min_volume, include_archived


        Optional live-preview params (all three required together when previewing):

        - preview_weights[{metric}]: numeric 0-100 — one per metric, summing to 100

        - preview_thresholds[{metric}][{i}][min]: numeric; preview_thresholds[{metric}][{i}][score]:
        integer 1-5

        - preview_min_po_count: integer, min 1


        preview_weights and preview_thresholds may be passed either as bracketed array
        params (shown above) or as a single URL-encoded JSON string — the live-preview
        UI sends them as JSON strings.'
      parameters:
      - name: period_mode
        in: query
        schema:
          type: string
        description: 'Required. Period comparison model: yoy | qoq | mom | custom'
        example: yoy
      - name: brand
        in: path
        schema:
          type: string
        required: true
        description: The brand ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 OK
                  value:
                    data:
                      composite: 4.15
                      band: good
                      is_sufficient: true
                      po_count: 18
                      dimensions:
                      - key: on_time_delivery
                        label: On-Time Delivery
                        raw: 92.3
                        raw_display: 92.3%
                        score: 4
                        weight: 25.0
                      - key: lead_time_reliability
                        label: Lead-Time Reliability
                        raw: 88.0
                        raw_display: 88.0%
                        score: 3
                        weight: 15.0
                      - key: fill_rate
                        label: Fill Rate
                        raw: 98.6
                        raw_display: 98.6%
                        score: 5
                        weight: 15.0
                      - key: defect_rate
                        label: Defect / RTV Rate
                        raw: 1.2
                        raw_display: 1.2%
                        score: 5
                        weight: 15.0
                      - key: cost_competitiveness
                        label: Cost Competitiveness
                        raw: 74.5
                        raw_display: 74.5 / 100
                        score: 3
                        weight: 25.0
                      - key: price_stability
                        label: Price Stability
                        raw: 0.18
                        raw_display: 18% price increases
                        score: 4
                        weight: 5.0
                example-1:
                  summary: 200 OK (Insufficient Data)
                  value:
                    data:
                      composite: 0.0
                      band: not_rated
                      is_sufficient: false
                      po_count: 1
                      dimensions: []
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No query results for model [App\Models\ProductBrand].
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      preview_weights:
                        type: array
                        items:
                          type: string
                      preview:
                        type: array
                        items:
                          type: string
                example:
                  message: The given data was invalid.
                  errors:
                    preview_weights:
                    - Preview scorecard weights must sum to exactly 100 (currently
                      90).
                    preview:
                    - A scorecard preview requires preview_weights, preview_thresholds
                      and preview_min_po_count together.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-reporting-brands-brand-scorecard
  /api/product-data-health/metrics:
    get:
      tags:
      - Reporting
      summary: Get Product Data Health Metrics
      description: 'Aggregated product data-health metrics for the Product Data Health
        dashboard: product-type distribution, active/archived breakdown, unit-cost
        health (>0 / =0 / null), brand and supplier coverage, supplier-price health,
        kit/bundle component gaps, pricing coverage, image health, and sales-channel
        mapping coverage.


        :::info[Required scope: `products:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Image health: `products_with_image` / `products_without_image` reflect image
        presence (a primary or any product image). `products_with_broken_image` counts
        products whose primary image was checked and found unresolvable by the on-demand
        image-health check (see POST /api/product-data-health/check-image-health).
        `image_health_last_checked_at` is the most recent time any product image was
        validated (UTC, ISO-8601), or null if no check has ever run.


        Authentication: Requires Bearer token (scope: products read-write).


        Optional filters (all narrow every metric):

        - archived_status: active | archived — restrict to active or archived products

        - brand_id: integer — restrict to a single brand

        - default_supplier_id: integer — restrict to products whose default supplier
        matches'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  product_counts_by_type:
                    type: object
                    properties:
                      standard:
                        type: integer
                      kit:
                        type: integer
                      bundle:
                        type: integer
                      variation:
                        type: integer
                      variation_child:
                        type: integer
                  total_products:
                    type: integer
                  active_products:
                    type: integer
                  archived_products:
                    type: integer
                  active_products_by_type:
                    type: object
                    properties:
                      standard:
                        type: integer
                      kit:
                        type: integer
                      bundle:
                        type: integer
                      variation:
                        type: integer
                      variation_child:
                        type: integer
                  archived_products_by_type:
                    type: object
                    properties:
                      standard:
                        type: integer
                      kit:
                        type: integer
                      bundle:
                        type: integer
                      variation:
                        type: integer
                      variation_child:
                        type: integer
                  products_with_unit_cost:
                    type: integer
                  products_with_zero_unit_cost:
                    type: integer
                  products_with_null_unit_cost:
                    type: integer
                  products_with_unit_cost_by_type:
                    type: object
                    properties:
                      standard:
                        type: integer
                      kit:
                        type: integer
                      bundle:
                        type: integer
                      variation_child:
                        type: integer
                  products_with_zero_unit_cost_by_type:
                    type: object
                    properties:
                      standard:
                        type: integer
                      kit:
                        type: integer
                      bundle:
                        type: integer
                      variation_child:
                        type: integer
                  products_with_null_unit_cost_by_type:
                    type: object
                    properties:
                      standard:
                        type: integer
                      kit:
                        type: integer
                      bundle:
                        type: integer
                      variation_child:
                        type: integer
                  products_with_brand:
                    type: integer
                  products_without_brand:
                    type: integer
                  brand_distribution:
                    type: array
                    items:
                      type: object
                      properties:
                        name:
                          type: string
                        count:
                          type: integer
                  products_with_supplier:
                    type: integer
                  products_without_supplier:
                    type: integer
                  products_with_supplier_by_type:
                    type: object
                    properties:
                      standard:
                        type: integer
                      variation_child:
                        type: integer
                  products_without_supplier_by_type:
                    type: object
                    properties:
                      standard:
                        type: integer
                      variation_child:
                        type: integer
                  supplier_count_distribution:
                    type: array
                    items:
                      type: object
                      properties:
                        supplier_count:
                          type: integer
                        products:
                          type: integer
                  products_with_zero_supplier_price:
                    type: integer
                  products_with_non_zero_supplier_price:
                    type: integer
                  default_supplier_pricing_tier_name:
                    type: string
                  kits_without_components:
                    type: integer
                  bundles_without_components:
                    type: integer
                  total_kits:
                    type: integer
                  total_bundles:
                    type: integer
                  products_with_pricing:
                    type: integer
                  products_without_pricing:
                    type: integer
                  products_without_pricing_by_type:
                    type: object
                    properties:
                      standard:
                        type: integer
                      kit:
                        type: integer
                      bundle:
                        type: integer
                      variation_child:
                        type: integer
                  default_pricing_tier_name:
                    type: string
                  products_with_image:
                    type: integer
                  products_without_image:
                    type: integer
                  products_without_image_by_type:
                    type: object
                    properties:
                      standard:
                        type: integer
                      kit:
                        type: integer
                      bundle:
                        type: integer
                      variation_child:
                        type: integer
                  products_with_broken_image:
                    type: integer
                  image_health_last_checked_at:
                    type: string
                  mapped_product_listings:
                    type: integer
                  unmapped_sales_channel_products:
                    type: integer
                  sales_channel_mapping_by_channel:
                    type: array
                    items:
                      type: object
                      properties:
                        name:
                          type: string
                        mapped:
                          type: integer
                        unmapped:
                          type: integer
                        integration_instance_id:
                          type: integer
                        channel_type:
                          type: string
                example:
                  product_counts_by_type:
                    standard: 1240
                    kit: 85
                    bundle: 42
                    variation: 30
                    variation_child: 180
                  total_products: 1577
                  active_products: 1402
                  archived_products: 175
                  active_products_by_type:
                    standard: 1100
                    kit: 78
                    bundle: 38
                    variation: 28
                    variation_child: 158
                  archived_products_by_type:
                    standard: 140
                    kit: 7
                    bundle: 4
                    variation: 2
                    variation_child: 22
                  products_with_unit_cost: 1180
                  products_with_zero_unit_cost: 95
                  products_with_null_unit_cost: 302
                  products_with_unit_cost_by_type:
                    standard: 980
                    kit: 60
                    bundle: 30
                    variation_child: 110
                  products_with_zero_unit_cost_by_type:
                    standard: 80
                    kit: 5
                    bundle: 4
                    variation_child: 6
                  products_with_null_unit_cost_by_type:
                    standard: 180
                    kit: 20
                    bundle: 8
                    variation_child: 64
                  products_with_brand: 1320
                  products_without_brand: 257
                  brand_distribution:
                  - name: Acme
                    count: 540
                  - name: Globex
                    count: 320
                  - name: Unbranded
                    count: 257
                  products_with_supplier: 1190
                  products_without_supplier: 387
                  products_with_supplier_by_type:
                    standard: 1000
                    variation_child: 190
                  products_without_supplier_by_type:
                    standard: 240
                    variation_child: 147
                  supplier_count_distribution:
                  - supplier_count: 1
                    products: 900
                  - supplier_count: 2
                    products: 220
                  - supplier_count: 3
                    products: 70
                  products_with_zero_supplier_price: 64
                  products_with_non_zero_supplier_price: 1126
                  default_supplier_pricing_tier_name: Default Cost
                  kits_without_components: 3
                  bundles_without_components: 1
                  total_kits: 85
                  total_bundles: 42
                  products_with_pricing: 1450
                  products_without_pricing: 127
                  products_without_pricing_by_type:
                    standard: 90
                    kit: 12
                    bundle: 5
                    variation_child: 20
                  default_pricing_tier_name: Retail
                  products_with_image: 1390
                  products_without_image: 187
                  products_without_image_by_type:
                    standard: 150
                    kit: 18
                    bundle: 9
                    variation_child: 10
                  products_with_broken_image: 12
                  image_health_last_checked_at: '2026-06-09T14:32:00.000000Z'
                  mapped_product_listings: 2104
                  unmapped_sales_channel_products: 96
                  sales_channel_mapping_by_channel:
                  - name: Amazon US
                    mapped: 980
                    unmapped: 40
                    integration_instance_id: 12
                    channel_type: amazon
                  - name: Shopify Storefront
                    mapped: 1124
                    unmapped: 56
                    integration_instance_id: 7
                    channel_type: shopify
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: products:read
      operationId: get-api-product-data-health-metrics
  /api/product-data-health/check-image-health:
    post:
      tags:
      - Reporting
      summary: Check Image Health
      description: 'Dispatch the on-demand image-health check job. The job re-validates
        every product image — local (disk) images are checked for existence on their
        storage disk, remote (URL) images via an HTTP request — records the result
        on each product image (resolvable + checked-at), and surfaces progress through
        the tracked job log endpoints.


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Returns the tracked job log id so the frontend can follow progress via the
        tracked job log endpoints. There is no request body.


        Authentication: Requires Bearer token (scope: products read-write).'
      requestBody:
        content: {}
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 84213
                  message: Image health check started
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: products:write
      operationId: post-api-product-data-health-check-image-health
  /api/reporting/sales-by-source-type:
    get:
      tags:
      - Reporting
      summary: Sales by Source Type (POS vs Online)
      description: Omnichannel sales segmented by sub-sales-channel source type (in-store
        / Point of Sale vs online vs marketplace). Integration-agnostic — aggregates
        Shopify POS, Square, and any classified source. Returns per-segment order_count,
        units, line revenue, plus point_of_sale_total and online_total. Optional date_from/date_to
        (Y-m-d). Authenticate with a Personal Access Token.
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        source_type:
                          type: string
                        label:
                          type: string
                        order_count:
                          type: integer
                        units:
                          type: integer
                        revenue:
                          type: number
                  point_of_sale_total:
                    type: number
                  online_total:
                    type: integer
                example:
                  data:
                  - source_type: point_of_sale
                    label: Point of Sale
                    order_count: 42
                    units: 118
                    revenue: 3840.5
                  - source_type: online
                    label: Online
                    order_count: 97
                    units: 210
                    revenue: 8120
                  point_of_sale_total: 3840.5
                  online_total: 8120
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-reporting-sales-by-source-type
  /api/reporting/irr/suppliers:
    get:
      tags:
      - Reporting
      summary: List Supplier IRR Ranking
      description: 'Rank every supplier by the pooled internal rate of return on the
        cash deployed with them.


        Each row''s `xirr` is the annualized money-weighted return (0.549 = 54.9%),
        pooled across all the entity''s non-draft purchase orders — deposit and balance
        payments out, then net sales proceeds in as the received units sell through,
        plus remaining stock valued at cost as of today. Also returns the cash multiple
        (`moic`), profit, capital deployed, days deployed, and units sold. Rows are
        ranked by IRR (unsolvable rows sort last with `is_rankable=false`). Amounts
        are in the account''s base currency. Requires a Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      currency_code:
                        type: string
                      last_refreshed_at:
                        type: string
                      eligible_po_count:
                        type: integer
                      covered_po_count:
                        type: integer
                      pending_po_count:
                        type: integer
                      summary:
                        type: object
                        properties:
                          entity_count:
                            type: integer
                          ranked_count:
                            type: integer
                          total_capital_deployed:
                            type: integer
                          total_profit:
                            type: number
                          blended_moic:
                            type: number
                          best:
                            type: object
                            properties:
                              id:
                                type: integer
                              name:
                                type: string
                              sku:
                                type: string
                                nullable: true
                              xirr:
                                type: number
                              period_return:
                                type: number
                              moic:
                                type: number
                              profit:
                                type: integer
                              capital_deployed:
                                type: integer
                              total_cash_in:
                                type: integer
                              npv_at_hurdle:
                                type: number
                              days_capital_deployed:
                                type: integer
                              po_count:
                                type: integer
                              units_bought:
                                type: integer
                              units_sold:
                                type: integer
                              pct_realized:
                                type: number
                              selling_since:
                                type: string
                              is_short_hold:
                                type: boolean
                              is_provisional:
                                type: boolean
                              is_rankable:
                                type: boolean
                          worst:
                            type: object
                            properties:
                              id:
                                type: integer
                              name:
                                type: string
                              sku:
                                type: string
                                nullable: true
                              xirr:
                                type: number
                              period_return:
                                type: number
                              moic:
                                type: number
                              profit:
                                type: number
                              capital_deployed:
                                type: integer
                              total_cash_in:
                                type: number
                              npv_at_hurdle:
                                type: integer
                              days_capital_deployed:
                                type: integer
                              po_count:
                                type: integer
                              units_bought:
                                type: integer
                              units_sold:
                                type: integer
                              pct_realized:
                                type: number
                              selling_since:
                                type: string
                              is_short_hold:
                                type: boolean
                              is_provisional:
                                type: boolean
                              is_rankable:
                                type: boolean
                      rows:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            sku:
                              type: string
                              nullable: true
                            xirr:
                              type: number
                            period_return:
                              type: number
                            moic:
                              type: number
                            profit:
                              type: integer
                            capital_deployed:
                              type: integer
                            total_cash_in:
                              type: integer
                            npv_at_hurdle:
                              type: number
                            days_capital_deployed:
                              type: integer
                            po_count:
                              type: integer
                            units_bought:
                              type: integer
                            units_sold:
                              type: integer
                            pct_realized:
                              type: number
                            selling_since:
                              type: string
                            is_short_hold:
                              type: boolean
                            is_provisional:
                              type: boolean
                            is_rankable:
                              type: boolean
                example:
                  data:
                    currency_code: USD
                    last_refreshed_at: '2026-07-18T04:30:11+00:00'
                    eligible_po_count: 47
                    covered_po_count: 47
                    pending_po_count: 0
                    summary:
                      entity_count: 3
                      ranked_count: 3
                      total_capital_deployed: 26750
                      total_profit: 8125.8
                      blended_moic: 1.3038
                      best:
                        id: 12
                        name: Rainier Roasters
                        sku: null
                        xirr: 5.4903
                        period_return: 0.05
                        moic: 1.52
                        profit: 4653
                        capital_deployed: 9000
                        total_cash_in: 13653
                        npv_at_hurdle: 4091.55
                        days_capital_deployed: 150
                        po_count: 1
                        units_bought: 1000
                        units_sold: 188
                        pct_realized: 0.94
                        selling_since: '2025-02-14'
                        is_short_hold: false
                        is_provisional: false
                        is_rankable: true
                      worst:
                        id: 21
                        name: Umbrella Goods
                        sku: null
                        xirr: -0.0312
                        period_return: 0.05
                        moic: 0.98
                        profit: -197.6
                        capital_deployed: 9750
                        total_cash_in: 9552.4
                        npv_at_hurdle: -410
                        days_capital_deployed: 280
                        po_count: 1
                        units_bought: 1000
                        units_sold: 38
                        pct_realized: 0.25
                        selling_since: '2025-02-14'
                        is_short_hold: false
                        is_provisional: false
                        is_rankable: true
                    rows:
                    - id: 12
                      name: Rainier Roasters
                      sku: null
                      xirr: 5.4903
                      period_return: 0.05
                      moic: 1.52
                      profit: 4653
                      capital_deployed: 9000
                      total_cash_in: 13653
                      npv_at_hurdle: 4091.55
                      days_capital_deployed: 150
                      po_count: 1
                      units_bought: 1000
                      units_sold: 188
                      pct_realized: 0.94
                      selling_since: '2025-02-14'
                      is_short_hold: false
                      is_provisional: false
                      is_rankable: true
                    - id: 7
                      name: Acme Supplies
                      sku: null
                      xirr: 1.6112
                      period_return: 0.05
                      moic: 1.46
                      profit: 3670.4
                      capital_deployed: 8000
                      total_cash_in: 11670.4
                      npv_at_hurdle: 3120.1
                      days_capital_deployed: 240
                      po_count: 1
                      units_bought: 1000
                      units_sold: 74
                      pct_realized: 0.74
                      selling_since: '2025-02-14'
                      is_short_hold: false
                      is_provisional: false
                      is_rankable: true
                    - id: 21
                      name: Umbrella Goods
                      sku: null
                      xirr: -0.0312
                      period_return: 0.05
                      moic: 0.98
                      profit: -197.6
                      capital_deployed: 9750
                      total_cash_in: 9552.4
                      npv_at_hurdle: -410
                      days_capital_deployed: 280
                      po_count: 1
                      units_bought: 1000
                      units_sold: 38
                      pct_realized: 0.25
                      selling_since: '2025-02-14'
                      is_short_hold: false
                      is_provisional: false
                      is_rankable: true
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-reporting-irr-suppliers
  /api/reporting/irr/products:
    get:
      tags:
      - Reporting
      summary: List Product IRR Ranking
      description: 'Rank every product by the internal rate of return on its purchasing
        cash flows (each order''s flows prorated to the product by its cost share
        of the order).


        Each row''s `xirr` is the annualized money-weighted return (0.549 = 54.9%),
        pooled across all the entity''s non-draft purchase orders — deposit and balance
        payments out, then net sales proceeds in as the received units sell through,
        plus remaining stock valued at cost as of today. Also returns the cash multiple
        (`moic`), profit, capital deployed, days deployed, and units sold. Rows are
        ranked by IRR (unsolvable rows sort last with `is_rankable=false`). Amounts
        are in the account''s base currency. Requires a Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      currency_code:
                        type: string
                      last_refreshed_at:
                        type: string
                      eligible_po_count:
                        type: integer
                      covered_po_count:
                        type: integer
                      pending_po_count:
                        type: integer
                      summary:
                        type: object
                        properties:
                          entity_count:
                            type: integer
                          ranked_count:
                            type: integer
                          total_capital_deployed:
                            type: integer
                          total_profit:
                            type: integer
                          blended_moic:
                            type: number
                          best:
                            type: object
                            properties:
                              id:
                                type: integer
                              name:
                                type: string
                              sku:
                                type: string
                              xirr:
                                type: number
                              period_return:
                                type: number
                              moic:
                                type: number
                              profit:
                                type: integer
                              capital_deployed:
                                type: integer
                              total_cash_in:
                                type: integer
                              npv_at_hurdle:
                                type: number
                              days_capital_deployed:
                                type: integer
                              po_count:
                                type: integer
                              units_bought:
                                type: integer
                              units_sold:
                                type: integer
                              pct_realized:
                                type: number
                              selling_since:
                                type: string
                              is_short_hold:
                                type: boolean
                              is_provisional:
                                type: boolean
                              is_rankable:
                                type: boolean
                          worst:
                            type: object
                            properties:
                              id:
                                type: integer
                              name:
                                type: string
                              sku:
                                type: string
                              xirr:
                                type: number
                              period_return:
                                type: number
                              moic:
                                type: number
                              profit:
                                type: integer
                              capital_deployed:
                                type: integer
                              total_cash_in:
                                type: integer
                              npv_at_hurdle:
                                type: number
                              days_capital_deployed:
                                type: integer
                              po_count:
                                type: integer
                              units_bought:
                                type: integer
                              units_sold:
                                type: integer
                              pct_realized:
                                type: integer
                              selling_since:
                                type: string
                              is_short_hold:
                                type: boolean
                              is_provisional:
                                type: boolean
                              is_rankable:
                                type: boolean
                      rows:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            sku:
                              type: string
                            xirr:
                              type: number
                            period_return:
                              type: number
                            moic:
                              type: number
                            profit:
                              type: integer
                            capital_deployed:
                              type: integer
                            total_cash_in:
                              type: integer
                            npv_at_hurdle:
                              type: number
                            days_capital_deployed:
                              type: integer
                            po_count:
                              type: integer
                            units_bought:
                              type: integer
                            units_sold:
                              type: integer
                            pct_realized:
                              type: number
                            selling_since:
                              type: string
                            is_short_hold:
                              type: boolean
                            is_provisional:
                              type: boolean
                            is_rankable:
                              type: boolean
                example:
                  data:
                    currency_code: USD
                    last_refreshed_at: '2026-07-18T04:30:11+00:00'
                    eligible_po_count: 47
                    covered_po_count: 47
                    pending_po_count: 0
                    summary:
                      entity_count: 2
                      ranked_count: 2
                      total_capital_deployed: 16200
                      total_profit: 8109
                      blended_moic: 1.5006
                      best:
                        id: 31
                        name: Cold Brew Concentrate 32oz
                        sku: CB-32
                        xirr: 5.4903
                        period_return: 0.05
                        moic: 1.52
                        profit: 4653
                        capital_deployed: 9000
                        total_cash_in: 13653
                        npv_at_hurdle: 4091.55
                        days_capital_deployed: 150
                        po_count: 1
                        units_bought: 1000
                        units_sold: 188
                        pct_realized: 0.94
                        selling_since: '2025-02-14'
                        is_short_hold: false
                        is_provisional: false
                        is_rankable: true
                      worst:
                        id: 44
                        name: Gooseneck Kettle 1.2L
                        sku: KET-GN-12
                        xirr: 1.5701
                        period_return: 0.05
                        moic: 1.48
                        profit: 3456
                        capital_deployed: 7200
                        total_cash_in: 10656
                        npv_at_hurdle: 2980.2
                        days_capital_deployed: 320
                        po_count: 1
                        units_bought: 1000
                        units_sold: 90
                        pct_realized: 1
                        selling_since: '2025-02-14'
                        is_short_hold: false
                        is_provisional: false
                        is_rankable: true
                    rows:
                    - id: 31
                      name: Cold Brew Concentrate 32oz
                      sku: CB-32
                      xirr: 5.4903
                      period_return: 0.05
                      moic: 1.52
                      profit: 4653
                      capital_deployed: 9000
                      total_cash_in: 13653
                      npv_at_hurdle: 4091.55
                      days_capital_deployed: 150
                      po_count: 1
                      units_bought: 1000
                      units_sold: 188
                      pct_realized: 0.94
                      selling_since: '2025-02-14'
                      is_short_hold: false
                      is_provisional: false
                      is_rankable: true
                    - id: 44
                      name: Gooseneck Kettle 1.2L
                      sku: KET-GN-12
                      xirr: 1.5701
                      period_return: 0.05
                      moic: 1.48
                      profit: 3456
                      capital_deployed: 7200
                      total_cash_in: 10656
                      npv_at_hurdle: 2980.2
                      days_capital_deployed: 320
                      po_count: 1
                      units_bought: 1000
                      units_sold: 90
                      pct_realized: 1
                      selling_since: '2025-02-14'
                      is_short_hold: false
                      is_provisional: false
                      is_rankable: true
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-reporting-irr-products
  /api/reporting/irr/suppliers/{supplier}/products:
    get:
      tags:
      - Reporting
      summary: List Supplier Product IRR Breakdown
      description: 'For one supplier, return its own pooled IRR (in `supplier`) plus
        every product purchased from it, ranked by IRR.


        Each row''s `xirr` is the annualized money-weighted return (0.549 = 54.9%),
        pooled across all the entity''s non-draft purchase orders — deposit and balance
        payments out, then net sales proceeds in as the received units sell through,
        plus remaining stock valued at cost as of today. Also returns the cash multiple
        (`moic`), profit, capital deployed, days deployed, and units sold. Rows are
        ranked by IRR (unsolvable rows sort last with `is_rankable=false`). Amounts
        are in the account''s base currency. Requires a Bearer token.'
      parameters:
      - name: supplier
        in: path
        schema:
          type: integer
        required: true
        description: Supplier ID
        example: '12'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      currency_code:
                        type: string
                      last_refreshed_at:
                        type: string
                      eligible_po_count:
                        type: integer
                      covered_po_count:
                        type: integer
                      pending_po_count:
                        type: integer
                      summary:
                        type: object
                        properties:
                          entity_count:
                            type: integer
                          ranked_count:
                            type: integer
                          total_capital_deployed:
                            type: integer
                          total_profit:
                            type: integer
                          blended_moic:
                            type: number
                          best:
                            type: object
                            properties:
                              id:
                                type: integer
                              name:
                                type: string
                              sku:
                                type: string
                              xirr:
                                type: number
                              period_return:
                                type: number
                              moic:
                                type: number
                              profit:
                                type: integer
                              capital_deployed:
                                type: integer
                              total_cash_in:
                                type: integer
                              npv_at_hurdle:
                                type: number
                              days_capital_deployed:
                                type: integer
                              po_count:
                                type: integer
                              units_bought:
                                type: integer
                              units_sold:
                                type: integer
                              pct_realized:
                                type: number
                              selling_since:
                                type: string
                              is_short_hold:
                                type: boolean
                              is_provisional:
                                type: boolean
                              is_rankable:
                                type: boolean
                          worst:
                            type: object
                            properties:
                              id:
                                type: integer
                              name:
                                type: string
                              sku:
                                type: string
                              xirr:
                                type: number
                              period_return:
                                type: number
                              moic:
                                type: number
                              profit:
                                type: integer
                              capital_deployed:
                                type: integer
                              total_cash_in:
                                type: integer
                              npv_at_hurdle:
                                type: number
                              days_capital_deployed:
                                type: integer
                              po_count:
                                type: integer
                              units_bought:
                                type: integer
                              units_sold:
                                type: integer
                              pct_realized:
                                type: number
                              selling_since:
                                type: string
                              is_short_hold:
                                type: boolean
                              is_provisional:
                                type: boolean
                              is_rankable:
                                type: boolean
                      supplier:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          sku:
                            type: string
                            nullable: true
                          xirr:
                            type: number
                          period_return:
                            type: number
                          moic:
                            type: number
                          profit:
                            type: integer
                          capital_deployed:
                            type: integer
                          total_cash_in:
                            type: integer
                          npv_at_hurdle:
                            type: number
                          days_capital_deployed:
                            type: integer
                          po_count:
                            type: integer
                          units_bought:
                            type: integer
                          units_sold:
                            type: integer
                          pct_realized:
                            type: number
                          selling_since:
                            type: string
                          is_short_hold:
                            type: boolean
                          is_provisional:
                            type: boolean
                          is_rankable:
                            type: boolean
                      rows:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            sku:
                              type: string
                            xirr:
                              type: number
                            period_return:
                              type: number
                            moic:
                              type: number
                            profit:
                              type: integer
                            capital_deployed:
                              type: integer
                            total_cash_in:
                              type: integer
                            npv_at_hurdle:
                              type: number
                            days_capital_deployed:
                              type: integer
                            po_count:
                              type: integer
                            units_bought:
                              type: integer
                            units_sold:
                              type: integer
                            pct_realized:
                              type: number
                            selling_since:
                              type: string
                            is_short_hold:
                              type: boolean
                            is_provisional:
                              type: boolean
                            is_rankable:
                              type: boolean
                example:
                  data:
                    currency_code: USD
                    last_refreshed_at: '2026-07-18T04:30:11+00:00'
                    eligible_po_count: 47
                    covered_po_count: 47
                    pending_po_count: 0
                    summary:
                      entity_count: 1
                      ranked_count: 1
                      total_capital_deployed: 9000
                      total_profit: 4653
                      blended_moic: 1.517
                      best:
                        id: 31
                        name: Cold Brew Concentrate 32oz
                        sku: CB-32
                        xirr: 5.4903
                        period_return: 0.05
                        moic: 1.52
                        profit: 4653
                        capital_deployed: 9000
                        total_cash_in: 13653
                        npv_at_hurdle: 4091.55
                        days_capital_deployed: 150
                        po_count: 1
                        units_bought: 1000
                        units_sold: 188
                        pct_realized: 0.94
                        selling_since: '2025-02-14'
                        is_short_hold: false
                        is_provisional: false
                        is_rankable: true
                      worst:
                        id: 31
                        name: Cold Brew Concentrate 32oz
                        sku: CB-32
                        xirr: 5.4903
                        period_return: 0.05
                        moic: 1.52
                        profit: 4653
                        capital_deployed: 9000
                        total_cash_in: 13653
                        npv_at_hurdle: 4091.55
                        days_capital_deployed: 150
                        po_count: 1
                        units_bought: 1000
                        units_sold: 188
                        pct_realized: 0.94
                        selling_since: '2025-02-14'
                        is_short_hold: false
                        is_provisional: false
                        is_rankable: true
                    supplier:
                      id: 12
                      name: Rainier Roasters
                      sku: null
                      xirr: 5.4903
                      period_return: 0.05
                      moic: 1.52
                      profit: 4653
                      capital_deployed: 9000
                      total_cash_in: 13653
                      npv_at_hurdle: 4091.55
                      days_capital_deployed: 150
                      po_count: 1
                      units_bought: 1000
                      units_sold: 188
                      pct_realized: 0.94
                      selling_since: '2025-02-14'
                      is_short_hold: false
                      is_provisional: false
                      is_rankable: true
                    rows:
                    - id: 31
                      name: Cold Brew Concentrate 32oz
                      sku: CB-32
                      xirr: 5.4903
                      period_return: 0.05
                      moic: 1.52
                      profit: 4653
                      capital_deployed: 9000
                      total_cash_in: 13653
                      npv_at_hurdle: 4091.55
                      days_capital_deployed: 150
                      po_count: 1
                      units_bought: 1000
                      units_sold: 188
                      pct_realized: 0.94
                      selling_since: '2025-02-14'
                      is_short_hold: false
                      is_provisional: false
                      is_rankable: true
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-reporting-irr-suppliers-supplier-products
  /api/reporting/irr/suppliers/{supplier}/reconciliation-events:
    get:
      tags:
      - Reporting
      summary: List Supplier Reconciliation Events
      description: 'The bulk stock-take write-off events behind a supplier''s reconciliation
        figure, grouped by stock-take (largest first) with per-product lines. Each
        event carries the stock-take date, warehouse, status, mode (full_count or
        adjustment), variance direction, units, and cost value, plus a link to the
        stock-take record. Use to see exactly which physical counts wrote off inventory.


        Authentication: requires a Bearer token.


        Query params: `since` (optional) restricts to purchase orders placed on/after
        the date.'
      parameters:
      - name: supplier
        in: path
        schema:
          type: integer
        required: true
        description: Supplier ID
        example: '12'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      entity:
                        type: object
                        properties:
                          type:
                            type: string
                          id:
                            type: integer
                          name:
                            type: string
                          sku:
                            type: string
                            nullable: true
                      currency_code:
                        type: string
                      total_value:
                        type: number
                      total_units:
                        type: integer
                      event_count:
                        type: integer
                      events:
                        type: array
                        items:
                          type: object
                          properties:
                            stock_take_id:
                              type: integer
                            reference:
                              type: string
                            link_route:
                              type: string
                            date:
                              type: string
                            warehouse:
                              type: string
                            status:
                              type: string
                            mode:
                              type: string
                            variance_direction:
                              type: string
                            notes:
                              type: string
                            value_change:
                              type: number
                            units:
                              type: integer
                            value:
                              type: number
                            lines:
                              type: array
                              items:
                                type: object
                                properties:
                                  product_id:
                                    type: integer
                                  product_name:
                                    type: string
                                  sku:
                                    type: string
                                  product_route:
                                    type: string
                                  units:
                                    type: integer
                                  value:
                                    type: number
                                  unit_cost:
                                    type: number
                                  variance_reason:
                                    type: string
                                  variance_reason_label:
                                    type: string
                                  counted_before:
                                    type: integer
                                  counted_after:
                                    type: integer
                                  purchase_orders:
                                    type: array
                                    items:
                                      type: object
                                      properties:
                                        id:
                                          type: integer
                                        number:
                                          type: string
                                        route:
                                          type: string
                example:
                  data:
                    entity:
                      type: supplier
                      id: 17
                      name: Example Supplier
                      sku: null
                    currency_code: USD
                    total_value: 28416.43
                    total_units: 234
                    event_count: 2
                    events:
                    - stock_take_id: 147
                      reference: 'Stock Take #147'
                      link_route: /inventory/stock-takes/147?tab=movements
                      date: '2026-06-11'
                      warehouse: Main Warehouse
                      status: closed
                      mode: full_count
                      variance_direction: mixed
                      notes: Stock take created from inventory discrepancies found
                        during the fulfillment-provider sync.
                      value_change: -45028.88
                      units: 233
                      value: 28305.58
                      lines:
                      - product_id: 517
                        product_name: Diagnostic Scanner Pro
                        sku: SCAN-PRO
                        product_route: /products/517
                        units: 28
                        value: 7154.7
                        unit_cost: 255.53
                        variance_reason: damage
                        variance_reason_label: Damage
                        counted_before: 75
                        counted_after: 47
                        purchase_orders:
                        - id: 373
                          number: PO-0318
                          route: /orders/purchase-orders/373
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-reporting-irr-suppliers-supplier-reconciliation-events
  /api/reporting/irr/products/{product}/reconciliation-events:
    get:
      tags:
      - Reporting
      summary: List Product Reconciliation Events
      description: 'The bulk stock-take write-off events behind a product''s reconciliation
        figure, grouped by stock-take (largest first). Each event carries the stock-take
        date, warehouse, status, mode, variance direction, units, and cost value,
        plus a link to the stock-take record.


        Authentication: requires a Bearer token.


        Query params: `since` (optional) restricts to purchase orders placed on/after
        the date.'
      parameters:
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: Product ID
        example: '34'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      entity:
                        type: object
                        properties:
                          type:
                            type: string
                          id:
                            type: integer
                          name:
                            type: string
                          sku:
                            type: string
                            nullable: true
                      currency_code:
                        type: string
                      total_value:
                        type: number
                      total_units:
                        type: integer
                      event_count:
                        type: integer
                      events:
                        type: array
                        items:
                          type: object
                          properties:
                            stock_take_id:
                              type: integer
                            reference:
                              type: string
                            link_route:
                              type: string
                            date:
                              type: string
                            warehouse:
                              type: string
                            status:
                              type: string
                            mode:
                              type: string
                            variance_direction:
                              type: string
                            notes:
                              type: string
                            value_change:
                              type: number
                            units:
                              type: integer
                            value:
                              type: number
                            lines:
                              type: array
                              items:
                                type: object
                                properties:
                                  product_id:
                                    type: integer
                                  product_name:
                                    type: string
                                  sku:
                                    type: string
                                  product_route:
                                    type: string
                                  units:
                                    type: integer
                                  value:
                                    type: number
                                  unit_cost:
                                    type: number
                                  variance_reason:
                                    type: string
                                  variance_reason_label:
                                    type: string
                                  counted_before:
                                    type: integer
                                  counted_after:
                                    type: integer
                                  purchase_orders:
                                    type: array
                                    items:
                                      type: object
                                      properties:
                                        id:
                                          type: integer
                                        number:
                                          type: string
                                        route:
                                          type: string
                example:
                  data:
                    entity:
                      type: supplier
                      id: 17
                      name: Example Supplier
                      sku: null
                    currency_code: USD
                    total_value: 28416.43
                    total_units: 234
                    event_count: 2
                    events:
                    - stock_take_id: 147
                      reference: 'Stock Take #147'
                      link_route: /inventory/stock-takes/147?tab=movements
                      date: '2026-06-11'
                      warehouse: Main Warehouse
                      status: closed
                      mode: full_count
                      variance_direction: mixed
                      notes: Stock take created from inventory discrepancies found
                        during the fulfillment-provider sync.
                      value_change: -45028.88
                      units: 233
                      value: 28305.58
                      lines:
                      - product_id: 517
                        product_name: Diagnostic Scanner Pro
                        sku: SCAN-PRO
                        product_route: /products/517
                        units: 28
                        value: 7154.7
                        unit_cost: 255.53
                        variance_reason: damage
                        variance_reason_label: Damage
                        counted_before: 75
                        counted_after: 47
                        purchase_orders:
                        - id: 373
                          number: PO-0318
                          route: /orders/purchase-orders/373
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-reporting-irr-products-product-reconciliation-events
  /api/reporting/irr/suppliers/{supplier}/cash-flows:
    get:
      tags:
      - Reporting
      summary: Get Supplier Cash-Flow Proof
      description: 'The full proof behind a supplier''s pooled return: the pooled
        metrics, a monthly cash-flow shape (money-in/out + running cumulative for
        charts), the dated cash-flow ledger (every flow the MIRR is solved on, each
        linked to its source document), and a per-purchase-order contribution breakdown.


        Authentication: requires a Bearer token.'
      parameters:
      - name: supplier
        in: path
        schema:
          type: integer
        required: true
        description: Supplier ID
        example: '12'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      entity:
                        type: object
                        properties:
                          type:
                            type: string
                          id:
                            type: integer
                          name:
                            type: string
                          sku:
                            type: string
                            nullable: true
                      currency_code:
                        type: string
                      metrics:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          xirr:
                            type: number
                          xirr_exact:
                            type: string
                            nullable: true
                          moic:
                            type: number
                          profit:
                            type: integer
                          capital_deployed:
                            type: integer
                          total_cash_in:
                            type: integer
                          days_capital_deployed:
                            type: integer
                          po_count:
                            type: integer
                          units_sold:
                            type: integer
                          pct_realized:
                            type: number
                          is_rankable:
                            type: boolean
                      monthly:
                        type: array
                        items:
                          type: object
                          properties:
                            month:
                              type: string
                            inflow:
                              type: number
                            outflow:
                              type: integer
                            net:
                              type: number
                            cumulative:
                              type: number
                      flows:
                        type: array
                        items:
                          type: object
                          properties:
                            date:
                              type: string
                            amount:
                              type: integer
                            type:
                              type: string
                            label:
                              type: string
                            source_type:
                              type: string
                            source_type_label:
                              type: string
                            source_id:
                              type: integer
                            source_route:
                              type: string
                              nullable: true
                      flows_total:
                        type: integer
                      purchase_orders:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            number:
                              type: string
                            route:
                              type: string
                            date:
                              type: string
                            capital:
                              type: integer
                            cash_in:
                              type: number
                            profit:
                              type: number
                            moic:
                              type: number
                            xirr:
                              type: number
                            days_held:
                              type: integer
                            pct_realized:
                              type: number
                example:
                  data:
                    entity:
                      type: supplier
                      id: 4
                      name: Example Supplier
                      sku: null
                    currency_code: USD
                    metrics:
                      id: 4
                      name: Example Supplier
                      xirr: 0.93
                      xirr_exact: null
                      moic: 1.89
                      profit: 67425
                      capital_deployed: 75480
                      total_cash_in: 142905
                      days_capital_deployed: 472
                      po_count: 2
                      units_sold: 1641
                      pct_realized: 0.66
                      is_rankable: true
                    monthly:
                    - month: 2025-01
                      inflow: 212.5
                      outflow: 0
                      net: 212.5
                      cumulative: 212.5
                    - month: 2025-02
                      inflow: 1078.31
                      outflow: -65480
                      net: -64401.69
                      cumulative: -64189.19
                    flows:
                    - date: '2025-02-19'
                      amount: -65480
                      type: deposit
                      label: Vendor deposit
                      source_type: App\Models\VendorDeposit
                      source_type_label: Vendor Deposit
                      source_id: 812
                      source_route: null
                    - date: '2025-04-18'
                      amount: 9180
                      type: sale
                      label: Sale of 42 unit(s)
                      source_type: App\Models\SalesOrderLine
                      source_type_label: Sales Order Line
                      source_id: 10233
                      source_route: null
                    flows_total: 510
                    purchase_orders:
                    - id: 312
                      number: PO-0269
                      route: /orders/purchase-orders/312
                      date: '2025-02-19'
                      capital: 65480
                      cash_in: 142904.65
                      profit: 77424.65
                      moic: 2.1824
                      xirr: 1.12
                      days_held: 544
                      pct_realized: 0.66
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-reporting-irr-suppliers-supplier-cash-flows
  /api/reporting/irr/products/{product}/cash-flows:
    get:
      tags:
      - Reporting
      summary: Get Product Cash-Flow Proof
      description: 'The full proof behind a product''s pooled return (cash flows prorated
        to the product''s cost share of each order): pooled metrics, monthly cash-flow
        shape, the dated ledger, and per-purchase-order breakdown.


        Authentication: requires a Bearer token.'
      parameters:
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: Product ID
        example: '34'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      entity:
                        type: object
                        properties:
                          type:
                            type: string
                          id:
                            type: integer
                          name:
                            type: string
                          sku:
                            type: string
                            nullable: true
                      currency_code:
                        type: string
                      metrics:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          xirr:
                            type: number
                          xirr_exact:
                            type: string
                            nullable: true
                          moic:
                            type: number
                          profit:
                            type: integer
                          capital_deployed:
                            type: integer
                          total_cash_in:
                            type: integer
                          days_capital_deployed:
                            type: integer
                          po_count:
                            type: integer
                          units_sold:
                            type: integer
                          pct_realized:
                            type: number
                          is_rankable:
                            type: boolean
                      monthly:
                        type: array
                        items:
                          type: object
                          properties:
                            month:
                              type: string
                            inflow:
                              type: number
                            outflow:
                              type: integer
                            net:
                              type: number
                            cumulative:
                              type: number
                      flows:
                        type: array
                        items:
                          type: object
                          properties:
                            date:
                              type: string
                            amount:
                              type: integer
                            type:
                              type: string
                            label:
                              type: string
                            source_type:
                              type: string
                            source_type_label:
                              type: string
                            source_id:
                              type: integer
                            source_route:
                              type: string
                              nullable: true
                      flows_total:
                        type: integer
                      purchase_orders:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            number:
                              type: string
                            route:
                              type: string
                            date:
                              type: string
                            capital:
                              type: integer
                            cash_in:
                              type: number
                            profit:
                              type: number
                            moic:
                              type: number
                            xirr:
                              type: number
                            days_held:
                              type: integer
                            pct_realized:
                              type: number
                example:
                  data:
                    entity:
                      type: product
                      id: 4
                      name: Example Product
                      sku: null
                    currency_code: USD
                    metrics:
                      id: 4
                      name: Example Supplier
                      xirr: 0.93
                      xirr_exact: null
                      moic: 1.89
                      profit: 67425
                      capital_deployed: 75480
                      total_cash_in: 142905
                      days_capital_deployed: 472
                      po_count: 2
                      units_sold: 1641
                      pct_realized: 0.66
                      is_rankable: true
                    monthly:
                    - month: 2025-01
                      inflow: 212.5
                      outflow: 0
                      net: 212.5
                      cumulative: 212.5
                    - month: 2025-02
                      inflow: 1078.31
                      outflow: -65480
                      net: -64401.69
                      cumulative: -64189.19
                    flows:
                    - date: '2025-02-19'
                      amount: -65480
                      type: deposit
                      label: Vendor deposit
                      source_type: App\Models\VendorDeposit
                      source_type_label: Vendor Deposit
                      source_id: 812
                      source_route: null
                    - date: '2025-04-18'
                      amount: 9180
                      type: sale
                      label: Sale of 42 unit(s)
                      source_type: App\Models\SalesOrderLine
                      source_type_label: Sales Order Line
                      source_id: 10233
                      source_route: null
                    flows_total: 510
                    purchase_orders:
                    - id: 312
                      number: PO-0269
                      route: /orders/purchase-orders/312
                      date: '2025-02-19'
                      capital: 65480
                      cash_in: 142904.65
                      profit: 77424.65
                      moic: 2.1824
                      xirr: 1.12
                      days_held: 544
                      pct_realized: 0.66
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-reporting-irr-products-product-cash-flows
  /api/reporting/irr/refresh:
    post:
      tags:
      - Reporting
      summary: Refresh IRR Metrics
      description: 'Recompute every eligible purchase order''s return metric in the
        background so the supplier and product IRR leaderboards reflect fresh figures.
        The leaderboards read these persisted metrics, so a refresh is what updates
        `last_refreshed_at` and clears any pending (not-yet-computed) purchase orders.


        Runs as a background job and returns immediately. Idempotent: if a refresh
        is already running, `started` is `false` and no second run is queued. Requires
        a Bearer token with reports write access.'
      requestBody:
        content: {}
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      started:
                        type: boolean
                      tracked_job_log_id:
                        type: integer
                example:
                  data:
                    started: true
                    tracked_job_log_id: 4821
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-reporting-irr-refresh
  /api/reports/supplier-pickup-orders:
    get:
      tags:
      - Reporting
      summary: List Supplier Pickup Orders
      description: 'Paginated Supplier Pickup Orders report — one row per drop-ship
        purchase-order line whose requested shipping method is a supplier pickup (vendor
        will-call), so a customer collects the goods directly from the merchant''s
        supplier. Each row carries COGS (from the purchase-order line), revenue (from
        the matching sales-order line), margin, the customer, the supplier, the pickup
        location, and the derived pickup status.


        Filters (Spatie `filter[...]`): search (SKU, product name, PO number, SO number,
        customer name, supplier name, or row id), status (picked_up | awaiting_pickup
        | all), customer_id (comma-separated customer ids), supplier_id (comma-separated),
        warehouse_id (comma-separated pickup-location / supplier-warehouse ids), customer_tag
        (comma-separated tag names on the customer).


        Advanced grouped filters are also accepted via a `filter_groups` tree over
        the columns expected_pickup_at, order_date, quantity, customer, supplier,
        product, sku.


        Sorting (`sort`, prefix `-` for descending): id, order_date, expected_pickup_at,
        days_open, customer, supplier. Default order is newest order date first.


        Pagination: page, per_page (default 10).


        Authentication: Requires Bearer token'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        sales_order:
                          type: object
                          properties:
                            id:
                              type: integer
                            number:
                              type: string
                            route:
                              type: string
                        purchase_order:
                          type: object
                          properties:
                            id:
                              type: integer
                            number:
                              type: string
                            route:
                              type: string
                        customer:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            route:
                              type: string
                        supplier:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            route:
                              type: string
                        pickup_location:
                          type: string
                        product:
                          type: object
                          properties:
                            id:
                              type: integer
                            sku:
                              type: string
                            name:
                              type: string
                            route:
                              type: string
                        quantity:
                          type: integer
                        order_date:
                          type: string
                        expected_pickup_at:
                          type: string
                        days_open:
                          type: integer
                        status:
                          type: string
                        unit_cost:
                          type: integer
                        cogs:
                          type: integer
                        revenue:
                          type: integer
                        margin:
                          type: integer
                        margin_pct:
                          type: number
                        currency:
                          type: string
                  current_page:
                    type: integer
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 98
                    sales_order:
                      id: 512
                      number: SO-9236
                      route: /orders/sales-orders/512
                    purchase_order:
                      id: 28
                      number: PO-0028
                      route: /orders/purchase-orders/28
                    customer:
                      id: 44
                      name: Harbor Freight Traders
                      route: /crm/customers/44
                    supplier:
                      id: 7
                      name: Shenzhen Helmet Co.
                      route: /crm/suppliers/7
                    pickup_location: Shenzhen Supplier DC
                    product:
                      id: 61
                      sku: '5884265723882'
                      name: Carbon Track Helmet
                      route: /products/61/overview
                    quantity: 180
                    order_date: '2026-06-27T00:00:00+00:00'
                    expected_pickup_at: '2026-09-07T00:00:00+00:00'
                    days_open: 27
                    status: awaiting_pickup
                    unit_cost: 14
                    cogs: 2520
                    revenue: 5670
                    margin: 3150
                    margin_pct: 0.5556
                    currency: USD
                  current_page: 1
                  first_page_url: '{{protocol}}{{domain}}/api/reports/supplier-pickup-orders?page=1'
                  from: 1
                  last_page: 1
                  last_page_url: '{{protocol}}{{domain}}/api/reports/supplier-pickup-orders?page=1'
                  next_page_url: null
                  path: '{{protocol}}{{domain}}/api/reports/supplier-pickup-orders'
                  per_page: 10
                  prev_page_url: null
                  to: 3
                  total: 3
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-reports-supplier-pickup-orders
  /api/reports/supplier-pickup-orders/summary:
    get:
      tags:
      - Reporting
      summary: Get Supplier Pickup Summary
      description: 'KPI summary totals for the Supplier Pickup Orders report header
        cards. Honours the same filters as the list endpoint (search, customer_id,
        supplier_id, warehouse_id, customer_tag, and the advanced filter_groups) EXCEPT
        status, which is ignored so both the awaiting and picked-up buckets are always
        represented.


        Returns: open_count (distinct orders awaiting pickup), units_awaiting, value_awaiting
        (COGS of awaiting lines), picked_up_count (distinct picked-up orders), revenue_period
        and margin_period (revenue / margin of picked-up lines).


        Authentication: Requires Bearer token'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      open_count:
                        type: integer
                      units_awaiting:
                        type: integer
                      value_awaiting:
                        type: integer
                      picked_up_count:
                        type: integer
                      revenue_period:
                        type: integer
                      margin_period:
                        type: integer
                example:
                  data:
                    open_count: 1
                    units_awaiting: 180
                    value_awaiting: 2520
                    picked_up_count: 2
                    revenue_period: 13230
                    margin_period: 7350
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-reports-supplier-pickup-orders-summary
  /api/export/download:
    get:
      tags:
      - Export
      summary: Download Export File
      description: 'Downloads a completed export file from the model-exports disk
        by filename (the `file` returned from create-download-file). Streams the file
        as a CSV download (Content-Type: text/csv).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token


        Query parameters:

        - file (required): Filename of the completed export. Returns 404 if omitted.


        Responses:

        - 200: File download (text/csv).

        - 404: The `file` param is missing, or the export file no longer exists /
        has expired / its metadata can''t be read. Regenerate the export.


        Note: Response is a file download, not JSON.'
      parameters:
      - name: file
        in: query
        schema:
          type: string
        description: Filename of the completed export (from create-download-file).
          Required.
        example: export-file.csv
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: text/csv
            Content-Disposition:
              schema:
                type: string
                example: attachment; filename="export-file.csv"
          content:
            text/plain:
              schema:
                type: string
                example: 'id,name

                  1,Widget

                  2,Gadget'
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 404 File Missing Or Expired
                  value:
                    message: Export file is no longer available. Please regenerate
                      the export.
                example-1:
                  summary: 404 Missing File Parameter
                  value:
                    message: Export file not found.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-export-download
  /api/export/initial-inventory/{warehouse}/export:
    get:
      tags:
      - Export
      summary: Export Initial Inventory
      description: 'Exports initial inventory for a specific warehouse as a CSV file.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token


        Response: text/csv file download'
      parameters:
      - name: warehouse
        in: path
        schema:
          type: integer
        required: true
        description: Warehouse ID
        example: '1'
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-export-initial-inventory-warehouse-export
  /api/export/sales-orders/{id}/export-lines:
    get:
      tags:
      - Export
      summary: Export Sales Order Lines
      description: 'Exports lines for a specific sales order as a CSV file.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token


        Response: text/csv file download


        Columns: sales_order_number, sku, description, quantity, price, warehouse_id,
        weight, weight_unit, length, width, height, dimension_unit, weight_extended
        (quantity x unit weight), volume_extended (quantity x unit volume). Weight
        and dimension values are sourced from the line''s product. The header row
        is always returned even when the order has no lines.'
      parameters:
      - name: id
        in: path
        schema:
          type: integer
        required: true
        description: Sales Order ID
        example: '100'
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-export-sales-orders-id-export-lines
  /api/export/v2/sales-order-line-financials:
    get:
      tags:
      - Export
      summary: Export Sales Order Line Financials (V2)
      description: 'Exports sales order line financials (v2) as a CSV file.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token


        Response: text/csv file download'
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-export-v2-sales-order-line-financials
  /api/export/sales-orders/packing-slips:
    get:
      tags:
      - Export
      summary: Export Sales Order Packing Slips
      description: 'Exports packing slips for multiple sales orders.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token


        Response: file download'
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-export-sales-orders-packing-slips
  /api/export/sales-orders/{sales_order}/invoice/pdf:
    get:
      tags:
      - Export
      summary: Download Sales Order Invoice PDF
      description: 'Downloads the invoice PDF for a specific sales order.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token


        Response: application/pdf file download'
      parameters:
      - name: sales_order
        in: path
        schema:
          type: integer
        required: true
        description: Sales Order ID
        example: '100'
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-export-sales-orders-sales-order-invoice-pdf
  /api/export/sales-orders/{sales_order}/packing-slip/pdf:
    get:
      tags:
      - Export
      summary: Download Sales Order Packing Slip PDF
      description: 'Downloads the packing slip PDF for a specific sales order.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token


        Response: application/pdf file download'
      parameters:
      - name: sales_order
        in: path
        schema:
          type: integer
        required: true
        description: Sales Order ID
        example: '100'
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-export-sales-orders-sales-order-packing-slip-pdf
  /api/export/sales-credits:
    get:
      tags:
      - Export
      summary: Export Sales Credits
      description: 'Exports sales credits as a CSV file.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token


        Response: text/csv file download'
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-export-sales-credits
  /api/export/sales-order-fulfillments/packing-slips:
    get:
      tags:
      - Export
      summary: Export Sales Order Fulfillment Packing Slips
      description: 'Exports packing slips for multiple sales order fulfillments.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token


        Response: file download'
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-export-sales-order-fulfillments-packing-slips
  /api/export/purchase-orders/{id}/export-lines:
    get:
      tags:
      - Export
      summary: Export Purchase Order Lines
      description: 'Exports lines for a specific purchase order as a CSV file.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token


        Response: text/csv file download'
      parameters:
      - name: id
        in: path
        schema:
          type: integer
        required: true
        description: Purchase Order ID
        example: '50'
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-export-purchase-orders-id-export-lines
  /api/export/purchase-orders/{purchase_order}/invoice/csv:
    get:
      tags:
      - Export
      summary: Download Purchase Order Invoice CSV
      description: 'Downloads the invoice CSV for a specific purchase order.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token


        Response: text/csv file download'
      parameters:
      - name: purchase_order
        in: path
        schema:
          type: integer
        required: true
        description: Purchase Order ID
        example: '50'
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-export-purchase-orders-purchase-order-invoice-csv
  /api/export/purchase-orders/{purchase_order}/invoice/pdf:
    get:
      tags:
      - Export
      summary: Download Purchase Order Invoice PDF
      description: 'Downloads the invoice PDF for a specific purchase order.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token


        Response: application/pdf file download'
      parameters:
      - name: purchase_order
        in: path
        schema:
          type: integer
        required: true
        description: Purchase Order ID
        example: '50'
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-export-purchase-orders-purchase-order-invoice-pdf
  /api/export/purchase-orders/{purchase_order}/picklist/pdf:
    get:
      tags:
      - Export
      summary: Download Purchase Order Picklist PDF
      description: 'Downloads the picklist PDF for a specific purchase order.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token


        Response: application/pdf file download'
      parameters:
      - name: purchase_order
        in: path
        schema:
          type: integer
        required: true
        description: Purchase Order ID
        example: '50'
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-export-purchase-orders-purchase-order-picklist-pdf
  /api/export/stock-takes/{stock_take}/export-lines:
    get:
      tags:
      - Export
      summary: Export Stock Take Lines
      description: 'Exports lines for a specific stock take as a CSV file.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token


        Response: text/csv file download'
      parameters:
      - name: stock_take
        in: path
        schema:
          type: integer
        required: true
        description: Stock Take ID
        example: '1'
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-export-stock-takes-stock-take-export-lines
  /api/export/warehouse-transfers/{id}/export-lines:
    get:
      tags:
      - Export
      summary: Export Warehouse Transfer Lines
      description: 'Exports lines for a specific warehouse transfer as a CSV file.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token


        Response: text/csv file download'
      parameters:
      - name: id
        in: path
        schema:
          type: integer
        required: true
        description: Warehouse Transfer ID
        example: '1'
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-export-warehouse-transfers-id-export-lines
  /api/export/ship-by-schedule:
    get:
      tags:
      - Export
      summary: Export Ship By Schedule
      description: 'Exports ship-by schedule data as a CSV/JSON file.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token


        Response: file download'
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-export-ship-by-schedule
  /api/export/v2/financial-alerts:
    get:
      tags:
      - Export
      summary: Export Financial Alerts (V2)
      description: 'Exports all financial alerts using the V2 API. Returns JSON array
        for client-side CSV generation.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        salesOrder:
                          type: string
                        salesOrderId:
                          type: integer
                        sku:
                          type: string
                        product_id:
                          type: integer
                        total_revenue:
                          type: number
                        cogs:
                          type: number
                        cogs_returned:
                          type: number
                        cost_allocated:
                          type: number
                        allocated_details:
                          type: array
                          items:
                            type: object
                            properties:
                              description:
                                type: string
                              amount:
                                type: number
                        total_cost:
                          type: number
                        profit:
                          type: number
                        profit_margin:
                          type: number
                        classification:
                          type: string
                        classification_id:
                          type: integer
                        archived_by_user:
                          type: string
                          nullable: true
                        archived_at:
                          type: string
                          nullable: true
                        is_resolved:
                          type: string
                example:
                  data:
                  - salesOrder: SO-1001
                    salesOrderId: 1001
                    sku: WIDGET-001
                    product_id: 42
                    total_revenue: 150.0
                    cogs: 80.0
                    cogs_returned: 0.0
                    cost_allocated: 10.0
                    allocated_details:
                    - description: Shipping
                      amount: 10.0
                    total_cost: 90.0
                    profit: 60.0
                    profit_margin: 40.0
                    classification: Low Margin
                    classification_id: 2
                    archived_by_user: null
                    archived_at: null
                    is_resolved: 'false'
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-export-v2-financial-alerts
  /api/export/v2/accounting-transactions:
    get:
      tags:
      - Export
      summary: Export Accounting Transactions (CSV)
      description: 'Streams a CSV export of accounting transactions with the same
        filters as the v3/transactions list endpoint. Response is a streaming text/csv
        file download.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token


        Filters use the same Spatie QueryBuilder parameters as GET /api/accounting/v3/transactions.'
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-export-v2-accounting-transactions
  /api/export/v2/profitability-drilldown:
    get:
      tags:
      - Export
      summary: Export Profitability Drilldown
      description: 'Dispatch an asynchronous CSV export of all profitability drilldown
        orders for a dimension. The drilldown materialises every order and builds
        the whole file, which can exceed a ~100s edge-proxy limit (Cloudflare 524)
        — so it runs as a tracked export job. Returns a tracked_job_log_id; progress
        and the download link surface via the tracked job log endpoints. The finished
        file is fetched from GET /api/export/download?file={filename}.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Query params: dimension (brand|sku|supplier|sales_channel|product_type|sub_sales_channel|customer_tags;
        customer_tags fans out so an order counts toward each of its customer''s tags
        and the grand total is deduplicated), dimension_value, flt_ids[] (financial
        line type ids for extra columns).'
      parameters:
      - name: dimension
        in: query
        schema:
          type: string
        description: 'Dimension to drilldown: brand | sku | supplier | sales_channel
          | product_type | sub_sales_channel | customer_tags. customer_tags fans out
          — an order counts toward each of its customer''s tags — and the grand total
          is deduplicated. customer_tags does not require attribute_id.'
        example: brand
      - name: dimension_value
        in: query
        schema:
          type: string
        description: Specific dimension value to filter by
        example: Nike
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                      queued:
                        type: boolean
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 5123
                    queued: true
                  message: Export started — track progress in the job tray
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-export-v2-profitability-drilldown
  /api/export/daily-financials:
    get:
      tags:
      - Export
      summary: Export Daily Financials
      description: 'Returns the full daily financial summary dataset as JSON for export,
        honoring the same filters and sorting as the daily summary listing (`GET /api/v2/financials/daily-summary`)
        but without pagination.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Each row aggregates one day''s financial activity for a subject: either a
        product (units sold, revenue, cost, profit for that SKU on that day) or a
        financial line type (order-level amounts such as shipping revenue or transaction
        fees). The `reportable` object identifies the subject.


        The response contains every matching row, so filter by date range to keep
        payloads manageable on large accounts.


        Large result sets are exported asynchronously: when the filtered dataset exceeds
        1000 rows the endpoint dispatches a background CSV export job and responds
        with a tracked_job_log_id (queued=true) instead of the inline rows. Poll the
        job by its tracked_job_log_id and fetch the finished file from GET /api/export/download?file={filename}.
        Smaller result sets return the rows inline as shown below.


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 OK
                  value:
                    data:
                    - id: 5012
                      date: '2026-06-15T00:00:00.000000Z'
                      reportable:
                        id: 101
                        type: App\Models\Product
                        product:
                          id: 101
                          sku: TSHIRT-BLK-M
                          brand: Acme
                          brand_id: 3
                      quantity: 14
                      quantity_returned: 1
                      num_orders: 12
                      revenue: 349.86
                      revenue_allocated: 0
                      revenue_credits: -24.99
                      revenue_discount: -10.0
                      total_revenue: 314.87
                      cost: 126.0
                      cost_allocated: 8.4
                      cost_invoices: 0
                      cost_returned: -9.0
                      cost_breakdown: null
                      total_cost: 125.4
                      profit: 189.47
                      profit_margin: 60.17
                      created_at: '2026-06-16T02:10:00.000000Z'
                      updated_at: '2026-06-16T02:10:00.000000Z'
                    - id: 5013
                      date: '2026-06-15T00:00:00.000000Z'
                      reportable:
                        id: 7
                        type: App\Models\FinancialLineType
                        financial_line_type:
                          id: 7
                          name: Shipping Revenue
                          classification: revenue
                      quantity: 0
                      quantity_returned: 0
                      num_orders: 12
                      revenue: 58.8
                      revenue_allocated: 0
                      revenue_credits: 0
                      revenue_discount: 0
                      total_revenue: 58.8
                      cost: 0
                      cost_allocated: 0
                      cost_invoices: 0
                      cost_returned: 0
                      cost_breakdown: null
                      total_cost: 0
                      profit: 58.8
                      profit_margin: 100
                      created_at: '2026-06-16T02:10:00.000000Z'
                      updated_at: '2026-06-16T02:10:00.000000Z'
                example-1:
                  summary: 200 Queued (large export)
                  value:
                    data:
                      tracked_job_log_id: 5123
                      queued: true
                    message: Export started — track progress in the job tray
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-export-daily-financials
  /api/export/v2/vendor-deposits:
    get:
      tags:
      - Export
      summary: Export Vendor Deposits
      description: 'Streams all vendor deposits matching the given filters as a CSV
        file download (`vendor-deposits.csv`). Honors the same filters and sorting
        as the vendor deposit list endpoints.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        CSV columns: Deposit #, Supplier, Purchase Order, Status, Currency, Amount,
        Amount Paid, Amount Applied, Amount Refunded, Available Balance, Deposit Date,
        Due Date, External Reference, Notes, Created At. Available Balance is computed
        as amount paid minus amounts applied and refunded (floored at 0).


        Archived deposits are excluded by default; pass `filter[archived]=1` to include
        them. The response is a file download (`text/csv`), not JSON.


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: text/csv
          content:
            text/plain:
              schema:
                type: string
                example: 'Deposit #,Supplier,Purchase Order,Status,Currency,Amount,Amount
                  Paid,Amount Applied,Amount Refunded,Available Balance,Deposit Date,Due
                  Date,External Reference,Notes,Created At

                  VD-00042,Acme Apparel Co,PO-350,paid,USD,5000.00,5000.00,2500.00,0.00,2500.00,2026-05-01,2026-05-15,WIRE-88213,30%
                  deposit on spring order,2026-05-01 14:22:10

                  VD-00043,Global Freight Co,PO-351,partially_paid,USD,1200.00,600.00,0.00,0.00,600.00,2026-05-20,2026-06-01,,,2026-05-20
                  09:03:41

                  '
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-export-v2-vendor-deposits
  /api/data-feeds/{id}:
    get:
      tags:
      - Data Feeds
      summary: Get Data Feed
      description: 'Returns a single data feed by ID.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      type:
                        type: string
                      data_direction:
                        type: string
                      connection_type:
                        type: string
                      connection_settings:
                        type: object
                        properties:
                          host:
                            type: string
                          username:
                            type: string
                          path:
                            type: string
                      field_settings:
                        type: string
                        nullable: true
                      filters:
                        type: string
                        nullable: true
                      schedule:
                        type: object
                        properties:
                          frequency:
                            type: string
                          time:
                            type: string
                      processed_at:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                example:
                  data:
                    id: 1
                    name: Daily Product Feed
                    type: product_feed
                    data_direction: import
                    connection_type: ftp_download
                    connection_settings:
                      host: ftp.supplier.com
                      username: feeduser
                      path: /feeds/products.csv
                    field_settings: null
                    filters: null
                    schedule:
                      frequency: daily
                      time: 02:00
                    processed_at: '2024-03-01T02:05:00.000000Z'
                    created_at: '2024-01-10T08:00:00.000000Z'
                    updated_at: '2024-03-01T02:05:00.000000Z'
                    archived_at: null
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No query results for model [App\Models\DataFeed] 999
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: get-api-data-feeds-id
    put:
      tags:
      - Data Feeds
      summary: Update Data Feed
      description: 'Updates an existing data feed configuration.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.


        All fields from Create are accepted.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                type:
                  type: string
                data_direction:
                  type: string
                connection_type:
                  type: string
                connection_settings:
                  type: object
                  properties:
                    sheet_id:
                      type: string
                    sheet_name:
                      type: string
                schedule:
                  type: object
                  properties:
                    frequency:
                      type: string
              example:
                name: Daily Product Feed Updated
                type: product_feed
                data_direction: import
                connection_type: google_sheets
                connection_settings:
                  sheet_id: 1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgVE2upms
                  sheet_name: Products
                schedule:
                  frequency: hourly
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      type:
                        type: string
                      connection_type:
                        type: string
                      updated_at:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 2
                    name: Daily Product Feed Updated
                    type: product_feed
                    connection_type: google_sheets
                    updated_at: '2024-03-01T14:00:00.000000Z'
                  message: data feed Daily Product Feed Updated updated successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-session-only: true
      operationId: put-api-data-feeds-id
    delete:
      tags:
      - Data Feeds
      summary: Delete Data Feed
      description: 'Deletes a data feed. Returns an error if the feed is linked to
        other records.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: data feed 2 deleted successfully
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: data feed 1 could not be deleted
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-session-only: true
      operationId: delete-api-data-feeds-id
  /api/data-feeds:
    post:
      tags:
      - Data Feeds
      summary: Create Data Feed
      description: 'Creates a new data feed and immediately dispatches an import job.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.


        Fields:

        - name (required, string, max:255)

        - type (required, string): product_feed

        - data_direction (required, string): import | export

        - connection_type (required, string): upload_file | download_file | ftp_download
        | google_sheets | rest_api | downloadable_file

        - connection_settings (optional, array — connection credentials and settings)

        - field_settings (optional, array — column mappings)

        - filters (optional, array — data filtering rules)

        - schedule (optional, array — scheduling configuration)


        **Requires permission:** `data_feeds.create`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                type:
                  type: string
                data_direction:
                  type: string
                connection_type:
                  type: string
                connection_settings:
                  type: object
                  properties:
                    host:
                      type: string
                    username:
                      type: string
                    password:
                      type: string
                    path:
                      type: string
                field_settings:
                  type: object
                  properties:
                    sku_column:
                      type: string
                    name_column:
                      type: string
                    price_column:
                      type: string
                filters:
                  type: object
                  properties:
                    active_only:
                      type: boolean
                schedule:
                  type: object
                  properties:
                    frequency:
                      type: string
                    time:
                      type: string
              example:
                name: Daily Product Feed
                type: product_feed
                data_direction: import
                connection_type: ftp_download
                connection_settings:
                  host: ftp.supplier.com
                  username: feeduser
                  password: secret
                  path: /feeds/products.csv
                field_settings:
                  sku_column: SKU
                  name_column: Product Name
                  price_column: Price
                filters:
                  active_only: true
                schedule:
                  frequency: daily
                  time: 02:00
      parameters: []
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      type:
                        type: string
                      data_direction:
                        type: string
                      connection_type:
                        type: string
                      connection_settings:
                        type: object
                        properties:
                          host:
                            type: string
                          username:
                            type: string
                          path:
                            type: string
                      field_settings:
                        type: object
                        properties:
                          sku_column:
                            type: string
                          name_column:
                            type: string
                          price_column:
                            type: string
                      filters:
                        type: object
                        properties:
                          active_only:
                            type: boolean
                      schedule:
                        type: object
                        properties:
                          frequency:
                            type: string
                          time:
                            type: string
                      processed_at:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                  message:
                    type: string
                example:
                  data:
                    id: 2
                    name: Daily Product Feed
                    type: product_feed
                    data_direction: import
                    connection_type: ftp_download
                    connection_settings:
                      host: ftp.supplier.com
                      username: feeduser
                      path: /feeds/products.csv
                    field_settings:
                      sku_column: SKU
                      name_column: Product Name
                      price_column: Price
                    filters:
                      active_only: true
                    schedule:
                      frequency: daily
                      time: 02:00
                    processed_at: null
                    created_at: '2024-03-01T12:00:00.000000Z'
                    updated_at: '2024-03-01T12:00:00.000000Z'
                    archived_at: null
                  message: data feed created successfully
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      name:
                        type: array
                        items:
                          type: string
                      type:
                        type: array
                        items:
                          type: string
                      connection_type:
                        type: array
                        items:
                          type: string
                example:
                  message: The given data was invalid.
                  errors:
                    name:
                    - The name field is required.
                    type:
                    - The selected type is invalid.
                    connection_type:
                    - The selected connection type is invalid.
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: post-api-data-feeds
    delete:
      tags:
      - Data Feeds
      summary: Bulk Delete Data Feeds
      description: 'Bulk deletes multiple data feeds by IDs.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `data_feeds.delete`'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 2 data feeds deleted successfully
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: delete-api-data-feeds
  /api/data-feeds/{id}/archive:
    put:
      tags:
      - Data Feeds
      summary: Archive Data Feed
      description: 'Archives a data feed. Returns a warning if already archived.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: data feed 1 archived successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-session-only: true
      operationId: put-api-data-feeds-id-archive
  /api/data-feeds/{id}/unarchived:
    put:
      tags:
      - Data Feeds
      summary: Unarchive Data Feed
      description: 'Unarchives a data feed. Returns a warning if not currently archived.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: data feed 1 unarchived successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-session-only: true
      operationId: put-api-data-feeds-id-unarchived
  /api/data-feeds/archive:
    put:
      tags:
      - Data Feeds
      summary: Bulk Archive Data Feeds
      description: 'Bulk archives multiple data feeds by IDs.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `data_feeds.archive`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1
                - 2
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 2 data feeds archived successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-session-only: true
      operationId: put-api-data-feeds-archive
  /api/data-feeds/unarchive:
    put:
      tags:
      - Data Feeds
      summary: Bulk Unarchive Data Feeds
      description: 'Bulk unarchives multiple data feeds by IDs.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `data_feeds.archive`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1
                - 2
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 2 data feeds unarchived successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-session-only: true
      operationId: put-api-data-feeds-unarchive
  /api/data-feeds/deletable:
    post:
      tags:
      - Data Feeds
      summary: Check Data Feeds Deletable
      description: 'Checks which data feeds can be safely deleted.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `data_feeds.delete`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1
                - 2
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                example:
                  data:
                  - id: 1
                    name: Daily Product Feed
                  - id: 2
                    name: Hourly Price Feed
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-session-only: true
      operationId: post-api-data-feeds-deletable
  /api/data-feeds/import-config/product_feed:
    get:
      tags:
      - Data Feeds
      summary: Get Import Config
      description: 'Returns the import configuration schema for a specific data feed
        type. Used to determine available field mappings and settings for a given
        feed type.


        Authentication: Requires Bearer token.


        The {dataFeed} path parameter should be a feed type key (e.g., product_feed).'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  fields:
                    type: array
                    items:
                      type: object
                      properties:
                        key:
                          type: string
                        label:
                          type: string
                        required:
                          type: boolean
                  connection_types:
                    type: array
                    items:
                      type: string
                example:
                  fields:
                  - key: sku
                    label: SKU
                    required: true
                  - key: name
                    label: Product Name
                    required: true
                  - key: price
                    label: Price
                    required: false
                  - key: quantity
                    label: Quantity
                    required: false
                  connection_types:
                  - upload_file
                  - ftp_download
                  - google_sheets
                  - rest_api
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-data-feeds-import-config-product-feed
  /api/inventory-forecasting/build:
    post:
      tags:
      - Inventory Intelligence
      summary: Build Forecast
      description: 'Build a replenishment forecast for one or more suppliers and return
        recommended order quantities per supplier, with a full per-line breakdown
        of how each number was derived.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        FORECAST TYPES (forecast_type)

        - with_sales_history: derive demand from historical sales velocity over the
        chosen window. The most common mode.

        - target_stock_level: order up to a fixed target quantity per product (target_quantity),
        or up to each product''s minimum stock level when use_min_stock_level_as_target
        is true. Velocity is not used to set the target.

        - fill_backorders: order only what is needed to clear outstanding backorders.
        Baseline and trend settings do not apply.


        BASELINE METHODS (baseline_method) - how the daily velocity baseline is derived
        from sales history (applies to with_sales_history)

        - flat (default): plain mean over the window (total units / days covered).
        No trend. Legacy behaviour - stable and predictable. Use when demand is roughly
        level.

        - recency_weighted: weights recent history more heavily than older history,
        so a recent shift in demand is reflected faster without projecting a hard
        trend line. Use for choppy demand that has recently stepped up or down. Tune
        with trend_half_life_days.

        - damped_trend: fits the recent growth (or decline) trend and projects it
        forward, attenuated by trend_damping_factor so a short surge does not overshoot
        into over-ordering. Use for a SKU on a sustained growth or decline curve.


        DAMPED-TREND CONTROLS

        - trend_damping_factor (0..1, default 0.85): the damping factor phi. Each
        period further out keeps only phi of the previous period''s growth, so the
        projected trend flattens instead of compounding forever. Lower = more damping
        (closer to flat mean); 1.0 = undamped.

        - trend_max_growth_pct (>= 0, default 100): caps how far the trend may lift
        the baseline above the flat mean. 100 means the trend may at most double the
        flat mean; 0 disables any lift. When the cap binds, the line reports trend_capped:
        true.

        - trend_half_life_days (>= 1, nullable, default 21): reserved tuning for recency_weighted
        - the age at which a day''s weight halves.


        SPARSE-HISTORY FALLBACK

        A trend needs enough signal to be trustworthy. If a product has fewer than
        roughly 8 weeks of history or fewer than 8 orders in the window, the trend
        is skipped and the baseline falls back to the flat mean for that product (trend_factor
        1.0), regardless of baseline_method. This stops a couple of early sales from
        projecting a runaway trend.


        ANOMALY CLEANSING (exclude_detected_anomalies, default false)

        When true, days already resolved as excluded or smoothed anomalies for a product
        are dropped (excluded) or replaced with their expected value (smoothed) before
        the baseline is computed. This de-contaminates one-off promo spikes and stockout
        gaps so they do not distort ordinary velocity. Detect and resolve anomalies
        first (see the Anomalies folder). Each line reports how many days were affected
        via inputs.anomaly_days_excluded and inputs.anomaly_days_smoothed.


        DEMAND MODIFIERS (demand_modifiers[])

        An array of adjustments layered onto the baseline. Each entry has a type:

        - percentage: scale demand by (1 + value/100), e.g. value 10 = +10%.

        - seasonal / event: a bounded uplift or reduction over a date range (start_date,
        end_date) for a known seasonal peak or one-time event; value is the percent
        change.

        - override: replace the daily average outright with value.

        - promo_lift: re-apply a previously measured promotion. Set promo_window_id
        to a promo window whose lift has been measured; the server hydrates that window''s
        live measured lift and applies it as a MULTIPLICATIVE factor on the current
        baseline. Because it multiplies the CURRENT baseline (not a stored absolute
        number), the same promo automatically re-scales as the business grows. Send
        value 0 - it is ignored and hydrated server-side.

        Optional per-modifier fields: apply_to (all or a scope key), name (label),
        period_key, start_date, end_date, product_id (limit to one product), promo_window_id
        (promo_lift only).


        FILTERS (product_filters, sales_filters)

        Both accept a filter_groups tree: a conjunction (and / or) plus a children
        array of conditions and nested groups. Each condition has column, operator,
        and value. product_filters narrows which products are forecast; sales_filters
        narrows which historical orders feed the velocity baseline. A legacy filters.filterSet
        shape is also accepted for older saved configurations.

        Operators: is, is_not, contains, does_not_contain, starts_with, ends_with,
        is_empty, is_not_empty, is_one_of, greater_than, less_than, between.

        Example: {"filter_groups": {"conjunction": "and", "children": [{"type": "condition",
        "condition": {"column": "order_status", "operator": "is_one_of", "value":
        ["shipped", "fulfilled"]}}]}}


        DECOMPOSITION RETURNED PER LINE (inputs object)

        Each forecast line''s inputs object exposes the multiplicative decomposition:

        - base_flat: the flat mean before any trend.

        - trend_factor: the multiplicative trend baked into the baseline (1.0 = none).

        - baseline_method: which method produced the baseline.

        - trend_capped: true if trend_max_growth_pct clamped the trend.

        - anomaly_days_excluded / anomaly_days_smoothed: how many history days were
        dropped / replaced by anomaly cleansing.

        - promo_factor: the multiplicative promo lift applied (null when no promo_lift
        modifier applied).

        - promo_window_name: the promo window that supplied the lift (null if none).

        - promo_current_baseline: the baseline the promo factor multiplied.

        The effective daily_average is base_flat x trend_factor x (promo_factor or
        1), then any percentage/event/override demand modifiers.


        SCENARIOS (copy a body variation for each)

        1) Flat baseline (default / legacy): omit baseline_method or send "flat".
        Velocity is the plain window mean; inputs.trend_factor is 1.0 and inputs.base_flat
        equals daily_average.

        2) Damped-trend for a growing SKU: baseline_method "damped_trend", trend_damping_factor
        0.85, trend_max_growth_pct 100. Recent growth is projected forward but damped
        and capped at 2x the flat mean; inputs.trend_factor rises above 1.0 and inputs.trend_capped
        reports whether the cap bound.

        3) Recency-weighted: baseline_method "recency_weighted", trend_half_life_days
        21. Recent days count more; no hard trend line is projected.

        4) Anomaly-cleansed baseline: exclude_detected_anomalies true (after resolving
        anomalies as excluded/smoothed). Promo spikes and stockout gaps are removed
        before the mean is taken; inputs.anomaly_days_excluded / inputs.anomaly_days_smoothed
        report the count.

        5) Re-apply a past promotion: add a demand_modifiers entry of type "promo_lift"
        with promo_window_id set to a measured promo window and value 0. The window''s
        live lift multiplies the current baseline, so it auto-scales with growth;
        inputs.promo_factor, inputs.promo_window_name, and inputs.promo_current_baseline
        are populated.

        6) Target stock level / fill backorders: forecast_type "target_stock_level"
        (with target_quantity, or use_min_stock_level_as_target true) orders up to
        a fixed target; forecast_type "fill_backorders" clears backorders only. Baseline
        and trend settings do not apply to fill_backorders.


        MINIMUMS

        enforce_minimum_order_value / enforce_minimum_order_quantity: when true, the
        per-supplier minimums block flags whether the forecast totals fall below the
        supplier''s minimum_purchase_order / minimum_purchase_order_quantity. Display-only
        here; enforcement is applied at PO creation time (POST /api/inventory-forecasting/purchase-orders).


        Each line also carries a confidence object (tier high/medium/low/new, 0-100
        score, drivers, reasons, actions), a prediction_interval (point/lower/upper
        at a service level), and a plain-language rationale.


        Returns 422 if too many products are found for any supplier.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                supplier_ids:
                  type: array
                  items:
                    type: integer
                forecast_type:
                  type: string
                target_stock_days:
                  type: integer
                sales_history_days:
                  type: integer
                sales_start_date:
                  type: string
                  nullable: true
                sales_end_date:
                  type: string
                  nullable: true
                use_leadtime:
                  type: boolean
                use_measured_lead_time:
                  type: boolean
                use_moq:
                  type: boolean
                use_case_pack:
                  type: boolean
                case_pack_rounding:
                  type: string
                override_product_target_days:
                  type: boolean
                rounding_method:
                  type: string
                destination_warehouse_id:
                  type: string
                  nullable: true
                pricing_tier_id:
                  type: string
                  nullable: true
                ignore_min_stock_level:
                  type: boolean
                baseline_method:
                  type: string
                trend_damping_factor:
                  type: number
                trend_max_growth_pct:
                  type: integer
                trend_half_life_days:
                  type: integer
                exclude_detected_anomalies:
                  type: boolean
                product_filters:
                  type: object
                  properties:
                    filter_groups:
                      type: object
                      properties:
                        conjunction:
                          type: string
                        children:
                          type: array
                          items:
                            type: object
                            properties:
                              type:
                                type: string
                              condition:
                                type: object
                                properties:
                                  column:
                                    type: string
                                  operator:
                                    type: string
                                  value:
                                    type: string
                sales_filters:
                  type: object
                  properties:
                    filter_groups:
                      type: object
                      properties:
                        conjunction:
                          type: string
                        children:
                          type: array
                          items:
                            type: object
                            properties:
                              type:
                                type: string
                              condition:
                                type: object
                                properties:
                                  column:
                                    type: string
                                  operator:
                                    type: string
                                  value:
                                    type: array
                                    items:
                                      type: string
                demand_modifiers:
                  type: array
                  items:
                    type: object
                    properties:
                      type:
                        type: string
                      value:
                        type: integer
                      apply_to:
                        type: string
                      name:
                        type: string
                      period_key:
                        type: string
                        nullable: true
                      start_date:
                        type: string
                      end_date:
                        type: string
                      product_id:
                        type: string
                        nullable: true
                enforce_minimum_order_value:
                  type: boolean
                enforce_minimum_order_quantity:
                  type: boolean
              example:
                supplier_ids:
                - 1
                - 2
                forecast_type: with_sales_history
                target_stock_days: 30
                sales_history_days: 90
                sales_start_date: null
                sales_end_date: null
                use_leadtime: true
                use_measured_lead_time: false
                use_moq: true
                use_case_pack: false
                case_pack_rounding: round_nearest
                override_product_target_days: false
                rounding_method: round_half_up
                destination_warehouse_id: null
                pricing_tier_id: null
                ignore_min_stock_level: false
                baseline_method: damped_trend
                trend_damping_factor: 0.85
                trend_max_growth_pct: 100
                trend_half_life_days: 21
                exclude_detected_anomalies: true
                product_filters:
                  filter_groups:
                    conjunction: and
                    children:
                    - type: condition
                      condition:
                        column: sku
                        operator: contains
                        value: PROD
                sales_filters:
                  filter_groups:
                    conjunction: and
                    children:
                    - type: condition
                      condition:
                        column: order_status
                        operator: is_one_of
                        value:
                        - shipped
                        - fulfilled
                demand_modifiers:
                - type: event
                  value: 15
                  apply_to: all
                  name: Holiday Boost
                  period_key: null
                  start_date: '2024-11-01'
                  end_date: '2024-12-31'
                  product_id: null
                - type: promo_lift
                  value: 0
                  apply_to: all
                  name: Re-apply Black Friday 2024
                  product_id: 56
                  promo_window_id: 12
                enforce_minimum_order_value: false
                enforce_minimum_order_quantity: false
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        supplier_id:
                          type: integer
                        supplier_name:
                          type: string
                        summary:
                          type: object
                          properties:
                            total_products:
                              type: integer
                            products_to_order:
                              type: integer
                            total_units:
                              type: integer
                            total_value:
                              type: number
                        lines:
                          type: array
                          items:
                            type: object
                            properties:
                              supplier_product_id:
                                type: integer
                              product_id:
                                type: integer
                              sku:
                                type: string
                              name:
                                type: string
                              recommended_quantity:
                                type: integer
                              unit_cost:
                                type: number
                              total_cost:
                                type: number
                              current_stock:
                                type: integer
                              days_of_stock:
                                type: integer
                              avg_daily_sales:
                                type: number
                              leadtime_days:
                                type: integer
                              status:
                                type: string
                              inputs:
                                type: object
                                properties:
                                  target_days:
                                    type: integer
                                  target_days_source:
                                    type: string
                                  leadtime:
                                    type: integer
                                  leadtime_source:
                                    type: string
                                  supplier_lead_time:
                                    type: integer
                                  effective_days:
                                    type: integer
                                  daily_average:
                                    type: number
                                  available:
                                    type: integer
                                  inbound:
                                    type: integer
                                  in_transit:
                                    type: integer
                                  backordered:
                                    type: integer
                                  moq:
                                    type: integer
                                  moq_source:
                                    type: string
                                  min_stock_level:
                                    type: integer
                                  min_stock_level_ignored:
                                    type: boolean
                                  order_trigger:
                                    type: string
                                  rounding_method:
                                    type: string
                                  base_daily_average:
                                    type: number
                                  base_flat:
                                    type: number
                                  trend_factor:
                                    type: number
                                  baseline_method:
                                    type: string
                                  trend_capped:
                                    type: boolean
                                  anomaly_days_excluded:
                                    type: integer
                                  anomaly_days_smoothed:
                                    type: integer
                                  promo_factor:
                                    type: string
                                    nullable: true
                                  promo_window_name:
                                    type: string
                                    nullable: true
                                  promo_current_baseline:
                                    type: string
                                    nullable: true
                                  formula:
                                    type: string
                              confidence:
                                type: object
                                properties:
                                  tier:
                                    type: string
                                  score:
                                    type: integer
                                  drivers:
                                    type: array
                                    items:
                                      type: object
                                      properties:
                                        key:
                                          type: string
                                        label:
                                          type: string
                                        value:
                                          type: string
                                        status:
                                          type: string
                                  reasons:
                                    type: array
                                    items:
                                      type: string
                                  actions:
                                    type: array
                                    items:
                                      type: object
                                      properties:
                                        type:
                                          type: string
                                        label:
                                          type: string
                              prediction_interval:
                                type: object
                                properties:
                                  point:
                                    type: integer
                                  lower:
                                    type: integer
                                  upper:
                                    type: integer
                                  service_level:
                                    type: number
                                  method:
                                    type: string
                                  sigma:
                                    type: number
                              rationale:
                                type: string
                        active_lines_count:
                          type: integer
                        skipped_lines_count:
                          type: integer
                        pricing_tiers:
                          type: array
                        default_pricing_tier_id:
                          type: string
                          nullable: true
                        minimums:
                          type: object
                          properties:
                            enforce_value:
                              type: boolean
                            enforce_quantity:
                              type: boolean
                            minimum_value:
                              type: number
                            minimum_quantity:
                              type: integer
                example:
                  data:
                  - supplier_id: 1
                    supplier_name: Acme Supplier Co.
                    summary:
                      total_products: 25
                      products_to_order: 18
                      total_units: 512
                      total_value: 14380.0
                    lines:
                    - supplier_product_id: 101
                      product_id: 55
                      sku: PROD-001
                      name: Widget A
                      recommended_quantity: 88
                      unit_cost: 12.5
                      total_cost: 1100.0
                      current_stock: 10
                      days_of_stock: 2
                      avg_daily_sales: 5.1618
                      leadtime_days: 14
                      status: order
                      inputs:
                        target_days: 30
                        target_days_source: config
                        leadtime: 14
                        leadtime_source: supplier
                        supplier_lead_time: 14
                        effective_days: 44
                        daily_average: 5.1618
                        available: 10
                        inbound: 0
                        in_transit: 0
                        backordered: 0
                        moq: 25
                        moq_source: supplier
                        min_stock_level: 20
                        min_stock_level_ignored: false
                        order_trigger: velocity
                        rounding_method: round_half_up
                        base_daily_average: 5.1618
                        base_flat: 3.08
                        trend_factor: 1.6759
                        baseline_method: damped_trend
                        trend_capped: false
                        anomaly_days_excluded: 2
                        anomaly_days_smoothed: 0
                        promo_factor: null
                        promo_window_name: null
                        promo_current_baseline: null
                        formula: (daily_average x effective_days) - available - inbound
                          + backordered
                      confidence:
                        tier: medium
                        score: 62
                        drivers:
                        - key: history_length
                          label: History length
                          value: 90 days
                          status: ok
                        - key: selling_density
                          label: Selling density
                          value: 71/90 days had sales
                          status: ok
                        - key: variability
                          label: Demand variability (CV)
                          value: '0.80'
                          status: warn
                        - key: recency
                          label: Last sale
                          value: 1 day ago
                          status: ok
                        reasons:
                        - Demand is moderately variable (CV 0.80)
                        actions:
                        - type: extend_window
                          label: Extend the sales window
                      prediction_interval:
                        point: 88
                        lower: 66
                        upper: 116
                        service_level: 90.0
                        method: cv_heuristic
                        sigma: 15.1
                      rationale: 'Ordering 88: 90 days of history, damped-trend baseline
                        lifting a 3.08/day flat mean to 5.16/day (trend factor 1.68),
                        2 promo-spike days excluded, 14-day lead time, 10 on hand.
                        Confidence Medium. Likely range 66-116 at 90% service level.'
                    - supplier_product_id: 102
                      product_id: 56
                      sku: PROD-002
                      name: Widget B
                      recommended_quantity: 140
                      unit_cost: 8.0
                      total_cost: 1120.0
                      current_stock: 25
                      days_of_stock: 3
                      avg_daily_sales: 7.77
                      leadtime_days: 14
                      status: order
                      inputs:
                        target_days: 30
                        target_days_source: config
                        leadtime: 14
                        leadtime_source: supplier
                        supplier_lead_time: 14
                        effective_days: 44
                        daily_average: 7.77
                        available: 25
                        inbound: 0
                        in_transit: 0
                        backordered: 0
                        moq: 50
                        moq_source: supplier
                        min_stock_level: 30
                        min_stock_level_ignored: false
                        order_trigger: velocity
                        rounding_method: round_half_up
                        base_daily_average: 4.2
                        base_flat: 4.2
                        trend_factor: 1.0
                        baseline_method: damped_trend
                        trend_capped: false
                        anomaly_days_excluded: 0
                        anomaly_days_smoothed: 0
                        promo_factor: 1.85
                        promo_window_name: Black Friday 2024
                        promo_current_baseline: 4.2
                        demand_modifier_description: 'Promo lift: Black Friday 2024
                          (x1.85)'
                        formula: (daily_average x effective_days) - available - inbound
                          + backordered
                      confidence:
                        tier: high
                        score: 84
                        drivers:
                        - key: history_length
                          label: History length
                          value: 90 days
                          status: ok
                        - key: selling_density
                          label: Selling density
                          value: 88/90 days had sales
                          status: ok
                        - key: variability
                          label: Demand variability (CV)
                          value: '0.42'
                          status: ok
                        - key: recency
                          label: Last sale
                          value: today
                          status: ok
                        reasons:
                        - Dense, recent, low-variability history
                        actions: []
                      prediction_interval:
                        point: 140
                        lower: 118
                        upper: 168
                        service_level: 90.0
                        method: cv_heuristic
                        sigma: 17.2
                      rationale: 'Ordering 140: flat 4.2/day baseline re-scaled by
                        the measured Black Friday 2024 lift (x1.85) to 7.77/day, 14-day
                        lead time, 25 on hand. The lift is multiplicative on the current
                        baseline, so it tracks this year''s larger demand. Confidence
                        High. Likely range 118-168 at 90% service level.'
                    active_lines_count: 18
                    skipped_lines_count: 7
                    pricing_tiers: []
                    default_pricing_tier_id: null
                    minimums:
                      enforce_value: false
                      enforce_quantity: false
                      minimum_value: 1000.0
                      minimum_quantity: 100
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                  message:
                    type: string
                example:
                  error: Too many products
                  message: Supplier has 55000 products which exceeds the limit of
                    50000.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-inventory-forecasting-build
  /api/inventory-forecasting/build-single:
    post:
      tags:
      - Inventory Intelligence
      summary: Build Forecast (Single Supplier)
      description: 'Build a forecast for a single supplier. If the product count is
        large the request is queued as a background job and the response returns a
        job_id for polling; otherwise the result is returned synchronously.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Response type field: sync (includes data) or async (includes job_id for status
        polling).


        This endpoint accepts the same forecast controls as Build Forecast, including
        the baseline decomposition:

        - baseline_method: flat (default), recency_weighted, or damped_trend.

        - trend_damping_factor (0..1, default 0.85): damping factor phi for damped_trend;
        lower = more damping.

        - trend_max_growth_pct (>= 0, default 100): caps the trend lift above the
        flat mean (100 = may at most double it).

        - trend_half_life_days (>= 1, nullable, default 21): reserved tuning for recency_weighted.

        - exclude_detected_anomalies (default false): drop/replace resolved anomaly
        days before computing the baseline.

        - demand_modifiers[]: percentage, seasonal, event, override, or promo_lift
        (carry promo_window_id and send value 0 - the window''s measured lift is applied
        multiplicatively to the current baseline).


        The sparse-history fallback applies here too: a product with fewer than roughly
        8 weeks of history or fewer than 8 orders falls back to the flat mean (trend_factor
        1.0). See Build Forecast for the full field guide and the per-line inputs
        decomposition (base_flat, trend_factor, baseline_method, trend_capped, anomaly_days_excluded,
        anomaly_days_smoothed, promo_factor, promo_window_name, promo_current_baseline).


        enforce_minimum_order_value / enforce_minimum_order_quantity: when true, the
        minimums block flags whether the forecast totals fall below the supplier''s
        minimum_purchase_order / minimum_purchase_order_quantity. Display-only here;
        enforcement is applied at PO creation time (POST /api/inventory-forecasting/purchase-orders).


        Returns 422 if too many products are found.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                supplier_id:
                  type: integer
                product_count:
                  type: integer
                supplier_ids:
                  type: array
                  items:
                    type: integer
                forecast_type:
                  type: string
                target_stock_days:
                  type: integer
                sales_history_days:
                  type: integer
                use_leadtime:
                  type: boolean
                use_measured_lead_time:
                  type: boolean
                use_moq:
                  type: boolean
                rounding_method:
                  type: string
                baseline_method:
                  type: string
                trend_damping_factor:
                  type: number
                trend_max_growth_pct:
                  type: integer
                trend_half_life_days:
                  type: integer
                exclude_detected_anomalies:
                  type: boolean
                product_filters:
                  type: object
                  properties: {}
                sales_filters:
                  type: object
                  properties: {}
                demand_modifiers:
                  type: array
                  items:
                    type: object
                    properties:
                      type:
                        type: string
                      value:
                        type: integer
                      apply_to:
                        type: string
                      name:
                        type: string
                      product_id:
                        type: integer
                      promo_window_id:
                        type: integer
                enforce_minimum_order_value:
                  type: boolean
                enforce_minimum_order_quantity:
                  type: boolean
              example:
                supplier_id: 1
                product_count: 120
                supplier_ids:
                - 1
                forecast_type: with_sales_history
                target_stock_days: 30
                sales_history_days: 90
                use_leadtime: true
                use_measured_lead_time: false
                use_moq: true
                rounding_method: round_half_up
                baseline_method: recency_weighted
                trend_damping_factor: 0.85
                trend_max_growth_pct: 100
                trend_half_life_days: 21
                exclude_detected_anomalies: false
                product_filters: {}
                sales_filters: {}
                demand_modifiers:
                - type: promo_lift
                  value: 0
                  apply_to: all
                  name: Re-apply Prime Day
                  product_id: 55
                  promo_window_id: 8
                enforce_minimum_order_value: false
                enforce_minimum_order_quantity: false
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 Sync Result
                  value:
                    data:
                      type: sync
                      data:
                        supplier_id: 1
                        supplier_name: Acme Supplier Co.
                        active_lines_count: 12
                        skipped_lines_count: 3
                        minimums:
                          enforce_value: false
                          enforce_quantity: false
                          minimum_value: 1000.0
                          minimum_quantity: 100
                example-1:
                  summary: 200 Async Job
                  value:
                    data:
                      type: async
                      job_id: abc123def456
                      status: queued
                      minimums:
                        enforce_value: false
                        enforce_quantity: false
                        minimum_value: 1000.0
                        minimum_quantity: 100
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-inventory-forecasting-build-single
  /api/inventory-forecasting/job/{jobId}/status:
    get:
      tags:
      - Inventory Intelligence
      summary: Get Job Status
      description: 'Poll the status of a background forecast job dispatched by build-single.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Status values: queued, processing, completed, failed.


        When status is ''completed'', the result field is included with full forecast
        data.


        Returns 404 if job ID not found or has expired.'
      parameters:
      - name: jobId
        in: path
        schema:
          type: string
        required: true
        description: The job ID returned from build-single when dispatched async
        example: abc123def456
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 Processing
                  value:
                    data:
                      status: processing
                      progress: 45
                      message: Processing products 45 of 120
                      supplier_id: 1
                      product_count: 120
                example-1:
                  summary: 200 Completed
                  value:
                    data:
                      status: completed
                      progress: 100
                      message: Completed
                      supplier_id: 1
                      product_count: 120
                      result:
                        supplier_id: 1
                        supplier_name: Acme Supplier Co.
                        active_lines_count: 85
                        skipped_lines_count: 35
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                  message:
                    type: string
                example:
                  error: Job not found
                  message: The requested job ID was not found or has expired.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-inventory-forecasting-job-jobid-status
  /api/inventory-forecasting/sales-history:
    post:
      tags:
      - Inventory Intelligence
      summary: Get Sales History
      description: 'Get aggregated sales history for products grouped by time period.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Period values: week, month, quarter, year (defaults to week).


        Date format: YYYY-MM-DD. start_date must be <= end_date.


        Returns an array keyed by product_id, each with periods array containing quantity
        and value per period.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                product_ids:
                  type: array
                  items:
                    type: integer
                start_date:
                  type: string
                end_date:
                  type: string
                period:
                  type: string
                warehouse_id:
                  type: string
                  nullable: true
                filters:
                  type: object
                  properties: {}
              example:
                product_ids:
                - 55
                - 56
                - 57
                start_date: '2023-10-01'
                end_date: '2024-10-01'
                period: week
                warehouse_id: null
                filters: {}
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        product_id:
                          type: integer
                        periods:
                          type: array
                          items:
                            type: object
                            properties:
                              period:
                                type: string
                              quantity:
                                type: integer
                              value:
                                type: number
                example:
                  data:
                  - product_id: 55
                    periods:
                    - period: 2024-W01
                      quantity: 12
                      value: 150.0
                    - period: 2024-W02
                      quantity: 8
                      value: 100.0
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-inventory-forecasting-sales-history
  /api/inventory-forecasting/sales-orders:
    get:
      tags:
      - Inventory Intelligence
      summary: List Sales Orders Behind a Forecast Cell
      description: 'Get individual sales orders for a product (drill-down view). Used
        when clicking into a product''s sales period in the forecast UI.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Date format: YYYY-MM-DD. Returns paginated sales orders.'
      parameters:
      - name: product_id
        in: query
        schema:
          type: integer
        description: Required. Product ID to get sales orders for.
        example: '55'
      - name: start_date
        in: query
        schema:
          type: string
        description: Required. Start date (YYYY-MM-DD).
        example: '2023-10-01'
      - name: end_date
        in: query
        schema:
          type: string
        description: Required. End date (YYYY-MM-DD).
        example: '2024-10-01'
      - name: per_page
        in: query
        schema:
          type: integer
        description: Optional. Items per page (1-100, default 10).
        example: '10'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        order_number:
                          type: string
                        order_date:
                          type: string
                        quantity:
                          type: integer
                        unit_price:
                          type: number
                        total:
                          type: number
                        status:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 1001
                    order_number: SO-1001
                    order_date: '2024-03-15'
                    quantity: 10
                    unit_price: 25.0
                    total: 250.0
                    status: fulfilled
                  current_page: 1
                  last_page: 3
                  per_page: 10
                  total: 28
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-inventory-forecasting-sales-orders
  /api/inventory-forecasting/purchase-orders:
    post:
      tags:
      - Inventory Intelligence
      summary: Create Purchase Orders from Forecast
      description: 'Create purchase orders from forecast results. Creates a ForecastScheduleRun
        to track the creation.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        approval_status: draft (default) or approved — if approved, auto-approves
        the PO after creation.


        submit_to_supplier: if true, submits the PO to the supplier after creation.


        fore cast_config is optional but recommended for tracking — stores a snapshot
        of the config used.


        Also syncs backorder coverage for all new PO lines.


        Returns 422 if no valid orders provided.


        Supplier minimum enforcement: when forecast_config.enforce_minimum_order_value
        or forecast_config.enforce_minimum_order_quantity is true and the order totals
        fall below the supplier''s minimum_purchase_order or minimum_purchase_order_quantity,
        the request is rejected with 422 unless minimums_acknowledged is true on that
        order.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                orders:
                  type: array
                  items:
                    type: object
                    properties:
                      supplier_id:
                        type: integer
                      pricing_tier_id:
                        type: string
                        nullable: true
                      destination_warehouse_id:
                        type: integer
                      approval_status:
                        type: string
                      submit_to_supplier:
                        type: boolean
                      lines:
                        type: array
                        items:
                          type: object
                          properties:
                            supplier_product_id:
                              type: integer
                            quantity:
                              type: integer
                            unit_cost:
                              type: number
                      forecast_config:
                        type: object
                        properties:
                          supplier_ids:
                            type: array
                            items:
                              type: integer
                          forecast_type:
                            type: string
                          target_stock_days:
                            type: integer
                          use_leadtime:
                            type: boolean
                          use_measured_lead_time:
                            type: boolean
                          use_moq:
                            type: boolean
                          rounding_method:
                            type: string
                          sales_history_days:
                            type: integer
                          product_filters:
                            type: object
                            properties: {}
                          sales_filters:
                            type: object
                            properties: {}
                          demand_modifiers:
                            type: array
                          enforce_minimum_order_value:
                            type: boolean
                          enforce_minimum_order_quantity:
                            type: boolean
                      minimums_acknowledged:
                        type: boolean
              example:
                orders:
                - supplier_id: 1
                  pricing_tier_id: null
                  destination_warehouse_id: 2
                  approval_status: draft
                  submit_to_supplier: false
                  lines:
                  - supplier_product_id: 101
                    quantity: 50
                    unit_cost: 12.5
                  - supplier_product_id: 102
                    quantity: 25
                    unit_cost: null
                  forecast_config:
                    supplier_ids:
                    - 1
                    forecast_type: sales_history
                    target_stock_days: 30
                    use_leadtime: true
                    use_measured_lead_time: false
                    use_moq: true
                    rounding_method: round_half_up
                    sales_history_days: 90
                    product_filters: {}
                    sales_filters: {}
                    demand_modifiers: []
                    enforce_minimum_order_value: false
                    enforce_minimum_order_quantity: false
                  minimums_acknowledged: false
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        purchase_order_number:
                          type: string
                        supplier_id:
                          type: integer
                        supplier_name:
                          type: string
                        order_status:
                          type: string
                        total_cost:
                          type: number
                        created_at:
                          type: string
                example:
                  data:
                  - id: 500
                    purchase_order_number: PO-500
                    supplier_id: 1
                    supplier_name: Acme Supplier Co.
                    order_status: draft
                    total_cost: 850.0
                    created_at: '2024-10-15T09:00:00+00:00'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                  message:
                    type: string
                  violations:
                    type: array
                    items:
                      type: object
                      properties:
                        supplier_id:
                          type: integer
                        supplier_name:
                          type: string
                        total_value:
                          type: number
                        total_quantity:
                          type: integer
                        minimum_value:
                          type: number
                        minimum_quantity:
                          type: string
                          nullable: true
                        below_value:
                          type: boolean
                        below_quantity:
                          type: boolean
                example:
                  error: Supplier minimum not met
                  message: One or more orders fall below the supplier minimum and
                    have not been acknowledged.
                  violations:
                  - supplier_id: 1
                    supplier_name: Acme Supplier Co.
                    total_value: 50.0
                    total_quantity: 10
                    minimum_value: 1000.0
                    minimum_quantity: null
                    below_value: true
                    below_quantity: false
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-inventory-forecasting-purchase-orders
  /api/inventory-forecasting/recalculate-costs:
    post:
      tags:
      - Inventory Intelligence
      summary: Recalculate Costs
      description: 'Recalculate supplier product costs using a different pricing tier.
        Used when the user switches pricing tier in the forecast UI.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        priceing_tier_id: optional; pass null to use default pricing.


        Returns a map of supplier_product_id → new unit cost.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                supplier_product_ids:
                  type: array
                  items:
                    type: integer
                pricing_tier_id:
                  type: integer
              example:
                supplier_product_ids:
                - 101
                - 102
                - 103
                pricing_tier_id: 5
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      costs:
                        type: object
                        properties:
                          '101':
                            type: number
                          '102':
                            type: number
                          '103':
                            type: number
                example:
                  data:
                    costs:
                      '101': 11.5
                      '102': 8.75
                      '103': 22.0
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-inventory-forecasting-recalculate-costs
  /api/inventory-forecasting/suppliers/summary:
    post:
      tags:
      - Inventory Intelligence
      summary: Get Supplier Summary
      description: 'Get a summary of suppliers with product counts. Used for lazy-loading
        supplier tabs in the forecast UI before running the full forecast.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        forecast_type: optional — if provided, filters product counts based on type
        compatibility.


        product_filters: optional filter_groups structure.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                supplier_ids:
                  type: array
                  items:
                    type: integer
                product_filters:
                  type: object
                  properties: {}
                forecast_type:
                  type: string
              example:
                supplier_ids:
                - 1
                - 2
                - 3
                product_filters: {}
                forecast_type: sales_history
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        supplier_id:
                          type: integer
                        supplier_name:
                          type: string
                        product_count:
                          type: integer
                        active_product_count:
                          type: integer
                example:
                  data:
                  - supplier_id: 1
                    supplier_name: Acme Supplier Co.
                    product_count: 120
                    active_product_count: 105
                  - supplier_id: 2
                    supplier_name: Beta Parts Ltd.
                    product_count: 45
                    active_product_count: 42
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-inventory-forecasting-suppliers-summary
  /api/inventory-forecasting/schedule-runs/{runId}/lines:
    get:
      tags:
      - Inventory Intelligence
      summary: List Forecast Run Lines
      description: 'List the stored per-line breakdown for a forecast run, paginated.
        Each line captures the recommended quantity, confidence tier and drivers,
        and the inventory/sales snapshots that fed the calculation.


        Authentication: Requires Bearer token.


        Path parameter: runId - the forecast run to read lines for.


        Pagination: page (default 1), per_page (default 15).'
      parameters:
      - name: runId
        in: path
        schema:
          type: string
        required: true
        description: The run ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        forecast_schedule_run_id:
                          type: integer
                        product_id:
                          type: integer
                        supplier_id:
                          type: integer
                        final_quantity:
                          type: integer
                        confidence_tier:
                          type: string
                        confidence_drivers:
                          type: object
                          properties:
                            history_days:
                              type: integer
                            selling_density:
                              type: number
                            coefficient_of_variation:
                              type: number
                            days_with_sales:
                              type: integer
                            from_fallback:
                              type: boolean
                            reason:
                              type: string
                        inputs:
                          type: object
                          properties:
                            forecast_type:
                              type: string
                            target_stock_days:
                              type: integer
                            sales_history_days:
                              type: integer
                            avg_daily_sales:
                              type: number
                            leadtime_days:
                              type: integer
                        inventory_snapshot:
                          type: object
                          properties:
                            current_stock:
                              type: integer
                            incoming:
                              type: integer
                            allocated:
                              type: integer
                        sales_snapshot:
                          type: object
                          properties:
                            total_sold:
                              type: integer
                            period_days:
                              type: integer
                            avg_daily_sales:
                              type: number
                        forecast_method:
                          type: string
                        baseline_method:
                          type: string
                        product:
                          type: object
                          properties:
                            id:
                              type: integer
                            sku:
                              type: string
                            name:
                              type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 8801
                    forecast_schedule_run_id: 512
                    product_id: 55
                    supplier_id: 1
                    final_quantity: 50
                    confidence_tier: high
                    confidence_drivers:
                      history_days: 742
                      selling_density: 0.86
                      coefficient_of_variation: 0.22
                      days_with_sales: 78
                      from_fallback: false
                      reason: Long, dense, stable sales history
                    inputs:
                      forecast_type: sales_history
                      target_stock_days: 30
                      sales_history_days: 90
                      avg_daily_sales: 2.5
                      leadtime_days: 14
                    inventory_snapshot:
                      current_stock: 10
                      incoming: 0
                      allocated: 3
                    sales_snapshot:
                      total_sold: 225
                      period_days: 90
                      avg_daily_sales: 2.5
                    forecast_method: sales_history
                    baseline_method: moving_average
                    product:
                      id: 55
                      sku: PROD-001
                      name: Widget A
                    created_at: '2024-10-15T09:00:00+00:00'
                    updated_at: '2024-10-15T09:00:00+00:00'
                  current_page: 1
                  last_page: 1
                  per_page: 15
                  total: 18
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-inventory-forecasting-schedule-runs-runid-lines
    post:
      tags:
      - Inventory Intelligence
      summary: Persist Forecast Run Lines
      description: 'Build a forecast from the supplied configuration and store its
        per-line breakdown against an existing forecast run. The work runs in the
        background; the response returns immediately with a job reference to poll
        for progress.


        Authentication: Requires Bearer token.


        Path parameter: runId - the forecast run to attach the persisted lines to.


        Body: configuration (required) - the full forecast configuration (forecast
        type, stock targets, filters, and demand modifiers) to build from.


        Returns 202 Accepted with a job reference (tracked_job_log_id).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                configuration:
                  type: object
                  properties:
                    supplier_ids:
                      type: array
                      items:
                        type: integer
                    forecast_type:
                      type: string
                    target_stock_days:
                      type: integer
                    sales_history_days:
                      type: integer
                    use_leadtime:
                      type: boolean
                    use_moq:
                      type: boolean
                    rounding_method:
                      type: string
                    product_filters:
                      type: object
                      properties: {}
                    sales_filters:
                      type: object
                      properties: {}
                    demand_modifiers:
                      type: array
              example:
                configuration:
                  supplier_ids:
                  - 1
                  forecast_type: sales_history
                  target_stock_days: 30
                  sales_history_days: 90
                  use_leadtime: true
                  use_moq: true
                  rounding_method: round_half_up
                  product_filters: {}
                  sales_filters: {}
                  demand_modifiers: []
      parameters:
      - name: runId
        in: path
        schema:
          type: string
        required: true
        description: The run ID.
      responses:
        '202':
          description: Accepted
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 12345
                  message: Forecast run persistence started
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-inventory-forecasting-schedule-runs-runid-lines
  /api/inventory-forecasting/schedule-runs/{runId}/lines/{productId}:
    get:
      tags:
      - Inventory Intelligence
      summary: Get Forecast Run Line
      description: 'Get the stored forecast run line for a single product within a
        run, including the full confidence drivers and the inventory and sales snapshots
        taken at build time.


        Authentication: Requires Bearer token.


        Path parameters: runId - the forecast run; productId - the product whose line
        to read.


        Returns 404 if no line exists for that run and product.'
      parameters:
      - name: runId
        in: path
        schema:
          type: string
        required: true
        description: The run ID.
      - name: productId
        in: path
        schema:
          type: string
        required: true
        description: The product ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      forecast_schedule_run_id:
                        type: integer
                      product_id:
                        type: integer
                      supplier_id:
                        type: integer
                      final_quantity:
                        type: integer
                      confidence_tier:
                        type: string
                      confidence_drivers:
                        type: object
                        properties:
                          history_days:
                            type: integer
                          selling_density:
                            type: number
                          coefficient_of_variation:
                            type: number
                          days_with_sales:
                            type: integer
                          from_fallback:
                            type: boolean
                          reason:
                            type: string
                      inputs:
                        type: object
                        properties:
                          forecast_type:
                            type: string
                          target_stock_days:
                            type: integer
                          sales_history_days:
                            type: integer
                          avg_daily_sales:
                            type: number
                          leadtime_days:
                            type: integer
                      inventory_snapshot:
                        type: object
                        properties:
                          current_stock:
                            type: integer
                          incoming:
                            type: integer
                          allocated:
                            type: integer
                      sales_snapshot:
                        type: object
                        properties:
                          total_sold:
                            type: integer
                          period_days:
                            type: integer
                          avg_daily_sales:
                            type: number
                      forecast_method:
                        type: string
                      baseline_method:
                        type: string
                      product:
                        type: object
                        properties:
                          id:
                            type: integer
                          sku:
                            type: string
                          name:
                            type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 8801
                    forecast_schedule_run_id: 512
                    product_id: 55
                    supplier_id: 1
                    final_quantity: 50
                    confidence_tier: high
                    confidence_drivers:
                      history_days: 742
                      selling_density: 0.86
                      coefficient_of_variation: 0.22
                      days_with_sales: 78
                      from_fallback: false
                      reason: Long, dense, stable sales history
                    inputs:
                      forecast_type: sales_history
                      target_stock_days: 30
                      sales_history_days: 90
                      avg_daily_sales: 2.5
                      leadtime_days: 14
                    inventory_snapshot:
                      current_stock: 10
                      incoming: 0
                      allocated: 3
                    sales_snapshot:
                      total_sold: 225
                      period_days: 90
                      avg_daily_sales: 2.5
                    forecast_method: sales_history
                    baseline_method: moving_average
                    product:
                      id: 55
                      sku: PROD-001
                      name: Widget A
                    created_at: '2024-10-15T09:00:00+00:00'
                    updated_at: '2024-10-15T09:00:00+00:00'
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: Forecast run line not found
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-inventory-forecasting-schedule-runs-runid-lines-productid
  /api/inventory-forecasting/configurations:
    get:
      tags:
      - Inventory
      summary: List Forecast Configurations
      description: 'Lists all forecast configurations (no pagination). Each item includes
        a `schedules_count` field for the number of automation schedules referencing
        it.

        Authentication: Requires Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        description:
                          type: string
                        supplier_ids:
                          type: array
                          items:
                            type: integer
                        forecast_type:
                          type: string
                        target_quantity:
                          type: string
                          nullable: true
                        use_min_stock_level_as_target:
                          type: boolean
                        sales_history_days:
                          type: integer
                        sales_start_date:
                          type: string
                          nullable: true
                        sales_end_date:
                          type: string
                          nullable: true
                        target_stock_days:
                          type: integer
                        use_leadtime:
                          type: boolean
                        use_measured_lead_time:
                          type: boolean
                        use_moq:
                          type: boolean
                        enforce_minimum_order_value:
                          type: boolean
                        enforce_minimum_order_quantity:
                          type: boolean
                        use_case_pack:
                          type: boolean
                        case_pack_rounding:
                          type: string
                          nullable: true
                        ignore_min_stock_level:
                          type: boolean
                        rounding_method:
                          type: string
                        destination_warehouse_id:
                          type: integer
                        pricing_tier_id:
                          type: string
                          nullable: true
                        product_filters:
                          type: array
                        sales_filters:
                          type: array
                        demand_modifiers:
                          type: array
                        schedules_count:
                          type: integer
                        created_at:
                          type: string
                        updated_at:
                          type: string
                example:
                  data:
                  - id: 1
                    name: Weekly Sales History — Main Warehouse
                    description: Standard 90-day sales history forecast for our primary
                      warehouse.
                    supplier_ids:
                    - 5
                    - 12
                    forecast_type: sales_history
                    target_quantity: null
                    use_min_stock_level_as_target: false
                    sales_history_days: 90
                    sales_start_date: null
                    sales_end_date: null
                    target_stock_days: 30
                    use_leadtime: true
                    use_measured_lead_time: false
                    use_moq: true
                    enforce_minimum_order_value: false
                    enforce_minimum_order_quantity: false
                    use_case_pack: false
                    case_pack_rounding: null
                    ignore_min_stock_level: false
                    rounding_method: round_half_up
                    destination_warehouse_id: 1
                    pricing_tier_id: null
                    product_filters: []
                    sales_filters: []
                    demand_modifiers: []
                    schedules_count: 2
                    created_at: '2024-01-15T10:30:00Z'
                    updated_at: '2024-01-15T10:30:00Z'
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-inventory-forecasting-configurations
    post:
      tags:
      - Inventory
      summary: Create Forecast Configuration
      description: 'Creates a new forecast configuration.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Required fields:**

        - `name` (string, max 255, unique among non-deleted configurations)

        - `supplier_ids` (array of integers, min 1, must exist in suppliers table)

        - `forecast_type` (enum: `with_sales_history`, `target_stock_level`, `fill_backorders`)

        - `target_stock_days` (integer 0-365) — required for `with_sales_history`.
        Optional for `target_stock_level` (allows 0 when `use_min_stock_level_as_target`
        is true) and `fill_backorders` (ignored)


        **Optional fields:**

        - `description` (string, max 1000)

        - `target_quantity` (integer, min 0) — fixed target quantity used by `target_stock_level`
        forecast type

        - `use_min_stock_level_as_target` (boolean) — when true, `target_stock_level`
        forecasts use each product''s minimum stock level as the target instead of
        a fixed `target_quantity`. Persisted on both create and update.

        - `sales_history_days` (integer 1-365) — used by `with_sales_history` forecast
        type

        - `sales_start_date` / `sales_end_date` (Y-m-d) — alternative date range for
        sales history

        - `use_leadtime` (boolean)

        - `use_moq` (boolean)

        - `enforce_minimum_order_value` (boolean) — enforces supplier minimum order
        value when generating POs

        - `enforce_minimum_order_quantity` (boolean) — enforces supplier minimum order
        quantity when generating POs

        - `use_case_pack` (boolean) — round order quantities to supplier case-pack
        multiples

        - `case_pack_rounding` (enum: `always_round_up`, `always_round_down`, `round_nearest`)
        — how to round to the case-pack multiple

        - `ignore_min_stock_level` (boolean) — skip the per-product minimum stock
        level constraint when computing demand

        - `rounding_method` (enum: `round_half_up`, `round_half_down`, `always_round_up`,
        `always_round_down`, `no_rounding`)

        - `destination_warehouse_id` (integer, must exist in warehouses table)

        - `pricing_tier_id` (integer, must exist in supplier_pricing_tiers table)

        - `product_filters` (array) — filter criteria applied to candidate products

        - `sales_filters` (array) — filter criteria applied to sales history

        - `demand_modifiers` (array) — adjustments to projected demand


        Authentication: Requires Bearer token.


        **Baseline decomposition fields (persist onto the saved configuration and
        drive scheduled runs):**

        - `baseline_method` (enum: `flat` default, `recency_weighted`, `damped_trend`)
        — how the daily velocity baseline is derived from sales history.

        - `trend_damping_factor` (number 0..1, default 0.85) — damping factor phi
        for `damped_trend`; lower = more damping.

        - `trend_max_growth_pct` (number >= 0, default 100) — caps how far the trend
        may lift the baseline above the flat mean (100 = may at most double it). When
        the cap binds a line reports `trend_capped: true`.

        - `trend_half_life_days` (integer >= 1, nullable, default 21) — reserved tuning
        for `recency_weighted`.

        - `exclude_detected_anomalies` (boolean, default false) — when true, days
        resolved as excluded or smoothed anomalies are dropped/replaced before the
        baseline is computed, de-contaminating promo spikes and stockout gaps.


        These persist onto the configuration, so a schedule attached to it re-applies
        the same trend and anomaly-cleansing settings on every run. Baseline settings
        are ignored for `fill_backorders`.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                description:
                  type: string
                supplier_ids:
                  type: array
                  items:
                    type: integer
                forecast_type:
                  type: string
                target_quantity:
                  type: string
                  nullable: true
                use_min_stock_level_as_target:
                  type: boolean
                sales_history_days:
                  type: string
                  nullable: true
                sales_start_date:
                  type: string
                  nullable: true
                sales_end_date:
                  type: string
                  nullable: true
                target_stock_days:
                  type: integer
                use_leadtime:
                  type: boolean
                use_measured_lead_time:
                  type: boolean
                use_moq:
                  type: boolean
                enforce_minimum_order_value:
                  type: boolean
                enforce_minimum_order_quantity:
                  type: boolean
                use_case_pack:
                  type: boolean
                case_pack_rounding:
                  type: string
                ignore_min_stock_level:
                  type: boolean
                rounding_method:
                  type: string
                destination_warehouse_id:
                  type: integer
                pricing_tier_id:
                  type: string
                  nullable: true
                product_filters:
                  type: array
                sales_filters:
                  type: array
                demand_modifiers:
                  type: array
                baseline_method:
                  type: string
                trend_damping_factor:
                  type: number
                trend_max_growth_pct:
                  type: integer
                trend_half_life_days:
                  type: integer
                exclude_detected_anomalies:
                  type: boolean
              example:
                name: Min Stock Replenishment — Main Warehouse
                description: Target stock level forecast using each product's minimum
                  stock level as the target quantity.
                supplier_ids:
                - 5
                - 12
                forecast_type: target_stock_level
                target_quantity: null
                use_min_stock_level_as_target: true
                sales_history_days: null
                sales_start_date: null
                sales_end_date: null
                target_stock_days: 0
                use_leadtime: true
                use_measured_lead_time: false
                use_moq: true
                enforce_minimum_order_value: false
                enforce_minimum_order_quantity: false
                use_case_pack: true
                case_pack_rounding: always_round_up
                ignore_min_stock_level: false
                rounding_method: always_round_up
                destination_warehouse_id: 1
                pricing_tier_id: null
                product_filters: []
                sales_filters: []
                demand_modifiers: []
                baseline_method: damped_trend
                trend_damping_factor: 0.85
                trend_max_growth_pct: 100
                trend_half_life_days: 21
                exclude_detected_anomalies: true
      parameters: []
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      description:
                        type: string
                      supplier_ids:
                        type: array
                        items:
                          type: integer
                      forecast_type:
                        type: string
                      target_quantity:
                        type: string
                        nullable: true
                      use_min_stock_level_as_target:
                        type: boolean
                      sales_history_days:
                        type: integer
                      sales_start_date:
                        type: string
                        nullable: true
                      sales_end_date:
                        type: string
                        nullable: true
                      target_stock_days:
                        type: integer
                      use_leadtime:
                        type: boolean
                      use_measured_lead_time:
                        type: boolean
                      use_moq:
                        type: boolean
                      enforce_minimum_order_value:
                        type: boolean
                      enforce_minimum_order_quantity:
                        type: boolean
                      use_case_pack:
                        type: boolean
                      case_pack_rounding:
                        type: string
                        nullable: true
                      ignore_min_stock_level:
                        type: boolean
                      rounding_method:
                        type: string
                      destination_warehouse_id:
                        type: integer
                      pricing_tier_id:
                        type: string
                        nullable: true
                      product_filters:
                        type: array
                      sales_filters:
                        type: array
                      demand_modifiers:
                        type: array
                      created_by:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 42
                    name: Weekly Sales History — Main Warehouse
                    description: Standard 90-day sales history forecast for our primary
                      warehouse.
                    supplier_ids:
                    - 5
                    - 12
                    forecast_type: sales_history
                    target_quantity: null
                    use_min_stock_level_as_target: false
                    sales_history_days: 90
                    sales_start_date: null
                    sales_end_date: null
                    target_stock_days: 30
                    use_leadtime: true
                    use_measured_lead_time: false
                    use_moq: true
                    enforce_minimum_order_value: false
                    enforce_minimum_order_quantity: false
                    use_case_pack: false
                    case_pack_rounding: null
                    ignore_min_stock_level: false
                    rounding_method: round_half_up
                    destination_warehouse_id: 1
                    pricing_tier_id: null
                    product_filters: []
                    sales_filters: []
                    demand_modifiers: []
                    created_by:
                      id: 7
                      name: Jane Doe
                    created_at: '2024-01-15T10:30:00Z'
                    updated_at: '2024-01-15T10:30:00Z'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      name:
                        type: array
                        items:
                          type: string
                      supplier_ids:
                        type: array
                        items:
                          type: string
                      forecast_type:
                        type: array
                        items:
                          type: string
                example:
                  message: The name field is required.
                  errors:
                    name:
                    - A configuration name is required.
                    supplier_ids:
                    - At least one supplier must be selected.
                    forecast_type:
                    - A forecast type must be selected.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-inventory-forecasting-configurations
  /api/inventory-forecasting/configurations/paginated:
    get:
      tags:
      - Inventory
      summary: List Forecast Configurations
      description: 'Returns paginated forecast configurations.

        Authentication: Requires Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        description: Page number. Defaults to 1.
        example: '1'
      - name: per_page
        in: query
        schema:
          type: integer
        description: Items per page. Defaults to 10.
        example: '10'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        description:
                          type: string
                        supplier_ids:
                          type: array
                          items:
                            type: integer
                        forecast_type:
                          type: string
                        target_quantity:
                          type: string
                          nullable: true
                        use_min_stock_level_as_target:
                          type: boolean
                        sales_history_days:
                          type: integer
                        sales_start_date:
                          type: string
                          nullable: true
                        sales_end_date:
                          type: string
                          nullable: true
                        target_stock_days:
                          type: integer
                        use_leadtime:
                          type: boolean
                        use_measured_lead_time:
                          type: boolean
                        use_moq:
                          type: boolean
                        enforce_minimum_order_value:
                          type: boolean
                        enforce_minimum_order_quantity:
                          type: boolean
                        use_case_pack:
                          type: boolean
                        case_pack_rounding:
                          type: string
                          nullable: true
                        ignore_min_stock_level:
                          type: boolean
                        rounding_method:
                          type: string
                        destination_warehouse_id:
                          type: integer
                        pricing_tier_id:
                          type: string
                          nullable: true
                        product_filters:
                          type: array
                        sales_filters:
                          type: array
                        demand_modifiers:
                          type: array
                        schedules_count:
                          type: integer
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - id: 1
                    name: Weekly Sales History — Main Warehouse
                    description: Standard 90-day sales history forecast.
                    supplier_ids:
                    - 5
                    - 12
                    forecast_type: sales_history
                    target_quantity: null
                    use_min_stock_level_as_target: false
                    sales_history_days: 90
                    sales_start_date: null
                    sales_end_date: null
                    target_stock_days: 30
                    use_leadtime: true
                    use_measured_lead_time: false
                    use_moq: true
                    enforce_minimum_order_value: false
                    enforce_minimum_order_quantity: false
                    use_case_pack: false
                    case_pack_rounding: null
                    ignore_min_stock_level: false
                    rounding_method: round_half_up
                    destination_warehouse_id: 1
                    pricing_tier_id: null
                    product_filters: []
                    sales_filters: []
                    demand_modifiers: []
                    schedules_count: 2
                    created_at: '2024-01-15T10:30:00Z'
                    updated_at: '2024-01-15T10:30:00Z'
                  current_page: 1
                  last_page: 3
                  per_page: 10
                  total: 25
                  from: 1
                  to: 10
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-inventory-forecasting-configurations-paginated
  /api/inventory-forecasting/configurations/{configuration}:
    get:
      tags:
      - Inventory
      summary: Get Forecast Configuration
      description: 'Returns a single forecast configuration with `created_by`, `updated_by`,
        and `pricing_tier` relationships eager-loaded, plus the `schedules_count`
        of automation schedules referencing it.

        Authentication: Requires Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: configuration
        in: path
        schema:
          type: integer
        required: true
        description: Forecast configuration ID.
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      description:
                        type: string
                      supplier_ids:
                        type: array
                        items:
                          type: integer
                      forecast_type:
                        type: string
                      target_quantity:
                        type: string
                        nullable: true
                      use_min_stock_level_as_target:
                        type: boolean
                      sales_history_days:
                        type: integer
                      sales_start_date:
                        type: string
                        nullable: true
                      sales_end_date:
                        type: string
                        nullable: true
                      target_stock_days:
                        type: integer
                      use_leadtime:
                        type: boolean
                      use_measured_lead_time:
                        type: boolean
                      use_moq:
                        type: boolean
                      enforce_minimum_order_value:
                        type: boolean
                      enforce_minimum_order_quantity:
                        type: boolean
                      use_case_pack:
                        type: boolean
                      case_pack_rounding:
                        type: string
                        nullable: true
                      ignore_min_stock_level:
                        type: boolean
                      rounding_method:
                        type: string
                      destination_warehouse_id:
                        type: integer
                      pricing_tier_id:
                        type: string
                        nullable: true
                      product_filters:
                        type: array
                      sales_filters:
                        type: array
                      demand_modifiers:
                        type: array
                      created_by:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      updated_by:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      schedules_count:
                        type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 1
                    name: Weekly Sales History — Main Warehouse
                    description: Standard 90-day sales history forecast.
                    supplier_ids:
                    - 5
                    - 12
                    forecast_type: sales_history
                    target_quantity: null
                    use_min_stock_level_as_target: false
                    sales_history_days: 90
                    sales_start_date: null
                    sales_end_date: null
                    target_stock_days: 30
                    use_leadtime: true
                    use_measured_lead_time: false
                    use_moq: true
                    enforce_minimum_order_value: true
                    enforce_minimum_order_quantity: true
                    use_case_pack: false
                    case_pack_rounding: null
                    ignore_min_stock_level: false
                    rounding_method: round_half_up
                    destination_warehouse_id: 1
                    pricing_tier_id: null
                    product_filters: []
                    sales_filters: []
                    demand_modifiers: []
                    created_by:
                      id: 7
                      name: Jane Doe
                    updated_by:
                      id: 7
                      name: Jane Doe
                    schedules_count: 2
                    created_at: '2024-01-15T10:30:00Z'
                    updated_at: '2024-01-15T10:30:00Z'
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No query results for model [App\Models\ForecastConfiguration]
                    999
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-inventory-forecasting-configurations-configuration
    put:
      tags:
      - Inventory
      summary: Update Forecast Configuration
      description: 'Updates an existing forecast configuration. All fields use `sometimes`
        validation — only send the fields you want to change.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        The controller merges the incoming payload over the existing configuration
        data via `ForecastConfigurationData::fromModel($configuration)`, so omitted
        fields retain their current values. **Any field you want to change must be
        present in the validation rules — otherwise `validated()` strips it and the
        merge silently reverts it to the stored value.**


        Accepts the same fields as Create, including `use_min_stock_level_as_target`,
        `use_case_pack`, `case_pack_rounding`, and `ignore_min_stock_level`. The `name`
        uniqueness rule excludes the current record (so unchanged names pass validation).


        Authentication: Requires Bearer token.


        **Baseline decomposition fields** (`baseline_method`, `trend_damping_factor`,
        `trend_max_growth_pct`, `trend_half_life_days`, `exclude_detected_anomalies`)
        persist onto the configuration and can be changed here; the new values apply
        to the next on-demand build and to any schedule attached to this configuration.
        `baseline_method` is `flat` (default), `recency_weighted`, or `damped_trend`;
        `trend_damping_factor` (0..1, default 0.85) is the damping factor phi (lower
        = more damping); `trend_max_growth_pct` (>= 0, default 100) caps the trend
        lift above the flat mean; `trend_half_life_days` (>= 1, nullable, default
        21) tunes `recency_weighted`; `exclude_detected_anomalies` (default false)
        drops/replaces resolved anomaly days before the baseline is computed. Baseline
        settings are ignored for `fill_backorders`.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                forecast_type:
                  type: string
                use_min_stock_level_as_target:
                  type: boolean
                use_case_pack:
                  type: boolean
                case_pack_rounding:
                  type: string
                ignore_min_stock_level:
                  type: boolean
                baseline_method:
                  type: string
                trend_damping_factor:
                  type: number
                trend_max_growth_pct:
                  type: integer
                trend_half_life_days:
                  type: integer
                exclude_detected_anomalies:
                  type: boolean
              example:
                name: Min Stock Replenishment — Main Warehouse (v2)
                forecast_type: target_stock_level
                use_min_stock_level_as_target: true
                use_case_pack: true
                case_pack_rounding: always_round_up
                ignore_min_stock_level: false
                baseline_method: damped_trend
                trend_damping_factor: 0.8
                trend_max_growth_pct: 75
                trend_half_life_days: 28
                exclude_detected_anomalies: true
      parameters:
      - name: configuration
        in: path
        schema:
          type: integer
        required: true
        description: Forecast configuration ID.
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      description:
                        type: string
                      supplier_ids:
                        type: array
                        items:
                          type: integer
                      forecast_type:
                        type: string
                      target_quantity:
                        type: string
                        nullable: true
                      use_min_stock_level_as_target:
                        type: boolean
                      sales_history_days:
                        type: integer
                      sales_start_date:
                        type: string
                        nullable: true
                      sales_end_date:
                        type: string
                        nullable: true
                      target_stock_days:
                        type: integer
                      use_leadtime:
                        type: boolean
                      use_measured_lead_time:
                        type: boolean
                      use_moq:
                        type: boolean
                      enforce_minimum_order_value:
                        type: boolean
                      enforce_minimum_order_quantity:
                        type: boolean
                      use_case_pack:
                        type: boolean
                      case_pack_rounding:
                        type: string
                        nullable: true
                      ignore_min_stock_level:
                        type: boolean
                      rounding_method:
                        type: string
                      destination_warehouse_id:
                        type: integer
                      pricing_tier_id:
                        type: string
                        nullable: true
                      product_filters:
                        type: array
                      sales_filters:
                        type: array
                      demand_modifiers:
                        type: array
                      created_by:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      updated_by:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 1
                    name: Weekly Sales History — Main Warehouse (v2)
                    description: Updated to enforce supplier minimums.
                    supplier_ids:
                    - 5
                    - 12
                    forecast_type: sales_history
                    target_quantity: null
                    use_min_stock_level_as_target: false
                    sales_history_days: 90
                    sales_start_date: null
                    sales_end_date: null
                    target_stock_days: 45
                    use_leadtime: true
                    use_measured_lead_time: false
                    use_moq: true
                    enforce_minimum_order_value: true
                    enforce_minimum_order_quantity: true
                    use_case_pack: false
                    case_pack_rounding: null
                    ignore_min_stock_level: false
                    rounding_method: round_half_up
                    destination_warehouse_id: 1
                    pricing_tier_id: null
                    product_filters: []
                    sales_filters: []
                    demand_modifiers: []
                    created_by:
                      id: 7
                      name: Jane Doe
                    updated_by:
                      id: 7
                      name: Jane Doe
                    created_at: '2024-01-15T10:30:00Z'
                    updated_at: '2024-01-20T14:22:00Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-inventory-forecasting-configurations-configuration
    delete:
      tags:
      - Inventory
      summary: Delete Forecast Configuration
      description: 'Soft-deletes a forecast configuration.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        If the configuration is in use by any automation schedule, returns 422 unless
        `force=true` is passed.


        Authentication: Requires Bearer token.'
      parameters:
      - name: configuration
        in: path
        schema:
          type: integer
        required: true
        description: Forecast configuration ID.
        example: '1'
      responses:
        '204':
          description: No Content
          content:
            text/plain:
              schema:
                type: string
                example: ''
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                  message:
                    type: string
                example:
                  error: Cannot delete configuration
                  message: Configuration is used by 2 schedule(s). Pass force=true
                    to delete anyway.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-inventory-forecasting-configurations-configuration
  /api/inventory-forecasting/configurations/{configuration}/duplicate:
    post:
      tags:
      - Inventory
      summary: Duplicate Forecast Configuration
      description: 'Creates a copy of an existing forecast configuration.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Optional body field:**

        - `name` (string, max 255) — name for the new copy. If omitted, defaults to
        `"<Original Name> (Copy)"`.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
              example:
                name: Weekly Sales History — Copy
      parameters:
      - name: configuration
        in: path
        schema:
          type: integer
        required: true
        description: Forecast configuration ID to duplicate.
        example: '1'
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      description:
                        type: string
                      supplier_ids:
                        type: array
                        items:
                          type: integer
                      forecast_type:
                        type: string
                      target_quantity:
                        type: string
                        nullable: true
                      use_min_stock_level_as_target:
                        type: boolean
                      sales_history_days:
                        type: integer
                      sales_start_date:
                        type: string
                        nullable: true
                      sales_end_date:
                        type: string
                        nullable: true
                      target_stock_days:
                        type: integer
                      use_leadtime:
                        type: boolean
                      use_measured_lead_time:
                        type: boolean
                      use_moq:
                        type: boolean
                      enforce_minimum_order_value:
                        type: boolean
                      enforce_minimum_order_quantity:
                        type: boolean
                      use_case_pack:
                        type: boolean
                      case_pack_rounding:
                        type: string
                        nullable: true
                      ignore_min_stock_level:
                        type: boolean
                      rounding_method:
                        type: string
                      destination_warehouse_id:
                        type: integer
                      pricing_tier_id:
                        type: string
                        nullable: true
                      product_filters:
                        type: array
                      sales_filters:
                        type: array
                      demand_modifiers:
                        type: array
                      created_by:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 43
                    name: Weekly Sales History — Copy
                    description: Standard 90-day sales history forecast.
                    supplier_ids:
                    - 5
                    - 12
                    forecast_type: sales_history
                    target_quantity: null
                    use_min_stock_level_as_target: false
                    sales_history_days: 90
                    sales_start_date: null
                    sales_end_date: null
                    target_stock_days: 30
                    use_leadtime: true
                    use_measured_lead_time: false
                    use_moq: true
                    enforce_minimum_order_value: false
                    enforce_minimum_order_quantity: false
                    use_case_pack: false
                    case_pack_rounding: null
                    ignore_min_stock_level: false
                    rounding_method: round_half_up
                    destination_warehouse_id: 1
                    pricing_tier_id: null
                    product_filters: []
                    sales_filters: []
                    demand_modifiers: []
                    created_by:
                      id: 7
                      name: Jane Doe
                    created_at: '2024-01-20T14:22:00Z'
                    updated_at: '2024-01-20T14:22:00Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-inventory-forecasting-configurations-configuration-duplicate
  /api/inventory-forecasting/configurations/{configuration}/usage:
    get:
      tags:
      - Inventory
      summary: Check Forecast Configuration Usage
      description: 'Returns whether the configuration is referenced by any automation
        schedules and the count.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Use this before showing a delete confirmation in the UI.


        Authentication: Requires Bearer token.'
      parameters:
      - name: configuration
        in: path
        schema:
          type: integer
        required: true
        description: Forecast configuration ID.
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 In Use
                  value:
                    data:
                      in_use: true
                      schedules_count: 2
                example-1:
                  summary: 200 Not In Use
                  value:
                    data:
                      in_use: false
                      schedules_count: 0
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-inventory-forecasting-configurations-configuration-usage
  /api/inventory-forecasting/configurations/default:
    get:
      tags:
      - Inventory Intelligence
      summary: Get My Default Configuration
      description: 'Get the current user''s default forecast configuration, if one
        has been set.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        The demand-planning UI calls this on initial load and pre-applies the returned
        configuration.


        Returns `{ "data": null }` (200) when the user has no default set.


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 With Default
                  value:
                    data:
                      id: 3
                      name: Weekly Replenishment - Supplier A
                      forecast_type: sales_history
                      supplier_ids:
                      - 1
                      is_default: true
                      created_at: '2024-10-15T10:00:00+00:00'
                      updated_at: '2024-10-15T10:00:00+00:00'
                example-1:
                  summary: 200 No Default Set
                  value:
                    data: null
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-inventory-forecasting-configurations-default
    delete:
      tags:
      - Inventory Intelligence
      summary: Clear My Default Configuration
      description: 'Unset the current user''s default configuration. Subsequent visits
        to demand planning load with a blank slate.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Returns 204 No Content on success. Safe to call when no default is set.


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '204':
          description: No Content
          content:
            text/plain:
              schema:
                type: string
                example: ''
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: delete-api-inventory-forecasting-configurations-default
  /api/inventory-forecasting/configurations/{configuration}/set-default:
    post:
      tags:
      - Inventory Intelligence
      summary: Set as My Default Configuration
      description: 'Mark this configuration as the current user''s default. The default
        is loaded automatically in the demand-planning UI on page load.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        At most one default per user. Calling this on a different configuration replaces
        the previous default (no need to clear first).


        The response''s `is_default` flag will reflect the new state.


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: configuration
        in: path
        schema:
          type: integer
        required: true
        description: Configuration ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      forecast_type:
                        type: string
                      supplier_ids:
                        type: array
                        items:
                          type: integer
                      is_default:
                        type: boolean
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 3
                    name: Weekly Replenishment - Supplier A
                    forecast_type: sales_history
                    supplier_ids:
                    - 1
                    is_default: true
                    created_at: '2024-10-15T10:00:00+00:00'
                    updated_at: '2024-10-15T10:00:00+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-inventory-forecasting-configurations-configuration-set-default
  /api/inventory-forecasting/schedules:
    get:
      tags:
      - Inventory Intelligence
      summary: List Schedules
      description: 'List all forecast schedules (non-paginated).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: is_enabled
        in: query
        schema:
          type: string
        description: Optional. Filter by enabled status (1 or 0).
      - name: supplier_id
        in: query
        schema:
          type: string
        description: Optional. Filter by supplier ID.
      - name: forecast_type
        in: query
        schema:
          type: string
        description: Optional. Filter by forecast type.
      - name: search
        in: query
        schema:
          type: string
        description: Optional. Search by name.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        is_enabled:
                          type: boolean
                        schedule_time:
                          type: string
                        days_of_week:
                          type: array
                          items:
                            type: integer
                        timezone:
                          type: string
                        forecast_configuration_id:
                          type: integer
                        alert_channels:
                          type: array
                          items:
                            type: string
                        alert_email_recipients:
                          type: array
                          items:
                            type: string
                        slack_webhook_url:
                          type: string
                          nullable: true
                        auto_create_po:
                          type: boolean
                        po_status:
                          type: string
                        separate_po_by_brand:
                          type: boolean
                        auto_receive_po:
                          type: boolean
                        misfire_policy:
                          type: string
                        misfire_policy_label:
                          type: string
                        starting_deadline_minutes:
                          type: integer
                        last_run_at:
                          type: string
                        next_run_at:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                example:
                  data:
                  - id: 1
                    name: Weekly Monday Run
                    is_enabled: true
                    schedule_time: 06:00:00
                    days_of_week:
                    - 1
                    timezone: America/New_York
                    forecast_configuration_id: 1
                    alert_channels:
                    - email
                    alert_email_recipients:
                    - ops@company.com
                    slack_webhook_url: null
                    auto_create_po: true
                    po_status: approved
                    separate_po_by_brand: false
                    auto_receive_po: false
                    misfire_policy: run_once
                    misfire_policy_label: Run Once
                    starting_deadline_minutes: 60
                    last_run_at: '2024-10-14T06:05:00+00:00'
                    next_run_at: '2024-10-21T10:00:00+00:00'
                    created_at: '2024-01-15T08:00:00+00:00'
                    updated_at: '2024-06-20T14:30:00+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-inventory-forecasting-schedules
    post:
      tags:
      - Inventory Intelligence
      summary: Create Schedule
      description: 'Create a new forecast schedule.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        schedule_time: HH:MM:SS format.


        days_of_week: array of integers 0-6 (0=Sunday, 1=Monday, ..., 6=Saturday).


        alert_channels: array of ''email'' and/or ''slack''.


        PO settings:

        - auto_create_po (boolean): create POs automatically from the forecast results.

        - po_status: draft, approved, or approved_sent.

        - separate_po_by_brand (boolean): split POs per brand instead of one per supplier.

        - auto_receive_po (boolean): automatically mark the created PO as received
        once it has been created and approved. Ignored when po_status is draft (a
        draft PO cannot be received).


        Returns 201.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                is_enabled:
                  type: boolean
                schedule_time:
                  type: string
                days_of_week:
                  type: array
                  items:
                    type: integer
                timezone:
                  type: string
                forecast_configuration_id:
                  type: integer
                alert_channels:
                  type: array
                  items:
                    type: string
                alert_email_recipients:
                  type: array
                  items:
                    type: string
                slack_webhook_url:
                  type: string
                  nullable: true
                auto_create_po:
                  type: boolean
                po_status:
                  type: string
                separate_po_by_brand:
                  type: boolean
                auto_receive_po:
                  type: boolean
              example:
                name: Weekly Monday Run
                is_enabled: true
                schedule_time: 06:00:00
                days_of_week:
                - 1
                timezone: America/New_York
                forecast_configuration_id: 1
                alert_channels:
                - email
                alert_email_recipients:
                - ops@company.com
                slack_webhook_url: null
                auto_create_po: true
                po_status: approved
                separate_po_by_brand: false
                auto_receive_po: false
      parameters: []
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      is_enabled:
                        type: boolean
                      schedule_time:
                        type: string
                      days_of_week:
                        type: array
                        items:
                          type: integer
                      timezone:
                        type: string
                      auto_create_po:
                        type: boolean
                      po_status:
                        type: string
                      separate_po_by_brand:
                        type: boolean
                      auto_receive_po:
                        type: boolean
                      next_run_at:
                        type: string
                      created_at:
                        type: string
                example:
                  data:
                    id: 3
                    name: Weekly Monday Run
                    is_enabled: true
                    schedule_time: 06:00:00
                    days_of_week:
                    - 1
                    timezone: America/New_York
                    auto_create_po: true
                    po_status: approved
                    separate_po_by_brand: false
                    auto_receive_po: false
                    next_run_at: '2024-10-21T10:00:00+00:00'
                    created_at: '2024-10-15T09:00:00+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-inventory-forecasting-schedules
  /api/inventory-forecasting/schedules/{schedule}:
    get:
      tags:
      - Inventory Intelligence
      summary: Get Schedule
      description: 'Get a single forecast schedule with full details.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Loads configuration, createdByUser, updatedByUser, latestRun relationships.'
      parameters:
      - name: schedule
        in: path
        schema:
          type: integer
        required: true
        description: Schedule ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      is_enabled:
                        type: boolean
                      schedule_time:
                        type: string
                      days_of_week:
                        type: array
                        items:
                          type: integer
                      timezone:
                        type: string
                      forecast_configuration_id:
                        type: integer
                      configuration:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      auto_create_po:
                        type: boolean
                      po_status:
                        type: string
                      separate_po_by_brand:
                        type: boolean
                      auto_receive_po:
                        type: boolean
                      last_run_at:
                        type: string
                      next_run_at:
                        type: string
                      latest_run:
                        type: object
                        properties:
                          id:
                            type: integer
                          status:
                            type: string
                          started_at:
                            type: string
                          completed_at:
                            type: string
                example:
                  data:
                    id: 1
                    name: Weekly Monday Run
                    is_enabled: true
                    schedule_time: 06:00:00
                    days_of_week:
                    - 1
                    timezone: America/New_York
                    forecast_configuration_id: 1
                    configuration:
                      id: 1
                      name: Weekly Replenishment - Supplier A
                    auto_create_po: true
                    po_status: approved
                    separate_po_by_brand: false
                    auto_receive_po: false
                    last_run_at: '2024-10-14T06:05:00+00:00'
                    next_run_at: '2024-10-21T10:00:00+00:00'
                    latest_run:
                      id: 50
                      status: completed
                      started_at: '2024-10-14T06:00:12+00:00'
                      completed_at: '2024-10-14T06:05:44+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-inventory-forecasting-schedules-schedule
    put:
      tags:
      - Inventory Intelligence
      summary: Update Schedule
      description: 'Update a forecast schedule. All fields are optional; merges with
        existing data.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        PO settings (all optional):

        - auto_create_po (boolean), po_status (draft|approved|approved_sent), separate_po_by_brand
        (boolean), auto_receive_po (boolean). auto_receive_po is ignored when po_status
        is draft.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                schedule_time:
                  type: string
                days_of_week:
                  type: array
                  items:
                    type: integer
                auto_create_po:
                  type: boolean
                po_status:
                  type: string
                auto_receive_po:
                  type: boolean
              example:
                schedule_time: 07:00:00
                days_of_week:
                - 1
                - 4
                auto_create_po: true
                po_status: approved
                auto_receive_po: true
      parameters:
      - name: schedule
        in: path
        schema:
          type: integer
        required: true
        description: Schedule ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      schedule_time:
                        type: string
                      days_of_week:
                        type: array
                        items:
                          type: integer
                      updated_at:
                        type: string
                example:
                  data:
                    id: 1
                    name: Weekly Monday Run
                    schedule_time: 07:00:00
                    days_of_week:
                    - 1
                    - 4
                    updated_at: '2024-10-16T11:00:00+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-inventory-forecasting-schedules-schedule
    delete:
      tags:
      - Inventory Intelligence
      summary: Delete Schedule
      description: 'Delete a forecast schedule.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Returns 204 on success.'
      parameters:
      - name: schedule
        in: path
        schema:
          type: integer
        required: true
        description: Schedule ID
        example: '1'
      responses:
        '204':
          description: No Content
          content:
            text/plain:
              schema:
                type: string
                example: ''
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-inventory-forecasting-schedules-schedule
  /api/inventory-forecasting/schedules/{schedule}/toggle:
    post:
      tags:
      - Inventory Intelligence
      summary: Toggle Schedule
      description: 'Toggle a schedule''s enabled/disabled status.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: schedule
        in: path
        schema:
          type: integer
        required: true
        description: Schedule ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      is_enabled:
                        type: boolean
                      updated_at:
                        type: string
                example:
                  data:
                    id: 1
                    name: Weekly Monday Run
                    is_enabled: false
                    updated_at: '2024-10-16T11:00:00+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-inventory-forecasting-schedules-schedule-toggle
  /api/inventory-forecasting/schedules/{schedule}/run:
    post:
      tags:
      - Inventory Intelligence
      summary: Run Schedule Now
      description: 'Manually trigger a forecast schedule immediately.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Returns 500 if execution fails.'
      requestBody:
        content: {}
      parameters:
      - name: schedule
        in: path
        schema:
          type: integer
        required: true
        description: Schedule ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      forecast_schedule_id:
                        type: integer
                      status:
                        type: string
                      run_type:
                        type: string
                      started_at:
                        type: string
                      completed_at:
                        type: string
                      duration_seconds:
                        type: integer
                      results_summary:
                        type: object
                        properties:
                          suppliers_processed:
                            type: integer
                          skus_to_order:
                            type: integer
                          purchase_orders_created:
                            type: integer
                example:
                  data:
                    id: 55
                    forecast_schedule_id: 1
                    status: completed
                    run_type: Manual
                    started_at: '2024-10-15T09:00:00+00:00'
                    completed_at: '2024-10-15T09:05:00+00:00'
                    duration_seconds: 300
                    results_summary:
                      suppliers_processed: 1
                      skus_to_order: 18
                      purchase_orders_created: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-inventory-forecasting-schedules-schedule-run
  /api/inventory-forecasting/schedules/{schedule}/runs:
    get:
      tags:
      - Inventory Intelligence
      summary: Get Schedule Runs
      description: 'Get paginated run history for a specific schedule.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: schedule
        in: path
        schema:
          type: integer
        required: true
        description: Schedule ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        status:
                          type: string
                        run_type:
                          type: string
                        started_at:
                          type: string
                        completed_at:
                          type: string
                        duration_seconds:
                          type: integer
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 55
                    status: completed
                    run_type: Scheduled
                    started_at: '2024-10-14T06:00:12+00:00'
                    completed_at: '2024-10-14T06:05:44+00:00'
                    duration_seconds: 332
                  current_page: 1
                  last_page: 2
                  per_page: 15
                  total: 22
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-inventory-forecasting-schedules-schedule-runs
  /api/inventory-forecasting/schedules/{schedule}/activity-log:
    get:
      tags:
      - Inventory Intelligence
      summary: Get Schedule Activity Log
      description: 'Get the Spatie activity log for a specific schedule showing all
        changes.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: per_page
        in: query
        schema:
          type: integer
        description: Optional. Items per page (default 25).
        example: '25'
      - name: schedule
        in: path
        schema:
          type: integer
        required: true
        description: Schedule ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        description:
                          type: string
                        event:
                          type: string
                        properties:
                          type: object
                          properties:
                            old:
                              type: object
                              properties:
                                is_enabled:
                                  type: boolean
                            attributes:
                              type: object
                              properties:
                                is_enabled:
                                  type: boolean
                        causer_name:
                          type: string
                        created_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 1001
                    description: updated
                    event: updated
                    properties:
                      old:
                        is_enabled: true
                      attributes:
                        is_enabled: false
                    causer_name: Jane Smith
                    created_at: '2024-10-15T09:00:00+00:00'
                  current_page: 1
                  last_page: 1
                  per_page: 25
                  total: 5
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-inventory-forecasting-schedules-schedule-activity-log
  /api/inventory-forecasting/schedules/limits:
    get:
      tags:
      - Inventory Intelligence
      summary: Get Schedule Limits
      description: 'Get supplier run limits status. Shows how many runs are scheduled
        for each supplier on a given date.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: supplier_ids[]
        in: query
        schema:
          type: integer
        description: Required. Array of supplier IDs to check limits for.
        example: '1'
      - name: date
        in: query
        schema:
          type: string
        description: Optional. Date to check limits for (defaults to today).
        example: '2024-10-15'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        supplier_id:
                          type: integer
                        supplier_name:
                          type: string
                        runs_today:
                          type: integer
                        limit:
                          type: integer
                        can_run:
                          type: boolean
                example:
                  data:
                  - supplier_id: 1
                    supplier_name: Acme Supplier Co.
                    runs_today: 1
                    limit: 3
                    can_run: true
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-inventory-forecasting-schedules-limits
  /api/inventory-forecasting/schedules/statistics:
    get:
      tags:
      - Inventory Intelligence
      summary: Get Schedule Statistics
      description: 'Get aggregate statistics for all forecast schedules.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      total_schedules:
                        type: integer
                      enabled_schedules:
                        type: integer
                      total_runs_this_month:
                        type: integer
                      successful_runs:
                        type: integer
                      failed_runs:
                        type: integer
                example:
                  data:
                    total_schedules: 5
                    enabled_schedules: 4
                    total_runs_this_month: 16
                    successful_runs: 15
                    failed_runs: 1
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-inventory-forecasting-schedules-statistics
  /api/inventory-forecasting/schedules/timeline:
    get:
      tags:
      - Inventory Intelligence
      summary: Get Schedule Timeline
      description: 'Get upcoming schedule runs for a date range.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: start_date
        in: query
        schema:
          type: string
        description: Optional. Start date for timeline (defaults to today).
        example: '2024-10-15'
      - name: end_date
        in: query
        schema:
          type: string
        description: Optional. End date for timeline (defaults to today + 7 days).
        example: '2024-10-22'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        date:
                          type: string
                        schedules:
                          type: array
                          items:
                            type: object
                            properties:
                              id:
                                type: integer
                              name:
                                type: string
                              schedule_time:
                                type: string
                example:
                  data:
                  - date: '2024-10-21'
                    schedules:
                    - id: 1
                      name: Weekly Monday Run
                      schedule_time: 06:00:00
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-inventory-forecasting-schedules-timeline
  /api/inventory-forecasting/schedules/today:
    get:
      tags:
      - Inventory Intelligence
      summary: Get Today's Schedules
      description: 'Get schedules that run on the given day of the week.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: date
        in: query
        schema:
          type: string
        description: Optional. Date to get schedules for (defaults to today).
        example: '2024-10-15'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        is_enabled:
                          type: boolean
                        schedule_time:
                          type: string
                        next_run_at:
                          type: string
                example:
                  data:
                  - id: 1
                    name: Weekly Monday Run
                    is_enabled: true
                    schedule_time: 06:00:00
                    next_run_at: '2024-10-21T10:00:00+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-inventory-forecasting-schedules-today
  /api/inventory-forecasting/schedule-runs:
    get:
      tags:
      - Inventory Intelligence
      summary: List All Runs
      description: 'Get all forecast runs across all schedules (both manual and scheduled),
        paginated. Loads the schedule, triggering user, and linked purchase orders.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Text search uses filter[search] (matches run ID, schedule name, or user name).
        Advanced filtering uses filter_groups — a base64-encoded tree of AND/OR condition
        groups over: id, status, run_type (manual or scheduled), started_at, purge_at,
        created_at, updated_at. Sortable: id, started_at, status, run_type, purge_at
        (default -started_at, newest first).'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        forecast_schedule_id:
                          type: integer
                        user_id:
                          type: integer
                        is_manual_run:
                          type: boolean
                        is_scheduled_run:
                          type: boolean
                        run_type:
                          type: string
                        status:
                          type: string
                        started_at:
                          type: string
                        completed_at:
                          type: string
                        duration_seconds:
                          type: integer
                        duration_human:
                          type: string
                        results_summary:
                          type: object
                          properties:
                            suppliers_processed:
                              type: integer
                            skus_to_order:
                              type: integer
                            purchase_orders_created:
                              type: integer
                            total_value:
                              type: number
                        error_message:
                          type: string
                          nullable: true
                        purchase_order_ids:
                          type: array
                          items:
                            type: integer
                        has_purchase_orders:
                          type: boolean
                        schedule:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        user:
                          type: string
                          nullable: true
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 55
                    forecast_schedule_id: 1
                    user_id: 10
                    is_manual_run: false
                    is_scheduled_run: true
                    run_type: Scheduled
                    status: completed
                    started_at: '2024-10-14T06:00:12+00:00'
                    completed_at: '2024-10-14T06:05:44+00:00'
                    duration_seconds: 332
                    duration_human: 5m 32s
                    results_summary:
                      suppliers_processed: 1
                      skus_to_order: 18
                      purchase_orders_created: 1
                      total_value: 12500.0
                    error_message: null
                    purchase_order_ids:
                    - 500
                    has_purchase_orders: true
                    schedule:
                      id: 1
                      name: Weekly Monday Run
                    user: null
                  current_page: 1
                  last_page: 4
                  per_page: 15
                  total: 48
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-inventory-forecasting-schedule-runs
  /api/inventory-forecasting/schedule-runs/recent:
    get:
      tags:
      - Inventory Intelligence
      summary: Get Recent Runs
      description: 'Get recent runs (not paginated). Useful for dashboard widgets.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: limit
        in: query
        schema:
          type: integer
        description: Optional. Number of recent runs to return (default 5, max 20).
        example: '5'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        status:
                          type: string
                        run_type:
                          type: string
                        started_at:
                          type: string
                        completed_at:
                          type: string
                example:
                  data:
                  - id: 55
                    status: completed
                    run_type: Scheduled
                    started_at: '2024-10-14T06:00:12+00:00'
                    completed_at: '2024-10-14T06:05:44+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-inventory-forecasting-schedule-runs-recent
  /api/inventory-forecasting/schedule-runs/{runId}:
    get:
      tags:
      - Inventory Intelligence
      summary: Get Run Details
      description: 'Get full details for a single forecast run.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Loads schedule, user, supplierRuns, linkedPurchaseOrders.


        Returns 404 if run not found.'
      parameters:
      - name: runId
        in: path
        schema:
          type: integer
        required: true
        description: Run ID
        example: '55'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      forecast_schedule_id:
                        type: integer
                      status:
                        type: string
                      run_type:
                        type: string
                      started_at:
                        type: string
                      completed_at:
                        type: string
                      duration_seconds:
                        type: integer
                      results_summary:
                        type: object
                        properties:
                          purchase_orders_created:
                            type: integer
                      linked_purchase_orders:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            purchase_order_number:
                              type: string
                            supplier_name:
                              type: string
                            total_cost:
                              type: number
                            order_status:
                              type: string
                example:
                  data:
                    id: 55
                    forecast_schedule_id: 1
                    status: completed
                    run_type: Scheduled
                    started_at: '2024-10-14T06:00:12+00:00'
                    completed_at: '2024-10-14T06:05:44+00:00'
                    duration_seconds: 332
                    results_summary:
                      purchase_orders_created: 1
                    linked_purchase_orders:
                    - id: 500
                      purchase_order_number: PO-500
                      supplier_name: Acme Supplier Co.
                      total_cost: 12500.0
                      order_status: draft
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: Run not found
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-inventory-forecasting-schedule-runs-runid
  /api/inventory-forecasting/schedule-runs/manual:
    post:
      tags:
      - Inventory Intelligence
      summary: Create Manual Run
      description: 'Create and persist a manual (ad-hoc) forecast run record. Called
        when users run forecasts manually from the UI.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        configuration_snapshot: required — stores the forecast config used.


        results_summary: required — stores aggregate results.


        purchase_order_ids: optional — IDs of POs created from this run.


        Returns 201.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                configuration_snapshot:
                  type: object
                  properties:
                    supplier_ids:
                      type: array
                      items:
                        type: integer
                    forecast_type:
                      type: string
                    target_stock_days:
                      type: integer
                results_summary:
                  type: object
                  properties:
                    suppliers_processed:
                      type: integer
                    skus_to_order:
                      type: integer
                    purchase_orders_created:
                      type: integer
                    total_value:
                      type: integer
                purchase_order_ids:
                  type: array
              example:
                configuration_snapshot:
                  supplier_ids:
                  - 1
                  forecast_type: sales_history
                  target_stock_days: 30
                results_summary:
                  suppliers_processed: 1
                  skus_to_order: 18
                  purchase_orders_created: 0
                  total_value: 12500
                purchase_order_ids: []
      parameters: []
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      is_manual_run:
                        type: boolean
                      status:
                        type: string
                      run_type:
                        type: string
                      results_summary:
                        type: object
                        properties:
                          suppliers_processed:
                            type: integer
                          skus_to_order:
                            type: integer
                      created_at:
                        type: string
                example:
                  data:
                    id: 60
                    is_manual_run: true
                    status: completed
                    run_type: Manual
                    results_summary:
                      suppliers_processed: 1
                      skus_to_order: 18
                    created_at: '2024-10-15T09:00:00+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-inventory-forecasting-schedule-runs-manual
  /api/inventory-forecasting/schedule-runs/{runId}/link-purchase-orders:
    post:
      tags:
      - Inventory Intelligence
      summary: Link Purchase Orders to Run
      description: 'Link purchase orders to an existing manual forecast run. Can only
        be used for manual runs.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Returns 404 if run not found. Returns 400 if not a manual run.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                purchase_order_ids:
                  type: array
                  items:
                    type: integer
              example:
                purchase_order_ids:
                - 500
                - 501
      parameters:
      - name: runId
        in: path
        schema:
          type: integer
        required: true
        description: Run ID
        example: '60'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      purchase_order_ids:
                        type: array
                        items:
                          type: integer
                      has_purchase_orders:
                        type: boolean
                example:
                  data:
                    id: 60
                    purchase_order_ids:
                    - 500
                    - 501
                    has_purchase_orders: true
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-inventory-forecasting-schedule-runs-runid-link-purchase-orders
  /api/inventory-forecasting/schedule-runs/{runId}/rerun:
    post:
      tags:
      - Inventory Intelligence
      summary: Re-run Forecast from Previous Run
      description: 'Re-run a forecast using the configuration from a previous run.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        For scheduled runs with an active schedule, re-executes the schedule. For
        manual runs or runs whose schedule was deleted, returns the configuration_snapshot
        for manual re-execution.


        Request body fields:

        - preview (boolean, optional, default false): When true, computes the forecast
        for inspection only. Skips PO creation (even when the schedule has auto_create_po
        enabled), skips alerts, and does not advance the schedule''s next_run_at.
        The resulting run is recorded with results_summary.is_preview = true. Has
        no effect on manual runs (configuration_only path).


        Authentication: Requires Bearer token.


        Returns 404 if run not found. Returns 500 if execution fails.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                preview:
                  type: boolean
              example:
                preview: false
      parameters:
      - name: runId
        in: path
        schema:
          type: integer
        required: true
        description: Run ID
        example: '55'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 Scheduled Run (Re-executed)
                  value:
                    data:
                      id: 56
                      status: completed
                      run_type: Scheduled
                      results_summary:
                        is_preview: false
                        purchase_orders_created: 1
                example-1:
                  summary: 200 Scheduled Run (Preview)
                  value:
                    data:
                      id: 57
                      status: completed
                      run_type: Scheduled
                      results_summary:
                        is_preview: true
                        skus_to_order: 21
                        total_value: 535.27
                        purchase_orders_created: 0
                example-2:
                  summary: 200 Configuration Only
                  value:
                    data:
                      type: configuration_only
                      message: This run's schedule no longer exists. Use the configuration
                        to run a new forecast manually.
                      configuration_snapshot:
                        supplier_ids:
                        - 1
                        forecast_type: sales_history
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-inventory-forecasting-schedule-runs-runid-rerun
  /api/inventory-forecasting/export:
    post:
      tags:
      - Inventory Intelligence
      summary: Export Forecast
      description: 'Build a forecast and export the results to a file. Returns a download
        URL/filename.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        format: csv (default) or excel.


        include_calculation_details: include the per-product calculation breakdown
        (default true).


        include_sales_history: include historical sales totals (default false).


        config: the same forecast settings used for the build (forecast_type, sales
        window, lead time, MOQ, rounding, filters, demand_modifiers, and so on).


        BASELINE DECOMPOSITION COLUMNS

        With include_calculation_details on (the default), the export adds the baseline-decomposition
        columns that mirror each line''s inputs object:

        - Baseline Method

        - Base Velocity (the flat mean before trend, base_flat)

        - Trend Factor

        - Trend Capped

        - Promo Factor

        - Promo Window

        - Promo Current Baseline

        - Anomaly Days Excluded

        - Anomaly Days Smoothed

        Send the same baseline_method / trend / exclude_detected_anomalies / demand_modifiers
        settings inside config that you would pass to the build endpoint so the exported
        numbers match.


        include_confidence (boolean, default true) adds the confidence tier/score,
        the prediction interval, and the plain-language rationale columns to the export.


        Returns 422 if too many products.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                supplier_ids:
                  type: array
                  items:
                    type: integer
                format:
                  type: string
                include_calculation_details:
                  type: boolean
                include_sales_history:
                  type: boolean
                config:
                  type: object
                  properties:
                    forecast_type:
                      type: string
                    sales_history_days:
                      type: integer
                    target_stock_days:
                      type: integer
                    use_leadtime:
                      type: boolean
                    use_measured_lead_time:
                      type: boolean
                    use_moq:
                      type: boolean
                    rounding_method:
                      type: string
                    product_filters:
                      type: object
                      properties: {}
                    sales_filters:
                      type: object
                      properties: {}
                    demand_modifiers:
                      type: array
                include_confidence:
                  type: boolean
              example:
                supplier_ids:
                - 1
                - 2
                format: csv
                include_calculation_details: true
                include_sales_history: false
                config:
                  forecast_type: sales_history
                  sales_history_days: 90
                  target_stock_days: 30
                  use_leadtime: true
                  use_measured_lead_time: false
                  use_moq: true
                  rounding_method: round_half_up
                  product_filters: {}
                  sales_filters: {}
                  demand_modifiers: []
                include_confidence: true
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      filename:
                        type: string
                      download_url:
                        type: string
                example:
                  data:
                    filename: forecast_export_20241015_090000.csv
                    download_url: /api/inventory-forecasting/download/forecast_export_20241015_090000.csv
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-inventory-forecasting-export
  /api/inventory-forecasting/download/{filename}:
    get:
      tags:
      - Inventory Intelligence
      summary: Download Export File
      description: 'Download an exported forecast file. The filename is returned from
        the POST /export endpoint.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Response is a file download (text/csv or application/vnd.openxmlformats-officedocument.spreadsheetml.sheet).


        Returns 404 if file not found or has expired.'
      parameters:
      - name: filename
        in: path
        schema:
          type: string
        required: true
        description: Filename returned from export endpoint
        example: forecast_export_20241015_090000.csv
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: text/csv
            Content-Disposition:
              schema:
                type: string
                example: attachment; filename="forecast_export_20241015_090000.csv"
          content:
            text/plain:
              schema:
                type: string
                example: 'sku,name,recommended_quantity,unit_cost,total_cost

                  PROD-001,Widget A,50,12.50,625.00'
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                  message:
                    type: string
                example:
                  error: File not found
                  message: The requested export file does not exist or has expired.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-inventory-forecasting-download-filename
  /api/inventory-forecasting/anomalies/detect:
    post:
      tags:
      - Inventory Intelligence
      summary: Detect Demand Anomalies
      description: 'Detect one-off demand anomalies (spikes, drops, and stockout gaps)
        in the daily sales history of one or more products. Runs synchronously, persists
        each flagged point, and returns them.


        Authentication: Requires Bearer token.


        The detector scores each day with a robust modified z-score built from the
        median and median absolute deviation, so a handful of extreme days cannot
        mask the rest. The k threshold is expressed in robust standard deviations;
        lower values flag more points. Each day is classified as:

        - spike_up: demand far above the local norm (often a promotion).

        - drop_down: demand far below the local norm.

        - stockout_zero: a zero-sales gap consistent with being out of stock.


        Detected points feed two workflows:

        1. Resolve them (see Resolve / Bulk Resolve Demand Anomalies) as excluded,
        smoothed, or kept_tagged. Points resolved as excluded or smoothed are the
        ones a build with exclude_detected_anomalies true removes or replaces before
        computing the baseline, de-contaminating the velocity.

        2. Cluster spike_up points into candidate promotions via Suggest Promo Windows.
        A spike can also be linked to a promo_window_id when resolved as kept_tagged.


        Body fields:

        - product_ids (required): array of product IDs, at least one.

        - k (optional): sensitivity threshold in robust standard deviations, 0.1-20
        (default 3.0). Lower flags more points.

        - start_date / end_date (optional, YYYY-MM-DD): detection window. Defaults
        to the trailing 365 days.

        - sales_filters (optional): object narrowing which sales feed the series.

        - warehouse_id (optional): restrict the series to one warehouse.


        Each flagged point has a direction of spike_up, drop_down, or stockout_zero
        and a status of detected until it is resolved.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                product_ids:
                  type: array
                  items:
                    type: integer
                k:
                  type: integer
                start_date:
                  type: string
                end_date:
                  type: string
                sales_filters:
                  type: object
                  properties: {}
                warehouse_id:
                  type: string
                  nullable: true
              example:
                product_ids:
                - 55
                - 56
                k: 3
                start_date: '2023-07-01'
                end_date: '2024-07-01'
                sales_filters: {}
                warehouse_id: null
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        product_id:
                          type: integer
                        anomaly_date:
                          type: string
                        direction:
                          type: string
                        actual_value:
                          type: number
                        expected_value:
                          type: number
                        residual_score:
                          type: number
                        status:
                          type: string
                        is_stockout:
                          type: boolean
                example:
                  data:
                  - product_id: 55
                    anomaly_date: '2024-07-04'
                    direction: spike_up
                    actual_value: 145.0
                    expected_value: 22.0
                    residual_score: 8.7
                    status: detected
                    is_stockout: false
                  - product_id: 55
                    anomaly_date: '2024-09-02'
                    direction: stockout_zero
                    actual_value: 0.0
                    expected_value: 18.0
                    residual_score: 5.1
                    status: detected
                    is_stockout: true
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-inventory-forecasting-anomalies-detect
  /api/inventory-forecasting/anomalies:
    get:
      tags:
      - Inventory Intelligence
      summary: List Demand Anomalies
      description: "List a product's detected demand anomalies, most recent first,\
        \ optionally scoped to a single resolution status.\n\nAuthentication: Requires\
        \ Bearer token.\n\nQuery parameters:\n- product_id (required): the product\
        \ to list anomalies for.\n- status (optional): filter by resolution status.\n\
        \  - detected: flagged, not yet actioned.\n  - excluded: dropped from the\
        \ baseline (a build with exclude_detected_anomalies true removes these days).\n\
        \  - smoothed: replaced with the expected value before the baseline is computed.\n\
        \  - kept_tagged: kept in the baseline, optionally attributed to a promotion\
        \ via promo_window_id."
      parameters:
      - name: product_id
        in: query
        schema:
          type: integer
        description: Required. Product to list anomalies for.
        example: '55'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        product_id:
                          type: integer
                        anomaly_date:
                          type: string
                        direction:
                          type: string
                        actual_value:
                          type: number
                        expected_value:
                          type: number
                        residual_score:
                          type: number
                        method:
                          type: string
                        status:
                          type: string
                        promo_window_id:
                          type: string
                          nullable: true
                        resolved_by:
                          type: string
                          nullable: true
                        resolved_at:
                          type: string
                          nullable: true
                example:
                  data:
                  - id: 3001
                    product_id: 55
                    anomaly_date: '2024-07-04'
                    direction: spike_up
                    actual_value: 145.0
                    expected_value: 22.0
                    residual_score: 8.7
                    method: mad_zscore
                    status: detected
                    promo_window_id: null
                    resolved_by: null
                    resolved_at: null
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-inventory-forecasting-anomalies
  /api/inventory-forecasting/anomalies/{id}/resolve:
    post:
      tags:
      - Inventory Intelligence
      summary: Resolve Demand Anomaly
      description: 'Record a decision for a single demand anomaly so future forecasts
        treat the point correctly.


        Authentication: Requires Bearer token.


        How each status affects a subsequent build (only when that build sets exclude_detected_anomalies
        true):

        - excluded: drop the day from the history before the baseline is computed.
        Use for a true one-off that should not count.

        - smoothed: replace the day with its expected (model) value, keeping the day
        but removing the spike/gap. Use when the day should contribute a normal amount.

        - kept_tagged: keep the day as-is, optionally attributed to a promotion via
        promo_window_id. Excluded and smoothed days are the ones anomaly cleansing
        acts on; kept_tagged days stay in the baseline. detected resets the point
        to unresolved.


        Path parameter: id - the anomaly to resolve.


        Body fields:

        - status (required): excluded, smoothed, kept_tagged, or detected.

        - promo_window_id (optional): link the point to a promo window when kept_tagged,
        associating the spike with a known promotion.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                status:
                  type: string
                promo_window_id:
                  type: integer
              example:
                status: kept_tagged
                promo_window_id: 12
      parameters:
      - name: id
        in: path
        schema:
          type: string
        required: true
        description: The record ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      product_id:
                        type: integer
                      anomaly_date:
                        type: string
                      direction:
                        type: string
                      actual_value:
                        type: number
                      expected_value:
                        type: number
                      residual_score:
                        type: number
                      method:
                        type: string
                      status:
                        type: string
                      promo_window_id:
                        type: integer
                      resolved_by:
                        type: integer
                      resolved_at:
                        type: string
                example:
                  data:
                    id: 3001
                    product_id: 55
                    anomaly_date: '2024-07-04'
                    direction: spike_up
                    actual_value: 145.0
                    expected_value: 22.0
                    residual_score: 8.7
                    method: mad_zscore
                    status: kept_tagged
                    promo_window_id: 12
                    resolved_by: 10
                    resolved_at: '2024-10-15T09:30:00+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-inventory-forecasting-anomalies-id-resolve
  /api/inventory-forecasting/anomalies/bulk-resolve:
    post:
      tags:
      - Inventory Intelligence
      summary: Bulk Resolve Demand Anomalies
      description: 'Apply the same resolution decision to many demand anomalies at
        once - the fast path after Detect Demand Anomalies. Unknown IDs are skipped;
        the response reports how many were actually updated.


        Authentication: Requires Bearer token.


        Status meanings match Resolve Demand Anomaly: excluded (drop from baseline),
        smoothed (replace with expected value), kept_tagged (keep, optionally tagged
        to a promotion), detected (reset). Only excluded and smoothed points are removed/replaced
        when a build runs with exclude_detected_anomalies true.


        Body fields:

        - anomaly_ids (required): array of anomaly IDs, at least one.

        - status (required): excluded, smoothed, kept_tagged, or detected.

        - promo_window_id (optional): link the points to a promo window when kept_tagged.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                anomaly_ids:
                  type: array
                  items:
                    type: integer
                status:
                  type: string
                promo_window_id:
                  type: string
                  nullable: true
              example:
                anomaly_ids:
                - 3001
                - 3002
                - 3003
                status: excluded
                promo_window_id: null
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      resolved_count:
                        type: integer
                example:
                  data:
                    resolved_count: 3
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-inventory-forecasting-anomalies-bulk-resolve
  /api/inventory-forecasting/promo-windows:
    get:
      tags:
      - Inventory Intelligence
      summary: List Promo Windows
      description: 'List all promo windows, including any realised lift (measured_lift_pct)
        and post-promo dip (post_promo_dip_pct) already measured for each. Use a window''s
        id as the promo_window_id of a promo_lift demand modifier to re-apply its
        lift on a build.


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        start_date:
                          type: string
                        end_date:
                          type: string
                        order_tag:
                          type: string
                        product_scope:
                          type: array
                          items:
                            type: integer
                        channel_scope:
                          type: array
                          items:
                            type: string
                        recurrence:
                          type: string
                        measured_lift_pct:
                          type: number
                        post_promo_dip_pct:
                          type: number
                        measured_at:
                          type: string
                        created_by:
                          type: integer
                        created_at:
                          type: string
                        updated_at:
                          type: string
                example:
                  data:
                  - id: 12
                    name: Black Friday 2024
                    start_date: '2024-11-25'
                    end_date: '2024-11-30'
                    order_tag: black-friday
                    product_scope:
                    - 55
                    - 56
                    channel_scope:
                    - shopify
                    recurrence: annual
                    measured_lift_pct: 34.78
                    post_promo_dip_pct: -11.2
                    measured_at: '2024-12-05T08:00:00+00:00'
                    created_by: 10
                    created_at: '2024-11-01T12:00:00+00:00'
                    updated_at: '2024-12-05T08:00:00+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-inventory-forecasting-promo-windows
    post:
      tags:
      - Inventory Intelligence
      summary: Create Promo Window
      description: 'Create a promo window - a named date range, optionally scoped
        to an order tag, a set of products, and sales channels. A promo window is
        the anchor for measuring a promotion''s demand lift and later re-applying
        it.


        Authentication: Requires Bearer token.


        Typical flow:

        1. Create the window over the promotion''s date range (optionally scoped by
        order_tag, product_scope, channel_scope).

        2. Call Measure Promo Lift for a product to compute the realised in-window
        lift and the post-promo dip; the measured lift is stored on the window.

        3. Reference the window from a build request as a demand_modifiers entry of
        type promo_lift (promo_window_id). The stored lift is applied MULTIPLICATIVELY
        to the current baseline, so a window measured last year automatically re-scales
        to this year''s larger baseline.


        Body fields:

        - name (required): label for the window, up to 255 characters.

        - start_date (required, YYYY-MM-DD): must be on or before end_date.

        - end_date (required, YYYY-MM-DD): must be on or after start_date.

        - order_tag (optional): the order tag that marks orders belonging to this
        promotion.

        - recurrence (optional): one_off (a single-date promotion) or annual (repeats
        on the same dates each year, so its lift can be re-applied to the next occurrence).
        Default one_off.

        - product_scope (optional): array of product IDs the window applies to.

        - channel_scope (optional): array of sales channels the window applies to.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                start_date:
                  type: string
                end_date:
                  type: string
                order_tag:
                  type: string
                recurrence:
                  type: string
                product_scope:
                  type: array
                  items:
                    type: integer
                channel_scope:
                  type: array
                  items:
                    type: string
              example:
                name: Black Friday 2024
                start_date: '2024-11-25'
                end_date: '2024-11-30'
                order_tag: black-friday
                recurrence: annual
                product_scope:
                - 55
                - 56
                channel_scope:
                - shopify
      parameters: []
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      start_date:
                        type: string
                      end_date:
                        type: string
                      order_tag:
                        type: string
                      product_scope:
                        type: array
                        items:
                          type: integer
                      channel_scope:
                        type: array
                        items:
                          type: string
                      recurrence:
                        type: string
                      measured_lift_pct:
                        type: string
                        nullable: true
                      post_promo_dip_pct:
                        type: string
                        nullable: true
                      measured_at:
                        type: string
                        nullable: true
                      created_by:
                        type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 12
                    name: Black Friday 2024
                    start_date: '2024-11-25'
                    end_date: '2024-11-30'
                    order_tag: black-friday
                    product_scope:
                    - 55
                    - 56
                    channel_scope:
                    - shopify
                    recurrence: annual
                    measured_lift_pct: null
                    post_promo_dip_pct: null
                    measured_at: null
                    created_by: 10
                    created_at: '2024-11-01T12:00:00+00:00'
                    updated_at: '2024-12-05T08:00:00+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-inventory-forecasting-promo-windows
  /api/inventory-forecasting/promo-windows/suggest:
    post:
      tags:
      - Inventory Intelligence
      summary: Suggest Promo Windows
      description: 'Suggest candidate promo windows for a product by clustering its
        detected upward demand spikes into contiguous date ranges, so a promotion
        can be confirmed instead of typed by hand.


        Authentication: Requires Bearer token.


        This consumes the same spike_up points produced by Detect Demand Anomalies:
        it clusters unresolved upward spikes into candidate date ranges. Downward
        and stockout anomalies are never suggested. Candidates are ranked by peak
        spike severity and capped at 10. A confirmed suggestion can be created as
        a promo window (Create Promo Window), measured (Measure Promo Lift), and then
        re-applied on a future build as a promo_lift demand modifier.


        Body fields:

        - product_id (required): the product to analyse.

        - min_gap_days (optional): a gap larger than this many days splits two spike
        clusters into separate windows, 0-60 (default 3).

        - lookback_days (optional): how far back to scan for spikes, 1-1095 (default
        365).


        Each suggestion reports the cluster''s start_date and end_date, the peak spike
        score, the total excess units above expectation, the number of flagged days,
        and whether an existing promo window already overlaps the range.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                product_id:
                  type: integer
                min_gap_days:
                  type: integer
                lookback_days:
                  type: integer
              example:
                product_id: 55
                min_gap_days: 3
                lookback_days: 365
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        start_date:
                          type: string
                        end_date:
                          type: string
                        peak_residual_score:
                          type: number
                        total_excess_units:
                          type: integer
                        day_count:
                          type: integer
                        already_has_window:
                          type: boolean
                example:
                  data:
                  - start_date: '2024-11-22'
                    end_date: '2024-11-29'
                    peak_residual_score: 6.1
                    total_excess_units: 420
                    day_count: 8
                    already_has_window: false
                  - start_date: '2024-07-03'
                    end_date: '2024-07-06'
                    peak_residual_score: 4.2
                    total_excess_units: 180
                    day_count: 4
                    already_has_window: true
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      product_id:
                        type: array
                        items:
                          type: string
                example:
                  message: A product must be provided to suggest promo windows.
                  errors:
                    product_id:
                    - A product must be provided to suggest promo windows.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-inventory-forecasting-promo-windows-suggest
  /api/inventory-forecasting/promo-windows/{id}:
    get:
      tags:
      - Inventory Intelligence
      summary: Get Promo Window
      description: 'Get a single promo window by ID.


        Authentication: Requires Bearer token.


        Path parameter: id - the promo window to read.


        Returns 404 if the promo window does not exist.'
      parameters:
      - name: id
        in: path
        schema:
          type: string
        required: true
        description: The record ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      start_date:
                        type: string
                      end_date:
                        type: string
                      order_tag:
                        type: string
                      product_scope:
                        type: array
                        items:
                          type: integer
                      channel_scope:
                        type: array
                        items:
                          type: string
                      recurrence:
                        type: string
                      measured_lift_pct:
                        type: number
                      post_promo_dip_pct:
                        type: number
                      measured_at:
                        type: string
                      created_by:
                        type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 12
                    name: Black Friday 2024
                    start_date: '2024-11-25'
                    end_date: '2024-11-30'
                    order_tag: black-friday
                    product_scope:
                    - 55
                    - 56
                    channel_scope:
                    - shopify
                    recurrence: annual
                    measured_lift_pct: 34.78
                    post_promo_dip_pct: -11.2
                    measured_at: '2024-12-05T08:00:00+00:00'
                    created_by: 10
                    created_at: '2024-11-01T12:00:00+00:00'
                    updated_at: '2024-12-05T08:00:00+00:00'
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Promo window not found.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-inventory-forecasting-promo-windows-id
    put:
      tags:
      - Inventory Intelligence
      summary: Update Promo Window
      description: 'Update a promo window. A full representation is expected, mirroring
        create.


        Authentication: Requires Bearer token.


        Editing the date range, order_tag, or scope changes what a future Measure
        Promo Lift call will consider; re-measure afterwards so any promo_lift demand
        modifier that references this window applies the refreshed lift. Because the
        lift is applied multiplicatively to the current baseline, the same window
        keeps re-scaling as demand grows.


        Path parameter: id - the promo window to update.


        Body fields:

        - name (required): label for the window, up to 255 characters.

        - start_date (required, YYYY-MM-DD): must be on or before end_date.

        - end_date (required, YYYY-MM-DD): must be on or after start_date.

        - order_tag (optional): the order tag that marks orders belonging to this
        promotion.

        - recurrence (optional): one_off or annual (default one_off).

        - product_scope (optional): array of product IDs the window applies to.

        - channel_scope (optional): array of sales channels the window applies to.


        Returns 404 if the promo window does not exist.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                start_date:
                  type: string
                end_date:
                  type: string
                order_tag:
                  type: string
                recurrence:
                  type: string
                product_scope:
                  type: array
                  items:
                    type: integer
                channel_scope:
                  type: array
                  items:
                    type: string
              example:
                name: Black Friday 2024
                start_date: '2024-11-25'
                end_date: '2024-11-30'
                order_tag: black-friday
                recurrence: annual
                product_scope:
                - 55
                - 56
                channel_scope:
                - shopify
      parameters:
      - name: id
        in: path
        schema:
          type: string
        required: true
        description: The record ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      start_date:
                        type: string
                      end_date:
                        type: string
                      order_tag:
                        type: string
                      product_scope:
                        type: array
                        items:
                          type: integer
                      channel_scope:
                        type: array
                        items:
                          type: string
                      recurrence:
                        type: string
                      measured_lift_pct:
                        type: number
                      post_promo_dip_pct:
                        type: number
                      measured_at:
                        type: string
                      created_by:
                        type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 12
                    name: Black Friday 2024
                    start_date: '2024-11-25'
                    end_date: '2024-11-30'
                    order_tag: black-friday
                    product_scope:
                    - 55
                    - 56
                    channel_scope:
                    - shopify
                    recurrence: annual
                    measured_lift_pct: 34.78
                    post_promo_dip_pct: -11.2
                    measured_at: '2024-12-05T08:00:00+00:00'
                    created_by: 10
                    created_at: '2024-11-01T12:00:00+00:00'
                    updated_at: '2024-12-05T08:00:00+00:00'
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Promo window not found.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: put-api-inventory-forecasting-promo-windows-id
    delete:
      tags:
      - Inventory Intelligence
      summary: Delete Promo Window
      description: 'Delete a promo window.


        Authentication: Requires Bearer token.


        Path parameter: id - the promo window to delete.


        Returns 204 on success, or 404 if the promo window does not exist.'
      parameters:
      - name: id
        in: path
        schema:
          type: string
        required: true
        description: The record ID.
      responses:
        '204':
          description: No Content
          content:
            text/plain:
              schema:
                type: string
                example: ''
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Promo window not found.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: delete-api-inventory-forecasting-promo-windows-id
  /api/inventory-forecasting/promo-windows/{id}/measure:
    post:
      tags:
      - Inventory Intelligence
      summary: Measure Promo Lift
      description: 'Measure the realised demand lift during a promo window and the
        dip in the days after it, for one product. The result is persisted onto the
        window and returned alongside suggested forward demand modifiers for next
        year''s occurrence.


        Authentication: Requires Bearer token.


        The measured lift is what a promo_lift demand modifier applies at build time.
        It is reported as a percentage but is applied MULTIPLICATIVELY to whatever
        the current baseline is, so it stays correct as demand grows - a promotion
        that lifted demand 85% last year still lifts this year''s larger baseline
        by 85%. Re-measure whenever you want the applied lift refreshed (for example
        after editing the window or accruing more sales).


        Path parameter: id - the promo window to measure.


        Body fields:

        - product_id (required): the product to measure.

        - dip_days (optional): number of days after the window to measure the post-promo
        dip, 1-365 (default 14).

        - sales_filters (optional): object narrowing which sales are counted.

        - warehouse_id (optional): restrict the measurement to one warehouse.


        The response reports measured_lift_pct, post_promo_dip_pct, the in-window
        and expected daily rates, and suggested_modifiers - event demand modifiers
        pre-dated to the same window one year forward, ready to add to a build or
        configuration.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                product_id:
                  type: integer
                dip_days:
                  type: integer
                sales_filters:
                  type: object
                  properties: {}
                warehouse_id:
                  type: string
                  nullable: true
              example:
                product_id: 55
                dip_days: 14
                sales_filters: {}
                warehouse_id: null
      parameters:
      - name: id
        in: path
        schema:
          type: string
        required: true
        description: The record ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      measured_lift_pct:
                        type: number
                      post_promo_dip_pct:
                        type: number
                      in_window_daily:
                        type: number
                      expected_daily:
                        type: number
                      suggested_modifiers:
                        type: array
                        items:
                          type: object
                          properties:
                            type:
                              type: string
                            value:
                              type: integer
                            apply_to:
                              type: string
                            name:
                              type: string
                            period_key:
                              type: string
                              nullable: true
                            start_date:
                              type: string
                            end_date:
                              type: string
                            product_id:
                              type: string
                              nullable: true
                example:
                  data:
                    measured_lift_pct: 34.7821
                    post_promo_dip_pct: -11.2
                    in_window_daily: 8.5
                    expected_daily: 6.3
                    suggested_modifiers:
                    - type: event
                      value: 35
                      apply_to: all
                      name: Black Friday 2024 lift
                      period_key: null
                      start_date: '2025-11-25'
                      end_date: '2025-11-30'
                      product_id: null
                    - type: event
                      value: -11
                      apply_to: all
                      name: Black Friday 2024 post-promo dip
                      period_key: null
                      start_date: '2025-12-01'
                      end_date: '2025-12-14'
                      product_id: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-inventory-forecasting-promo-windows-id-measure
  /api/inventory-forecasting/accuracy:
    get:
      tags:
      - Inventory Intelligence
      summary: List Forecast Accuracy
      description: 'List a product''s forecast-accuracy history across runs, paginated.
        Each entry compares a run''s projected demand against the actual quantity
        sold in the evaluation window.


        Authentication: Requires Bearer token.


        Query parameters:

        - product_id (required): the product to read accuracy for.

        - page (default 1), per_page (default 15).


        Each entry reports ape (absolute percentage error), signed_bias with a bias_direction
        of over, under, or none, a tracking_signal, and is_drifting when the forecast
        is trending off.'
      parameters:
      - name: product_id
        in: query
        schema:
          type: integer
        description: Required. Product to list accuracy history for.
        example: '55'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        forecast_schedule_run_id:
                          type: integer
                        product_id:
                          type: integer
                        product_link:
                          type: string
                        product_sku:
                          type: string
                        product_name:
                          type: string
                        evaluation_start:
                          type: string
                        evaluation_end:
                          type: string
                        forecast_quantity:
                          type: number
                        actual_quantity:
                          type: number
                        ape:
                          type: number
                        signed_bias:
                          type: number
                        bias_direction:
                          type: string
                        tracking_signal:
                          type: number
                        is_drifting:
                          type: boolean
                        computed_at:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 700
                    forecast_schedule_run_id: 512
                    product_id: 55
                    product_link: /products/55
                    product_sku: PROD-001
                    product_name: Widget A
                    evaluation_start: '2024-09-01'
                    evaluation_end: '2024-09-30'
                    forecast_quantity: 75.0
                    actual_quantity: 68.0
                    ape: 10.29
                    signed_bias: 7.0
                    bias_direction: over
                    tracking_signal: 1.8
                    is_drifting: false
                    computed_at: '2024-10-15T09:00:00+00:00'
                    created_at: '2024-10-15T09:00:00+00:00'
                    updated_at: '2024-10-15T09:00:00+00:00'
                  current_page: 1
                  last_page: 1
                  per_page: 15
                  total: 6
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-inventory-forecasting-accuracy
  /api/inventory-forecasting/accuracy/evaluate:
    post:
      tags:
      - Inventory Intelligence
      summary: Evaluate Forecast Accuracy
      description: 'Backtest a completed forecast run by comparing its projected demand
        against actual sales, and store the resulting accuracy metrics per product.
        The work runs in the background; the response returns immediately with a job
        reference to poll for progress.


        Authentication: Requires Bearer token.


        Body fields:

        - run_id (required): the forecast run to evaluate.

        - eval_start (optional, YYYY-MM-DD): start of the evaluation window; must
        be on or before eval_end.

        - eval_end (optional, YYYY-MM-DD): end of the evaluation window.


        Returns a job reference (tracked_job_log_id).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                run_id:
                  type: integer
                eval_start:
                  type: string
                eval_end:
                  type: string
              example:
                run_id: 512
                eval_start: '2024-09-01'
                eval_end: '2024-09-30'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 12345
                  message: Forecast accuracy evaluation started.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-inventory-forecasting-accuracy-evaluate
  /api/inventory-forecasting/schedule-runs/{runId}/accuracy:
    get:
      tags:
      - Inventory Intelligence
      summary: Get Run Forecast Accuracy
      description: 'Get all forecast-accuracy metrics computed for a single forecast
        run - one entry per evaluated product.


        Authentication: Requires Bearer token.


        Path parameter: runId - the forecast run to read accuracy for.


        Each entry reports ape, signed_bias with a bias_direction, a tracking_signal,
        and is_drifting. Returns an empty list if the run has not been evaluated yet.'
      parameters:
      - name: runId
        in: path
        schema:
          type: string
        required: true
        description: The run ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        forecast_schedule_run_id:
                          type: integer
                        product_id:
                          type: integer
                        product_link:
                          type: string
                        product_sku:
                          type: string
                        product_name:
                          type: string
                        evaluation_start:
                          type: string
                        evaluation_end:
                          type: string
                        forecast_quantity:
                          type: number
                        actual_quantity:
                          type: number
                        ape:
                          type: number
                        signed_bias:
                          type: number
                        bias_direction:
                          type: string
                        tracking_signal:
                          type: number
                        is_drifting:
                          type: boolean
                        computed_at:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                example:
                  data:
                  - id: 700
                    forecast_schedule_run_id: 512
                    product_id: 55
                    product_link: /products/55
                    product_sku: PROD-001
                    product_name: Widget A
                    evaluation_start: '2024-09-01'
                    evaluation_end: '2024-09-30'
                    forecast_quantity: 75.0
                    actual_quantity: 68.0
                    ape: 10.29
                    signed_bias: 7.0
                    bias_direction: over
                    tracking_signal: 1.8
                    is_drifting: false
                    computed_at: '2024-10-15T09:00:00+00:00'
                    created_at: '2024-10-15T09:00:00+00:00'
                    updated_at: '2024-10-15T09:00:00+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-inventory-forecasting-schedule-runs-runid-accuracy
  /api/inventory-forecasting/lead-time-coverage/summary:
    post:
      tags:
      - Inventory Intelligence
      summary: Get Measured Lead Time Coverage Summary
      description: 'Coverage counts and averages for the measured (purchase-order-derived)
        lead times available across a forecast scope. Answers, for the selected suppliers
        and optional destination warehouse, how many supplier-products have a measured
        lead time versus fall back to the configured value.


        Authentication: Requires Bearer token.


        Request body:

        - supplier_ids (required, integer array) — suppliers in scope.

        - destination_warehouse_id (optional, integer) — when set, the destination-scoped
        measured actual is preferred over the blended per-supplier-product average.

        - product_filters (optional, object) — filter_groups structure to narrow the
        products in scope.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                supplier_ids:
                  type: array
                  items:
                    type: integer
                destination_warehouse_id:
                  type: integer
                product_filters:
                  type: object
                  properties: {}
              example:
                supplier_ids:
                - 1
                - 2
                - 3
                destination_warehouse_id: 4
                product_filters: {}
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      total_products:
                        type: integer
                      with_measured:
                        type: integer
                      falls_back:
                        type: integer
                      avg_measured_days:
                        type: number
                      avg_on_time_pct:
                        type: number
                example:
                  data:
                    total_products: 310
                    with_measured: 142
                    falls_back: 168
                    avg_measured_days: 34.0
                    avg_on_time_pct: 78.0
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-inventory-forecasting-lead-time-coverage-summary
  /api/inventory-forecasting/lead-time-coverage/products:
    post:
      tags:
      - Inventory Intelligence
      summary: List Measured Lead Time Coverage Products
      description: 'Paginated per-product breakdown of configured versus measured
        lead time for a forecast scope, including which value would drive the forecast
        when measured lead times are enabled.


        Authentication: Requires Bearer token.


        Request body:

        - supplier_ids (required, integer array) — suppliers in scope.

        - destination_warehouse_id (optional, integer) — prefers the destination-scoped
        measured actual.

        - product_filters (optional, object) — filter_groups structure to narrow the
        products.

        - search (optional, string) — matches product SKU or name.

        - measured (optional, string) — one of ''has_measured'' or ''falls_back''
        to only return products that do or do not have measured data.

        - page (optional, integer, default 1).

        - per_page (optional, integer, default 10, max 100).


        Response fields per product:

        - configured_lead_time / configured_source — the configured lead time and
        where it comes from.

        - measured_avg_days, measured_sample_size, measured_reliability_pct, measured_variance
        — the measured evidence (null when none exists).

        - measured_scope — ''warehouse'' (destination-scoped), ''blended'' (across
        all warehouses), or null.

        - resolved_lead_time / resolved_source / uses_measured — the value that would
        drive the forecast and whether measured data won.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                supplier_ids:
                  type: array
                  items:
                    type: integer
                destination_warehouse_id:
                  type: integer
                product_filters:
                  type: object
                  properties: {}
                search:
                  type: string
                measured:
                  type: string
                page:
                  type: integer
                per_page:
                  type: integer
              example:
                supplier_ids:
                - 1
                - 2
                - 3
                destination_warehouse_id: 4
                product_filters: {}
                search: widget
                measured: has_measured
                page: 1
                per_page: 10
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        supplier_product_id:
                          type: integer
                        product_id:
                          type: integer
                        sku:
                          type: string
                        name:
                          type: string
                        supplier_id:
                          type: integer
                        supplier_name:
                          type: string
                        configured_lead_time:
                          type: integer
                        configured_source:
                          type: string
                        configured_source_label:
                          type: string
                        measured_avg_days:
                          type: number
                        measured_sample_size:
                          type: integer
                        measured_reliability_pct:
                          type: number
                        measured_variance:
                          type: number
                        measured_scope:
                          type: string
                        measured_computed_at:
                          type: string
                        has_measured:
                          type: boolean
                        resolved_lead_time:
                          type: integer
                        resolved_source:
                          type: string
                        resolved_source_label:
                          type: string
                        uses_measured:
                          type: boolean
                        product_route:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - supplier_product_id: 8842
                    product_id: 55
                    sku: WIDGET-BLK
                    name: Widget - Black
                    supplier_id: 1
                    supplier_name: Acme Supplier Co.
                    configured_lead_time: 30
                    configured_source: product
                    configured_source_label: Product Override
                    measured_avg_days: 19.0
                    measured_sample_size: 11
                    measured_reliability_pct: 91.0
                    measured_variance: 2.1
                    measured_scope: warehouse
                    measured_computed_at: '2026-07-20T02:00:00+00:00'
                    has_measured: true
                    resolved_lead_time: 19
                    resolved_source: measured
                    resolved_source_label: Measured Actual
                    uses_measured: true
                    product_route: /products/55
                  current_page: 1
                  last_page: 15
                  per_page: 10
                  total: 142
                  from: 1
                  to: 10
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-inventory-forecasting-lead-time-coverage-products
  /api/inventory-forecasting/lead-time-coverage/{supplierProduct}/purchase-orders:
    get:
      tags:
      - Inventory Intelligence
      summary: List Measured Lead Time Contributing Purchase Orders
      description: 'The closed purchase orders a supplier-product''s measured lead
        time is derived from: the same closed-PO population (last 12 months, with
        submitted, received and estimated delivery dates present) that the measured
        average is computed over. Each row shows the submitted-to-received span and
        whether it landed on or before its estimated delivery date.


        Authentication: Requires Bearer token.


        Path parameter:

        - supplierProduct (required, integer) — the supplier-product id.


        Query parameter:

        - warehouse_id (optional, integer) — restrict to POs delivered to a specific
        destination warehouse.


        Ordered by received date, most recent first.'
      parameters:
      - name: supplierProduct
        in: path
        schema:
          type: integer
        required: true
        description: Supplier-product id whose measured lead time you want the evidence
          for.
        example: '8842'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        purchase_order_id:
                          type: integer
                        purchase_order_number:
                          type: string
                        submitted_at:
                          type: string
                        received_at:
                          type: string
                        estimated_delivery_date:
                          type: string
                        lead_time_days:
                          type: integer
                        on_time:
                          type: boolean
                        late_days:
                          type: integer
                        destination_warehouse_id:
                          type: integer
                        destination_warehouse_name:
                          type: string
                        link_route:
                          type: string
                example:
                  data:
                  - purchase_order_id: 1042
                    purchase_order_number: PO-1042
                    submitted_at: '2026-03-03T09:00:00+00:00'
                    received_at: '2026-03-22T14:30:00+00:00'
                    estimated_delivery_date: '2026-03-24T00:00:00+00:00'
                    lead_time_days: 19
                    on_time: true
                    late_days: 0
                    destination_warehouse_id: 4
                    destination_warehouse_name: Main Warehouse
                    link_route: /orders/purchase-orders/1042
                  - purchase_order_id: 1051
                    purchase_order_number: PO-1051
                    submitted_at: '2026-03-17T09:00:00+00:00'
                    received_at: '2026-04-09T16:00:00+00:00'
                    estimated_delivery_date: '2026-04-06T00:00:00+00:00'
                    lead_time_days: 23
                    on_time: false
                    late_days: 3
                    destination_warehouse_id: 4
                    destination_warehouse_name: Main Warehouse
                    link_route: /orders/purchase-orders/1051
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-inventory-forecasting-lead-time-coverage-supplierproduct-purchase-orders
  /api/inventory-aging:
    get:
      tags:
      - Inventory Intelligence
      summary: Get Inventory Aging Report
      description: 'Paginated inventory aging report.


        :::info[Required scope: `inventory:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Two views:

        - `view=product_summary` — one row per product aggregated across its FIFO
        layers, enriched with listings, sales velocity (7/14/30/90 days), days of
        supply, channel sales, margin, bracket-scoped `aged_value` (dollars in the
        active bracket, or 181+ days when no bracket filter is set), an estimated
        90-day `holding_cost_90d`, a rule-based `suggested_action`, and the recorded
        `action` state.

        - `view=fifo_detail` — raw cost layers (one row per layer) with age bracket,
        layer date, source document and value.


        Sorting (product summary): pass `sort_by` + `sort_dir`; sorting runs server-side
        over the full filtered dataset. Allowed sorts: sku, total_quantity, avg_unit_cost,
        total_value, aged_value, max_days_old, holding_cost, velocity_30d.


        Action scope (product summary): `action_scope` partitions rows by their recorded
        action state; metrics and distribution deliberately ignore it so totals keep
        counting accepted/resolved stock.


        All other filters apply identically to this endpoint, the metrics, the distribution
        and the CSV export. `sales_period` governs every sales-window filter (has_sales,
        channel sold-on / no-sales-on, margin).'
      parameters:
      - name: view
        in: query
        schema:
          type: string
        description: product_summary (one row per product, enriched) or fifo_detail
          (raw cost layers). Default fifo_detail
        example: product_summary
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        product_id:
                          type: integer
                        sku:
                          type: string
                        product_name:
                          type: string
                        brand_name:
                          type: string
                        brand_id:
                          type: integer
                        supplier_name:
                          type: string
                        age_bracket:
                          type: string
                        max_days_old:
                          type: integer
                        total_quantity:
                          type: integer
                        avg_unit_cost:
                          type: number
                        total_value:
                          type: number
                        warehouses:
                          type: array
                          items:
                            type: string
                        aged_value:
                          type: number
                        aged_quantity:
                          type: integer
                        aged_value_label:
                          type: string
                        holding_cost_90d:
                          type: number
                        listings:
                          type: array
                          items:
                            type: object
                            properties:
                              id:
                                type: integer
                              sales_channel_name:
                                type: string
                              integration_name:
                                type: string
                              listing_price:
                                type: number
                              default_tier_price:
                                type: number
                              discount_percentage:
                                type: integer
                              listing_sku:
                                type: string
                              listing_type:
                                type: string
                                nullable: true
                              listing_status:
                                type: string
                                nullable: true
                              condition:
                                type: string
                                nullable: true
                        listing_count:
                          type: integer
                        has_listings:
                          type: boolean
                        all_full_price:
                          type: boolean
                        has_fba_layers:
                          type: boolean
                        sold_7d:
                          type: integer
                        sold_14d:
                          type: integer
                        sold_30d:
                          type: integer
                        sold_90d:
                          type: integer
                        days_of_supply:
                          type: string
                          nullable: true
                        channel_sales_30d:
                          type: array
                        total_channel_sales_30d:
                          type: integer
                        total_channel_revenue_30d:
                          type: integer
                        default_retail_price:
                          type: number
                        avg_selling_price_30d:
                          type: string
                          nullable: true
                        avg_cogs_per_unit_30d:
                          type: string
                          nullable: true
                        total_revenue_30d:
                          type: string
                          nullable: true
                        total_cogs_30d:
                          type: string
                          nullable: true
                        margin_pct_30d:
                          type: string
                          nullable: true
                        suggested_action:
                          type: object
                          properties:
                            action:
                              type: string
                            label:
                              type: string
                            reason:
                              type: string
                        action:
                          type: string
                          nullable: true
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - product_id: 1935
                    sku: SZ909
                    product_name: Brand New Hayg OEM Fuel Pump
                    brand_name: Hayg
                    brand_id: 12
                    supplier_name: Hayg Distribution
                    age_bracket: 365+
                    max_days_old: 412
                    total_quantity: 115
                    avg_unit_cost: 13.51
                    total_value: 1553.2
                    warehouses:
                    - FBA US
                    - ShipMyOrders Warehouse
                    aged_value: 1553.2
                    aged_quantity: 115
                    aged_value_label: 181+ days
                    holding_cost_90d: 97.08
                    listings:
                    - id: 881
                      sales_channel_name: AMZ partusa
                      integration_name: amazon
                      listing_price: 39.95
                      default_tier_price: 39.95
                      discount_percentage: 0
                      listing_sku: SZ909-FBA
                      listing_type: null
                      listing_status: null
                      condition: null
                    listing_count: 1
                    has_listings: true
                    all_full_price: true
                    has_fba_layers: true
                    sold_7d: 0
                    sold_14d: 0
                    sold_30d: 0
                    sold_90d: 5
                    days_of_supply: null
                    channel_sales_30d: []
                    total_channel_sales_30d: 0
                    total_channel_revenue_30d: 0
                    default_retail_price: 39.95
                    avg_selling_price_30d: null
                    avg_cogs_per_unit_30d: null
                    total_revenue_30d: null
                    total_cogs_30d: null
                    margin_pct_30d: null
                    suggested_action:
                      action: expand_channels
                      label: Expand channels
                      reason: Listed on 1 of 4 active channels
                    action: null
                  current_page: 1
                  last_page: 8
                  per_page: 50
                  total: 382
                  from: 1
                  to: 50
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      sort_by:
                        type: array
                        items:
                          type: string
                example:
                  message: Invalid sort column.
                  errors:
                    sort_by:
                    - Invalid sort column.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: inventory:read
      operationId: get-api-inventory-aging
  /api/inventory-aging/metrics:
    get:
      tags:
      - Inventory Intelligence
      summary: Get Inventory Aging Metrics
      description: 'Summary metrics for the aging report: total inventory value at
        cost, value-weighted average age, product counts (total, slow-moving 180+,
        dead stock 365+), value at risk (181+ days), and per-bracket value/quantity/percentage
        breakdowns.


        :::info[Required scope: `inventory:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Honors every filter the report honors (warehouse, brand, supplier, search,
        quantity, age bracket, listings, sales, channels, margin), so these figures
        always describe the same population as the filtered report. `action_scope`
        is deliberately ignored — accepted/resolved stock stays counted.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  total_inventory_value:
                    type: number
                  average_age:
                    type: integer
                  total_skus:
                    type: integer
                  slow_moving_skus:
                    type: integer
                  dead_stock_skus:
                    type: integer
                  value_at_risk:
                    type: number
                  value_by_age_bracket:
                    type: object
                    properties:
                      0-30:
                        type: number
                      31-60:
                        type: number
                      61-90:
                        type: number
                      91-180:
                        type: number
                      181-365:
                        type: number
                      365+:
                        type: number
                  quantity_by_age_bracket:
                    type: object
                    properties:
                      0-30:
                        type: integer
                      31-60:
                        type: integer
                      61-90:
                        type: integer
                      91-180:
                        type: integer
                      181-365:
                        type: integer
                      365+:
                        type: integer
                  percentage_by_age_bracket:
                    type: object
                    properties:
                      0-30:
                        type: number
                      31-60:
                        type: number
                      61-90:
                        type: number
                      91-180:
                        type: number
                      181-365:
                        type: number
                      365+:
                        type: number
                example:
                  total_inventory_value: 716964.57
                  average_age: 279
                  total_skus: 569
                  slow_moving_skus: 382
                  dead_stock_skus: 177
                  value_at_risk: 366573.77
                  value_by_age_bracket:
                    0-30: 249322.11
                    31-60: 54210.09
                    61-90: 46858.6
                    91-180: 101243.4
                    181-365: 158218.9
                    365+: 208354.87
                  quantity_by_age_bracket:
                    0-30: 1204
                    31-60: 310
                    61-90: 280
                    91-180: 642
                    181-365: 801
                    365+: 1388
                  percentage_by_age_bracket:
                    0-30: 34.8
                    31-60: 7.6
                    61-90: 6.5
                    91-180: 14.1
                    181-365: 22.1
                    365+: 29.1
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: inventory:read
      operationId: get-api-inventory-aging-metrics
  /api/inventory-aging/distribution:
    get:
      tags:
      - Inventory Intelligence
      summary: Get Inventory Aging Distribution
      description: 'Per-bracket distribution for the value-at-risk funnel: quantity,
        value, percentage of total value and a display color per age bracket. Always
        returns all six brackets (zeroed when empty).


        :::info[Required scope: `inventory:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Honors the same filters as the report and metrics, so the funnel always reconciles
        with both.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: array
                items:
                  type: object
                  properties:
                    age_bracket:
                      type: string
                    quantity:
                      type: integer
                    value:
                      type: number
                    percentage:
                      type: number
                    color:
                      type: string
                example:
                - age_bracket: 0-30
                  quantity: 1204
                  value: 249322.11
                  percentage: 34.8
                  color: '#4CAF50'
                - age_bracket: 31-60
                  quantity: 310
                  value: 54210.09
                  percentage: 7.6
                  color: '#8BC34A'
                - age_bracket: 61-90
                  quantity: 280
                  value: 46858.6
                  percentage: 6.5
                  color: '#FFEB3B'
                - age_bracket: 91-180
                  quantity: 642
                  value: 101243.4
                  percentage: 14.1
                  color: '#FF9800'
                - age_bracket: 181-365
                  quantity: 801
                  value: 158218.9
                  percentage: 22.1
                  color: '#FF5722'
                - age_bracket: 365+
                  quantity: 1388
                  value: 208354.87
                  percentage: 29.1
                  color: '#F44336'
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: inventory:read
      operationId: get-api-inventory-aging-distribution
  /api/inventory-aging/trend:
    get:
      tags:
      - Inventory Intelligence
      summary: Get Inventory Aging Trend
      description: 'Aged-value trend series from nightly snapshots: per-bracket inventory
        value and quantity per snapshot date, for charting whether aged value is shrinking
        over time.


        Without `warehouse_id` the tenant-wide rollup series is returned. Snapshots
        are recorded nightly going forward — history begins the day the feature is
        enabled.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        snapshot_date:
                          type: string
                        age_bracket:
                          type: string
                        total_value:
                          type: number
                        total_quantity:
                          type: integer
                example:
                  data:
                  - snapshot_date: '2026-07-12'
                    age_bracket: 181-365
                    total_value: 158218.9
                    total_quantity: 801
                  - snapshot_date: '2026-07-12'
                    age_bracket: 365+
                    total_value: 208354.87
                    total_quantity: 1388
                  - snapshot_date: '2026-07-13'
                    age_bracket: 181-365
                    total_value: 155102.4
                    total_quantity: 788
                  - snapshot_date: '2026-07-13'
                    age_bracket: 365+
                    total_value: 206220.11
                    total_quantity: 1371
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-inventory-aging-trend
  /api/inventory-aging/export:
    get:
      tags:
      - Inventory Intelligence
      summary: Export Inventory Aging to CSV
      description: 'Stream the aging report as a CSV download. `view=product_summary`
        exports enriched product rows (including aged value, holding cost, suggested
        action and recorded action state); the default view exports raw FIFO layer
        detail.


        :::info[Required scope: `inventory:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Honors every report filter plus `sort_by`/`sort_dir` and `action_scope`, so
        the file matches what the filtered report shows. Response is a `text/csv`
        attachment, not JSON.'
      parameters:
      - name: view
        in: query
        schema:
          type: string
        description: product_summary (one row per product, enriched) or fifo_detail
          (raw cost layers). Default fifo_detail
        example: product_summary
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: inventory:read
      operationId: get-api-inventory-aging-export
  /api/inventory-aging/sales-channels:
    get:
      tags:
      - Inventory Intelligence
      summary: List Sales Channels (Aging Report Filter Values)
      description: 'Sales channels that have had sales in the last 90 days — the option
        list for the sold-on / no-sales-on / not-listed-on channel filters.


        :::info[Required scope: `inventory:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: array
                items:
                  type: object
                  properties:
                    id:
                      type: integer
                    channelName:
                      type: string
                    integrationName:
                      type: string
                example:
                - id: 2
                  channelName: AMZ partusa
                  integrationName: amazon
                - id: 5
                  channelName: EBAY fuelpumpsusa
                  integrationName: ebay
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: inventory:read
      operationId: get-api-inventory-aging-sales-channels
  /api/inventory-aging/actions/{product}:
    put:
      tags:
      - Inventory Intelligence
      summary: Record Product Aging Action
      description: 'Create or update the aging action state for a product. One state
        per product:


        - `needs_action` — default; nothing recorded yet

        - `in_progress` — a clearance action was recorded (`action_type` required:
        price_reduced, listed_on_channel, promotion, bundled, transferred, removal_ordered,
        written_down, other)

        - `resolved` — the aged stock was dealt with (`resolution` required: sold_through,
        cleared, written_off)

        - `accepted` — deliberate long-tail stock; optional `snooze_until` (today
        or later) keeps it out of the needs-attention scope until that date


        `note` (max 1000 chars) and `assigned_to` (an active user belonging to the
        current account) are optional on every status; `action_type` is rejected for
        accepted/needs_action and `resolution` outside resolved. Each write stamps
        who acted and when.


        When granular permissions are enabled for the account, this endpoint requires
        the `inventory.manage_aging` permission.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                status:
                  type: string
                action_type:
                  type: string
                note:
                  type: string
                assigned_to:
                  type: integer
              example:
                status: in_progress
                action_type: price_reduced
                note: Dropped price 15% on Amazon and eBay
                assigned_to: 4
      parameters:
      - name: product
        in: path
        schema:
          type: string
        required: true
        description: The product ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  product_id:
                    type: integer
                  status:
                    type: string
                  action_type:
                    type: string
                  resolution:
                    type: string
                    nullable: true
                  note:
                    type: string
                  assigned_to:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                  snooze_until:
                    type: string
                    nullable: true
                  acted_at:
                    type: string
                  updated_by:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                example:
                  product_id: 1935
                  status: in_progress
                  action_type: price_reduced
                  resolution: null
                  note: Dropped price 15% on Amazon and eBay
                  assigned_to:
                    id: 4
                    name: Jo Merchant
                  snooze_until: null
                  acted_at: '2026-07-13T14:05:22+00:00'
                  updated_by:
                    id: 1
                    name: Administrator
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      action_type:
                        type: array
                        items:
                          type: string
                example:
                  message: An action type is required when recording an in-progress
                    action.
                  errors:
                    action_type:
                    - An action type is required when recording an in-progress action.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: put-api-inventory-aging-actions-product
    delete:
      tags:
      - Inventory Intelligence
      summary: Clear Product Aging Action
      description: 'Remove a product''s recorded aging action state, returning it
        to needs-action.


        When granular permissions are enabled for the account, this endpoint requires
        the `inventory.manage_aging` permission.'
      parameters:
      - name: product
        in: path
        schema:
          type: string
        required: true
        description: The product ID.
      responses:
        '204':
          description: No Content
          content:
            text/plain:
              schema:
                type: string
                example: ''
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-inventory-aging-actions-product
  /api/inventory-aging/actions/bulk:
    post:
      tags:
      - Inventory Intelligence
      summary: Bulk Record Product Aging Actions
      description: 'Record the same aging action state for up to 50 products in one
        call. Field rules match the single-product endpoint (`action_type` required
        for in_progress, `resolution` required for resolved, `snooze_until` only for
        accepted).


        Returns a per-product result list; a failure on one product does not roll
        back the others.


        When granular permissions are enabled for the account, this endpoint requires
        the `inventory.manage_aging` permission.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                product_ids:
                  type: array
                  items:
                    type: integer
                status:
                  type: string
                note:
                  type: string
                snooze_until:
                  type: string
              example:
                product_ids:
                - 1935
                - 1994
                - 2017
                status: accepted
                note: Evergreen replacement-part stock
                snooze_until: '2026-10-01'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  results:
                    type: array
                    items:
                      type: object
                      properties:
                        product_id:
                          type: integer
                        ok:
                          type: boolean
                example:
                  results:
                  - product_id: 1935
                    ok: true
                  - product_id: 1994
                    ok: true
                  - product_id: 2017
                    ok: true
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      product_ids:
                        type: array
                        items:
                          type: string
                example:
                  message: Bulk actions are limited to 50 products at a time.
                  errors:
                    product_ids:
                    - Bulk actions are limited to 50 products at a time.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-inventory-aging-actions-bulk
  /api/inventory-aging/actions/generate-ai-suggestions:
    post:
      tags:
      - Inventory Intelligence
      summary: Generate AI Aging Suggestions
      description: 'Start a background process that scores aged products with AI and
        caches a recommended next action on each. Returns a tracked job id you can
        poll for completion; when the job finishes, the aging report shows the AI-scored
        suggestions in place of the rule-based ones. If AI is disabled or unavailable
        for the account, the job completes immediately and rows keep their rule-based
        suggestions.


        Takes no request body.


        When granular permissions are enabled for the account, this endpoint requires
        the `inventory.manage_aging` permission.'
      requestBody:
        content: {}
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 84213
                  message: AI aging suggestions are being generated.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-inventory-aging-actions-generate-ai-suggestions
  /api/inventory-expiry:
    get:
      tags:
      - Inventory Expiry & Shelf-Life
      summary: Get Expiry & Shelf-Life Report
      description: 'Paginated Inventory Expiry & Shelf-Life report. Blends internal
        lot-tracked FIFO layers with Amazon FBA/AWD layers, bucketed by days-to-expiry.
        Defaults to the lot_detail view (one row per lot/FIFO layer, each carrying
        a real fifo_layer_id for disposition actions); pass view=product_summary for
        one row per product rolled up to the worst-case (soonest) expiry.


        Available on both GET and POST (the POST variant mirrors all filters and additionally
        accepts the filter_groups product advanced-filter tree in the body).


        Authentication: Requires Bearer token. Scope: reports:read.


        Buckets: expired, 0-30, 31-60, 61-90, 91-180, 180+, no_expiry.

        Sort: fixed — soonest-to-expire first, undated lots last.

        Pagination: page (default 1), per_page (default 50, max 500).


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        This endpoint accepts the canonical list view param contract used by the application
        UI: filters as filter[&lt;key>], a `sort` param (see below), `page`/`per_page`,
        and a base64-encoded `filter_groups` tree — in addition to the flat params
        shown.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 OK (lot_detail view)
                  value:
                    current_page: 1
                    data:
                    - fifo_layer_id: 8842
                      product_id: 42
                      sku: VIT-D3-1000
                      product_name: Vitamin D3 1000 IU
                      brand_name: Acme
                      brand_id: 3
                      supplier_name: Wellness Distributors
                      warehouse_id: 1
                      warehouse_name: Main Warehouse
                      bucket: 0-30
                      days_to_expiry: 18
                      expiry_date: '2026-07-04T00:00:00.000000Z'
                      manufacture_date: '2024-07-04T00:00:00.000000Z'
                      batch_number: LOT-2026-01
                      shelf_life_remaining_pct: 2.5
                      link_type: App\Models\PurchaseOrderLine
                      link_type_name: Purchase Order Line
                      link_id: 5521
                      quantity: 120.0
                      avg_unit_cost: 8.5
                      total_value: 1020.0
                      valuation_source: internal
                      is_fba: false
                      review_status: open
                      review_status_label: Open
                      review_notes: null
                      reviewed_at: null
                      reviewed_by_name: null
                      inventory_hold_id: null
                    per_page: 50
                    total: 137
                    last_page: 3
                example-1:
                  summary: 200 OK (product_summary view)
                  value:
                    current_page: 1
                    data:
                    - product_id: 42
                      sku: VIT-D3-1000
                      product_name: Vitamin D3 1000 IU
                      brand_name: Acme
                      brand_id: 3
                      supplier_name: Wellness Distributors
                      bucket: 0-30
                      min_days_to_expiry: 18
                      earliest_expiry: '2026-07-04T00:00:00.000000Z'
                      total_quantity: 340.0
                      expired_quantity: 0.0
                      avg_unit_cost: 8.5
                      total_value: 2890.0
                      warehouses:
                      - Main Warehouse
                      - Overflow Warehouse
                    per_page: 50
                    total: 54
                    last_page: 2
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      bucket:
                        type: array
                        items:
                          type: string
                      warehouse_id:
                        type: array
                        items:
                          type: string
                example:
                  message: 'Invalid expiry bucket. Must be one of: expired, 0-30,
                    31-60, 61-90, 91-180, 180+, no_expiry'
                  errors:
                    bucket:
                    - 'Invalid expiry bucket. Must be one of: expired, 0-30, 31-60,
                      61-90, 91-180, 180+, no_expiry'
                    warehouse_id:
                    - The selected warehouse does not exist.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:read
      operationId: get-api-inventory-expiry
    post:
      tags:
      - Inventory Expiry & Shelf-Life
      summary: Get Expiry & Shelf-Life Report (POST, Advanced Filters)
      description: 'POST variant of the expiry report. Mirrors every GET filter and
        additionally carries the larger product advanced-filter tree (filter_groups)
        in the request body.


        Authentication: Requires Bearer token. Scope: reports:read.


        Product advanced-filter tree (GroupedFilterSupport). POSTed in the body to
        carry larger filter sets than the query string allows; bridged into the report
        via a products.id subquery.


        Structure: { conjunction: ''and''|''or'', children: [ { type: ''condition'',
        condition: { column, operator, value } } | { type: ''group'', group: {…} }
        ] } (groups may nest).


        Allowed columns: sku, name, barcode, mpn, type (text); brand_name, supplier_name,
        category, tag (relationship text); shelf_life_days, near_expiry_threshold_days
        (numeric).

        Text operators: contains, does_not_contain, is, is_not, is_one_of, starts_with,
        does_not_start_with, ends_with, does_not_end_with, is_empty, is_not_empty.

        Numeric operators: is, is_not, is_one_of, greater_than, less_than, greater_than_or_equal,
        less_than_or_equal, between, is_empty, is_not_empty.

        Legacy { filters: { conjunction, filterSet } } format is also accepted for
        backward compatibility.


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                view:
                  type: string
                bucket:
                  type: string
                warehouse_id:
                  type: integer
                near_expiry_only:
                  type: boolean
                filter_groups:
                  type: object
                  properties:
                    conjunction:
                      type: string
                    children:
                      type: array
                      items:
                        type: object
                        properties:
                          type:
                            type: string
                          condition:
                            type: object
                            properties:
                              column:
                                type: string
                              operator:
                                type: string
                              value:
                                type: string
                page:
                  type: integer
                per_page:
                  type: integer
              example:
                view: lot_detail
                bucket: 0-30
                warehouse_id: 1
                near_expiry_only: true
                filter_groups:
                  conjunction: and
                  children:
                  - type: condition
                    condition:
                      column: brand_name
                      operator: is
                      value: Acme
                  - type: group
                    group:
                      conjunction: or
                      children:
                      - type: condition
                        condition:
                          column: shelf_life_days
                          operator: less_than
                          value: 365
                      - type: condition
                        condition:
                          column: category
                          operator: contains
                          value: Supplement
                page: 1
                per_page: 50
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        fifo_layer_id:
                          type: integer
                        product_id:
                          type: integer
                        sku:
                          type: string
                        product_name:
                          type: string
                        brand_name:
                          type: string
                        brand_id:
                          type: integer
                        supplier_name:
                          type: string
                        warehouse_id:
                          type: integer
                        warehouse_name:
                          type: string
                        bucket:
                          type: string
                        days_to_expiry:
                          type: integer
                        expiry_date:
                          type: string
                        manufacture_date:
                          type: string
                        batch_number:
                          type: string
                        shelf_life_remaining_pct:
                          type: number
                        link_type:
                          type: string
                        link_type_name:
                          type: string
                        link_id:
                          type: integer
                        quantity:
                          type: number
                        avg_unit_cost:
                          type: number
                        total_value:
                          type: number
                        valuation_source:
                          type: string
                        is_fba:
                          type: boolean
                        review_status:
                          type: string
                        review_status_label:
                          type: string
                        review_notes:
                          type: string
                          nullable: true
                        reviewed_at:
                          type: string
                          nullable: true
                        reviewed_by_name:
                          type: string
                          nullable: true
                        inventory_hold_id:
                          type: string
                          nullable: true
                  per_page:
                    type: integer
                  total:
                    type: integer
                  last_page:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - fifo_layer_id: 8842
                    product_id: 42
                    sku: VIT-D3-1000
                    product_name: Vitamin D3 1000 IU
                    brand_name: Acme
                    brand_id: 3
                    supplier_name: Wellness Distributors
                    warehouse_id: 1
                    warehouse_name: Main Warehouse
                    bucket: 0-30
                    days_to_expiry: 18
                    expiry_date: '2026-07-04T00:00:00.000000Z'
                    manufacture_date: '2024-07-04T00:00:00.000000Z'
                    batch_number: LOT-2026-01
                    shelf_life_remaining_pct: 2.5
                    link_type: App\Models\PurchaseOrderLine
                    link_type_name: Purchase Order Line
                    link_id: 5521
                    quantity: 120.0
                    avg_unit_cost: 8.5
                    total_value: 1020.0
                    valuation_source: internal
                    is_fba: false
                    review_status: open
                    review_status_label: Open
                    review_notes: null
                    reviewed_at: null
                    reviewed_by_name: null
                    inventory_hold_id: null
                  per_page: 50
                  total: 137
                  last_page: 3
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      bucket:
                        type: array
                        items:
                          type: string
                      warehouse_id:
                        type: array
                        items:
                          type: string
                example:
                  message: 'Invalid expiry bucket. Must be one of: expired, 0-30,
                    31-60, 61-90, 91-180, 180+, no_expiry'
                  errors:
                    bucket:
                    - 'Invalid expiry bucket. Must be one of: expired, 0-30, 31-60,
                      61-90, 91-180, 180+, no_expiry'
                    warehouse_id:
                    - The selected warehouse does not exist.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:read
      operationId: post-api-inventory-expiry
  /api/inventory-expiry/metrics:
    get:
      tags:
      - Inventory Expiry & Shelf-Life
      summary: Get Expiry Metrics
      description: 'Summary metric cards for the expiry dashboard: total tracked value,
        expired value, value expiring within 30/60/90 days, at-risk and expired lot
        counts, the Amazon auto-disposal-risk value (FBA lots within Amazon''s 50-day
        disposal window), and per-bucket value/quantity/percentage breakdowns.


        Honours the same filters as the report (GET query string or POST filter_groups
        body).


        Authentication: Requires Bearer token. Scope: reports:read.


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  total_tracked_value:
                    type: number
                  expired_value:
                    type: number
                  value_within_30_days:
                    type: number
                  value_within_60_days:
                    type: number
                  value_within_90_days:
                    type: number
                  at_risk_lot_count:
                    type: integer
                  expired_lot_count:
                    type: integer
                  amazon_disposal_risk_value:
                    type: number
                  value_by_bucket:
                    type: object
                    properties:
                      expired:
                        type: number
                      0-30:
                        type: number
                      31-60:
                        type: number
                      61-90:
                        type: number
                      91-180:
                        type: number
                      180+:
                        type: number
                      no_expiry:
                        type: number
                  quantity_by_bucket:
                    type: object
                    properties:
                      expired:
                        type: integer
                      0-30:
                        type: integer
                      31-60:
                        type: integer
                      61-90:
                        type: integer
                      91-180:
                        type: integer
                      180+:
                        type: integer
                      no_expiry:
                        type: integer
                  percentage_by_bucket:
                    type: object
                    properties:
                      expired:
                        type: number
                      0-30:
                        type: number
                      31-60:
                        type: number
                      61-90:
                        type: number
                      91-180:
                        type: number
                      180+:
                        type: number
                      no_expiry:
                        type: number
                example:
                  total_tracked_value: 184920.5
                  expired_value: 4210.0
                  value_within_30_days: 12040.0
                  value_within_60_days: 28110.0
                  value_within_90_days: 41880.0
                  at_risk_lot_count: 63
                  expired_lot_count: 9
                  amazon_disposal_risk_value: 7300.0
                  value_by_bucket:
                    expired: 4210.0
                    0-30: 12040.0
                    31-60: 16070.0
                    61-90: 13770.0
                    91-180: 38900.0
                    180+: 99930.5
                    no_expiry: 0.0
                  quantity_by_bucket:
                    expired: 540
                    0-30: 1420
                    31-60: 1890
                    61-90: 1620
                    91-180: 4580
                    180+: 11760
                    no_expiry: 0
                  percentage_by_bucket:
                    expired: 2.3
                    0-30: 6.5
                    31-60: 8.7
                    61-90: 7.4
                    91-180: 21.0
                    180+: 54.0
                    no_expiry: 0.0
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:read
      operationId: get-api-inventory-expiry-metrics
    post:
      tags:
      - Inventory Expiry & Shelf-Life
      summary: Get Expiry Metrics (POST, Advanced Filters)
      description: 'POST variant of the metric cards — same response as the GET, with
        the product advanced-filter tree in the body.


        Authentication: Requires Bearer token. Scope: reports:read.


        Product advanced-filter tree (GroupedFilterSupport). POSTed in the body to
        carry larger filter sets than the query string allows; bridged into the report
        via a products.id subquery.


        Structure: { conjunction: ''and''|''or'', children: [ { type: ''condition'',
        condition: { column, operator, value } } | { type: ''group'', group: {…} }
        ] } (groups may nest).


        Allowed columns: sku, name, barcode, mpn, type (text); brand_name, supplier_name,
        category, tag (relationship text); shelf_life_days, near_expiry_threshold_days
        (numeric).

        Text operators: contains, does_not_contain, is, is_not, is_one_of, starts_with,
        does_not_start_with, ends_with, does_not_end_with, is_empty, is_not_empty.

        Numeric operators: is, is_not, is_one_of, greater_than, less_than, greater_than_or_equal,
        less_than_or_equal, between, is_empty, is_not_empty.

        Legacy { filters: { conjunction, filterSet } } format is also accepted for
        backward compatibility.


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                filter_groups:
                  type: object
                  properties:
                    conjunction:
                      type: string
                    children:
                      type: array
                      items:
                        type: object
                        properties:
                          type:
                            type: string
                          condition:
                            type: object
                            properties:
                              column:
                                type: string
                              operator:
                                type: string
                              value:
                                type: string
              example:
                filter_groups:
                  conjunction: and
                  children:
                  - type: condition
                    condition:
                      column: brand_name
                      operator: is
                      value: Acme
                  - type: group
                    group:
                      conjunction: or
                      children:
                      - type: condition
                        condition:
                          column: shelf_life_days
                          operator: less_than
                          value: 365
                      - type: condition
                        condition:
                          column: category
                          operator: contains
                          value: Supplement
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  total_tracked_value:
                    type: number
                  expired_value:
                    type: number
                  value_within_30_days:
                    type: number
                  value_within_60_days:
                    type: number
                  value_within_90_days:
                    type: number
                  at_risk_lot_count:
                    type: integer
                  expired_lot_count:
                    type: integer
                  amazon_disposal_risk_value:
                    type: number
                  value_by_bucket:
                    type: object
                    properties:
                      expired:
                        type: number
                      0-30:
                        type: number
                      31-60:
                        type: number
                      61-90:
                        type: number
                      91-180:
                        type: number
                      180+:
                        type: number
                      no_expiry:
                        type: number
                  quantity_by_bucket:
                    type: object
                    properties:
                      expired:
                        type: integer
                      0-30:
                        type: integer
                      31-60:
                        type: integer
                      61-90:
                        type: integer
                      91-180:
                        type: integer
                      180+:
                        type: integer
                      no_expiry:
                        type: integer
                  percentage_by_bucket:
                    type: object
                    properties:
                      expired:
                        type: number
                      0-30:
                        type: number
                      31-60:
                        type: number
                      61-90:
                        type: number
                      91-180:
                        type: number
                      180+:
                        type: number
                      no_expiry:
                        type: number
                example:
                  total_tracked_value: 184920.5
                  expired_value: 4210.0
                  value_within_30_days: 12040.0
                  value_within_60_days: 28110.0
                  value_within_90_days: 41880.0
                  at_risk_lot_count: 63
                  expired_lot_count: 9
                  amazon_disposal_risk_value: 7300.0
                  value_by_bucket:
                    expired: 4210.0
                    0-30: 12040.0
                    31-60: 16070.0
                    61-90: 13770.0
                    91-180: 38900.0
                    180+: 99930.5
                    no_expiry: 0.0
                  quantity_by_bucket:
                    expired: 540
                    0-30: 1420
                    31-60: 1890
                    61-90: 1620
                    91-180: 4580
                    180+: 11760
                    no_expiry: 0
                  percentage_by_bucket:
                    expired: 2.3
                    0-30: 6.5
                    31-60: 8.7
                    61-90: 7.4
                    91-180: 21.0
                    180+: 54.0
                    no_expiry: 0.0
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: reports:read
      operationId: post-api-inventory-expiry-metrics
  /api/inventory-expiry/distribution:
    get:
      tags:
      - Inventory Expiry & Shelf-Life
      summary: Get Expiry Distribution
      description: 'Expiry bucket distribution for charts — one entry per bucket (in
        display order) with quantity, value, percentage-of-total-value, label and
        colour. Honours the same filters as the report.


        Authentication: Requires Bearer token. Scope: reports:read.


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: array
                items:
                  type: object
                  properties:
                    bucket:
                      type: string
                    label:
                      type: string
                    quantity:
                      type: integer
                    value:
                      type: number
                    percentage:
                      type: number
                    color:
                      type: string
                example:
                - bucket: expired
                  label: Expired
                  quantity: 540
                  value: 4210.0
                  percentage: 2.3
                  color: '#F44336'
                - bucket: 0-30
                  label: 0–30 days
                  quantity: 1420
                  value: 12040.0
                  percentage: 6.5
                  color: '#FF5722'
                - bucket: 31-60
                  label: 31–60 days
                  quantity: 1890
                  value: 16070.0
                  percentage: 8.7
                  color: '#FF9800'
                - bucket: 61-90
                  label: 61–90 days
                  quantity: 1620
                  value: 13770.0
                  percentage: 7.4
                  color: '#FFC107'
                - bucket: 91-180
                  label: 91–180 days
                  quantity: 4580
                  value: 38900.0
                  percentage: 21.0
                  color: '#8BC34A'
                - bucket: 180+
                  label: 180+ days
                  quantity: 11760
                  value: 99930.5
                  percentage: 54.0
                  color: '#4CAF50'
                - bucket: no_expiry
                  label: No expiry
                  quantity: 0
                  value: 0.0
                  percentage: 0.0
                  color: '#9E9E9E'
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:read
      operationId: get-api-inventory-expiry-distribution
    post:
      tags:
      - Inventory Expiry & Shelf-Life
      summary: Get Expiry Distribution (POST, Advanced Filters)
      description: 'POST variant of the bucket distribution — same response as the
        GET, with the product advanced-filter tree in the body.


        Authentication: Requires Bearer token. Scope: reports:read.


        Product advanced-filter tree (GroupedFilterSupport). POSTed in the body to
        carry larger filter sets than the query string allows; bridged into the report
        via a products.id subquery.


        Structure: { conjunction: ''and''|''or'', children: [ { type: ''condition'',
        condition: { column, operator, value } } | { type: ''group'', group: {…} }
        ] } (groups may nest).


        Allowed columns: sku, name, barcode, mpn, type (text); brand_name, supplier_name,
        category, tag (relationship text); shelf_life_days, near_expiry_threshold_days
        (numeric).

        Text operators: contains, does_not_contain, is, is_not, is_one_of, starts_with,
        does_not_start_with, ends_with, does_not_end_with, is_empty, is_not_empty.

        Numeric operators: is, is_not, is_one_of, greater_than, less_than, greater_than_or_equal,
        less_than_or_equal, between, is_empty, is_not_empty.

        Legacy { filters: { conjunction, filterSet } } format is also accepted for
        backward compatibility.


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                filter_groups:
                  type: object
                  properties:
                    conjunction:
                      type: string
                    children:
                      type: array
                      items:
                        type: object
                        properties:
                          type:
                            type: string
                          condition:
                            type: object
                            properties:
                              column:
                                type: string
                              operator:
                                type: string
                              value:
                                type: string
              example:
                filter_groups:
                  conjunction: and
                  children:
                  - type: condition
                    condition:
                      column: brand_name
                      operator: is
                      value: Acme
                  - type: group
                    group:
                      conjunction: or
                      children:
                      - type: condition
                        condition:
                          column: shelf_life_days
                          operator: less_than
                          value: 365
                      - type: condition
                        condition:
                          column: category
                          operator: contains
                          value: Supplement
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: array
                items:
                  type: object
                  properties:
                    bucket:
                      type: string
                    label:
                      type: string
                    quantity:
                      type: integer
                    value:
                      type: number
                    percentage:
                      type: number
                    color:
                      type: string
                example:
                - bucket: expired
                  label: Expired
                  quantity: 540
                  value: 4210.0
                  percentage: 2.3
                  color: '#F44336'
                - bucket: 0-30
                  label: 0–30 days
                  quantity: 1420
                  value: 12040.0
                  percentage: 6.5
                  color: '#FF5722'
                - bucket: 31-60
                  label: 31–60 days
                  quantity: 1890
                  value: 16070.0
                  percentage: 8.7
                  color: '#FF9800'
                - bucket: 61-90
                  label: 61–90 days
                  quantity: 1620
                  value: 13770.0
                  percentage: 7.4
                  color: '#FFC107'
                - bucket: 91-180
                  label: 91–180 days
                  quantity: 4580
                  value: 38900.0
                  percentage: 21.0
                  color: '#8BC34A'
                - bucket: 180+
                  label: 180+ days
                  quantity: 11760
                  value: 99930.5
                  percentage: 54.0
                  color: '#4CAF50'
                - bucket: no_expiry
                  label: No expiry
                  quantity: 0
                  value: 0.0
                  percentage: 0.0
                  color: '#9E9E9E'
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: reports:read
      operationId: post-api-inventory-expiry-distribution
  /api/inventory-expiry/export:
    get:
      tags:
      - Inventory Expiry & Shelf-Life
      summary: Export Expiry Report (async)
      description: 'Starts an asynchronous CSV export of the expiry report (lot-detail
        or product-summary view).


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        The export runs as a tray-tracked job: a full lot-detail export can run for
        minutes, and a synchronous response that long is terminated by the edge proxy
        (Cloudflare 524). The CSV is built off the request cycle, written to the model-exports
        disk, and surfaced as a download via the tracked job log endpoints.


        Returns the tracked job log id; poll the tracked job log endpoints (or GET
        /api/export/download?file=...) for the finished file.


        Authentication: Requires Bearer token (scope reports:read). Accepts the same
        filters as the report endpoint (view, warehouse_id, search, batch_number,
        bucket, brand_id, supplier_id, min_quantity, fba_only, near_expiry_only, and
        the advanced filter_groups tree on the POST variant).'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 12345
                  message: Export started — track progress in the job tray.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:read
      operationId: get-api-inventory-expiry-export
    post:
      tags:
      - Inventory Expiry & Shelf-Life
      summary: Export Expiry Report (async, POST + filter_groups)
      description: 'Starts an asynchronous CSV export of the expiry report (lot-detail
        or product-summary view).


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        The export runs as a tray-tracked job: a full lot-detail export can run for
        minutes, and a synchronous response that long is terminated by the edge proxy
        (Cloudflare 524). The CSV is built off the request cycle, written to the model-exports
        disk, and surfaced as a download via the tracked job log endpoints.


        Returns the tracked job log id; poll the tracked job log endpoints (or GET
        /api/export/download?file=...) for the finished file.


        Authentication: Requires Bearer token (scope reports:read). Accepts the same
        filters as the report endpoint (view, warehouse_id, search, batch_number,
        bucket, brand_id, supplier_id, min_quantity, fba_only, near_expiry_only, and
        the advanced filter_groups tree on the POST variant).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                view:
                  type: string
                filter_groups:
                  type: object
                  properties:
                    conjunction:
                      type: string
                    children:
                      type: array
                      items:
                        type: object
                        properties:
                          type:
                            type: string
                          condition:
                            type: object
                            properties:
                              column:
                                type: string
                              operator:
                                type: string
                              value:
                                type: string
              example:
                view: lot_detail
                filter_groups:
                  conjunction: and
                  children:
                  - type: condition
                    condition:
                      column: brand_name
                      operator: is
                      value: Acme
                  - type: group
                    group:
                      conjunction: or
                      children:
                      - type: condition
                        condition:
                          column: shelf_life_days
                          operator: less_than
                          value: 365
                      - type: condition
                        condition:
                          column: category
                          operator: contains
                          value: Supplement
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 12345
                  message: Export started — track progress in the job tray.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: reports:read
      operationId: post-api-inventory-expiry-export
  /api/inventory-expiry/alert-count:
    get:
      tags:
      - Inventory Expiry & Shelf-Life
      summary: Get Actionable Lot Count
      description: 'Lightweight count of lot-tracked lots that are expired or within
        their near-expiry threshold and still need attention (no review record yet,
        or one left "open"). Acknowledged, quarantined and written-off lots drop out.
        Powers the navigation badge.


        Authentication: Requires Bearer token. Scope: reports:read.


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      actionable_lot_count:
                        type: integer
                example:
                  data:
                    actionable_lot_count: 63
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:read
      operationId: get-api-inventory-expiry-alert-count
  /api/inventory-expiry/alert-summary:
    get:
      tags:
      - Inventory Expiry & Shelf-Life
      summary: Get Near-Expiry Alert Summary
      description: 'Near-expiry alert summary for the report-header risk banner and
        the daily digest: expired and near-expiry lot counts/values (threshold-aware
        per product), the Amazon auto-disposal-risk value, the actionable (needs-review)
        lot count, and the highest-value at-risk products (worst-case first).


        Authentication: Requires Bearer token. Scope: reports:read.


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      expired_lot_count:
                        type: integer
                      expired_value:
                        type: number
                      near_expiry_lot_count:
                        type: integer
                      near_expiry_value:
                        type: number
                      amazon_disposal_risk_value:
                        type: number
                      actionable_lot_count:
                        type: integer
                      top_products:
                        type: array
                        items:
                          type: object
                          properties:
                            product_id:
                              type: integer
                            sku:
                              type: string
                            product_name:
                              type: string
                            soonest_days_to_expiry:
                              type: integer
                            at_risk_quantity:
                              type: number
                            at_risk_value:
                              type: number
                example:
                  data:
                    expired_lot_count: 9
                    expired_value: 4210.0
                    near_expiry_lot_count: 54
                    near_expiry_value: 24080.0
                    amazon_disposal_risk_value: 7300.0
                    actionable_lot_count: 63
                    top_products:
                    - product_id: 42
                      sku: VIT-D3-1000
                      product_name: Vitamin D3 1000 IU
                      soonest_days_to_expiry: 18
                      at_risk_quantity: 120.0
                      at_risk_value: 1020.0
                    - product_id: 77
                      sku: FISH-OIL-500
                      product_name: Fish Oil 500mg
                      soonest_days_to_expiry: -3
                      at_risk_quantity: 80.0
                      at_risk_value: 640.0
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:read
      operationId: get-api-inventory-expiry-alert-summary
  /api/inventory-expiry/lots/{fifoLayer}/write-off:
    post:
      tags:
      - Inventory Expiry & Shelf-Life
      summary: Write Off Lot
      description: 'Write off a lot''s remaining (or partial) quantity via an expired-stock
        DECREASE inventory adjustment (reason: expired). quantity is optional — when
        omitted the layer''s full remaining available quantity is written off; when
        set, only that portion is consumed (partial write-off).


        Authentication: Requires Bearer token. Scope: scope.rw:inventory (write) +
        permission inventory.adjust.


        Path param: fifoLayer — the FIFO layer (lot) id, route-model-bound.


        void_confirmations (array, optional) — when the write-off would consume stock
        that is hard-allocated to a fulfillment with a printed shipping label, list
        one entry per fulfillment to authorize voiding that label and proceeding.
        Omit it and the request is rejected with a 422 conflict if hard-allocated
        stock is in the way.

        void_confirmations[].fulfillment_id (integer, required) — the fulfillment
        whose label may be voided.

        void_confirmations[].attempt_void (boolean, required) — true to void the label
        and consume its stock.

        void_confirmations[].reason (string, optional) — free-text audit note for
        the void.


        :::info[Required scope: `inventory:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                quantity:
                  type: integer
                notes:
                  type: string
                void_confirmations:
                  type: array
                  items:
                    type: object
                    properties:
                      fulfillment_id:
                        type: integer
                      attempt_void:
                        type: boolean
                      reason:
                        type: string
              example:
                quantity: 50
                notes: Past expiry — destroyed on site.
                void_confirmations:
                - fulfillment_id: 77120
                  attempt_void: true
                  reason: Customer cancelled after the label was printed
      parameters:
      - name: fifoLayer
        in: path
        schema:
          type: string
        required: true
        description: The fifo layer ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      fifo_layer_id:
                        type: integer
                      status:
                        type: string
                      status_label:
                        type: string
                      notes:
                        type: string
                      inventory_hold_id:
                        type: string
                        nullable: true
                      reviewed_at:
                        type: string
                      reviewed_by:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      fifo_layer:
                        type: object
                        properties:
                          id:
                            type: integer
                          available_quantity:
                            type: number
                          batch_number:
                            type: string
                          expiry_date:
                            type: string
                example:
                  data:
                    id: 301
                    fifo_layer_id: 8842
                    status: written_off
                    status_label: Written Off
                    notes: Past expiry — destroyed on site.
                    inventory_hold_id: null
                    reviewed_at: '2026-06-16T14:32:10+00:00'
                    reviewed_by:
                      id: 4
                      name: Dana Ops
                    fifo_layer:
                      id: 8842
                      available_quantity: 0.0
                      batch_number: LOT-2026-01
                      expiry_date: '2026-07-04'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 422 Logic Error
                  value:
                    error: This lot has no remaining quantity to write off.
                example-1:
                  summary: 422 Validation Error
                  value:
                    message: The write-off quantity must be greater than zero.
                    errors:
                      quantity:
                      - The write-off quantity must be greater than zero.
                example-2:
                  summary: 422 Conflict — Hard-Allocated Stock
                  value:
                    message: Cannot decrease 5 units. Only 3 available after protecting
                      2 hard-allocated units and 0 active hold units.
                    conflict:
                      requested_quantity: 5
                      available_quantity: 3
                      protected_quantity: 2
                      conflicting_allocations:
                      - type: shipping_label
                        id: 88240
                        reference: SO-10450
                        quantity_allocated: 2
                        line_details:
                          fulfillment_id: 77120
                          fulfillment_status: label_purchased
                          tracking_number: 1Z999AA10123456784
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: inventory:write
      operationId: post-api-inventory-expiry-lots-fifolayer-write-off
  /api/inventory-expiry/lots/{fifoLayer}/quarantine:
    post:
      tags:
      - Inventory Expiry & Shelf-Life
      summary: Quarantine Lot
      description: 'Quarantine a lot — remove its quantity from available-to-promise
        via a reversible inventory hold (no stock movement). quantity is optional
        — when omitted the layer''s full remaining available quantity is held. Returns
        the review record including the inventory_hold_id.


        Authentication: Requires Bearer token. Scope: scope.rw:inventory (write) +
        permission inventory.adjust.


        Path param: fifoLayer — the FIFO layer (lot) id, route-model-bound.


        :::info[Required scope: `inventory:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                quantity:
                  type: integer
                notes:
                  type: string
              example:
                quantity: 120
                notes: Hold pending QA inspection.
      parameters:
      - name: fifoLayer
        in: path
        schema:
          type: string
        required: true
        description: The fifo layer ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      fifo_layer_id:
                        type: integer
                      status:
                        type: string
                      status_label:
                        type: string
                      notes:
                        type: string
                      inventory_hold_id:
                        type: integer
                      reviewed_at:
                        type: string
                      reviewed_by:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      fifo_layer:
                        type: object
                        properties:
                          id:
                            type: integer
                          available_quantity:
                            type: number
                          batch_number:
                            type: string
                          expiry_date:
                            type: string
                example:
                  data:
                    id: 302
                    fifo_layer_id: 8842
                    status: quarantined
                    status_label: Quarantined
                    notes: Hold pending QA inspection.
                    inventory_hold_id: 1190
                    reviewed_at: '2026-06-16T14:35:02+00:00'
                    reviewed_by:
                      id: 4
                      name: Dana Ops
                    fifo_layer:
                      id: 8842
                      available_quantity: 120.0
                      batch_number: LOT-2026-01
                      expiry_date: '2026-07-04'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 422 Insufficient Stock
                  value:
                    error: Not enough available quantity to quarantine.
                example-1:
                  summary: 422 Validation Error
                  value:
                    message: The quarantine quantity must be greater than zero.
                    errors:
                      quantity:
                      - The quarantine quantity must be greater than zero.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: inventory:write
      operationId: post-api-inventory-expiry-lots-fifolayer-quarantine
  /api/inventory-expiry/lots/{fifoLayer}/release-quarantine:
    post:
      tags:
      - Inventory Expiry & Shelf-Life
      summary: Release Quarantine
      description: 'Release a lot from quarantine — return the held quantity to available-to-promise
        by lifting the inventory hold. No request body. The lot''s review status returns
        to open.


        Authentication: Requires Bearer token. Scope: scope.rw:inventory (write) +
        permission inventory.adjust.


        Path param: fifoLayer — the FIFO layer (lot) id, route-model-bound.


        :::info[Required scope: `inventory:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters:
      - name: fifoLayer
        in: path
        schema:
          type: string
        required: true
        description: The fifo layer ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      fifo_layer_id:
                        type: integer
                      status:
                        type: string
                      status_label:
                        type: string
                      notes:
                        type: string
                      inventory_hold_id:
                        type: string
                        nullable: true
                      reviewed_at:
                        type: string
                      reviewed_by:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      fifo_layer:
                        type: object
                        properties:
                          id:
                            type: integer
                          available_quantity:
                            type: number
                          batch_number:
                            type: string
                          expiry_date:
                            type: string
                example:
                  data:
                    id: 302
                    fifo_layer_id: 8842
                    status: open
                    status_label: Open
                    notes: Hold pending QA inspection.
                    inventory_hold_id: null
                    reviewed_at: '2026-06-16T15:01:44+00:00'
                    reviewed_by:
                      id: 4
                      name: Dana Ops
                    fifo_layer:
                      id: 8842
                      available_quantity: 120.0
                      batch_number: LOT-2026-01
                      expiry_date: '2026-07-04'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: This lot is not currently quarantined.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: inventory:write
      operationId: post-api-inventory-expiry-lots-fifolayer-release-quarantine
  /api/inventory-expiry/lots/{fifoLayer}/review-status:
    put:
      tags:
      - Inventory Expiry & Shelf-Life
      summary: Set Lot Review Status
      description: 'Set a lot''s non-stock review disposition (acknowledge a near-expiry
        lot, or re-open it). status is restricted to the bookkeeping states open and
        acknowledged — the stock-mutating dispositions (written_off / quarantined)
        are set only by their dedicated endpoints.


        Authentication: Requires Bearer token. Scope: scope.rw:inventory (write) +
        permission inventory.adjust.


        Path param: fifoLayer — the FIFO layer (lot) id, route-model-bound.


        :::info[Required scope: `inventory:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                status:
                  type: string
                notes:
                  type: string
              example:
                status: acknowledged
                notes: Reviewed — will sell through before expiry.
      parameters:
      - name: fifoLayer
        in: path
        schema:
          type: string
        required: true
        description: The fifo layer ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      fifo_layer_id:
                        type: integer
                      status:
                        type: string
                      status_label:
                        type: string
                      notes:
                        type: string
                      inventory_hold_id:
                        type: string
                        nullable: true
                      reviewed_at:
                        type: string
                      reviewed_by:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      fifo_layer:
                        type: object
                        properties:
                          id:
                            type: integer
                          available_quantity:
                            type: number
                          batch_number:
                            type: string
                          expiry_date:
                            type: string
                example:
                  data:
                    id: 303
                    fifo_layer_id: 8842
                    status: acknowledged
                    status_label: Acknowledged
                    notes: Reviewed — will sell through before expiry.
                    inventory_hold_id: null
                    reviewed_at: '2026-06-16T15:10:00+00:00'
                    reviewed_by:
                      id: 4
                      name: Dana Ops
                    fifo_layer:
                      id: 8842
                      available_quantity: 120.0
                      batch_number: LOT-2026-01
                      expiry_date: '2026-07-04'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      status:
                        type: array
                        items:
                          type: string
                example:
                  message: Review status must be either open or acknowledged. Use
                    the write-off or quarantine actions for stock dispositions.
                  errors:
                    status:
                    - Review status must be either open or acknowledged. Use the write-off
                      or quarantine actions for stock dispositions.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: inventory:write
      operationId: put-api-inventory-expiry-lots-fifolayer-review-status
  /api/inventory-expiry/lots/{fifoLayer}/write-off-impact:
    get:
      tags:
      - Inventory Expiry & Shelf-Life
      summary: Preview Lot Write-Off Impact
      description: 'Preview the demotion and label-void impact of writing off a lot
        before committing the write-off. Read-only — mutates nothing.


        Returns one row per product the write-off would consume stock for. shortfall_quantity
        is how much MORE than available the write-off removes (stock goes negative
        if greater than zero). unallocated_quantity / soft_allocated_quantity / hard_allocated_quantity
        split the consumed quantity into free / soft-reserved / hard-allocated (label-printed).
        affected_allocations[] lists the order allocations that would be consumed,
        highest priority first; allocation_type is soft or hard. For hard rows, fulfillment_id
        / carrier identify the printed shipping label and carrier_void_supported /
        voidable_status (voidable, or otherwise) indicate whether it can be voided
        through the API.


        Authentication: Requires Bearer token. Scope: scope.rw:inventory + permission
        inventory.adjust.


        Path param: fifoLayer — the FIFO layer (lot) id, route-model-bound.

        Query param: quantity (optional) — the portion to write off; omit to preview
        writing off the layer''s full remaining available quantity.'
      parameters:
      - name: fifoLayer
        in: path
        schema:
          type: string
        required: true
        description: The fifo layer ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        product_id:
                          type: integer
                        product_sku:
                          type: string
                        product_name:
                          type: string
                        shortfall_quantity:
                          type: integer
                        unallocated_quantity:
                          type: integer
                        soft_allocated_quantity:
                          type: integer
                        hard_allocated_quantity:
                          type: integer
                        affected_allocations:
                          type: array
                          items:
                            type: object
                            properties:
                              allocation_id:
                                type: integer
                              allocation_type:
                                type: string
                              sales_order_id:
                                type: integer
                              order_number:
                                type: string
                              customer_name:
                                type: string
                              fulfillment_id:
                                type: string
                                nullable: true
                              carrier:
                                type: string
                                nullable: true
                              carrier_void_supported:
                                type: string
                                nullable: true
                              voidable_status:
                                type: string
                                nullable: true
                              voidable_detail:
                                type: string
                                nullable: true
                              quantity:
                                type: integer
                example:
                  data:
                  - product_id: 123
                    product_sku: WIDGET-001
                    product_name: Blue Widget 500ml
                    shortfall_quantity: 0
                    unallocated_quantity: 4
                    soft_allocated_quantity: 3
                    hard_allocated_quantity: 2
                    affected_allocations:
                    - allocation_id: 88213
                      allocation_type: soft
                      sales_order_id: 4521
                      order_number: SO-10442
                      customer_name: Acme Retail
                      fulfillment_id: null
                      carrier: null
                      carrier_void_supported: null
                      voidable_status: null
                      voidable_detail: null
                      quantity: 3
                    - allocation_id: 88240
                      allocation_type: hard
                      sales_order_id: 4530
                      order_number: SO-10450
                      customer_name: Beta Wholesale
                      fulfillment_id: 77120
                      carrier: ups
                      carrier_void_supported: true
                      voidable_status: voidable
                      voidable_detail: null
                      quantity: 2
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-inventory-expiry-lots-fifolayer-write-off-impact
  /api/inventory-expiry/lot-backfill/template:
    get:
      tags:
      - Inventory Expiry & Shelf-Life
      summary: Download Lot Backfill Template (CSV)
      description: 'Download the lot-data backfill CSV template (header row + one
        example row) so uploads start from the exact header layout the importer expects
        (filename: lot-data-backfill-template.csv, Content-Type: text/csv).


        Columns: sku, warehouse, batch, manufacture_date, expiry_date, quantity.


        Authentication: Requires Bearer token. Scope: reports:read.


        This is a file download — the response is CSV text, not JSON.


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: text/csv
          content:
            text/plain:
              schema:
                type: string
                example: sku,warehouse,batch,manufacture_date,expiry_date,quantity\nABC-123,Main
                  Warehouse,LOT-2026-01,2026-01-15,2027-01-15,100\n
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:read
      operationId: get-api-inventory-expiry-lot-backfill-template
  /api/inventory-expiry/lot-backfill:
    post:
      tags:
      - Inventory Expiry & Shelf-Life
      summary: Import Lot Backfill CSV
      description: 'Upload a lot-data backfill CSV (multipart/form-data). The file
        is parsed, then a tray-tracked job is dispatched that splits the named quantities
        off each product''s existing un-lotted FIFO stock into dated lots (cost preserved).
        Returns the tracked_job_log_id so the frontend can follow progress via the
        tracked job log endpoints; per-row outcomes (assigned / partial / skipped
        / failed) are reported in the job summary.


        Body: multipart/form-data with a single file field. Accepted mime: csv, txt.
        Max size: 10 MB.


        Authentication: Requires Bearer token. Scope: scope.rw:inventory (write) +
        permission inventory.adjust.


        :::info[Required scope: `inventory:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                file:
                  type: string
                  description: 'The lot-data backfill CSV file. Required. Accepted
                    mime: csv or txt. Max size: 10240 KB (10 MB). Columns (case-insensitive
                    headers): sku, warehouse, batch, manufacture_date (or mfg), expiry_date
                    (or expiry), quantity (or qty). Dates are date-only in the app
                    timezone, normalized to Y-m-d.'
                  format: binary
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 9921
                  message: Lot data backfill started — track progress in the job tray.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 422 Empty File
                  value:
                    message: The CSV file is empty or unreadable.
                example-1:
                  summary: 422 No Data Rows
                  value:
                    message: The CSV file has no data rows.
                example-2:
                  summary: 422 Validation Error
                  value:
                    message: The file must be a CSV.
                    errors:
                      file:
                      - The file must be a CSV.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: inventory:write
      operationId: post-api-inventory-expiry-lot-backfill
  /api/amazon/list:
    get:
      tags:
      - Amazon
      summary: List Amazon Integration Instances (Simple Dropdown)
      description: 'Simple flat list of all Amazon integration instances suitable
        for use in dropdown selectors and integration filters in the UI. Returns just
        `{id, name}` for each instance with no pagination.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                example:
                  data:
                  - id: 3
                    name: Amazon US - Main
                  - id: 4
                    name: Amazon CA - Secondary
                  - id: 5
                    name: Amazon UK
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-amazon-list
  /api/amazon/{integrationInstance}:
    get:
      tags:
      - Amazon
      summary: Show Amazon Integration Instance
      description: 'Show a single Amazon integration instance with its salesChannel
        and integration relationships eager-loaded. Returns an Amazon integration
        instance object.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Amazon integration instance ID
        example: '3'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      connection_settings:
                        type: object
                        properties:
                          selling_partner_id:
                            type: string
                          refresh_token:
                            type: string
                          access_token:
                            type: string
                      integration_settings:
                        type: object
                        properties:
                          start_date:
                            type: string
                          store_id:
                            type: integer
                          auto_link_products:
                            type: boolean
                          auto_create_products:
                            type: boolean
                          sales_nominal_code_id:
                            type: integer
                          cogs_nominal_code_id:
                            type: integer
                          shipping_revenue_nominal_code_id:
                            type: integer
                          shipping_refund_nominal_code_id:
                            type: integer
                          sales_returns_allowances_nominal_code_id:
                            type: integer
                          is_fba_enabled:
                            type: boolean
                          fba_inventory_tracking_start_date:
                            type: string
                          batch_sales_order_invoices:
                            type: boolean
                          sync_sales_order_invoices_to_accounting:
                            type: boolean
                          sync_sales_credit_to_accounting:
                            type: boolean
                          reconcile_ledger:
                            type: boolean
                          automatically_create_warehouse_transfers_from_inbounds:
                            type: boolean
                          automatically_create_purchase_orders_from_inbounds:
                            type: boolean
                          automatically_create_warehouse_transfers_from_removal_orders:
                            type: boolean
                          awd_initial_inventory_imported:
                            type: boolean
                          awd_initial_inventory_confirmed_no_inventory:
                            type: boolean
                          setup_step:
                            type: string
                          setup_completed:
                            type: boolean
                      is_automatic_sync_enabled:
                        type: boolean
                      sales_channel:
                        type: object
                        properties:
                          id:
                            type: integer
                          store_id:
                            type: integer
                          integration_instance_id:
                            type: integer
                      connection_status:
                        type: string
                      account_status_signal:
                        type: string
                        nullable: true
                      pricing_health_signal:
                        type: string
                        nullable: true
                      fee_promotion_signals:
                        type: array
                      integration_name:
                        type: string
                      store:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 3
                    name: Amazon US - Main
                    connection_settings:
                      selling_partner_id: A1B2C3D4E5F6G7
                      refresh_token: Atzr|IwEBI...
                      access_token: Atza|IwEBI...
                    integration_settings:
                      start_date: '2026-01-01'
                      store_id: 12
                      auto_link_products: true
                      auto_create_products: false
                      sales_nominal_code_id: 200
                      cogs_nominal_code_id: 500
                      shipping_revenue_nominal_code_id: 210
                      shipping_refund_nominal_code_id: 211
                      sales_returns_allowances_nominal_code_id: 215
                      is_fba_enabled: true
                      fba_inventory_tracking_start_date: '2026-01-01'
                      batch_sales_order_invoices: true
                      sync_sales_order_invoices_to_accounting: true
                      sync_sales_credit_to_accounting: true
                      reconcile_ledger: true
                      automatically_create_warehouse_transfers_from_inbounds: false
                      automatically_create_purchase_orders_from_inbounds: false
                      automatically_create_warehouse_transfers_from_removal_orders: false
                      awd_initial_inventory_imported: false
                      awd_initial_inventory_confirmed_no_inventory: false
                      setup_step: finalize
                      setup_completed: true
                    is_automatic_sync_enabled: true
                    sales_channel:
                      id: 9
                      store_id: 12
                      integration_instance_id: 3
                    connection_status: connected
                    account_status_signal: null
                    pricing_health_signal: null
                    fee_promotion_signals: []
                    integration_name: Amazon
                    store:
                      id: 12
                      name: Main Store
                    created_at: '2026-01-15T10:30:00.000000Z'
                    updated_at: '2026-05-20T14:30:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-integrationinstance
    put:
      tags:
      - Amazon
      summary: Update Amazon Integration Instance
      description: 'Full or partial update of an Amazon integration instance. Validated
        by `UpdateAmazonIntegrationData` (all fields Optional). Supports both `PUT`
        (full) and `PATCH` (partial with deep-merge of `integration_settings` / `connection_settings`).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        If `is_fba_enabled` changes, the controller dispatches the FBA state-change
        handler. If `sync_sales_order_invoices_to_accounting` or `sync_sales_credit_to_accounting`
        change, the accounting sync state is updated. If `pricing.masterOfPrice.name`
        changes, a background job is dispatched. If `inventory` changes, the full
        inventory cache is invalidated. If `store_id` changes, the SalesChannel row
        is re-pointed.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                is_automatic_sync_enabled:
                  type: boolean
                connection_settings:
                  type: object
                  properties:
                    selling_partner_id:
                      type: string
                    refresh_token:
                      type: string
                integration_settings:
                  type: object
                  properties:
                    start_date:
                      type: string
                    store_id:
                      type: integer
                    auto_link_products:
                      type: boolean
                    auto_create_products:
                      type: boolean
                    is_fba_enabled:
                      type: boolean
                    fba_inventory_tracking_start_date:
                      type: string
                    batch_sales_order_invoices:
                      type: boolean
                    sync_sales_order_invoices_to_accounting:
                      type: boolean
                    sync_sales_credit_to_accounting:
                      type: boolean
                    reconcile_ledger:
                      type: boolean
              example:
                name: Amazon US - Main (renamed)
                is_automatic_sync_enabled: true
                connection_settings:
                  selling_partner_id: A1B2C3D4E5F6G7
                  refresh_token: Atzr|IwEBI...
                integration_settings:
                  start_date: '2026-01-01'
                  store_id: 12
                  auto_link_products: true
                  auto_create_products: false
                  is_fba_enabled: true
                  fba_inventory_tracking_start_date: '2026-01-01'
                  batch_sales_order_invoices: true
                  sync_sales_order_invoices_to_accounting: true
                  sync_sales_credit_to_accounting: true
                  reconcile_ledger: true
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Amazon integration instance ID
        example: '3'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      is_automatic_sync_enabled:
                        type: boolean
                      connection_settings:
                        type: object
                        properties:
                          selling_partner_id:
                            type: string
                          refresh_token:
                            type: string
                      integration_settings:
                        type: object
                        properties:
                          start_date:
                            type: string
                          store_id:
                            type: integer
                          is_fba_enabled:
                            type: boolean
                          reconcile_ledger:
                            type: boolean
                      connection_status:
                        type: string
                      integration_name:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 3
                    name: Amazon US - Main (renamed)
                    is_automatic_sync_enabled: true
                    connection_settings:
                      selling_partner_id: A1B2C3D4E5F6G7
                      refresh_token: Atzr|IwEBI...
                    integration_settings:
                      start_date: '2026-01-01'
                      store_id: 12
                      is_fba_enabled: true
                      reconcile_ledger: true
                    connection_status: connected
                    integration_name: Amazon
                    created_at: '2026-01-15T10:30:00.000000Z'
                    updated_at: '2026-05-29T12:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-amazon-integrationinstance
    delete:
      tags:
      - Amazon
      summary: Delete Amazon Integration Instance
      description: 'Soft-delete an Amazon integration instance. Dispatches a background
        job to clean up the linked sales channel and related records asynchronously.
        Returns 204 No Content.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Amazon integration instance ID
        example: '3'
      responses:
        '204':
          description: No Content
          content:
            application/json:
              schema:
                type: object
                properties: {}
                example: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-amazon-integrationinstance
  /api/amazon:
    post:
      tags:
      - Amazon
      summary: Create Amazon Integration Instance
      description: 'Create a new Amazon integration instance. Validated by `StoreAmazonIntegrationData`.
        After creation the controller also ensures a PaymentType for Amazon exists,
        then returns the redirect URL the user must follow to authorize the SP-API
        connection.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Fields**

        - `name` (string, required) — display name for this instance

        - `integration_id` (int, required, must exist in `integrations` table) — id
        of the Amazon integration row

        - `country` (string, optional) — ISO country code (e.g. `US`, `CA`, `UK`)

        - `is_automatic_sync_enabled` (bool, default false)

        - `connection_settings` (object, optional) — typically populated by OAuth
        callback

        - `integration_settings` (object, required) — AmazonIntegrationSettingsData
        fields (see show response for available keys)'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                integration_id:
                  type: integer
                country:
                  type: string
                is_automatic_sync_enabled:
                  type: boolean
                connection_settings:
                  type: object
                  properties:
                    selling_partner_id:
                      type: string
                integration_settings:
                  type: object
                  properties:
                    start_date:
                      type: string
                    store_id:
                      type: integer
                    auto_link_products:
                      type: boolean
                    auto_create_products:
                      type: boolean
                    sales_nominal_code_id:
                      type: integer
                    cogs_nominal_code_id:
                      type: integer
                    shipping_revenue_nominal_code_id:
                      type: integer
                    shipping_refund_nominal_code_id:
                      type: integer
                    sales_returns_allowances_nominal_code_id:
                      type: integer
                    is_fba_enabled:
                      type: boolean
                    fba_inventory_tracking_start_date:
                      type: string
                    batch_sales_order_invoices:
                      type: boolean
              example:
                name: Amazon US - Main
                integration_id: 4
                country: US
                is_automatic_sync_enabled: false
                connection_settings:
                  selling_partner_id: A1B2C3D4E5F6G7
                integration_settings:
                  start_date: '2026-01-01'
                  store_id: 12
                  auto_link_products: true
                  auto_create_products: false
                  sales_nominal_code_id: 200
                  cogs_nominal_code_id: 500
                  shipping_revenue_nominal_code_id: 210
                  shipping_refund_nominal_code_id: 211
                  sales_returns_allowances_nominal_code_id: 215
                  is_fba_enabled: true
                  fba_inventory_tracking_start_date: '2026-01-01'
                  batch_sales_order_invoices: true
      parameters: []
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      integration_id:
                        type: integer
                      is_automatic_sync_enabled:
                        type: boolean
                      connection_settings:
                        type: object
                        properties:
                          selling_partner_id:
                            type: string
                      integration_settings:
                        type: object
                        properties:
                          start_date:
                            type: string
                          store_id:
                            type: integer
                          is_fba_enabled:
                            type: boolean
                      created_at:
                        type: string
                      updated_at:
                        type: string
                  redirect_url:
                    type: string
                example:
                  data:
                    id: 3
                    name: Amazon US - Main
                    integration_id: 4
                    is_automatic_sync_enabled: false
                    connection_settings:
                      selling_partner_id: A1B2C3D4E5F6G7
                    integration_settings:
                      start_date: '2026-01-01'
                      store_id: 12
                      is_fba_enabled: true
                    created_at: '2026-05-29T12:00:00.000000Z'
                    updated_at: '2026-05-29T12:00:00.000000Z'
                  redirect_url: https://sellercentral.amazon.com/apps/authorize/consent?application_id=amzn1.sp.solution.xxxx&state=eyJpbnN0YW5jZUlkIjozfQ&version=beta
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-amazon
    get:
      tags:
      - Amazon
      summary: List Amazon Integration Instances
      description: 'List all Amazon integration instances. Registered automatically
        by the `Route::salesChannel(''amazon'', ...)` macro — this is the standard
        `apiResource` index returning the configured list view response (paginated
        Amazon integration instance object collection).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        connection_settings:
                          type: object
                          properties:
                            selling_partner_id:
                              type: string
                            refresh_token:
                              type: string
                            access_token:
                              type: string
                        integration_settings:
                          type: object
                          properties:
                            start_date:
                              type: string
                            store_id:
                              type: integer
                            auto_link_products:
                              type: boolean
                            auto_create_products:
                              type: boolean
                            is_fba_enabled:
                              type: boolean
                            reconcile_ledger:
                              type: boolean
                            batch_sales_order_invoices:
                              type: boolean
                        is_automatic_sync_enabled:
                          type: boolean
                        connection_status:
                          type: string
                        account_status_signal:
                          type: string
                          nullable: true
                        pricing_health_signal:
                          type: string
                          nullable: true
                        fee_promotion_signals:
                          type: array
                        integration_name:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 3
                    name: Amazon US - Main
                    connection_settings:
                      selling_partner_id: A1B2C3D4E5F6G7
                      refresh_token: Atzr|IwEBI...
                      access_token: Atza|IwEBI...
                    integration_settings:
                      start_date: '2026-01-01'
                      store_id: 12
                      auto_link_products: true
                      auto_create_products: false
                      is_fba_enabled: true
                      reconcile_ledger: true
                      batch_sales_order_invoices: true
                    is_automatic_sync_enabled: true
                    connection_status: connected
                    account_status_signal: null
                    pricing_health_signal: null
                    fee_promotion_signals: []
                    integration_name: Amazon
                    created_at: '2026-01-15T10:30:00.000000Z'
                    updated_at: '2026-05-20T14:30:00.000000Z'
                  current_page: 1
                  first_page_url: '{{protocol}}{{domain}}/api/amazon?page=1'
                  from: 1
                  last_page: 1
                  per_page: 10
                  to: 1
                  total: 1
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-amazon
  /api/amazon/{integrationInstance}/settings:
    patch:
      tags:
      - Amazon
      summary: Update Amazon Settings (Partial)
      description: 'Optimized partial update used by the application UI Amazon settings
        page. Validated by `UpdateAmazonSettingsOnlyData` — every field is Optional,
        so the client may send only the fields the user actually changed. Internally,
        root-level fields (`name`, `is_automatic_sync_enabled`) are separated from
        `integration_settings` fields and merged into the existing settings JSON.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Returns the freshly reloaded Amazon integration instance object with `salesChannel.store`
        and `integration` eager-loaded.


        fbmBackup (optional): catalog-wide FBM Backup Mode default { enabled: bool,
        fbaThreshold: int>=0, scope: "same_country"|"all_marketplaces" }. Malformed
        values return 422.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                is_automatic_sync_enabled:
                  type: boolean
                store_id:
                  type: integer
                sales_nominal_code_id:
                  type: integer
                cogs_nominal_code_id:
                  type: integer
                shipping_revenue_nominal_code_id:
                  type: integer
                shipping_refund_nominal_code_id:
                  type: integer
                sales_returns_allowances_nominal_code_id:
                  type: integer
                batch_sales_order_invoices:
                  type: boolean
                sync_sales_order_invoices_to_accounting:
                  type: boolean
                sync_sales_credit_to_accounting:
                  type: boolean
                start_date:
                  type: string
                reconcile_ledger:
                  type: boolean
                pricing:
                  type: object
                  properties:
                    masterOfPrice:
                      type: object
                      properties:
                        name:
                          type: string
                automatically_create_warehouse_transfers_from_inbounds:
                  type: boolean
                automatically_create_purchase_orders_from_inbounds:
                  type: boolean
                automatically_create_warehouse_transfers_from_removal_orders:
                  type: boolean
                inbound_manager_process_error_notification_emails:
                  type: string
                selected_marketplace_ids:
                  type: array
                  items:
                    type: string
                payment_method_mappings:
                  type: array
                  items:
                    type: object
                    properties:
                      amazon_method:
                        type: string
                      payment_type_id:
                        type: integer
                fbmBackup:
                  type: object
                  properties:
                    enabled:
                      type: boolean
                    fbaThreshold:
                      type: integer
                    scope:
                      type: string
              example:
                name: Amazon US - Main
                is_automatic_sync_enabled: true
                store_id: 12
                sales_nominal_code_id: 200
                cogs_nominal_code_id: 500
                shipping_revenue_nominal_code_id: 210
                shipping_refund_nominal_code_id: 211
                sales_returns_allowances_nominal_code_id: 215
                batch_sales_order_invoices: true
                sync_sales_order_invoices_to_accounting: true
                sync_sales_credit_to_accounting: true
                start_date: '2026-01-01'
                reconcile_ledger: true
                pricing:
                  masterOfPrice:
                    name: sku
                automatically_create_warehouse_transfers_from_inbounds: false
                automatically_create_purchase_orders_from_inbounds: false
                automatically_create_warehouse_transfers_from_removal_orders: false
                inbound_manager_process_error_notification_emails: ops@example.com
                selected_marketplace_ids:
                - ATVPDKIKX0DER
                payment_method_mappings:
                - amazon_method: Other
                  payment_type_id: 7
                fbmBackup:
                  enabled: true
                  fbaThreshold: 0
                  scope: same_country
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Amazon integration instance ID
        example: '3'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      connection_settings:
                        type: object
                        properties:
                          selling_partner_id:
                            type: string
                      integration_settings:
                        type: object
                        properties:
                          start_date:
                            type: string
                          store_id:
                            type: integer
                          sales_nominal_code_id:
                            type: integer
                          cogs_nominal_code_id:
                            type: integer
                          shipping_revenue_nominal_code_id:
                            type: integer
                          shipping_refund_nominal_code_id:
                            type: integer
                          sales_returns_allowances_nominal_code_id:
                            type: integer
                          batch_sales_order_invoices:
                            type: boolean
                          sync_sales_order_invoices_to_accounting:
                            type: boolean
                          sync_sales_credit_to_accounting:
                            type: boolean
                          reconcile_ledger:
                            type: boolean
                          pricing:
                            type: object
                            properties:
                              masterOfPrice:
                                type: object
                                properties:
                                  name:
                                    type: string
                          selected_marketplace_ids:
                            type: array
                            items:
                              type: string
                          payment_method_mappings:
                            type: array
                            items:
                              type: object
                              properties:
                                amazon_method:
                                  type: string
                                payment_type_id:
                                  type: integer
                      is_automatic_sync_enabled:
                        type: boolean
                      sales_channel:
                        type: object
                        properties:
                          id:
                            type: integer
                          store_id:
                            type: integer
                          integration_instance_id:
                            type: integer
                      connection_status:
                        type: string
                      integration_name:
                        type: string
                      store:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 3
                    name: Amazon US - Main
                    connection_settings:
                      selling_partner_id: A1B2C3D4E5F6G7
                    integration_settings:
                      start_date: '2026-01-01'
                      store_id: 12
                      sales_nominal_code_id: 200
                      cogs_nominal_code_id: 500
                      shipping_revenue_nominal_code_id: 210
                      shipping_refund_nominal_code_id: 211
                      sales_returns_allowances_nominal_code_id: 215
                      batch_sales_order_invoices: true
                      sync_sales_order_invoices_to_accounting: true
                      sync_sales_credit_to_accounting: true
                      reconcile_ledger: true
                      pricing:
                        masterOfPrice:
                          name: sku
                      selected_marketplace_ids:
                      - ATVPDKIKX0DER
                      payment_method_mappings:
                      - amazon_method: Other
                        payment_type_id: 7
                    is_automatic_sync_enabled: true
                    sales_channel:
                      id: 9
                      store_id: 12
                      integration_instance_id: 3
                    connection_status: connected
                    integration_name: Amazon
                    store:
                      id: 12
                      name: Main Store
                    created_at: '2026-01-15T10:30:00.000000Z'
                    updated_at: '2026-05-29T12:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: patch-api-amazon-integrationinstance-settings
  /amazon/callback:
    get:
      tags:
      - Amazon
      summary: OAuth Callback (Web)
      description: 'Amazon Seller Central OAuth callback endpoint. Amazon redirects
        the user here after they grant or deny SP-API access in Seller Central. This
        endpoint is a **web** route (not under `/api`), is invoked by the user''s
        browser (not by SKU.io frontend code), and accepts any HTTP method (`Route::any`).


        Flow:

        1. Validates the presence of `spapi_oauth_code` and `state` query params (400
        if missing).

        2. Re-initializes tenancy from the `state` value.

        3. Loads the matching `AmazonIntegrationInstance` and exchanges the auth code
        for an access/refresh token via the Amazon SP-API connector.

        4. Persists the authenticator + `selling_partner_id` and marks the integration
        instance `sync_status = ACTIVE` and `is_automatic_sync_enabled = true`.

        5. Performs initial setup calls when not in fake-OAuth mode: fetches marketplace
        participations, requests initial reports, processes FBA state, and dispatches
        the initial Financial Event Groups + Orders refresh jobs onto the `serial`
        queue.

        6. Redirects the browser to `/integrations/amazon/{integrationInstanceId}/dashboard`.


        The response is a 302 redirect to the Vue 2/application UI Amazon integration
        dashboard for the instance — there is no JSON payload.'
      parameters:
      - name: state
        in: query
        schema:
          type: string
        description: Opaque OAuth state token built by SKU.io when generating the
          authorization URL. Contains the tenant identifier and the integration instance
          ID, e.g. `<tenant>_<integration_instance_id>`. Used to validate the callback
          origin and re-initialize tenancy.
        example: tenant1_1
      - name: spapi_oauth_code
        in: query
        schema:
          type: string
        description: Single-use authorization code issued by Amazon LWA. Exchanged
          server-side for a refresh + access token pair.
        example: ANabcDEFghiJKLmnoPQR
      - name: selling_partner_id
        in: query
        schema:
          type: string
        description: The Amazon Seller Central account identifier (merchant token)
          of the seller who completed the OAuth consent flow. Persisted onto the integration
          instance connection settings.
        example: A1XYZ123EXAMPLE
      responses:
        '302':
          description: Found
          headers:
            Location:
              schema:
                type: string
                example: /integrations/amazon/1/dashboard
          content:
            text/plain:
              schema:
                type: string
                example: ''
        '400':
          description: Bad Request
          content:
            text/plain:
              schema:
                type: string
              examples:
                example-0:
                  summary: Missing code
                  value: Missing code
                example-1:
                  summary: Missing state
                  value: Missing state
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-amazon-callback
  /api/amazon/{integrationInstance}/get-authorization-url:
    get:
      tags:
      - Amazon
      summary: Get Authorization URL
      description: 'Returns the Amazon Seller Central OAuth authorization URL for
        the given Amazon integration instance. The frontend should redirect the user
        to this URL so they can grant SP-API access to SKU.io. Upon successful authorization,
        Amazon redirects the user back to the configured callback URL with `spapi_oauth_code`,
        `state`, and `selling_partner_id` query parameters.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        When `FakeOAuthService` is enabled in non-production environments, a fake
        OAuth URL is returned to allow the OAuth handshake to be tested end-to-end
        without contacting Amazon.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: The ID of the Amazon integration instance for which to build
          the Amazon Seller Central OAuth authorization URL.
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: string
                  errors:
                    type: array
                  messages:
                    type: array
                  success:
                    type: boolean
                example:
                  data: https://sellercentral.amazon.com/apps/authorize/consent?application_id=amzn1.sp.solution.example-app-id&state=tenant1_1&version=beta
                  errors: []
                  messages: []
                  success: true
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-integrationinstance-get-authorization-url
  /api/amazon/unified/fee-mappings:
    get:
      tags:
      - Amazon
      summary: List Fee Mappings
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        example: '1'
        description: Page number (default 1).
      - name: per_page
        in: query
        schema:
          type: integer
        example: '10'
        description: Results per page (default 10).
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      description: 'List Fee Mappings


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      operationId: get-api-amazon-unified-fee-mappings
    post:
      tags:
      - Amazon
      summary: Create Fee Mapping
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                fee_type:
                  type: string
                financial_line_type_id:
                  type: string
                  nullable: true
              example:
                fee_type: ''
                financial_line_type_id: null
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      description: 'Create Fee Mapping


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      operationId: post-api-amazon-unified-fee-mappings
  /api/amazon/unified/fee-mappings/{feeMapping}:
    patch:
      tags:
      - Amazon
      summary: Update Fee Mapping
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                financial_line_type_id:
                  type: string
                  nullable: true
              example:
                financial_line_type_id: null
      parameters:
      - name: feeMapping
        in: path
        schema:
          type: string
        required: true
        description: The fee mapping ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      description: 'Update Fee Mapping


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      operationId: patch-api-amazon-unified-fee-mappings-feemapping
    delete:
      tags:
      - Amazon
      summary: Delete Fee Mapping
      parameters:
      - name: feeMapping
        in: path
        schema:
          type: string
        required: true
        description: The fee mapping ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      description: 'Delete Fee Mapping


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      operationId: delete-api-amazon-unified-fee-mappings-feemapping
  /api/amazon/unified/fee-mappings/recategorize-historical/preview:
    get:
      tags:
      - Amazon
      summary: Preview Recategorization
      description: 'Preview the impact of recategorizing historical settlement data
        based on current fee mappings (dry-run).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      affected_count:
                        type: integer
                      fee_types:
                        type: array
                        items:
                          type: string
                example:
                  data:
                    affected_count: 152
                    fee_types:
                    - FBAPerUnitFulfillmentFee
                    - Commission
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-amazon-unified-fee-mappings-recategorize-historical-preview
  /api/amazon/unified/fee-mappings/recategorize-historical:
    post:
      tags:
      - Amazon
      summary: Recategorize Historical
      description: 'Recategorize historical settlement data based on current fee mappings.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties: {}
              example: {}
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      updated_count:
                        type: integer
                example:
                  message: Historical recategorization complete
                  data:
                    updated_count: 152
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-amazon-unified-fee-mappings-recategorize-historical
  /api/amazon/unified/merchant-sku-mappings:
    get:
      tags:
      - Amazon
      summary: List Merchant SKU Mappings
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        example: '1'
        description: Page number (default 1).
      - name: per_page
        in: query
        schema:
          type: integer
        example: '10'
        description: Results per page (default 10).
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      description: 'List Merchant SKU Mappings


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      operationId: get-api-amazon-unified-merchant-sku-mappings
  /api/amazon/unified/merchant-sku-mappings/bulk:
    put:
      tags:
      - Amazon
      summary: Bulk Update Merchant SKU Mappings
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                mappings:
                  type: array
              example:
                mappings: []
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      description: 'Bulk Update Merchant SKU Mappings


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      operationId: put-api-amazon-unified-merchant-sku-mappings-bulk
  /api/amazon/unified/merchant-sku-mappings/{id}:
    put:
      tags:
      - Amazon
      summary: Update Merchant SKU Mapping
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                product_id:
                  type: string
                  nullable: true
              example:
                product_id: null
      parameters:
      - name: id
        in: path
        schema:
          type: string
        required: true
        description: The record ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      description: 'Update Merchant SKU Mapping


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      operationId: put-api-amazon-unified-merchant-sku-mappings-id
  /api/amazon/{integrationInstance}/inbound/ship-from-mappings:
    get:
      tags:
      - Amazon
      summary: List Ship From Mappings
      description: 'List FBA inbound ship-from location mappings for an integration
        instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        ship_from_location:
                          type: string
                        warehouse_id:
                          type: integer
                        warehouse_name:
                          type: string
                example:
                  data:
                  - id: 1
                    ship_from_location: US-WEST
                    warehouse_id: 3
                    warehouse_name: West Coast Warehouse
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-integrationinstance-inbound-ship-from-mappings
    post:
      tags:
      - Amazon
      summary: Update Ship From Mappings
      description: 'Update ship-from location to warehouse mappings.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                mappings:
                  type: array
                  items:
                    type: object
                    properties:
                      ship_from_location:
                        type: string
                      warehouse_id:
                        type: integer
              example:
                mappings:
                - ship_from_location: US-WEST
                  warehouse_id: 3
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Ship-from mappings updated successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-amazon-integrationinstance-inbound-ship-from-mappings
  /api/amazon/{integrationInstance}/awd/shipments/{shipment}:
    get:
      tags:
      - Amazon
      summary: Show AWD Shipment
      description: 'Get details of a specific AWD shipment.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: shipment
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The shipment ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      shipment_id:
                        type: string
                      status:
                        type: string
                      items:
                        type: array
                        items:
                          type: object
                          properties:
                            sku:
                              type: string
                            quantity:
                              type: integer
                example:
                  data:
                    id: 1
                    shipment_id: AWD-12345
                    status: SHIPPED
                    items:
                    - sku: WIDGET-RED
                      quantity: 100
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-integrationinstance-awd-shipments-shipment
  /api/amazon/{integrationInstance}/awd/shipments/{shipment}/refresh:
    post:
      tags:
      - Amazon
      summary: Refresh AWD Shipment
      description: 'Refresh a specific AWD shipment from Amazon API.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: shipment
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The shipment ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: AWD shipment refreshed successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-amazon-integrationinstance-awd-shipments-shipment-refresh
  /api/amazon/{integrationInstance}/awd/shipments/{shipment}/export:
    get:
      tags:
      - Amazon
      summary: Export AWD Shipment Items
      description: 'Export items from a specific AWD shipment as CSV.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: shipment
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The shipment ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: text/csv
          content:
            text/plain:
              schema:
                type: string
                example: 'shipment_id,sku,quantity

                  AWD-12345,WIDGET-RED,100'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-integrationinstance-awd-shipments-shipment-export
  /api/amazon/{integrationInstance}/lpn-lookup:
    get:
      tags:
      - Amazon
      summary: LPN Lookup
      description: 'Look up a License Plate Number (LPN) to find associated inventory
        items.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: lpn
        in: query
        schema:
          type: string
        example: LPN123456789
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      lpn:
                        type: string
                      fnsku:
                        type: string
                      quantity:
                        type: integer
                example:
                  data:
                    lpn: LPN123456789
                    fnsku: X001ABC123
                    quantity: 50
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-integrationinstance-lpn-lookup
  /api/amazon/{integrationInstance}/warehouses:
    get:
      tags:
      - Amazon
      summary: List Warehouses
      description: 'List Amazon FBA warehouses/fulfillment centers for the integration
        instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: string
                        name:
                          type: string
                        country:
                          type: string
                example:
                  data:
                  - id: PHX7
                    name: Phoenix FC
                    country: US
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-integrationinstance-warehouses
  /api/amazon/mappings/available-fields:
    get:
      tags:
      - Amazon
      summary: Get available fields
      description: 'Returns the catalog of fields that can participate in a mapping:
        all Amazon listing fields (`seller_sku`, `asin1`, `item_name`, `brand`, `price`,
        etc.) and all SKU.io product fields (static fields like `sku`, `name`, plus
        dynamic fields like product pricing tiers, supplier pricing tiers, and custom
        product attributes). This endpoint is global (not scoped to an integration
        instance) and is used to populate the source/target dropdowns in the mapping
        configuration UI.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      amazon_fields:
                        type: object
                        properties:
                          seller_sku:
                            type: object
                            properties:
                              name:
                                type: string
                              label:
                                type: string
                              type:
                                type: string
                              description:
                                type: string
                              group:
                                type: string
                          asin1:
                            type: object
                            properties:
                              name:
                                type: string
                              label:
                                type: string
                              type:
                                type: string
                              description:
                                type: string
                              group:
                                type: string
                          item_name:
                            type: object
                            properties:
                              name:
                                type: string
                              label:
                                type: string
                              type:
                                type: string
                              description:
                                type: string
                              group:
                                type: string
                          brand:
                            type: object
                            properties:
                              name:
                                type: string
                              label:
                                type: string
                              type:
                                type: string
                              description:
                                type: string
                              group:
                                type: string
                          price:
                            type: object
                            properties:
                              name:
                                type: string
                              label:
                                type: string
                              type:
                                type: string
                              description:
                                type: string
                              group:
                                type: string
                          quantity:
                            type: object
                            properties:
                              name:
                                type: string
                              label:
                                type: string
                              type:
                                type: string
                              description:
                                type: string
                              group:
                                type: string
                      sku_fields:
                        type: object
                        properties:
                          sku:
                            type: object
                            properties:
                              name:
                                type: string
                              label:
                                type: string
                              type:
                                type: string
                              description:
                                type: string
                              group:
                                type: string
                          name:
                            type: object
                            properties:
                              name:
                                type: string
                              label:
                                type: string
                              type:
                                type: string
                              description:
                                type: string
                              group:
                                type: string
                          unit_cost:
                            type: object
                            properties:
                              name:
                                type: string
                              label:
                                type: string
                              type:
                                type: string
                              description:
                                type: string
                              group:
                                type: string
                          price.Default.value:
                            type: object
                            properties:
                              name:
                                type: string
                              label:
                                type: string
                              type:
                                type: string
                              description:
                                type: string
                              group:
                                type: string
                          attributes.Color:
                            type: object
                            properties:
                              name:
                                type: string
                              label:
                                type: string
                              type:
                                type: string
                              description:
                                type: string
                              group:
                                type: string
                example:
                  data:
                    amazon_fields:
                      seller_sku:
                        name: seller_sku
                        label: Seller SKU
                        type: string
                        description: Amazon seller SKU
                        group: Identifiers
                      asin1:
                        name: asin1
                        label: ASIN
                        type: string
                        description: Amazon Standard Identification Number
                        group: Identifiers
                      item_name:
                        name: item_name
                        label: Item Name
                        type: string
                        description: Amazon listing title
                        group: Product Info
                      brand:
                        name: brand
                        label: Brand
                        type: string
                        description: Product brand
                        group: Product Info
                      price:
                        name: price
                        label: Price
                        type: decimal
                        description: Listing price
                        group: Pricing
                      quantity:
                        name: quantity
                        label: Quantity
                        type: integer
                        description: Available inventory quantity
                        group: Inventory
                    sku_fields:
                      sku:
                        name: sku
                        label: SKU
                        type: string
                        description: Stock Keeping Unit
                        group: Basic Info
                      name:
                        name: name
                        label: Product Name
                        type: string
                        description: Product name/title
                        group: Basic Info
                      unit_cost:
                        name: unit_cost
                        label: Unit Cost
                        type: decimal
                        description: Product cost price
                        group: Pricing
                      price.Default.value:
                        name: price.Default.value
                        label: 'Pricing: Default'
                        type: decimal
                        description: Price value for Default pricing tier
                        group: Pricing Tiers
                      attributes.Color:
                        name: attributes.Color
                        label: 'Attribute: Color'
                        type: string
                        description: 'Product attribute: Color'
                        group: Product Attributes
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-amazon-mappings-available-fields
  /api/amazon/{integrationInstance}/mappings:
    get:
      tags:
      - Amazon
      summary: Get mappings for integration instance
      description: 'Returns the full field-mapping picture for the given Amazon integration
        instance:


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        - `mappings` / `effective_mappings`: the merged set of listing→sku field mappings
        that are actually applied during sync (custom mappings override defaults).

        - `default_mappings`: the built-in system defaults (e.g. `seller_sku → sku`,
        `item_name → item_name`, `brand → brand`, `manufacturer → vendor`, `price
        → price.<default-tier>.value`).

        - `custom_mappings`: any per-instance overrides that have been persisted via
        the update endpoint.

        - `available_amazon_fields`: the same catalog of Amazon listing fields returned
        by `GET /api/amazon/mappings/available-fields`.

        - `available_sku_fields`: the same catalog of SKU.io fields (static + dynamic
        pricing tiers / supplier pricing tiers / attributes).'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: ID of the Amazon integration instance (AmazonIntegrationInstance
          route-model binding)
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      integration_instance_id:
                        type: integer
                      integration_name:
                        type: string
                      mappings:
                        type: array
                        items:
                          type: object
                          properties:
                            listing_field:
                              type: string
                            sku_field:
                              type: string
                            parsers:
                              type: array
                            source:
                              type: string
                            description:
                              type: string
                      available_amazon_fields:
                        type: object
                        properties:
                          seller_sku:
                            type: object
                            properties:
                              name:
                                type: string
                              label:
                                type: string
                              type:
                                type: string
                              description:
                                type: string
                              group:
                                type: string
                      available_sku_fields:
                        type: object
                        properties:
                          sku:
                            type: object
                            properties:
                              name:
                                type: string
                              label:
                                type: string
                              type:
                                type: string
                              description:
                                type: string
                              group:
                                type: string
                      default_mappings:
                        type: array
                        items:
                          type: object
                          properties:
                            listing_field:
                              type: string
                            sku_field:
                              type: string
                            parsers:
                              type: array
                            source:
                              type: string
                            description:
                              type: string
                      custom_mappings:
                        type: array
                        items:
                          type: object
                          properties:
                            listing_field:
                              type: string
                            sku_field:
                              type: string
                            parsers:
                              type: array
                            source:
                              type: string
                            description:
                              type: string
                      effective_mappings:
                        type: array
                        items:
                          type: object
                          properties:
                            listing_field:
                              type: string
                            sku_field:
                              type: string
                            parsers:
                              type: array
                            source:
                              type: string
                            description:
                              type: string
                example:
                  data:
                    integration_instance_id: 1
                    integration_name: Acme US Amazon
                    mappings:
                    - listing_field: seller_sku
                      sku_field: sku
                      parsers: []
                      source: default
                      description: Maps seller_sku to sku
                    - listing_field: item_name
                      sku_field: item_name
                      parsers: []
                      source: default
                      description: Maps item_name to item_name
                    - listing_field: brand
                      sku_field: brand
                      parsers: []
                      source: custom
                      description: 'Custom mapping: brand → brand'
                    available_amazon_fields:
                      seller_sku:
                        name: seller_sku
                        label: Seller SKU
                        type: string
                        description: Amazon seller SKU
                        group: Identifiers
                    available_sku_fields:
                      sku:
                        name: sku
                        label: SKU
                        type: string
                        description: Stock Keeping Unit
                        group: Basic Info
                    default_mappings:
                    - listing_field: seller_sku
                      sku_field: sku
                      parsers: []
                      source: default
                      description: Maps seller_sku to sku
                    - listing_field: item_name
                      sku_field: item_name
                      parsers: []
                      source: default
                      description: Maps item_name to item_name
                    - listing_field: brand
                      sku_field: brand
                      parsers: []
                      source: default
                      description: Maps brand to brand
                    - listing_field: manufacturer
                      sku_field: vendor
                      parsers: []
                      source: default
                      description: Maps manufacturer to vendor
                    - listing_field: price
                      sku_field: price.Default.value
                      parsers: []
                      source: default
                      description: Maps price to price.Default.value
                    custom_mappings:
                    - listing_field: brand
                      sku_field: brand
                      parsers: []
                      source: custom
                      description: 'Custom mapping: brand → brand'
                    effective_mappings:
                    - listing_field: seller_sku
                      sku_field: sku
                      parsers: []
                      source: default
                      description: Maps seller_sku to sku
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-integrationinstance-mappings
    put:
      tags:
      - Amazon
      summary: Update mappings for integration instance
      description: "Persists the full set of custom field mappings for the given Amazon\
        \ integration instance. The payload completely replaces the previously stored\
        \ custom mappings for the `listings` mapping group.\n\n:::info[Authorization]\n\
        Any valid API token can call this endpoint — no specific scope required. [Manage\
        \ tokens](https://app.sku.io/settings/api).\n:::\n\nRequest body (validated\
        \ via `UpdateAmazonFieldMappingsData`):\n- `mappings` (array, required): list\
        \ of mapping entries. Each entry contains:\n  - `listing_field` (string, required):\
        \ the Amazon listing field name (e.g. `seller_sku`, `item_name`, `brand`,\
        \ `price`). Must match one of the keys returned by `GET /api/amazon/mappings/available-fields`\
        \ under `amazon_fields`.\n  - `sku_field` (string, required): the SKU.io target\
        \ field. Either a static field (e.g. `sku`, `name`, `vendor`), a pricing tier\
        \ path (e.g. `price.Default.value`), a supplier pricing tier path (e.g. `supplier_pricing.Wholesale.value`),\
        \ or an attribute path (e.g. `attributes.Color`).\n  - `parsers` (array, required):\
        \ zero or more parser transformations applied in order to the incoming Amazon\
        \ value before it is written to the SKU.io field. Each parser has a `rule`\
        \ (must be one of the supported `FieldParserFactory::SUPPORTED_PARSERS` rules)\
        \ and a stringified `args` payload.\n\nThe response echoes back the integration\
        \ instance id/name plus the updated `mappings` and `effective_mappings` (custom\
        \ merged on top of defaults)."
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                mappings:
                  type: array
                  items:
                    type: object
                    properties:
                      listing_field:
                        type: string
                      sku_field:
                        type: string
                      parsers:
                        type: array
              example:
                mappings:
                - listing_field: seller_sku
                  sku_field: sku
                  parsers: []
                - listing_field: item_name
                  sku_field: name
                  parsers: []
                - listing_field: brand
                  sku_field: brand
                  parsers: []
                - listing_field: price
                  sku_field: price.Default.value
                  parsers:
                  - rule: trim
                    args: ''
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: ID of the Amazon integration instance (AmazonIntegrationInstance
          route-model binding)
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      integration_instance_id:
                        type: integer
                      integration_name:
                        type: string
                      mappings:
                        type: array
                        items:
                          type: object
                          properties:
                            listing_field:
                              type: string
                            sku_field:
                              type: string
                            parsers:
                              type: array
                            source:
                              type: string
                            description:
                              type: string
                      effective_mappings:
                        type: array
                        items:
                          type: object
                          properties:
                            listing_field:
                              type: string
                            sku_field:
                              type: string
                            parsers:
                              type: array
                            source:
                              type: string
                            description:
                              type: string
                  message:
                    type: string
                example:
                  data:
                    integration_instance_id: 1
                    integration_name: Acme US Amazon
                    mappings:
                    - listing_field: seller_sku
                      sku_field: sku
                      parsers: []
                      source: custom
                      description: 'Custom mapping: seller_sku → sku'
                    effective_mappings:
                    - listing_field: seller_sku
                      sku_field: sku
                      parsers: []
                      source: custom
                      description: 'Custom mapping: seller_sku → sku'
                    - listing_field: item_name
                      sku_field: item_name
                      parsers: []
                      source: default
                      description: Maps item_name to item_name
                  message: Field mappings updated successfully
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      mappings.0.sku_field:
                        type: array
                        items:
                          type: string
                      mappings.0.parsers:
                        type: array
                        items:
                          type: string
                example:
                  message: The mappings.0.sku_field field is required. (and 1 more
                    error)
                  errors:
                    mappings.0.sku_field:
                    - The mappings.0.sku_field field is required.
                    mappings.0.parsers:
                    - The mappings.0.parsers field is required.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: put-api-amazon-integrationinstance-mappings
  /api/amazon/{integrationInstance}/shipping-method-mappings:
    get:
      tags:
      - Amazon
      summary: List Shipping Method Mappings
      description: 'List every shipping method mapping for the Amazon integration''s
        sales channel. Each row pairs an Amazon shipping method name (e.g. "Standard",
        "Expedited") with an optional internal SKU.io shipping method (eager-loaded
        with its carrier). Returns 404 if the integration has no sales channel.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Amazon integration instance ID
        example: '10'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        sales_channel_id:
                          type: integer
                        sales_channel_method:
                          type: string
                        shipping_method_id:
                          type: string
                          nullable: true
                        shipping_method:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                        updated_at:
                          type: string
                example:
                  data:
                  - id: 21
                    sales_channel_id: 9
                    sales_channel_method: Econ US Dom
                    shipping_method_id: null
                    shipping_method: null
                    created_at: '2025-06-13T15:50:43.000000Z'
                    updated_at: '2025-06-13T15:50:43.000000Z'
                  - id: 22
                    sales_channel_id: 9
                    sales_channel_method: Expedited
                    shipping_method_id: 2
                    shipping_method:
                      id: 2
                      name: 2nd Day Air AM
                      full_name: UPS 2nd Day Air AM
                      carrier_id: 1
                      carrier_name: UPS
                    created_at: '2025-06-13T15:50:43.000000Z'
                    updated_at: '2026-06-02T20:27:59.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-integrationinstance-shipping-method-mappings
    put:
      tags:
      - Amazon
      summary: Save Shipping Method Mappings (bulk upsert)
      description: 'Bulk upsert mappings. Each row is matched by (sales_channel_id,
        sales_channel_method); existing rows are updated, new method names create
        rows. A null shipping_method_id clears the mapping but keeps the row. After
        each upsert, the new shipping_method_id is propagated to all open sales orders
        (order_status != closed) for that sales_channel + requested_shipping_method,
        so the SKU.io SO display stays in sync.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Validation:

        - mappings — required, array, min:1

        - mappings.*.sales_channel_method — required, string, max:255

        - mappings.*.shipping_method_id — nullable, integer, exists:shipping_methods,id


        Authentication: Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                mappings:
                  type: array
                  items:
                    type: object
                    properties:
                      sales_channel_method:
                        type: string
                      shipping_method_id:
                        type: integer
              example:
                mappings:
                - sales_channel_method: Standard
                  shipping_method_id: 1
                - sales_channel_method: Expedited
                  shipping_method_id: 2
                - sales_channel_method: NextDay
                  shipping_method_id: null
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Amazon integration instance ID
        example: '10'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        sales_channel_id:
                          type: integer
                        sales_channel_method:
                          type: string
                        shipping_method_id:
                          type: integer
                        shipping_method:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            full_name:
                              type: string
                            carrier_id:
                              type: integer
                            carrier_name:
                              type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  message:
                    type: string
                example:
                  data:
                  - id: 2
                    sales_channel_id: 9
                    sales_channel_method: Standard
                    shipping_method_id: 1
                    shipping_method:
                      id: 1
                      name: 2nd Day Air
                      full_name: UPS 2nd Day Air
                      carrier_id: 1
                      carrier_name: UPS
                    created_at: '2025-06-13T09:31:47.000000Z'
                    updated_at: '2026-06-02T20:27:59.000000Z'
                  message: Shipping method mappings saved.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      mappings:
                        type: array
                        items:
                          type: string
                example:
                  message: At least one mapping is required.
                  errors:
                    mappings:
                    - At least one mapping is required.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: put-api-amazon-integrationinstance-shipping-method-mappings
  /api/amazon/{integrationInstance}/shipping-method-mappings/{mapping}:
    delete:
      tags:
      - Amazon
      summary: Delete Shipping Method Mapping
      description: 'Delete a single shipping method mapping. Open sales orders that
        requested this shipping method (and belong to the same sales_channel) have
        their shipping_method_id cleared so SO display stays consistent. Returns 404
        if the mapping belongs to a different integration''s sales channel.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Amazon integration instance ID
        example: '10'
      - name: mapping
        in: path
        schema:
          type: integer
        required: true
        description: ShippingMethodMappingsSalesChannelToSku ID
        example: '22'
      responses:
        '204':
          description: No Content
          content:
            text/plain:
              schema:
                type: string
                example: ''
        '404':
          description: Not Found
          content:
            text/plain:
              schema:
                type: string
                example: ''
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: delete-api-amazon-integrationinstance-shipping-method-mappings-mapping
  /api/amazon/{integrationInstance}/shipping-method-mappings/import:
    post:
      tags:
      - Amazon
      summary: Import Shipping Method Mappings (CSV)
      description: 'Bulk import shipping method mappings from a CSV upload. Existing
        rows with the same amazon_method are updated, new method names create rows.
        Rows with an unresolvable shipping_method_id or shipping_method_full_name
        are skipped and reported in the response''s errors array (the rest of the
        import still succeeds). Same propagation to open sales orders as the bulk
        save endpoint.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Content-Type: multipart/form-data


        Validation:

        - file — required, file, mimes:csv,txt, max:5120 (KB)


        Authentication: Bearer token.'
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                file:
                  type: string
                  description: 'CSV file. Header row required. Recognized columns
                    (case-insensitive): amazon_method (required), shipping_method_id
                    (optional, int), shipping_method_full_name (optional, exact full_name
                    match). Use shipping_method_id OR shipping_method_full_name to
                    set a mapping; leave both blank to clear the mapping for that
                    amazon_method.'
                  format: binary
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Amazon integration instance ID
        example: '10'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      created:
                        type: integer
                      updated:
                        type: integer
                      skipped:
                        type: integer
                      errors:
                        type: array
                        items:
                          type: object
                          properties:
                            row:
                              type: integer
                            amazon_method:
                              type: string
                            message:
                              type: string
                  message:
                    type: string
                example:
                  data:
                    created: 2
                    updated: 4
                    skipped: 1
                    errors:
                    - row: 5
                      amazon_method: UnknownPlan
                      message: Shipping method not found (use a known shipping_method_id
                        or shipping_method_full_name, or leave blank to clear the
                        mapping).
                  message: 2 created, 4 updated, 1 skipped, 1 error(s).
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      file:
                        type: array
                        items:
                          type: string
                example:
                  message: Please attach a CSV file to import.
                  errors:
                    file:
                    - Please attach a CSV file to import.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-amazon-integrationinstance-shipping-method-mappings-import
  /api/amazon/{integrationInstance}/shipping-method-mappings/export:
    get:
      tags:
      - Amazon
      summary: Export Shipping Method Mappings (CSV)
      description: 'Stream every shipping method mapping for the integration as a
        CSV download. Header row: amazon_method,shipping_method_id,shipping_method_full_name,carrier_name.
        Round-trip-compatible with the import endpoint.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Response Content-Type: text/csv (file download named amazon-shipping-mappings-{instanceId}-{date}.csv).


        Authentication: Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Amazon integration instance ID
        example: '10'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: text/csv
            Content-Disposition:
              schema:
                type: string
                example: attachment; filename="amazon-shipping-mappings-10-2026-06-02.csv"
          content:
            text/plain:
              schema:
                type: string
                example: 'amazon_method,shipping_method_id,shipping_method_full_name,carrier_name

                  "Econ US Dom",,,

                  Expedited,2,"UPS 2nd Day Air AM",UPS

                  NextDay,,,

                  SecondDay,,,

                  Standard,1,"UPS 2nd Day Air",UPS

                  "Std US D2D Dom",,,

                  '
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-integrationinstance-shipping-method-mappings-export
  /api/amazon/{integrationInstance}/orders:
    get:
      tags:
      - Amazon
      summary: List Orders
      description: 'List Amazon orders for an integration instance (list view endpoint).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Query params:

        - page, limit: pagination

        - search: text search

        - sort: sort field (prefix with - for desc)

        - archived: 0 or 1'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        example: '1'
        description: Page number (default 1).
      - name: limit
        in: query
        schema:
          type: integer
        example: '20'
        description: Maximum number of results to return.
      - name: search
        in: query
        schema:
          type: string
        description: Free-text search across the resource’s searchable fields.
      - name: sort
        in: query
        schema:
          type: string
        description: Prefix with - for descending
        example: -id
      - name: archived
        in: query
        schema:
          type: integer
        description: 0 = active, 1 = archived
        example: '0'
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        AmazonOrderId:
                          type: string
                        OrderStatus:
                          type: string
                        PurchaseDate:
                          type: string
                        LastUpdateDate:
                          type: string
                        integration_instance_id:
                          type: integer
                        sku_sales_order:
                          type: object
                          properties:
                            id:
                              type: integer
                            number:
                              type: string
                        archived_at:
                          type: string
                          nullable: true
                  current_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 1
                    AmazonOrderId: 114-1234567-1234567
                    OrderStatus: Shipped
                    PurchaseDate: '2024-06-01T10:00:00Z'
                    LastUpdateDate: '2024-06-03T08:00:00Z'
                    integration_instance_id: 1
                    sku_sales_order:
                      id: 55
                      number: SO-2024-0055
                    archived_at: null
                  current_page: 1
                  per_page: 20
                  total: 1250
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-integrationinstance-orders
  /api/amazon/{integrationInstance}/orders/{order}:
    get:
      tags:
      - Amazon
      summary: Show Order
      description: 'Get details of a specific Amazon order.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: order
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      AmazonOrderId:
                        type: string
                      OrderStatus:
                        type: string
                      PurchaseDate:
                        type: string
                      sku_sales_order:
                        type: object
                        properties:
                          id:
                            type: integer
                          number:
                            type: string
                example:
                  data:
                    id: 1
                    AmazonOrderId: 114-1234567-1234567
                    OrderStatus: Shipped
                    PurchaseDate: '2024-06-01T10:00:00Z'
                    sku_sales_order:
                      id: 55
                      number: SO-2024-0055
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-integrationinstance-orders-order
    delete:
      tags:
      - Amazon
      summary: Delete Order
      description: 'Delete a single Amazon order.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: order
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Order deleted successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-amazon-integrationinstance-orders-order
  /api/amazon/{integrationInstance}/orders/{order}/archive:
    post:
      tags:
      - Amazon
      summary: Archive Order
      description: 'Archive a single Amazon order.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: order
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  archived:
                    type: boolean
                example:
                  message: Order archived successfully
                  archived: true
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-amazon-integrationinstance-orders-order-archive
  /api/amazon/{integrationInstance}/orders/{order}/unarchive:
    post:
      tags:
      - Amazon
      summary: Unarchive Order
      description: 'Unarchive a single Amazon order.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: order
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  unarchived:
                    type: boolean
                example:
                  message: Order unarchived successfully
                  unarchived: true
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-amazon-integrationinstance-orders-order-unarchive
  /api/amazon/{integrationInstance}/orders/bulk-archive:
    post:
      tags:
      - Amazon
      summary: Bulk Archive Orders
      description: 'Archive multiple Amazon orders.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Fields:

        - ids: array of integers (required_without apply_to_all)

        - apply_to_all: boolean

        - filters: array of filter conditions'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
                apply_to_all:
                  type: boolean
                filters:
                  type: object
                  properties: {}
              example:
                ids:
                - 1
                - 2
                - 3
                apply_to_all: false
                filters: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  archived_count:
                    type: integer
                example:
                  message: 3 orders archived successfully
                  archived_count: 3
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-amazon-integrationinstance-orders-bulk-archive
  /api/amazon/{integrationInstance}/orders/bulk-unarchive:
    post:
      tags:
      - Amazon
      summary: Bulk Unarchive Orders
      description: 'Unarchive multiple Amazon orders.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
                apply_to_all:
                  type: boolean
                filters:
                  type: object
                  properties: {}
              example:
                ids:
                - 1
                - 2
                - 3
                apply_to_all: false
                filters: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  unarchived_count:
                    type: integer
                example:
                  message: 3 orders unarchived successfully
                  unarchived_count: 3
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-amazon-integrationinstance-orders-bulk-unarchive
  /api/amazon/{integrationInstance}/orders/bulk-delete:
    post:
      tags:
      - Amazon
      summary: Bulk Delete Orders
      description: 'Delete multiple Amazon orders.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
                apply_to_all:
                  type: boolean
                filters:
                  type: object
                  properties: {}
              example:
                ids:
                - 1
                - 2
                - 3
                apply_to_all: false
                filters: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  deleted_count:
                    type: integer
                example:
                  message: 3 orders deleted successfully
                  deleted_count: 3
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-amazon-integrationinstance-orders-bulk-delete
  /api/amazon/{integrationInstance}/orders/create-sku-orders:
    post:
      tags:
      - Amazon
      summary: Create SKU Orders from Amazon Orders
      description: 'Create SKU.io sales orders from this instance''s Amazon orders.
        Runs synchronously.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Body fields:

        - ids (array of integers, optional) — internal Amazon order record IDs (the
        SKU.io row ids, not Amazon marketplace order numbers) to convert. When specific
        ids are given, the configured order start-date restriction is bypassed and
        the response includes the created sales orders.

        - create_all_orders (boolean, default false) — set true to convert all pending
        orders regardless of the integration''s configured order start date (the "Create
        All" behaviour).

        - filters (string, optional) — JSON string in the same flat-filter format
        as the orders list ({"conjunction","filterSet":[...]}). When present, ids
        is overwritten server-side with the order ids matching the filter set for
        this instance.


        When neither ids nor create_all_orders is provided, all pending orders dated
        after the integration''s configured order start date are converted. For each
        created sales order, automated fulfillment rules are evaluated by a background
        job. When specific ids all fail to convert, a 422 is returned with the first
        failure reason (for example an unmapped product, or an order currency that
        does not exist in Settings > Currencies).


        Bulk selection contract:

        - {"ids": [1, 2]} — create for the given channel order IDs

        - {"create_all_orders": true} — create for all eligible orders on the integration
        instance

        - {"create_all_orders": true, "filters": {...}} — create only for orders matching
        the filters. The filters object accepts the same filter keys as the corresponding
        orders list endpoint (bare column keys, e.g. {"order_status": "pending"})
        and/or a "filter_groups" tree (base64-encoded JSON, same format as the list
        endpoint). When filters match no orders, nothing is created and the response
        message is "No orders to create".

        - Legacy {"conjunction", "filterSet"} filter payloads are rejected with 422.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
                create_all_orders:
                  type: boolean
              example:
                ids:
                - 1024
                - 1025
                create_all_orders: false
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Amazon integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      created_sales_orders:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            sales_order_number:
                              type: string
                  message:
                    type: string
                  status:
                    type: string
                example:
                  data:
                    created_sales_orders:
                    - id: 8817
                      sales_order_number: SO-2026-08817
                    - id: 8818
                      sales_order_number: SO-2026-08818
                  message: Sku.io sales orders successfully created
                  status: success
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 422 Unprocessable Entity (Creation Failed)
                  value:
                    message: 'Failed to create SKU order: No SKU.io product is mapped
                      to merchant SKU LS-RAZOR-BLK'
                    status: failure
                example-1:
                  summary: 422 Unprocessable Entity (Missing Currency)
                  value:
                    message: Currency "AUD" does not exist in the system. Please add
                      it in Settings > Currencies before creating SKU orders.
                    status: failure
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-amazon-integrationinstance-orders-create-sku-orders
  /api/amazon/{integrationInstance}/orders/refresh:
    post:
      tags:
      - Amazon
      summary: Refresh Orders from Amazon
      description: 'Refresh this instance''s Amazon orders from the Amazon Selling
        Partner API. Queues a background job on a serialized queue that pulls new
        and updated orders since the last sync; the request returns immediately with
        a confirmation message. No request body.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Amazon integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  status:
                    type: string
                example:
                  message: Added to queue, orders will be refreshed shortly.
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-amazon-integrationinstance-orders-refresh
  /api/amazon/{integrationInstance}/removal-orders/{orderId}:
    get:
      tags:
      - Amazon
      summary: Get Order Details (by path)
      description: 'Aggregates removal orders + removal shipments for the given order
        ID, hydrates FNSKU products and metadata, and revalidates the receipt status
        when applicable. Returns 404 if neither orders nor shipments exist for the
        order ID.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Amazon integration instance ID
        example: '1'
      - name: orderId
        in: path
        schema:
          type: string
        required: true
        description: Amazon removal order ID. Path-param accepts any characters including
          `/` via `where('orderId', '.*')`. Use the query-string variant when the
          ID contains URL-unsafe characters such as a trailing slash that Apache would
          strip.
        example: YmPxcdTqk
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      order_id:
                        type: string
                      integration_instance_id:
                        type: integer
                      order_type:
                        type: string
                      order_status:
                        type: string
                      metadata:
                        type: object
                        properties:
                          id:
                            type: integer
                          integration_instance_id:
                            type: integer
                          removal_order_id:
                            type: string
                          receiving_warehouse_id:
                            type: integer
                          receipt_status:
                            type: string
                          created_at:
                            type: string
                          updated_at:
                            type: string
                          receipt_status_data:
                            type: object
                            properties:
                              value:
                                type: string
                              label:
                                type: string
                              color:
                                type: string
                              icon:
                                type: string
                      order_lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            fnsku:
                              type: string
                            fnsku_product_id:
                              type: integer
                            fnsku_product:
                              type: object
                              properties:
                                id:
                                  type: integer
                                fnsku:
                                  type: string
                                product:
                                  type: object
                                  properties:
                                    id:
                                      type: integer
                                    sku:
                                      type: string
                                    name:
                                      type: string
                            sku:
                              type: string
                            product_sku:
                              type: string
                            product_id:
                              type: integer
                            product_name:
                              type: string
                            disposition:
                              type: string
                            requested_quantity:
                              type: integer
                            shipped_quantity:
                              type: integer
                            cancelled_quantity:
                              type: integer
                            disposed_quantity:
                              type: integer
                            in_process_quantity:
                              type: integer
                            removal_fee:
                              type: number
                            currency:
                              type: string
                            request_date:
                              type: string
                            last_updated_date:
                              type: string
                            is_unknown_item:
                              type: boolean
                            sku_link_id:
                              type: integer
                            sku_link_type:
                              type: string
                            detail_link_id:
                              type: integer
                            detail_link_type:
                              type: string
                      shipments:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            uniqueId:
                              type: string
                            fnsku:
                              type: string
                            fnsku_product_id:
                              type: integer
                            fnsku_product:
                              type: object
                              properties:
                                id:
                                  type: integer
                                fnsku:
                                  type: string
                                product:
                                  type: object
                                  properties:
                                    id:
                                      type: integer
                                    sku:
                                      type: string
                                    name:
                                      type: string
                            sku:
                              type: string
                            product_sku:
                              type: string
                            product_id:
                              type: integer
                            product_name:
                              type: string
                            disposition:
                              type: string
                            tracking_number:
                              type: string
                            carrier:
                              type: string
                            shipment_date:
                              type: string
                            request_date:
                              type: string
                            shipped_quantity:
                              type: integer
                            qty_discarded:
                              type: integer
                            qty_reconciled_pretracking:
                              type: integer
                            received_quantity:
                              type: integer
                            pending_quantity:
                              type: integer
                            is_pre_tracking:
                              type: boolean
                            receipt_status:
                              type: string
                            removal_order_type:
                              type: string
                            receipts:
                              type: array
                              items:
                                type: object
                                properties:
                                  id:
                                    type: integer
                                  adjustment_date:
                                    type: string
                                  quantity:
                                    type: integer
                                  unit_cost:
                                    type: number
                                  notes:
                                    type: string
                                  warehouse_id:
                                    type: integer
                                  warehouse_name:
                                    type: string
                                  created_at:
                                    type: string
                  status:
                    type: string
                example:
                  data:
                    order_id: YmPxcdTqk
                    integration_instance_id: 1
                    order_type: Return
                    order_status: Completed
                    metadata:
                      id: 17
                      integration_instance_id: 1
                      removal_order_id: YmPxcdTqk
                      receiving_warehouse_id: 4
                      receipt_status: partially_received
                      created_at: '2026-05-12T14:35:30.000000Z'
                      updated_at: '2026-05-14T08:21:55.000000Z'
                      receipt_status_data:
                        value: partially_received
                        label: Partially Received
                        color: primary
                        icon: mdi-truck-delivery
                    order_lines:
                    - id: 4521
                      fnsku: X001ABC123
                      fnsku_product_id: 7
                      fnsku_product:
                        id: 7
                        fnsku: X001ABC123
                        product:
                          id: 333
                          sku: PARENT-001
                          name: Parent Product
                      sku: ABC-001
                      product_sku: PARENT-001
                      product_id: 333
                      product_name: Parent Product
                      disposition: Sellable
                      requested_quantity: 10
                      shipped_quantity: 10
                      cancelled_quantity: 0
                      disposed_quantity: 0
                      in_process_quantity: 0
                      removal_fee: 5.5
                      currency: USD
                      request_date: '2026-05-12T14:35:00.000000Z'
                      last_updated_date: '2026-05-13T09:11:02.000000Z'
                      is_unknown_item: false
                      sku_link_id: 901
                      sku_link_type: App\Models\WarehouseTransferLine
                      detail_link_id: 88
                      detail_link_type: App\Models\WarehouseTransfer
                    shipments:
                    - id: 9011
                      uniqueId: shipment_0
                      fnsku: X001ABC123
                      fnsku_product_id: 7
                      fnsku_product:
                        id: 7
                        fnsku: X001ABC123
                        product:
                          id: 333
                          sku: PARENT-001
                          name: Parent Product
                      sku: ABC-001
                      product_sku: PARENT-001
                      product_id: 333
                      product_name: Parent Product
                      disposition: Sellable
                      tracking_number: 1Z999AA10123456784
                      carrier: UPS
                      shipment_date: '2026-05-13T00:00:00.000000Z'
                      request_date: '2026-05-12T14:35:00.000000Z'
                      shipped_quantity: 10
                      qty_discarded: 0
                      qty_reconciled_pretracking: 0
                      received_quantity: 4
                      pending_quantity: 6
                      is_pre_tracking: false
                      receipt_status: partially_received
                      removal_order_type: Return
                      receipts:
                      - id: 2201
                        adjustment_date: '2026-05-14'
                        quantity: 4
                        unit_cost: 1.25
                        notes: Partial receive
                        warehouse_id: 4
                        warehouse_name: Main WH
                        created_at: '2026-05-14T08:21:55.000000Z'
                    - id: 9012
                      uniqueId: shipment_1
                      fnsku: X001ABC123
                      fnsku_product_id: 7
                      fnsku_product:
                        id: 7
                        fnsku: X001ABC123
                        product:
                          id: 333
                          sku: PARENT-001
                          name: Parent Product
                      sku: ABC-001
                      product_sku: PARENT-001
                      product_id: 333
                      product_name: Parent Product
                      disposition: Sellable
                      tracking_number: 1Z999AA10123456785
                      carrier: UPS
                      shipment_date: '2024-11-20T00:00:00.000000Z'
                      request_date: '2024-11-18T14:35:00.000000Z'
                      shipped_quantity: 8
                      qty_discarded: 0
                      qty_reconciled_pretracking: 8
                      received_quantity: 0
                      pending_quantity: 0
                      is_pre_tracking: true
                      receipt_status: reconciled_at_go_live
                      removal_order_type: Return
                      receipts: []
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-integrationinstance-removal-orders-orderid
  /api/amazon/{integrationInstance}/removal-orders/order-details:
    get:
      tags:
      - Amazon
      summary: Get Order Details (by query string)
      description: 'Query-string variant of `getOrderDetails`. Returns 422 when `order_id`
        is missing/empty, 404 when no matching orders or shipments exist. Response
        payload is identical to the path-param variant.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: order_id
        in: query
        schema:
          type: string
        description: Removal order ID. Required. Use this endpoint for IDs containing
          characters Apache's trailing-slash redirect would strip from a path segment
          (e.g. a trailing `/`).
        example: YmPxcdTqk/
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Amazon integration instance ID
        example: '1'
      responses:
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: order_id query parameter is required
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-integrationinstance-removal-orders-order-details
  /api/amazon/{integrationInstance}/removal-orders/set-warehouse:
    post:
      tags:
      - Amazon
      summary: Set Receiving Warehouse
      description: 'Assigns (or replaces) the receiving warehouse on a removal order''s
        metadata. Validation (`SetRemovalOrderWarehouseData`):

        - `removal_order_id` (string, required)

        - `warehouse_id` (integer, required, exists in `warehouses.id`)


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Returns the resulting `RemovalOrderWarehouseData` (`removal_order_id`, `receiving_warehouse_id`).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                removal_order_id:
                  type: string
                warehouse_id:
                  type: integer
              example:
                removal_order_id: YmPxcdTqk
                warehouse_id: 4
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Amazon integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      removal_order_id:
                        type: string
                      receiving_warehouse_id:
                        type: integer
                  status:
                    type: string
                example:
                  data:
                    removal_order_id: YmPxcdTqk
                    receiving_warehouse_id: 4
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-amazon-integrationinstance-removal-orders-set-warehouse
  /api/amazon/{integrationInstance}/removal-orders/unprocess:
    post:
      tags:
      - Amazon
      summary: Unprocess Removal Orders
      description: 'Unprocess removal orders.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1
                - 2
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Removal orders unprocessed
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-amazon-integrationinstance-removal-orders-unprocess
  /api/amazon/{integrationInstance}/removal-orders/archive:
    post:
      tags:
      - Amazon
      summary: Archive Removal Orders
      description: 'Bulk-archives removal orders (sets `archived_at = now()`). Request
        body uses `IdSelectionData`:

        - `ids` (array of integers, required) — removal order row IDs

        - `value` (string, optional) — opaque selection identifier (e.g. `selected`,
        `all`)


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Note: this endpoint does NOT take an integration instance filter on the database
        update; the route is namespaced by `{integrationInstance}` but the manager
        only filters by the supplied IDs.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
                value:
                  type: string
              example:
                ids:
                - 4521
                - 4522
                - 4523
                value: selected
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Amazon integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  status:
                    type: string
                example:
                  message: Removal orders archived successfully
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-amazon-integrationinstance-removal-orders-archive
  /api/amazon/{integrationInstance}/removal-orders/unarchive:
    post:
      tags:
      - Amazon
      summary: Unarchive Removal Orders
      description: 'Bulk-unarchives removal orders (sets `archived_at = null`). Request
        body uses `IdSelectionData`:

        - `ids` (array of integers, required) — removal order row IDs

        - `value` (string, optional) — opaque selection identifier


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
                value:
                  type: string
              example:
                ids:
                - 4521
                - 4522
                - 4523
                value: selected
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Amazon integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  status:
                    type: string
                example:
                  message: Removal orders unarchived successfully
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-amazon-integrationinstance-removal-orders-unarchive
  /api/amazon/{integrationInstance}/removal-orders/{removalOrder}/mark-item-as-unknown:
    post:
      tags:
      - Amazon
      summary: Mark Item As Unknown
      description: 'Marks a single removal order row as an unknown item (`is_unknown_item
        = true`). No request body.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          '*/*':
            schema:
              type: string
              example: '""'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Amazon integration instance ID
        example: '1'
      - name: removalOrder
        in: path
        schema:
          type: integer
        required: true
        description: Primary key of the AmazonFbaReportRemovalOrder row.
        example: '4521'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  status:
                    type: string
                example:
                  message: Item marked as unknown
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-amazon-integrationinstance-removal-orders-removalorder-mark-item-as-unknown
  /api/amazon/{integrationInstance}/removal-orders/{removalOrder}/unmark-item-as-unknown:
    post:
      tags:
      - Amazon
      summary: Unmark Item As Unknown
      description: 'Reverses the unknown-item flag on a removal order row (`is_unknown_item
        = false`). No request body.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          '*/*':
            schema:
              type: string
              example: '""'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Amazon integration instance ID
        example: '1'
      - name: removalOrder
        in: path
        schema:
          type: integer
        required: true
        description: Primary key of the AmazonFbaReportRemovalOrder row.
        example: '4521'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  status:
                    type: string
                example:
                  message: Item unmarked as unknown
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-amazon-integrationinstance-removal-orders-removalorder-unmark-item-as-unknown
  /api/amazon/{integrationInstance}/removal-orders/{removalOrderId}/close-receiving:
    patch:
      tags:
      - Amazon
      summary: Close Receiving
      description: 'Closes receiving for a removal order. The status manager automatically
        derives the next receipt status based on current receipts:

        - `received_for_less` → ''Removal order marked as received for less''

        - `closed_without_receipt` → ''Removal order closed without receipt''

        - otherwise → ''Removal order status updated''


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Returns 422 with the exception message if the status transition is invalid
        (`InvalidArgumentException`).'
      requestBody:
        content:
          '*/*':
            schema:
              type: string
              example: '""'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Amazon integration instance ID
        example: '1'
      - name: removalOrderId
        in: path
        schema:
          type: string
        required: true
        description: Removal order ID. Accepts slashes via `where('removalOrderId',
          '.*')`.
        example: YmPxcdTqk
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      new_status:
                        type: string
                  message:
                    type: string
                  status:
                    type: string
                example:
                  data:
                    new_status: closed_without_receipt
                  message: Removal order closed without receipt
                  status: success
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Removal order cannot be closed in its current state
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: patch-api-amazon-integrationinstance-removal-orders-removalorderid-close-receiving
  /api/amazon/{integrationInstance}/removal-orders/{removalOrderId}/resume-receiving:
    patch:
      tags:
      - Amazon
      summary: Resume Receiving
      description: 'Re-opens receiving for a removal order by re-evaluating the receipt
        status against current shipments + receipts. Returns the resulting status
        value.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          '*/*':
            schema:
              type: string
              example: '""'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Amazon integration instance ID
        example: '1'
      - name: removalOrderId
        in: path
        schema:
          type: string
        required: true
        description: Removal order ID. Accepts slashes via `where('removalOrderId',
          '.*')`.
        example: YmPxcdTqk
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      new_status:
                        type: string
                  message:
                    type: string
                  status:
                    type: string
                example:
                  data:
                    new_status: partially_received
                  message: Removal order reopened for receiving
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: patch-api-amazon-integrationinstance-removal-orders-removalorderid-resume-receiving
  /api/amazon/{integrationInstance}/removal-orders/{removalOrderId}/clear-warehouse:
    delete:
      tags:
      - Amazon
      summary: Clear Receiving Warehouse
      description: 'Clears the receiving warehouse from a removal order''s metadata.
        Returns `Warehouse cleared successfully` if a value was cleared, or `No warehouse
        to clear` if there was nothing to remove.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Amazon integration instance ID
        example: '1'
      - name: removalOrderId
        in: path
        schema:
          type: string
        required: true
        description: Removal order ID. Accepts any characters including slashes (`where('removalOrderId',
          '.*')`).
        example: YmPxcdTqk
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  status:
                    type: string
                example:
                  message: Warehouse cleared successfully
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-amazon-integrationinstance-removal-orders-removalorderid-clear-warehouse
  /api/amazon/{integrationInstance}/removal-orders/unlinked:
    get:
      tags:
      - Amazon
      summary: Get Unlinked Removal Orders
      description: 'Returns distinct removal orders of type `Return` that are not
        yet linked to a SKU (warehouse transfer line). Grouped by `order_id`, sorted
        by request_date desc. Each row exposes only `order_id` and `date` (earliest
        request date).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Amazon integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        order_id:
                          type: string
                        date:
                          type: string
                  status:
                    type: string
                example:
                  data:
                  - order_id: YmPxcdTqk
                    date: '2026-05-12'
                  - order_id: AbCdEfGhI
                    date: '2026-05-10'
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-integrationinstance-removal-orders-unlinked
  /api/amazon/{integrationInstance}/removal-orders/backfill-straddle:
    post:
      tags:
      - Amazon
      summary: Backfill Straddle Removal Orders
      description: 'One-time repair for removal orders that straddle the integration''s
        FBA inventory tracking start date. Before the straddle fix, removal shipments
        dispatched before go-live were dropped during report import, leaving the surviving
        removal orders with zero receivable shipments and phantom shrinkage.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Queues a background job; returns a job id (tracked_job_log_id) for polling
        progress. Per instance, the job: (1) re-creates the dropped removal shipment
        rows by replaying the stored report payloads where they still exist (replay
        is idempotent — checksum de-duplication re-inserts only the previously-missing
        rows and never touches existing receipts, discards or inventory adjustments),
        (2) surfaces reports whose source payload is no longer available so an operator
        can act (quantities are never fabricated), and (3) re-evaluates the receipt
        status of every straddling removal order. Instances without an FBA inventory
        tracking start date no-op cleanly.


        Body fields:

        - dry_run (boolean, optional, default false) — compute and record the same
        counts in the job results without writing any changes.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                dry_run:
                  type: boolean
              example:
                dry_run: false
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Amazon integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                  status:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 4821
                  message: Backfill started
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-amazon-integrationinstance-removal-orders-backfill-straddle
  /api/amazon/{integrationInstance}/removal-shipments/{removalShipment}:
    get:
      tags:
      - Amazon
      summary: Show Removal Shipment
      description: 'Fetch a single removal shipment with its parent removal order
        eager-loaded. Returns 404 if the shipment does not belong to the supplied
        integration instance. NOTE: this route is registered twice — under `/api/amazon/{integrationInstance}/removal-shipments/{removalShipment}`
        and under `/api/amazon/{integrationInstance}/ledgers/removal-shipments/{removalShipment}`
        — both invoke the same controller method.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Amazon integration instance ID
        example: '1'
      - name: removalShipment
        in: path
        schema:
          type: integer
        required: true
        description: AmazonFbaReportRemovalShipment ID
        example: '12345'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      event_datetime:
                        type: string
                      request_date:
                        type: string
                      shipment_date:
                        type: string
                      order_id:
                        type: string
                      sku:
                        type: string
                      fnsku:
                        type: string
                      disposition:
                        type: string
                      shipped_quantity:
                        type: integer
                      carrier:
                        type: string
                      tracking_number:
                        type: string
                      removal_order_type:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 12345
                    event_datetime: '2026-04-12T14:32:00.000000Z'
                    request_date: '2026-04-10T00:00:00.000000Z'
                    shipment_date: '2026-04-11T00:00:00.000000Z'
                    order_id: AMZ-REMOVAL-1234567
                    sku: SKU-ABC-001
                    fnsku: X001ABCDEF
                    disposition: SELLABLE
                    shipped_quantity: 25
                    carrier: UPS
                    tracking_number: 1Z999AA10123456784
                    removal_order_type: Return
                    created_at: '2026-04-12T14:35:00.000000Z'
                    updated_at: '2026-04-12T14:35:00.000000Z'
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Not Found
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-amazon-integrationinstance-removal-shipments-removalshipment
  /api/amazon/{integrationInstance}/removal-shipments/{removalShipment}/receive:
    post:
      tags:
      - Amazon
      summary: Receive Shipment
      description: 'Record receipt of a removal shipment. Splits returned units into
        new (resellable), discarded (damaged), and optionally blemished. `items[].blemished_configurations`
        is an array where each entry represents ONE blemished unit. The shipment must
        belong to the supplied integration instance (404 otherwise).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Validation:

        - `receipt_date` — required, date

        - `items` — required, min:1

        - `items[].quantity_new` — required integer >= 0

        - `items[].quantity_discarded` — required integer >= 0

        - `items[].cogs_per_unit` — required numeric >= 0

        - `items[].product_id` — required, exists:products,id

        - `items[].removal_shipment_id` — nullable integer

        - `items[].quantity_blemished` — nullable integer >= 0

        - `items[].blemished_configurations` — nullable array'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                receipt_date:
                  type: string
                items:
                  type: array
                  items:
                    type: object
                    properties:
                      quantity_new:
                        type: integer
                      quantity_discarded:
                        type: integer
                      cogs_per_unit:
                        type: number
                      product_id:
                        type: integer
                      removal_shipment_id:
                        type: integer
                      quantity_blemished:
                        type: integer
                      blemished_configurations:
                        type: array
                        items:
                          type: object
                          properties:
                            reason:
                              type: string
                            discount_percent:
                              type: integer
              example:
                receipt_date: '2026-05-15'
                items:
                - quantity_new: 20
                  quantity_discarded: 2
                  cogs_per_unit: 4.75
                  product_id: 4567
                  removal_shipment_id: 12345
                  quantity_blemished: 3
                  blemished_configurations:
                  - reason: Damaged Packaging
                    discount_percent: 25
                  - reason: Damaged Packaging
                    discount_percent: 25
                  - reason: Used
                    discount_percent: 40
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Amazon integration instance ID
        example: '1'
      - name: removalShipment
        in: path
        schema:
          type: integer
        required: true
        description: AmazonFbaReportRemovalShipment ID to receive
        example: '12345'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      shipment_id:
                        type: integer
                      receipts_created:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            product_id:
                              type: integer
                            warehouse_id:
                              type: integer
                            quantity:
                              type: integer
                            type:
                              type: string
                            receipt_date:
                              type: string
                            cogs_per_unit:
                              type: number
                example:
                  data:
                    shipment_id: 12345
                    receipts_created:
                    - id: 88001
                      product_id: 4567
                      warehouse_id: 12
                      quantity: 20
                      type: new
                      receipt_date: '2026-05-15'
                      cogs_per_unit: 4.75
                    - id: 88002
                      product_id: 4567
                      warehouse_id: 12
                      quantity: 2
                      type: discarded
                      receipt_date: '2026-05-15'
                      cogs_per_unit: 4.75
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      receipt_date:
                        type: array
                        items:
                          type: string
                      items:
                        type: array
                        items:
                          type: string
                example:
                  message: The receipt date field is required.
                  errors:
                    receipt_date:
                    - The receipt date field is required.
                    items:
                    - The items field is required.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-amazon-integrationinstance-removal-shipments-removalshipment-receive
  /api/amazon/{integrationInstance}/removal-shipments/receive-bulk:
    post:
      tags:
      - Amazon
      summary: Bulk Receive Shipments
      description: 'Receive multiple removal shipments in one call, all into the same
        warehouse with the same receipt date. Each shipment must belong to the supplied
        integration instance — the controller validates this up-front and returns
        404 if any shipment is missing or belongs to another integration instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Validation:

        - `warehouse_id` — required, exists:warehouses,id

        - `receipt_date` — required, date

        - `shipments` — required, min:1

        - `shipments[].shipment_id` — required, exists:amazon_fba_report_removal_shipments,id

        - `shipments[].items` — required, min:1 — same item shape as the single receive
        endpoint.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                warehouse_id:
                  type: integer
                receipt_date:
                  type: string
                shipments:
                  type: array
                  items:
                    type: object
                    properties:
                      shipment_id:
                        type: integer
                      items:
                        type: array
                        items:
                          type: object
                          properties:
                            quantity_new:
                              type: integer
                            quantity_discarded:
                              type: integer
                            cogs_per_unit:
                              type: number
                            product_id:
                              type: integer
                            removal_shipment_id:
                              type: integer
                            quantity_blemished:
                              type: integer
                            blemished_configurations:
                              type: string
                              nullable: true
              example:
                warehouse_id: 12
                receipt_date: '2026-05-15'
                shipments:
                - shipment_id: 12345
                  items:
                  - quantity_new: 20
                    quantity_discarded: 2
                    cogs_per_unit: 4.75
                    product_id: 4567
                    removal_shipment_id: 12345
                    quantity_blemished: 0
                    blemished_configurations: null
                - shipment_id: 12346
                  items:
                  - quantity_new: 15
                    quantity_discarded: 0
                    cogs_per_unit: 8.1
                    product_id: 4568
                    removal_shipment_id: 12346
                    quantity_blemished: 1
                    blemished_configurations:
                    - reason: Damaged Packaging
                      discount_percent: 30
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Amazon integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      warehouse_id:
                        type: integer
                      receipt_date:
                        type: string
                      shipments_processed:
                        type: integer
                      receipts_created:
                        type: integer
                      shipment_ids:
                        type: array
                        items:
                          type: integer
                example:
                  data:
                    warehouse_id: 12
                    receipt_date: '2026-05-15'
                    shipments_processed: 2
                    receipts_created: 4
                    shipment_ids:
                    - 12345
                    - 12346
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-amazon-integrationinstance-removal-shipments-receive-bulk
  /api/amazon/{integrationInstance}/removal-shipments/{removalShipment}/remove-receipt:
    delete:
      tags:
      - Amazon
      summary: Remove Receipt (Single Shipment)
      description: 'Reverse the receipt for a single removal shipment, deleting the
        inventory adjustments created when it was received. Returns 404 if the shipment
        does not belong to the supplied integration instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Returns 422 when the receipt cannot be reversed:

        - it would consume stock hard-allocated to a shipment whose label cannot be
        voided (void it at the carrier first, or supply a `void_confirmations` entry
        to void it as part of the request), or

        - it would consume stock committed to another in-flight process (a warehouse
        transfer or an FBA inbound plan): cancel or adjust that transfer/plan first.


        If the received units have already been sold or consumed with no live reservation
        to release, the reversal fails with a server error (not a 422) — a data anomaly
        worth investigating rather than a routine rejection.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Amazon integration instance ID
        example: '1'
      - name: removalShipment
        in: path
        schema:
          type: integer
        required: true
        description: AmazonFbaReportRemovalShipment ID whose receipt should be removed
        example: '12345'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      shipment_id:
                        type: integer
                      receipts_removed:
                        type: integer
                      inventory_adjustments_deleted:
                        type: array
                        items:
                          type: integer
                example:
                  data:
                    shipment_id: 12345
                    receipts_removed: 2
                    inventory_adjustments_deleted:
                    - 88001
                    - 88002
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: This stock is committed to FBA Inbound Plan ABC — cancel
                    or adjust it first, otherwise that reservation would be stranded.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-amazon-integrationinstance-removal-shipments-removalshipment-remove-receipt
  /api/amazon/{integrationInstance}/removal-shipments/bulk-remove-receipts:
    post:
      tags:
      - Amazon
      summary: Bulk Remove Receipts
      description: 'Remove multiple receipts (inventory_adjustments rows) by ID for
        the given integration instance. Useful when undoing a batch of receipts at
        once.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Validation:

        - `receipt_ids` — required, array, min:1

        - `receipt_ids.*` — integer, exists:inventory_adjustments,id


        Returns 422 when the receipt cannot be reversed:

        - it would consume stock hard-allocated to a shipment whose label cannot be
        voided (void it at the carrier first, or supply a `void_confirmations` entry
        to void it as part of the request), or

        - it would consume stock committed to another in-flight process (a warehouse
        transfer or an FBA inbound plan): cancel or adjust that transfer/plan first.


        If the received units have already been sold or consumed with no live reservation
        to release, the reversal fails with a server error (not a 422) — a data anomaly
        worth investigating rather than a routine rejection.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                receipt_ids:
                  type: array
                  items:
                    type: integer
              example:
                receipt_ids:
                - 88001
                - 88002
                - 88003
                - 88004
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Amazon integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      integration_instance_id:
                        type: integer
                      receipt_ids_requested:
                        type: array
                        items:
                          type: integer
                      receipts_removed:
                        type: integer
                      shipments_affected:
                        type: array
                        items:
                          type: integer
                example:
                  data:
                    integration_instance_id: 1
                    receipt_ids_requested:
                    - 88001
                    - 88002
                    - 88003
                    - 88004
                    receipts_removed: 4
                    shipments_affected:
                    - 12345
                    - 12346
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: This stock is committed to FBA Inbound Plan ABC — cancel
                    or adjust it first, otherwise that reservation would be stranded.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-amazon-integrationinstance-removal-shipments-bulk-remove-receipts
  /api/amazon/{integrationInstance}/removal-shipment-discards/bulk-remove:
    post:
      tags:
      - Amazon
      summary: Bulk Remove Discards
      description: 'Bulk-remove discard records by their IDs for the given integration
        instance. Each deleted discard decrements the parent shipment''s `qty_discarded`
        counter so the legacy column stays in sync with the audit-trail rows. Discards
        belonging to shipments outside the supplied integration instance are silently
        skipped (not an error). After deletion, the removal order''s receipt_status
        is recomputed.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Validation:

        - `discard_ids` — required, array, min:1

        - `discard_ids.*` — integer


        Introduced alongside the first-class discards refactor that replaced the standalone
        `qty_discarded` counter with an auditable `amazon_fba_removal_shipment_discards`
        table.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                discard_ids:
                  type: array
                  items:
                    type: integer
              example:
                discard_ids:
                - 9001
                - 9002
                - 9003
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Amazon integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      integration_instance_id:
                        type: integer
                      discard_ids_requested:
                        type: array
                        items:
                          type: integer
                      discards_removed:
                        type: integer
                      total_quantity_restored:
                        type: integer
                      shipments_affected:
                        type: array
                        items:
                          type: integer
                      removed_discards:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            removal_shipment_id:
                              type: integer
                            product_id:
                              type: string
                              nullable: true
                            warehouse_id:
                              type: string
                              nullable: true
                            quantity:
                              type: integer
                            notes:
                              type: string
                              nullable: true
                example:
                  data:
                    integration_instance_id: 1
                    discard_ids_requested:
                    - 9001
                    - 9002
                    - 9003
                    discards_removed: 3
                    total_quantity_restored: 7
                    shipments_affected:
                    - 12345
                    - 12346
                    removed_discards:
                    - id: 9001
                      removal_shipment_id: 12345
                      product_id: null
                      warehouse_id: null
                      quantity: 2
                      notes: null
                    - id: 9002
                      removal_shipment_id: 12345
                      product_id: null
                      warehouse_id: null
                      quantity: 3
                      notes: Damaged on arrival
                    - id: 9003
                      removal_shipment_id: 12346
                      product_id: null
                      warehouse_id: null
                      quantity: 2
                      notes: null
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      discard_ids:
                        type: array
                        items:
                          type: string
                example:
                  message: The discard ids field must have at least 1 items.
                  errors:
                    discard_ids:
                    - The discard ids field must have at least 1 items.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-amazon-integrationinstance-removal-shipment-discards-bulk-remove
  /api/amazon/{integrationInstance}/removal-shipment-discards/{discard}:
    delete:
      tags:
      - Amazon
      summary: Remove Single Discard
      description: 'Remove a single discard record. The parent shipment''s `qty_discarded`
        counter is decremented by the deleted row''s quantity (backward-compat column
        kept in sync with the new `amazon_fba_removal_shipment_discards` audit table).
        Returns 404 if the discard does not belong to the supplied integration instance.
        After deletion, the removal order''s receipt_status is recomputed (e.g. an
        order that was `fully_discarded` may transition back to `pending` if there
        are no other discards or receipts).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Amazon integration instance ID
        example: '1'
      - name: discard
        in: path
        schema:
          type: integer
        required: true
        description: AmazonFbaRemovalShipmentDiscard ID to remove
        example: '9001'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      integration_instance_id:
                        type: integer
                      removed_discards_count:
                        type: integer
                      removed_quantity:
                        type: integer
                      affected_shipment_ids:
                        type: array
                        items:
                          type: integer
                      affected_order_ids:
                        type: array
                        items:
                          type: string
                      message:
                        type: string
                example:
                  data:
                    integration_instance_id: 1
                    removed_discards_count: 1
                    removed_quantity: 2
                    affected_shipment_ids:
                    - 12345
                    affected_order_ids:
                    - AMZ-REMOVAL-1234567
                    message: Discard removed successfully
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No query results for model [Modules\Amazon\Entities\AmazonFbaRemovalShipmentDiscard]
                    9001
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: delete-api-amazon-integrationinstance-removal-shipment-discards-discard
  /api/amazon/{integrationInstance}/removal-orders/{orderId}/undo-all-receipts:
    delete:
      tags:
      - Amazon
      summary: Undo All Receipts for Removal Order
      description: 'Undo every receipt across all shipments for a single Amazon removal
        order. The endpoint verifies that at least one shipment exists for the given
        `order_id` and integration instance, otherwise returns 404.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Voiding hard-allocated labels (`void_confirmations`):** When this removal
        would consume stock that is hard-allocated to a fulfillment (a printed shipping
        label), include a `void_confirmations` array in the request body — one entry
        per fulfillment you authorize voiding: `{ "fulfillment_id": <int>, "attempt_void":
        true, "reason": <string|null> }`. Each confirmed label is voided first so
        the removal can proceed. Omit `void_confirmations` (or leave out a fulfillment
        that is in the way) and the request is rejected with 422 when hard-allocated
        stock blocks the operation. Call the matching preview-impact endpoint first
        to see exactly which fulfillments block it.


        The request is also rejected with 422 when the stock is committed to another
        in-flight process (a warehouse transfer or an FBA inbound plan): cancel or
        adjust that transfer/plan first.


        If the received units have already been sold or consumed with no live reservation
        to release, the reversal fails with a server error (not a 422) — a data anomaly
        worth investigating rather than a routine rejection.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Amazon integration instance ID
        example: '1'
      - name: orderId
        in: path
        schema:
          type: string
        required: true
        description: Amazon removal order_id string (route uses `where('orderId',
          '.*')` so it accepts characters like `/` or `.`)
        example: AMZ-REMOVAL-1234567
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      integration_instance_id:
                        type: integer
                      order_id:
                        type: string
                      shipments_affected:
                        type: array
                        items:
                          type: integer
                      receipts_removed:
                        type: integer
                example:
                  data:
                    integration_instance_id: 1
                    order_id: AMZ-REMOVAL-1234567
                    shipments_affected:
                    - 12345
                    - 12346
                    receipts_removed: 4
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Removal order UNKNOWN not found or does not belong to integration
                    instance 1
        '422':
          description: Unprocessable Entity
          headers:
            undefined:
              schema:
                type: string
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 422 Protected Inventory Conflict
                  value:
                    message: Cannot take 100 units. Only 20 available after protecting
                      80 units allocated to submitted or acknowledged fulfillments.
                    conflict:
                      requested_quantity: 100
                      available_quantity: 20
                      protected_quantity: 80
                      conflicting_allocations:
                      - type: sales_order_fulfillment
                        id: 123
                        reference: SO-12345
                        quantity_allocated: 5
                        line_details:
                          sales_order_number: SO-12345
                          sales_order_line_id: 456
                          product_sku: ABC-123
                example-1:
                  summary: 422 Label Not Voidable
                  value:
                    message: 'Fulfillment #90142 can''t be voided (its label cannot
                      be voided), so this reduction isn''t allowed.'
                example-2:
                  summary: Committed To Another Process
                  value:
                    message: This stock is committed to FBA Inbound Plan ABC — cancel
                      or adjust it first, otherwise that reservation would be stranded.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: delete-api-amazon-integrationinstance-removal-orders-orderid-undo-all-receipts
  /api/amazon/{integrationInstance}/removal-shipments/{removalShipment}/reconcile-pretracking:
    post:
      tags:
      - Amazon
      summary: Reconcile Pre-Tracking Units (Straddle)
      description: 'Quarantine pre-tracking units on a STRADDLE removal shipment (one
        that shipped before the integration''s FBA inventory tracking start date).
        These units were already counted in opening inventory at go-live, so they
        are closed out into the `qty_reconciled_pretracking` bucket instead of being
        received into inventory — no stock, no COGS, no FBA ledger impact. Capped
        at the shipment''s remaining pending quantity.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        The shipment must belong to the supplied integration instance (404 otherwise).


        Validation:

        - `quantity` — required, integer, min:1

        - `notes` — nullable, string


        Errors:

        - 404 — shipment does not belong to the integration instance

        - 422 — shipment is not a straddle (post-go-live) shipment, or quantity exceeds
        remaining pending'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                quantity:
                  type: integer
                notes:
                  type: string
              example:
                quantity: 5
                notes: Counted in opening inventory at go-live
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Amazon integration instance ID
        example: '1'
      - name: removalShipment
        in: path
        schema:
          type: integer
        required: true
        description: AmazonFbaReportRemovalShipment ID (must be a straddle/pre-tracking
          shipment)
        example: '12345'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      removal_shipment_id:
                        type: integer
                      qty_reconciled_pretracking:
                        type: integer
                      pending_quantity:
                        type: integer
                      order_receipt_status:
                        type: string
                      message:
                        type: string
                example:
                  data:
                    removal_shipment_id: 12345
                    qty_reconciled_pretracking: 5
                    pending_quantity: 5
                    order_receipt_status: reconciled_at_go_live
                    message: Pre-tracking units reconciled successfully
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Not Found
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Cannot reconcile 7 units — only 6 pending units remain
                    on this shipment.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-amazon-integrationinstance-removal-shipments-removalshipment-reconcile-pretracking
    delete:
      tags:
      - Amazon
      summary: Undo Reconcile Pre-Tracking (Straddle)
      description: 'Undo a pre-tracking reconciliation: resets the shipment''s `qty_reconciled_pretracking`
        bucket back to zero and returns those units to pending. The shipment must
        belong to the supplied integration instance (404 otherwise).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        No request body.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Amazon integration instance ID
        example: '1'
      - name: removalShipment
        in: path
        schema:
          type: integer
        required: true
        description: AmazonFbaReportRemovalShipment ID
        example: '12345'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      removal_shipment_id:
                        type: integer
                      qty_reconciled_pretracking:
                        type: integer
                      pending_quantity:
                        type: integer
                      order_receipt_status:
                        type: string
                      message:
                        type: string
                example:
                  data:
                    removal_shipment_id: 12345
                    qty_reconciled_pretracking: 0
                    pending_quantity: 10
                    order_receipt_status: pending
                    message: Pre-tracking reconciliation undone successfully
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Not Found
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: delete-api-amazon-integrationinstance-removal-shipments-removalshipment-reconcile-pretracking
  /api/amazon/{integrationInstance}/inbound/shipments/{shipment}:
    get:
      tags:
      - Amazon
      summary: Show Inbound Shipment
      description: 'Get details of a specific legacy FBA inbound shipment, including
        its items (eager loaded), SKU link, integration instance, and counts for items
        and receipts. Powers the legacy inbound shipment detail page.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Additional fields exposed on the resource:

        - FromCountryCode

        - cached_shipment_date

        - destination_country (computed via getDestinationCountry)

        - status (lowercased enum value or raw ShipmentStatus)

        - items_count, receipts_count

        - items (collection of Amazon FBA inbound shipment item object)'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: shipment
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The shipment ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      integration_instance_name:
                        type: string
                      ShipmentId:
                        type: string
                      ShipmentName:
                        type: string
                      ShipFromName:
                        type: string
                      DestinationFulfillmentCenterId:
                        type: string
                      ShipmentStatus:
                        type: string
                      LabelPrepType:
                        type: string
                      BoxContentsSource:
                        type: string
                      FromCountryCode:
                        type: string
                      cached_shipment_date:
                        type: string
                      destination_country:
                        type: string
                      status:
                        type: string
                      errorLog:
                        type: string
                        nullable: true
                      is_before_initial_count:
                        type: boolean
                      sku_link:
                        type: object
                        properties:
                          id:
                            type: integer
                          type:
                            type: string
                          name:
                            type: string
                          displayType:
                            type: string
                      items_count:
                        type: integer
                      receipts_count:
                        type: integer
                      items:
                        type: array
                        items:
                          type: object
                          properties:
                            SellerSKU:
                              type: string
                            FulfillmentNetworkSKU:
                              type: string
                            QuantityShipped:
                              type: integer
                            item_name:
                              type: string
                            item_asin:
                              type: string
                            fnsku_product:
                              type: object
                              properties:
                                id:
                                  type: integer
                                fnsku:
                                  type: string
                                location:
                                  type: string
                                product:
                                  type: object
                                  properties:
                                    id:
                                      type: integer
                                    name:
                                      type: string
                                    sku:
                                      type: string
                                    inventory_available:
                                      type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 88
                    integration_instance_id: 3
                    integration_instance_name: Amazon US - Main
                    ShipmentId: FBA15XYZABC
                    ShipmentName: FBA (05/15/2026 10:22 AM) - 1 SKU(s)
                    ShipFromName: Main Warehouse
                    DestinationFulfillmentCenterId: PHX7
                    ShipmentStatus: CLOSED
                    LabelPrepType: SELLER_LABEL
                    BoxContentsSource: FEED
                    FromCountryCode: US
                    cached_shipment_date: '2026-05-15T10:22:00.000000Z'
                    destination_country: US
                    status: CLOSED
                    errorLog: null
                    is_before_initial_count: false
                    sku_link:
                      id: 5521
                      type: App\Models\Product
                      name: ACME-HOODIE-MD-BLU
                      displayType: Product
                    items_count: 2
                    receipts_count: 1
                    items:
                    - SellerSKU: ACME-HOODIE-MD-BLU
                      FulfillmentNetworkSKU: X001ABC123
                      QuantityShipped: 100
                      item_name: Acme Hoodie Medium Blue
                      item_asin: B07XYZ1234
                      fnsku_product:
                        id: 778
                        fnsku: X001ABC123
                        location: A-12-3
                        product:
                          id: 5521
                          name: Acme Hoodie Medium Blue
                          sku: ACME-HOODIE-MD-BLU
                          inventory_available: 240
                    created_at: '2026-05-15T10:22:00.000000Z'
                    updated_at: '2026-05-16T08:05:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-integrationinstance-inbound-shipments-shipment
    delete:
      tags:
      - Amazon
      summary: Delete Inbound Shipment
      description: 'Permanently delete a legacy FBA inbound shipment and its downloaded
        items. Deletion is blocked with a 422 response when the shipment is linked
        to a purchase order or warehouse transfer — unprocess the shipment first to
        remove the link. Deleting only removes the local record; the shipment on Amazon
        is unaffected and an active shipment can reappear on the next refresh.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: shipment
        in: path
        schema:
          type: integer
        required: true
        example: '6289'
        description: The shipment ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                example:
                  status: success
                  message: Inbound shipment deleted
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: object
                    properties:
                      sku_link:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: array
                  status:
                    type: string
                  message:
                    type: string
                example:
                  errors:
                    sku_link:
                    - message: Cannot delete this inbound shipment — it is linked
                        to a Purchase Order. Unprocess it first.
                      code: IsLinked
                      data: []
                  status: failure
                  message: Cannot delete this inbound shipment — it is linked to a
                    Purchase Order. Unprocess it first.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-amazon-integrationinstance-inbound-shipments-shipment
  /api/amazon/{integrationInstance}/inbound/shipments/{shipment}/activity-log:
    get:
      tags:
      - Amazon
      summary: Get Activity Log for Inbound Shipment
      description: 'Get the Spatie activity log for a specific legacy FBA inbound
        shipment. Returns the most recent 200 activities, newest first.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        The shipment model uses the Spatie LogsActivity trait and logs changes to:
        ShipmentStatus, ShipmentId, ShipmentName, ShipFromName, DestinationFulfillmentCenterId,
        FromCountryCode, sku_link_id, sku_link_type, is_before_initial_count, errorLog,
        cached_shipment_date.


        Each entry includes:

        - id, description, event (created/updated/deleted)

        - causer: { id, name } — the user who triggered the change, or null for system
        changes

        - properties: { old: {...}, attributes: {...} } — Spatie diff of changed fields

        - created_at


        Note: activity logging was added in this release — entries for older shipments
        will not be backfilled.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: shipment
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The shipment ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        description:
                          type: string
                        event:
                          type: string
                        causer:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        properties:
                          type: object
                          properties:
                            old:
                              type: object
                              properties:
                                ShipmentStatus:
                                  type: string
                            attributes:
                              type: object
                              properties:
                                ShipmentStatus:
                                  type: string
                        created_at:
                          type: string
                example:
                  data:
                  - id: 88231
                    description: updated
                    event: updated
                    causer:
                      id: 17
                      name: Kalvin Mizzi
                    properties:
                      old:
                        ShipmentStatus: IN_TRANSIT
                      attributes:
                        ShipmentStatus: DELIVERED
                    created_at: '2026-05-28T17:42:00.000000Z'
                  - id: 88102
                    description: updated
                    event: updated
                    causer: null
                    properties:
                      old:
                        errorLog: Rate limit
                      attributes:
                        errorLog: null
                    created_at: '2026-05-27T08:11:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-integrationinstance-inbound-shipments-shipment-activity-log
  /api/amazon/{integrationInstance}/inbound/shipments/{shipment}/items:
    get:
      tags:
      - Amazon
      summary: Get Items For Inbound Shipment
      description: 'Paginated list of items for a single legacy FBA inbound shipment.
        Powers the Items tab on the legacy shipment detail page using the canonical
        sku.io list view stack (server-side pagination, search, sort, advanced filters).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Supports Spatie QueryBuilder filters and sorts. The `filter[search]` parameter
        uses AdvancedSearchFilter to search across the item''s SellerSKU and FulfillmentNetworkSKU.


        Allowed sorts: id, SellerSKU, FulfillmentNetworkSKU, QuantityShipped, QuantityReceived,
        QuantityInCase, ReleaseDate. Prefix with `-` for descending order (e.g. `sort=-QuantityShipped`).


        Default page size is 25.'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        description: 'Page number (default: 1)'
        example: '1'
      - name: per_page
        in: query
        schema:
          type: integer
        description: 'Items per page (default: 25)'
        example: '25'
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: shipment
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The shipment ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        SellerSKU:
                          type: string
                        FulfillmentNetworkSKU:
                          type: string
                        QuantityShipped:
                          type: integer
                        item_name:
                          type: string
                        item_asin:
                          type: string
                        fnsku_product:
                          type: object
                          properties:
                            id:
                              type: integer
                            fnsku:
                              type: string
                            location:
                              type: string
                            product:
                              type: object
                              properties:
                                id:
                                  type: integer
                                name:
                                  type: string
                                sku:
                                  type: string
                                inventory_available:
                                  type: integer
                  current_page:
                    type: integer
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - SellerSKU: ACME-HOODIE-MD-BLU
                    FulfillmentNetworkSKU: X001ABC123
                    QuantityShipped: 100
                    item_name: Acme Hoodie Medium Blue
                    item_asin: B07XYZ1234
                    fnsku_product:
                      id: 778
                      fnsku: X001ABC123
                      location: A-12-3
                      product:
                        id: 5521
                        name: Acme Hoodie Medium Blue
                        sku: ACME-HOODIE-MD-BLU
                        inventory_available: 240
                  - SellerSKU: ACME-TEE-LG-RED
                    FulfillmentNetworkSKU: X002DEF456
                    QuantityShipped: 50
                    item_name: Acme Tee Large Red
                    item_asin: B08QWERTY2
                    fnsku_product: null
                  current_page: 1
                  first_page_url: '{{protocol}}{{domain}}/api/amazon/1/inbound/shipments/1/items?page=1'
                  from: 1
                  last_page: 1
                  next_page_url: null
                  path: '{{protocol}}{{domain}}/api/amazon/1/inbound/shipments/1/items'
                  per_page: 25
                  prev_page_url: null
                  to: 2
                  total: 2
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-integrationinstance-inbound-shipments-shipment-items
  /api/amazon/{integrationInstance}/inbound/shipments/{shipment}/receipts:
    get:
      tags:
      - Amazon
      summary: Get Inbound Shipment Receipts
      description: 'Paginated list of Receipt-type AmazonLedger entries for a single
        legacy FBA inbound shipment. Receipts are matched by integration_instance_id,
        reference_id (= shipment ShipmentId), and event_type = Receipts. Powers the
        Ledgers tab on the legacy shipment detail page.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Supports Spatie QueryBuilder filters and sorts. The `filter[search]` parameter
        uses AdvancedSearchFilter to search across msku/fnsku/asin/title/fulfillment_center.


        Allowed sorts: id, date, event_datetime, msku, fnsku, asin, quantity, reconciled_quantity,
        reconciled_at. Default: -event_datetime. Prefix with `-` for descending order.


        Note: legacy shipments may have zero linked receipts if the ledger→shipment
        linking job did not run for that period — in which case this endpoint returns
        an empty page.'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        description: 'Page number (default: 1)'
        example: '1'
      - name: per_page
        in: query
        schema:
          type: integer
        description: 'Items per page (default: 25)'
        example: '25'
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: shipment
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The shipment ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        msku:
                          type: string
                        fnsku:
                          type: string
                        asin:
                          type: string
                        title:
                          type: string
                        event_type:
                          type: string
                        event_datetime:
                          type: string
                        reference_id:
                          type: string
                        fulfillment_center:
                          type: string
                        quantity:
                          type: integer
                        reconciled_quantity:
                          type: integer
                        reconciled_at:
                          type: string
                        disposition:
                          type: string
                  current_page:
                    type: integer
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 9981
                    msku: ACME-HOODIE-MD-BLU
                    fnsku: X001ABC123
                    asin: B07XYZ1234
                    title: Acme Hoodie Medium Blue
                    event_type: Receipts
                    event_datetime: '2026-05-16T08:00:00.000000Z'
                    reference_id: FBA15XYZABC
                    fulfillment_center: PHX7
                    quantity: 100
                    reconciled_quantity: 100
                    reconciled_at: '2026-05-16T09:30:00.000000Z'
                    disposition: SELLABLE
                  current_page: 1
                  first_page_url: '{{protocol}}{{domain}}/api/amazon/1/inbound/shipments/1/receipts?page=1'
                  from: 1
                  last_page: 1
                  next_page_url: null
                  path: '{{protocol}}{{domain}}/api/amazon/1/inbound/shipments/1/receipts'
                  per_page: 25
                  prev_page_url: null
                  to: 1
                  total: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-integrationinstance-inbound-shipments-shipment-receipts
  /api/amazon/{integrationInstance}/inbound/shipments/refresh:
    post:
      tags:
      - Amazon
      summary: Refresh Inbound Shipments
      description: 'Refresh FBA inbound shipments from Amazon API.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Refresh started
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-amazon-integrationinstance-inbound-shipments-refresh
  /api/amazon/{integrationInstance}/inbound/process:
    post:
      tags:
      - Amazon
      summary: Process Shipments
      description: 'Process FBA inbound shipments.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                shipment_ids:
                  type: array
                  items:
                    type: integer
              example:
                shipment_ids:
                - 1
                - 2
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Shipments processed
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-amazon-integrationinstance-inbound-process
  /api/amazon/{integrationInstance}/inbound/process-all:
    post:
      tags:
      - Amazon
      summary: Process All Shipments
      description: 'Process all unprocessed FBA inbound shipments.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: All shipments processing started
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-amazon-integrationinstance-inbound-process-all
  /api/amazon/{integrationInstance}/inbound/unprocess:
    post:
      tags:
      - Amazon
      summary: Unprocess Shipments
      description: 'Unprocess FBA inbound shipments.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Returns 422 when a selected shipment is linked to a purchase order that has
        purchase invoices attached - the invoices must be deleted before the shipment
        can be unprocessed.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1
                - 2
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Shipments unprocessed
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Cannot delete purchase order FBA17WHH38R2 because it has
                    invoices. Please delete the invoices first.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-amazon-integrationinstance-inbound-unprocess
  /api/amazon/{integrationInstance}/inbound/shipments/unlinked:
    get:
      tags:
      - Amazon
      summary: Get Unlinked Shipments
      description: 'Get unlinked FBA inbound shipments.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        shipment_id:
                          type: string
                        status:
                          type: string
                example:
                  data:
                  - id: 1
                    shipment_id: FBA15N999999
                    status: SHIPPED
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-integrationinstance-inbound-shipments-unlinked
  /api/amazon/{integrationInstance}/inbound/shipments/set-sent-before-initial-count:
    post:
      tags:
      - Amazon
      summary: Set Sent Before Initial Count
      description: 'Mark shipments as sent before the initial count was taken.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                shipment_ids:
                  type: array
                  items:
                    type: integer
                sent_before_initial_count:
                  type: boolean
              example:
                shipment_ids:
                - 1
                - 2
                sent_before_initial_count: true
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Updated
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-amazon-integrationinstance-inbound-shipments-set-sent-before-initial-count
  /api/amazon/{integrationInstance}/inbound/shipments/get-shipment:
    post:
      tags:
      - Amazon
      summary: Get Shipment from Amazon
      description: 'Fetch a specific shipment directly from Amazon API by shipment
        ID.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                shipment_id:
                  type: string
              example:
                shipment_id: FBA15N123456
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      shipment_id:
                        type: string
                      status:
                        type: string
                example:
                  data:
                    shipment_id: FBA15N123456
                    status: SHIPPED
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-amazon-integrationinstance-inbound-shipments-get-shipment
  /api/amazon/{integrationInstance}/inbound/shipments/{shipment}/process-preview:
    get:
      tags:
      - Amazon
      summary: Preview Process with Stock Take
      description: 'Preview the covering stock take that the "Process with Stock Take"
        action would create for this legacy FBA inbound. Resolves the source warehouse
        (from the ship-from mapping) and destination FBA warehouse, aggregates the
        inbound''s items per product, and computes each product''s source-warehouse
        shortfall (max(0, needed − on-hand available).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Returns:

        - `can_process` (bool) — false when any hard blocker is present

        - `source_warehouse` / `destination_warehouse` — {id, name} or null when unresolved

        - `lines[]` — per-product {line_id, sku, product_id, needed_qty, current_available,
        shortfall}

        - `skipped_lines[]` — unmapped inbound lines that will be ignored {line_id,
        sku, reason}

        - `blockers[]` — hard blockers as {code, message}; codes: NoSourceWarehouse,
        IneligibleStatus, AlreadyProcessed, AwdSource, PoRouted, NoMappedLines

        - `totals` — {units, shortfall}


        This is a read-only computation — it does not create a stock take or mutate
        inventory. Use it to populate the confirm dialog and to disable the confirm
        button (with the blocker message as the tooltip reason) when `can_process`
        is false.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: shipment
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The shipment ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      can_process:
                        type: boolean
                      source_warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      destination_warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      lines:
                        type: array
                        items:
                          type: object
                          properties:
                            line_id:
                              type: integer
                            sku:
                              type: string
                            product_id:
                              type: integer
                            needed_qty:
                              type: integer
                            current_available:
                              type: integer
                            shortfall:
                              type: integer
                      skipped_lines:
                        type: array
                        items:
                          type: object
                          properties:
                            line_id:
                              type: integer
                            sku:
                              type: string
                            reason:
                              type: string
                      blockers:
                        type: array
                      totals:
                        type: object
                        properties:
                          units:
                            type: integer
                          shortfall:
                            type: integer
                example:
                  data:
                    can_process: true
                    source_warehouse:
                      id: 3
                      name: Main Warehouse
                    destination_warehouse:
                      id: 8
                      name: Amazon FBA (US)
                    lines:
                    - line_id: 4471
                      sku: ACME-HOODIE-MD-BLU
                      product_id: 1024
                      needed_qty: 100
                      current_available: 60
                      shortfall: 40
                    - line_id: 4472
                      sku: ACME-TEE-LG-RED
                      product_id: 1025
                      needed_qty: 50
                      current_available: 50
                      shortfall: 0
                    skipped_lines:
                    - line_id: 4473
                      sku: UNMAPPED-SKU-XYZ
                      reason: No matching product found for this line
                    blockers: []
                    totals:
                      units: 150
                      shortfall: 40
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-integrationinstance-inbound-shipments-shipment-process-preview
  /api/amazon/{integrationInstance}/inbound/shipments/{shipment}/process-with-stock-take:
    post:
      tags:
      - Amazon
      summary: Process Inbound with Stock Take
      description: 'Dispatch the tracked job that injects each product''s source-warehouse
        shortfall via a covering stock take and then processes the legacy FBA inbound
        into its warehouse transfer (source warehouse → FBA warehouse).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        The covering stock take runs in adjustment mode with backorder auto-release
        SUPPRESSED, and the source inventory pool lock is held across inject→process
        so the injected units flow into the transfer''s own Allocated reservation
        and are never stolen by a pending backorder. No InventoryHold is used.


        Request body (both optional):

        - `notes` (string, max 1000) — appended to the covering stock take''s note

        - `source_warehouse_id` (integer, exists:warehouses) — overrides the resolved
        source warehouse


        Returns the tracked job log ID so the frontend can follow progress via the
        tracked job log endpoints (job name: "Process FBA Inbound with Stock Take:
        {ShipmentConfirmationId}"). The operation is idempotent — a shipment already
        linked to a transfer returns early without creating a second stock take.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                notes:
                  type: string
                source_warehouse_id:
                  type: integer
              example:
                notes: Covering stock take for FBA15XYZABC
                source_warehouse_id: 3
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: shipment
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The shipment ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 123
                  message: Processing inbound with stock take — track progress in
                    the job tray
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-amazon-integrationinstance-inbound-shipments-shipment-process-with-stock-take
  /api/amazon/{integrationInstance}/inbound/shipments/delete:
    post:
      tags:
      - Amazon
      summary: Bulk Delete Inbound Shipments
      description: 'Bulk delete legacy FBA inbound shipments by ID. Shipments that
        are linked to a purchase order or warehouse transfer are skipped and returned
        in the blocked array; unprocess them first to remove the link. Deleting only
        removes the local records; the shipments on Amazon are unaffected.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 6289
                - 6290
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      deleted:
                        type: integer
                      blocked:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            ShipmentId:
                              type: string
                            sku_link_type:
                              type: string
                  status:
                    type: string
                  message:
                    type: string
                example:
                  data:
                    deleted: 1
                    blocked:
                    - id: 6290
                      ShipmentId: FBA17WHH38R2
                      sku_link_type: Purchase Order
                  status: success
                  message: 1 inbound shipment(s) deleted — 1 skipped (linked to a
                    purchase order / warehouse transfer)
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-amazon-integrationinstance-inbound-shipments-delete
  /api/amazon/{integrationInstance}/new-inbound/shipments/{shipment}:
    get:
      tags:
      - Amazon
      summary: Show New Inbound Shipment
      description: 'Get a specific new FBA inbound shipment with full detail.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Eager loads: amazonFbaInboundShipmentItems.amazonProduct, skuLink, receipts,
        integrationInstance, shipFromMapping.link, pendingInbound.


        Response includes:

        - Identifiers: shipmentId, shipmentConfirmationId, amazonReferenceId, name,
        sourceName

        - Status fields: status, pending_status, errorLog, is_before_initial_count,
        is_archived, archived_at

        - Destination: destinationCountry, destinationWarehouse, destinationType,
        destinationAddress, destination

        - Transportation/placement IDs and cached_shipment_date

        - sku_link: the user-bound source (PurchaseOrder or WarehouseTransfer) — polymorphic
        with id, type, name, displayType

        - actual_source: resolved from sku_link (Supplier for PO, Warehouse for WT)
        — { name, type, link_type, link_id, route }

        - ship_from_mapping: current mapping target — UI compares to actual_source
        to detect divergence and strike-through the current mapping when they differ

        - pending_inbound: linked PendingInbound row with status/shipped_at

        - receipts: linked inventory receipt/ledger entries

        - items: per-line with id, msku, fnsku, quantity, item_name, item_asin, amazon_product_id,
        fnsku_product (with product + inventory_available when ship-from is a Warehouse)


        Shelf-life compliance: the shipment includes aggregate `shelf_life_warnings_count`
        and `has_shelf_life_warnings`. Each item carries `shelf_life_compliance` (or
        null when the product is not lot-tracked, has no dated source lots, or ships
        from a non-warehouse source). The compliance object reports `expiry_date`,
        `remaining_shelf_life_days`, `min_remaining_shelf_life_days`, `is_compliant`,
        `will_be_auto_disposed` (within Amazon''s 50-day auto-disposal window), and
        `disposal_window_days`.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: shipment
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The shipment ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      integration_instance_name:
                        type: string
                      shipmentId:
                        type: string
                      shipmentConfirmationId:
                        type: string
                      amazonReferenceId:
                        type: string
                      name:
                        type: string
                      sourceName:
                        type: string
                      status:
                        type: string
                      pending_status:
                        type: string
                      errorLog:
                        type: string
                        nullable: true
                      is_before_initial_count:
                        type: boolean
                      is_archived:
                        type: boolean
                      archived_at:
                        type: string
                        nullable: true
                      destinationCountry:
                        type: string
                      destinationWarehouse:
                        type: string
                      destinationType:
                        type: string
                      destinationAddress:
                        type: string
                      destination:
                        type: object
                        properties:
                          warehouse:
                            type: string
                          country:
                            type: string
                          address:
                            type: string
                      selectedTransportationOptionId:
                        type: string
                      placementOptionId:
                        type: string
                      cached_shipment_date:
                        type: string
                      sku_link:
                        type: object
                        properties:
                          id:
                            type: integer
                          type:
                            type: string
                          name:
                            type: string
                          displayType:
                            type: string
                      actual_source:
                        type: object
                        properties:
                          name:
                            type: string
                          type:
                            type: string
                          link_type:
                            type: string
                          link_id:
                            type: integer
                          route:
                            type: string
                      ship_from_mapping:
                        type: object
                        properties:
                          name:
                            type: string
                          mapping_id:
                            type: integer
                          target:
                            type: object
                            properties:
                              name:
                                type: string
                              type:
                                type: string
                              link_type:
                                type: string
                              link_id:
                                type: integer
                              route:
                                type: string
                      pending_inbound:
                        type: object
                        properties:
                          id:
                            type: integer
                          status:
                            type: string
                          shipped_at:
                            type: string
                      receipts:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            quantity:
                              type: integer
                            created_at:
                              type: string
                      items:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            msku:
                              type: string
                            fnsku:
                              type: string
                            quantity:
                              type: integer
                            item_name:
                              type: string
                            item_asin:
                              type: string
                            amazon_product_id:
                              type: integer
                            fnsku_product:
                              type: object
                              properties:
                                id:
                                  type: integer
                                fnsku:
                                  type: string
                                location:
                                  type: string
                                product:
                                  type: object
                                  properties:
                                    id:
                                      type: integer
                                    name:
                                      type: string
                                    sku:
                                      type: string
                                    inventory_available:
                                      type: integer
                            shelf_life_compliance:
                              type: object
                              properties:
                                expiry_date:
                                  type: string
                                remaining_shelf_life_days:
                                  type: integer
                                min_remaining_shelf_life_days:
                                  type: integer
                                is_compliant:
                                  type: boolean
                                will_be_auto_disposed:
                                  type: boolean
                                disposal_window_days:
                                  type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      shelf_life_warnings_count:
                        type: integer
                      has_shelf_life_warnings:
                        type: boolean
                example:
                  data:
                    id: 101
                    integration_instance_id: 3
                    integration_instance_name: Amazon US - Main
                    shipmentId: sps-1234-5678-90ab
                    shipmentConfirmationId: FBA17ABCXYZ
                    amazonReferenceId: AMZN-REF-9988
                    name: FBA STA (06/01/2026) - Main Warehouse
                    sourceName: Main Warehouse
                    status: WORKING
                    pending_status: READY_TO_SHIP
                    errorLog: null
                    is_before_initial_count: false
                    is_archived: false
                    archived_at: null
                    destinationCountry: US
                    destinationWarehouse: LEX1
                    destinationType: SELLER
                    destinationAddress: 1850 Mercer Rd, Lexington, KY 40511, US
                    destination:
                      warehouse: LEX1
                      country: US
                      address: 1850 Mercer Rd, Lexington, KY 40511, US
                    selectedTransportationOptionId: to-aaaa-bbbb
                    placementOptionId: po-cccc-dddd
                    cached_shipment_date: '2026-06-01T00:00:00.000000Z'
                    sku_link:
                      id: 442
                      type: App\Models\PurchaseOrder
                      name: PO-2026-0442
                      displayType: Purchase Order
                    actual_source:
                      name: Acme Manufacturing Co.
                      type: Supplier
                      link_type: App\Models\Supplier
                      link_id: 88
                      route: /crm/suppliers/88
                    ship_from_mapping:
                      name: Main Warehouse
                      mapping_id: 17
                      target:
                        name: Main Warehouse
                        type: Warehouse
                        link_type: App\Models\Warehouse
                        link_id: 4
                        route: /crm/warehouses/4
                    pending_inbound:
                      id: 2210
                      status: shipped
                      shipped_at: '2026-05-28T17:42:00.000000Z'
                    receipts:
                    - id: 9981
                      quantity: 100
                      created_at: '2026-05-30T11:00:00.000000Z'
                    items:
                    - id: 9101
                      msku: ACME-HOODIE-MD-BLU
                      fnsku: X001ABC123
                      quantity: 100
                      item_name: Acme Hoodie Medium Blue
                      item_asin: B07XYZ1234
                      amazon_product_id: 552
                      fnsku_product:
                        id: 778
                        fnsku: X001ABC123
                        location: A-12-3
                        product:
                          id: 5521
                          name: Acme Hoodie Medium Blue
                          sku: ACME-HOODIE-MD-BLU
                          inventory_available: 240
                      shelf_life_compliance:
                        expiry_date: '2026-07-20'
                        remaining_shelf_life_days: 49
                        min_remaining_shelf_life_days: 105
                        is_compliant: false
                        will_be_auto_disposed: true
                        disposal_window_days: 50
                    created_at: '2026-05-20T14:30:00.000000Z'
                    updated_at: '2026-05-21T09:15:00.000000Z'
                    shelf_life_warnings_count: 1
                    has_shelf_life_warnings: true
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-integrationinstance-new-inbound-shipments-shipment
  /api/amazon/{integrationInstance}/new-inbound/shipments/{shipment}/activity-log:
    get:
      tags:
      - Amazon
      summary: Get Activity Log for New Inbound Shipment
      description: 'Get the Spatie activity log for a specific new FBA inbound shipment.
        Returns the most recent 200 activities, newest first.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        The shipment model uses the Spatie LogsActivity trait and logs changes to
        fields including status, sku_link_id, sku_link_type, shipmentConfirmationId,
        amazonReferenceId, shipmentId, selectedTransportationOptionId, placementOptionId,
        is_before_initial_count, archived_at, errorLog, cached_shipment_date.


        Each entry includes:

        - id, description, event (created/updated/deleted)

        - causer: { id, name } — the user who triggered the change, or null for system
        changes

        - properties: { old: {...}, attributes: {...} } — Spatie diff of changed fields

        - created_at'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: shipment
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The shipment ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        description:
                          type: string
                        event:
                          type: string
                        causer:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        properties:
                          type: object
                          properties:
                            old:
                              type: object
                              properties:
                                status:
                                  type: string
                            attributes:
                              type: object
                              properties:
                                status:
                                  type: string
                        created_at:
                          type: string
                example:
                  data:
                  - id: 88231
                    description: updated
                    event: updated
                    causer:
                      id: 17
                      name: Kalvin Mizzi
                    properties:
                      old:
                        status: WORKING
                      attributes:
                        status: SHIPPED
                    created_at: '2026-05-28T17:42:00.000000Z'
                  - id: 88102
                    description: updated
                    event: updated
                    causer: null
                    properties:
                      old:
                        errorLog: Rate limit
                      attributes:
                        errorLog: null
                    created_at: '2026-05-27T08:11:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-integrationinstance-new-inbound-shipments-shipment-activity-log
  /api/amazon/{integrationInstance}/new-inbound/shipments/{shipment}/items:
    get:
      tags:
      - Amazon
      summary: Get Items For Shipment
      description: 'Paginated list of items for a single new FBA inbound shipment.
        Powers the Items tab on the shipment detail page using the canonical sku.io
        list view stack (server-side pagination, search, sort, advanced filters, saved
        views, column selector).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Supports Spatie QueryBuilder filters and sorts. The `filter[search]` parameter
        uses AdvancedSearchFilter to search across the item''s msku/fnsku/asin and
        the related amazonProduct''s item_name/asin1.


        Allowed sorts: id, msku, fnsku, asin, quantity. Prefix with `-` for descending
        order (e.g. `sort=-quantity`).


        Default page size is 25.


        Shelf-life compliance: each item carries `shelf_life_compliance` — `expiry_date`,
        `remaining_shelf_life_days`, `min_remaining_shelf_life_days`, `is_compliant`,
        `will_be_auto_disposed` (within Amazon''s 50-day auto-disposal window), `disposal_window_days`
        — or null when the product is not lot-tracked, has no dated source lots, or
        ships from a non-warehouse source.'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        description: 'Page number (default: 1)'
        example: '1'
      - name: per_page
        in: query
        schema:
          type: integer
        description: 'Items per page (default: 25)'
        example: '25'
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: shipment
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The shipment ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        msku:
                          type: string
                        fnsku:
                          type: string
                        quantity:
                          type: integer
                        item_name:
                          type: string
                        item_asin:
                          type: string
                        amazon_product_id:
                          type: integer
                        fnsku_product:
                          type: object
                          properties:
                            id:
                              type: integer
                            fnsku:
                              type: string
                            location:
                              type: string
                            product:
                              type: object
                              properties:
                                id:
                                  type: integer
                                name:
                                  type: string
                                sku:
                                  type: string
                                inventory_available:
                                  type: integer
                        shelf_life_compliance:
                          type: object
                          properties:
                            expiry_date:
                              type: string
                            remaining_shelf_life_days:
                              type: integer
                            min_remaining_shelf_life_days:
                              type: integer
                            is_compliant:
                              type: boolean
                            will_be_auto_disposed:
                              type: boolean
                            disposal_window_days:
                              type: integer
                  current_page:
                    type: integer
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 1001
                    msku: SKU-12345
                    fnsku: X001ABCDEF
                    quantity: 24
                    item_name: Acme Widget 4-Pack
                    item_asin: B07ABCXYZ1
                    amazon_product_id: 4421
                    fnsku_product:
                      id: 882
                      fnsku: X001ABCDEF
                      location: AISLE-7
                      product:
                        id: 5571
                        name: Acme Widget 4-Pack
                        sku: AW-4PK
                        inventory_available: 152
                    shelf_life_compliance:
                      expiry_date: '2026-11-15'
                      remaining_shelf_life_days: 167
                      min_remaining_shelf_life_days: 105
                      is_compliant: true
                      will_be_auto_disposed: false
                      disposal_window_days: 50
                  - id: 1002
                    msku: SKU-67890
                    fnsku: X002GHIJKL
                    quantity: 8
                    item_name: Acme Gizmo Standard
                    item_asin: B08QWERTY2
                    amazon_product_id: 4520
                    fnsku_product: null
                    shelf_life_compliance: null
                  current_page: 1
                  first_page_url: '{{protocol}}{{domain}}/api/amazon/1/new-inbound/shipments/1/items?page=1'
                  from: 1
                  last_page: 1
                  next_page_url: null
                  path: '{{protocol}}{{domain}}/api/amazon/1/new-inbound/shipments/1/items'
                  per_page: 25
                  prev_page_url: null
                  to: 2
                  total: 2
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-integrationinstance-new-inbound-shipments-shipment-items
  /api/amazon/{integrationInstance}/new-inbound/shipments/{shipment}/receipts:
    get:
      tags:
      - Amazon
      summary: Get New Inbound Shipment Receipts
      description: 'Paginated list of receipt ledger entries for a single new FBA
        inbound shipment. Powers the Ledgers tab on the shipment detail page using
        the canonical sku.io list view stack (server-side pagination, search, sort,
        advanced filters, saved views, column selector).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Receipts are AmazonLedger rows scoped by:

        - `event_type` = ''Receipts''

        - `integration_instance_id` = shipment.integration_instance_id

        - `reference_id` = shipment.shipmentConfirmationId


        Supports Spatie QueryBuilder filters and sorts. The `filter[search]` parameter
        uses AdvancedSearchFilter to search across msku, fnsku, asin, and title.


        Allowed sorts: id, date, event_datetime, msku, fnsku, asin, quantity, reconciled_quantity,
        reconciled_at. Prefix with `-` for descending order (e.g. `sort=-event_datetime`).
        Default sort is `-event_datetime`.


        Default page size is 25.


        The `status` filter accepts ''reconciled'' or ''unreconciled'' which maps
        to reconciled_at IS NOT NULL / IS NULL respectively.


        Date filters use m/d/Y format (e.g. 05/15/2026).'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        description: 'Page number (default: 1)'
        example: '1'
      - name: per_page
        in: query
        schema:
          type: integer
        description: 'Items per page (default: 25)'
        example: '25'
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: shipment
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The shipment ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        event_type:
                          type: string
                        quantity:
                          type: integer
                        event_datetime:
                          type: string
                        date:
                          type: string
                        fnsku:
                          type: string
                        asin:
                          type: string
                        msku:
                          type: string
                        title:
                          type: string
                        country:
                          type: string
                        disposition:
                          type: string
                        reference_id:
                          type: string
                        reconciled_at:
                          type: string
                        reconciled_quantity:
                          type: integer
                        unreconciled_quantity:
                          type: integer
                        status:
                          type: string
                        fulfillment_center:
                          type: string
                        reason:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                        updated_at:
                          type: string
                        computed_cogs:
                          type: number
                        computed_extended_cogs:
                          type: integer
                  current_page:
                    type: integer
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 5501
                    event_type: Receipts
                    quantity: 24
                    event_datetime: '2026-05-22T14:30:00.000000Z'
                    date: '2026-05-22'
                    fnsku: X001ABCDEF
                    asin: B07ABCXYZ1
                    msku: SKU-12345
                    title: Acme Widget 4-Pack
                    country: US
                    disposition: SELLABLE
                    reference_id: FBA17ABCXYZ
                    reconciled_at: '2026-05-23T10:15:00.000000Z'
                    reconciled_quantity: 24
                    unreconciled_quantity: 0
                    status: reconciled
                    fulfillment_center: LEX1
                    reason: null
                    created_at: '2026-05-22T15:00:00.000000Z'
                    updated_at: '2026-05-23T10:15:00.000000Z'
                    computed_cogs: 4.75
                    computed_extended_cogs: 114
                  - id: 5502
                    event_type: Receipts
                    quantity: 8
                    event_datetime: '2026-05-22T14:30:00.000000Z'
                    date: '2026-05-22'
                    fnsku: X002GHIJKL
                    asin: B08QWERTY2
                    msku: SKU-67890
                    title: Acme Gizmo Standard
                    country: US
                    disposition: SELLABLE
                    reference_id: FBA17ABCXYZ
                    reconciled_at: null
                    reconciled_quantity: 0
                    unreconciled_quantity: 8
                    status: unreconciled
                    fulfillment_center: LEX1
                    reason: null
                    created_at: '2026-05-22T15:00:00.000000Z'
                    updated_at: '2026-05-22T15:00:00.000000Z'
                    computed_cogs: null
                    computed_extended_cogs: null
                  current_page: 1
                  first_page_url: '{{protocol}}{{domain}}/api/amazon/1/new-inbound/shipments/1/receipts?page=1'
                  from: 1
                  last_page: 1
                  next_page_url: null
                  path: '{{protocol}}{{domain}}/api/amazon/1/new-inbound/shipments/1/receipts'
                  per_page: 25
                  prev_page_url: null
                  to: 2
                  total: 2
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-integrationinstance-new-inbound-shipments-shipment-receipts
  /api/amazon/{integrationInstance}/new-inbound/shipments/process:
    post:
      tags:
      - Amazon
      summary: Process New Inbound Shipments
      description: 'Process the given new FBA inbound shipments. For each ID this
        resolves the SKU link source (purchase order or warehouse transfer), creates
        / updates the linked PendingInbound, and applies inventory movement.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Response behaviour:

        - All succeed → 200 with success message and the processed shipments

        - Mix of success + failure → 207 Multi-Status, message lists the unique errors
        and processed shipments are returned

        - All fail → 422 with combined error message

        - Hard exception (e.g. integration not connected) → 422 with single error
        message


        The per-shipment errorLog field on each returned resource is the source of
        truth for partial failures.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 101
                - 102
                - 103
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        status:
                          type: string
                        pending_status:
                          type: string
                        errorLog:
                          type: string
                          nullable: true
                example:
                  message: Inbound shipments processed
                  data:
                  - id: 101
                    status: SHIPPED
                    pending_status: shipped
                    errorLog: null
                  - id: 102
                    status: SHIPPED
                    pending_status: shipped
                    errorLog: null
        '207':
          description: Multi-Status
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        status:
                          type: string
                        errorLog:
                          type: string
                          nullable: true
                example:
                  message: 'Processed 1 shipment(s) successfully, but 1 failed. Errors:
                    SKU link not set'
                  data:
                  - id: 101
                    status: SHIPPED
                    errorLog: null
                  - id: 102
                    status: WORKING
                    errorLog: SKU link not set
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-amazon-integrationinstance-new-inbound-shipments-process
  /api/amazon/{integrationInstance}/new-inbound/shipments/process-all:
    post:
      tags:
      - Amazon
      summary: Process All Unprocessed New Inbound Shipments
      description: 'Process every unprocessed new FBA inbound shipment for this integration
        instance. Returns immediately with a success message regardless of per-shipment
        outcomes — check the index endpoint afterwards to see updated statuses and
        any errorLog entries.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties: {}
              example: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Inbound shipments processed
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-amazon-integrationinstance-new-inbound-shipments-process-all
  /api/amazon/{integrationInstance}/new-inbound/shipments/unprocess:
    post:
      tags:
      - Amazon
      summary: Unprocess New Inbound Shipments
      description: 'Reverse the processing of the given new FBA inbound shipments.
        Detaches PendingInbound rows and reverses any inventory movement that was
        created when the shipments were processed.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Returns 422 when a selected shipment is linked to a purchase order that has
        purchase invoices attached - the invoices must be deleted before the shipment
        can be unprocessed.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 101
                - 102
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Inbound shipments unprocessed
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Cannot delete purchase order FBA17WHH38R2 because it has
                    invoices. Please delete the invoices first.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-amazon-integrationinstance-new-inbound-shipments-unprocess
  /api/amazon/{integrationInstance}/new-inbound/shipments/archive:
    post:
      tags:
      - Amazon
      summary: Archive New Inbound Shipments
      description: 'Archive the given new FBA inbound shipments by setting archived_at
        to now. Archived shipments are hidden from the default list view but remain
        in the database for audit/history. Returns the count actually archived.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 101
                - 102
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Archived 2 inbound shipments
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-amazon-integrationinstance-new-inbound-shipments-archive
  /api/amazon/{integrationInstance}/new-inbound/shipments/unlinked:
    get:
      tags:
      - Amazon
      summary: Get Unlinked New Inbound Shipments
      description: 'List new FBA inbound shipments for this integration instance that
        have not been linked to a SKU source (no purchase order or warehouse transfer
        assigned). Used by the UI to surface shipments that still need source assignment
        before they can be processed.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        shipmentConfirmationId:
                          type: string
                        sourceName:
                          type: string
                        status:
                          type: string
                        created_at:
                          type: string
                example:
                  data:
                  - id: 215
                    shipmentConfirmationId: FBA17UNLINKED1
                    sourceName: East Coast Warehouse
                    status: WORKING
                    created_at: '2026-05-22T10:00:00.000000Z'
                  - id: 216
                    shipmentConfirmationId: FBA17UNLINKED2
                    sourceName: West Coast Warehouse
                    status: WORKING
                    created_at: '2026-05-23T09:30:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-integrationinstance-new-inbound-shipments-unlinked
  /api/amazon/{integrationInstance}/new-inbound/shipments/set-sent-before-initial-count:
    post:
      tags:
      - Amazon
      summary: Set Sent Before Initial Count
      description: 'Bulk toggle the is_before_initial_count flag on the given shipments.
        Pass value as the string ''true'' or ''false''. When set, the shipment is
        treated as sent prior to the integration''s initial inventory count and excluded
        from inbound inventory math. Also clears the errorLog on the affected shipments.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
                value:
                  type: string
              example:
                ids:
                - 101
                - 102
                value: 'true'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Inbound shipments updated
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-amazon-integrationinstance-new-inbound-shipments-set-sent-before-initial-count
  /api/amazon/{integrationInstance}/new-inbound/shipments/unarchive:
    post:
      tags:
      - Amazon
      summary: Unarchive New Inbound Shipments
      description: 'Restore previously archived shipments by clearing archived_at.
        Returns the count actually unarchived.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 101
                - 102
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Unarchived 2 inbound shipments
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-amazon-integrationinstance-new-inbound-shipments-unarchive
  /api/amazon/{integrationInstance}/draft-inbound-plans/list:
    get:
      tags:
      - Amazon
      summary: List Draft Plans (Drafts Tab)
      description: 'Paginated Drafts-tab listing for the list view.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Scope:** in-progress drafts that have NOT yet been submitted to Amazon (no
        linked Amazon plan) — plus ABORTED drafts regardless of submission, so a plan
        voided on Amazon (e.g. via Cancel & Create Draft) stays visible as history.
        Live submitted drafts appear on the Inbound Plans tab instead.


        Response includes `unfiltered_total` (for the export modal) and `status_counts`
        (total / in_progress / finalized / aborted, powering the metric cards).


        Requires Bearer token.


        Aborted rows additionally carry `aborted_at` / `aborted_by` (from the status-transition
        activity log) for the Cancelled column.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Amazon integration instance ID
        example: '2'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        status:
                          type: string
                        workflow_step:
                          type: integer
                        source_mode:
                          type: string
                        source_type:
                          type: string
                        source_warehouse_name:
                          type: string
                        supplier_name:
                          type: string
                          nullable: true
                        destination_warehouse_name:
                          type: string
                        item_count:
                          type: integer
                        created_at:
                          type: string
                        updated_at:
                          type: string
                        aborted_at:
                          type: string
                        aborted_by:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                  unfiltered_total:
                    type: integer
                  status_counts:
                    type: object
                    properties:
                      total:
                        type: integer
                      in_progress:
                        type: integer
                      finalized:
                        type: integer
                      aborted:
                        type: integer
                example:
                  data:
                  - id: 58
                    name: QA Aborted After Submit
                    status: aborted
                    workflow_step: 5
                    source_mode: warehouse_transfer
                    source_type: warehouse
                    source_warehouse_name: ShipMyOrders Warehouse
                    supplier_name: null
                    destination_warehouse_name: FBA US (AMZ partusa)
                    item_count: 22
                    created_at: '2026-07-02T23:56:00.000000Z'
                    updated_at: '2026-07-02T23:56:00.000000Z'
                    aborted_at: '2026-07-03T07:20:00.000000Z'
                    aborted_by: Kalvin Mizzi
                  current_page: 1
                  last_page: 3
                  per_page: 15
                  total: 35
                  from: 1
                  to: 15
                  unfiltered_total: 35
                  status_counts:
                    total: 35
                    in_progress: 3
                    finalized: 0
                    aborted: 32
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-integrationinstance-draft-inbound-plans-list
  /api/amazon/{integrationInstance}/draft-inbound-plans:
    get:
      tags:
      - Amazon
      summary: List Draft Inbound Plans
      description: 'List draft FBA inbound plans for an integration instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        status:
                          type: string
                        warehouse_id:
                          type: integer
                example:
                  data:
                  - id: 1
                    name: Q2 Restock
                    status: draft
                    warehouse_id: 3
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-integrationinstance-draft-inbound-plans
    post:
      tags:
      - Amazon
      summary: Create Draft Inbound Plan
      description: 'Create a new draft FBA inbound plan.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                warehouse_id:
                  type: integer
                destination_marketplace:
                  type: string
              example:
                name: Q2 Restock Plan
                warehouse_id: 3
                destination_marketplace: ATVPDKIKX0DER
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      status:
                        type: string
                example:
                  data:
                    id: 5
                    name: Q2 Restock Plan
                    status: draft
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-amazon-integrationinstance-draft-inbound-plans
  /api/amazon/{integrationInstance}/draft-inbound-plans/{draft_inbound_plan}:
    get:
      tags:
      - Amazon
      summary: Show Draft Inbound Plan
      description: 'Get details of a specific draft FBA inbound plan.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **`prep_details_snapshot`** (object|null): the last successful Amazon prep-details
        fetch persisted on the plan — `{details: [{msku, prepCategory, prepTypes[],
        labelOwnerConstraint, prepOwnerConstraint, allOwnersConstraint}], invalid_mskus:
        [msku], fetched_at: ISO8601}`. Lets the Configuration page render prep requirements
        after a reload without re-hitting Amazon; refreshed on every successful `list-prep-details`
        call.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: draft_inbound_plan
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The draft inbound plan ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      status:
                        type: string
                      warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      items:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            product_id:
                              type: integer
                            quantity:
                              type: integer
                      prep_details_snapshot:
                        type: object
                        properties:
                          details:
                            type: array
                            items:
                              type: object
                              properties:
                                msku:
                                  type: string
                                prepCategory:
                                  type: string
                                prepTypes:
                                  type: array
                                  items:
                                    type: string
                                labelOwnerConstraint:
                                  type: string
                                  nullable: true
                                prepOwnerConstraint:
                                  type: string
                                  nullable: true
                                allOwnersConstraint:
                                  type: string
                                  nullable: true
                          invalid_mskus:
                            type: array
                          fetched_at:
                            type: string
                example:
                  data:
                    id: 1
                    name: Q2 Restock
                    status: draft
                    warehouse:
                      id: 3
                      name: Main Warehouse
                    items:
                    - id: 1
                      product_id: 42
                      quantity: 100
                    prep_details_snapshot:
                      details:
                      - msku: ACME-SKU-A
                        prepCategory: FRAGILE
                        prepTypes:
                        - ITEM_BUBBLEWRAP
                        - ITEM_LABELING
                        labelOwnerConstraint: null
                        prepOwnerConstraint: null
                        allOwnersConstraint: null
                      invalid_mskus: []
                      fetched_at: '2026-07-07T05:00:00+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-integrationinstance-draft-inbound-plans-draft-inbound-plan
    put:
      tags:
      - Amazon
      summary: Update Draft Inbound Plan
      description: 'Update a draft FBA inbound plan. Advancing the plan to a verified
        state reserves source-warehouse stock; if the warehouse lacks enough on-hand
        quantity the request returns 400 with a product error.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Kit lines:** a kit line in `kit_stock` mode that lacks pre-built stock —
        but whose components could assemble the requested quantity — returns a dedicated
        400 error including `buildable_from_components`, hinting that the line should
        be switched to `components` mode (PATCH the item with `kit_fulfillment_mode:
        components`) so verification can allocate the component stock instead.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
              example:
                name: Q2 Restock Plan - Updated
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: draft_inbound_plan
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The draft inbound plan ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                example:
                  data:
                    id: 1
                    name: Q2 Restock Plan - Updated
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 400 Insufficient Stock
                  value:
                    errors:
                      product:
                      - message: 'Not enough quantity of product (ABC-123) '
                        code: ProductIsUnacceptable
                        data:
                          product_id: 456
                example-1:
                  summary: 400 Kit Assembly Available
                  value:
                    errors:
                      product:
                      - message: Kit (GSL392-KIT) has no pre-built stock at the source,
                          but its components can assemble 40. Switch the line to "Assemble
                          from Components" to plan the build at the source.
                        code: ProductIsUnacceptable
                        data:
                          product_id: 42
                          buildable_from_components: 40
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-amazon-integrationinstance-draft-inbound-plans-draft-inbound-plan
    delete:
      tags:
      - Amazon
      summary: Delete Draft Inbound Plan
      description: 'Delete a draft FBA inbound plan and its associated warehouse transfer.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: draft_inbound_plan
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The draft inbound plan ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Draft inbound plan deleted successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-amazon-integrationinstance-draft-inbound-plans-draft-inbound-plan
  /api/amazon/{integrationInstance}/draft-inbound-plans/{draft_inbound_plan}/allocations:
    get:
      tags:
      - Amazon
      summary: List Plan Allocations
      description: 'List the inventory allocations reserved against a draft inbound
        plan''s line items. These are the source-stock reservations (`InventoryAllocation`
        rows linked to `DraftAmazonFbaInboundPlanItem`) created when the plan is verified,
        and — after Amazon splits the plan into shipments — their migrated/fulfilled
        states. Backs the plan detail page''s "Allocations" tab.


        Authentication: requires Bearer token.


        Filters: `filter[search]` (allocation id / product SKU / product name), `filter[status]`
        (exact: allocated, planned, awaiting_receipt, fulfilled, cancelled), `filter[warehouse_id]`
        (exact).

        Sort: `sort` — allowed: id, quantity, status, created_at (prefix with - for
        DESC; default -id).

        Pagination: `page`, `per_page` (default 10).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Amazon integration instance id.
        example: '2'
      - name: draft_inbound_plan
        in: path
        schema:
          type: integer
        required: true
        description: Draft inbound plan id.
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        product_id:
                          type: integer
                        product:
                          type: object
                          properties:
                            id:
                              type: integer
                            sku:
                              type: string
                            name:
                              type: string
                        warehouse_id:
                          type: integer
                        warehouse:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        link_id:
                          type: integer
                        link_type:
                          type: string
                        link_type_label:
                          type: string
                        link_route:
                          type: string
                          nullable: true
                        link_reference:
                          type: string
                          nullable: true
                        date:
                          type: string
                          nullable: true
                        quantity:
                          type: integer
                        status:
                          type: string
                        status_label:
                          type: string
                        priority:
                          type: string
                          nullable: true
                        supplier_id:
                          type: string
                          nullable: true
                        purchase_order_line_id:
                          type: string
                          nullable: true
                        is_tight_coverage:
                          type: boolean
                        release_source_id:
                          type: string
                          nullable: true
                        release_source_type:
                          type: string
                          nullable: true
                        fulfilled_at:
                          type: string
                          nullable: true
                        cancelled_at:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                  first_page_url:
                    type: string
                  last_page_url:
                    type: string
                  next_page_url:
                    type: string
                    nullable: true
                  prev_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  links:
                    type: array
                example:
                  data:
                  - id: 4821
                    product_id: 1
                    product:
                      id: 1
                      sku: WIDGET-BLUE-01
                      name: Blue Widget — Standard
                    warehouse_id: 12
                    warehouse:
                      id: 12
                      name: Main Distribution Center
                    link_id: 1
                    link_type: Modules\Amazon\Entities\DraftAmazonFbaInboundPlanItem
                    link_type_label: FBA Inbound Plan
                    link_route: null
                    link_reference: null
                    date: null
                    quantity: 120
                    status: allocated
                    status_label: Allocated
                    priority: null
                    supplier_id: null
                    purchase_order_line_id: null
                    is_tight_coverage: false
                    release_source_id: null
                    release_source_type: null
                    fulfilled_at: null
                    cancelled_at: null
                    created_at: '2026-06-19T16:45:28.000000Z'
                    updated_at: '2026-06-19T16:45:28.000000Z'
                  current_page: 1
                  last_page: 1
                  per_page: 10
                  total: 3
                  from: 1
                  to: 3
                  first_page_url: '...'
                  last_page_url: '...'
                  next_page_url: null
                  prev_page_url: null
                  path: '...'
                  links: []
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-integrationinstance-draft-inbound-plans-draft-inbound-plan-allocations
  /api/amazon/{integrationInstance}/draft-inbound-plans/{draft_inbound_plan}/inbound-products:
    get:
      tags:
      - Amazon
      summary: Search Inbound Products (Plan Context)
      description: 'Search the Amazon inbound product catalog (amazon_inbound_products_view)
        with plan context for the SKU Selection step. Each row is an Amazon listing
        joined to its internal product with FBA quantities, label/prep owners, source-warehouse
        availability for the plan''s source, and the product''s case pack.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        `case_pack_qty` resolves from the per-product replenishment-settings override,
        else the instance default, else the product''s shipping-settings case quantity.
        `case_pack_rounding` is one of `always_round_up`, `always_round_down`, `round_nearest`.


        Requires Bearer token.


        Each product includes an eligibility object { shippable: bool, reason: string|null
        } — false with a reason when the SKU can''t be inbounded (no FNSKU, removed
        from Amazon, or an inactive listing).'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: draft_inbound_plan
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The draft inbound plan ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        msku:
                          type: string
                        asin:
                          type: string
                        fnsku:
                          type: string
                        product_id:
                          type: integer
                        product_sku:
                          type: string
                        product_name:
                          type: string
                        product_image:
                          type: string
                        country_code:
                          type: string
                        warehouse_quantity:
                          type: integer
                        fulfillable_quantity:
                          type: integer
                        unsellable_quantity:
                          type: integer
                        reserved_quantity:
                          type: integer
                        inbound_quantity:
                          type: integer
                        inbound_working_quantity:
                          type: integer
                        inbound_shipped_quantity:
                          type: integer
                        inbound_receiving_quantity:
                          type: integer
                        label_owner:
                          type: string
                        prep_owner:
                          type: string
                        source_quantity:
                          type: string
                        case_pack_qty:
                          type: integer
                        case_pack_rounding:
                          type: string
                example:
                  data:
                  - msku: 80707522-FBA
                    asin: B0EXAMPLE1
                    fnsku: X001ABC123
                    product_id: 1979
                    product_sku: '80707522'
                    product_name: Reusable Swim Diaper Snaps L
                    product_image: https://cdn.example.com/image.jpg
                    country_code: US
                    warehouse_quantity: 71
                    fulfillable_quantity: 65
                    unsellable_quantity: 0
                    reserved_quantity: 6
                    inbound_quantity: 12
                    inbound_working_quantity: 12
                    inbound_shipped_quantity: 0
                    inbound_receiving_quantity: 0
                    label_owner: SELLER
                    prep_owner: SELLER
                    source_quantity: '71'
                    case_pack_qty: 12
                    case_pack_rounding: always_round_down
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-integrationinstance-draft-inbound-plans-draft-inbound-plan-inbound-products
  /api/amazon/{integrationInstance}/draft-inbound-plans/{draft_inbound_plan}/lookup-by-mskus:
    post:
      tags:
      - Amazon
      summary: Lookup Inbound Products by Identifiers (Bulk Add)
      description: 'Bulk-resolve identifiers to Amazon inbound products with plan
        context — powers the Bulk Add flow on the SKU Selection step.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Modes via `identifier_type`:

        - `auto` (default): try MSKU first, fall back to product SKU for not-found
        identifiers

        - `msku`: only match Amazon seller SKUs

        - `sku`: only match internal product SKUs


        A product SKU mapping to multiple MSKUs is returned under `multiple_msku_matches`
        for the operator to pick. Products include the same fields as the inbound-products
        search (including `case_pack_qty`/`case_pack_rounding`).


        Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                mskus:
                  type: array
                  items:
                    type: string
                identifier_type:
                  type: string
              example:
                mskus:
                - 80707522-FBA
                - '80707568'
                identifier_type: auto
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: draft_inbound_plan
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The draft inbound plan ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      products:
                        type: array
                        items:
                          type: object
                          properties:
                            msku:
                              type: string
                            asin:
                              type: string
                            fnsku:
                              type: string
                            product_id:
                              type: integer
                            product_sku:
                              type: string
                            product_name:
                              type: string
                            product_image:
                              type: string
                            country_code:
                              type: string
                            warehouse_quantity:
                              type: integer
                            fulfillable_quantity:
                              type: integer
                            unsellable_quantity:
                              type: integer
                            reserved_quantity:
                              type: integer
                            inbound_quantity:
                              type: integer
                            inbound_working_quantity:
                              type: integer
                            inbound_shipped_quantity:
                              type: integer
                            inbound_receiving_quantity:
                              type: integer
                            label_owner:
                              type: string
                            prep_owner:
                              type: string
                            source_quantity:
                              type: string
                            case_pack_qty:
                              type: integer
                            case_pack_rounding:
                              type: string
                      found_identifiers:
                        type: array
                        items:
                          type: string
                      not_found_identifiers:
                        type: array
                        items:
                          type: string
                      multiple_msku_matches:
                        type: object
                        properties:
                          '80707568':
                            type: array
                            items:
                              type: object
                              properties:
                                msku:
                                  type: string
                                asin:
                                  type: string
                                fnsku:
                                  type: string
                                product_id:
                                  type: integer
                                product_sku:
                                  type: string
                                product_name:
                                  type: string
                                product_image:
                                  type: string
                                country_code:
                                  type: string
                                warehouse_quantity:
                                  type: integer
                                fulfillable_quantity:
                                  type: integer
                                unsellable_quantity:
                                  type: integer
                                reserved_quantity:
                                  type: integer
                                inbound_quantity:
                                  type: integer
                                inbound_working_quantity:
                                  type: integer
                                inbound_shipped_quantity:
                                  type: integer
                                inbound_receiving_quantity:
                                  type: integer
                                label_owner:
                                  type: string
                                prep_owner:
                                  type: string
                                source_quantity:
                                  type: string
                                case_pack_qty:
                                  type: integer
                                case_pack_rounding:
                                  type: string
                      found_mskus:
                        type: array
                        items:
                          type: string
                      not_found_mskus:
                        type: array
                        items:
                          type: string
                example:
                  data:
                    products:
                    - msku: 80707522-FBA
                      asin: B0EXAMPLE1
                      fnsku: X001ABC123
                      product_id: 1979
                      product_sku: '80707522'
                      product_name: Reusable Swim Diaper Snaps L
                      product_image: https://cdn.example.com/image.jpg
                      country_code: US
                      warehouse_quantity: 71
                      fulfillable_quantity: 65
                      unsellable_quantity: 0
                      reserved_quantity: 6
                      inbound_quantity: 12
                      inbound_working_quantity: 12
                      inbound_shipped_quantity: 0
                      inbound_receiving_quantity: 0
                      label_owner: SELLER
                      prep_owner: SELLER
                      source_quantity: '71'
                      case_pack_qty: 12
                      case_pack_rounding: always_round_down
                    found_identifiers:
                    - 80707522-FBA
                    - '80707568'
                    not_found_identifiers:
                    - UNKNOWN-1
                    multiple_msku_matches:
                      '80707568':
                      - msku: 80707568-FBA-1
                        asin: B0EXAMPLE1
                        fnsku: X001ABC123
                        product_id: 1981
                        product_sku: '80707568'
                        product_name: Reusable Swim Diaper Snaps L
                        product_image: https://cdn.example.com/image.jpg
                        country_code: US
                        warehouse_quantity: 71
                        fulfillable_quantity: 65
                        unsellable_quantity: 0
                        reserved_quantity: 6
                        inbound_quantity: 12
                        inbound_working_quantity: 12
                        inbound_shipped_quantity: 0
                        inbound_receiving_quantity: 0
                        label_owner: SELLER
                        prep_owner: SELLER
                        source_quantity: '71'
                        case_pack_qty: 12
                        case_pack_rounding: always_round_down
                      - msku: 80707568-FBA-2
                        asin: B0EXAMPLE1
                        fnsku: X001ABC123
                        product_id: 1981
                        product_sku: '80707568'
                        product_name: Reusable Swim Diaper Snaps L
                        product_image: https://cdn.example.com/image.jpg
                        country_code: US
                        warehouse_quantity: 71
                        fulfillable_quantity: 65
                        unsellable_quantity: 0
                        reserved_quantity: 6
                        inbound_quantity: 12
                        inbound_working_quantity: 12
                        inbound_shipped_quantity: 0
                        inbound_receiving_quantity: 0
                        label_owner: SELLER
                        prep_owner: SELLER
                        source_quantity: '71'
                        case_pack_qty: 12
                        case_pack_rounding: always_round_down
                    found_mskus:
                    - 80707522-FBA
                    not_found_mskus:
                    - UNKNOWN-1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-amazon-integrationinstance-draft-inbound-plans-draft-inbound-plan-lookup-by-mskus
  /api/amazon/{integrationInstance}/draft-inbound-plans/{draft_inbound_plan}/submit-to-amazon:
    post:
      tags:
      - Amazon
      summary: Submit Plan to Amazon
      description: 'Submit a draft inbound plan to Amazon''s API for processing.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Pre-flight validation:** every plan item must carry an Amazon listing (MSKU).
        Items without one (e.g. a bulk-add identifier that matched a local product
        SKU only) fail with a 422 `items` error naming the offending product SKUs
        — nothing is sent to Amazon.'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: draft_inbound_plan
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The draft inbound plan ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      status:
                        type: string
                      amazon_plan_id:
                        type: string
                example:
                  data:
                    id: 1
                    status: submitted
                    amazon_plan_id: PLAN-123456
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      items:
                        type: array
                        items:
                          type: string
                example:
                  message: O-13 has no Amazon listing (MSKU) on this integration.
                    Remove it from the plan, or create the listing in Seller Central
                    and re-add it.
                  errors:
                    items:
                    - O-13 has no Amazon listing (MSKU) on this integration. Remove
                      it from the plan, or create the listing in Seller Central and
                      re-add it.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-amazon-integrationinstance-draft-inbound-plans-draft-inbound-plan-submit-to-amazon
  /api/amazon/{integrationInstance}/draft-inbound-plans/{draft_inbound_plan}/cancel-amazon-plan:
    post:
      tags:
      - Amazon
      summary: Cancel Amazon Plan
      description: 'Cancel a draft inbound plan.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Never-submitted plans** are simply marked ABORTED locally and their reserved
        inventory is released.


        **Submitted plans** are voided on Amazon; the original draft stays bound to
        its now-VOIDED Amazon plan as ABORTED history and remains visible on the Drafts
        tab. With `create_draft=true` (default) a fresh duplicate draft is returned
        for resubmission.


        **Flagged-SKU handling:** MSKUs Amazon named in the plan''s rejection problems
        (e.g. FBA_INB_0465 manufacturer-barcode errors) are automatically left out
        of the duplicate — unless `msku_replacements` maps them to an alternate listing
        (from → to), in which case the item is carried into the copy under the replacement
        MSKU with its label owner reset for reconfiguration. Dropped MSKUs are returned
        in `excluded_flagged_mskus`; applied swaps in `replaced_mskus`.


        The resubmission copy preserves per-line kit assembly consent (`kit_fulfillment_mode`)
        and case-pack snapshots.


        Requires Bearer token.


        When a resubmission draft is created, the returned duplicate carries: excluded_flagged_mskus
        (SKUs Amazon flagged as invalid, dropped from the copy), replaced_mskus (flagged->alternate
        swaps applied), and — for fixable rejections that keep every SKU — resubmission_expiration_mskus
        (SKUs needing an expiration date), resubmission_address_issue (bool; the ship-from
        address needs fixing) and resubmission_other_problems (other messages to resolve
        before resubmitting).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                create_draft:
                  type: boolean
                msku_replacements:
                  type: array
                  items:
                    type: object
                    properties:
                      from:
                        type: string
                      to:
                        type: string
              example:
                create_draft: true
                msku_replacements:
                - from: 1727570-FBA
                  to: 1727570-FBA-NEW
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: draft_inbound_plan
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The draft inbound plan ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      name:
                        type: string
                      status:
                        type: string
                      workflow_step:
                        type: integer
                      source_mode:
                        type: string
                      source_warehouse_id:
                        type: integer
                      warehouse_transfer_id:
                        type: string
                        nullable: true
                      amazon_new_fba_inbound_plan:
                        type: string
                        nullable: true
                      items:
                        type: array
                      excluded_flagged_mskus:
                        type: array
                        items:
                          type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      replaced_mskus:
                        type: object
                        properties:
                          1727570-FBA:
                            type: string
                example:
                  data:
                    id: 58
                    integration_instance_id: 2
                    name: SMO Inbound Order 20260702 (Resubmit)
                    status: source_selected
                    workflow_step: 1
                    source_mode: warehouse_transfer
                    source_warehouse_id: 12
                    warehouse_transfer_id: null
                    amazon_new_fba_inbound_plan: null
                    items: []
                    excluded_flagged_mskus:
                    - 1726527-FBA
                    created_at: '2026-07-02T23:10:00.000000Z'
                    updated_at: '2026-07-02T23:10:00.000000Z'
                    replaced_mskus:
                      1727570-FBA: 1727570-FBA-NEW
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-amazon-integrationinstance-draft-inbound-plans-draft-inbound-plan-cancel-amazon-plan
  /api/amazon/{integrationInstance}/draft-inbound-plans/{draft_inbound_plan}/packing-options/generate:
    post:
      tags:
      - Amazon
      summary: Generate Packing Options
      description: 'Generate packing options for a submitted draft FBA inbound plan
        via the Amazon FBA Inbound API (v2024-03-20 generatePackingOptions operation).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        This is an asynchronous endpoint: it dispatches a tracked background job and
        returns `{ "data": { "tracked_job_log_id": <id> } }` immediately. Progress
        is visible via the tracked job log endpoints, and the underlying Amazon operation
        is resolved by the `amazon_inbound_operations` poller (a background job).


        Tracked job name: `Generate FBA Packing Options: {plan name}`. When the job
        completes, the offered packing options (with their packing groups and items)
        are persisted locally and can be retrieved with **List Packing Options**.


        No request body is required.'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: draft_inbound_plan
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The draft inbound plan ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 123
                  message: Packing options generation started
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-amazon-integrationinstance-draft-inbound-plans-draft-inbound-plan-packing-options-generate
  /api/amazon/{integrationInstance}/draft-inbound-plans/{draft_inbound_plan}/packing-options:
    get:
      tags:
      - Amazon
      summary: List Packing Options
      description: 'List the packing options generated for a draft FBA inbound plan,
        including each option''s packing groups and their items (with linked product
        details).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Each option includes:

        - `status` — one of `offered`, `confirmed`, `expired`

        - `discounts` / `fees` — Amazon-quoted incentives for the option

        - `expiration` — when the offered option expires on Amazon''s side

        - `supported_shipping_configurations` — shipping mode/solution pairs the option
        supports

        - `packing_groups[].items[]` — the MSKUs and quantities that must be packed
        together, with `prep_owner` / `label_owner`, the linked SKU.io product, and
        the product''s per-unit `weight` / `weight_unit` and `length` / `width` /
        `height` / `dimension_unit` plus its `case_pack_qty`. Missing weight/dimension
        figures are returned as `null` with `weight_estimated` / `dims_estimated`
        set to `true` so the UI can flag them as estimates in load & transport calculations.


        Run **Generate Packing Options** first; this endpoint reads the locally persisted
        results.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: draft_inbound_plan
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The draft inbound plan ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        packing_option_id:
                          type: string
                        status:
                          type: string
                        discounts:
                          type: array
                        fees:
                          type: array
                          items:
                            type: object
                            properties:
                              target:
                                type: string
                              type:
                                type: string
                              value:
                                type: object
                                properties:
                                  amount:
                                    type: number
                                  code:
                                    type: string
                        expiration:
                          type: string
                        supported_shipping_configurations:
                          type: array
                          items:
                            type: object
                            properties:
                              shippingMode:
                                type: string
                              shippingSolution:
                                type: string
                        packing_groups:
                          type: array
                          items:
                            type: object
                            properties:
                              id:
                                type: integer
                              packing_group_id:
                                type: string
                              content_information_source:
                                type: string
                                nullable: true
                              packing_submitted_at:
                                type: string
                                nullable: true
                              items:
                                type: array
                                items:
                                  type: object
                                  properties:
                                    id:
                                      type: integer
                                    msku:
                                      type: string
                                    fnsku:
                                      type: string
                                    quantity:
                                      type: integer
                                    expiration_date:
                                      type: string
                                      nullable: true
                                    prep_owner:
                                      type: string
                                    label_owner:
                                      type: string
                                    draft_amazon_fba_inbound_plan_item_id:
                                      type: integer
                                    case_pack_qty:
                                      type: integer
                                    weight:
                                      type: number
                                    weight_unit:
                                      type: string
                                    weight_estimated:
                                      type: boolean
                                    length:
                                      type: integer
                                    width:
                                      type: integer
                                    height:
                                      type: integer
                                    dimension_unit:
                                      type: string
                                    dims_estimated:
                                      type: boolean
                                    product:
                                      type: object
                                      properties:
                                        id:
                                          type: integer
                                        sku:
                                          type: string
                                        name:
                                          type: string
                                        image_url:
                                          type: string
                example:
                  data:
                  - id: 7
                    packing_option_id: po-1f2e3d4c-5b6a-7980-bcde-f01234567890
                    status: offered
                    discounts: []
                    fees:
                    - target: Placement Services
                      type: FEE
                      value:
                        amount: 0.3
                        code: USD
                    expiration: '2026-06-19T00:00:00Z'
                    supported_shipping_configurations:
                    - shippingMode: GROUND_SMALL_PARCEL
                      shippingSolution: AMAZON_PARTNERED_CARRIER
                    - shippingMode: FREIGHT_LTL
                      shippingSolution: USE_YOUR_OWN_CARRIER
                    packing_groups:
                    - id: 12
                      packing_group_id: pg-0a1b2c3d-4e5f-6789-abcd-ef0123456789
                      content_information_source: null
                      packing_submitted_at: null
                      items:
                      - id: 31
                        msku: WIDGET-BLUE-L
                        fnsku: X001ABC123
                        quantity: 40
                        expiration_date: null
                        prep_owner: SELLER
                        label_owner: SELLER
                        draft_amazon_fba_inbound_plan_item_id: 88
                        case_pack_qty: 10
                        weight: 1.25
                        weight_unit: lb
                        weight_estimated: false
                        length: 6
                        width: 4
                        height: 2
                        dimension_unit: in
                        dims_estimated: false
                        product:
                          id: 42
                          sku: WIDGET-BLUE-L
                          name: Blue Widget - Large
                          image_url: https://cdn.sku.io/products/42/primary.jpg
                      - id: 32
                        msku: WIDGET-RED-S
                        fnsku: X001DEF456
                        quantity: 12
                        expiration_date: null
                        prep_owner: AMAZON
                        label_owner: SELLER
                        draft_amazon_fba_inbound_plan_item_id: 89
                        case_pack_qty: null
                        weight: null
                        weight_unit: null
                        weight_estimated: true
                        length: null
                        width: null
                        height: null
                        dimension_unit: null
                        dims_estimated: true
                        product:
                          id: 43
                          sku: WIDGET-RED-S
                          name: Red Widget - Small
                          image_url: https://cdn.sku.io/products/43/primary.jpg
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-integrationinstance-draft-inbound-plans-draft-inbound-plan-packing-options
  /api/amazon/{integrationInstance}/draft-inbound-plans/{draft_inbound_plan}/packing-options/{packing_option}/confirm:
    post:
      tags:
      - Amazon
      summary: Confirm Packing Option
      description: 'Confirm one of the offered packing options for the plan (Amazon
        FBA Inbound v2024-03-20 confirmPackingOption operation). Once confirmed, the
        plan''s packing groups are fixed and boxes can be packed against them.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        This is an asynchronous endpoint: it dispatches a tracked background job and
        returns `{ "data": { "tracked_job_log_id": <id> } }` immediately. Progress
        is visible via the tracked job log endpoints, and the underlying Amazon operation
        is resolved by the `amazon_inbound_operations` poller (a background job).


        Tracked job name: `Confirm FBA Packing Option: {plan name}`.


        Returns 404 if the packing option does not belong to the draft inbound plan.


        No request body is required.'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: draft_inbound_plan
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The draft inbound plan ID.
      - name: packing_option
        in: path
        schema:
          type: integer
        required: true
        example: '7'
        description: The packing option ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 124
                  message: Packing option confirmation started
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-amazon-integrationinstance-draft-inbound-plans-draft-inbound-plan-packing-options-packing-option-confirm
  /api/amazon/{integrationInstance}/draft-inbound-plans/{draft_inbound_plan}/boxes:
    get:
      tags:
      - Amazon
      summary: List Boxes
      description: 'List all locally managed boxes for a draft FBA inbound plan, across
        all of its packing groups, including each box''s items.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Each box includes its `box_number` (unique per plan), dimensions/weight with
        units, `status` (`open`, `packed`, or `submitted`), the packing group it belongs
        to, the optional carton template it was created from, and its packed items
        (plan item reference, quantity, optional expiration date).'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: draft_inbound_plan
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The draft inbound plan ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        box_number:
                          type: integer
                        amazon_fba_inbound_packing_group_id:
                          type: integer
                        amazon_fba_carton_template_id:
                          type: integer
                        length:
                          type: string
                        width:
                          type: string
                        height:
                          type: string
                        dimension_unit:
                          type: string
                        weight:
                          type: string
                        weight_unit:
                          type: string
                        status:
                          type: string
                        items:
                          type: array
                          items:
                            type: object
                            properties:
                              id:
                                type: integer
                              draft_amazon_fba_inbound_plan_item_id:
                                type: integer
                              quantity:
                                type: integer
                              expiration_date:
                                type: string
                example:
                  data:
                  - id: 101
                    box_number: 1
                    amazon_fba_inbound_packing_group_id: 12
                    amazon_fba_carton_template_id: 3
                    length: '18.00'
                    width: '14.00'
                    height: '12.00'
                    dimension_unit: IN
                    weight: '32.50'
                    weight_unit: LB
                    status: open
                    items:
                    - id: 501
                      draft_amazon_fba_inbound_plan_item_id: 88
                      quantity: 24
                      expiration_date: '2027-01-31'
                    - id: 502
                      draft_amazon_fba_inbound_plan_item_id: 89
                      quantity: 12
                      expiration_date: null
                  - id: 102
                    box_number: 2
                    amazon_fba_inbound_packing_group_id: 12
                    amazon_fba_carton_template_id: null
                    length: '20.00'
                    width: '16.00'
                    height: '10.00'
                    dimension_unit: IN
                    weight: '28.00'
                    weight_unit: LB
                    status: open
                    items:
                    - id: 503
                      draft_amazon_fba_inbound_plan_item_id: 88
                      quantity: 16
                      expiration_date: '2027-01-31'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-integrationinstance-draft-inbound-plans-draft-inbound-plan-boxes
    post:
      tags:
      - Amazon
      summary: Create Box
      description: 'Create a new (empty) box in a packing group of the draft inbound
        plan. The box is assigned the next sequential `box_number` for the plan and
        starts with status `open`.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Fields:**

        - `amazon_fba_inbound_packing_group_id` (integer, **required**) — the packing
        group the box belongs to; must exist and must belong to this draft inbound
        plan (422 otherwise)

        - `amazon_fba_carton_template_id` (integer, optional, nullable) — a carton
        template to prefill from; must exist. When set, any omitted `length`/`width`/`height`
        are filled from the template, `weight` defaults to the template''s `tare_weight`,
        and the units default to the template''s units

        - `length` (numeric, optional, nullable, > 0)

        - `width` (numeric, optional, nullable, > 0)

        - `height` (numeric, optional, nullable, > 0)

        - `weight` (numeric, optional, nullable, > 0)

        - `dimension_unit` (string, optional, `IN` or `CM`, default `IN`)

        - `weight_unit` (string, optional, `LB` or `KG`, default `LB`)


        Add items to the box afterwards with **Update Box**.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                amazon_fba_inbound_packing_group_id:
                  type: integer
                amazon_fba_carton_template_id:
                  type: integer
                length:
                  type: integer
                width:
                  type: integer
                height:
                  type: integer
                weight:
                  type: number
                dimension_unit:
                  type: string
                weight_unit:
                  type: string
              example:
                amazon_fba_inbound_packing_group_id: 12
                amazon_fba_carton_template_id: 3
                length: 18
                width: 14
                height: 12
                weight: 1.25
                dimension_unit: IN
                weight_unit: LB
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: draft_inbound_plan
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The draft inbound plan ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      box_number:
                        type: integer
                      amazon_fba_inbound_packing_group_id:
                        type: integer
                      amazon_fba_carton_template_id:
                        type: integer
                      length:
                        type: string
                      width:
                        type: string
                      height:
                        type: string
                      dimension_unit:
                        type: string
                      weight:
                        type: string
                      weight_unit:
                        type: string
                      status:
                        type: string
                      items:
                        type: array
                example:
                  data:
                    id: 103
                    box_number: 3
                    amazon_fba_inbound_packing_group_id: 12
                    amazon_fba_carton_template_id: 3
                    length: '18.00'
                    width: '14.00'
                    height: '12.00'
                    dimension_unit: IN
                    weight: '1.25'
                    weight_unit: LB
                    status: open
                    items: []
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      amazon_fba_inbound_packing_group_id:
                        type: array
                        items:
                          type: string
                example:
                  message: The packing group does not belong to this draft inbound
                    plan.
                  errors:
                    amazon_fba_inbound_packing_group_id:
                    - The packing group does not belong to this draft inbound plan.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-amazon-integrationinstance-draft-inbound-plans-draft-inbound-plan-boxes
  /api/amazon/{integrationInstance}/draft-inbound-plans/{draft_inbound_plan}/boxes/{box}:
    patch:
      tags:
      - Amazon
      summary: Update Box
      description: "Update a box's attributes and/or its packed items. Returns 404\
        \ if the box does not belong to the draft inbound plan.\n\n:::info[Authorization]\n\
        Any valid API token can call this endpoint — no specific scope required. [Manage\
        \ tokens](https://app.sku.io/settings/api).\n:::\n\n**Fields (all optional):**\n\
        - `amazon_fba_carton_template_id` (integer, nullable) — must exist in carton\
        \ templates\n- `length` (numeric, nullable, > 0)\n- `width` (numeric, nullable,\
        \ > 0)\n- `height` (numeric, nullable, > 0)\n- `weight` (numeric, nullable,\
        \ > 0)\n- `dimension_unit` (string, `IN` or `CM`)\n- `weight_unit` (string,\
        \ `LB` or `KG`)\n- `items` (array) — **full-replace** set of the box's items.\
        \ When present, ALL existing box items are deleted and replaced with this\
        \ set:\n  - `items.*.draft_amazon_fba_inbound_plan_item_id` (integer, **required**)\
        \ — must exist, must belong to this plan, and its MSKU must be part of the\
        \ box's packing group (422 otherwise)\n  - `items.*.quantity` (integer, **required**,\
        \ min 1)\n  - `items.*.expiration_date` (date, optional, nullable, must be\
        \ today or later — \"Expiration dates cannot be in the past.\")\n\nThe authenticated\
        \ user is recorded as `packed_by_user_id` on each created item."
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                length:
                  type: integer
                width:
                  type: integer
                height:
                  type: integer
                weight:
                  type: number
                dimension_unit:
                  type: string
                weight_unit:
                  type: string
                items:
                  type: array
                  items:
                    type: object
                    properties:
                      draft_amazon_fba_inbound_plan_item_id:
                        type: integer
                      quantity:
                        type: integer
                      expiration_date:
                        type: string
              example:
                length: 18
                width: 14
                height: 12
                weight: 32.5
                dimension_unit: IN
                weight_unit: LB
                items:
                - draft_amazon_fba_inbound_plan_item_id: 88
                  quantity: 24
                  expiration_date: '2027-01-31'
                - draft_amazon_fba_inbound_plan_item_id: 89
                  quantity: 12
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: draft_inbound_plan
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The draft inbound plan ID.
      - name: box
        in: path
        schema:
          type: integer
        required: true
        example: '101'
        description: The box ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      box_number:
                        type: integer
                      amazon_fba_inbound_packing_group_id:
                        type: integer
                      amazon_fba_carton_template_id:
                        type: integer
                      length:
                        type: string
                      width:
                        type: string
                      height:
                        type: string
                      dimension_unit:
                        type: string
                      weight:
                        type: string
                      weight_unit:
                        type: string
                      status:
                        type: string
                      items:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            draft_amazon_fba_inbound_plan_item_id:
                              type: integer
                            quantity:
                              type: integer
                            expiration_date:
                              type: string
                example:
                  data:
                    id: 101
                    box_number: 1
                    amazon_fba_inbound_packing_group_id: 12
                    amazon_fba_carton_template_id: 3
                    length: '18.00'
                    width: '14.00'
                    height: '12.00'
                    dimension_unit: IN
                    weight: '32.50'
                    weight_unit: LB
                    status: open
                    items:
                    - id: 501
                      draft_amazon_fba_inbound_plan_item_id: 88
                      quantity: 24
                      expiration_date: '2027-01-31'
                    - id: 502
                      draft_amazon_fba_inbound_plan_item_id: 89
                      quantity: 12
                      expiration_date: null
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      items.0.draft_amazon_fba_inbound_plan_item_id:
                        type: array
                        items:
                          type: string
                      items.1.expiration_date:
                        type: array
                        items:
                          type: string
                example:
                  message: The item (WIDGET-GREEN-M) is not part of this box's packing
                    group.
                  errors:
                    items.0.draft_amazon_fba_inbound_plan_item_id:
                    - The item (WIDGET-GREEN-M) is not part of this box's packing
                      group.
                    items.1.expiration_date:
                    - Expiration dates cannot be in the past.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: patch-api-amazon-integrationinstance-draft-inbound-plans-draft-inbound-plan-boxes-box
    delete:
      tags:
      - Amazon
      summary: Delete Box
      description: 'Delete a box (and its items) from the draft inbound plan. Returns
        404 if the box does not belong to the plan.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: draft_inbound_plan
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The draft inbound plan ID.
      - name: box
        in: path
        schema:
          type: integer
        required: true
        example: '101'
        description: The box ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Box deleted successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-amazon-integrationinstance-draft-inbound-plans-draft-inbound-plan-boxes-box
  /api/amazon/{integrationInstance}/draft-inbound-plans/{draft_inbound_plan}/boxes/import:
    post:
      tags:
      - Amazon
      summary: Import Boxes (CSV)
      description: 'Import box contents for a packing group from a CSV file (multipart/form-data).
        Boxes are created or updated by `box_number` and item quantities are added
        per row.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Form fields:**

        - `file` (file, **required**) — CSV file (`.csv`/`.txt`), max 2MB

        - `amazon_fba_inbound_packing_group_id` (integer, **required**) — must exist
        and must belong to this draft inbound plan (422 otherwise)


        **CSV columns** (header row required; column names are case-insensitive):

        - `box_number` (**required**) — positive whole number; rows with the same
        box number go into the same box. A box number already used by a DIFFERENT
        packing group on this plan is rejected

        - `sku` (**required**) — matched case-insensitively against the plan items''
        product SKU or MSKU; must resolve to an item that is part of the selected
        packing group

        - `quantity` (**required**) — positive whole number; added to the box''s quantity
        for that item

        - `weight`, `length`, `width`, `height` (optional) — numbers > 0; when present
        they update the box''s measurements


        **The import is all-or-nothing:** every row is validated first, and any invalid
        row aborts the entire import with row-numbered error messages (422). On success
        the response includes a summary (`boxes_created`, `items_imported`) plus the
        full refreshed box list for the plan.'
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                file:
                  type: string
                  description: 'CSV file (max 2MB). Required columns: box_number,
                    sku, quantity. Optional: weight, length, width, height.'
                  format: binary
                amazon_fba_inbound_packing_group_id:
                  type: integer
                  description: Packing group to import boxes into (must belong to
                    this plan).
                  example: '12'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: draft_inbound_plan
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The draft inbound plan ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      boxes_created:
                        type: integer
                      items_imported:
                        type: integer
                      boxes:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            box_number:
                              type: integer
                            amazon_fba_inbound_packing_group_id:
                              type: integer
                            amazon_fba_carton_template_id:
                              type: integer
                            length:
                              type: string
                            width:
                              type: string
                            height:
                              type: string
                            dimension_unit:
                              type: string
                            weight:
                              type: string
                            weight_unit:
                              type: string
                            status:
                              type: string
                            items:
                              type: array
                              items:
                                type: object
                                properties:
                                  id:
                                    type: integer
                                  draft_amazon_fba_inbound_plan_item_id:
                                    type: integer
                                  quantity:
                                    type: integer
                                  expiration_date:
                                    type: string
                  message:
                    type: string
                example:
                  data:
                    boxes_created: 2
                    items_imported: 3
                    boxes:
                    - id: 101
                      box_number: 1
                      amazon_fba_inbound_packing_group_id: 12
                      amazon_fba_carton_template_id: 3
                      length: '18.00'
                      width: '14.00'
                      height: '12.00'
                      dimension_unit: IN
                      weight: '32.50'
                      weight_unit: LB
                      status: open
                      items:
                      - id: 501
                        draft_amazon_fba_inbound_plan_item_id: 88
                        quantity: 24
                        expiration_date: '2027-01-31'
                      - id: 502
                        draft_amazon_fba_inbound_plan_item_id: 89
                        quantity: 12
                        expiration_date: null
                    - id: 102
                      box_number: 2
                      amazon_fba_inbound_packing_group_id: 12
                      amazon_fba_carton_template_id: null
                      length: '20.00'
                      width: '16.00'
                      height: '10.00'
                      dimension_unit: IN
                      weight: '28.00'
                      weight_unit: LB
                      status: open
                      items:
                      - id: 503
                        draft_amazon_fba_inbound_plan_item_id: 88
                        quantity: 16
                        expiration_date: '2027-01-31'
                  message: Boxes imported successfully.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      file:
                        type: array
                        items:
                          type: string
                example:
                  message: 'Row 2: quantity must be a positive whole number.'
                  errors:
                    file:
                    - 'Row 2: quantity must be a positive whole number.'
                    - 'Row 4: SKU ''WIDGET-GREEN-M'' does not match any item on this
                      draft inbound plan.'
                    - 'Row 7: box_number 5 already belongs to another packing group
                      on this plan.'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-amazon-integrationinstance-draft-inbound-plans-draft-inbound-plan-boxes-import
  /api/amazon/{integrationInstance}/draft-inbound-plans/{draft_inbound_plan}/packing/submit:
    post:
      tags:
      - Amazon
      summary: Submit Packing Information
      description: 'Submit box content information for **every packing group of the
        plan''s confirmed packing option** in a single request (FBA Inbound v2024-03-20
        setPackingInformation operation). Amazon requires all of the confirmed option''s
        package grouping ids together, so submission is plan-level rather than per-group
        — submitting one group at a time is rejected with "Provided package grouping
        ids are incorrect. Expected all of [...]".


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Fields:**

        - `sources` (object, optional) — map of packing group id => content information
        source. Each value is one of `BOX_CONTENT_PROVIDED`, `MANUAL_PROCESS`, `BARCODE_2D`.
        Groups omitted from the map (or the whole `sources` object omitted) default
        to `BOX_CONTENT_PROVIDED`. With `BOX_CONTENT_PROVIDED` a group''s per-box
        item contents are submitted; `MANUAL_PROCESS` and `BARCODE_2D` submit box
        dimensions/weights without item contents


        **Confirmed packing option required:** if the plan has no confirmed packing
        option, returns 422 with the message under `errors.packing_option` ("Confirm
        a packing option before submitting box contents.").


        **Pre-flight validation** (applies to each group whose source is `BOX_CONTENT_PROVIDED`;
        any failure returns 422 with messages under `errors.packing_group`):

        - The packing group must have at least one box

        - Every box must have length, width, height, AND weight greater than zero

        - The plan may not exceed 5,000 boxes

        - Per-MSKU packed totals across the group''s boxes must EXACTLY equal the
        packing group''s planned quantities (no shortfalls, overages, or MSKUs outside
        the group)

        - No box item may have an expiration date in the past


        This is an asynchronous endpoint: it dispatches a tracked background job and
        returns `{ "data": { "tracked_job_log_id": <id> } }` immediately. Progress
        is visible via the tracked job log endpoints, and the underlying Amazon operation
        is resolved by the `amazon_inbound_operations` poller (a background job).


        Tracked job name: `Submit FBA Box Contents: {plan name}`.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                sources:
                  type: object
                  properties:
                    '12':
                      type: string
              example:
                sources:
                  '12': BOX_CONTENT_PROVIDED
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: draft_inbound_plan
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The draft inbound plan ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 125
                  message: Box content submission started
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      packing_group:
                        type: array
                        items:
                          type: string
                example:
                  message: Box 2 is missing dimensions or weight — length, width,
                    height, and weight must all be greater than zero.
                  errors:
                    packing_group:
                    - Box 2 is missing dimensions or weight — length, width, height,
                      and weight must all be greater than zero.
                    - Packed quantity for WIDGET-BLUE-L is 36 but the packing group
                      requires exactly 40.
                    - 'Box 1: WIDGET-RED-S has an expiration date in the past.'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-amazon-integrationinstance-draft-inbound-plans-draft-inbound-plan-packing-submit
  /api/amazon/{integrationInstance}/fba/carton-templates:
    get:
      tags:
      - Amazon
      summary: List Carton Templates
      description: 'List all ACTIVE carton templates. Soft-retired templates (`is_active`
        = false) are excluded.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Carton templates are reusable carton (box) presets used by the FBA packing
        station — selecting a template when creating a box prefills its dimensions,
        units, and tare weight.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        length:
                          type: string
                        width:
                          type: string
                        height:
                          type: string
                        dimension_unit:
                          type: string
                        tare_weight:
                          type: string
                        weight_unit:
                          type: string
                        is_active:
                          type: boolean
                        created_at:
                          type: string
                        updated_at:
                          type: string
                example:
                  data:
                  - id: 3
                    name: Standard Large Carton
                    length: '18.00'
                    width: '14.00'
                    height: '12.00'
                    dimension_unit: IN
                    tare_weight: '1.25'
                    weight_unit: LB
                    is_active: true
                    created_at: '2026-06-01T10:15:00.000000Z'
                    updated_at: '2026-06-01T10:15:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-integrationinstance-fba-carton-templates
    post:
      tags:
      - Amazon
      summary: Create Carton Template
      description: 'Create a reusable carton template.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Fields:**

        - `name` (string, **required**, max 255) — must be unique across carton templates

        - `length` (numeric, **required**, > 0)

        - `width` (numeric, **required**, > 0)

        - `height` (numeric, **required**, > 0)

        - `dimension_unit` (string, optional, `IN` or `CM`, default `IN`)

        - `tare_weight` (numeric, optional, nullable, min 0) — empty-carton weight,
        used as the default box weight when a box is created from this template

        - `weight_unit` (string, optional, `LB` or `KG`, default `LB`)

        - `is_active` (boolean, optional, default `true`)'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                length:
                  type: integer
                width:
                  type: integer
                height:
                  type: integer
                dimension_unit:
                  type: string
                tare_weight:
                  type: number
                weight_unit:
                  type: string
                is_active:
                  type: boolean
              example:
                name: Standard Large Carton
                length: 18
                width: 14
                height: 12
                dimension_unit: IN
                tare_weight: 1.25
                weight_unit: LB
                is_active: true
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      length:
                        type: string
                      width:
                        type: string
                      height:
                        type: string
                      dimension_unit:
                        type: string
                      tare_weight:
                        type: string
                      weight_unit:
                        type: string
                      is_active:
                        type: boolean
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 3
                    name: Standard Large Carton
                    length: '18.00'
                    width: '14.00'
                    height: '12.00'
                    dimension_unit: IN
                    tare_weight: '1.25'
                    weight_unit: LB
                    is_active: true
                    created_at: '2026-06-01T10:15:00.000000Z'
                    updated_at: '2026-06-01T10:15:00.000000Z'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      name:
                        type: array
                        items:
                          type: string
                example:
                  message: The name has already been taken.
                  errors:
                    name:
                    - The name has already been taken.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-amazon-integrationinstance-fba-carton-templates
  /api/amazon/{integrationInstance}/fba/carton-templates/{carton_template}:
    patch:
      tags:
      - Amazon
      summary: Update Carton Template
      description: 'Update a carton template. All fields are optional; only provided
        fields are changed.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Fields (all optional):**

        - `name` (string, max 255) — must be unique across carton templates (the current
        template is ignored)

        - `length` (numeric, > 0)

        - `width` (numeric, > 0)

        - `height` (numeric, > 0)

        - `dimension_unit` (string, `IN` or `CM`)

        - `tare_weight` (numeric, nullable, min 0)

        - `weight_unit` (string, `LB` or `KG`)

        - `is_active` (boolean) — set false to retire, true to reactivate'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                tare_weight:
                  type: number
              example:
                name: Standard Large Carton (Reinforced)
                tare_weight: 1.5
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: carton_template
        in: path
        schema:
          type: integer
        required: true
        example: '3'
        description: The carton template ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      length:
                        type: string
                      width:
                        type: string
                      height:
                        type: string
                      dimension_unit:
                        type: string
                      tare_weight:
                        type: string
                      weight_unit:
                        type: string
                      is_active:
                        type: boolean
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 3
                    name: Standard Large Carton (Reinforced)
                    length: '18.00'
                    width: '14.00'
                    height: '12.00'
                    dimension_unit: IN
                    tare_weight: '1.50'
                    weight_unit: LB
                    is_active: true
                    created_at: '2026-06-01T10:15:00.000000Z'
                    updated_at: '2026-06-12T09:30:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: patch-api-amazon-integrationinstance-fba-carton-templates-carton-template
    delete:
      tags:
      - Amazon
      summary: Delete Carton Template
      description: 'Delete (soft-retire) a carton template. The template is deactivated
        (`is_active` = false) rather than removed, so historical boxes keep their
        carton template reference. Retired templates no longer appear in **List Carton
        Templates**.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: carton_template
        in: path
        schema:
          type: integer
        required: true
        example: '3'
        description: The carton template ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Carton template deleted successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-amazon-integrationinstance-fba-carton-templates-carton-template
  /api/amazon/{integrationInstance}/draft-inbound-plans/{draft_inbound_plan}/placement-options/generate:
    post:
      tags:
      - Amazon
      summary: Generate Placement Options
      description: 'Generate placement options for the draft FBA inbound plan via
        the Amazon FBA Inbound API (v2024-03-20 generatePlacementOptions operation).
        Each placement option is a possible shipment split — Amazon proposes different
        ways to spread the plan''s inventory across fulfillment centers, with different
        placement fees and discounts.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        This is an asynchronous endpoint: it dispatches a tracked background job and
        returns `{ "data": { "tracked_job_log_id": <id> } }` immediately. Progress
        is visible via the tracked job log endpoints, and the underlying Amazon operation
        is resolved by the `amazon_inbound_operations` poller (a background job).


        Tracked job name: `Generate FBA Placement Options: {plan name}`. When the
        job completes, the offered placement options (with their preview shipments)
        are persisted locally and can be retrieved with **List Placement Options**.


        No request body is required.'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: draft_inbound_plan
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The draft inbound plan ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 201
                  message: Placement options generation started
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-amazon-integrationinstance-draft-inbound-plans-draft-inbound-plan-placement-options-generate
  /api/amazon/{integrationInstance}/draft-inbound-plans/{draft_inbound_plan}/placement-options:
    get:
      tags:
      - Amazon
      summary: List Placement Options
      description: 'List the placement options generated for the draft FBA inbound
        plan, including each option''s preview shipments (the shipment split Amazon
        would create if that option is confirmed).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Each option includes:

        - `status` — one of `offered`, `confirmed`, `expired` (lowercase)

        - `fees` / `discounts` — Amazon-quoted placement fees and incentives for the
        option

        - `expiration` — when the offered option expires on Amazon''s side

        - `shipment_ids` — the Amazon shipment ids making up the option''s split

        - `shipments[]` — preview shipments with `destination_fc`, `destination_address`,
        and `amazon_status`


        Use this to compare splits (fee vs. number of destinations) before confirming
        one with **Confirm Placement Option** — confirmation is irreversible.


        Run **Generate Placement Options** first; this endpoint reads the locally
        persisted results.


        Each shipment includes `distance_miles` (integer|null): the great-circle distance
        in miles from the plan origin (source warehouse) to that fulfillment center,
        computed from internal zip coordinates. Null when a zip cannot be geocoded.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: draft_inbound_plan
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The draft inbound plan ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        placement_option_id:
                          type: string
                        status:
                          type: string
                        fees:
                          type: array
                          items:
                            type: object
                            properties:
                              target:
                                type: string
                              type:
                                type: string
                              value:
                                type: object
                                properties:
                                  amount:
                                    type: integer
                                  code:
                                    type: string
                        discounts:
                          type: array
                          items:
                            type: object
                            properties:
                              target:
                                type: string
                              type:
                                type: string
                              value:
                                type: object
                                properties:
                                  amount:
                                    type: number
                                  code:
                                    type: string
                        expiration:
                          type: string
                        shipment_ids:
                          type: array
                          items:
                            type: string
                        shipments:
                          type: array
                          items:
                            type: object
                            properties:
                              id:
                                type: integer
                              amazon_shipment_id:
                                type: string
                              name:
                                type: string
                              destination_fc:
                                type: string
                              destination_address:
                                type: object
                                properties:
                                  name:
                                    type: string
                                  addressLine1:
                                    type: string
                                  city:
                                    type: string
                                  stateOrProvinceCode:
                                    type: string
                                  postalCode:
                                    type: string
                                  countryCode:
                                    type: string
                              distance_miles:
                                type: integer
                              amazon_status:
                                type: string
                example:
                  data:
                  - id: 3
                    placement_option_id: pl-9f8e7d6c-5b4a-3210-fedc-ba9876543210
                    status: offered
                    fees:
                    - target: Placement Services
                      type: FEE
                      value:
                        amount: 0
                        code: USD
                    discounts:
                    - target: Placement Services
                      type: DISCOUNT
                      value:
                        amount: 42.6
                        code: USD
                    expiration: '2026-06-19T00:00:00.000000Z'
                    shipment_ids:
                    - sh-0a1b2c3d-4e5f-6789-abcd-ef0123456789
                    - sh-1b2c3d4e-5f6a-7890-bcde-f01234567890
                    shipments:
                    - id: 15
                      amazon_shipment_id: sh-0a1b2c3d-4e5f-6789-abcd-ef0123456789
                      name: Shipment 1 of 2
                      destination_fc: TEB9
                      destination_address:
                        name: Amazon.com Services LLC (TEB9)
                        addressLine1: 2170 State Route 27
                        city: Edison
                        stateOrProvinceCode: NJ
                        postalCode: 08817
                        countryCode: US
                      distance_miles: 1536
                      amazon_status: UNCONFIRMED
                    - id: 16
                      amazon_shipment_id: sh-1b2c3d4e-5f6a-7890-bcde-f01234567890
                      name: Shipment 2 of 2
                      destination_fc: FTW1
                      destination_address:
                        name: Amazon.com Services LLC (FTW1)
                        addressLine1: 33333 LBJ FWY
                        city: Dallas
                        stateOrProvinceCode: TX
                        postalCode: '75241'
                        countryCode: US
                      distance_miles: 1536
                      amazon_status: UNCONFIRMED
                  - id: 4
                    placement_option_id: pl-8e7d6c5b-4a39-2810-edcb-a98765432109
                    status: offered
                    fees:
                    - target: Placement Services
                      type: FEE
                      value:
                        amount: 42.6
                        code: USD
                    discounts: []
                    expiration: '2026-06-19T00:00:00.000000Z'
                    shipment_ids:
                    - sh-2c3d4e5f-6a7b-8901-cdef-012345678901
                    shipments:
                    - id: 17
                      amazon_shipment_id: sh-2c3d4e5f-6a7b-8901-cdef-012345678901
                      name: Shipment 1 of 1
                      destination_fc: TEB9
                      destination_address:
                        name: Amazon.com Services LLC (TEB9)
                        addressLine1: 2170 State Route 27
                        city: Edison
                        stateOrProvinceCode: NJ
                        postalCode: 08817
                        countryCode: US
                      distance_miles: 1536
                      amazon_status: UNCONFIRMED
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-integrationinstance-draft-inbound-plans-draft-inbound-plan-placement-options
  /api/amazon/{integrationInstance}/draft-inbound-plans/{draft_inbound_plan}/placement-transport-estimates:
    get:
      tags:
      - Amazon
      summary: Get Placement Transport Estimates
      description: 'Own-carrier small-parcel (SPD) transport cost estimates for every
        OFFERED placement option of the draft plan, so the operator can compare "placement
        fee + transport" totals in real dollars before confirming an option.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        For each offered option, every preview shipment''s physical load (derived
        from the plan items'' product weights/dimensions) is approximated into SPD
        parcels (max 50 lb / 25" per box), rated from the plan''s source-warehouse
        zip to the shipment''s destination FC via EasyPost, and the cheapest carrier
        service per shipment is summed into the option total.


        Response fields per estimate:

        - `placement_option_id` — the local placement option id

        - `total` — summed cheapest-rate transport cost for the option (null when
        `incomplete`)

        - `currency` — quote currency (USD)

        - `incomplete` — true when at least one shipment could not be estimated (missing
        product weight/dims, missing zips, or rating failure)

        - `shipments[]` — per-shipment breakdown: `shipment_id`, `destination_fc`,
        `quote` (`carrier`, `service`, `amount`, `currency`, `parcels`) or null when
        inestimable, `skipped_reason` (null when quoted; otherwise why the shipment
        could not be rated, e.g. `missing_product_dimensions`), and `missing_dims_mskus`
        (MSKUs lacking weight/dimensions when `skipped_reason` is `missing_product_dimensions`;
        empty otherwise)


        `origin_zip` is the source warehouse zip used as the rating origin.


        Each shipment also carries an `assumptions` object describing the physical
        load the rate is built on: `source`, `units`, `weight_lb`, `volume_cuft`,
        `estimated_pallets`, `parcel_count`, `parcel_weight_lb`, `parcel_side_in`,
        `items_missing_data`, `missing_data_mskus`. `assumptions.source` is `box_config`
        when the shipment has real packed cartons (amazon_fba_inbound_boxes with complete
        dims + weight) — then `weight_lb` / `volume_cuft` / `estimated_pallets` /
        `parcel_count` reflect those actual boxes — or `estimated` when the load is
        inferred from the plan items'' product unit dimensions.


        `estimated_at` (top level) is the ISO-8601 time the persisted estimates were
        last computed (null when none stored). The estimate is a ROUGH approximation
        whenever `source` is `estimated`; once real box configurations exist for a
        shipment its rate uses them. Confirmed/expired options are skipped. Requires
        placement options to have been generated first.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: draft_inbound_plan
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The draft inbound plan ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      estimates:
                        type: array
                        items:
                          type: object
                          properties:
                            placement_option_id:
                              type: integer
                            total:
                              type: number
                            currency:
                              type: string
                            incomplete:
                              type: boolean
                            shipments:
                              type: array
                              items:
                                type: object
                                properties:
                                  shipment_id:
                                    type: integer
                                  destination_fc:
                                    type: string
                                  quote:
                                    type: object
                                    properties:
                                      carrier:
                                        type: string
                                      carrier_label:
                                        type: string
                                      service:
                                        type: string
                                      service_label:
                                        type: string
                                      amount:
                                        type: number
                                      currency:
                                        type: string
                                      delivery_days:
                                        type: integer
                                      parcels:
                                        type: integer
                                  options:
                                    type: array
                                    items:
                                      type: object
                                      properties:
                                        carrier:
                                          type: string
                                        carrier_label:
                                          type: string
                                        service:
                                          type: string
                                        service_label:
                                          type: string
                                        amount:
                                          type: number
                                        currency:
                                          type: string
                                        delivery_days:
                                          type: integer
                                        parcels:
                                          type: integer
                                  assumptions:
                                    type: object
                                    properties:
                                      source:
                                        type: string
                                      units:
                                        type: integer
                                      weight_lb:
                                        type: integer
                                      volume_cuft:
                                        type: number
                                      estimated_pallets:
                                        type: string
                                        nullable: true
                                      parcel_count:
                                        type: integer
                                      parcel_weight_lb:
                                        type: integer
                                      parcel_side_in:
                                        type: integer
                                      items_missing_data:
                                        type: integer
                                      missing_data_mskus:
                                        type: array
                                  skipped_reason:
                                    type: string
                                    nullable: true
                                  missing_dims_mskus:
                                    type: array
                      origin_zip:
                        type: string
                      estimated_at:
                        type: string
                example:
                  data:
                    estimates:
                    - placement_option_id: 12
                      total: 148.62
                      currency: USD
                      incomplete: false
                      shipments:
                      - shipment_id: 341
                        destination_fc: SCK8
                        quote:
                          carrier: USPS
                          carrier_label: USPS
                          service: GroundAdvantage
                          service_label: USPS Ground Advantage
                          amount: 74.31
                          currency: USD
                          delivery_days: 3
                          parcels: 3
                        options:
                        - carrier: USPS
                          carrier_label: USPS
                          service: GroundAdvantage
                          service_label: USPS Ground Advantage
                          amount: 74.31
                          currency: USD
                          delivery_days: 3
                          parcels: 3
                        - carrier: UPSDAP
                          carrier_label: UPS
                          service: Ground
                          service_label: UPS Ground
                          amount: 78.9
                          currency: USD
                          delivery_days: 2
                          parcels: 3
                        - carrier: FedExDefault
                          carrier_label: FedEx
                          service: FEDEX_GROUND
                          service_label: FedEx Ground
                          amount: 81.15
                          currency: USD
                          delivery_days: 2
                          parcels: 3
                        assumptions:
                          source: box_config
                          units: 120
                          weight_lb: 105
                          volume_cuft: 12.4
                          estimated_pallets: null
                          parcel_count: 3
                          parcel_weight_lb: 35
                          parcel_side_in: 18
                          items_missing_data: 0
                          missing_data_mskus: []
                        skipped_reason: null
                        missing_dims_mskus: []
                      - shipment_id: 342
                        destination_fc: CLT2
                        quote:
                          carrier: UPSDAP
                          carrier_label: UPS
                          service: Ground
                          service_label: UPS Ground
                          amount: 74.31
                          currency: USD
                          delivery_days: 2
                          parcels: 3
                        options:
                        - carrier: UPSDAP
                          carrier_label: UPS
                          service: Ground
                          service_label: UPS Ground
                          amount: 74.31
                          currency: USD
                          delivery_days: 2
                          parcels: 3
                        - carrier: USPS
                          carrier_label: USPS
                          service: GroundAdvantage
                          service_label: USPS Ground Advantage
                          amount: 76.4
                          currency: USD
                          delivery_days: 3
                          parcels: 3
                        assumptions:
                          source: estimated
                          units: 96
                          weight_lb: 88
                          volume_cuft: 10.1
                          estimated_pallets: null
                          parcel_count: 2
                          parcel_weight_lb: 44
                          parcel_side_in: 20
                          items_missing_data: 0
                          missing_data_mskus: []
                        skipped_reason: null
                        missing_dims_mskus: []
                    - placement_option_id: 13
                      total: null
                      currency: USD
                      incomplete: true
                      shipments:
                      - shipment_id: 343
                        destination_fc: TEB9
                        quote: null
                        options: []
                        assumptions:
                          source: estimated
                          units: 24
                          weight_lb: null
                          volume_cuft: null
                          estimated_pallets: null
                          parcel_count: null
                          parcel_weight_lb: null
                          parcel_side_in: null
                          items_missing_data: 1
                          missing_data_mskus:
                          - MSKU-ABC-123
                        skipped_reason: missing_dims
                        missing_dims_mskus:
                        - MSKU-ABC-123
                    origin_zip: '95206'
                    estimated_at: '2026-07-03T18:00:00+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-integrationinstance-draft-inbound-plans-draft-inbound-plan-placement-transport-estimates
  /api/amazon/{integrationInstance}/draft-inbound-plans/{draft_inbound_plan}/placement-options/{placement_option}/confirm:
    post:
      tags:
      - Amazon
      summary: Confirm Placement Option
      description: 'Confirm one of the offered placement options for the plan (Amazon
        FBA Inbound v2024-03-20 confirmPlacementOption operation). **Confirmation
        is irreversible** — once a placement option is confirmed the other options
        expire, and only the confirmed split''s shipments remain the plan''s real
        shipments.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        This is an asynchronous endpoint: it dispatches a tracked background job and
        returns `{ "data": { "tracked_job_log_id": <id> } }` immediately. Progress
        is visible via the tracked job log endpoints, and the underlying Amazon operation
        is resolved by the `amazon_inbound_operations` poller (a background job).


        Tracked job name: `Confirm FBA Placement Option: {plan name}`. When the job
        completes, the option is marked `confirmed`, every other option of the plan
        is marked `expired`, and the confirmed shipments can be retrieved with **List
        Shipments**.


        Pre-flight validation (HTTP 422, checked synchronously before the job is dispatched):

        - the placement option must not be expired (status `expired` or `expiration`
        in the past)

        - no placement option may already be confirmed for the plan — including this
        one (placement confirmation is irreversible)


        Returns 404 when the placement option does not belong to the draft inbound
        plan.


        No request body is required.'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: draft_inbound_plan
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The draft inbound plan ID.
      - name: placement_option
        in: path
        schema:
          type: integer
        required: true
        example: '3'
        description: The placement option ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 202
                  message: Placement option confirmation started
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 422 Expired Option
                  value:
                    message: This placement option has expired — generate new placement
                      options and pick a current one.
                    errors:
                      placement_option:
                      - This placement option has expired — generate new placement
                        options and pick a current one.
                example-1:
                  summary: 422 Placement Already Confirmed
                  value:
                    message: Another placement option is already confirmed for this
                      plan — placement confirmation is irreversible.
                    errors:
                      placement_option:
                      - Another placement option is already confirmed for this plan
                        — placement confirmation is irreversible.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-amazon-integrationinstance-draft-inbound-plans-draft-inbound-plan-placement-options-placement-option-confirm
  /api/amazon/{integrationInstance}/draft-inbound-plans/{draft_inbound_plan}/shipments:
    get:
      tags:
      - Amazon
      summary: List Shipments
      description: 'List the plan shipments of the draft FBA inbound plan with all
        placement/transport details nested: `items`, `pallets`, `transportation_options`,
        and `delivery_window_options`.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Note:** once a placement option has been confirmed, only the confirmed split''s
        shipments are returned — preview shipments belonging to the rejected (expired)
        placement options are excluded.


        Field notes:

        - `local_status` — lowercase, one of `pending`, `ready`, `shipped`, `checked_in`,
        `receiving`, `closed`, `cancelled`

        - `amazon_status` — Amazon''s raw shipment status (e.g. `UNCONFIRMED`, `WORKING`,
        `SHIPPED`)

        - `confirmed_delivery_window` — populated after a delivery window option is
        confirmed for the shipment

        - `transportation_options[]` / `delivery_window_options[]` — same shape as
        the corresponding list endpoints

        - `tracking_summary` / `freight_bill_numbers` / `shipped_at` — filled in later
        by the shipping workflow


        Each shipment includes `distance_miles` (integer|null): the great-circle distance
        in miles from the plan origin (source warehouse) to that fulfillment center,
        computed from internal zip coordinates. Null when a zip cannot be geocoded.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: draft_inbound_plan
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The draft inbound plan ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        amazon_shipment_id:
                          type: string
                        shipment_confirmation_id:
                          type: string
                        name:
                          type: string
                        destination_fc:
                          type: string
                        destination_address:
                          type: object
                          properties:
                            name:
                              type: string
                            addressLine1:
                              type: string
                            city:
                              type: string
                            stateOrProvinceCode:
                              type: string
                            postalCode:
                              type: string
                            countryCode:
                              type: string
                        distance_miles:
                          type: integer
                        amazon_status:
                          type: string
                        local_status:
                          type: string
                        tracking_summary:
                          type: string
                          nullable: true
                        freight_bill_numbers:
                          type: string
                          nullable: true
                        delivery_window_option_id:
                          type: string
                          nullable: true
                        confirmed_delivery_window:
                          type: string
                          nullable: true
                        shipped_at:
                          type: string
                          nullable: true
                        items:
                          type: array
                          items:
                            type: object
                            properties:
                              id:
                                type: integer
                              msku:
                                type: string
                              fnsku:
                                type: string
                              quantity_shipped:
                                type: integer
                              quantity_received:
                                type: integer
                        pallets:
                          type: array
                          items:
                            type: object
                            properties:
                              id:
                                type: integer
                              length:
                                type: integer
                              width:
                                type: integer
                              height:
                                type: integer
                              dimension_unit:
                                type: string
                              weight:
                                type: integer
                              weight_unit:
                                type: string
                              stackability:
                                type: string
                              quantity:
                                type: integer
                        transportation_options:
                          type: array
                          items:
                            type: object
                            properties:
                              id:
                                type: integer
                              amazon_fba_inbound_plan_shipment_id:
                                type: integer
                              transportation_option_id:
                                type: string
                              program:
                                type: string
                              shipping_mode:
                                type: string
                              carrier:
                                type: object
                                properties:
                                  alphaCode:
                                    type: string
                                  name:
                                    type: string
                              quote:
                                type: object
                                properties:
                                  cost:
                                    type: object
                                    properties:
                                      amount:
                                        type: number
                                      code:
                                        type: string
                                  expiration:
                                    type: string
                              preconditions:
                                type: array
                              status:
                                type: string
                              confirmed_at:
                                type: string
                                nullable: true
                              void_deadline:
                                type: string
                                nullable: true
                        delivery_window_options:
                          type: array
                          items:
                            type: object
                            properties:
                              id:
                                type: integer
                              delivery_window_option_id:
                                type: string
                              start_date:
                                type: string
                              end_date:
                                type: string
                              availability_type:
                                type: string
                              valid_until:
                                type: string
                              status:
                                type: string
                example:
                  data:
                  - id: 15
                    amazon_shipment_id: sh-0a1b2c3d-4e5f-6789-abcd-ef0123456789
                    shipment_confirmation_id: FBA15K7Z9QXM
                    name: Shipment 1 of 2
                    destination_fc: TEB9
                    destination_address:
                      name: Amazon.com Services LLC (TEB9)
                      addressLine1: 2170 State Route 27
                      city: Edison
                      stateOrProvinceCode: NJ
                      postalCode: 08817
                      countryCode: US
                    distance_miles: 1536
                    amazon_status: WORKING
                    local_status: pending
                    tracking_summary: null
                    freight_bill_numbers: null
                    delivery_window_option_id: null
                    confirmed_delivery_window: null
                    shipped_at: null
                    items:
                    - id: 61
                      msku: WIDGET-BLUE-L
                      fnsku: X001ABC123
                      quantity_shipped: 40
                      quantity_received: 0
                    - id: 62
                      msku: WIDGET-RED-S
                      fnsku: X001DEF456
                      quantity_shipped: 12
                      quantity_received: 0
                    pallets:
                    - id: 9
                      length: 48
                      width: 40
                      height: 52
                      dimension_unit: IN
                      weight: 480
                      weight_unit: LB
                      stackability: NON_STACKABLE
                      quantity: 2
                    transportation_options:
                    - id: 21
                      amazon_fba_inbound_plan_shipment_id: 15
                      transportation_option_id: to-3c4d5e6f-7a8b-9012-cdef-345678901234
                      program: AMAZON_PARTNERED_CARRIER
                      shipping_mode: GROUND_SMALL_PARCEL
                      carrier:
                        alphaCode: UPSN
                        name: United Parcel Service Inc.
                      quote:
                        cost:
                          amount: 124.52
                          code: USD
                        expiration: '2026-06-13T00:00:00Z'
                      preconditions: []
                      status: OFFERED
                      confirmed_at: null
                      void_deadline: null
                    - id: 22
                      amazon_fba_inbound_plan_shipment_id: 15
                      transportation_option_id: to-4d5e6f7a-8b9c-0123-def4-456789012345
                      program: USE_YOUR_OWN_CARRIER
                      shipping_mode: FREIGHT_LTL
                      carrier:
                        alphaCode: OTHR
                        name: Other carrier
                      quote: null
                      preconditions:
                      - CONFIRMED_DELIVERY_WINDOW
                      status: OFFERED
                      confirmed_at: null
                      void_deadline: null
                    delivery_window_options:
                    - id: 4
                      delivery_window_option_id: dw-5e6f7a8b-9c0d-1234-ef56-678901234567
                      start_date: '2026-06-22T08:00:00.000000Z'
                      end_date: '2026-06-28T20:00:00.000000Z'
                      availability_type: AVAILABLE
                      valid_until: '2026-06-15T00:00:00.000000Z'
                      status: OFFERED
                  - id: 16
                    amazon_shipment_id: sh-1b2c3d4e-5f6a-7890-bcde-f01234567890
                    shipment_confirmation_id: FBA15K7Z9QXN
                    name: Shipment 2 of 2
                    destination_fc: FTW1
                    destination_address:
                      name: Amazon.com Services LLC (FTW1)
                      addressLine1: 33333 LBJ FWY
                      city: Dallas
                      stateOrProvinceCode: TX
                      postalCode: '75241'
                      countryCode: US
                    distance_miles: 1536
                    amazon_status: WORKING
                    local_status: ready
                    tracking_summary: null
                    freight_bill_numbers: null
                    delivery_window_option_id: dw-6f7a8b9c-0d1e-2345-f678-789012345678
                    confirmed_delivery_window:
                      startDate: 2026-06-22T08:00Z
                      endDate: 2026-06-28T20:00Z
                      availabilityType: AVAILABLE
                      editableUntil: 2026-06-20T00:00Z
                    shipped_at: null
                    items:
                    - id: 63
                      msku: WIDGET-BLUE-L
                      fnsku: X001ABC123
                      quantity_shipped: 24
                      quantity_received: 0
                    pallets: []
                    transportation_options:
                    - id: 24
                      amazon_fba_inbound_plan_shipment_id: 16
                      transportation_option_id: to-5e6f7a8b-9c0d-1234-ef56-567890123456
                      program: AMAZON_PARTNERED_CARRIER
                      shipping_mode: GROUND_SMALL_PARCEL
                      carrier:
                        alphaCode: UPSN
                        name: United Parcel Service Inc.
                      quote:
                        cost:
                          amount: 86.1
                          code: USD
                        expiration: '2026-06-13T00:00:00Z'
                      preconditions: []
                      status: CONFIRMED
                      confirmed_at: '2026-06-12T15:04:05.000000Z'
                      void_deadline: '2026-06-13T15:04:05.000000Z'
                    delivery_window_options:
                    - id: 5
                      delivery_window_option_id: dw-6f7a8b9c-0d1e-2345-f678-789012345678
                      start_date: '2026-06-22T08:00:00.000000Z'
                      end_date: '2026-06-28T20:00:00.000000Z'
                      availability_type: AVAILABLE
                      valid_until: '2026-06-15T00:00:00.000000Z'
                      status: CONFIRMED
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-integrationinstance-draft-inbound-plans-draft-inbound-plan-shipments
  /api/amazon/{integrationInstance}/draft-inbound-plans/{draft_inbound_plan}/transportation-options/generate:
    post:
      tags:
      - Amazon
      summary: Generate Transportation Options
      description: 'Generate transportation options (carrier quotes) for the confirmed
        placement''s shipments via the Amazon FBA Inbound API (v2024-03-20 generateTransportationOptions
        operation). Amazon returns partnered-carrier and own-carrier options per shipping
        mode for each shipment.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        This is an asynchronous endpoint: it dispatches a tracked background job and
        returns `{ "data": { "tracked_job_log_id": <id> } }` immediately. Progress
        is visible via the tracked job log endpoints, and the underlying Amazon operation
        is resolved by the `amazon_inbound_operations` poller (a background job).


        Tracked job name: `Generate FBA Transportation Options: {plan name}`. When
        the job completes, the offered options are persisted locally and can be retrieved
        with **List Transportation Options** or nested on **List Shipments**.


        **Request body fields:**

        - `shipments` (array, **required**, min 1) — one entry per shipment to quote

        - `shipments.*.shipment_id` (integer, **required**) — LOCAL plan-shipment
        row id (not the Amazon shipment id); must belong to this draft inbound plan
        (422 otherwise)

        - `shipments.*.ready_to_ship_date` (date, **required**) — must be today or
        later (422: “The ready-to-ship date must be today or later.”)

        - `shipments.*.pallets` (array, optional) — pallet configuration, needed for
        freight (LTL/FTL) quotes

        - `shipments.*.pallets.*.length` / `width` / `height` (numeric, **required**,
        > 0)

        - `shipments.*.pallets.*.weight` (numeric, **required**, > 0)

        - `shipments.*.pallets.*.dimension_unit` (string, optional, `IN` or `CM`)

        - `shipments.*.pallets.*.weight_unit` (string, optional, `LB` or `KG`)

        - `shipments.*.pallets.*.stackability` (string, optional, nullable, `STACKABLE`
        or `NON_STACKABLE`)

        - `shipments.*.pallets.*.quantity` (integer, **required**, min 1)


        Pre-flight validation (HTTP 422, checked synchronously before the job is dispatched):

        - a placement option must already be confirmed for the plan

        - every `shipment_id` must belong to this draft inbound plan'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                shipments:
                  type: array
                  items:
                    type: object
                    properties:
                      shipment_id:
                        type: integer
                      ready_to_ship_date:
                        type: string
                      pallets:
                        type: array
                        items:
                          type: object
                          properties:
                            length:
                              type: integer
                            width:
                              type: integer
                            height:
                              type: integer
                            weight:
                              type: integer
                            dimension_unit:
                              type: string
                            weight_unit:
                              type: string
                            stackability:
                              type: string
                            quantity:
                              type: integer
              example:
                shipments:
                - shipment_id: 15
                  ready_to_ship_date: '2026-06-18'
                  pallets:
                  - length: 48
                    width: 40
                    height: 52
                    weight: 480
                    dimension_unit: IN
                    weight_unit: LB
                    stackability: NON_STACKABLE
                    quantity: 2
                - shipment_id: 16
                  ready_to_ship_date: '2026-06-18'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: draft_inbound_plan
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The draft inbound plan ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 203
                  message: Transportation options generation started
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 422 No Confirmed Placement
                  value:
                    message: Confirm a placement option before working with transportation
                      options.
                    errors:
                      placement_option:
                      - Confirm a placement option before working with transportation
                        options.
                example-1:
                  summary: 422 Shipment Not In Plan
                  value:
                    message: The shipment does not belong to this draft inbound plan.
                    errors:
                      shipments.0.shipment_id:
                      - The shipment does not belong to this draft inbound plan.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-amazon-integrationinstance-draft-inbound-plans-draft-inbound-plan-transportation-options-generate
  /api/amazon/{integrationInstance}/draft-inbound-plans/{draft_inbound_plan}/transportation-options:
    get:
      tags:
      - Amazon
      summary: List Transportation Options
      description: 'List all transportation options generated for the draft FBA inbound
        plan, across all of its shipments. Use `amazon_fba_inbound_plan_shipment_id`
        to group options by shipment.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Each option includes:

        - `program` — `AMAZON_PARTNERED_CARRIER` or `USE_YOUR_OWN_CARRIER` (uppercase)

        - `shipping_mode` — uppercase, one of `GROUND_SMALL_PARCEL`, `FREIGHT_LTL`,
        `FREIGHT_FTL_PALLET`, `FREIGHT_FTL_NONPALLET`, `OCEAN_LCL`, `OCEAN_FCL`, `AIR_SMALL_PARCEL`,
        `AIR_SMALL_PARCEL_EXPRESS`

        - `carrier` — Amazon carrier object (`alphaCode`, `name`)

        - `quote` — partnered-carrier cost quote (`cost.amount` / `cost.code`); `null`
        for own-carrier options

        - `preconditions` — e.g. `CONFIRMED_DELIVERY_WINDOW` on non-partnered (nPCP)
        options that require a confirmed delivery window before they can be confirmed

        - `status` — `OFFERED`, `CONFIRMED`, or `VOIDED` (uppercase)

        - `confirmed_at` / `void_deadline` — set when the option is confirmed; the
        void deadline is the cut-off for cancelling a partnered confirmation without
        carrier charges


        Run **Generate Transportation Options** first; this endpoint reads the locally
        persisted results.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: draft_inbound_plan
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The draft inbound plan ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        amazon_fba_inbound_plan_shipment_id:
                          type: integer
                        transportation_option_id:
                          type: string
                        program:
                          type: string
                        shipping_mode:
                          type: string
                        carrier:
                          type: object
                          properties:
                            alphaCode:
                              type: string
                            name:
                              type: string
                        quote:
                          type: object
                          properties:
                            cost:
                              type: object
                              properties:
                                amount:
                                  type: number
                                code:
                                  type: string
                            expiration:
                              type: string
                        preconditions:
                          type: array
                        status:
                          type: string
                        confirmed_at:
                          type: string
                          nullable: true
                        void_deadline:
                          type: string
                          nullable: true
                example:
                  data:
                  - id: 21
                    amazon_fba_inbound_plan_shipment_id: 15
                    transportation_option_id: to-3c4d5e6f-7a8b-9012-cdef-345678901234
                    program: AMAZON_PARTNERED_CARRIER
                    shipping_mode: GROUND_SMALL_PARCEL
                    carrier:
                      alphaCode: UPSN
                      name: United Parcel Service Inc.
                    quote:
                      cost:
                        amount: 124.52
                        code: USD
                      expiration: '2026-06-13T00:00:00Z'
                    preconditions: []
                    status: OFFERED
                    confirmed_at: null
                    void_deadline: null
                  - id: 22
                    amazon_fba_inbound_plan_shipment_id: 15
                    transportation_option_id: to-4d5e6f7a-8b9c-0123-def4-456789012345
                    program: USE_YOUR_OWN_CARRIER
                    shipping_mode: FREIGHT_LTL
                    carrier:
                      alphaCode: OTHR
                      name: Other carrier
                    quote: null
                    preconditions:
                    - CONFIRMED_DELIVERY_WINDOW
                    status: OFFERED
                    confirmed_at: null
                    void_deadline: null
                  - id: 24
                    amazon_fba_inbound_plan_shipment_id: 16
                    transportation_option_id: to-5e6f7a8b-9c0d-1234-ef56-567890123456
                    program: AMAZON_PARTNERED_CARRIER
                    shipping_mode: GROUND_SMALL_PARCEL
                    carrier:
                      alphaCode: UPSN
                      name: United Parcel Service Inc.
                    quote:
                      cost:
                        amount: 86.1
                        code: USD
                      expiration: '2026-06-13T00:00:00Z'
                    preconditions: []
                    status: CONFIRMED
                    confirmed_at: '2026-06-12T15:04:05.000000Z'
                    void_deadline: '2026-06-13T15:04:05.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-integrationinstance-draft-inbound-plans-draft-inbound-plan-transportation-options
  /api/amazon/{integrationInstance}/draft-inbound-plans/{draft_inbound_plan}/transportation-options/confirm:
    post:
      tags:
      - Amazon
      summary: Confirm Transportation Options
      description: 'Confirm one transportation option per shipment of the confirmed
        placement (Amazon FBA Inbound v2024-03-20 confirmTransportationOptions operation).
        This is lock gate #2 of the inbound workflow — carrier charges apply once
        the void window passes.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        This is an asynchronous endpoint: it dispatches a tracked background job and
        returns `{ "data": { "tracked_job_log_id": <id> } }` immediately. Progress
        is visible via the tracked job log endpoints, and the underlying Amazon operation
        is resolved by the `amazon_inbound_operations` poller (a background job).


        Tracked job name: `Confirm FBA Transportation: {plan name}`. When the job
        completes, the selected options are marked `CONFIRMED` with their void deadlines
        and the shipments are refreshed.


        **Request body fields:**

        - `selections` (array, **required**, min 1) — exactly one entry per shipment
        of the confirmed placement

        - `selections.*.shipment_id` (integer, **required**) — LOCAL plan-shipment
        row id

        - `selections.*.transportation_option_id` (integer, **required**) — LOCAL
        transportation-option row id


        Both ids are LOCAL row ids — the confirm job maps them to Amazon ids before
        calling SP-API.


        Pre-flight validation (HTTP 422, checked synchronously before the job is dispatched):

        - a placement option must be confirmed for the plan

        - each `shipment_id` must belong to the confirmed placement option of this
        plan

        - each shipment must have exactly one selection — no duplicates, and every
        shipment of the confirmed placement must be covered (none missing)

        - each `transportation_option_id` must belong to its selected shipment

        - non-partnered options carrying the `CONFIRMED_DELIVERY_WINDOW` precondition
        require the shipment to already have a confirmed delivery window

        - Amazon SPD rule: when any selection ships via small parcel (`GROUND_SMALL_PARCEL`),
        every selection must use the same carrier and the same program


        **Void-window semantics:** on confirmation each option''s `void_deadline`
        is set to now + 24 hours for partnered small parcel, now + 1 hour for partnered
        freight (LTL/FTL), and `null` for own-carrier options (nothing to void).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                selections:
                  type: array
                  items:
                    type: object
                    properties:
                      shipment_id:
                        type: integer
                      transportation_option_id:
                        type: integer
              example:
                selections:
                - shipment_id: 15
                  transportation_option_id: 21
                - shipment_id: 16
                  transportation_option_id: 24
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: draft_inbound_plan
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The draft inbound plan ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 204
                  message: Transportation confirmation started
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 422 Selection Errors
                  value:
                    message: Each shipment must have exactly one transportation selection.
                      (and 2 more errors)
                    errors:
                      selections.1.shipment_id:
                      - Each shipment must have exactly one transportation selection.
                      selections.2.transportation_option_id:
                      - The transportation option does not belong to the selected
                        shipment.
                      selections:
                      - 'Every shipment of the confirmed placement requires a transportation
                        selection. Missing: Shipment 2 of 2.'
                example-1:
                  summary: 422 Delivery Window Required (nPCP)
                  value:
                    message: Shipment sh-0a1b2c3d-4e5f-6789-abcd-ef0123456789 requires
                      a confirmed delivery window before this carrier option can be
                      confirmed — confirm a delivery window first.
                    errors:
                      selections.0.transportation_option_id:
                      - Shipment sh-0a1b2c3d-4e5f-6789-abcd-ef0123456789 requires
                        a confirmed delivery window before this carrier option can
                        be confirmed — confirm a delivery window first.
                example-2:
                  summary: 422 SPD Carrier/Program Mismatch
                  value:
                    message: Amazon requires all shipments to use the same carrier
                      and program when any shipment ships via small parcel (SPD) —
                      pick matching small parcel options for every shipment.
                    errors:
                      selections:
                      - Amazon requires all shipments to use the same carrier and
                        program when any shipment ships via small parcel (SPD) — pick
                        matching small parcel options for every shipment.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-amazon-integrationinstance-draft-inbound-plans-draft-inbound-plan-transportation-options-confirm
  ? /api/amazon/{integrationInstance}/draft-inbound-plans/{draft_inbound_plan}/shipments/{plan_shipment}/delivery-window-options/generate
  : post:
      tags:
      - Amazon
      summary: Generate Delivery Window Options
      description: 'Generate delivery window options for a single plan shipment (Amazon
        FBA Inbound v2024-03-20 generateDeliveryWindowOptions operation). Delivery
        windows are required for non-partnered (own-carrier) transportation options
        that carry the `CONFIRMED_DELIVERY_WINDOW` precondition — confirm a window
        before confirming such a transportation option.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        This is an asynchronous endpoint: it dispatches a tracked background job and
        returns `{ "data": { "tracked_job_log_id": <id> } }` immediately. Progress
        is visible via the tracked job log endpoints, and the underlying Amazon operation
        is resolved by the `amazon_inbound_operations` poller (a background job).


        Tracked job name: `Generate FBA Delivery Windows: {plan name}`. When the job
        completes, the offered windows are persisted locally and can be retrieved
        with **List Delivery Window Options**.


        Returns 404 when the shipment does not belong to the draft inbound plan.


        No request body is required.'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: draft_inbound_plan
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The draft inbound plan ID.
      - name: plan_shipment
        in: path
        schema:
          type: integer
        required: true
        example: '15'
        description: The plan shipment ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 205
                  message: Delivery window options generation started
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-amazon-integrationinstance-draft-inbound-plans-draft-inbound-plan-shipments-plan-shipment-delivery-window-options-generate
  ? /api/amazon/{integrationInstance}/draft-inbound-plans/{draft_inbound_plan}/shipments/{plan_shipment}/delivery-window-options
  : get:
      tags:
      - Amazon
      summary: List Delivery Window Options
      description: 'List the delivery window options generated for a plan shipment.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Each option includes:

        - `start_date` / `end_date` — the delivery window Amazon offers for the shipment

        - `availability_type` — e.g. `AVAILABLE` or `CONGESTED`

        - `valid_until` — when the offered window expires and can no longer be confirmed

        - `status` — `OFFERED`, `CONFIRMED`, or `EXPIRED` (uppercase)


        Run **Generate Delivery Window Options** first; this endpoint reads the locally
        persisted results. Returns 404 when the shipment does not belong to the draft
        inbound plan.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: draft_inbound_plan
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The draft inbound plan ID.
      - name: plan_shipment
        in: path
        schema:
          type: integer
        required: true
        example: '15'
        description: The plan shipment ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        delivery_window_option_id:
                          type: string
                        start_date:
                          type: string
                        end_date:
                          type: string
                        availability_type:
                          type: string
                        valid_until:
                          type: string
                        status:
                          type: string
                example:
                  data:
                  - id: 4
                    delivery_window_option_id: dw-5e6f7a8b-9c0d-1234-ef56-678901234567
                    start_date: '2026-06-22T08:00:00.000000Z'
                    end_date: '2026-06-28T20:00:00.000000Z'
                    availability_type: AVAILABLE
                    valid_until: '2026-06-15T00:00:00.000000Z'
                    status: OFFERED
                  - id: 6
                    delivery_window_option_id: dw-7a8b9c0d-1e2f-3456-a789-890123456789
                    start_date: '2026-06-29T08:00:00.000000Z'
                    end_date: '2026-07-05T20:00:00.000000Z'
                    availability_type: CONGESTED
                    valid_until: '2026-06-15T00:00:00.000000Z'
                    status: OFFERED
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-integrationinstance-draft-inbound-plans-draft-inbound-plan-shipments-plan-shipment-delivery-window-options
  ? /api/amazon/{integrationInstance}/draft-inbound-plans/{draft_inbound_plan}/shipments/{plan_shipment}/delivery-window-options/{delivery_window_option}/confirm
  : post:
      tags:
      - Amazon
      summary: Confirm Delivery Window Option
      description: 'Confirm a delivery window option for the shipment (Amazon FBA
        Inbound v2024-03-20 confirmDeliveryWindowOptions operation). Once confirmed,
        the shipment''s `confirmed_delivery_window` is populated and transportation
        options that carry the `CONFIRMED_DELIVERY_WINDOW` precondition become confirmable.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        This is an asynchronous endpoint: it dispatches a tracked background job and
        returns `{ "data": { "tracked_job_log_id": <id> } }` immediately. Progress
        is visible via the tracked job log endpoints, and the underlying Amazon operation
        is resolved by the `amazon_inbound_operations` poller (a background job).


        Tracked job name: `Confirm FBA Delivery Window: {plan name}`.


        Pre-flight validation (HTTP 422, checked synchronously before the job is dispatched):

        - the delivery window option must not be expired (status `EXPIRED` or `valid_until`
        in the past)


        Returns 404 when the shipment does not belong to the draft inbound plan, or
        the delivery window option does not belong to the shipment.


        No request body is required.'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: draft_inbound_plan
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The draft inbound plan ID.
      - name: plan_shipment
        in: path
        schema:
          type: integer
        required: true
        example: '15'
        description: The plan shipment ID.
      - name: delivery_window_option
        in: path
        schema:
          type: integer
        required: true
        example: '4'
        description: The delivery window option ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 206
                  message: Delivery window confirmation started
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      delivery_window_option:
                        type: array
                        items:
                          type: string
                example:
                  message: This delivery window has expired — generate new delivery
                    window options and pick a current one.
                  errors:
                    delivery_window_option:
                    - This delivery window has expired — generate new delivery window
                      options and pick a current one.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-amazon-integrationinstance-draft-inbound-plans-draft-inbound-plan-shipments-plan-shipment-delivery-window-options-delivery-window-option-confirm
  /api/amazon/{integrationInstance}/draft-inbound-plans/{draft_inbound_plan}/placement-transport-estimates/estimate:
    post:
      tags:
      - Amazon
      summary: Estimate Placement Transport Costs
      description: 'Kicks off a fresh own-carrier transport estimate for every OFFERED
        placement option on the draft inbound plan. **Queues a background job** (the
        estimate runs dozens of carrier rate calls, so it is taken off the request
        thread) and returns a job id (`tracked_job_log_id`) for polling progress.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        For each placement option the job rates every shipment against the connected
        carriers, keeps the cheapest quote per shipment, and sums them per option
        — letting you compare Amazon''s placement fee plus your own transport cost
        across options. Results persist per option and are read back instantly via
        `GET .../placement-transport-estimates`.


        The estimate is intentionally rough: parcels are derived from product weights/dimensions
        (or the plan''s box configuration when available); the real box configuration
        confirmed later is authoritative. No request body or query parameters.'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Amazon integration instance id
        example: '1'
      - name: draft_inbound_plan
        in: path
        schema:
          type: string
        required: true
        description: Draft inbound plan id
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 4821
                  message: Transport estimate started
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-amazon-integrationinstance-draft-inbound-plans-draft-inbound-plan-placement-transport-estimates-estimate
  /api/amazon/{integrationInstance}/draft-inbound-plans/{draft_inbound_plan}/labels/item-labels:
    post:
      tags:
      - Amazon
      summary: Create Item Labels (FNSKU)
      description: "Generate FNSKU (MSKU) item labels for products on the draft inbound\
        \ plan via the synchronous Amazon FBA Inbound v2024-03-20 `createMarketplaceItemLabels`\
        \ operation. Returns the label document download URL immediately (no tracked\
        \ job) and records the print in the label-print audit trail (see **List Label\
        \ Prints**; repeat prints are auto-flagged `is_reprint`).\n\n:::info[Authorization]\n\
        Any valid API token can call this endpoint — no specific scope required. [Manage\
        \ tokens](https://app.sku.io/settings/api).\n:::\n\n**Fields:**\n- `label_type`\
        \ (string, **required**) — `STANDARD_FORMAT` or `THERMAL_PRINTING`\n- `page_type`\
        \ (string, **required**, max 64) — Amazon label page type, e.g. `Letter_30`\
        \ (30-up letter sheet), `Letter_24`, `Thermal_NonPCP`. Pair thermal page types\
        \ with `THERMAL_PRINTING`\n- `mskus` (array, **required**, min 1) — the MSKUs\
        \ to print labels for:\n  - `mskus.*.msku` (string, **required**, max 255)\
        \ — must be an MSKU that is part of this inbound plan (422 otherwise)\n  -\
        \ `mskus.*.quantity` (integer, **required**, min 1) — number of labels for\
        \ this MSKU\n\n**Response:** `url` (time-limited label document download URL),\
        \ `expiration` (URL expiration timestamp, may be null), and `label_print_id`\
        \ (the audit-trail record).\n\n**422 conditions:**\n- an `mskus.*.msku` value\
        \ is not part of this inbound plan\n- the integration instance has no participating\
        \ Amazon marketplace (re-sync marketplace participations)\n- Amazon rejects\
        \ the request (SP-API error messages are parsed and surfaced per field)\n\
        - Amazon does not return a label document"
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                label_type:
                  type: string
                page_type:
                  type: string
                mskus:
                  type: array
                  items:
                    type: object
                    properties:
                      msku:
                        type: string
                      quantity:
                        type: integer
              example:
                label_type: STANDARD_FORMAT
                page_type: Letter_30
                mskus:
                - msku: WIDGET-BLUE-L
                  quantity: 24
                - msku: WIDGET-RED-M
                  quantity: 12
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: draft_inbound_plan
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The draft inbound plan ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      url:
                        type: string
                      expiration:
                        type: string
                      label_print_id:
                        type: integer
                example:
                  data:
                    url: https://sellercentral.amazon.com/labels/download/amzn1.tortuga.4.na.aGVsbG8td29ybGQ.pdf?X-Amz-Expires=300
                    expiration: '2026-06-12T18:45:00Z'
                    label_print_id: 41
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 422 Unknown MSKU
                  value:
                    message: MSKU "WIDGET-BLUE-L" is not part of this inbound plan.
                    errors:
                      mskus.0.msku:
                      - MSKU "WIDGET-BLUE-L" is not part of this inbound plan.
                example-1:
                  summary: 422 Amazon Error
                  value:
                    message: Amazon did not return a label document — try again.
                    errors:
                      general:
                      - Amazon did not return a label document — try again.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-amazon-integrationinstance-draft-inbound-plans-draft-inbound-plan-labels-item-labels
  /api/amazon/{integrationInstance}/draft-inbound-plans/{draft_inbound_plan}/shipments/{plan_shipment}/labels/box-labels:
    post:
      tags:
      - Amazon
      summary: Create Box Labels
      description: 'Generate box (carton) labels for a confirmed shipment via the
        Amazon Fulfillment Inbound v0 `getLabels` operation. **Requires a shipment
        confirmation ID** — confirm transportation first (422 otherwise). Returns
        the label document download URL synchronously and records the print in the
        audit trail.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Fields:**

        - `page_type` (string, **required**, max 64) — v0 PageType, e.g. `PackageLabel_Letter_6`,
        `PackageLabel_Thermal`, `PackageLabel_Plain_Paper`

        - `label_type` (string, optional, max 32, default `UNIQUE`) — v0 LabelType

        - `box_count` (integer, optional, nullable, min 1) — number of package labels
        (v0 NumberOfPackages). Defaults to the number of boxes packed for this shipment
        when omitted


        **422 conditions:**

        - the shipment has no `shipment_confirmation_id` yet (transportation not confirmed)

        - Amazon rejects the request or returns no label document (SP-API errors parsed
        per field)


        Returns 404 when the shipment does not belong to the draft inbound plan.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                page_type:
                  type: string
                label_type:
                  type: string
                box_count:
                  type: integer
              example:
                page_type: PackageLabel_Letter_6
                label_type: UNIQUE
                box_count: 8
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: draft_inbound_plan
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The draft inbound plan ID.
      - name: plan_shipment
        in: path
        schema:
          type: integer
        required: true
        example: '5'
        description: The plan shipment ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      url:
                        type: string
                      label_print_id:
                        type: integer
                example:
                  data:
                    url: https://fba-inbound-labels.s3.amazonaws.com/FBA15K7Q8XYZ/PackageLabel_Letter_6.pdf?X-Amz-Expires=300
                    label_print_id: 42
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      shipment:
                        type: array
                        items:
                          type: string
                example:
                  message: Confirm transportation first — box labels need a shipment
                    confirmation ID
                  errors:
                    shipment:
                    - Confirm transportation first — box labels need a shipment confirmation
                      ID
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-amazon-integrationinstance-draft-inbound-plans-draft-inbound-plan-shipments-plan-shipment-labels-box-labels
  /api/amazon/{integrationInstance}/draft-inbound-plans/{draft_inbound_plan}/shipments/{plan_shipment}/labels/pallet-labels:
    post:
      tags:
      - Amazon
      summary: Create Pallet Labels
      description: 'Generate pallet labels for a confirmed LTL/FTL shipment via the
        Amazon Fulfillment Inbound v0 `getLabels` operation with `LabelType=PALLET`.
        The page type is fixed to `PackageLabel_Letter_4` (Amazon''s standard letter-format
        pallet label sheet). **Requires a shipment confirmation ID** — confirm transportation
        first (422 otherwise). Records the print in the audit trail.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Fields:**

        - `count` (integer, **required**, min 1) — number of pallet labels (v0 NumberOfPallets).
        Amazon recommends 4 labels per pallet (one per side)


        **422 conditions:**

        - the shipment has no `shipment_confirmation_id` yet (transportation not confirmed)

        - Amazon rejects the request or returns no label document (SP-API errors parsed
        per field)


        Returns 404 when the shipment does not belong to the draft inbound plan.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                count:
                  type: integer
              example:
                count: 8
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: draft_inbound_plan
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The draft inbound plan ID.
      - name: plan_shipment
        in: path
        schema:
          type: integer
        required: true
        example: '5'
        description: The plan shipment ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      url:
                        type: string
                      label_print_id:
                        type: integer
                example:
                  data:
                    url: https://fba-inbound-labels.s3.amazonaws.com/FBA15K7Q8XYZ/PackageLabel_Letter_4.pdf?X-Amz-Expires=300
                    label_print_id: 43
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      shipment:
                        type: array
                        items:
                          type: string
                example:
                  message: Confirm transportation first — pallet labels need a shipment
                    confirmation ID
                  errors:
                    shipment:
                    - Confirm transportation first — pallet labels need a shipment
                      confirmation ID
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-amazon-integrationinstance-draft-inbound-plans-draft-inbound-plan-shipments-plan-shipment-labels-pallet-labels
  /api/amazon/{integrationInstance}/draft-inbound-plans/{draft_inbound_plan}/shipments/{plan_shipment}/bill-of-lading:
    get:
      tags:
      - Amazon
      summary: Get Bill of Lading
      description: 'Fetch the bill of lading (BOL) document for a confirmed LTL/FTL
        shipment via the Amazon Fulfillment Inbound v0 `getBillOfLading` operation.
        Amazon only generates the BOL after the carrier is assigned — until then this
        endpoint returns **200 with `available: false`** (not an error), including
        when the shipment has no confirmation ID yet or Amazon responds 404/empty.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        When the BOL is available, the response contains the download `url`, `available:
        true`, and a `label_print_id` (the fetch is recorded in the label-print audit
        trail as kind `BOL`).


        Returns 404 when the shipment does not belong to the draft inbound plan.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: draft_inbound_plan
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The draft inbound plan ID.
      - name: plan_shipment
        in: path
        schema:
          type: integer
        required: true
        example: '5'
        description: The plan shipment ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 OK (Available)
                  value:
                    data:
                      url: https://fba-inbound-labels.s3.amazonaws.com/FBA15K7Q8XYZ/bill-of-lading.pdf?X-Amz-Expires=300
                      available: true
                      label_print_id: 44
                example-1:
                  summary: 200 OK (Not Yet Available)
                  value:
                    data:
                      url: null
                      available: false
                      message: Bill of lading not yet available — Amazon generates
                        it after the carrier is assigned.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-integrationinstance-draft-inbound-plans-draft-inbound-plan-shipments-plan-shipment-bill-of-lading
  /api/amazon/{integrationInstance}/draft-inbound-plans/{draft_inbound_plan}/labels/2d-barcode-data:
    get:
      tags:
      - Amazon
      summary: Get 2D Barcode Data
      description: 'Get the 2D box-content barcode content strings for every box of
        a packing group that was submitted with the `BARCODE_2D` content information
        source. Returns one entry per box with the content string in Amazon''s documented
        AMZN 2D box-content format:


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        `AMZN,PO:<shipment reference>,MSKU:<msku>,QTY:<qty>[,EXP:<YYYY-MM-DD>],MSKU:...`


        The `PO:` reference is the shipment confirmation ID (FBA…) when available,
        falling back to the Amazon shipment ID, then `PLAN-{id}`. Each box item contributes
        an `MSKU:`/`QTY:` pair; `EXP:` follows the pair it applies to when the item
        has an expiration date.


        **Note:** this endpoint returns content STRINGS only — PDF417 graphic rendering
        is deferred (render client-side or in a later phase).


        **Query parameters:**

        - `packing_group_id` (integer, **required**) — the packing group; must belong
        to this draft inbound plan (404 otherwise)


        **422 condition:** the packing group was not submitted with the `BARCODE_2D`
        content information source.'
      parameters:
      - name: packing_group_id
        in: query
        schema:
          type: integer
        description: (Required) The packing group ID. Must belong to this draft inbound
          plan and have been submitted with BARCODE_2D.
        example: '12'
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: draft_inbound_plan
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The draft inbound plan ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      groups:
                        type: array
                        items:
                          type: object
                          properties:
                            box_id:
                              type: integer
                            box_number:
                              type: integer
                            content_string:
                              type: string
                example:
                  data:
                    groups:
                    - box_id: 101
                      box_number: 1
                      content_string: AMZN,PO:FBA15K7Q8XYZ,MSKU:WIDGET-BLUE-L,QTY:12,MSKU:WIDGET-RED-M,QTY:6,EXP:2027-01-31
                    - box_id: 102
                      box_number: 2
                      content_string: AMZN,PO:FBA15K7Q8XYZ,MSKU:WIDGET-BLUE-L,QTY:24
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      packing_group_id:
                        type: array
                        items:
                          type: string
                example:
                  message: 2D barcode data is only available for packing groups submitted
                    with the BARCODE_2D content information source.
                  errors:
                    packing_group_id:
                    - 2D barcode data is only available for packing groups submitted
                      with the BARCODE_2D content information source.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-integrationinstance-draft-inbound-plans-draft-inbound-plan-labels-2d-barcode-data
  /api/amazon/{integrationInstance}/draft-inbound-plans/{draft_inbound_plan}/label-prints:
    get:
      tags:
      - Amazon
      summary: List Label Prints
      description: 'List the label-print audit trail for the draft inbound plan, newest
        first. Every successful label generation (item labels, box labels, pallet
        labels, BOL fetch) records an entry; repeat prints of the same kind for the
        same shipment (or plan, for plan-level kinds like FNSKU) are auto-flagged
        `is_reprint: true`.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Response fields (per entry):**

        - `id` (integer)

        - `label_kind` (string) — `FNSKU`, `BOX`, `PALLET`, `BOL`, or `CONTENT_2D`

        - `format` (string) — label format/page type as printed, e.g. `STANDARD_FORMAT/Letter_30`,
        `PackageLabel_Letter_6`, `PackageLabel_Letter_4`, `PDF`

        - `quantity` (integer) — number of labels printed

        - `document_url_snapshot` (string) — the (time-limited) document URL at print
        time

        - `is_reprint` (boolean)

        - `user` (object|null) — `{ id, name }` of the user who printed

        - `amazon_fba_inbound_plan_shipment_id` (integer|null) — the shipment, for
        shipment-level kinds; null for plan-level kinds (FNSKU)

        - `created_at` (datetime, UTC)'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: draft_inbound_plan
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The draft inbound plan ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        label_kind:
                          type: string
                        format:
                          type: string
                        quantity:
                          type: integer
                        document_url_snapshot:
                          type: string
                        is_reprint:
                          type: boolean
                        user:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        amazon_fba_inbound_plan_shipment_id:
                          type: integer
                        created_at:
                          type: string
                example:
                  data:
                  - id: 44
                    label_kind: BOL
                    format: PDF
                    quantity: 1
                    document_url_snapshot: https://fba-inbound-labels.s3.amazonaws.com/FBA15K7Q8XYZ/bill-of-lading.pdf?X-Amz-Expires=300
                    is_reprint: false
                    user:
                      id: 3
                      name: Jane Operator
                    amazon_fba_inbound_plan_shipment_id: 5
                    created_at: '2026-06-12T16:42:11.000000Z'
                  - id: 42
                    label_kind: BOX
                    format: PackageLabel_Letter_6
                    quantity: 8
                    document_url_snapshot: https://fba-inbound-labels.s3.amazonaws.com/FBA15K7Q8XYZ/PackageLabel_Letter_6.pdf?X-Amz-Expires=300
                    is_reprint: true
                    user:
                      id: 3
                      name: Jane Operator
                    amazon_fba_inbound_plan_shipment_id: 5
                    created_at: '2026-06-12T15:30:05.000000Z'
                  - id: 41
                    label_kind: FNSKU
                    format: STANDARD_FORMAT/Letter_30
                    quantity: 36
                    document_url_snapshot: https://sellercentral.amazon.com/labels/download/amzn1.tortuga.4.na.aGVsbG8td29ybGQ.pdf?X-Amz-Expires=300
                    is_reprint: false
                    user:
                      id: 3
                      name: Jane Operator
                    amazon_fba_inbound_plan_shipment_id: null
                    created_at: '2026-06-12T14:05:48.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-integrationinstance-draft-inbound-plans-draft-inbound-plan-label-prints
  /api/amazon/{integrationInstance}/draft-inbound-plans/{draft_inbound_plan}/shipments/{plan_shipment}/mark-shipped:
    post:
      tags:
      - Amazon
      summary: Mark Shipment as Shipped
      description: 'Mark a shipment of the plan as shipped. Sets the shipment''s local
        status to `shipped` (with `shipped_at`) and, for warehouse-sourced shipments
        (those with a linked warehouse transfer), transitions the linked warehouse
        transfer to **in-transit** via the existing FBA transfer pathway (physical-out
        movements + pending inbound). Supplier-sourced shipments (no warehouse transfer)
        skip the transfer step.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Runs in one DB transaction — a warehouse-transfer failure rolls back the status
        change and surfaces as a 422 with the underlying message.


        No request body is required.


        **Response:** the refreshed shipment with `items`, `pallets`, `transportation_options`,
        and `delivery_window_options` loaded.


        **422 conditions:**

        - the shipment is already marked as shipped

        - the shipment has no confirmed transportation option (confirm transportation
        first)

        - the linked warehouse transfer fails to transition to in-transit (underlying
        message surfaced on `warehouse_transfer`)


        Returns 404 when the shipment does not belong to the draft inbound plan.'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: draft_inbound_plan
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The draft inbound plan ID.
      - name: plan_shipment
        in: path
        schema:
          type: integer
        required: true
        example: '5'
        description: The plan shipment ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      amazon_shipment_id:
                        type: string
                      shipment_confirmation_id:
                        type: string
                      name:
                        type: string
                      destination_fc:
                        type: string
                      destination_address:
                        type: object
                        properties:
                          name:
                            type: string
                          addressLine1:
                            type: string
                          city:
                            type: string
                          stateOrProvinceCode:
                            type: string
                          postalCode:
                            type: string
                          countryCode:
                            type: string
                      amazon_status:
                        type: string
                      local_status:
                        type: string
                      tracking_summary:
                        type: object
                        properties:
                          boxes:
                            type: array
                            items:
                              type: object
                              properties:
                                box_id:
                                  type: integer
                                amazon_box_id:
                                  type: string
                                box_number:
                                  type: integer
                                tracking_id:
                                  type: string
                      freight_bill_numbers:
                        type: string
                        nullable: true
                      delivery_window_option_id:
                        type: integer
                      confirmed_delivery_window:
                        type: object
                        properties:
                          start_date:
                            type: string
                          end_date:
                            type: string
                      shipped_at:
                        type: string
                      items:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            msku:
                              type: string
                            fnsku:
                              type: string
                            quantity_shipped:
                              type: integer
                            quantity_received:
                              type: integer
                      pallets:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            length:
                              type: integer
                            width:
                              type: integer
                            height:
                              type: integer
                            dimension_unit:
                              type: string
                            weight:
                              type: integer
                            weight_unit:
                              type: string
                            stackability:
                              type: string
                            quantity:
                              type: integer
                      transportation_options:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            amazon_fba_inbound_plan_shipment_id:
                              type: integer
                            transportation_option_id:
                              type: string
                            program:
                              type: string
                            shipping_mode:
                              type: string
                            carrier:
                              type: object
                              properties:
                                name:
                                  type: string
                                alphaCode:
                                  type: string
                            quote:
                              type: string
                              nullable: true
                            preconditions:
                              type: array
                            status:
                              type: string
                            confirmed_at:
                              type: string
                            void_deadline:
                              type: string
                              nullable: true
                      delivery_window_options:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            delivery_window_option_id:
                              type: string
                            start_date:
                              type: string
                            end_date:
                              type: string
                            availability_type:
                              type: string
                            valid_until:
                              type: string
                            status:
                              type: string
                example:
                  data:
                    id: 5
                    amazon_shipment_id: sh-1234abcd-5678-90ef-ghij-klmnopqrstuv
                    shipment_confirmation_id: FBA15K7Q8XYZ
                    name: Shipment 1 - IND9
                    destination_fc: IND9
                    destination_address:
                      name: Amazon.com Services LLC
                      addressLine1: 1151 S Graham Rd
                      city: Greenwood
                      stateOrProvinceCode: IN
                      postalCode: '46143'
                      countryCode: US
                    amazon_status: WORKING
                    local_status: shipped
                    tracking_summary:
                      boxes:
                      - box_id: 101
                        amazon_box_id: FBA15K7Q8XYZU000001
                        box_number: 1
                        tracking_id: 1Z999AA10123456784
                    freight_bill_numbers: null
                    delivery_window_option_id: 7
                    confirmed_delivery_window:
                      start_date: '2026-06-15'
                      end_date: '2026-06-21'
                    shipped_at: '2026-06-12T16:50:00.000000Z'
                    items:
                    - id: 11
                      msku: WIDGET-BLUE-L
                      fnsku: X0012ABCDE
                      quantity_shipped: 24
                      quantity_received: 0
                    - id: 12
                      msku: WIDGET-RED-M
                      fnsku: X0012FGHIJ
                      quantity_shipped: 12
                      quantity_received: 0
                    pallets:
                    - id: 2
                      length: 48
                      width: 40
                      height: 60
                      dimension_unit: IN
                      weight: 450
                      weight_unit: LB
                      stackability: NON_STACKABLE
                      quantity: 2
                    transportation_options:
                    - id: 9
                      amazon_fba_inbound_plan_shipment_id: 5
                      transportation_option_id: to-9876fedc-ba98-7654-3210-zyxwvutsrqpo
                      program: USE_YOUR_OWN_CARRIER
                      shipping_mode: GROUND_SMALL_PARCEL
                      carrier:
                        name: United Parcel Service Inc.
                        alphaCode: UPSN
                      quote: null
                      preconditions: []
                      status: confirmed
                      confirmed_at: '2026-06-11T20:15:00.000000Z'
                      void_deadline: null
                    delivery_window_options:
                    - id: 7
                      delivery_window_option_id: dw-1111aaaa-2222-bbbb-3333-cccc4444dddd
                      start_date: '2026-06-15'
                      end_date: '2026-06-21'
                      availability_type: AVAILABLE
                      valid_until: '2026-06-14T00:00:00.000000Z'
                      status: confirmed
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 422 Transportation Not Confirmed
                  value:
                    message: Confirm transportation for this shipment before marking
                      it as shipped.
                    errors:
                      shipment:
                      - Confirm transportation for this shipment before marking it
                        as shipped.
                example-1:
                  summary: 422 Already Shipped
                  value:
                    message: This shipment is already marked as shipped.
                    errors:
                      shipment:
                      - This shipment is already marked as shipped.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-amazon-integrationinstance-draft-inbound-plans-draft-inbound-plan-shipments-plan-shipment-mark-shipped
  /api/amazon/{integrationInstance}/draft-inbound-plans/{draft_inbound_plan}/shipments/{plan_shipment}/tracking:
    post:
      tags:
      - Amazon
      summary: Submit Shipment Tracking
      description: "Submit non-partnered-carrier (nPCP) tracking for a shipment. Provide\
        \ **exactly ONE** of:\n- `box_tracking` — per-box tracking IDs (small parcel\
        \ / SPD)\n- `freight_bill_numbers` — freight bill numbers (LTL/FTL)\n\n:::info[Authorization]\n\
        Any valid API token can call this endpoint — no specific scope required. [Manage\
        \ tokens](https://app.sku.io/settings/api).\n:::\n\nSending both (or neither)\
        \ is a 422.\n\n**Fields:**\n- `box_tracking` (array, min 1, required without\
        \ `freight_bill_numbers`, prohibits `freight_bill_numbers`):\n  - `box_tracking.*.box_id`\
        \ (integer, **required**) — local box ID; must belong to this shipment/plan\
        \ and must already have an Amazon box ID (submit packing information first\
        \ — 422 otherwise)\n  - `box_tracking.*.tracking_id` (string, **required**,\
        \ max 255) — carrier tracking number\n- `freight_bill_numbers` (array of strings,\
        \ min 1, max 255 each, required without `box_tracking`)\n\nThe tracking is\
        \ persisted locally first (boxes merged into the shipment's `tracking_summary.boxes`;\
        \ freight bill numbers stored on the shipment), then a tracked background\
        \ job submits it to Amazon via the FBA Inbound v2024-03-20 `updateShipmentTrackingDetails`\
        \ operation. Returns `{ \"data\": { \"tracked_job_log_id\": <id> } }` immediately;\
        \ progress is visible via the tracked job log endpoints.\n\nTracked job name:\
        \ `Update FBA Shipment Tracking: {plan name}`. The job starts an asynchronous\
        \ Amazon operation; the TrackedJobLog is completed (or failed) by the `amazon_inbound_operations`\
        \ poller (a background job), which refreshes the shipment's `tracking_summary`\
        \ from Amazon via `getShipment` on success.\n\n**422 conditions:**\n- neither\
        \ or both of `box_tracking` / `freight_bill_numbers` provided\n- a `box_tracking.*.box_id`\
        \ does not belong to this shipment or plan\n- a box has no Amazon box ID yet\
        \ (packing information not submitted)\n\nReturns 404 when the shipment does\
        \ not belong to the draft inbound plan.\n\n**LTL example body:**\n```json\n\
        {\n  \"freight_bill_numbers\": [\"FBN-2026-0001\", \"FBN-2026-0002\"]\n}\n\
        ```"
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                box_tracking:
                  type: array
                  items:
                    type: object
                    properties:
                      box_id:
                        type: integer
                      tracking_id:
                        type: string
              example:
                box_tracking:
                - box_id: 101
                  tracking_id: 1Z999AA10123456784
                - box_id: 102
                  tracking_id: 1Z999AA10123456791
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: draft_inbound_plan
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The draft inbound plan ID.
      - name: plan_shipment
        in: path
        schema:
          type: integer
        required: true
        example: '5'
        description: The plan shipment ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 318
                  message: Tracking submission started
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 422 Both Provided
                  value:
                    message: Provide either box_tracking (SPD) or freight_bill_numbers
                      (LTL) — not both.
                    errors:
                      box_tracking:
                      - Provide either box_tracking (SPD) or freight_bill_numbers
                        (LTL) — not both.
                example-1:
                  summary: 422 Box Missing Amazon Box ID
                  value:
                    message: 'Box #1 has no Amazon box ID yet — submit packing information
                      before adding tracking.'
                    errors:
                      box_tracking.0.box_id:
                      - 'Box #1 has no Amazon box ID yet — submit packing information
                        before adding tracking.'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-amazon-integrationinstance-draft-inbound-plans-draft-inbound-plan-shipments-plan-shipment-tracking
  /api/amazon/{integrationInstance}/draft-inbound-plans/{draft_inbound_plan}/tracking/board:
    get:
      tags:
      - Amazon
      summary: Get Shipment Board
      description: 'Post-ship shipment board for a draft inbound plan: every shipment
        of the plan''s confirmed placement option with its items, extended with the
        Phase 7 monitoring fields. Data is refreshed hourly by the scheduled `amazon:fba-inbound:sync-shipments`
        sweep (and on demand via **Refresh Shipment**).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Board-only fields** (on top of the standard plan-shipment payload):

        - `days_since_shipped` (integer|null) — whole days since `shipped_at`; null
        when not yet marked shipped

        - `units_shipped` / `units_received` (integer) — sums of the item quantities

        - `boxes_count` (integer) — number of boxes on the shipment

        - `claim_deadline` (date|null) — `shipped_at` + 60 days (Amazon''s reimbursement
        claim window, policy since Oct 2024); null when not shipped

        - `claim_days_remaining` (integer|null) — whole days until `claim_deadline`
        (negative once lapsed); null when not shipped

        - `reconciliation_status` (string) — shipment-level rollup of the item discrepancy
        statuses: `pending` (nothing decided yet, or some items still PENDING/undecided),
        `match` (every item MATCH), `short` (any SHORT), `over` (any OVER), `mixed`
        (both SHORT and OVER present)


        **Discrepancy mapping** (per item, recomputed on every sync):

        - `amazon_status` NOT in (`RECEIVING`, `CLOSED`) → `null` (too early to judge)

        - received == shipped → `MATCH`

        - received > shipped → `OVER`

        - received < shipped and `amazon_status` = `CLOSED` → `SHORT` (final shortage)

        - received < shipped and `amazon_status` = `RECEIVING` → `PENDING` (still
        being received)


        Responses include `items` (id, msku, fnsku, quantity_shipped, quantity_received).
        Pallets, transportation options, and delivery window options are NOT loaded
        on the board endpoint — use **List Shipments** (Placement & Transport) for
        those.


        **Authentication:** Bearer token (PAT).'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: draft_inbound_plan
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The draft inbound plan ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      shipments:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            amazon_shipment_id:
                              type: string
                            shipment_confirmation_id:
                              type: string
                            name:
                              type: string
                            destination_fc:
                              type: string
                            destination_address:
                              type: object
                              properties:
                                name:
                                  type: string
                                addressLine1:
                                  type: string
                                city:
                                  type: string
                                stateOrProvinceCode:
                                  type: string
                                postalCode:
                                  type: string
                                countryCode:
                                  type: string
                            amazon_status:
                              type: string
                            local_status:
                              type: string
                            tracking_summary:
                              type: string
                              nullable: true
                            freight_bill_numbers:
                              type: string
                              nullable: true
                            delivery_window_option_id:
                              type: string
                              nullable: true
                            confirmed_delivery_window:
                              type: string
                              nullable: true
                            shipped_at:
                              type: string
                            items:
                              type: array
                              items:
                                type: object
                                properties:
                                  id:
                                    type: integer
                                  msku:
                                    type: string
                                  fnsku:
                                    type: string
                                  quantity_shipped:
                                    type: integer
                                  quantity_received:
                                    type: integer
                            days_since_shipped:
                              type: integer
                            units_shipped:
                              type: integer
                            units_received:
                              type: integer
                            boxes_count:
                              type: integer
                            claim_deadline:
                              type: string
                            claim_days_remaining:
                              type: integer
                            reconciliation_status:
                              type: string
                example:
                  data:
                    shipments:
                    - id: 15
                      amazon_shipment_id: sh-0a1b2c3d-4e5f-6789-abcd-ef0123456789
                      shipment_confirmation_id: FBA15K7Z9QXM
                      name: Shipment 1 of 2
                      destination_fc: TEB9
                      destination_address:
                        name: Amazon.com Services LLC (TEB9)
                        addressLine1: 2170 State Route 27
                        city: Edison
                        stateOrProvinceCode: NJ
                        postalCode: 08817
                        countryCode: US
                      amazon_status: CLOSED
                      local_status: shipped
                      tracking_summary: null
                      freight_bill_numbers: null
                      delivery_window_option_id: null
                      confirmed_delivery_window: null
                      shipped_at: '2026-05-04T00:00:00.000000Z'
                      items:
                      - id: 61
                        msku: WIDGET-BLUE-L
                        fnsku: X001ABC123
                        quantity_shipped: 40
                        quantity_received: 36
                      - id: 62
                        msku: WIDGET-RED-S
                        fnsku: X001DEF456
                        quantity_shipped: 12
                        quantity_received: 12
                      days_since_shipped: 39
                      units_shipped: 52
                      units_received: 48
                      boxes_count: 6
                      claim_deadline: '2026-07-03'
                      claim_days_remaining: 21
                      reconciliation_status: short
                    - id: 16
                      amazon_shipment_id: sh-1b2c3d4e-5f6a-7890-bcde-f01234567890
                      shipment_confirmation_id: FBA15K8A2RLN
                      name: Shipment 2 of 2
                      destination_fc: ONT8
                      destination_address:
                        name: Amazon.com Services LLC (ONT8)
                        addressLine1: 24300 Nandina Ave
                        city: Moreno Valley
                        stateOrProvinceCode: CA
                        postalCode: '92551'
                        countryCode: US
                      amazon_status: RECEIVING
                      local_status: receiving
                      tracking_summary: null
                      freight_bill_numbers:
                      - FB123456789
                      delivery_window_option_id: dw-5e6f7a8b-9c0d-1234-ef56-678901234567
                      confirmed_delivery_window:
                        startDate: '2026-06-08T08:00:00Z'
                        endDate: '2026-06-14T20:00:00Z'
                        availabilityType: AVAILABLE
                      shipped_at: '2026-06-01T00:00:00.000000Z'
                      items:
                      - id: 63
                        msku: GADGET-GRN-M
                        fnsku: X001GHI789
                        quantity_shipped: 60
                        quantity_received: 25
                      days_since_shipped: 11
                      units_shipped: 60
                      units_received: 25
                      boxes_count: 4
                      claim_deadline: '2026-07-31'
                      claim_days_remaining: 49
                      reconciliation_status: pending
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-integrationinstance-draft-inbound-plans-draft-inbound-plan-tracking-board
  /api/amazon/{integrationInstance}/draft-inbound-plans/{draft_inbound_plan}/tracking/reconciliation:
    get:
      tags:
      - Amazon
      summary: Get Reconciliation
      description: 'Per-shipment reconciliation grid for a draft inbound plan: shipped
        vs received per item with the discrepancy delta, discrepancy status, and resolution
        state. Products are resolved through the plan''s items by MSKU — `product`
        is null when the MSKU is not (or no longer) on the plan.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Shipment fields:** `id`, `name`, `shipment_confirmation_id`, `amazon_status`,
        `claim_deadline` (date|null, `shipped_at` + 60 days), `claim_days_remaining`
        (integer|null, negative once lapsed), `items[]`.


        **Item fields:**

        - `id` (integer) — shipment item id (use for the resolve/unresolve endpoints)

        - `msku` / `fnsku` (string)

        - `quantity_shipped` / `quantity_received` (integer)

        - `discrepancy` (integer) — `quantity_received - quantity_shipped` (negative
        = short, positive = over)

        - `discrepancy_status` (string|null) — `PENDING`, `MATCH`, `SHORT`, `OVER`,
        or null when the shipment is not yet RECEIVING/CLOSED

        - `discrepancy_resolved_at` (datetime|null) / `resolution_note` (string|null)
        — the acknowledge-resolution overlay (does not change `discrepancy_status`)

        - `product` (object|null) — `id`, `sku`, `name`, `image_url`


        **Discrepancy mapping** (per item, recomputed on every sync):

        - `amazon_status` NOT in (`RECEIVING`, `CLOSED`) → `null` (too early to judge)

        - received == shipped → `MATCH`

        - received > shipped → `OVER`

        - received < shipped and `amazon_status` = `CLOSED` → `SHORT` (final shortage)

        - received < shipped and `amazon_status` = `RECEIVING` → `PENDING` (still
        being received)


        **Authentication:** Bearer token (PAT).'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: draft_inbound_plan
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The draft inbound plan ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      shipments:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            shipment_confirmation_id:
                              type: string
                            amazon_status:
                              type: string
                            claim_deadline:
                              type: string
                            claim_days_remaining:
                              type: integer
                            items:
                              type: array
                              items:
                                type: object
                                properties:
                                  id:
                                    type: integer
                                  msku:
                                    type: string
                                  fnsku:
                                    type: string
                                  quantity_shipped:
                                    type: integer
                                  quantity_received:
                                    type: integer
                                  discrepancy:
                                    type: integer
                                  discrepancy_status:
                                    type: string
                                  discrepancy_resolved_at:
                                    type: string
                                    nullable: true
                                  resolution_note:
                                    type: string
                                    nullable: true
                                  product:
                                    type: object
                                    properties:
                                      id:
                                        type: integer
                                      sku:
                                        type: string
                                      name:
                                        type: string
                                      image_url:
                                        type: string
                example:
                  data:
                    shipments:
                    - id: 15
                      name: Shipment 1 of 2
                      shipment_confirmation_id: FBA15K7Z9QXM
                      amazon_status: CLOSED
                      claim_deadline: '2026-07-03'
                      claim_days_remaining: 21
                      items:
                      - id: 61
                        msku: WIDGET-BLUE-L
                        fnsku: X001ABC123
                        quantity_shipped: 40
                        quantity_received: 36
                        discrepancy: -4
                        discrepancy_status: SHORT
                        discrepancy_resolved_at: null
                        resolution_note: null
                        product:
                          id: 412
                          sku: WIDGET-BLUE-L
                          name: Widget - Blue, Large
                          image_url: https://cdn.sku.io/products/412/primary.jpg
                      - id: 62
                        msku: WIDGET-RED-S
                        fnsku: X001DEF456
                        quantity_shipped: 12
                        quantity_received: 12
                        discrepancy: 0
                        discrepancy_status: MATCH
                        discrepancy_resolved_at: null
                        resolution_note: null
                        product:
                          id: 413
                          sku: WIDGET-RED-S
                          name: Widget - Red, Small
                          image_url: https://cdn.sku.io/products/413/primary.jpg
                    - id: 16
                      name: Shipment 2 of 2
                      shipment_confirmation_id: FBA15K8A2RLN
                      amazon_status: RECEIVING
                      claim_deadline: '2026-07-31'
                      claim_days_remaining: 49
                      items:
                      - id: 63
                        msku: GADGET-GRN-M
                        fnsku: X001GHI789
                        quantity_shipped: 60
                        quantity_received: 25
                        discrepancy: -35
                        discrepancy_status: PENDING
                        discrepancy_resolved_at: null
                        resolution_note: null
                        product:
                          id: 418
                          sku: GADGET-GRN-M
                          name: Gadget - Green, Medium
                          image_url: https://cdn.sku.io/products/418/primary.jpg
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-integrationinstance-draft-inbound-plans-draft-inbound-plan-tracking-reconciliation
  /api/amazon/{integrationInstance}/draft-inbound-plans/{draft_inbound_plan}/tracking/items/{shipment_item}/resolve:
    post:
      tags:
      - Amazon
      summary: Resolve Discrepancy Item
      description: 'Acknowledge (resolve) a shipment item''s discrepancy with a note
        — e.g. after filing an Amazon reimbursement case for a SHORT item. Resolution
        is an overlay: it stamps `discrepancy_resolved_at` and `resolution_note` but
        leaves `discrepancy_status` untouched. Resolved items drop out of the tenant-level
        discrepancies report (unless `filter[resolved]=1`). Reversible via **Unresolve
        Discrepancy Item**.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Resolvable statuses: `SHORT`, `OVER`, and `PENDING`. Items with no discrepancy
        (`MATCH` or null status) return a 422.


        **Fields:**

        - `resolution_note` (string, **required**, max 1000) — why/how the discrepancy
        was handled


        **Response:** the updated reconciliation item payload (same shape as the **Get
        Reconciliation** items).


        **Errors:**

        - 404 — the shipment item does not belong to this draft inbound plan

        - 422 — the item has no discrepancy to resolve (status `MATCH` or null)

        - 422 — `resolution_note` missing or longer than 1000 characters


        **Authentication:** Bearer token (PAT).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                resolution_note:
                  type: string
              example:
                resolution_note: Filed reimbursement case 12345-67890 with Amazon
                  for the 4 missing units.
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: draft_inbound_plan
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The draft inbound plan ID.
      - name: shipment_item
        in: path
        schema:
          type: integer
        required: true
        example: '61'
        description: The shipment item ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      msku:
                        type: string
                      fnsku:
                        type: string
                      quantity_shipped:
                        type: integer
                      quantity_received:
                        type: integer
                      discrepancy:
                        type: integer
                      discrepancy_status:
                        type: string
                      discrepancy_resolved_at:
                        type: string
                      resolution_note:
                        type: string
                      product:
                        type: object
                        properties:
                          id:
                            type: integer
                          sku:
                            type: string
                          name:
                            type: string
                          image_url:
                            type: string
                example:
                  data:
                    id: 61
                    msku: WIDGET-BLUE-L
                    fnsku: X001ABC123
                    quantity_shipped: 40
                    quantity_received: 36
                    discrepancy: -4
                    discrepancy_status: SHORT
                    discrepancy_resolved_at: '2026-06-12T15:21:09.000000Z'
                    resolution_note: Filed reimbursement case 12345-67890 with Amazon
                      for the 4 missing units.
                    product:
                      id: 412
                      sku: WIDGET-BLUE-L
                      name: Widget - Blue, Large
                      image_url: https://cdn.sku.io/products/412/primary.jpg
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 422 No Discrepancy
                  value:
                    message: This item has no discrepancy to resolve.
                    errors:
                      shipment_item:
                      - This item has no discrepancy to resolve.
                example-1:
                  summary: 422 Validation Error
                  value:
                    message: The resolution note field is required.
                    errors:
                      resolution_note:
                      - The resolution note field is required.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-amazon-integrationinstance-draft-inbound-plans-draft-inbound-plan-tracking-items-shipment-item-resolve
  /api/amazon/{integrationInstance}/draft-inbound-plans/{draft_inbound_plan}/tracking/items/{shipment_item}/unresolve:
    post:
      tags:
      - Amazon
      summary: Unresolve Discrepancy Item
      description: 'Clear a shipment item''s discrepancy resolution — nulls `discrepancy_resolved_at`
        and `resolution_note`, returning the item to the unresolved pool (it reappears
        in the tenant-level discrepancies report). `discrepancy_status` is untouched.
        No request body.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Response:** the updated reconciliation item payload (same shape as the **Get
        Reconciliation** items).


        **Errors:**

        - 404 — the shipment item does not belong to this draft inbound plan


        **Authentication:** Bearer token (PAT).'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: draft_inbound_plan
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The draft inbound plan ID.
      - name: shipment_item
        in: path
        schema:
          type: integer
        required: true
        example: '61'
        description: The shipment item ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      msku:
                        type: string
                      fnsku:
                        type: string
                      quantity_shipped:
                        type: integer
                      quantity_received:
                        type: integer
                      discrepancy:
                        type: integer
                      discrepancy_status:
                        type: string
                      discrepancy_resolved_at:
                        type: string
                        nullable: true
                      resolution_note:
                        type: string
                        nullable: true
                      product:
                        type: object
                        properties:
                          id:
                            type: integer
                          sku:
                            type: string
                          name:
                            type: string
                          image_url:
                            type: string
                example:
                  data:
                    id: 61
                    msku: WIDGET-BLUE-L
                    fnsku: X001ABC123
                    quantity_shipped: 40
                    quantity_received: 36
                    discrepancy: -4
                    discrepancy_status: SHORT
                    discrepancy_resolved_at: null
                    resolution_note: null
                    product:
                      id: 412
                      sku: WIDGET-BLUE-L
                      name: Widget - Blue, Large
                      image_url: https://cdn.sku.io/products/412/primary.jpg
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-amazon-integrationinstance-draft-inbound-plans-draft-inbound-plan-tracking-items-shipment-item-unresolve
  /api/amazon/{integrationInstance}/draft-inbound-plans/{draft_inbound_plan}/shipments/{plan_shipment}/refresh:
    post:
      tags:
      - Amazon
      summary: Refresh Shipment
      description: 'Synchronous on-demand refresh of one shipment from Amazon (the
        board''s refresh button): runs SP-API `getShipment` (status + tracking) and
        `listShipmentItems` (shipped/received quantities), then recomputes the per-item
        discrepancy statuses. Returns the shipment''s updated board entry. No request
        body.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Received quantities are only updated when Amazon includes a received-quantity
        key — absent keys never zero out previously synced values. The same refresh
        also runs hourly for all non-terminal shipments via the scheduled `amazon:fba-inbound:sync-shipments`
        sweep (terminal Amazon statuses: `CLOSED`, `CANCELLED`, `DELETED`).


        **Response:** the updated shipment in **Get Shipment Board** entry shape (standard
        plan-shipment payload + `days_since_shipped`, `units_shipped`, `units_received`,
        `boxes_count`, `claim_deadline`, `claim_days_remaining`, `reconciliation_status`).


        **Errors:**

        - 404 — the shipment does not belong to this draft inbound plan

        - 422 — Amazon rejected the request (SP-API client-error messages are parsed
        and surfaced per field)


        **Authentication:** Bearer token (PAT).'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: draft_inbound_plan
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The draft inbound plan ID.
      - name: plan_shipment
        in: path
        schema:
          type: integer
        required: true
        example: '15'
        description: The plan shipment ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      amazon_shipment_id:
                        type: string
                      shipment_confirmation_id:
                        type: string
                      name:
                        type: string
                      destination_fc:
                        type: string
                      destination_address:
                        type: object
                        properties:
                          name:
                            type: string
                          addressLine1:
                            type: string
                          city:
                            type: string
                          stateOrProvinceCode:
                            type: string
                          postalCode:
                            type: string
                          countryCode:
                            type: string
                      amazon_status:
                        type: string
                      local_status:
                        type: string
                      tracking_summary:
                        type: string
                        nullable: true
                      freight_bill_numbers:
                        type: string
                        nullable: true
                      delivery_window_option_id:
                        type: string
                        nullable: true
                      confirmed_delivery_window:
                        type: string
                        nullable: true
                      shipped_at:
                        type: string
                      items:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            msku:
                              type: string
                            fnsku:
                              type: string
                            quantity_shipped:
                              type: integer
                            quantity_received:
                              type: integer
                      days_since_shipped:
                        type: integer
                      units_shipped:
                        type: integer
                      units_received:
                        type: integer
                      boxes_count:
                        type: integer
                      claim_deadline:
                        type: string
                      claim_days_remaining:
                        type: integer
                      reconciliation_status:
                        type: string
                example:
                  data:
                    id: 15
                    amazon_shipment_id: sh-0a1b2c3d-4e5f-6789-abcd-ef0123456789
                    shipment_confirmation_id: FBA15K7Z9QXM
                    name: Shipment 1 of 2
                    destination_fc: TEB9
                    destination_address:
                      name: Amazon.com Services LLC (TEB9)
                      addressLine1: 2170 State Route 27
                      city: Edison
                      stateOrProvinceCode: NJ
                      postalCode: 08817
                      countryCode: US
                    amazon_status: CLOSED
                    local_status: shipped
                    tracking_summary: null
                    freight_bill_numbers: null
                    delivery_window_option_id: null
                    confirmed_delivery_window: null
                    shipped_at: '2026-05-04T00:00:00.000000Z'
                    items:
                    - id: 61
                      msku: WIDGET-BLUE-L
                      fnsku: X001ABC123
                      quantity_shipped: 40
                      quantity_received: 36
                    - id: 62
                      msku: WIDGET-RED-S
                      fnsku: X001DEF456
                      quantity_shipped: 12
                      quantity_received: 12
                    days_since_shipped: 39
                    units_shipped: 52
                    units_received: 48
                    boxes_count: 6
                    claim_deadline: '2026-07-03'
                    claim_days_remaining: 21
                    reconciliation_status: short
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      amazon:
                        type: array
                        items:
                          type: string
                example:
                  message: Shipment sh-0a1b2c3d-4e5f-6789-abcd-ef0123456789 not found
                    for inbound plan.
                  errors:
                    amazon:
                    - Shipment sh-0a1b2c3d-4e5f-6789-abcd-ef0123456789 not found for
                      inbound plan.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-amazon-integrationinstance-draft-inbound-plans-draft-inbound-plan-shipments-plan-shipment-refresh
  ? /api/amazon/{integrationInstance}/draft-inbound-plans/{draft_inbound_plan}/shipments/{plan_shipment}/content-updates/generate
  : post:
      tags:
      - Amazon
      summary: Generate Content Update Previews
      description: "Start generating content update previews (\"Adjust shipment\"\
        ) for a shipped shipment via the async SP-API `generateShipmentContentUpdatePreviews`\
        \ operation — used to correct box contents / item quantities after the fact.\
        \ Dispatches the tracked job **\"Generate FBA Content Update Previews: {plan\
        \ name}\"** and returns its `tracked_job_log_id` for the tracked job log endpoints;\
        \ once the job completes, fetch the previews via **List Content Update Previews**\
        \ and apply one via **Confirm Content Update Preview**.\n\n:::info[Authorization]\n\
        Any valid API token can call this endpoint — no specific scope required. [Manage\
        \ tokens](https://app.sku.io/settings/api).\n:::\n\nBoxes and items are passed\
        \ through to Amazon in SP-API shape — only the load-bearing keys are validated\
        \ locally; everything else is validated by Amazon (failures surface on the\
        \ tracked job).\n\n**Fields:**\n- `boxes` (array, **required**, min 1) — the\
        \ full updated box list in SP-API shape: `contentInformationSource`, `dimensions`\
        \ (length/width/height/unitOfMeasurement), `weight` (value/unit), `quantity`,\
        \ and `items` (msku/quantity/labelOwner/prepOwner, optional expiration)\n\
        - `items` (array, **required**, min 1) — the updated shipment item totals:\n\
        \  - `items.*.msku` (string, **required**, max 255)\n  - `items.*.quantity`\
        \ (integer, **required**, min 0) — the new total shipped quantity for the\
        \ MSKU\n  - `items.*.labelOwner` / `items.*.prepOwner` / `items.*.expiration`\
        \ — passed through to Amazon when provided\n\n**Errors:**\n- 404 — the shipment\
        \ does not belong to this draft inbound plan\n- 422 — validation failure (`boxes`/`items`\
        \ missing or empty, item rows missing `msku`/`quantity`)\n\n**Authentication:**\
        \ Bearer token (PAT)."
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                boxes:
                  type: array
                  items:
                    type: object
                    properties:
                      contentInformationSource:
                        type: string
                      dimensions:
                        type: object
                        properties:
                          length:
                            type: integer
                          width:
                            type: integer
                          height:
                            type: integer
                          unitOfMeasurement:
                            type: string
                      weight:
                        type: object
                        properties:
                          value:
                            type: number
                          unit:
                            type: string
                      quantity:
                        type: integer
                      items:
                        type: array
                        items:
                          type: object
                          properties:
                            msku:
                              type: string
                            quantity:
                              type: integer
                            labelOwner:
                              type: string
                            prepOwner:
                              type: string
                items:
                  type: array
                  items:
                    type: object
                    properties:
                      msku:
                        type: string
                      quantity:
                        type: integer
                      labelOwner:
                        type: string
                      prepOwner:
                        type: string
              example:
                boxes:
                - contentInformationSource: BOX_CONTENT_PROVIDED
                  dimensions:
                    length: 18
                    width: 14
                    height: 12
                    unitOfMeasurement: IN
                  weight:
                    value: 28.5
                    unit: LB
                  quantity: 1
                  items:
                  - msku: WIDGET-BLUE-L
                    quantity: 36
                    labelOwner: SELLER
                    prepOwner: SELLER
                  - msku: WIDGET-RED-S
                    quantity: 12
                    labelOwner: SELLER
                    prepOwner: SELLER
                items:
                - msku: WIDGET-BLUE-L
                  quantity: 36
                  labelOwner: SELLER
                  prepOwner: SELLER
                - msku: WIDGET-RED-S
                  quantity: 12
                  labelOwner: SELLER
                  prepOwner: SELLER
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: draft_inbound_plan
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The draft inbound plan ID.
      - name: plan_shipment
        in: path
        schema:
          type: integer
        required: true
        example: '15'
        description: The plan shipment ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 412
                  message: Content update preview generation started
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      items.0.quantity:
                        type: array
                        items:
                          type: string
                example:
                  message: The items.0.quantity field is required.
                  errors:
                    items.0.quantity:
                    - The items.0.quantity field is required.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-amazon-integrationinstance-draft-inbound-plans-draft-inbound-plan-shipments-plan-shipment-content-updates-generate
  /api/amazon/{integrationInstance}/draft-inbound-plans/{draft_inbound_plan}/shipments/{plan_shipment}/content-updates:
    get:
      tags:
      - Amazon
      summary: List Content Update Previews
      description: 'Synchronous raw passthrough of Amazon''s content update previews
        for a shipment (SP-API `listShipmentContentUpdatePreviews`, all pages merged
        — no local mirror tables). Each preview is Amazon''s native payload: `contentUpdatePreviewId`
        (use with **Confirm Content Update Preview**), `expiration`, `requestedUpdates`
        (the boxes/items you submitted), and `transportationOption` (the re-quoted
        transportation for the updated contents).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Errors:**

        - 404 — the shipment does not belong to this draft inbound plan

        - 422 — Amazon rejected the request (SP-API client-error messages are parsed
        and surfaced per field)


        **Authentication:** Bearer token (PAT).'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: draft_inbound_plan
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The draft inbound plan ID.
      - name: plan_shipment
        in: path
        schema:
          type: integer
        required: true
        example: '15'
        description: The plan shipment ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      previews:
                        type: array
                        items:
                          type: object
                          properties:
                            contentUpdatePreviewId:
                              type: string
                            expiration:
                              type: string
                            requestedUpdates:
                              type: object
                              properties:
                                boxes:
                                  type: array
                                  items:
                                    type: object
                                    properties:
                                      boxId:
                                        type: string
                                      contentInformationSource:
                                        type: string
                                      dimensions:
                                        type: object
                                        properties:
                                          length:
                                            type: integer
                                          width:
                                            type: integer
                                          height:
                                            type: integer
                                          unitOfMeasurement:
                                            type: string
                                      weight:
                                        type: object
                                        properties:
                                          value:
                                            type: number
                                          unit:
                                            type: string
                                      quantity:
                                        type: integer
                                      items:
                                        type: array
                                        items:
                                          type: object
                                          properties:
                                            msku:
                                              type: string
                                            quantity:
                                              type: integer
                                            labelOwner:
                                              type: string
                                            prepOwner:
                                              type: string
                                items:
                                  type: array
                                  items:
                                    type: object
                                    properties:
                                      msku:
                                        type: string
                                      quantity:
                                        type: integer
                                      labelOwner:
                                        type: string
                                      prepOwner:
                                        type: string
                            transportationOption:
                              type: object
                              properties:
                                transportationOptionId:
                                  type: string
                                program:
                                  type: string
                                shippingMode:
                                  type: string
                                carrier:
                                  type: object
                                  properties:
                                    alphaCode:
                                      type: string
                                    name:
                                      type: string
                                quote:
                                  type: object
                                  properties:
                                    cost:
                                      type: object
                                      properties:
                                        amount:
                                          type: number
                                        code:
                                          type: string
                                    expiration:
                                      type: string
                example:
                  data:
                    previews:
                    - contentUpdatePreviewId: cu-6f7a8b9c-0d1e-2345-f678-901234567890
                      expiration: '2026-06-13T18:00:00Z'
                      requestedUpdates:
                        boxes:
                        - boxId: FBA15K7Z9QXM000001
                          contentInformationSource: BOX_CONTENT_PROVIDED
                          dimensions:
                            length: 18
                            width: 14
                            height: 12
                            unitOfMeasurement: IN
                          weight:
                            value: 28.5
                            unit: LB
                          quantity: 1
                          items:
                          - msku: WIDGET-BLUE-L
                            quantity: 36
                            labelOwner: SELLER
                            prepOwner: SELLER
                        items:
                        - msku: WIDGET-BLUE-L
                          quantity: 36
                          labelOwner: SELLER
                          prepOwner: SELLER
                      transportationOption:
                        transportationOptionId: to-7a8b9c0d-1e2f-3456-7890-123456789012
                        program: AMAZON_PARTNERED_CARRIER
                        shippingMode: GROUND_SMALL_PARCEL
                        carrier:
                          alphaCode: UPSN
                          name: United Parcel Service Inc.
                        quote:
                          cost:
                            amount: 9.84
                            code: USD
                          expiration: '2026-06-13T18:00:00Z'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      amazon:
                        type: array
                        items:
                          type: string
                example:
                  message: Content updates are not available for shipment sh-0a1b2c3d-4e5f-6789-abcd-ef0123456789.
                  errors:
                    amazon:
                    - Content updates are not available for shipment sh-0a1b2c3d-4e5f-6789-abcd-ef0123456789.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-integrationinstance-draft-inbound-plans-draft-inbound-plan-shipments-plan-shipment-content-updates
  ? /api/amazon/{integrationInstance}/draft-inbound-plans/{draft_inbound_plan}/shipments/{plan_shipment}/content-updates/{contentUpdatePreviewId}/confirm
  : post:
      tags:
      - Amazon
      summary: Confirm Content Update Preview
      description: 'Apply a previously generated content update preview via the async
        SP-API `confirmShipmentContentUpdatePreview` operation. Dispatches the tracked
        job **"Confirm FBA Content Update: {plan name}"** and returns its `tracked_job_log_id`
        for the tracked job log endpoints. No request body — the preview id comes
        from **List Content Update Previews** (`contentUpdatePreviewId`).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        The job only starts the async Amazon operation; the tracked job log is completed
        (or failed) by the operation poller once Amazon reaches a terminal state.
        On SUCCESS the shipment items are re-synced from Amazon first, so `quantity_shipped`
        reflects the accepted deltas, and discrepancy statuses are recomputed.


        **Errors:**

        - 404 — the shipment does not belong to this draft inbound plan

        - (async) an invalid/expired preview id fails on the tracked job, not the
        HTTP response


        **Authentication:** Bearer token (PAT).'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: draft_inbound_plan
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The draft inbound plan ID.
      - name: plan_shipment
        in: path
        schema:
          type: integer
        required: true
        example: '15'
        description: The plan shipment ID.
      - name: contentUpdatePreviewId
        in: path
        schema:
          type: string
        required: true
        example: cu-6f7a8b9c-0d1e-2345-f678-901234567890
        description: The content update preview ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 413
                  message: Content update confirmation started
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-amazon-integrationinstance-draft-inbound-plans-draft-inbound-plan-shipments-plan-shipment-content-updates-contentupdatepreviewid-confirm
  /api/amazon/{integrationInstance}/fba-inbound/discrepancies:
    get:
      tags:
      - Amazon
      summary: List Inbound Discrepancies (Tenant-Level)
      description: 'Tenant-level FBA inbound discrepancies report — note the URL:
        this endpoint lives at `/api/amazon/{integrationInstance}/fba-inbound/discrepancies`,
        OUTSIDE the per-plan `draft-inbound-plans/{draft_inbound_plan}` group, because
        it aggregates across ALL of the instance''s inbound plans.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Returns every `SHORT`/`OVER` shipment item across the instance''s plans (unresolved
        only by default), ordered by `claim_days_remaining` ascending — the most urgent
        reimbursement claim windows first; shipments without a ship date sort last.
        `PENDING`/`MATCH` items are never included.


        **Query parameters:**

        - `filter[resolved]` (boolean, optional) — `1`/`true` also includes resolved
        (acknowledged) items. Default: unresolved only


        **Row fields:**

        - `plan_id` / `plan_name` — the draft inbound plan

        - `shipment_id` / `shipment_name` / `shipment_confirmation_id` — the shipment
        (e.g. `FBA15K7Z9QXM`)

        - `claim_deadline` (date|null) — `shipped_at` + 60 days (Amazon reimbursement
        claim window)

        - `claim_days_remaining` (integer|null) — whole days until the deadline (negative
        once lapsed); null when the shipment has no ship date

        - `approaching_deadline` (boolean) — true when `claim_days_remaining` is ≤
        14 (time to file a claim)

        - `item` — `msku`, `fnsku`, `quantity_shipped`, `quantity_received`, `discrepancy`
        (received - shipped), `discrepancy_status` (`SHORT` or `OVER`), `discrepancy_resolved_at`,
        `resolution_note`


        **Authentication:** Bearer token (PAT).'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        plan_id:
                          type: integer
                        plan_name:
                          type: string
                        shipment_id:
                          type: integer
                        shipment_name:
                          type: string
                        shipment_confirmation_id:
                          type: string
                        claim_deadline:
                          type: string
                        claim_days_remaining:
                          type: integer
                        approaching_deadline:
                          type: boolean
                        item:
                          type: object
                          properties:
                            msku:
                              type: string
                            fnsku:
                              type: string
                            quantity_shipped:
                              type: integer
                            quantity_received:
                              type: integer
                            discrepancy:
                              type: integer
                            discrepancy_status:
                              type: string
                            discrepancy_resolved_at:
                              type: string
                              nullable: true
                            resolution_note:
                              type: string
                              nullable: true
                example:
                  data:
                  - plan_id: 7
                    plan_name: June Replenishment - East
                    shipment_id: 12
                    shipment_name: Shipment 1 of 1
                    shipment_confirmation_id: FBA15K5T3PWB
                    claim_deadline: '2026-06-20'
                    claim_days_remaining: 8
                    approaching_deadline: true
                    item:
                      msku: GIZMO-BLK-XL
                      fnsku: X001JKL012
                      quantity_shipped: 100
                      quantity_received: 88
                      discrepancy: -12
                      discrepancy_status: SHORT
                      discrepancy_resolved_at: null
                      resolution_note: null
                  - plan_id: 9
                    plan_name: May Replenishment - West
                    shipment_id: 15
                    shipment_name: Shipment 1 of 2
                    shipment_confirmation_id: FBA15K7Z9QXM
                    claim_deadline: '2026-07-03'
                    claim_days_remaining: 21
                    approaching_deadline: false
                    item:
                      msku: WIDGET-BLUE-L
                      fnsku: X001ABC123
                      quantity_shipped: 40
                      quantity_received: 36
                      discrepancy: -4
                      discrepancy_status: SHORT
                      discrepancy_resolved_at: null
                      resolution_note: null
                  - plan_id: 9
                    plan_name: May Replenishment - West
                    shipment_id: 16
                    shipment_name: Shipment 2 of 2
                    shipment_confirmation_id: FBA15K8A2RLN
                    claim_deadline: '2026-07-31'
                    claim_days_remaining: 49
                    approaching_deadline: false
                    item:
                      msku: GADGET-GRN-M
                      fnsku: X001GHI789
                      quantity_shipped: 60
                      quantity_received: 63
                      discrepancy: 3
                      discrepancy_status: OVER
                      discrepancy_resolved_at: null
                      resolution_note: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-integrationinstance-fba-inbound-discrepancies
  /api/amazon/{integrationInstance}/draft-inbound-plans/{draft_inbound_plan}/refresh-amazon-plan:
    post:
      tags:
      - Amazon
      summary: Refresh from Amazon
      description: 'Refresh a submitted plan from Amazon. Pulls the latest plan +
        shipment state from Amazon''s Fulfillment Inbound API (`getInboundPlan`, `getShipment`,
        `listShipmentItems`) and mirrors it onto the linked `AmazonNewFbaInboundPlan`
        (status, shipments, accepted items). Use this to reconcile the in-app plan
        with Seller Central after submission.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Returns the updated draft Amazon FBA inbound plan object with the refreshed
        `amazon_new_fba_inbound_plan` relationship loaded.'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: draft_inbound_plan
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The draft inbound plan ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      portal_access_hash:
                        type: string
                      integration_instance_id:
                        type: integer
                      warehouse_id:
                        type: integer
                      warehouse_country_code:
                        type: string
                      name:
                        type: string
                      status:
                        type: string
                      workflow_step:
                        type: integer
                      source_mode:
                        type: string
                      source_warehouse_id:
                        type: integer
                      source_warehouse_name:
                        type: string
                      source_type:
                        type: string
                      source_supplier_name:
                        type: string
                        nullable: true
                      warehouse_type:
                        type: string
                      warehouse_transfer_id:
                        type: integer
                      amazon_new_fba_inbound_plan:
                        type: object
                        properties:
                          id:
                            type: integer
                          inboundPlanId:
                            type: string
                          status:
                            type: string
                          items_fetched:
                            type: boolean
                          sent_count:
                            type: integer
                          accepted_count:
                            type: integer
                          excluded_items:
                            type: array
                          shipments:
                            type: array
                            items:
                              type: object
                              properties:
                                id:
                                  type: integer
                                shipmentConfirmationId:
                                  type: string
                                sku_link_type:
                                  type: string
                                sku_link_id:
                                  type: integer
                      items:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            product_id:
                              type: integer
                            msku:
                              type: string
                            quantity:
                              type: integer
                      inventory_inquiry_last_processed_at:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 1
                    portal_access_hash: eyJpdiI6Ii4uLiI...
                    integration_instance_id: 1
                    warehouse_id: 5
                    warehouse_country_code: US
                    name: Q2 Restock
                    status: submitted_to_amazon
                    workflow_step: 7
                    source_mode: warehouse_transfer
                    source_warehouse_id: 8
                    source_warehouse_name: Main Warehouse
                    source_type: warehouse
                    source_supplier_name: null
                    warehouse_type: standard
                    warehouse_transfer_id: 17
                    amazon_new_fba_inbound_plan:
                      id: 33
                      inboundPlanId: wf52bdb8a9-d197-4d95-9f60-07d2293b587d
                      status: ACTIVE
                      items_fetched: true
                      sent_count: 2
                      accepted_count: 2
                      excluded_items: []
                      shipments:
                      - id: 91
                        shipmentConfirmationId: FBA15ABCDEFG
                        sku_link_type: warehouse_transfer
                        sku_link_id: 17
                    items:
                    - id: 501
                      product_id: 42
                      msku: SKU-1
                      quantity: 30
                    - id: 502
                      product_id: 77
                      msku: SKU-2
                      quantity: 20
                    inventory_inquiry_last_processed_at: null
                    created_at: '2026-06-10T22:00:00.000000Z'
                    updated_at: '2026-06-14T10:05:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-amazon-integrationinstance-draft-inbound-plans-draft-inbound-plan-refresh-amazon-plan
  /api/amazon/{integrationInstance}/new-inbound/plans/list:
    get:
      tags:
      - Amazon
      summary: List Inbound Plans (Tab)
      description: 'Paginated listing for the FBA Inbound "Inbound Plans" tab. Mirrors
        each plan''s Amazon status (ACTIVE / SHIPPED / VOIDED / ERRORED) and INCLUDES
        orphan ("Unlinked") plans that have no linked SKU draft.


        Requires a Bearer token.


        Each row exposes `source_type` ("warehouse" | "supplier" | null) and `source_id`
        so the UI can deep-link the source to its detail page, plus `draft_id` for
        linked plans (deep-link into the in-app workflow). The response also carries
        `status_counts` (per-Amazon-status totals powering the metric cards) and `unfiltered_total`
        (the tab''s total ignoring filters). Linked rows also expose `created_by_user_id`
        / `created_by` — the user who created the draft in-app (null for unlinked
        / Seller Central plans and drafts that predate creator tracking).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        inboundPlanId:
                          type: string
                        name:
                          type: string
                        status:
                          type: string
                        status_label:
                          type: string
                        sourceName:
                          type: string
                        sourceCountry:
                          type: string
                        source_type:
                          type: string
                        source_id:
                          type: integer
                        is_awd:
                          type: boolean
                        shipment_count:
                          type: integer
                        is_unlinked:
                          type: boolean
                        draft_id:
                          type: integer
                        draft_status:
                          type: string
                        draft_status_label:
                          type: string
                        created_by_user_id:
                          type: integer
                        created_by:
                          type: string
                        lastUpdatedAt:
                          type: string
                        createdAt:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  links:
                    type: object
                    properties:
                      first:
                        type: string
                      last:
                        type: string
                      prev:
                        type: string
                        nullable: true
                      next:
                        type: string
                        nullable: true
                  meta:
                    type: object
                    properties:
                      current_page:
                        type: integer
                      from:
                        type: integer
                      last_page:
                        type: integer
                      per_page:
                        type: integer
                      to:
                        type: integer
                      total:
                        type: integer
                  unfiltered_total:
                    type: integer
                  status_counts:
                    type: object
                    properties:
                      total:
                        type: integer
                      ACTIVE:
                        type: integer
                      SHIPPED:
                        type: integer
                      VOIDED:
                        type: integer
                      ERRORED:
                        type: integer
                example:
                  data:
                  - id: 412
                    inboundPlanId: wf1a2b3c4d
                    name: Q1 Restock - West
                    status: ACTIVE
                    status_label: Active
                    sourceName: Main Warehouse
                    sourceCountry: US
                    source_type: warehouse
                    source_id: 4
                    is_awd: false
                    shipment_count: 2
                    is_unlinked: false
                    draft_id: 65
                    draft_status: submitted_to_amazon
                    draft_status_label: Submitted To Amazon
                    created_by_user_id: 7
                    created_by: Jane Smith
                    lastUpdatedAt: '2026-06-14T18:22:00Z'
                    createdAt: '2026-06-10T12:00:00Z'
                    created_at: '2026-06-10T12:00:00.000000Z'
                    updated_at: '2026-06-14T18:22:00.000000Z'
                  - id: 388
                    inboundPlanId: wf9z8y7x6w
                    name: Seller Central Plan
                    status: VOIDED
                    status_label: Voided
                    sourceName: null
                    sourceCountry: US
                    source_type: null
                    source_id: null
                    is_awd: false
                    shipment_count: 1
                    is_unlinked: true
                    draft_id: null
                    draft_status: null
                    draft_status_label: null
                    created_by_user_id: null
                    created_by: null
                    lastUpdatedAt: '2026-05-30T09:10:00Z'
                    createdAt: '2026-05-28T08:00:00Z'
                    created_at: '2026-05-28T08:00:00.000000Z'
                    updated_at: '2026-05-30T09:10:00.000000Z'
                  links:
                    first: '...'
                    last: '...'
                    prev: null
                    next: null
                  meta:
                    current_page: 1
                    from: 1
                    last_page: 1
                    per_page: 15
                    to: 2
                    total: 2
                  unfiltered_total: 96
                  status_counts:
                    total: 96
                    ACTIVE: 64
                    SHIPPED: 6
                    VOIDED: 24
                    ERRORED: 2
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-integrationinstance-new-inbound-plans-list
  /api/amazon/{integrationInstance}/new-inbound/plans/bulk-void:
    post:
      tags:
      - Amazon
      summary: Bulk Void Inbound Plans
      description: 'Bulk-void selected inbound plans on Amazon — cleanup of stale
        plans from the "Inbound Plans" tab. Dispatches a tracked background job (follow
        it via the tracked job log endpoints) and returns its `tracked_job_log_id`.


        Requires a Bearer token.


        Voiding mirrors Amazon''s status to VOIDED. Linked plans also have their in-app
        draft aborted and any reserved warehouse transfer released back to stock;
        orphan (unlinked) plans are voided directly. Plans already VOIDED are skipped,
        and plans Amazon refuses to void (already shipped/closed) are captured as
        per-plan failures without aborting the batch.


        Body: `ids` — array of AmazonNewFbaInboundPlan primary keys (the `id` field
        from the list endpoint). Required, 1-1000 integers.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 412
                - 388
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 9123
                  message: Voiding 2 plan(s) — track progress in the job tray.
        '422':
          description: Unprocessable Content
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      ids:
                        type: array
                        items:
                          type: string
                example:
                  message: The ids field is required.
                  errors:
                    ids:
                    - The ids field is required.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-amazon-integrationinstance-new-inbound-plans-bulk-void
  /api/amazon/{integrationInstance}/draft-inbound-plans/refresh-from-amazon:
    post:
      tags:
      - Amazon
      summary: Refresh Inbound Plans From Amazon
      description: 'Refresh the "Inbound Plans" tab from Amazon. Dispatches a tracked
        background job (follow it via the tracked job log endpoints) and returns its
        tracked_job_log_id.


        Requires a Bearer token.


        Body (all optional; defaults to a full re-sync):

        - mode: all | since_latest | from_start_date | date_range

        - latest_date: lower bound for since_latest (ISO 8601 / date)

        - date_from: lower bound for from_start_date and date_range (Y-m-d)

        - date_to: upper bound for date_range (Y-m-d)


        Bounds are applied against each plan''s lastUpdatedAt; Amazon''s list is paged
        sorted by LAST_UPDATED_TIME DESC and stops once it passes the lower bound.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                mode:
                  type: string
                date_from:
                  type: string
                date_to:
                  type: string
              example:
                mode: date_range
                date_from: '2026-01-01'
                date_to: '2026-02-01'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 9123
                  message: Refresh started — track progress in the job tray.
        '422':
          description: Unprocessable Content
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      mode:
                        type: array
                        items:
                          type: string
                example:
                  message: The selected mode is invalid.
                  errors:
                    mode:
                    - The selected mode is invalid.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-amazon-integrationinstance-draft-inbound-plans-refresh-from-amazon
  /api/amazon/{integrationInstance}/draft-inbound-plans/sync-info:
    get:
      tags:
      - Amazon
      summary: Inbound Plan Sync Info
      description: 'Sync-info for the Refresh Inbound Plans modal header and "Fetch
        Since Latest" mode: the most recently updated plan already synced locally
        plus the total count.


        Requires a Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      latestIdentifier:
                        type: string
                      latestDate:
                        type: string
                      totalCount:
                        type: integer
                example:
                  data:
                    latestIdentifier: Q1 Restock - West
                    latestDate: '2026-03-01T00:00:00Z'
                    totalCount: 96
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-integrationinstance-draft-inbound-plans-sync-info
  /api/amazon/{integrationInstance}/draft-inbound-plans/search:
    get:
      tags:
      - Amazon
      summary: Search Inbound Plans
      description: 'Search a single inbound plan on Amazon by its inbound plan id
        (the modal''s "Search Specific Inbound" tab). Amazon''s list API has no id
        search, so this fetches the plan directly — which also imports/refreshes it
        — and returns an array with 0 or 1 OrderSearchResult-shaped row.


        Requires a Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: query
        in: query
        schema:
          type: string
        description: The Amazon inbound plan id to look up (required)
        example: wf1a2b3c4d
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: string
                        name:
                          type: string
                        email:
                          type: string
                          nullable: true
                        createdAt:
                          type: string
                        financialStatus:
                          type: string
                          nullable: true
                        fulfillmentStatus:
                          type: string
                        totalPrice:
                          type: string
                          nullable: true
                        currency:
                          type: string
                          nullable: true
                        existsInDatabase:
                          type: boolean
                example:
                  data:
                  - id: wf1a2b3c4d
                    name: Q1 Restock - West
                    email: null
                    createdAt: '2026-06-10T12:00:00Z'
                    financialStatus: null
                    fulfillmentStatus: ACTIVE
                    totalPrice: null
                    currency: null
                    existsInDatabase: true
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-integrationinstance-draft-inbound-plans-search
  /api/amazon/{integrationInstance}/draft-inbound-plans/refresh-single:
    post:
      tags:
      - Amazon
      summary: Refresh Single Inbound Plan
      description: 'Download / refresh a single inbound plan from Amazon by its inbound
        plan id — the per-row action in the modal''s search results.


        Requires a Bearer token.


        Body: uniqueId — the Amazon inbound plan id (required).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                uniqueId:
                  type: string
              example:
                uniqueId: wf1a2b3c4d
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Inbound plan refreshed.
        '422':
          description: Unprocessable Content
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      uniqueId:
                        type: array
                        items:
                          type: string
                example:
                  message: The unique id field is required.
                  errors:
                    uniqueId:
                    - The unique id field is required.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-amazon-integrationinstance-draft-inbound-plans-refresh-single
  /api/amazon/{integrationInstance}/draft-inbound-plans/portal/{hashedDraftInboundPlanId}:
    get:
      tags:
      - Amazon
      summary: Get Portal Data
      description: 'Plan header + line items for the external verification portal.
        No bearer token — access is granted by the encrypted `hashedDraftInboundPlanId`
        in the URL (single plan scope). Generated from the plan''s `portal_access_hash`.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Kit fields per item:** `is_kit` (boolean), `assemble_at_source` (boolean
        — the recipient builds this line''s kits from components before shipping),
        `components` (the pick list when assemble_at_source: `sku`, `name`, `barcode`,
        `per_kit`, `total_units` = per_kit × quantity).


        `user_name` falls back to the merchant''s store name when no inventory inquiry
        was explicitly sent.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: hashedDraftInboundPlanId
        in: path
        schema:
          type: string
        required: true
        description: The hashed draft inbound plan ID.
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      name:
                        type: string
                      user_name:
                        type: string
                      source_name:
                        type: string
                      created_at:
                        type: string
                      status:
                        type: string
                      items:
                        type: array
                        items:
                          type: object
                          properties:
                            product_id:
                              type: integer
                            image_url:
                              type: string
                              nullable: true
                            sku:
                              type: string
                            name:
                              type: string
                            barcode:
                              type: string
                            quantity:
                              type: integer
                            verified_quantity:
                              type: string
                              nullable: true
                            is_kit:
                              type: boolean
                            assemble_at_source:
                              type: boolean
                            components:
                              type: array
                              items:
                                type: object
                                properties:
                                  sku:
                                    type: string
                                  name:
                                    type: string
                                  barcode:
                                    type: string
                                  per_kit:
                                    type: integer
                                  total_units:
                                    type: integer
                example:
                  data:
                    name: SMO Inbound 2026/07/02
                    user_name: Jane Operator
                    source_name: ShipMyOrders Warehouse
                    created_at: '2026-07-02 16:36:09'
                    status: verification_in_progress
                    items:
                    - product_id: 707
                      image_url: null
                      sku: GSL392+400-939
                      name: Walbro GSL392 Fuel Pump + 400-939 Installation Kit
                      barcode: '703929123456'
                      quantity: 30
                      verified_quantity: null
                      is_kit: true
                      assemble_at_source: true
                      components:
                      - sku: GSL392
                        name: Walbro GSL392 255 LPH Fuel Pump
                        barcode: '703929787488'
                        per_kit: 1
                        total_units: 30
                      - sku: 400-939
                        name: Installation Kit
                        barcode: null
                        per_kit: 1
                        total_units: 30
                    - product_id: 15
                      image_url: null
                      sku: GSL395
                      name: Walbro GSL395 Fuel Pump
                      barcode: '703929111222'
                      quantity: 20
                      verified_quantity: null
                      is_kit: false
                      assemble_at_source: false
                      components: []
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-integrationinstance-draft-inbound-plans-portal-hasheddraftinboundplanid
  /api/amazon/{integrationInstance}/draft-inbound-plans/portal/{hashedDraftInboundPlanId}/verify-product:
    post:
      tags:
      - Amazon
      summary: Verify Product
      description: 'Record the quantity the source can provide for one product (spread
        across the plan''s lines for that product in order). For assemble-at-source
        kit lines the quantity is COMPLETE KITS buildable from component stock. No
        bearer token — access is granted by the encrypted `hashedDraftInboundPlanId`
        in the URL (single plan scope). Generated from the plan''s `portal_access_hash`.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                product_id:
                  type: integer
                verified_quantity:
                  type: integer
              example:
                product_id: 707
                verified_quantity: 25
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: hashedDraftInboundPlanId
        in: path
        schema:
          type: string
        required: true
        description: The hashed draft inbound plan ID.
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                example:
                  status: success
                  message: Product verified
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-amazon-integrationinstance-draft-inbound-plans-portal-hasheddraftinboundplanid-verify-product
  /api/amazon/{integrationInstance}/draft-inbound-plans/portal/{hashedDraftInboundPlanId}/verify-all-products:
    post:
      tags:
      - Amazon
      summary: Verify All Products
      description: 'Mark every line as verified at its requested quantity (the ''can
        fulfill everything'' shortcut). No bearer token — access is granted by the
        encrypted `hashedDraftInboundPlanId` in the URL (single plan scope). Generated
        from the plan''s `portal_access_hash`.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: hashedDraftInboundPlanId
        in: path
        schema:
          type: string
        required: true
        description: The hashed draft inbound plan ID.
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                example:
                  status: success
                  message: All products successfully verified
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-amazon-integrationinstance-draft-inbound-plans-portal-hasheddraftinboundplanid-verify-all-products
  /api/amazon/{integrationInstance}/draft-inbound-plans/portal/{hashedDraftInboundPlanId}/submit-verification:
    post:
      tags:
      - Amazon
      summary: Submit Verification
      description: 'Finalize the verification: plan moves to `verified` (or `verified_with_adjustments`
        when any line was verified short). Fails with 400 `cant_submit_verification_unless_all_items_verified`
        while any line is unverified. No bearer token — access is granted by the encrypted
        `hashedDraftInboundPlanId` in the URL (single plan scope). Generated from
        the plan''s `portal_access_hash`.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: hashedDraftInboundPlanId
        in: path
        schema:
          type: string
        required: true
        description: The hashed draft inbound plan ID.
      responses:
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: object
                    properties:
                      cant_submit_verification_unless_all_items_verified:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                example:
                  errors:
                    cant_submit_verification_unless_all_items_verified:
                    - message: Cannot submit verification unless all items are verified.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-amazon-integrationinstance-draft-inbound-plans-portal-hasheddraftinboundplanid-submit-verification
  /api/amazon/{integrationInstance}/draft-inbound-plans/{draft_inbound_plan}/fulfillment:
    get:
      tags:
      - Amazon
      summary: Show Fulfillment Packet
      description: 'Detect 3PL/supplier fulfillment availability for the plan and
        return the built packet (or null when not yet built). `available` reflects
        whether the plan is eligible; `source_type` is `3pl` or `supplier`; `packet`
        is the FbaInboundFulfillmentPacket resource including `recipient_email`, `recipient_name`,
        and the editable `email_template`.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **`email_will_attach_fnsku_labels`** (boolean): whether the 3PL email can
        carry the FNSKU label PDF (a durable label file is already attached, or labels
        are generatable at send for seller-labelled items) — drives the compose dialog''s
        attachment checkbox.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: draft_inbound_plan
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The draft inbound plan ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 OK — Packet Built
                  value:
                    available: true
                    source_type: 3pl
                    reason: null
                    packet:
                      id: 42
                      draft_amazon_fba_inbound_plan_id: 1
                      source_type: 3pl
                      source_type_label: 3PL
                      channels:
                      - portal
                      - email
                      integration_instance_id: 1
                      external_order_id: null
                      portal_url: '{{protocol}}://{{domain}}/v2/integrations/amazon/fba/draft-inbound-plans/verification-portal/uCJ8x2n1QwErTy?integration=1'
                      portal_token_expires_at: '2026-08-05T00:00:00+00:00'
                      portal_revoked_at: null
                      is_portal_accessible: true
                      recipient_email: warehouse@3pl.example.com
                      recipient_name: Acme 3PL Fulfillment
                      email_template:
                        subject: FBA inbound ready — {{reference}}
                        body: <p>Hi,</p><p>An Amazon FBA inbound shipment (<strong>{{reference}}</strong>)
                          is ready for you to prepare and ship.</p><p>Please use the
                          secure portal below to review the order and prep instructions,
                          submit your box contents, and confirm when the shipment
                          is ready:</p><p>{{portal_link}}</p><p><strong>Prep instructions</strong></p><p>{{instructions}}</p><p>Box/pallet
                          labels and the bill of lading are prepared separately and
                          will follow — the BOL is issued close to the pickup date.</p><p>Thank
                          you.</p>
                      instructions: Pack each MSKU into its own box. Apply the provided
                        FNSKU labels to every unit, then the box labels to the outside
                        of each carton.
                      instruction_override: null
                      has_custom_instructions: false
                      build_required: false
                      manufacturing_order_id: null
                      status: draft
                      status_label: Draft
                      sent_at: null
                      acknowledged_at: null
                      portal_submission: null
                      documents:
                      - id: 501
                        type: instructions
                        type_label: Instructions
                        stage: initial
                        stage_label: Initial
                        status: ready
                        status_label: Ready
                        is_downloadable: true
                        ready_at: '2026-07-06T12:00:00+00:00'
                        sent_at: null
                      - id: 502
                        type: fnsku_labels
                        type_label: FNSKU Labels
                        stage: initial
                        stage_label: Initial
                        status: ready
                        status_label: Ready
                        is_downloadable: true
                        ready_at: '2026-07-06T12:00:00+00:00'
                        sent_at: null
                      created_at: '2026-07-06T12:00:00+00:00'
                      updated_at: '2026-07-06T12:00:00+00:00'
                example-1:
                  summary: 200 OK — Not Yet Built
                  value:
                    available: true
                    source_type: 3pl
                    reason: null
                    packet: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-integrationinstance-draft-inbound-plans-draft-inbound-plan-fulfillment
    post:
      tags:
      - Amazon
      summary: Build Fulfillment Packet
      description: 'Build (or rebuild) the 3PL/supplier fulfillment packet for the
        plan: generates the prep documents, portal token, and default instructions.
        Body: `channels` (optional array of `api|email|portal`), `build_kits` (boolean,
        default true), `instruction_override` (optional string to replace the condition-aware
        default instructions).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **`email_will_attach_fnsku_labels`** (boolean): whether the 3PL email can
        carry the FNSKU label PDF (a durable label file is already attached, or labels
        are generatable at send for seller-labelled items) — drives the compose dialog''s
        attachment checkbox.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                channels:
                  type: array
                  items:
                    type: string
                build_kits:
                  type: boolean
                instruction_override:
                  type: string
                  nullable: true
              example:
                channels:
                - portal
                - email
                build_kits: true
                instruction_override: null
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: draft_inbound_plan
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The draft inbound plan ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      draft_amazon_fba_inbound_plan_id:
                        type: integer
                      source_type:
                        type: string
                      source_type_label:
                        type: string
                      channels:
                        type: array
                        items:
                          type: string
                      integration_instance_id:
                        type: integer
                      external_order_id:
                        type: string
                        nullable: true
                      portal_url:
                        type: string
                      portal_token_expires_at:
                        type: string
                      portal_revoked_at:
                        type: string
                        nullable: true
                      is_portal_accessible:
                        type: boolean
                      recipient_email:
                        type: string
                      recipient_name:
                        type: string
                      email_template:
                        type: object
                        properties:
                          subject:
                            type: string
                          body:
                            type: string
                      email_will_attach_fnsku_labels:
                        type: boolean
                      instructions:
                        type: string
                      instruction_override:
                        type: string
                        nullable: true
                      has_custom_instructions:
                        type: boolean
                      build_required:
                        type: boolean
                      manufacturing_order_id:
                        type: string
                        nullable: true
                      status:
                        type: string
                      status_label:
                        type: string
                      sent_at:
                        type: string
                        nullable: true
                      acknowledged_at:
                        type: string
                        nullable: true
                      portal_submission:
                        type: string
                        nullable: true
                      documents:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            type:
                              type: string
                            type_label:
                              type: string
                            stage:
                              type: string
                            stage_label:
                              type: string
                            status:
                              type: string
                            status_label:
                              type: string
                            is_downloadable:
                              type: boolean
                            ready_at:
                              type: string
                            sent_at:
                              type: string
                              nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  message: Fulfillment packet built.
                  data:
                    id: 42
                    draft_amazon_fba_inbound_plan_id: 1
                    source_type: 3pl
                    source_type_label: 3PL
                    channels:
                    - portal
                    - email
                    integration_instance_id: 1
                    external_order_id: null
                    portal_url: '{{protocol}}://{{domain}}/v2/integrations/amazon/fba/draft-inbound-plans/verification-portal/uCJ8x2n1QwErTy?integration=1'
                    portal_token_expires_at: '2026-08-05T00:00:00+00:00'
                    portal_revoked_at: null
                    is_portal_accessible: true
                    recipient_email: warehouse@3pl.example.com
                    recipient_name: Acme 3PL Fulfillment
                    email_template:
                      subject: FBA inbound ready — {{reference}}
                      body: <p>Hi,</p><p>An Amazon FBA inbound shipment (<strong>{{reference}}</strong>)
                        is ready for you to prepare and ship.</p><p>Please use the
                        secure portal below to review the order and prep instructions,
                        submit your box contents, and confirm when the shipment is
                        ready:</p><p>{{portal_link}}</p><p><strong>Prep instructions</strong></p><p>{{instructions}}</p><p>Box/pallet
                        labels and the bill of lading are prepared separately and
                        will follow — the BOL is issued close to the pickup date.</p><p>Thank
                        you.</p>
                    email_will_attach_fnsku_labels: true
                    instructions: Pack each MSKU into its own box. Apply the provided
                      FNSKU labels to every unit, then the box labels to the outside
                      of each carton.
                    instruction_override: null
                    has_custom_instructions: false
                    build_required: false
                    manufacturing_order_id: null
                    status: draft
                    status_label: Draft
                    sent_at: null
                    acknowledged_at: null
                    portal_submission: null
                    documents:
                    - id: 501
                      type: instructions
                      type_label: Instructions
                      stage: initial
                      stage_label: Initial
                      status: ready
                      status_label: Ready
                      is_downloadable: true
                      ready_at: '2026-07-06T12:00:00+00:00'
                      sent_at: null
                    - id: 502
                      type: fnsku_labels
                      type_label: FNSKU Labels
                      stage: initial
                      stage_label: Initial
                      status: ready
                      status_label: Ready
                      is_downloadable: true
                      ready_at: '2026-07-06T12:00:00+00:00'
                      sent_at: null
                    created_at: '2026-07-06T12:00:00+00:00'
                    updated_at: '2026-07-06T12:00:00+00:00'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      fulfillment_not_available:
                        type: array
                        items:
                          type: string
                example:
                  message: This plan is not eligible for 3PL/supplier fulfillment.
                  errors:
                    fulfillment_not_available:
                    - This plan is not eligible for 3PL/supplier fulfillment.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-amazon-integrationinstance-draft-inbound-plans-draft-inbound-plan-fulfillment
    put:
      tags:
      - Amazon
      summary: Update Fulfillment Packet
      description: 'Update the fulfillment packet — same payload and behaviour as
        Build; re-runs the packet build with the supplied channels / kit flag / instruction
        override.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **`email_will_attach_fnsku_labels`** (boolean): whether the 3PL email can
        carry the FNSKU label PDF (a durable label file is already attached, or labels
        are generatable at send for seller-labelled items) — drives the compose dialog''s
        attachment checkbox.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                channels:
                  type: array
                  items:
                    type: string
                build_kits:
                  type: boolean
                instruction_override:
                  type: string
                  nullable: true
              example:
                channels:
                - portal
                - email
                build_kits: true
                instruction_override: null
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: draft_inbound_plan
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The draft inbound plan ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      draft_amazon_fba_inbound_plan_id:
                        type: integer
                      source_type:
                        type: string
                      source_type_label:
                        type: string
                      channels:
                        type: array
                        items:
                          type: string
                      integration_instance_id:
                        type: integer
                      external_order_id:
                        type: string
                        nullable: true
                      portal_url:
                        type: string
                      portal_token_expires_at:
                        type: string
                      portal_revoked_at:
                        type: string
                        nullable: true
                      is_portal_accessible:
                        type: boolean
                      recipient_email:
                        type: string
                      recipient_name:
                        type: string
                      email_template:
                        type: object
                        properties:
                          subject:
                            type: string
                          body:
                            type: string
                      email_will_attach_fnsku_labels:
                        type: boolean
                      instructions:
                        type: string
                      instruction_override:
                        type: string
                        nullable: true
                      has_custom_instructions:
                        type: boolean
                      build_required:
                        type: boolean
                      manufacturing_order_id:
                        type: string
                        nullable: true
                      status:
                        type: string
                      status_label:
                        type: string
                      sent_at:
                        type: string
                        nullable: true
                      acknowledged_at:
                        type: string
                        nullable: true
                      portal_submission:
                        type: string
                        nullable: true
                      documents:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            type:
                              type: string
                            type_label:
                              type: string
                            stage:
                              type: string
                            stage_label:
                              type: string
                            status:
                              type: string
                            status_label:
                              type: string
                            is_downloadable:
                              type: boolean
                            ready_at:
                              type: string
                            sent_at:
                              type: string
                              nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  message: Fulfillment packet built.
                  data:
                    id: 42
                    draft_amazon_fba_inbound_plan_id: 1
                    source_type: 3pl
                    source_type_label: 3PL
                    channels:
                    - portal
                    - email
                    integration_instance_id: 1
                    external_order_id: null
                    portal_url: '{{protocol}}://{{domain}}/v2/integrations/amazon/fba/draft-inbound-plans/verification-portal/uCJ8x2n1QwErTy?integration=1'
                    portal_token_expires_at: '2026-08-05T00:00:00+00:00'
                    portal_revoked_at: null
                    is_portal_accessible: true
                    recipient_email: warehouse@3pl.example.com
                    recipient_name: Acme 3PL Fulfillment
                    email_template:
                      subject: FBA inbound ready — {{reference}}
                      body: <p>Hi,</p><p>An Amazon FBA inbound shipment (<strong>{{reference}}</strong>)
                        is ready for you to prepare and ship.</p><p>Please use the
                        secure portal below to review the order and prep instructions,
                        submit your box contents, and confirm when the shipment is
                        ready:</p><p>{{portal_link}}</p><p><strong>Prep instructions</strong></p><p>{{instructions}}</p><p>Box/pallet
                        labels and the bill of lading are prepared separately and
                        will follow — the BOL is issued close to the pickup date.</p><p>Thank
                        you.</p>
                    email_will_attach_fnsku_labels: true
                    instructions: Pack each MSKU into its own box. Apply the provided
                      FNSKU labels to every unit, then the box labels to the outside
                      of each carton.
                    instruction_override: null
                    has_custom_instructions: false
                    build_required: false
                    manufacturing_order_id: null
                    status: draft
                    status_label: Draft
                    sent_at: null
                    acknowledged_at: null
                    portal_submission: null
                    documents:
                    - id: 501
                      type: instructions
                      type_label: Instructions
                      stage: initial
                      stage_label: Initial
                      status: ready
                      status_label: Ready
                      is_downloadable: true
                      ready_at: '2026-07-06T12:00:00+00:00'
                      sent_at: null
                    - id: 502
                      type: fnsku_labels
                      type_label: FNSKU Labels
                      stage: initial
                      stage_label: Initial
                      status: ready
                      status_label: Ready
                      is_downloadable: true
                      ready_at: '2026-07-06T12:00:00+00:00'
                      sent_at: null
                    created_at: '2026-07-06T12:00:00+00:00'
                    updated_at: '2026-07-06T12:00:00+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-amazon-integrationinstance-draft-inbound-plans-draft-inbound-plan-fulfillment
  /api/amazon/{integrationInstance}/draft-inbound-plans/{draft_inbound_plan}/fulfillment/prep-sheet.csv:
    get:
      tags:
      - Amazon
      summary: Download Prep & Pack Sheet CSV
      description: 'Download the fulfillment prep & pack sheet as a CSV file, to hand
        to a 3PL or supplier that won''t use the fulfilment portal (e.g. for upload
        into their own system). The CSV contains a Unit Mix section (SKU, product,
        MSKU, FNSKU, UPC, quantity, unit weight, unit dimensions, who labels, who
        preps) and, once box contents have been submitted, a Box Contents section
        (box number, SKU, quantity) matching the box-import template so it round-trips.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: requires a Bearer token.


        Returns 422 if the fulfilment packet has not been built yet.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Amazon integration instance ID
        example: '1'
      - name: draft_inbound_plan
        in: path
        schema:
          type: integer
        required: true
        description: Draft FBA inbound plan ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: text/csv
          content:
            text/plain:
              schema:
                type: string
                example: 'Unit Mix

                  SKU,Product,MSKU,FNSKU,UPC,Qty,Unit weight,Unit dimensions,Who labels,Who
                  preps

                  SOAP-01,Shave Soap,1000070-FBA,X00ABCDEF1,850000000017,448,0.5 lb,4
                  x 4 x 2 in,SELLER,NONE


                  Box Contents

                  Box number,SKU,Qty

                  1,SOAP-01,112'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-integrationinstance-draft-inbound-plans-draft-inbound-plan-fulfillment-prep-sheet-csv
  /api/amazon/{integrationInstance}/draft-inbound-plans/{draft_inbound_plan}/fulfillment/send:
    post:
      tags:
      - Amazon
      summary: Send Fulfillment Order
      description: 'Dispatch the full fulfillment send as a tracked background job
        (marks documents + packet Sent and delivers the configured channels). Returns
        the tracked job log id to poll for progress via the tracked job log endpoints.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: draft_inbound_plan
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The draft inbound plan ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                example:
                  message: Order send started.
                  data:
                    tracked_job_log_id: 9001
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      packet_not_built:
                        type: array
                        items:
                          type: string
                example:
                  message: Build the fulfillment packet before sending.
                  errors:
                    packet_not_built:
                    - Build the fulfillment packet before sending.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-amazon-integrationinstance-draft-inbound-plans-draft-inbound-plan-fulfillment-send
  /api/amazon/{integrationInstance}/draft-inbound-plans/{draft_inbound_plan}/fulfillment/email/preview:
    post:
      tags:
      - Amazon
      summary: Preview 3PL Email
      description: 'Preview the "Email the 3PL" compose dialog: substitutes the `{{reference}}`,
        `{{portal_link}}`, and `{{instructions}}` tokens in the supplied subject/body
        server-side and returns the rendered result (no email is sent). Body: `subject`
        (required, max 255), `body` (required HTML string), `cc` (optional array of
        email addresses).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                subject:
                  type: string
                body:
                  type: string
                cc:
                  type: array
                  items:
                    type: string
              example:
                subject: FBA inbound ready — WF-2026-000123
                body: <p>Hi,</p><p>An Amazon FBA inbound shipment (<strong>{{reference}}</strong>)
                  is ready.</p><p>{{portal_link}}</p><p>{{instructions}}</p>
                cc:
                - ops@example.com
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: draft_inbound_plan
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The draft inbound plan ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      subject:
                        type: string
                      body:
                        type: string
                example:
                  data:
                    subject: FBA inbound ready — WF-2026-000123
                    body: <p>Hi,</p><p>An Amazon FBA inbound shipment (<strong>WF-2026-000123</strong>)
                      is ready.</p><p><a href="https://app.sku.io/v2/integrations/amazon/fba/draft-inbound-plans/verification-portal/uCJ8x2n1QwErTy?integration=1">https://app.sku.io/v2/integrations/amazon/fba/draft-inbound-plans/verification-portal/uCJ8x2n1QwErTy?integration=1</a></p><p>Pack
                      each MSKU into its own box.<br />Apply the provided FNSKU labels
                      to every unit.</p>
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      packet_not_built:
                        type: array
                        items:
                          type: string
                example:
                  message: Build the fulfillment packet before previewing the email.
                  errors:
                    packet_not_built:
                    - Build the fulfillment packet before previewing the email.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-amazon-integrationinstance-draft-inbound-plans-draft-inbound-plan-fulfillment-email-preview
  /api/amazon/{integrationInstance}/draft-inbound-plans/{draft_inbound_plan}/fulfillment/email:
    post:
      tags:
      - Amazon
      summary: Send 3PL Email
      description: 'Send the operator-composed "Email the 3PL" portal invitation:
        resolves the 3PL/supplier recipient, substitutes the `{{reference}}`/`{{portal_link}}`/`{{instructions}}`
        tokens, marks the packet Sent, and dispatches FbaInboundPortalInviteNotification
        (CC honoured). Returns the updated FbaInboundFulfillmentPacket resource. Same
        body as the preview endpoint.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **`attach_fnsku_labels`** (boolean, optional, default `true`): attach the
        FNSKU item-label PDF to the email. When no durable label file exists yet,
        labels are generated at send time for every seller-labelled item at its plan
        quantity (best-effort — a generation failure never blocks the email). Send
        `false` to omit the attachment.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                subject:
                  type: string
                body:
                  type: string
                cc:
                  type: array
                  items:
                    type: string
                attach_fnsku_labels:
                  type: boolean
              example:
                subject: FBA inbound ready — WF-2026-000123
                body: <p>Hi,</p><p>An Amazon FBA inbound shipment (<strong>{{reference}}</strong>)
                  is ready.</p><p>{{portal_link}}</p><p>{{instructions}}</p>
                cc:
                - ops@example.com
                attach_fnsku_labels: true
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: draft_inbound_plan
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The draft inbound plan ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      draft_amazon_fba_inbound_plan_id:
                        type: integer
                      source_type:
                        type: string
                      source_type_label:
                        type: string
                      channels:
                        type: array
                        items:
                          type: string
                      integration_instance_id:
                        type: integer
                      external_order_id:
                        type: string
                        nullable: true
                      portal_url:
                        type: string
                      portal_token_expires_at:
                        type: string
                      portal_revoked_at:
                        type: string
                        nullable: true
                      is_portal_accessible:
                        type: boolean
                      recipient_email:
                        type: string
                      recipient_name:
                        type: string
                      email_template:
                        type: object
                        properties:
                          subject:
                            type: string
                          body:
                            type: string
                      instructions:
                        type: string
                      instruction_override:
                        type: string
                        nullable: true
                      has_custom_instructions:
                        type: boolean
                      build_required:
                        type: boolean
                      manufacturing_order_id:
                        type: string
                        nullable: true
                      status:
                        type: string
                      status_label:
                        type: string
                      sent_at:
                        type: string
                      acknowledged_at:
                        type: string
                        nullable: true
                      portal_submission:
                        type: string
                        nullable: true
                      documents:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            type:
                              type: string
                            type_label:
                              type: string
                            stage:
                              type: string
                            stage_label:
                              type: string
                            status:
                              type: string
                            status_label:
                              type: string
                            is_downloadable:
                              type: boolean
                            ready_at:
                              type: string
                            sent_at:
                              type: string
                              nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  message: Email sent to the 3PL.
                  data:
                    id: 42
                    draft_amazon_fba_inbound_plan_id: 1
                    source_type: 3pl
                    source_type_label: 3PL
                    channels:
                    - portal
                    - email
                    integration_instance_id: 1
                    external_order_id: null
                    portal_url: '{{protocol}}://{{domain}}/v2/integrations/amazon/fba/draft-inbound-plans/verification-portal/uCJ8x2n1QwErTy?integration=1'
                    portal_token_expires_at: '2026-08-05T00:00:00+00:00'
                    portal_revoked_at: null
                    is_portal_accessible: true
                    recipient_email: warehouse@3pl.example.com
                    recipient_name: Acme 3PL Fulfillment
                    email_template:
                      subject: FBA inbound ready — {{reference}}
                      body: <p>Hi,</p><p>An Amazon FBA inbound shipment (<strong>{{reference}}</strong>)
                        is ready for you to prepare and ship.</p><p>Please use the
                        secure portal below to review the order and prep instructions,
                        submit your box contents, and confirm when the shipment is
                        ready:</p><p>{{portal_link}}</p><p><strong>Prep instructions</strong></p><p>{{instructions}}</p><p>Box/pallet
                        labels and the bill of lading are prepared separately and
                        will follow — the BOL is issued close to the pickup date.</p><p>Thank
                        you.</p>
                    instructions: Pack each MSKU into its own box. Apply the provided
                      FNSKU labels to every unit, then the box labels to the outside
                      of each carton.
                    instruction_override: null
                    has_custom_instructions: false
                    build_required: false
                    manufacturing_order_id: null
                    status: sent
                    status_label: Sent
                    sent_at: '2026-07-06T12:05:00+00:00'
                    acknowledged_at: null
                    portal_submission: null
                    documents:
                    - id: 501
                      type: instructions
                      type_label: Instructions
                      stage: initial
                      stage_label: Initial
                      status: ready
                      status_label: Ready
                      is_downloadable: true
                      ready_at: '2026-07-06T12:00:00+00:00'
                      sent_at: null
                    - id: 502
                      type: fnsku_labels
                      type_label: FNSKU Labels
                      stage: initial
                      stage_label: Initial
                      status: ready
                      status_label: Ready
                      is_downloadable: true
                      ready_at: '2026-07-06T12:00:00+00:00'
                      sent_at: null
                    created_at: '2026-07-06T12:00:00+00:00'
                    updated_at: '2026-07-06T12:00:00+00:00'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 422 Packet Not Built
                  value:
                    message: Build the fulfillment packet before sending the email.
                    errors:
                      packet_not_built:
                      - Build the fulfillment packet before sending the email.
                example-1:
                  summary: 422 No Recipient
                  value:
                    message: No recipient email is configured for this 3PL/supplier.
                      Add one to the source before emailing.
                    errors:
                      no_recipient:
                      - No recipient email is configured for this 3PL/supplier. Add
                        one to the source before emailing.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-amazon-integrationinstance-draft-inbound-plans-draft-inbound-plan-fulfillment-email
  /api/amazon/{integrationInstance}/draft-inbound-plans/{draft_inbound_plan}/fulfillment/documents/sync-labels:
    post:
      tags:
      - Amazon
      summary: Sync Label Documents
      description: 'Attach any newly-generated FBA label documents (FNSKU / box /
        pallet labels, BOL) from the plan to the fulfillment portal so the 3PL can
        download them. Returns the refreshed packet.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: draft_inbound_plan
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The draft inbound plan ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      draft_amazon_fba_inbound_plan_id:
                        type: integer
                      source_type:
                        type: string
                      source_type_label:
                        type: string
                      channels:
                        type: array
                        items:
                          type: string
                      integration_instance_id:
                        type: integer
                      external_order_id:
                        type: string
                        nullable: true
                      portal_url:
                        type: string
                      portal_token_expires_at:
                        type: string
                      portal_revoked_at:
                        type: string
                        nullable: true
                      is_portal_accessible:
                        type: boolean
                      recipient_email:
                        type: string
                      recipient_name:
                        type: string
                      email_template:
                        type: object
                        properties:
                          subject:
                            type: string
                          body:
                            type: string
                      instructions:
                        type: string
                      instruction_override:
                        type: string
                        nullable: true
                      has_custom_instructions:
                        type: boolean
                      build_required:
                        type: boolean
                      manufacturing_order_id:
                        type: string
                        nullable: true
                      status:
                        type: string
                      status_label:
                        type: string
                      sent_at:
                        type: string
                        nullable: true
                      acknowledged_at:
                        type: string
                        nullable: true
                      portal_submission:
                        type: string
                        nullable: true
                      documents:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            type:
                              type: string
                            type_label:
                              type: string
                            stage:
                              type: string
                            stage_label:
                              type: string
                            status:
                              type: string
                            status_label:
                              type: string
                            is_downloadable:
                              type: boolean
                            ready_at:
                              type: string
                            sent_at:
                              type: string
                              nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  message: Attached 2 label document(s) to the portal.
                  data:
                    id: 42
                    draft_amazon_fba_inbound_plan_id: 1
                    source_type: 3pl
                    source_type_label: 3PL
                    channels:
                    - portal
                    - email
                    integration_instance_id: 1
                    external_order_id: null
                    portal_url: '{{protocol}}://{{domain}}/v2/integrations/amazon/fba/draft-inbound-plans/verification-portal/uCJ8x2n1QwErTy?integration=1'
                    portal_token_expires_at: '2026-08-05T00:00:00+00:00'
                    portal_revoked_at: null
                    is_portal_accessible: true
                    recipient_email: warehouse@3pl.example.com
                    recipient_name: Acme 3PL Fulfillment
                    email_template:
                      subject: FBA inbound ready — {{reference}}
                      body: <p>Hi,</p><p>An Amazon FBA inbound shipment (<strong>{{reference}}</strong>)
                        is ready for you to prepare and ship.</p><p>Please use the
                        secure portal below to review the order and prep instructions,
                        submit your box contents, and confirm when the shipment is
                        ready:</p><p>{{portal_link}}</p><p><strong>Prep instructions</strong></p><p>{{instructions}}</p><p>Box/pallet
                        labels and the bill of lading are prepared separately and
                        will follow — the BOL is issued close to the pickup date.</p><p>Thank
                        you.</p>
                    instructions: Pack each MSKU into its own box. Apply the provided
                      FNSKU labels to every unit, then the box labels to the outside
                      of each carton.
                    instruction_override: null
                    has_custom_instructions: false
                    build_required: false
                    manufacturing_order_id: null
                    status: draft
                    status_label: Draft
                    sent_at: null
                    acknowledged_at: null
                    portal_submission: null
                    documents:
                    - id: 501
                      type: instructions
                      type_label: Instructions
                      stage: initial
                      stage_label: Initial
                      status: ready
                      status_label: Ready
                      is_downloadable: true
                      ready_at: '2026-07-06T12:00:00+00:00'
                      sent_at: null
                    - id: 502
                      type: fnsku_labels
                      type_label: FNSKU Labels
                      stage: initial
                      stage_label: Initial
                      status: ready
                      status_label: Ready
                      is_downloadable: true
                      ready_at: '2026-07-06T12:00:00+00:00'
                      sent_at: null
                    created_at: '2026-07-06T12:00:00+00:00'
                    updated_at: '2026-07-06T12:00:00+00:00'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      packet_not_built:
                        type: array
                        items:
                          type: string
                example:
                  message: Build the fulfillment packet first.
                  errors:
                    packet_not_built:
                    - Build the fulfillment packet first.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-amazon-integrationinstance-draft-inbound-plans-draft-inbound-plan-fulfillment-documents-sync-labels
  /api/amazon/{integrationInstance}/draft-inbound-plans/{draft_inbound_plan}/fulfillment/portal-token/rotate:
    post:
      tags:
      - Amazon
      summary: Rotate Portal Link
      description: 'Rotate the portal token — invalidates the old portal link and
        issues a fresh one (and a new `portal_url`). Use when a link may have leaked.
        Returns the refreshed packet.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: draft_inbound_plan
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The draft inbound plan ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      draft_amazon_fba_inbound_plan_id:
                        type: integer
                      source_type:
                        type: string
                      source_type_label:
                        type: string
                      channels:
                        type: array
                        items:
                          type: string
                      integration_instance_id:
                        type: integer
                      external_order_id:
                        type: string
                        nullable: true
                      portal_url:
                        type: string
                      portal_token_expires_at:
                        type: string
                      portal_revoked_at:
                        type: string
                        nullable: true
                      is_portal_accessible:
                        type: boolean
                      recipient_email:
                        type: string
                      recipient_name:
                        type: string
                      email_template:
                        type: object
                        properties:
                          subject:
                            type: string
                          body:
                            type: string
                      instructions:
                        type: string
                      instruction_override:
                        type: string
                        nullable: true
                      has_custom_instructions:
                        type: boolean
                      build_required:
                        type: boolean
                      manufacturing_order_id:
                        type: string
                        nullable: true
                      status:
                        type: string
                      status_label:
                        type: string
                      sent_at:
                        type: string
                        nullable: true
                      acknowledged_at:
                        type: string
                        nullable: true
                      portal_submission:
                        type: string
                        nullable: true
                      documents:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            type:
                              type: string
                            type_label:
                              type: string
                            stage:
                              type: string
                            stage_label:
                              type: string
                            status:
                              type: string
                            status_label:
                              type: string
                            is_downloadable:
                              type: boolean
                            ready_at:
                              type: string
                            sent_at:
                              type: string
                              nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  message: Portal link rotated.
                  data:
                    id: 42
                    draft_amazon_fba_inbound_plan_id: 1
                    source_type: 3pl
                    source_type_label: 3PL
                    channels:
                    - portal
                    - email
                    integration_instance_id: 1
                    external_order_id: null
                    portal_url: '{{protocol}}://{{domain}}/v2/integrations/amazon/fba/draft-inbound-plans/verification-portal/uCJ8x2n1QwErTy?integration=1'
                    portal_token_expires_at: '2026-08-05T00:00:00+00:00'
                    portal_revoked_at: null
                    is_portal_accessible: true
                    recipient_email: warehouse@3pl.example.com
                    recipient_name: Acme 3PL Fulfillment
                    email_template:
                      subject: FBA inbound ready — {{reference}}
                      body: <p>Hi,</p><p>An Amazon FBA inbound shipment (<strong>{{reference}}</strong>)
                        is ready for you to prepare and ship.</p><p>Please use the
                        secure portal below to review the order and prep instructions,
                        submit your box contents, and confirm when the shipment is
                        ready:</p><p>{{portal_link}}</p><p><strong>Prep instructions</strong></p><p>{{instructions}}</p><p>Box/pallet
                        labels and the bill of lading are prepared separately and
                        will follow — the BOL is issued close to the pickup date.</p><p>Thank
                        you.</p>
                    instructions: Pack each MSKU into its own box. Apply the provided
                      FNSKU labels to every unit, then the box labels to the outside
                      of each carton.
                    instruction_override: null
                    has_custom_instructions: false
                    build_required: false
                    manufacturing_order_id: null
                    status: draft
                    status_label: Draft
                    sent_at: null
                    acknowledged_at: null
                    portal_submission: null
                    documents:
                    - id: 501
                      type: instructions
                      type_label: Instructions
                      stage: initial
                      stage_label: Initial
                      status: ready
                      status_label: Ready
                      is_downloadable: true
                      ready_at: '2026-07-06T12:00:00+00:00'
                      sent_at: null
                    - id: 502
                      type: fnsku_labels
                      type_label: FNSKU Labels
                      stage: initial
                      stage_label: Initial
                      status: ready
                      status_label: Ready
                      is_downloadable: true
                      ready_at: '2026-07-06T12:00:00+00:00'
                      sent_at: null
                    created_at: '2026-07-06T12:00:00+00:00'
                    updated_at: '2026-07-06T12:00:00+00:00'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      packet_not_built:
                        type: array
                        items:
                          type: string
                example:
                  message: Build the fulfillment packet first.
                  errors:
                    packet_not_built:
                    - Build the fulfillment packet first.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-amazon-integrationinstance-draft-inbound-plans-draft-inbound-plan-fulfillment-portal-token-rotate
  /api/amazon/{integrationInstance}/draft-inbound-plans/fulfillment-portal/{token}:
    get:
      tags:
      - Amazon
      summary: Get Portal Payload (3PL Portal)
      description: 'Anonymous 3PL/supplier fulfillment portal entry point. Access
        is granted by the opaque `:token` in the URL (the packet''s `portal_token`)
        — no bearer auth (`tenant.public-portal` middleware). Returns the full portal
        payload the 3PL sees: shipment reference + FBA id, source, the destination
        fulfillment center (`destination_fc`) and its **full destination address**
        (`destination_address`, Amazon SP-API camelCase keys — null until Amazon assigns
        placement), shipping mode / LTL flags, condition-aware `instructions` (markdown,
        rendered inline by the portal), downloadable `documents`, the product catalogue
        for the box-contents packing station (`products`), the tenant''s saved carton
        presets (`carton_templates`), any existing `box_contents_submission` / `pallets_submission`,
        and the confirm gating (`can_confirm`, `confirm_blocked_reason`).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **`products[]` fields:** each item carries `product_id`, `sku`, `name`, `image_url`,
        `msku`, `fnsku`, `barcode` (UPC — enables barcode scanning in the portal),
        `quantity` (required units), `label_owner` / `prep_owner` (AMAZON | SELLER
        | NONE — SELLER label_owner means the 3PL applies FNSKU labels; SELLER prep_owner
        means the 3PL must prep the item before boxing), and the unit measurements
        saved on the product record: `weight`, `weight_unit`, `length`, `width`, `height`,
        `dimension_unit`.


        **`documents[]`** lists only genuinely downloadable paperwork (kitting work
        order, FNSKU/box/pallet labels, BOL once attached). The renderable `instructions`
        and `box_contents` types are NOT listed — the portal renders instructions
        inline and collects box contents via its own form.


        Every view is audit-logged (portal events). Returns 404 when the token is
        expired, rotated, or revoked.


        **`prep_details`** (object|null): the operator''s last persisted Amazon prep-details
        fetch — `{details: [{msku, prepCategory, prepTypes[], ...}], fetched_at}`
        — powering the portal''s per-category "Required Prep Types" breakdown. Null
        when prep details were never fetched.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: token
        in: path
        schema:
          type: string
        required: true
        description: The token ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      reference:
                        type: string
                      fba_shipment_id:
                        type: string
                      source_name:
                        type: string
                      source_type:
                        type: string
                      destination_fc:
                        type: string
                      destination_address:
                        type: object
                        properties:
                          name:
                            type: string
                          addressLine1:
                            type: string
                          addressLine2:
                            type: string
                            nullable: true
                          city:
                            type: string
                          stateOrProvinceCode:
                            type: string
                          postalCode:
                            type: string
                          countryCode:
                            type: string
                      shipping_mode:
                        type: string
                      is_ltl:
                        type: boolean
                      requires_pallets:
                        type: boolean
                      status:
                        type: string
                      requested_by:
                        type: string
                      build_required:
                        type: boolean
                      kits_pending_build:
                        type: boolean
                      kit_build_manifest:
                        type: array
                      instructions:
                        type: string
                      prep_details:
                        type: object
                        properties:
                          details:
                            type: array
                            items:
                              type: object
                              properties:
                                msku:
                                  type: string
                                prepCategory:
                                  type: string
                                prepTypes:
                                  type: array
                                  items:
                                    type: string
                                labelOwnerConstraint:
                                  type: string
                                  nullable: true
                                prepOwnerConstraint:
                                  type: string
                                  nullable: true
                                allOwnersConstraint:
                                  type: string
                                  nullable: true
                          fetched_at:
                            type: string
                      documents:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            type:
                              type: string
                            type_label:
                              type: string
                            stage:
                              type: string
                            status:
                              type: string
                      products:
                        type: array
                        items:
                          type: object
                          properties:
                            product_id:
                              type: integer
                            sku:
                              type: string
                            name:
                              type: string
                            image_url:
                              type: string
                            msku:
                              type: string
                            fnsku:
                              type: string
                            barcode:
                              type: string
                            quantity:
                              type: integer
                            label_owner:
                              type: string
                            prep_owner:
                              type: string
                            weight:
                              type: number
                            weight_unit:
                              type: string
                            length:
                              type: number
                            width:
                              type: number
                            height:
                              type: number
                            dimension_unit:
                              type: string
                      carton_templates:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            length:
                              type: integer
                            width:
                              type: integer
                            height:
                              type: integer
                            dimension_unit:
                              type: string
                            tare_weight:
                              type: number
                            weight_unit:
                              type: string
                            is_active:
                              type: boolean
                      box_contents_submission:
                        type: string
                        nullable: true
                      pallets_submission:
                        type: string
                        nullable: true
                      can_confirm:
                        type: boolean
                      confirm_blocked_reason:
                        type: string
                      acknowledged_at:
                        type: string
                        nullable: true
                example:
                  data:
                    reference: FBA-2026-000123
                    fba_shipment_id: FBA15ABCDEF
                    source_name: Acme 3PL Warehouse
                    source_type: 3pl
                    destination_fc: ONT8
                    destination_address:
                      name: Amazon.com
                      addressLine1: 24208 San Michele Rd
                      addressLine2: null
                      city: Moreno Valley
                      stateOrProvinceCode: CA
                      postalCode: '92551'
                      countryCode: US
                    shipping_mode: GROUND_SMALL_PARCEL
                    is_ltl: false
                    requires_pallets: false
                    status: in_progress
                    requested_by: Jane Buyer
                    build_required: false
                    kits_pending_build: false
                    kit_build_manifest: []
                    instructions: '# FBA Inbound Preparation Instructions

                      Shipment: FBA15ABCDEF

                      Ship to: Amazon ONT8


                      Pack each SKU into the boxes exactly as listed, label every
                      box, then confirm ready to ship.'
                    prep_details:
                      details:
                      - msku: ACME-SKU-A
                        prepCategory: FRAGILE
                        prepTypes:
                        - ITEM_BUBBLEWRAP
                        - ITEM_LABELING
                        labelOwnerConstraint: null
                        prepOwnerConstraint: null
                        allOwnersConstraint: null
                      fetched_at: '2026-07-07T05:00:00+00:00'
                    documents:
                    - id: 41
                      type: work_order
                      type_label: Kitting Work Order
                      stage: initial
                      status: ready
                    - id: 44
                      type: box_labels
                      type_label: Box Labels
                      stage: mid
                      status: ready
                    products:
                    - product_id: 5567
                      sku: SKU-A
                      name: Acme Widget - Blue
                      image_url: https://cdn.example.com/img/sku-a.jpg
                      msku: ACME-SKU-A
                      fnsku: X001ABCDEF
                      barcode: '812345678901'
                      quantity: 24
                      label_owner: SELLER
                      prep_owner: SELLER
                      weight: 1.4
                      weight_unit: lb
                      length: 7.3
                      width: 4.9
                      height: 2.8
                      dimension_unit: in
                    - product_id: 5568
                      sku: SKU-B
                      name: Acme Widget - Red
                      image_url: null
                      msku: ACME-SKU-B
                      fnsku: X001GHIJKL
                      barcode: null
                      quantity: 12
                      label_owner: AMAZON
                      prep_owner: NONE
                      weight: null
                      weight_unit: null
                      length: null
                      width: null
                      height: null
                      dimension_unit: null
                    carton_templates:
                    - id: 7
                      name: Standard 12x10x8
                      length: 12
                      width: 10
                      height: 8
                      dimension_unit: IN
                      tare_weight: 0.5
                      weight_unit: LB
                      is_active: true
                    - id: 8
                      name: Large 18x12x10
                      length: 18
                      width: 12
                      height: 10
                      dimension_unit: IN
                      tare_weight: 0.8
                      weight_unit: LB
                      is_active: true
                    box_contents_submission: null
                    pallets_submission: null
                    can_confirm: false
                    confirm_blocked_reason: Box contents have not been submitted yet.
                    acknowledged_at: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-integrationinstance-draft-inbound-plans-fulfillment-portal-token
  /api/amazon/{integrationInstance}/draft-inbound-plans/fulfillment-portal/{token}/box-contents:
    post:
      tags:
      - Amazon
      summary: Submit Box Contents (3PL Portal)
      description: 'Anonymous 3PL portal submission of packed box contents. Access
        is granted by the opaque `:token` in the URL (the packet''s `portal_token`)
        — no bearer auth. The submission is stored verbatim on the packet''s `portal_submission.boxes`
        JSON.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Validation**

        - `boxes` — required array, 1..1000 boxes

        - `boxes.*.box_number` — required integer 1..100000, **distinct** across boxes

        - `boxes.*.length` / `boxes.*.width` / `boxes.*.height` — optional numeric
        0..1000000 (per-box carton dimensions)

        - `boxes.*.dimension_unit` — optional string, one of `IN`, `CM`

        - `boxes.*.weight` — optional numeric 0..1000000

        - `boxes.*.weight_unit` — optional string, one of `LB`, `KG`

        - `boxes.*.amazon_fba_carton_template_id` — optional integer, must exist in
        `amazon_fba_carton_templates` (provenance marker set when the 3PL picks a
        saved carton preset; kept even after manual dimension edits)

        - `boxes.*.lines` — required array, 1..1000 lines per box

        - `boxes.*.lines.*.sku` — required string, max 255

        - `boxes.*.lines.*.quantity` — required integer 1..1000000


        The dimension/weight fields are optional so a bare SKU+quantity submission
        still validates, but the portal offers the same full-featured box entry (carton
        presets + L×W×H + weight) the internal packing station uses. Returns the refreshed
        portal payload (same shape as `GET .../fulfillment-portal/:token`).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                boxes:
                  type: array
                  items:
                    type: object
                    properties:
                      box_number:
                        type: integer
                      amazon_fba_carton_template_id:
                        type: integer
                      length:
                        type: integer
                      width:
                        type: integer
                      height:
                        type: integer
                      dimension_unit:
                        type: string
                      weight:
                        type: number
                      weight_unit:
                        type: string
                      lines:
                        type: array
                        items:
                          type: object
                          properties:
                            sku:
                              type: string
                            quantity:
                              type: integer
              example:
                boxes:
                - box_number: 1
                  amazon_fba_carton_template_id: 7
                  length: 12
                  width: 10
                  height: 8
                  dimension_unit: IN
                  weight: 15.5
                  weight_unit: LB
                  lines:
                  - sku: SKU-A
                    quantity: 3
                  - sku: SKU-B
                    quantity: 2
                - box_number: 2
                  length: 18
                  width: 12
                  height: 10
                  dimension_unit: IN
                  weight: 22
                  weight_unit: LB
                  lines:
                  - sku: SKU-C
                    quantity: 5
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: token
        in: path
        schema:
          type: string
        required: true
        description: The token ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      reference:
                        type: string
                      fba_shipment_id:
                        type: string
                      source_name:
                        type: string
                      source_type:
                        type: string
                      destination_fc:
                        type: string
                      destination_address:
                        type: object
                        properties:
                          name:
                            type: string
                          addressLine1:
                            type: string
                          addressLine2:
                            type: string
                            nullable: true
                          city:
                            type: string
                          stateOrProvinceCode:
                            type: string
                          postalCode:
                            type: string
                          countryCode:
                            type: string
                      shipping_mode:
                        type: string
                      is_ltl:
                        type: boolean
                      requires_pallets:
                        type: boolean
                      status:
                        type: string
                      requested_by:
                        type: string
                      build_required:
                        type: boolean
                      kits_pending_build:
                        type: boolean
                      kit_build_manifest:
                        type: array
                      instructions:
                        type: string
                      documents:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            type:
                              type: string
                            type_label:
                              type: string
                            stage:
                              type: string
                            status:
                              type: string
                      products:
                        type: array
                        items:
                          type: object
                          properties:
                            product_id:
                              type: integer
                            sku:
                              type: string
                            name:
                              type: string
                            image_url:
                              type: string
                            msku:
                              type: string
                            fnsku:
                              type: string
                            quantity:
                              type: integer
                            barcode:
                              type: string
                              nullable: true
                            weight:
                              type: string
                              nullable: true
                            weight_unit:
                              type: string
                              nullable: true
                            length:
                              type: string
                              nullable: true
                            width:
                              type: string
                              nullable: true
                            height:
                              type: string
                              nullable: true
                            dimension_unit:
                              type: string
                              nullable: true
                      carton_templates:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            length:
                              type: integer
                            width:
                              type: integer
                            height:
                              type: integer
                            dimension_unit:
                              type: string
                            tare_weight:
                              type: number
                            weight_unit:
                              type: string
                            is_active:
                              type: boolean
                      box_contents_submission:
                        type: array
                        items:
                          type: object
                          properties:
                            box_number:
                              type: integer
                            amazon_fba_carton_template_id:
                              type: integer
                            length:
                              type: integer
                            width:
                              type: integer
                            height:
                              type: integer
                            dimension_unit:
                              type: string
                            weight:
                              type: number
                            weight_unit:
                              type: string
                            lines:
                              type: array
                              items:
                                type: object
                                properties:
                                  sku:
                                    type: string
                                  quantity:
                                    type: integer
                      pallets_submission:
                        type: string
                        nullable: true
                      can_confirm:
                        type: boolean
                      confirm_blocked_reason:
                        type: string
                        nullable: true
                      acknowledged_at:
                        type: string
                        nullable: true
                example:
                  message: Box contents submitted.
                  data:
                    reference: FBA-2026-000123
                    fba_shipment_id: FBA15ABCDEF
                    source_name: Acme 3PL Warehouse
                    source_type: 3pl
                    destination_fc: ONT8
                    destination_address:
                      name: Amazon.com
                      addressLine1: 24208 San Michele Rd
                      addressLine2: null
                      city: Moreno Valley
                      stateOrProvinceCode: CA
                      postalCode: '92551'
                      countryCode: US
                    shipping_mode: GROUND_SMALL_PARCEL
                    is_ltl: false
                    requires_pallets: false
                    status: in_progress
                    requested_by: Jane Buyer
                    build_required: false
                    kits_pending_build: false
                    kit_build_manifest: []
                    instructions: '# FBA Inbound Preparation Instructions

                      Shipment: FBA15ABCDEF

                      Ship to: Amazon ONT8


                      Pack each SKU into the boxes exactly as listed, label every
                      box, then confirm ready to ship.'
                    documents:
                    - id: 41
                      type: work_order
                      type_label: Kitting Work Order
                      stage: initial
                      status: ready
                    products:
                    - product_id: 5567
                      sku: SKU-A
                      name: Acme Widget - Blue
                      image_url: https://cdn.example.com/img/sku-a.jpg
                      msku: ACME-SKU-A
                      fnsku: X001ABCDEF
                      quantity: 24
                      barcode: null
                      weight: null
                      weight_unit: null
                      length: null
                      width: null
                      height: null
                      dimension_unit: null
                    - product_id: 5568
                      sku: SKU-B
                      name: Acme Widget - Red
                      image_url: null
                      msku: ACME-SKU-B
                      fnsku: X001GHIJKL
                      quantity: 12
                      barcode: null
                      weight: null
                      weight_unit: null
                      length: null
                      width: null
                      height: null
                      dimension_unit: null
                    carton_templates:
                    - id: 7
                      name: Standard 12x10x8
                      length: 12
                      width: 10
                      height: 8
                      dimension_unit: IN
                      tare_weight: 0.5
                      weight_unit: LB
                      is_active: true
                    - id: 8
                      name: Large 18x12x10
                      length: 18
                      width: 12
                      height: 10
                      dimension_unit: IN
                      tare_weight: 0.8
                      weight_unit: LB
                      is_active: true
                    box_contents_submission:
                    - box_number: 1
                      amazon_fba_carton_template_id: 7
                      length: 12
                      width: 10
                      height: 8
                      dimension_unit: IN
                      weight: 15.5
                      weight_unit: LB
                      lines:
                      - sku: SKU-A
                        quantity: 3
                      - sku: SKU-B
                        quantity: 2
                    - box_number: 2
                      length: 18
                      width: 12
                      height: 10
                      dimension_unit: IN
                      weight: 22
                      weight_unit: LB
                      lines:
                      - sku: SKU-C
                        quantity: 5
                    pallets_submission: null
                    can_confirm: true
                    confirm_blocked_reason: null
                    acknowledged_at: null
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      boxes.0.box_number:
                        type: array
                        items:
                          type: string
                      boxes.1.lines.0.quantity:
                        type: array
                        items:
                          type: string
                example:
                  message: The boxes.0.box_number field has a duplicate value.
                  errors:
                    boxes.0.box_number:
                    - The boxes.0.box_number field has a duplicate value.
                    boxes.1.lines.0.quantity:
                    - The boxes.1.lines.0.quantity field must be at least 1.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-amazon-integrationinstance-draft-inbound-plans-fulfillment-portal-token-box-contents
  /api/amazon/{integrationInstance}/draft-inbound-plans/fulfillment-portal/{token}/fnsku-labels:
    post:
      tags:
      - Amazon
      summary: Generate FNSKU Labels (3PL Portal)
      description: 'Generate FNSKU (MSKU) item labels on demand from the anonymous
        3PL/supplier portal. Token-gated — no bearer auth (`tenant.public-portal`
        middleware); returns 404 when the token is expired, rotated, or revoked.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Runs Amazon''s synchronous `createMarketplaceItemLabels` for the requested
        MSKU quantities and returns the short-lived label document `url` (open/download
        promptly — Amazon expires it) plus its `expiration`. The print is recorded
        in the label audit trail with no user (marking a portal print), a `fnsku_labels_generated`
        portal event is logged, and a durable copy is auto-attached to the packet''s
        FNSKU Labels document.


        **Body fields:**

        - `label_type` (required): `STANDARD_FORMAT` (letter/laser sheets) or `THERMAL_PRINTING`

        - `page_type` (required): one of Amazon''s createMarketplaceItemLabels page
        types — `Letter_30`, `A4_21`, `A4_24`, `A4_27`, `A4_44_48x25`, `A4_24_66x35`,
        `A4_24_64x33`, `A4_40_52x29`, `A4_24_70x36`, `A4_24_70x37`, `A4_24i`

        - `mskus` (required, min 1): array of `{msku, quantity}` — every `msku` must
        belong to the plan (422 otherwise), `quantity` ≥ 1'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                label_type:
                  type: string
                page_type:
                  type: string
                mskus:
                  type: array
                  items:
                    type: object
                    properties:
                      msku:
                        type: string
                      quantity:
                        type: integer
              example:
                label_type: STANDARD_FORMAT
                page_type: Letter_30
                mskus:
                - msku: ACME-SKU-A
                  quantity: 24
                - msku: ACME-SKU-B
                  quantity: 12
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Amazon integration instance id
        example: '1'
      - name: token
        in: path
        schema:
          type: string
        required: true
        description: The packet's opaque portal_token
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      url:
                        type: string
                      expiration:
                        type: string
                      label_print_id:
                        type: integer
                example:
                  data:
                    url: https://d1irx6qbteivpz.cloudfront.net/labels/item-labels-abc123.pdf
                    expiration: '2026-07-08T00:15:00Z'
                    label_print_id: 87
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      mskus.0.msku:
                        type: array
                        items:
                          type: string
                example:
                  message: MSKU "UNKNOWN-MSKU" is not part of this inbound plan.
                  errors:
                    mskus.0.msku:
                    - MSKU "UNKNOWN-MSKU" is not part of this inbound plan.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-amazon-integrationinstance-draft-inbound-plans-fulfillment-portal-token-fnsku-labels
  /api/amazon/{integrationInstance}/draft-inbound-plans/fulfillment-portal/{token}/pallets:
    post:
      tags:
      - Amazon
      summary: Submit Pallets (3PL Portal)
      description: 'Anonymous 3PL portal submission of LTL pallet details. Access
        is granted by the opaque `:token` in the URL (the packet''s `portal_token`)
        — no bearer auth. The submission is stored verbatim on the packet''s `portal_submission.pallets`
        JSON and is required before an LTL packet can be confirmed ready.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Validation**

        - `pallet_count` — required integer 1..1000

        - `pallets` — optional array, max 1000. A count-only submission (no `pallets`)
        is allowed; when `pallets` is supplied its length **must equal** `pallet_count`

        - `pallets.*.weight` — required numeric, > 0, max 5000

        - `pallets.*.height` — required numeric, > 0, max 200


        Returns the refreshed portal payload (same shape as `GET .../fulfillment-portal/:token`).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                pallet_count:
                  type: integer
                pallets:
                  type: array
                  items:
                    type: object
                    properties:
                      weight:
                        type: number
                      height:
                        type: integer
              example:
                pallet_count: 2
                pallets:
                - weight: 120.5
                  height: 48
                - weight: 98
                  height: 40
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: token
        in: path
        schema:
          type: string
        required: true
        description: The token ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      reference:
                        type: string
                      fba_shipment_id:
                        type: string
                      source_name:
                        type: string
                      source_type:
                        type: string
                      destination_fc:
                        type: string
                      shipping_mode:
                        type: string
                      is_ltl:
                        type: boolean
                      requires_pallets:
                        type: boolean
                      status:
                        type: string
                      requested_by:
                        type: string
                      build_required:
                        type: boolean
                      kits_pending_build:
                        type: boolean
                      kit_build_manifest:
                        type: array
                      instructions:
                        type: string
                      documents:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            type:
                              type: string
                            type_label:
                              type: string
                            stage:
                              type: string
                            status:
                              type: string
                      box_contents_submission:
                        type: array
                        items:
                          type: object
                          properties:
                            box_number:
                              type: integer
                            lines:
                              type: array
                              items:
                                type: object
                                properties:
                                  sku:
                                    type: string
                                  quantity:
                                    type: integer
                      pallets_submission:
                        type: object
                        properties:
                          pallet_count:
                            type: integer
                          pallets:
                            type: array
                            items:
                              type: object
                              properties:
                                weight:
                                  type: number
                                height:
                                  type: integer
                      can_confirm:
                        type: boolean
                      confirm_blocked_reason:
                        type: string
                        nullable: true
                      acknowledged_at:
                        type: string
                        nullable: true
                example:
                  message: Pallet details submitted.
                  data:
                    reference: FBA-2026-000124
                    fba_shipment_id: FBA15GHIJKL
                    source_name: Acme 3PL Warehouse
                    source_type: 3pl
                    destination_fc: LGB8
                    shipping_mode: FREIGHT_LTL
                    is_ltl: true
                    requires_pallets: true
                    status: in_progress
                    requested_by: Jane Buyer
                    build_required: false
                    kits_pending_build: false
                    kit_build_manifest: []
                    instructions: Palletize the boxes, record each pallet's weight
                      and height, then confirm ready to ship.
                    documents:
                    - id: 51
                      type: pallet_labels
                      type_label: Pallet Labels
                      stage: shipping
                      status: ready
                    box_contents_submission:
                    - box_number: 1
                      lines:
                      - sku: SKU-A
                        quantity: 3
                    pallets_submission:
                      pallet_count: 2
                      pallets:
                      - weight: 120.5
                        height: 48
                      - weight: 98
                        height: 40
                    can_confirm: true
                    confirm_blocked_reason: null
                    acknowledged_at: null
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      pallets:
                        type: array
                        items:
                          type: string
                      pallets.0.weight:
                        type: array
                        items:
                          type: string
                example:
                  message: The number of pallet detail rows must match the pallet
                    count.
                  errors:
                    pallets:
                    - The number of pallet detail rows must match the pallet count.
                    pallets.0.weight:
                    - The pallets.0.weight field must be greater than 0.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-amazon-integrationinstance-draft-inbound-plans-fulfillment-portal-token-pallets
  /api/amazon/{integrationInstance}/draft-inbound-plans/fulfillment-portal/{token}/documents/{document}/download:
    get:
      tags:
      - Amazon
      summary: Download Portal Document (3PL Portal)
      description: 'Downloads one of the fulfillment packet''s documents from the
        anonymous 3PL/supplier portal. Access is granted solely by the opaque `:token`
        in the URL (the packet''s portal token from the emailed link) — no bearer
        auth. `:document` is a document id from the `documents[]` array of the portal
        payload.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        This is a **file download**: renderable paperwork (prep instructions, box
        contents, kitting work order) is generated on demand and returned as a `text/plain`
        attachment; label documents (FNSKU/box/pallet labels), bill of lading, and
        other attached files are streamed from storage with their stored content type
        (typically `application/pdf`).


        Every download is audit-logged as a portal event. Errors are plain-text: 404
        when the token is expired, rotated, or revoked, or when the document does
        not belong to this packet; 422 when the document is not yet downloadable or
        its file has not been attached yet.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Amazon integration instance id
        example: '1'
      - name: token
        in: path
        schema:
          type: string
        required: true
        description: The packet's opaque portal access token from the emailed fulfillment
          link
      - name: document
        in: path
        schema:
          type: string
        required: true
        description: Document id from the portal payload's documents[] list
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: text/plain; charset=UTF-8
          content:
            text/plain:
              schema:
                type: string
                example: "KITTING WORK ORDER — FBA15ABCDEF\nKit: ACME-KIT-1 (Acme\
                  \ Widget Kit 2-pack) x 12\n  - SKU-A Acme Widget - Blue x 24\nBuild\
                  \ all kits, then confirm via the portal."
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: text/html; charset=UTF-8
          content:
            text/plain:
              schema:
                type: string
                example: This portal link is no longer valid.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: text/html; charset=UTF-8
          content:
            text/plain:
              schema:
                type: string
                example: This document is not yet available.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-amazon-integrationinstance-draft-inbound-plans-fulfillment-portal-token-documents-document-download
  /api/amazon/{integrationInstance}/draft-inbound-plans/fulfillment-portal/{token}/acknowledge:
    post:
      tags:
      - Amazon
      summary: Acknowledge Fulfillment Order (3PL Portal)
      description: 'Confirms, from the anonymous 3PL/supplier portal, that the fulfillment
        order is packed and ready to ship. Access is granted solely by the opaque
        `:token` in the URL (the packet''s portal token from the emailed link) — no
        bearer auth. No request body.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Gating: box contents must have been submitted first, and pallet details as
        well when the shipment moves LTL/freight — otherwise a 422 with error key
        `not_ready_to_confirm` explains what is missing (the same gating is exposed
        as `can_confirm` / `confirm_blocked_reason` on the portal payload).


        Side effects on success: any component-sourced kits not yet explicitly confirmed
        built are realized (idempotent backstop — confirming ready-to-ship implies
        the kits were built), the packet status moves to `acknowledged` with an `acknowledged_at`
        timestamp, and the confirmation is audit-logged as a portal event. Returns
        the refreshed portal payload.


        Returns 404 when the token is expired, rotated, or revoked.'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Amazon integration instance id
        example: '1'
      - name: token
        in: path
        schema:
          type: string
        required: true
        description: The packet's opaque portal access token from the emailed fulfillment
          link
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      reference:
                        type: string
                      fba_shipment_id:
                        type: string
                      source_name:
                        type: string
                      source_type:
                        type: string
                      destination_fc:
                        type: string
                      destination_address:
                        type: object
                        properties:
                          name:
                            type: string
                          addressLine1:
                            type: string
                          addressLine2:
                            type: string
                            nullable: true
                          city:
                            type: string
                          stateOrProvinceCode:
                            type: string
                          postalCode:
                            type: string
                          countryCode:
                            type: string
                      shipping_mode:
                        type: string
                      is_ltl:
                        type: boolean
                      requires_pallets:
                        type: boolean
                      status:
                        type: string
                      requested_by:
                        type: string
                      build_required:
                        type: boolean
                      kits_pending_build:
                        type: boolean
                      kit_build_manifest:
                        type: array
                      instructions:
                        type: string
                      prep_details:
                        type: string
                        nullable: true
                      documents:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            type:
                              type: string
                            type_label:
                              type: string
                            stage:
                              type: string
                            status:
                              type: string
                      products:
                        type: array
                        items:
                          type: object
                          properties:
                            product_id:
                              type: integer
                            sku:
                              type: string
                            name:
                              type: string
                            image_url:
                              type: string
                            msku:
                              type: string
                            fnsku:
                              type: string
                            barcode:
                              type: string
                            quantity:
                              type: integer
                            label_owner:
                              type: string
                            prep_owner:
                              type: string
                            weight:
                              type: number
                            weight_unit:
                              type: string
                            length:
                              type: number
                            width:
                              type: number
                            height:
                              type: number
                            dimension_unit:
                              type: string
                      carton_templates:
                        type: array
                      box_contents_submission:
                        type: array
                        items:
                          type: object
                          properties:
                            box_number:
                              type: integer
                            lines:
                              type: array
                              items:
                                type: object
                                properties:
                                  sku:
                                    type: string
                                  quantity:
                                    type: integer
                      pallets_submission:
                        type: string
                        nullable: true
                      can_confirm:
                        type: boolean
                      confirm_blocked_reason:
                        type: string
                        nullable: true
                      acknowledged_at:
                        type: string
                example:
                  message: Thank you — the shipment has been confirmed as ready.
                  data:
                    reference: FBA-2026-000123
                    fba_shipment_id: FBA15ABCDEF
                    source_name: Acme 3PL Warehouse
                    source_type: 3pl
                    destination_fc: ONT8
                    destination_address:
                      name: Amazon.com
                      addressLine1: 24208 San Michele Rd
                      addressLine2: null
                      city: Moreno Valley
                      stateOrProvinceCode: CA
                      postalCode: '92551'
                      countryCode: US
                    shipping_mode: GROUND_SMALL_PARCEL
                    is_ltl: false
                    requires_pallets: false
                    status: acknowledged
                    requested_by: Jane Buyer
                    build_required: false
                    kits_pending_build: false
                    kit_build_manifest: []
                    instructions: '# FBA Inbound Preparation Instructions

                      Shipment: FBA15ABCDEF

                      Ship to: Amazon ONT8


                      Pack each SKU into the boxes exactly as listed, label every
                      box, then confirm ready to ship.'
                    prep_details: null
                    documents:
                    - id: 41
                      type: work_order
                      type_label: Kitting Work Order
                      stage: initial
                      status: ready
                    - id: 44
                      type: box_labels
                      type_label: Box Labels
                      stage: mid
                      status: ready
                    products:
                    - product_id: 5567
                      sku: SKU-A
                      name: Acme Widget - Blue
                      image_url: https://cdn.example.com/img/sku-a.jpg
                      msku: ACME-SKU-A
                      fnsku: X001ABCDEF
                      barcode: '812345678901'
                      quantity: 24
                      label_owner: SELLER
                      prep_owner: SELLER
                      weight: 1.4
                      weight_unit: lb
                      length: 7.3
                      width: 4.9
                      height: 2.8
                      dimension_unit: in
                    carton_templates: []
                    box_contents_submission:
                    - box_number: 1
                      lines:
                      - sku: SKU-A
                        quantity: 24
                    pallets_submission: null
                    can_confirm: true
                    confirm_blocked_reason: null
                    acknowledged_at: '2026-07-07T16:20:00+00:00'
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: This portal link is no longer valid.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: object
                    properties:
                      not_ready_to_confirm:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                  message:
                    type: string
                example:
                  errors:
                    not_ready_to_confirm:
                    - message: Submit your box contents before confirming the shipment
                        is ready.
                  message: Submit your box contents before confirming the shipment
                    is ready.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-amazon-integrationinstance-draft-inbound-plans-fulfillment-portal-token-acknowledge
  /api/amazon/{integrationInstance}/draft-inbound-plans/fulfillment-portal/{token}/kits-built:
    post:
      tags:
      - Amazon
      summary: Confirm Kits Built (3PL Portal)
      description: 'Confirms, from the anonymous 3PL/supplier portal, that the kits
        on the fulfillment order have been physically assembled. Access is granted
        solely by the opaque `:token` in the URL (the packet''s portal token from
        the emailed link) — no bearer auth. No request body.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Side effects: the reserved kit components are converted into finished kit
        stock and the kits are allocated to their transfer lines; the confirmation
        is audit-logged as a portal event. The operation is idempotent — lines already
        built are skipped, and calling it when there is nothing to build is a safe
        no-op.


        Returns the refreshed portal payload (`kits_pending_build` becomes false;
        `kit_build_manifest` still lists what was built). Returns 404 when the token
        is expired, rotated, or revoked.'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Amazon integration instance id
        example: '1'
      - name: token
        in: path
        schema:
          type: string
        required: true
        description: The packet's opaque portal access token from the emailed fulfillment
          link
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      reference:
                        type: string
                      fba_shipment_id:
                        type: string
                      source_name:
                        type: string
                      source_type:
                        type: string
                      destination_fc:
                        type: string
                      destination_address:
                        type: object
                        properties:
                          name:
                            type: string
                          addressLine1:
                            type: string
                          addressLine2:
                            type: string
                            nullable: true
                          city:
                            type: string
                          stateOrProvinceCode:
                            type: string
                          postalCode:
                            type: string
                          countryCode:
                            type: string
                      shipping_mode:
                        type: string
                      is_ltl:
                        type: boolean
                      requires_pallets:
                        type: boolean
                      status:
                        type: string
                      requested_by:
                        type: string
                      build_required:
                        type: boolean
                      kits_pending_build:
                        type: boolean
                      kit_build_manifest:
                        type: array
                        items:
                          type: object
                          properties:
                            kit_sku:
                              type: string
                            kit_name:
                              type: string
                            quantity:
                              type: integer
                            components:
                              type: array
                              items:
                                type: object
                                properties:
                                  sku:
                                    type: string
                                  name:
                                    type: string
                                  quantity_per_kit:
                                    type: integer
                                  total_quantity:
                                    type: integer
                      instructions:
                        type: string
                      prep_details:
                        type: string
                        nullable: true
                      documents:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            type:
                              type: string
                            type_label:
                              type: string
                            stage:
                              type: string
                            status:
                              type: string
                      products:
                        type: array
                        items:
                          type: object
                          properties:
                            product_id:
                              type: integer
                            sku:
                              type: string
                            name:
                              type: string
                            image_url:
                              type: string
                            msku:
                              type: string
                            fnsku:
                              type: string
                            barcode:
                              type: string
                            quantity:
                              type: integer
                            label_owner:
                              type: string
                            prep_owner:
                              type: string
                            weight:
                              type: number
                            weight_unit:
                              type: string
                            length:
                              type: number
                            width:
                              type: number
                            height:
                              type: number
                            dimension_unit:
                              type: string
                      carton_templates:
                        type: array
                      box_contents_submission:
                        type: string
                        nullable: true
                      pallets_submission:
                        type: string
                        nullable: true
                      can_confirm:
                        type: boolean
                      confirm_blocked_reason:
                        type: string
                      acknowledged_at:
                        type: string
                        nullable: true
                example:
                  message: Thank you — the kits have been marked as built.
                  data:
                    reference: FBA-2026-000125
                    fba_shipment_id: FBA15KITSXY
                    source_name: Acme 3PL Warehouse
                    source_type: 3pl
                    destination_fc: ONT8
                    destination_address:
                      name: Amazon.com
                      addressLine1: 24208 San Michele Rd
                      addressLine2: null
                      city: Moreno Valley
                      stateOrProvinceCode: CA
                      postalCode: '92551'
                      countryCode: US
                    shipping_mode: GROUND_SMALL_PARCEL
                    is_ltl: false
                    requires_pallets: false
                    status: in_progress
                    requested_by: Jane Buyer
                    build_required: true
                    kits_pending_build: false
                    kit_build_manifest:
                    - kit_sku: ACME-KIT-1
                      kit_name: Acme Widget Kit (2-pack)
                      quantity: 12
                      components:
                      - sku: SKU-A
                        name: Acme Widget - Blue
                        quantity_per_kit: 2
                        total_quantity: 24
                    instructions: '# FBA Inbound Preparation Instructions

                      Shipment: FBA15ABCDEF

                      Ship to: Amazon ONT8


                      Pack each SKU into the boxes exactly as listed, label every
                      box, then confirm ready to ship.'
                    prep_details: null
                    documents:
                    - id: 41
                      type: work_order
                      type_label: Kitting Work Order
                      stage: initial
                      status: ready
                    - id: 44
                      type: box_labels
                      type_label: Box Labels
                      stage: mid
                      status: ready
                    products:
                    - product_id: 5567
                      sku: SKU-A
                      name: Acme Widget - Blue
                      image_url: https://cdn.example.com/img/sku-a.jpg
                      msku: ACME-SKU-A
                      fnsku: X001ABCDEF
                      barcode: '812345678901'
                      quantity: 24
                      label_owner: SELLER
                      prep_owner: SELLER
                      weight: 1.4
                      weight_unit: lb
                      length: 7.3
                      width: 4.9
                      height: 2.8
                      dimension_unit: in
                    carton_templates: []
                    box_contents_submission: null
                    pallets_submission: null
                    can_confirm: false
                    confirm_blocked_reason: Submit your box contents before confirming
                      the shipment is ready.
                    acknowledged_at: null
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: This portal link is no longer valid.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-amazon-integrationinstance-draft-inbound-plans-fulfillment-portal-token-kits-built
  /api/amazon/{integrationInstance}/draft-inbound-plans/{draft_inbound_plan}/list-prep-details:
    post:
      tags:
      - Amazon
      summary: List Prep Details
      description: 'Fetch Amazon''s prep requirements (prep category + prep types)
        for every MSKU on a draft inbound plan. SKU.io sends all of the plan''s MSKUs
        to Amazon''s listPrepDetails operation and returns the per-MSKU results. Backs
        the plan configuration step''s "Fetch Amazon Prep Requirements" action.


        Resilient to invalid MSKUs: Amazon 400-rejects the whole batch if any single
        MSKU is not recognised for the seller account. When that happens, SKU.io parses
        the rejected MSKUs, drops them, and retries with the remaining valid SKUs
        — so one bad SKU no longer dead-ends the whole step. The rejected SKUs are
        returned in the top-level `invalid_mskus` array (excluded from `data`) so
        the UI can prompt the user to remove or remap them.


        A 400 that is NOT an invalid-MSKU error (or that names SKUs we did not send)
        surfaces as a 422 ValidationException.


        Authentication: requires Bearer token.


        No request body — the MSKU list is derived from the plan''s line items.


        Response: `data` is an array of prep detail items (msku, prepCategory, prepTypes[],
        labelOwnerConstraint, prepOwnerConstraint, allOwnersConstraint); `invalid_mskus`
        is an array of the MSKU strings Amazon rejected as "not valid".


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Amazon integration instance id.
        example: '2'
      - name: draft_inbound_plan
        in: path
        schema:
          type: integer
        required: true
        description: Draft inbound plan id.
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        msku:
                          type: string
                        prepCategory:
                          type: string
                        prepTypes:
                          type: array
                        labelOwnerConstraint:
                          type: string
                        prepOwnerConstraint:
                          type: string
                        allOwnersConstraint:
                          type: string
                          nullable: true
                  invalid_mskus:
                    type: array
                    items:
                      type: string
                example:
                  data:
                  - msku: WIDGET-BLUE-01
                    prepCategory: NONE
                    prepTypes: []
                    labelOwnerConstraint: SELLER
                    prepOwnerConstraint: SELLER
                    allOwnersConstraint: null
                  - msku: GLASS-JAR-8OZ
                    prepCategory: FRAGILE
                    prepTypes:
                    - ITEM_BUBBLEWRAP
                    labelOwnerConstraint: SELLER
                    prepOwnerConstraint: SELLER
                    allOwnersConstraint: null
                  invalid_mskus:
                  - 100830-M
                  - 100831-M
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      mskus:
                        type: array
                        items:
                          type: string
                example:
                  message: The mskus field is invalid.
                  errors:
                    mskus:
                    - 'Amazon does not recognise the following SKUs: BADSKU-1. Remove
                      them from the draft plan, or re-create them in Seller Central,
                      then try again.'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-amazon-integrationinstance-draft-inbound-plans-draft-inbound-plan-list-prep-details
  /api/amazon/{integrationInstance}/draft-inbound-plans/{draft_inbound_plan}/activity-log:
    get:
      tags:
      - Amazon
      summary: Get Draft Plan Activity Log
      description: 'Paginated activity log for a draft FBA inbound plan, rolling up
        activity recorded on the plan itself and on each of its line items into a
        single stream ordered newest first.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Each entry contains `id`, `description`, `event` (e.g. `created`, `updated`,
        `deleted`), `subject_type` (short type name of the record the event was recorded
        on — the plan or one of its line items), `subject_id`, `properties` (the recorded
        attribute changes, typically `{attributes: {...}, old: {...}}`), `causer_name`
        (the acting user, null for system events), and `created_at` (UTC datetime).


        Query parameters: `page` (default 1), `per_page` (default 15), and `filter[search]`
        — a free-text search matched against the acting user''s name, the event, the
        serialized property changes, and the subject type. Standard pagination metadata
        (`current_page`, `last_page`, `per_page`, `total`, `links`, ...) is included
        in the response.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Amazon integration instance id
        example: '1'
      - name: draft_inbound_plan
        in: path
        schema:
          type: string
        required: true
        description: Draft inbound plan id
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        description:
                          type: string
                        event:
                          type: string
                        subject_type:
                          type: string
                        subject_id:
                          type: integer
                        properties:
                          type: object
                          properties:
                            attributes:
                              type: object
                              properties:
                                quantity:
                                  type: integer
                            old:
                              type: object
                              properties:
                                quantity:
                                  type: integer
                        causer_name:
                          type: string
                        created_at:
                          type: string
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                    items:
                      type: object
                      properties:
                        url:
                          type: string
                          nullable: true
                        label:
                          type: string
                        active:
                          type: boolean
                  next_page_url:
                    type: string
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 9182
                    description: updated
                    event: updated
                    subject_type: DraftAmazonFbaInboundPlanItem
                    subject_id: 4411
                    properties:
                      attributes:
                        quantity: 24
                      old:
                        quantity: 12
                    causer_name: Jane Buyer
                    created_at: '2026-07-01T18:42:11.000000Z'
                  - id: 9169
                    description: created
                    event: created
                    subject_type: DraftAmazonFbaInboundPlan
                    subject_id: 512
                    properties:
                      attributes:
                        name: FBA-2026-000123
                        status: draft
                    causer_name: Jane Buyer
                    created_at: '2026-06-30T15:03:27.000000Z'
                  first_page_url: '{{protocol}}://{{domain}}/api/amazon/1/draft-inbound-plans/512/activity-log?page=1'
                  from: 1
                  last_page: 3
                  last_page_url: '{{protocol}}://{{domain}}/api/amazon/1/draft-inbound-plans/512/activity-log?page=3'
                  links:
                  - url: null
                    label: '&laquo; Previous'
                    active: false
                  - url: '{{protocol}}://{{domain}}/api/amazon/1/draft-inbound-plans/512/activity-log?page=1'
                    label: '1'
                    active: true
                  - url: '{{protocol}}://{{domain}}/api/amazon/1/draft-inbound-plans/512/activity-log?page=2'
                    label: '2'
                    active: false
                  - url: '{{protocol}}://{{domain}}/api/amazon/1/draft-inbound-plans/512/activity-log?page=2'
                    label: Next &raquo;
                    active: false
                  next_page_url: '{{protocol}}://{{domain}}/api/amazon/1/draft-inbound-plans/512/activity-log?page=2'
                  path: '{{protocol}}://{{domain}}/api/amazon/1/draft-inbound-plans/512/activity-log'
                  per_page: 15
                  prev_page_url: null
                  to: 15
                  total: 34
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-integrationinstance-draft-inbound-plans-draft-inbound-plan-activity-log
  /api/amazon/{integrationInstance}/draft-inbound-plans/{draft_inbound_plan}/download-inventory-inquiry-pdf:
    get:
      tags:
      - Amazon
      summary: Download Inventory Inquiry PDF
      description: 'Generates and downloads the inventory inquiry PDF for the draft
        inbound plan. The document lists every plan item (with product image, SKU,
        MSKU and requested quantity), the source warehouse/supplier details, and embeds
        a QR code linking to the shareable verification portal so the supplier can
        verify quantities on their phone.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        The response is a binary `application/pdf` attachment (`Content-Disposition:
        attachment`) named `inventory-inquiry-<plan-name-slug>.pdf`. No request body
        or query parameters.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Amazon integration instance id
        example: '1'
      - name: draft_inbound_plan
        in: path
        schema:
          type: string
        required: true
        description: Draft inbound plan id
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/pdf
          content:
            text/plain:
              schema:
                type: string
                example: '%PDF-1.7

                  % Binary PDF content — inventory-inquiry-fba-2026-000123.pdf (truncated
                  example)'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-integrationinstance-draft-inbound-plans-draft-inbound-plan-download-inventory-inquiry-pdf
  /api/amazon/{integrationInstance}/draft-inbound-plans/{draft_inbound_plan}/portal-access-hash:
    get:
      tags:
      - Amazon
      summary: Get Portal Access Hash
      description: 'Returns the encrypted plan identifier (`hashed_id`) used to build
        the shareable, unauthenticated verification portal URL for this draft inbound
        plan. The portal lets a supplier verify item quantities without logging in.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        The hash is an encrypted payload of the plan id; append it to the verification
        portal path (`/v2/integrations/amazon/fba/draft-inbound-plans/verification-portal/{hashed_id}?integration={integrationInstance}`)
        and share the resulting link. The same hash is embedded in the inventory inquiry
        email and the QR code on the inventory inquiry PDF. No request body or query
        parameters.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Amazon integration instance id
        example: '1'
      - name: draft_inbound_plan
        in: path
        schema:
          type: string
        required: true
        description: Draft inbound plan id
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      hashed_id:
                        type: string
                example:
                  data:
                    hashed_id: eyJpdiI6IlR2bXhOc2JQZk9rZz09IiwidmFsdWUiOiJkR0Z6ZEdWeVpYTjBaWEp1YldWaGJHbHVaUT09IiwibWFjIjoiOWY0YjFjMGEzZTc3NGIxZThhM2Q2YTJiMWM5ZDBlNWYiLCJ0YWciOiIifQ==
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-integrationinstance-draft-inbound-plans-draft-inbound-plan-portal-access-hash
  /api/amazon/{integrationInstance}/draft-inbound-plans/{draft_inbound_plan}/send-inventory-inquiry:
    get:
      tags:
      - Amazon
      summary: Send Inventory Inquiry
      description: 'Sends the inventory inquiry email for the draft inbound plan.
        **Note: although this is a GET request, it has a side effect — calling it
        sends an email** and updates the plan.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        The email goes to the plan''s source: for a supplier warehouse, the supplier''s
        purchase-order email (falling back to the supplier''s main email); otherwise
        the source warehouse address email. It contains the plan''s item list and
        a link to the unauthenticated verification portal where the recipient confirms
        available quantities.


        Side effects on success: the plan''s inventory-inquiry sent timestamp is stamped,
        the sending user is recorded, and the plan status moves to `verification_in_progress`.


        Errors: when no recipient email is on file for the source, the response carries
        an `inventory_inquiry_missing_email` error instead of sending.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Amazon integration instance id
        example: '1'
      - name: draft_inbound_plan
        in: path
        schema:
          type: string
        required: true
        description: Draft inbound plan id
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Inventory inquiry email sent successfully.
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      inventory_inquiry_missing_email:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                example:
                  message: No email found to send the inventory inquiry to.
                  errors:
                    inventory_inquiry_missing_email:
                    - message: No email found to send the inventory inquiry to.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-integrationinstance-draft-inbound-plans-draft-inbound-plan-send-inventory-inquiry
  /api/amazon/{integrationInstance}/draft-inbound-plans/{draft_inbound_plan}/set-prep-details:
    post:
      tags:
      - Amazon
      summary: Set Prep Details
      description: 'Sets Amazon SP-API prep details (prep category + prep types) for
        MSKUs on the draft inbound plan whose prep category is unknown. The request
        is forwarded to Amazon''s `setPrepDetails` operation for the plan''s marketplace
        (derived from the destination warehouse''s country); Amazon''s raw response
        (an `operationId` you can use to correlate the asynchronous SP-API operation)
        is returned under `data`.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Request body fields:

        - `mskuPrepDetails` (array, required) — one entry per MSKU

        - `mskuPrepDetails[].msku` (string, required) — the Amazon seller SKU

        - `mskuPrepDetails[].prepCategory` (string, required) — one of `ADULT`, `BABY`,
        `FC_PROVIDED`, `FRAGILE`, `GRANULAR`, `HANGER`, `LIQUID`, `NONE`, `PERFORATED`,
        `SET`, `SHARP`, `SMALL`, `TEXTILE`

        - `mskuPrepDetails[].prepTypes` (array of strings, required) — SP-API prep
        types (e.g. `ITEM_POLYBAGGING`, `ITEM_BUBBLEWRAP`, `ITEM_LABELING`, `ITEM_NO_PREP`)


        Business rule: when `prepCategory` is `NONE`, `prepTypes` must include `ITEM_NO_PREP`
        (422 otherwise). A 422 is also returned when Amazon rejects the request.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                mskuPrepDetails:
                  type: array
                  items:
                    type: object
                    properties:
                      msku:
                        type: string
                      prepCategory:
                        type: string
                      prepTypes:
                        type: array
                        items:
                          type: string
              example:
                mskuPrepDetails:
                - msku: ACME-WIDGET-BLUE-FBA
                  prepCategory: FRAGILE
                  prepTypes:
                  - ITEM_BUBBLEWRAP
                  - ITEM_LABELING
                - msku: ACME-WIDGET-RED-FBA
                  prepCategory: NONE
                  prepTypes:
                  - ITEM_NO_PREP
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Amazon integration instance id
        example: '1'
      - name: draft_inbound_plan
        in: path
        schema:
          type: string
        required: true
        description: Draft inbound plan id
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      operationId:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    operationId: 1f4c3a9e-8f21-4a2c-b0d3-7e5a9c1b2d43
                  message: Prep details set successfully.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      prepTypes:
                        type: array
                        items:
                          type: string
                example:
                  message: 'MSKU ACME-WIDGET-RED-FBA: When prepCategory is NONE, ITEM_NO_PREP
                    must be included in prepTypes.'
                  errors:
                    prepTypes:
                    - 'MSKU ACME-WIDGET-RED-FBA: When prepCategory is NONE, ITEM_NO_PREP
                      must be included in prepTypes.'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-amazon-integrationinstance-draft-inbound-plans-draft-inbound-plan-set-prep-details
  /api/amazon/{integrationInstance}/draft-inbound-plans/{draft_inbound_plan}/verify-all-products-internal:
    post:
      tags:
      - Amazon
      summary: Verify All Products (Internal)
      description: 'Marks every item on the draft inbound plan as verified at its
        full planned quantity, without going through the supplier verification portal.
        Use this when the operator already knows the source quantities are correct
        and wants to skip the emailed inventory inquiry round-trip.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        This is the authenticated counterpart of the portal''s verify-all action:
        each plan item''s verified quantity is set to its planned quantity. No request
        body or query parameters.'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Amazon integration instance id
        example: '1'
      - name: draft_inbound_plan
        in: path
        schema:
          type: string
        required: true
        description: Draft inbound plan id
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: All products successfully verified
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-amazon-integrationinstance-draft-inbound-plans-draft-inbound-plan-verify-all-products-internal
  /api/amazon/{integrationInstance}/inbound-products/{countryCode}:
    get:
      tags:
      - Amazon
      summary: Search Inbound Products by Country
      description: 'Searches products eligible for FBA inbound shipping on this integration
        instance, scoped to one marketplace country. Backed by the mapped Amazon listings
        joined with current FBA inventory, so each row carries the Amazon identifiers
        plus live FBA quantity buckets.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Path parameter `countryCode` is the marketplace country code (e.g. `US`, `CA`).
        Query parameter `query` (optional) does a partial match against product SKU,
        MSKU, ASIN, FNSKU, or product name; omit it to list all inbound-eligible products
        for the country.


        Each result includes identifiers (`msku`, `asin`, `fnsku`, `product_id`, `product_sku`,
        `product_name`, `product_image`, `country_code`), FBA quantity buckets (`warehouse_quantity`,
        `fulfillable_quantity`, `unsellable_quantity`, `reserved_quantity`, `inbound_quantity`,
        `inbound_working_quantity`, `inbound_shipped_quantity`, `inbound_receiving_quantity`),
        inbound ownership defaults (`label_owner`, `prep_owner` — `AMAZON` | `SELLER`
        | `NONE`), case-pack settings (`case_pack_qty`, `case_pack_rounding`), and
        unit measurements with derived metrics (`weight`, `weight_unit`, `weight_estimated`,
        `length`, `width`, `height`, `dimension_unit`, `dims_estimated`, `unit_weight_lb`,
        `unit_volume_cuft`, `unit_cost`, `size_tier`). `source_quantity` is null here
        — it is only populated by the plan-scoped product search, which computes availability
        at the plan''s source warehouse. Returns the full (non-paginated) matching
        list.


        Each product includes an eligibility object { shippable: bool, reason: string|null
        } — false with a reason when the SKU can''t be inbounded (no FNSKU, removed
        from Amazon, or an inactive listing).'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Amazon integration instance id
        example: '1'
      - name: countryCode
        in: path
        schema:
          type: string
        required: true
        description: Marketplace country code (e.g. US, CA, MX, GB, DE, AU)
        example: US
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        msku:
                          type: string
                        asin:
                          type: string
                        fnsku:
                          type: string
                        product_id:
                          type: integer
                        product_sku:
                          type: string
                        product_name:
                          type: string
                        product_image:
                          type: string
                        country_code:
                          type: string
                        warehouse_quantity:
                          type: integer
                        fulfillable_quantity:
                          type: integer
                        unsellable_quantity:
                          type: integer
                        reserved_quantity:
                          type: integer
                        inbound_quantity:
                          type: integer
                        inbound_working_quantity:
                          type: integer
                        inbound_shipped_quantity:
                          type: integer
                        inbound_receiving_quantity:
                          type: integer
                        label_owner:
                          type: string
                        prep_owner:
                          type: string
                        source_quantity:
                          type: string
                          nullable: true
                        case_pack_qty:
                          type: integer
                        case_pack_rounding:
                          type: string
                        weight:
                          type: number
                        weight_unit:
                          type: string
                        weight_estimated:
                          type: boolean
                        length:
                          type: number
                        width:
                          type: number
                        height:
                          type: number
                        dimension_unit:
                          type: string
                        dims_estimated:
                          type: boolean
                        unit_weight_lb:
                          type: number
                        unit_volume_cuft:
                          type: number
                        unit_cost:
                          type: number
                        size_tier:
                          type: string
                example:
                  data:
                  - msku: ACME-WIDGET-BLUE-FBA
                    asin: B0EXAMPLE1
                    fnsku: X002ABCDE1
                    product_id: 1979
                    product_sku: '80707522'
                    product_name: Acme Widget - Blue
                    product_image: https://cdn.example.com/img/80707522.jpg
                    country_code: US
                    warehouse_quantity: 71
                    fulfillable_quantity: 65
                    unsellable_quantity: 0
                    reserved_quantity: 6
                    inbound_quantity: 12
                    inbound_working_quantity: 12
                    inbound_shipped_quantity: 0
                    inbound_receiving_quantity: 0
                    label_owner: SELLER
                    prep_owner: SELLER
                    source_quantity: null
                    case_pack_qty: 12
                    case_pack_rounding: always_round_down
                    weight: 1.4
                    weight_unit: lb
                    weight_estimated: false
                    length: 7.3
                    width: 4.9
                    height: 2.8
                    dimension_unit: in
                    dims_estimated: false
                    unit_weight_lb: 1.4
                    unit_volume_cuft: 0.0579
                    unit_cost: 6.85
                    size_tier: standard
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-integrationinstance-inbound-products-countrycode
  /api/amazon/{integrationInstance}/new-inbound/plans/refresh:
    post:
      tags:
      - Amazon
      summary: Refresh Inbound Plans
      description: 'Refreshes the integration''s FBA inbound plans from Amazon. The
        request synchronously pulls inbound plan summaries from the SP-API — first
        plans in `SHIPPED` status, then `ACTIVE` (some active plans already have shipments)
        — and upserts them, along with the ship-from address mappings found on those
        plans.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        It then queues background jobs that download each plan''s full details, line
        items, and shipments, so plan data keeps loading after the response returns;
        there is no job id to poll — re-query the inbound plan list to see updated
        data. No request body or query parameters.


        Because the summary fetch calls Amazon synchronously, the response can take
        several seconds on accounts with many plans.'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Amazon integration instance id
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Inbound plans downloading...
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-amazon-integrationinstance-new-inbound-plans-refresh
  /api/amazon/{integrationInstance}/draft-inbound-plans/items/{draft_inbound_plan}/add-item:
    post:
      tags:
      - Amazon
      summary: Add Item to Draft Plan
      description: 'Add an item to a draft FBA inbound plan.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Fields:**

        - `product_id` (integer, required) — SKU product id

        - `msku` (string, required) — Amazon merchant SKU

        - `quantity` (integer, required) — units to send

        - `kit_fulfillment_mode` (string, optional) — for kit products only: `kit_stock`
        (ship pre-built kit stock) or `components` (the source assembles the kit from
        component stock; components are allocated at verify and convert to the kit
        when the source confirms the build).

        - `case_pack_qty` (integer, optional, nullable) — case pack size to snapshot
        onto this line. Defaults to the product''s current case pack size when omitted.

        - `case_pack_rounding` (string, optional, nullable) — rounding strategy snapshot
        for this line: `always_round_up`, `always_round_down`, or `round_nearest`.
        Defaults to the product''s current case pack rounding setting when omitted.


        **Smart default:** when `kit_fulfillment_mode` is omitted and the product
        is a kit sourced from a non-supplier warehouse, the mode defaults to `components`
        if pre-built kit stock cannot cover the quantity but component stock can assemble
        it. Pass the field explicitly to override.


        The response includes `is_kit`, `kit_fulfillment_mode`, `kit_availability`
        (kit stock on hand, max buildable from components, bottleneck component),
        and the snapshotted `case_pack_qty` / `case_pack_rounding`.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                product_id:
                  type: integer
                msku:
                  type: string
                quantity:
                  type: integer
                kit_fulfillment_mode:
                  type: string
                case_pack_qty:
                  type: integer
                case_pack_rounding:
                  type: string
              example:
                product_id: 42
                msku: GSL392-KIT
                quantity: 30
                kit_fulfillment_mode: components
                case_pack_qty: 12
                case_pack_rounding: always_round_up
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: draft_inbound_plan
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The draft inbound plan ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      product_id:
                        type: integer
                      quantity:
                        type: integer
                      case_pack_qty:
                        type: integer
                      case_pack_rounding:
                        type: string
                example:
                  data:
                    id: 5
                    product_id: 42
                    quantity: 100
                    case_pack_qty: 12
                    case_pack_rounding: always_round_up
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-amazon-integrationinstance-draft-inbound-plans-items-draft-inbound-plan-add-item
  /api/amazon/{integrationInstance}/draft-inbound-plans/items/{draft_inbound_plan}/bulk-add:
    post:
      tags:
      - Amazon
      summary: Bulk Add Items to Draft Plan
      description: 'Bulk add items to a draft FBA inbound plan. Items already on the
        plan (matched by MSKU) are skipped unless `replace_existing` is true, in which
        case their quantity is updated.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Each item accepts the same fields as **Add Item to Draft Plan** (`product_id`,
        `msku`, `quantity`, `kit_fulfillment_mode`, `case_pack_qty`, `case_pack_rounding`)
        — `case_pack_qty`/`case_pack_rounding` are optional per-item overrides; when
        omitted they default to the product''s current case pack settings.


        **Kit smart default:** each added kit product sourced from a non-supplier
        warehouse defaults `kit_fulfillment_mode` to `components` when pre-built kit
        stock cannot cover the requested quantity but component stock can assemble
        it (the source builds the kits; components are allocated at verify). Other
        lines default to shipping stock as-is.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                items:
                  type: array
                  items:
                    type: object
                    properties:
                      product_id:
                        type: integer
                      quantity:
                        type: integer
                      case_pack_qty:
                        type: integer
                      case_pack_rounding:
                        type: string
              example:
                items:
                - product_id: 42
                  quantity: 100
                  case_pack_qty: 12
                  case_pack_rounding: always_round_up
                - product_id: 43
                  quantity: 50
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: draft_inbound_plan
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The draft inbound plan ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        product_id:
                          type: integer
                        case_pack_qty:
                          type: integer
                        case_pack_rounding:
                          type: string
                example:
                  message: 2 items added
                  data:
                  - id: 5
                    product_id: 42
                    case_pack_qty: 12
                    case_pack_rounding: always_round_up
                  - id: 6
                    product_id: 43
                    case_pack_qty: null
                    case_pack_rounding: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-amazon-integrationinstance-draft-inbound-plans-items-draft-inbound-plan-bulk-add
  /api/amazon/{integrationInstance}/draft-inbound-plans/items/{draft_inbound_plan_item}:
    patch:
      tags:
      - Amazon
      summary: Update Item
      description: 'Update a single draft plan item.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Auth: Requires Bearer token.


        Body fields (all optional — only provided fields are updated):

        - product_id (int)

        - msku (string)

        - quantity (int)

        - label_owner (string|null)

        - prep_owner (string|null)

        - expiration (date|null)

        - manufacturing_lot_code (string|null)

        - kit_fulfillment_mode (string|null): how a KIT line is fulfilled from the
        source warehouse — `kit_stock` (ship existing pre-built kit stock as-is) or
        `components` (assemble the kit from component stock at the source warehouse
        when the plan is verified/allocated). Only meaningful for kit products with
        a non-supplier (3PL/direct) source; ignored otherwise.

        - case_pack_qty (int|null): case pack size snapshot for this line.

        - case_pack_rounding (string|null): rounding strategy snapshot for this line
        — `always_round_up`, `always_round_down`, or `round_nearest`.


        Returns the updated item, including `product_id`, `is_kit`, `kit_fulfillment_mode`,
        `kit_availability` (live kit-on-hand vs buildable-from-components, with the
        bottleneck component), and `case_pack_qty` / `case_pack_rounding` for kit
        lines.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                quantity:
                  type: integer
                kit_fulfillment_mode:
                  type: string
                case_pack_qty:
                  type: integer
                case_pack_rounding:
                  type: string
              example:
                quantity: 150
                kit_fulfillment_mode: components
                case_pack_qty: 12
                case_pack_rounding: always_round_up
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: draft_inbound_plan_item
        in: path
        schema:
          type: integer
        required: true
        example: '5'
        description: The draft inbound plan item ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      product_id:
                        type: integer
                      is_kit:
                        type: boolean
                      kit_fulfillment_mode:
                        type: string
                      kit_availability:
                        type: object
                        properties:
                          is_kit:
                            type: boolean
                          kit_on_hand:
                            type: integer
                          buildable_from_components:
                            type: integer
                          bottleneck_component:
                            type: object
                            properties:
                              product_id:
                                type: integer
                              sku:
                                type: string
                              name:
                                type: string
                              available:
                                type: integer
                              required_per_kit:
                                type: integer
                              buildable:
                                type: integer
                          components:
                            type: array
                            items:
                              type: object
                              properties:
                                product_id:
                                  type: integer
                                sku:
                                  type: string
                                name:
                                  type: string
                                available:
                                  type: integer
                                required_per_kit:
                                  type: integer
                                buildable:
                                  type: integer
                      product:
                        type: object
                        properties:
                          id:
                            type: integer
                          sku:
                            type: string
                          name:
                            type: string
                          image_url:
                            type: string
                            nullable: true
                      amazon_product_id:
                        type: integer
                      quantity:
                        type: integer
                      msku:
                        type: string
                      fnsku:
                        type: string
                      label_owner:
                        type: string
                      prep_owner:
                        type: string
                      expiration:
                        type: string
                        nullable: true
                      manufacturing_lot_code:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      verified_quantity:
                        type: string
                        nullable: true
                      source_quantity:
                        type: string
                      warehouse_quantity:
                        type: integer
                      fulfillable_quantity:
                        type: integer
                      unsellable_quantity:
                        type: integer
                      reserved_quantity:
                        type: integer
                      inbound_quantity:
                        type: integer
                      inbound_working_quantity:
                        type: integer
                      inbound_shipped_quantity:
                        type: integer
                      inbound_receiving_quantity:
                        type: integer
                      case_pack_qty:
                        type: integer
                      case_pack_rounding:
                        type: string
                example:
                  data:
                    id: 5
                    product_id: 42
                    is_kit: true
                    kit_fulfillment_mode: components
                    kit_availability:
                      is_kit: true
                      kit_on_hand: 0
                      buildable_from_components: 12
                      bottleneck_component:
                        product_id: 88
                        sku: COMP-A
                        name: Component A
                        available: 24
                        required_per_kit: 2
                        buildable: 12
                      components:
                      - product_id: 88
                        sku: COMP-A
                        name: Component A
                        available: 24
                        required_per_kit: 2
                        buildable: 12
                      - product_id: 89
                        sku: COMP-B
                        name: Component B
                        available: 60
                        required_per_kit: 1
                        buildable: 60
                    product:
                      id: 42
                      sku: KIT-001
                      name: Starter Kit
                      image_url: null
                    amazon_product_id: 17
                    quantity: 150
                    msku: KIT-001-FBA
                    fnsku: X00ABCDEF
                    label_owner: SELLER
                    prep_owner: SELLER
                    expiration: null
                    manufacturing_lot_code: null
                    created_at: '2026-06-18T12:00:00.000000Z'
                    updated_at: '2026-06-21T12:05:00.000000Z'
                    verified_quantity: null
                    source_quantity: '120'
                    warehouse_quantity: 120
                    fulfillable_quantity: 100
                    unsellable_quantity: 0
                    reserved_quantity: 5
                    inbound_quantity: 30
                    inbound_working_quantity: 10
                    inbound_shipped_quantity: 15
                    inbound_receiving_quantity: 5
                    case_pack_qty: 12
                    case_pack_rounding: always_round_up
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: patch-api-amazon-integrationinstance-draft-inbound-plans-items-draft-inbound-plan-item
    delete:
      tags:
      - Amazon
      summary: Remove Item from Draft Plan
      description: 'Remove an item from a draft FBA inbound plan.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: draft_inbound_plan_item
        in: path
        schema:
          type: integer
        required: true
        example: '5'
        description: The draft inbound plan item ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Item removed
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-amazon-integrationinstance-draft-inbound-plans-items-draft-inbound-plan-item
  /api/amazon/{integrationInstance}/draft-inbound-plans/items/bulk-update:
    patch:
      tags:
      - Amazon
      summary: Bulk Update Items
      description: 'Bulk update draft plan items.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                items:
                  type: array
                  items:
                    type: object
                    properties:
                      id:
                        type: integer
                      quantity:
                        type: integer
              example:
                items:
                - id: 5
                  quantity: 150
                - id: 6
                  quantity: 75
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 2 items updated
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: patch-api-amazon-integrationinstance-draft-inbound-plans-items-bulk-update
  /api/amazon/{integrationInstance}/initial-inventory/{initialInventory}:
    get:
      tags:
      - Amazon
      summary: Show Initial Inventory
      description: 'Get a specific initial inventory record.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: initialInventory
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The initial inventory ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      fnsku:
                        type: string
                      quantity:
                        type: integer
                      unit_cost:
                        type: number
                example:
                  data:
                    id: 1
                    fnsku: X001ABC123
                    quantity: 500
                    unit_cost: 12.5
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-integrationinstance-initial-inventory-initialinventory
  /api/amazon/{integrationInstance}/initial-inventory/{initialInventory}/reconcile:
    post:
      tags:
      - Amazon
      summary: Reconcile Initial Inventory
      description: 'Reconcile a specific initial inventory record.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: initialInventory
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The initial inventory ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Initial inventory reconciled
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-amazon-integrationinstance-initial-inventory-initialinventory-reconcile
  /api/amazon/{integrationInstance}/initial-inventory/{initialInventory}/unreconcile:
    post:
      tags:
      - Amazon
      summary: Unreconcile Initial Inventory
      description: 'Unreconcile a specific initial inventory record.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: initialInventory
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The initial inventory ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Initial inventory unreconciled
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-amazon-integrationinstance-initial-inventory-initialinventory-unreconcile
  /api/amazon/{integrationInstance}/initial-inventory/reconcile-all:
    post:
      tags:
      - Amazon
      summary: Reconcile All Initial Inventory
      description: 'Reconcile all initial inventory records.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: All initial inventory reconciled
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-amazon-integrationinstance-initial-inventory-reconcile-all
  /api/amazon/{integrationInstance}/initial-inventory/reconcile:
    post:
      tags:
      - Amazon
      summary: Reconcile Initial Inventories (Batch)
      description: 'Reconcile specific initial inventory records.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1
                - 2
                - 3
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Initial inventories reconciled
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-amazon-integrationinstance-initial-inventory-reconcile
  /api/amazon/{integrationInstance}/initial-inventory/unreconcile-all:
    post:
      tags:
      - Amazon
      summary: Unreconcile All Initial Inventory
      description: 'Unreconcile all initial inventory records.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: All initial inventory unreconciled
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-amazon-integrationinstance-initial-inventory-unreconcile-all
  /api/amazon/{integrationInstance}/initial-inventory/reconcile-for-fnskus:
    post:
      tags:
      - Amazon
      summary: Reconcile Initial Inventories for FNSKUs
      description: 'Reconcile initial inventories for specific FNSKU products.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                fnsku_product_ids:
                  type: array
                  items:
                    type: integer
              example:
                fnsku_product_ids:
                - 1
                - 2
                - 3
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Initial inventories reconciled for FNSKUs
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-amazon-integrationinstance-initial-inventory-reconcile-for-fnskus
  /api/amazon/{integrationInstance}/initial-inventory/unreconcile:
    post:
      tags:
      - Amazon
      summary: Unreconcile Initial Inventories (Batch)
      description: 'Unreconcile specific initial inventory records.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1
                - 2
                - 3
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Initial inventories unreconciled
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-amazon-integrationinstance-initial-inventory-unreconcile
  /api/amazon/unified/initial-inventory:
    get:
      tags:
      - Amazon
      summary: List Initial Inventory (Across Instances)
      description: "Returns paginated FBA initial inventory rows across all Amazon\
        \ integration instances. Initial inventory is the FBA warehouse balance snapshot\
        \ captured at the account's inventory tracking start date, used to seed FIFO\
        \ cost layers and reconcile early ledger activity.\n\n:::info[Authorization]\n\
        Any valid API token can call this endpoint — no specific scope required. [Manage\
        \ tokens](https://app.sku.io/settings/api).\n:::\n\nThis route accepts both\
        \ GET and POST with identical behavior - send the same parameters as a JSON\
        \ body via POST when the filter payload is too long for a query string (e.g.\
        \ a large `filter_groups` tree). Only this GET request is documented; do not\
        \ treat POST as a separate operation.\n\nQuery parameters:\n- `page` (default\
        \ 1), `per_page` (default 10).\n- `sort` - allowed fields: `id`, `fnsku`,\
        \ `asin`, `msku`, `disposition`, `ending_warehouse_balance`, `location`, `created_at`\
        \ (prefix `-` for descending).\n- `filter[integration_instance_ids]` - comma-separated\
        \ instance IDs.\n- `filter[search]` - matches fnsku, asin, msku, title, or\
        \ integration instance name.\n- Operator filters using `filter[column.operator]=value`\
        \ syntax:\n  - Text columns `fnsku`, `asin`, `msku`, `title`, `disposition`,\
        \ `location`, `integration_instance_name`: contains, does_not_contain, is,\
        \ is_not, is_one_of, is_not_one_of, starts_with, does_not_start_with, ends_with,\
        \ does_not_end_with, is_empty, is_not_empty.\n  - Numeric columns `id`, `ending_warehouse_balance`:\
        \ is, is_not, is_one_of, is_not_one_of, greater_than, less_than, greater_than_or_equal,\
        \ less_than_or_equal, between, is_empty, is_not_empty.\n  - Date column `created_at`:\
        \ is, is_not, before, after, on_or_before, on_or_after, between, is_empty,\
        \ is_not_empty, today, yesterday, tomorrow, past_week, past_month, past_year,\
        \ next_week, next_month, next_year.\n  - A bare `filter[column]=value` acts\
        \ as an implicit `is`.\n- `filter_groups` - base64-encoded JSON tree (`{\"\
        conjunction\": \"and\", \"children\": [...]}`) for nested and/or filter groups;\
        \ via POST it may be sent as a plain JSON object.\n\nEach row includes the\
        \ linked FNSKU product and its SKU.io product (when mapped), the initial unit\
        \ cost, reconciliation state, and the FIFO layer ID created from the row."
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        integration_instance_name:
                          type: string
                        fnsku:
                          type: string
                        asin:
                          type: string
                        msku:
                          type: string
                        title:
                          type: string
                        location:
                          type: string
                        disposition:
                          type: string
                        ending_warehouse_balance:
                          type: integer
                        fnsku_product:
                          type: object
                          properties:
                            id:
                              type: integer
                            initial_unit_cost:
                              type: number
                            reconciled_quantity:
                              type: integer
                            product:
                              type: object
                              properties:
                                id:
                                  type: integer
                                sku:
                                  type: string
                                name:
                                  type: string
                        is_reconciled:
                          type: boolean
                        amazon_fifo_layer_id:
                          type: integer
                        created_at:
                          type: string
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                    items:
                      type: object
                      properties:
                        url:
                          type: string
                          nullable: true
                        label:
                          type: string
                        active:
                          type: boolean
                  next_page_url:
                    type: string
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 101
                    integration_instance_id: 3
                    integration_instance_name: Amazon US
                    fnsku: X002QK7F5T
                    asin: B08XYZL4M2
                    msku: WIDGET-BLK-12
                    title: Widget Pro 12-Pack, Black
                    location: ONT8
                    disposition: SELLABLE
                    ending_warehouse_balance: 148
                    fnsku_product:
                      id: 55
                      initial_unit_cost: 4.25
                      reconciled_quantity: 148
                      product:
                        id: 918
                        sku: WIDGET-BLK-12
                        name: Widget Pro 12-Pack, Black
                    is_reconciled: true
                    amazon_fifo_layer_id: 7742
                    created_at: '2026-04-18T09:12:44.000000Z'
                  - id: 102
                    integration_instance_id: 3
                    integration_instance_name: Amazon US
                    fnsku: X001ZR8V2K
                    asin: B07QRS9T1P
                    msku: GADGET-RED-01
                    title: Gadget Mini, Red
                    location: TEB4
                    disposition: UNSELLABLE
                    ending_warehouse_balance: 6
                    fnsku_product: null
                    is_reconciled: null
                    amazon_fifo_layer_id: null
                    created_at: '2026-04-18T09:12:44.000000Z'
                  first_page_url: '{{protocol}}://{{domain}}/api/amazon/unified/initial-inventory?page=1'
                  from: 1
                  last_page: 9
                  last_page_url: '{{protocol}}://{{domain}}/api/amazon/unified/initial-inventory?page=9'
                  links:
                  - url: null
                    label: '&laquo; Previous'
                    active: false
                  - url: '{{protocol}}://{{domain}}/api/amazon/unified/initial-inventory?page=1'
                    label: '1'
                    active: true
                  - url: '{{protocol}}://{{domain}}/api/amazon/unified/initial-inventory?page=2'
                    label: '2'
                    active: false
                  - url: '{{protocol}}://{{domain}}/api/amazon/unified/initial-inventory?page=2'
                    label: Next &raquo;
                    active: false
                  next_page_url: '{{protocol}}://{{domain}}/api/amazon/unified/initial-inventory?page=2'
                  path: '{{protocol}}://{{domain}}/api/amazon/unified/initial-inventory'
                  per_page: 10
                  prev_page_url: null
                  to: 10
                  total: 84
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-amazon-unified-initial-inventory
  /api/amazon/{integrationInstance}/initial-inventory/unreconcile-for-fnskus:
    post:
      tags:
      - Amazon
      summary: Unreconcile Initial Inventories for FNSKUs
      description: 'Unreconcile the FBA initial inventory records linked to the given
        FNSKU products. Runs synchronously.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Body fields:

        - ids (array of integers, required) — FNSKU product IDs; each must exist.


        For every initial inventory row belonging to one of the FNSKU products that
        currently has an initial-inventory FIFO layer, the reconciliation is reversed
        in a transaction: the record''s initialization timestamp and FIFO layer link
        are cleared, the FIFO layer created during reconciliation is deleted, and
        the FNSKU product''s reconciled quantity is reset to 0. Rows without a FIFO
        layer are skipped. The request fails when a targeted FNSKU product still has
        reconciled ledger entries — unreconcile those ledgers first.


        Returns the updated initial inventory records (with amazon_fifo_layer_id and
        sku_product_initialized_at cleared). Returns 422 when an ID does not exist.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 412
                - 431
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Amazon integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        fnskuProduct:
                          type: object
                          properties:
                            id:
                              type: integer
                            reconciled_quantity:
                              type: integer
                        checksum:
                          type: string
                        integration_instance_id:
                          type: integer
                        amazon_report_id:
                          type: integer
                        amazon_product_id:
                          type: integer
                        fifo_layer_id:
                          type: string
                          nullable: true
                        amazon_fifo_layer_id:
                          type: string
                          nullable: true
                        sku_product_initialized_at:
                          type: string
                          nullable: true
                        date:
                          type: string
                        fnsku:
                          type: string
                        asin:
                          type: string
                        msku:
                          type: string
                        title:
                          type: string
                        disposition:
                          type: string
                        starting_warehouse_balance:
                          type: integer
                        in_transit_between_warehouses:
                          type: integer
                        receipts:
                          type: integer
                        customer_shipments:
                          type: integer
                        customer_returns:
                          type: integer
                        vendor_returns:
                          type: integer
                        warehouse_transfer_in_out:
                          type: integer
                        found:
                          type: integer
                        lost:
                          type: integer
                        damaged:
                          type: integer
                        disposed:
                          type: integer
                        other_events:
                          type: integer
                        adjustments:
                          type: integer
                        ending_warehouse_balance:
                          type: integer
                        total_inventory_quantity:
                          type: integer
                        unknown_events:
                          type: integer
                        location:
                          type: string
                        json_object:
                          type: object
                          properties:
                            date:
                              type: string
                            fnsku:
                              type: string
                            asin:
                              type: string
                            msku:
                              type: string
                            title:
                              type: string
                            disposition:
                              type: string
                            starting_warehouse_balance:
                              type: string
                            ending_warehouse_balance:
                              type: string
                            location:
                              type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  status:
                    type: string
                example:
                  data:
                  - id: 7719
                    fnskuProduct:
                      id: 412
                      reconciled_quantity: 0
                    checksum: 9c2e6f5a1b7d4c3e8f90a1b2c3d4e5f6
                    integration_instance_id: 1
                    amazon_report_id: 388
                    amazon_product_id: 1502
                    fifo_layer_id: null
                    amazon_fifo_layer_id: null
                    sku_product_initialized_at: null
                    date: '2026-01-31T00:00:00.000000Z'
                    fnsku: X002ABCDE1
                    asin: B08K4F9TXQ
                    msku: LS-RAZOR-BLK
                    title: Leaf Razor, Black
                    disposition: SELLABLE
                    starting_warehouse_balance: 120
                    in_transit_between_warehouses: 6
                    receipts: 0
                    customer_shipments: -14
                    customer_returns: 1
                    vendor_returns: 0
                    warehouse_transfer_in_out: -6
                    found: 0
                    lost: -1
                    damaged: 0
                    disposed: 0
                    other_events: 0
                    adjustments: -1
                    ending_warehouse_balance: 100
                    total_inventory_quantity: 106
                    unknown_events: 0
                    location: US
                    json_object:
                      date: 1/31/2026
                      fnsku: X002ABCDE1
                      asin: B08K4F9TXQ
                      msku: LS-RAZOR-BLK
                      title: Leaf Razor, Black
                      disposition: SELLABLE
                      starting_warehouse_balance: '120'
                      ending_warehouse_balance: '100'
                      location: US
                    created_at: '2026-02-01T04:10:22.000000Z'
                    updated_at: '2026-07-06T18:31:07.000000Z'
                  - id: 7742
                    fnskuProduct:
                      id: 431
                      reconciled_quantity: 0
                    checksum: 1f83ac7d9e2b4a5c6d7e8f9012a3b4c5
                    integration_instance_id: 1
                    amazon_report_id: 388
                    amazon_product_id: 1518
                    fifo_layer_id: null
                    amazon_fifo_layer_id: null
                    sku_product_initialized_at: null
                    date: '2026-01-31T00:00:00.000000Z'
                    fnsku: X003QWERT7
                    asin: B09PLMN3RZ
                    msku: LS-SOAP-3PK
                    title: Shave Soap Refill 3-Pack
                    disposition: SELLABLE
                    starting_warehouse_balance: 40
                    in_transit_between_warehouses: 0
                    receipts: 12
                    customer_shipments: -9
                    customer_returns: 0
                    vendor_returns: 0
                    warehouse_transfer_in_out: 0
                    found: 0
                    lost: 0
                    damaged: 0
                    disposed: 0
                    other_events: 0
                    adjustments: 0
                    ending_warehouse_balance: 43
                    total_inventory_quantity: 43
                    unknown_events: 0
                    location: US
                    json_object:
                      date: 1/31/2026
                      fnsku: X003QWERT7
                      asin: B09PLMN3RZ
                      msku: LS-SOAP-3PK
                      title: Shave Soap Refill 3-Pack
                      disposition: SELLABLE
                      starting_warehouse_balance: '40'
                      ending_warehouse_balance: '43'
                      location: US
                    created_at: '2026-02-01T04:10:22.000000Z'
                    updated_at: '2026-07-06T18:31:07.000000Z'
                  status: success
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      ids.0:
                        type: array
                        items:
                          type: string
                  status:
                    type: string
                example:
                  message: The selected ids.0 is invalid.
                  errors:
                    ids.0:
                    - The selected ids.0 is invalid.
                  status: failure
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-amazon-integrationinstance-initial-inventory-unreconcile-for-fnskus
  /api/amazon/{integrationInstance}/outbound:
    get:
      tags:
      - Amazon
      summary: List Outbound Fulfillments
      description: 'List Amazon outbound fulfillment orders.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        example: '1'
        description: Page number (default 1).
      - name: per_page
        in: query
        schema:
          type: integer
        example: '20'
        description: Results per page (default 10).
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        fulfillment_order_id:
                          type: string
                        status:
                          type: string
                  current_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 1
                    fulfillment_order_id: MFN-12345
                    status: COMPLETE
                  current_page: 1
                  total: 30
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-integrationinstance-outbound
  /api/amazon/{integrationInstance}/outbound/{id}:
    delete:
      tags:
      - Amazon
      summary: Delete Outbound Fulfillment
      description: 'Delete an outbound fulfillment order.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: id
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The record ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Outbound fulfillment deleted
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-amazon-integrationinstance-outbound-id
  /api/amazon/{integrationInstance}/outbound/unlinked:
    get:
      tags:
      - Amazon
      summary: Get Unlinked Outbound Fulfillments
      description: 'Get unlinked outbound fulfillment orders.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        fulfillment_order_id:
                          type: string
                example:
                  data:
                  - id: 1
                    fulfillment_order_id: MFN-99999
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-integrationinstance-outbound-unlinked
  /api/amazon/{integrationInstance}/outbound/refresh:
    post:
      tags:
      - Amazon
      summary: Refresh Outbound Fulfillments
      description: 'Refresh outbound fulfillment orders from Amazon.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Refresh started
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-amazon-integrationinstance-outbound-refresh
  /api/amazon/{integrationInstance}/outbound/create-fulfillment/{amazonFulfillmentOrder}/{salesOrder}:
    post:
      tags:
      - Amazon
      summary: Create Fulfillment
      description: 'Links an Amazon MCF (outbound) order to its SKU sales order''s
        FulfillmentOrder.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        deferred-shipment model: this no longer creates a SalesOrderFulfillment up
        front. The AmazonFulfillmentOrder is linked to its FulfillmentOrder, and the
        shipment SOF is minted by the canonical ship-time recorder when Amazon reports
        a shipment. If Amazon has already shipped, the endpoint returns the resulting
        fulfilled SalesOrderFulfillment; otherwise it returns a confirmation message
        that the order was linked and is awaiting Amazon''s ship signal.


        Requires a Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: amazonFulfillmentOrder
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The amazon fulfillment order ID.
      - name: salesOrder
        in: path
        schema:
          type: integer
        required: true
        example: '55'
        description: The sales order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 OK — shipment already recorded
                  value:
                    data:
                      id: 5
                      sales_order_id: 55
                      fulfillment_type: fba
                      status: fulfilled
                      tracking_number: TBA313166722760
                      fulfilled_at: '2026-06-21 14:02:11'
                example-1:
                  summary: 200 OK — linked, awaiting Amazon shipment
                  value:
                    message: Amazon MCF order linked to its fulfillment order. The
                      shipment will appear once Amazon reports it.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-amazon-integrationinstance-outbound-create-fulfillment-amazonfulfillmentorder-salesorder
  /api/amazon-pending-inbounds/{pendingInbound}/create-shortage:
    post:
      tags:
      - Amazon
      summary: Create Shortage from Pending Inbound
      description: 'Create an inbound shortage record from a pending inbound.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters:
      - name: pendingInbound
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The pending inbound ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      pending_inbound_id:
                        type: integer
                      shortage_quantity:
                        type: integer
                example:
                  data:
                    id: 3
                    pending_inbound_id: 1
                    shortage_quantity: 10
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-amazon-pending-inbounds-pendinginbound-create-shortage
  /api/amazon-inbound-shortages/{amazonInboundShortage}:
    put:
      tags:
      - Amazon
      summary: Update Inbound Shortage
      description: 'Update an Amazon inbound shortage record.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                notes:
                  type: string
              example:
                notes: Shortage confirmed — carrier damaged 10 units
      parameters:
      - name: amazonInboundShortage
        in: path
        schema:
          type: integer
        required: true
        example: '3'
        description: The amazon inbound shortage ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      notes:
                        type: string
                example:
                  data:
                    id: 3
                    notes: Shortage confirmed — carrier damaged 10 units
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-amazon-inbound-shortages-amazoninboundshortage
    delete:
      tags:
      - Amazon
      summary: Delete Inbound Shortage
      description: 'Delete an Amazon inbound shortage record.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: amazonInboundShortage
        in: path
        schema:
          type: integer
        required: true
        example: '3'
        description: The amazon inbound shortage ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Inbound shortage deleted
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-amazon-inbound-shortages-amazoninboundshortage
  /api/amazon-inbound-shortages/{amazonInboundShortage}/generate-accounting-transaction:
    post:
      tags:
      - Amazon
      summary: Generate Accounting Transaction for Shortage
      description: 'Generate an accounting transaction for an Amazon inbound shortage.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters:
      - name: amazonInboundShortage
        in: path
        schema:
          type: integer
        required: true
        example: '3'
        description: The amazon inbound shortage ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      transaction_id:
                        type: integer
                example:
                  message: Accounting transaction generated
                  data:
                    transaction_id: 99
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-amazon-inbound-shortages-amazoninboundshortage-generate-accounting-transaction
  /api/amazon/unified/reimbursement-cases:
    get:
      tags:
      - Amazon
      summary: List Reimbursement Cases
      description: 'Paginated list of SKU.io-tracked FBA reimbursement claim cases,
        unified across all Amazon integration instances. Cases are flagged by automated
        detectors (lost or damaged warehouse inventory, customer returns never received
        back, inbound shortages, fee overcharges, etc.) and move through a claim lifecycle:
        potential, under_review, ready_to_submit, submitted, partially_reimbursed,
        reimbursed, denied, dismissed, expired.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Pagination: `page` and `per_page` (default 10).

        Sorting: `sort=<field>` ascending or `sort=-<field>` descending. Sortable
        fields: id, category, status, amazon_case_id, flagged_at, submitted_at, reconciled_at,
        claim_window_expires_at, sku, fnsku, asin, quantity, unit_cost, potential_amount,
        reimbursed_amount, currency, created_at, updated_at.


        Simple filters:

        - `filter[search]` — fuzzy search across amazon_case_id, sku, asin, fnsku
        and the integration instance name. Restrict with `search_columns` and force
        exact matching per column with `search_strict_columns`.

        - `filter[integration_instance_ids]` — comma-separated Amazon integration
        instance IDs.

        - `filter[statuses]` — comma-separated list of statuses (potential, under_review,
        ready_to_submit, submitted, partially_reimbursed, reimbursed, denied, dismissed,
        expired).

        - `filter[categories]` — comma-separated list of categories (warehouse_lost,
        warehouse_damaged, customer_return_not_received, customer_return_damaged,
        customer_return_refund_mismatch, inbound_shortage, removal_order_discrepancy,
        fba_fee_overcharge, chargeback_reversal, destroyed_without_authorization).

        - `filter[expiring_within_days]` — only cases whose claim window expires within
        the next N days (and has not already expired).


        Advanced operator filters use the syntax `filter[column.operator]=value`;
        a bare `filter[column]=value` is treated as the `is` operator.

        - Text columns (amazon_case_id, sku, fnsku, asin, category, status, currency,
        unit_cost_source) support: contains, does_not_contain, is, is_not, is_one_of,
        is_not_one_of, starts_with, does_not_start_with, ends_with, does_not_end_with,
        is_empty, is_not_empty.

        - Numeric columns (quantity, unit_cost, potential_amount, reimbursed_amount)
        support: is, is_not, is_one_of, is_not_one_of, greater_than, less_than, greater_than_or_equal,
        less_than_or_equal, between, is_empty, is_not_empty.

        - Date columns (flagged_at, submitted_at, reconciled_at, claim_window_expires_at,
        created_at, updated_at) support: is, is_not, before, after, on_or_before,
        on_or_after, between, is_empty, is_not_empty, today, yesterday, tomorrow,
        past_week, past_month, past_year, next_week, next_month, next_year, days_ago,
        days_from_now, past_days, next_days. Date values use ISO 8601 / Y-m-d; `between`
        takes two comma-separated values.


        Complex AND/OR filter trees can be sent via `filter_groups` (base64-encoded
        JSON tree of conditions and nested groups).'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        integration_instance_name:
                          type: string
                        category:
                          type: string
                        category_label:
                          type: string
                        status:
                          type: string
                        amazon_case_id:
                          type: string
                          nullable: true
                        flagged_at:
                          type: string
                        detected_at:
                          type: string
                        submitted_at:
                          type: string
                          nullable: true
                        reconciled_at:
                          type: string
                          nullable: true
                        claim_window_opens_at:
                          type: string
                        claim_window_expires_at:
                          type: string
                        days_until_expiry:
                          type: integer
                        is_expired:
                          type: boolean
                        can_submit_now:
                          type: boolean
                        sku:
                          type: string
                        fnsku:
                          type: string
                        asin:
                          type: string
                        product_id:
                          type: integer
                        amazon_fnsku_product_id:
                          type: integer
                        quantity:
                          type: integer
                        unit_cost:
                          type: number
                        unit_cost_source:
                          type: string
                        potential_amount:
                          type: number
                        currency:
                          type: string
                        reimbursed_amount:
                          type: string
                          nullable: true
                        idempotency_key:
                          type: string
                        source_reference_type:
                          type: string
                        source_reference_id:
                          type: integer
                        evidence:
                          type: object
                          properties:
                            ledger_event_ids:
                              type: array
                              items:
                                type: integer
                            lost_on:
                              type: string
                        claim_text:
                          type: string
                        dismissed_reason:
                          type: string
                          nullable: true
                        assigned_user_id:
                          type: integer
                        assigned_user:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                    items:
                      type: object
                      properties:
                        url:
                          type: string
                          nullable: true
                        label:
                          type: string
                        active:
                          type: boolean
                  next_page_url:
                    type: string
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 42
                    integration_instance_id: 3
                    integration_instance_name: Amazon US
                    category: warehouse_lost
                    category_label: Warehouse Lost
                    status: potential
                    amazon_case_id: null
                    flagged_at: '2026-06-14T02:15:33+00:00'
                    detected_at: '2026-06-14T02:15:33+00:00'
                    submitted_at: null
                    reconciled_at: null
                    claim_window_opens_at: '2026-06-14T00:00:00+00:00'
                    claim_window_expires_at: '2026-08-12T23:59:59+00:00'
                    days_until_expiry: 37
                    is_expired: false
                    can_submit_now: true
                    sku: BCK-CANISTER-16OZ
                    fnsku: X002QDR3V7
                    asin: B08XYZ4Q2M
                    product_id: 918
                    amazon_fnsku_product_id: 2451
                    quantity: 3
                    unit_cost: 14.25
                    unit_cost_source: fifo
                    potential_amount: 42.75
                    currency: USD
                    reimbursed_amount: null
                    idempotency_key: warehouse_lost:3:X002QDR3V7:2026-05-14
                    source_reference_type: ledger_event
                    source_reference_id: 88213
                    evidence:
                      ledger_event_ids:
                      - 88213
                      lost_on: '2026-05-14'
                    claim_text: 3 units of FNSKU X002QDR3V7 were recorded as lost
                      in the FBA ledger on 2026-05-14 and have not been reimbursed
                      or found.
                    dismissed_reason: null
                    assigned_user_id: 7
                    assigned_user:
                      id: 7
                      name: Dana Whitfield
                    created_at: '2026-06-14T02:15:33+00:00'
                    updated_at: '2026-06-19T08:12:44+00:00'
                  - id: 38
                    integration_instance_id: 3
                    integration_instance_name: Amazon US
                    category: customer_return_not_received
                    category_label: Customer Return Not Received
                    status: reimbursed
                    amazon_case_id: '17389245671'
                    flagged_at: '2026-04-22T06:40:12+00:00'
                    detected_at: '2026-04-22T06:40:12+00:00'
                    submitted_at: '2026-05-02T15:21:07+00:00'
                    reconciled_at: '2026-06-03T09:02:51+00:00'
                    claim_window_opens_at: '2026-04-22T00:00:00+00:00'
                    claim_window_expires_at: '2026-10-19T23:59:59+00:00'
                    days_until_expiry: 104
                    is_expired: false
                    can_submit_now: false
                    sku: LEAF-RAZOR-STD
                    fnsku: X001M8KQZ3
                    asin: B0B7H2JKLM
                    product_id: 655
                    amazon_fnsku_product_id: 1994
                    quantity: 1
                    unit_cost: 18.9
                    unit_cost_source: fifo
                    potential_amount: 18.9
                    currency: USD
                    reimbursed_amount: 18.9
                    idempotency_key: customer_return_not_received:3:113-4092817-5544312:X001M8KQZ3
                    source_reference_type: customer_return
                    source_reference_id: 30412
                    evidence:
                      amazon_order_id: 113-4092817-5544312
                      refund_date: '2026-03-08'
                    claim_text: Refund issued on order 113-4092817-5544312 on 2026-03-08
                      but the returned unit was never received back into FBA inventory
                      within 45 days.
                    dismissed_reason: null
                    assigned_user_id: 7
                    assigned_user:
                      id: 7
                      name: Dana Whitfield
                    created_at: '2026-04-22T06:40:12+00:00'
                    updated_at: '2026-06-03T09:02:51+00:00'
                  first_page_url: '{{protocol}}://{{domain}}/api/amazon/unified/reimbursement-cases?page=1'
                  from: 1
                  last_page: 5
                  last_page_url: '{{protocol}}://{{domain}}/api/amazon/unified/reimbursement-cases?page=5'
                  links:
                  - url: null
                    label: '&laquo; Previous'
                    active: false
                  - url: '{{protocol}}://{{domain}}/api/amazon/unified/reimbursement-cases?page=1'
                    label: '1'
                    active: true
                  - url: '{{protocol}}://{{domain}}/api/amazon/unified/reimbursement-cases?page=2'
                    label: '2'
                    active: false
                  - url: '{{protocol}}://{{domain}}/api/amazon/unified/reimbursement-cases?page=2'
                    label: Next &raquo;
                    active: false
                  next_page_url: '{{protocol}}://{{domain}}/api/amazon/unified/reimbursement-cases?page=2'
                  path: '{{protocol}}://{{domain}}/api/amazon/unified/reimbursement-cases'
                  per_page: 10
                  prev_page_url: null
                  to: 2
                  total: 47
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-amazon-unified-reimbursement-cases
    post:
      tags:
      - Amazon
      summary: Create Reimbursement Case
      description: 'Creates a reimbursement case manually. Creation is idempotent
        on `idempotency_key` — if a case with the same key already exists, that case
        is returned instead of creating a duplicate.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Request body fields:

        - `integration_instance_id` (required, integer) — Amazon integration instance
        the case belongs to.

        - `category` (required) — one of: warehouse_lost, warehouse_damaged, customer_return_not_received,
        customer_return_damaged, customer_return_refund_mismatch, inbound_shortage,
        removal_order_discrepancy, fba_fee_overcharge, chargeback_reversal, destroyed_without_authorization.

        - `status` (optional) — one of: potential, under_review, ready_to_submit,
        submitted, partially_reimbursed, reimbursed, denied, dismissed, expired. Defaults
        to `potential`.

        - `flagged_at` (optional, date) — when the discrepancy was flagged.

        - `claim_window_expires_at` (required, date, must be in the future) — last
        day a claim can be filed with Amazon.

        - `sku` (optional, string, max 64) / `fnsku` (optional, string, max 32) /
        `asin` (optional, string, max 32).

        - `product_id` (optional, integer) — SKU.io product ID.

        - `amazon_fnsku_product_id` (optional, integer) — Amazon FNSKU product ID.

        - `quantity` (required, integer >= 0) — affected units.

        - `unit_cost` (required, numeric >= 0) and `unit_cost_source` (optional, string,
        max 32, e.g. fifo, manual).

        - `potential_amount` (required, numeric >= 0) — expected recovery amount.

        - `currency` (required, 3-letter ISO code).

        - `idempotency_key` (required, string, max 191) — unique key for deduplication.

        - `source_reference_type` (optional, string, max 64) and `source_reference_id`
        (optional, integer) — pointer to the record that evidences the discrepancy.

        - `evidence` (optional, object) — free-form supporting data.

        - `claim_text` (optional, string) — pre-drafted text for the Seller Central
        case.

        - `assigned_user_id` (optional, integer) — user responsible for the case.


        Returns the created (or pre-existing) case with HTTP 201.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                integration_instance_id:
                  type: integer
                category:
                  type: string
                status:
                  type: string
                flagged_at:
                  type: string
                claim_window_expires_at:
                  type: string
                sku:
                  type: string
                fnsku:
                  type: string
                asin:
                  type: string
                product_id:
                  type: integer
                amazon_fnsku_product_id:
                  type: integer
                quantity:
                  type: integer
                unit_cost:
                  type: number
                unit_cost_source:
                  type: string
                potential_amount:
                  type: number
                currency:
                  type: string
                idempotency_key:
                  type: string
                source_reference_type:
                  type: string
                source_reference_id:
                  type: integer
                evidence:
                  type: object
                  properties:
                    ledger_event_ids:
                      type: array
                      items:
                        type: integer
                    lost_on:
                      type: string
                claim_text:
                  type: string
                assigned_user_id:
                  type: integer
              example:
                integration_instance_id: 3
                category: warehouse_lost
                status: potential
                flagged_at: '2026-06-14'
                claim_window_expires_at: '2026-08-12'
                sku: BCK-CANISTER-16OZ
                fnsku: X002QDR3V7
                asin: B08XYZ4Q2M
                product_id: 918
                amazon_fnsku_product_id: 2451
                quantity: 3
                unit_cost: 14.25
                unit_cost_source: fifo
                potential_amount: 42.75
                currency: USD
                idempotency_key: warehouse_lost:3:X002QDR3V7:2026-05-14
                source_reference_type: ledger_event
                source_reference_id: 88213
                evidence:
                  ledger_event_ids:
                  - 88213
                  lost_on: '2026-05-14'
                claim_text: 3 units of FNSKU X002QDR3V7 were recorded as lost in the
                  FBA ledger on 2026-05-14 and have not been reimbursed or found.
                assigned_user_id: 7
      parameters: []
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      category:
                        type: string
                      category_label:
                        type: string
                      status:
                        type: string
                      amazon_case_id:
                        type: string
                        nullable: true
                      flagged_at:
                        type: string
                      detected_at:
                        type: string
                      submitted_at:
                        type: string
                        nullable: true
                      reconciled_at:
                        type: string
                        nullable: true
                      claim_window_opens_at:
                        type: string
                      claim_window_expires_at:
                        type: string
                      days_until_expiry:
                        type: integer
                      is_expired:
                        type: boolean
                      can_submit_now:
                        type: boolean
                      sku:
                        type: string
                      fnsku:
                        type: string
                      asin:
                        type: string
                      product_id:
                        type: integer
                      amazon_fnsku_product_id:
                        type: integer
                      quantity:
                        type: integer
                      unit_cost:
                        type: number
                      unit_cost_source:
                        type: string
                      potential_amount:
                        type: number
                      currency:
                        type: string
                      reimbursed_amount:
                        type: string
                        nullable: true
                      idempotency_key:
                        type: string
                      source_reference_type:
                        type: string
                      source_reference_id:
                        type: integer
                      evidence:
                        type: object
                        properties:
                          ledger_event_ids:
                            type: array
                            items:
                              type: integer
                          lost_on:
                            type: string
                      claim_text:
                        type: string
                      dismissed_reason:
                        type: string
                        nullable: true
                      assigned_user_id:
                        type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 42
                    integration_instance_id: 3
                    category: warehouse_lost
                    category_label: Warehouse Lost
                    status: potential
                    amazon_case_id: null
                    flagged_at: '2026-06-14T02:15:33+00:00'
                    detected_at: '2026-06-14T02:15:33+00:00'
                    submitted_at: null
                    reconciled_at: null
                    claim_window_opens_at: '2026-06-14T00:00:00+00:00'
                    claim_window_expires_at: '2026-08-12T23:59:59+00:00'
                    days_until_expiry: 37
                    is_expired: false
                    can_submit_now: true
                    sku: BCK-CANISTER-16OZ
                    fnsku: X002QDR3V7
                    asin: B08XYZ4Q2M
                    product_id: 918
                    amazon_fnsku_product_id: 2451
                    quantity: 3
                    unit_cost: 14.25
                    unit_cost_source: fifo
                    potential_amount: 42.75
                    currency: USD
                    reimbursed_amount: null
                    idempotency_key: warehouse_lost:3:X002QDR3V7:2026-05-14
                    source_reference_type: ledger_event
                    source_reference_id: 88213
                    evidence:
                      ledger_event_ids:
                      - 88213
                      lost_on: '2026-05-14'
                    claim_text: 3 units of FNSKU X002QDR3V7 were recorded as lost
                      in the FBA ledger on 2026-05-14 and have not been reimbursed
                      or found.
                    dismissed_reason: null
                    assigned_user_id: 7
                    created_at: '2026-06-14T02:15:33+00:00'
                    updated_at: '2026-06-19T08:12:44+00:00'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      integration_instance_id:
                        type: array
                        items:
                          type: string
                      category:
                        type: array
                        items:
                          type: string
                      claim_window_expires_at:
                        type: array
                        items:
                          type: string
                      quantity:
                        type: array
                        items:
                          type: string
                      unit_cost:
                        type: array
                        items:
                          type: string
                      potential_amount:
                        type: array
                        items:
                          type: string
                      currency:
                        type: array
                        items:
                          type: string
                      idempotency_key:
                        type: array
                        items:
                          type: string
                example:
                  message: The integration instance id field is required. (and 7 more
                    errors)
                  errors:
                    integration_instance_id:
                    - The integration instance id field is required.
                    category:
                    - The category field is required.
                    claim_window_expires_at:
                    - The claim window expires at field is required.
                    quantity:
                    - The quantity field is required.
                    unit_cost:
                    - The unit cost field is required.
                    potential_amount:
                    - The potential amount field is required.
                    currency:
                    - The currency field is required.
                    idempotency_key:
                    - The idempotency key field is required.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-amazon-unified-reimbursement-cases
  /api/amazon/unified/reimbursement-cases/summary:
    get:
      tags:
      - Amazon
      summary: Get Reimbursement Case Summary
      description: 'Headline reimbursement-case totals across Amazon integration instances,
        for dashboard-style summaries:

        - `potential_recovery` / `potential_recovery_count` — sum of potential_amount
        and count for open cases (potential, under_review, ready_to_submit).

        - `in_flight_amount` / `in_flight_count` — outstanding amount (potential minus
        already reimbursed, floored at zero) and count for submitted and partially_reimbursed
        cases.

        - `recovered_ytd_amount` / `recovered_ytd_count` — reimbursed amounts reconciled
        in the current calendar year (reimbursed and partially_reimbursed cases).

        - `lifetime_amount` / `lifetime_count` — all-time reimbursed totals.

        - `currency` — the currency code the totals are reported in (defaults to USD
        when no cases have a currency).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Optionally scope to specific instances with `integration_instance_ids` (comma-separated).'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      potential_recovery:
                        type: number
                      potential_recovery_count:
                        type: integer
                      in_flight_amount:
                        type: number
                      in_flight_count:
                        type: integer
                      recovered_ytd_amount:
                        type: number
                      recovered_ytd_count:
                        type: integer
                      lifetime_amount:
                        type: number
                      lifetime_count:
                        type: integer
                      currency:
                        type: string
                example:
                  data:
                    potential_recovery: 1284.5
                    potential_recovery_count: 18
                    in_flight_amount: 342.1
                    in_flight_count: 5
                    recovered_ytd_amount: 897.44
                    recovered_ytd_count: 12
                    lifetime_amount: 2145.09
                    lifetime_count: 31
                    currency: USD
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-amazon-unified-reimbursement-cases-summary
  /api/amazon/unified/reimbursement-cases/detect:
    post:
      tags:
      - Amazon
      summary: Detect Reimbursement Cases
      description: 'Re-runs the reimbursement discrepancy detectors and the case reconciler
        across all Amazon integration instances (or the subset given in `integration_instance_ids`).
        Works entirely from data already synced into SKU.io (inventory ledger events,
        customer returns, ingested reimbursement rows, etc.) — it does not call Amazon.
        Newly detected discrepancies create cases in `potential` status; existing
        open cases are matched against reimbursements Amazon has already paid.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Queues a background job; returns a job id (`tracked_job_log_id`) for polling
        progress.


        `integration_instance_ids` accepts an array of integers or a comma-separated
        string; omit it (or send an empty value) to scan every Amazon instance.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                integration_instance_ids:
                  type: array
                  items:
                    type: integer
              example:
                integration_instance_ids:
                - 3
                - 7
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                example:
                  message: Case re-scan started
                  data:
                    tracked_job_log_id: 15234
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-amazon-unified-reimbursement-cases-detect
  /api/amazon/unified/reimbursement-cases/{reimbursementCase}:
    get:
      tags:
      - Amazon
      summary: Get Reimbursement Case
      description: 'Returns a single reimbursement case by ID, including the integration
        instance name, the assigned user, and linked product identifiers. `days_until_expiry`,
        `is_expired` and `can_submit_now` are computed from the claim window dates
        at request time.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: reimbursementCase
        in: path
        schema:
          type: string
        required: true
        description: Reimbursement case ID
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      integration_instance_name:
                        type: string
                      category:
                        type: string
                      category_label:
                        type: string
                      status:
                        type: string
                      amazon_case_id:
                        type: string
                        nullable: true
                      flagged_at:
                        type: string
                      detected_at:
                        type: string
                      submitted_at:
                        type: string
                        nullable: true
                      reconciled_at:
                        type: string
                        nullable: true
                      claim_window_opens_at:
                        type: string
                      claim_window_expires_at:
                        type: string
                      days_until_expiry:
                        type: integer
                      is_expired:
                        type: boolean
                      can_submit_now:
                        type: boolean
                      sku:
                        type: string
                      fnsku:
                        type: string
                      asin:
                        type: string
                      product_id:
                        type: integer
                      amazon_fnsku_product_id:
                        type: integer
                      quantity:
                        type: integer
                      unit_cost:
                        type: number
                      unit_cost_source:
                        type: string
                      potential_amount:
                        type: number
                      currency:
                        type: string
                      reimbursed_amount:
                        type: string
                        nullable: true
                      idempotency_key:
                        type: string
                      source_reference_type:
                        type: string
                      source_reference_id:
                        type: integer
                      evidence:
                        type: object
                        properties:
                          ledger_event_ids:
                            type: array
                            items:
                              type: integer
                          lost_on:
                            type: string
                      claim_text:
                        type: string
                      dismissed_reason:
                        type: string
                        nullable: true
                      assigned_user_id:
                        type: integer
                      assigned_user:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 42
                    integration_instance_id: 3
                    integration_instance_name: Amazon US
                    category: warehouse_lost
                    category_label: Warehouse Lost
                    status: potential
                    amazon_case_id: null
                    flagged_at: '2026-06-14T02:15:33+00:00'
                    detected_at: '2026-06-14T02:15:33+00:00'
                    submitted_at: null
                    reconciled_at: null
                    claim_window_opens_at: '2026-06-14T00:00:00+00:00'
                    claim_window_expires_at: '2026-08-12T23:59:59+00:00'
                    days_until_expiry: 37
                    is_expired: false
                    can_submit_now: true
                    sku: BCK-CANISTER-16OZ
                    fnsku: X002QDR3V7
                    asin: B08XYZ4Q2M
                    product_id: 918
                    amazon_fnsku_product_id: 2451
                    quantity: 3
                    unit_cost: 14.25
                    unit_cost_source: fifo
                    potential_amount: 42.75
                    currency: USD
                    reimbursed_amount: null
                    idempotency_key: warehouse_lost:3:X002QDR3V7:2026-05-14
                    source_reference_type: ledger_event
                    source_reference_id: 88213
                    evidence:
                      ledger_event_ids:
                      - 88213
                      lost_on: '2026-05-14'
                    claim_text: 3 units of FNSKU X002QDR3V7 were recorded as lost
                      in the FBA ledger on 2026-05-14 and have not been reimbursed
                      or found.
                    dismissed_reason: null
                    assigned_user_id: 7
                    assigned_user:
                      id: 7
                      name: Dana Whitfield
                    created_at: '2026-06-14T02:15:33+00:00'
                    updated_at: '2026-06-19T08:12:44+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-unified-reimbursement-cases-reimbursementcase
    put:
      tags:
      - Amazon
      summary: Update Reimbursement Case
      description: 'Updates a reimbursement case. All fields are optional; only supplied
        fields are changed.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Request body fields:

        - `category` — one of: warehouse_lost, warehouse_damaged, customer_return_not_received,
        customer_return_damaged, customer_return_refund_mismatch, inbound_shortage,
        removal_order_discrepancy, fba_fee_overcharge, chargeback_reversal, destroyed_without_authorization.

        - `status` — one of: potential, under_review, ready_to_submit, submitted,
        partially_reimbursed, reimbursed, denied, dismissed, expired. Note: setting
        the status here does NOT enforce the lifecycle transition rules and does not
        record a case note — prefer the transition endpoint for status changes.

        - `amazon_case_id` (string, max 64) — Seller Central case ID.

        - `claim_window_expires_at` (date).

        - `quantity` (integer >= 0), `unit_cost` (numeric >= 0), `unit_cost_source`
        (string, max 32), `potential_amount` (numeric >= 0), `currency` (3-letter
        ISO code).

        - `evidence` (object), `claim_text` (string), `dismissed_reason` (string,
        max 255).

        - `assigned_user_id` (integer, nullable) — user responsible for the case.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                quantity:
                  type: integer
                potential_amount:
                  type: integer
                claim_text:
                  type: string
                assigned_user_id:
                  type: integer
              example:
                quantity: 4
                potential_amount: 57
                claim_text: 4 units of FNSKU X002QDR3V7 lost in the FBA ledger on
                  2026-05-14; ledger export attached.
                assigned_user_id: 7
      parameters:
      - name: reimbursementCase
        in: path
        schema:
          type: string
        required: true
        description: Reimbursement case ID
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      category:
                        type: string
                      category_label:
                        type: string
                      status:
                        type: string
                      amazon_case_id:
                        type: string
                        nullable: true
                      flagged_at:
                        type: string
                      detected_at:
                        type: string
                      submitted_at:
                        type: string
                        nullable: true
                      reconciled_at:
                        type: string
                        nullable: true
                      claim_window_opens_at:
                        type: string
                      claim_window_expires_at:
                        type: string
                      days_until_expiry:
                        type: integer
                      is_expired:
                        type: boolean
                      can_submit_now:
                        type: boolean
                      sku:
                        type: string
                      fnsku:
                        type: string
                      asin:
                        type: string
                      product_id:
                        type: integer
                      amazon_fnsku_product_id:
                        type: integer
                      quantity:
                        type: integer
                      unit_cost:
                        type: number
                      unit_cost_source:
                        type: string
                      potential_amount:
                        type: integer
                      currency:
                        type: string
                      reimbursed_amount:
                        type: string
                        nullable: true
                      idempotency_key:
                        type: string
                      source_reference_type:
                        type: string
                      source_reference_id:
                        type: integer
                      evidence:
                        type: object
                        properties:
                          ledger_event_ids:
                            type: array
                            items:
                              type: integer
                          lost_on:
                            type: string
                      claim_text:
                        type: string
                      dismissed_reason:
                        type: string
                        nullable: true
                      assigned_user_id:
                        type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 42
                    integration_instance_id: 3
                    category: warehouse_lost
                    category_label: Warehouse Lost
                    status: potential
                    amazon_case_id: null
                    flagged_at: '2026-06-14T02:15:33+00:00'
                    detected_at: '2026-06-14T02:15:33+00:00'
                    submitted_at: null
                    reconciled_at: null
                    claim_window_opens_at: '2026-06-14T00:00:00+00:00'
                    claim_window_expires_at: '2026-08-12T23:59:59+00:00'
                    days_until_expiry: 37
                    is_expired: false
                    can_submit_now: true
                    sku: BCK-CANISTER-16OZ
                    fnsku: X002QDR3V7
                    asin: B08XYZ4Q2M
                    product_id: 918
                    amazon_fnsku_product_id: 2451
                    quantity: 4
                    unit_cost: 14.25
                    unit_cost_source: fifo
                    potential_amount: 57
                    currency: USD
                    reimbursed_amount: null
                    idempotency_key: warehouse_lost:3:X002QDR3V7:2026-05-14
                    source_reference_type: ledger_event
                    source_reference_id: 88213
                    evidence:
                      ledger_event_ids:
                      - 88213
                      lost_on: '2026-05-14'
                    claim_text: 4 units of FNSKU X002QDR3V7 lost in the FBA ledger
                      on 2026-05-14; ledger export attached.
                    dismissed_reason: null
                    assigned_user_id: 7
                    created_at: '2026-06-14T02:15:33+00:00'
                    updated_at: '2026-07-06T11:42:18+00:00'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      currency:
                        type: array
                        items:
                          type: string
                example:
                  message: The currency field must be 3 characters.
                  errors:
                    currency:
                    - The currency field must be 3 characters.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: put-api-amazon-unified-reimbursement-cases-reimbursementcase
    delete:
      tags:
      - Amazon
      summary: Delete Reimbursement Case
      description: 'Permanently deletes a reimbursement case. Returns HTTP 204 with
        no body on success.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: reimbursementCase
        in: path
        schema:
          type: string
        required: true
        description: Reimbursement case ID
      responses:
        '204':
          description: No Content
          content:
            text/plain:
              schema:
                type: string
                example: ''
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-amazon-unified-reimbursement-cases-reimbursementcase
  /api/amazon/unified/reimbursement-cases/{reimbursementCase}/transition:
    post:
      tags:
      - Amazon
      summary: Transition Reimbursement Case Status
      description: 'Moves a reimbursement case to a new lifecycle status, enforcing
        the allowed transitions and recording a case note describing the change.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Request body fields:

        - `status` (required) — target status, one of: potential, under_review, ready_to_submit,
        submitted, partially_reimbursed, reimbursed, denied, dismissed, expired.

        - `reason` (optional, string, max 255) — stored as the dismissal/denial reason
        when moving to `dismissed` or `denied`, and appended to the transition note.

        - `amazon_case_id` (optional, string, max 64) — when provided together with
        `status=submitted`, the case is marked as submitted to Amazon with this Seller
        Central case ID and `submitted_at` is stamped (the case must currently be
        in potential, under_review or ready_to_submit).


        Allowed transitions:

        - potential -> under_review, ready_to_submit, submitted, dismissed, expired

        - under_review -> potential, ready_to_submit, submitted, dismissed, expired

        - ready_to_submit -> under_review, submitted, dismissed, expired

        - submitted -> partially_reimbursed, reimbursed, denied

        - partially_reimbursed -> reimbursed, denied

        - reimbursed, denied, dismissed and expired are terminal (no outgoing transitions).
        Transitioning to the current status is a no-op.


        An invalid transition returns HTTP 422 with an `error` message.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                status:
                  type: string
                reason:
                  type: string
                  nullable: true
                amazon_case_id:
                  type: string
                  nullable: true
              example:
                status: under_review
                reason: null
                amazon_case_id: null
      parameters:
      - name: reimbursementCase
        in: path
        schema:
          type: string
        required: true
        description: Reimbursement case ID
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      category:
                        type: string
                      category_label:
                        type: string
                      status:
                        type: string
                      amazon_case_id:
                        type: string
                        nullable: true
                      flagged_at:
                        type: string
                      detected_at:
                        type: string
                      submitted_at:
                        type: string
                        nullable: true
                      reconciled_at:
                        type: string
                        nullable: true
                      claim_window_opens_at:
                        type: string
                      claim_window_expires_at:
                        type: string
                      days_until_expiry:
                        type: integer
                      is_expired:
                        type: boolean
                      can_submit_now:
                        type: boolean
                      sku:
                        type: string
                      fnsku:
                        type: string
                      asin:
                        type: string
                      product_id:
                        type: integer
                      amazon_fnsku_product_id:
                        type: integer
                      quantity:
                        type: integer
                      unit_cost:
                        type: number
                      unit_cost_source:
                        type: string
                      potential_amount:
                        type: number
                      currency:
                        type: string
                      reimbursed_amount:
                        type: string
                        nullable: true
                      idempotency_key:
                        type: string
                      source_reference_type:
                        type: string
                      source_reference_id:
                        type: integer
                      evidence:
                        type: object
                        properties:
                          ledger_event_ids:
                            type: array
                            items:
                              type: integer
                          lost_on:
                            type: string
                      claim_text:
                        type: string
                      dismissed_reason:
                        type: string
                        nullable: true
                      assigned_user_id:
                        type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 42
                    integration_instance_id: 3
                    category: warehouse_lost
                    category_label: Warehouse Lost
                    status: under_review
                    amazon_case_id: null
                    flagged_at: '2026-06-14T02:15:33+00:00'
                    detected_at: '2026-06-14T02:15:33+00:00'
                    submitted_at: null
                    reconciled_at: null
                    claim_window_opens_at: '2026-06-14T00:00:00+00:00'
                    claim_window_expires_at: '2026-08-12T23:59:59+00:00'
                    days_until_expiry: 37
                    is_expired: false
                    can_submit_now: true
                    sku: BCK-CANISTER-16OZ
                    fnsku: X002QDR3V7
                    asin: B08XYZ4Q2M
                    product_id: 918
                    amazon_fnsku_product_id: 2451
                    quantity: 3
                    unit_cost: 14.25
                    unit_cost_source: fifo
                    potential_amount: 42.75
                    currency: USD
                    reimbursed_amount: null
                    idempotency_key: warehouse_lost:3:X002QDR3V7:2026-05-14
                    source_reference_type: ledger_event
                    source_reference_id: 88213
                    evidence:
                      ledger_event_ids:
                      - 88213
                      lost_on: '2026-05-14'
                    claim_text: 3 units of FNSKU X002QDR3V7 were recorded as lost
                      in the FBA ledger on 2026-05-14 and have not been reimbursed
                      or found.
                    dismissed_reason: null
                    assigned_user_id: 7
                    created_at: '2026-06-14T02:15:33+00:00'
                    updated_at: '2026-07-06T11:42:18+00:00'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 422 Invalid Transition
                  value:
                    error: 'Invalid status transition: potential → reimbursed'
                example-1:
                  summary: 422 Validation Error
                  value:
                    message: The selected status is invalid.
                    errors:
                      status:
                      - The selected status is invalid.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-amazon-unified-reimbursement-cases-reimbursementcase-transition
  /api/amazon/unified/reimbursement-cases/{reimbursementCase}/assign:
    post:
      tags:
      - Amazon
      summary: Assign Reimbursement Case
      description: 'Assigns a reimbursement case to a user, or unassigns it.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Request body fields:

        - `assigned_user_id` (optional, integer, nullable) — ID of the user to assign
        the case to. Send `null` (or omit) to unassign.


        Returns the updated case.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                assigned_user_id:
                  type: integer
              example:
                assigned_user_id: 7
      parameters:
      - name: reimbursementCase
        in: path
        schema:
          type: string
        required: true
        description: Reimbursement case ID
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      category:
                        type: string
                      category_label:
                        type: string
                      status:
                        type: string
                      amazon_case_id:
                        type: string
                        nullable: true
                      flagged_at:
                        type: string
                      detected_at:
                        type: string
                      submitted_at:
                        type: string
                        nullable: true
                      reconciled_at:
                        type: string
                        nullable: true
                      claim_window_opens_at:
                        type: string
                      claim_window_expires_at:
                        type: string
                      days_until_expiry:
                        type: integer
                      is_expired:
                        type: boolean
                      can_submit_now:
                        type: boolean
                      sku:
                        type: string
                      fnsku:
                        type: string
                      asin:
                        type: string
                      product_id:
                        type: integer
                      amazon_fnsku_product_id:
                        type: integer
                      quantity:
                        type: integer
                      unit_cost:
                        type: number
                      unit_cost_source:
                        type: string
                      potential_amount:
                        type: number
                      currency:
                        type: string
                      reimbursed_amount:
                        type: string
                        nullable: true
                      idempotency_key:
                        type: string
                      source_reference_type:
                        type: string
                      source_reference_id:
                        type: integer
                      evidence:
                        type: object
                        properties:
                          ledger_event_ids:
                            type: array
                            items:
                              type: integer
                          lost_on:
                            type: string
                      claim_text:
                        type: string
                      dismissed_reason:
                        type: string
                        nullable: true
                      assigned_user_id:
                        type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 42
                    integration_instance_id: 3
                    category: warehouse_lost
                    category_label: Warehouse Lost
                    status: potential
                    amazon_case_id: null
                    flagged_at: '2026-06-14T02:15:33+00:00'
                    detected_at: '2026-06-14T02:15:33+00:00'
                    submitted_at: null
                    reconciled_at: null
                    claim_window_opens_at: '2026-06-14T00:00:00+00:00'
                    claim_window_expires_at: '2026-08-12T23:59:59+00:00'
                    days_until_expiry: 37
                    is_expired: false
                    can_submit_now: true
                    sku: BCK-CANISTER-16OZ
                    fnsku: X002QDR3V7
                    asin: B08XYZ4Q2M
                    product_id: 918
                    amazon_fnsku_product_id: 2451
                    quantity: 3
                    unit_cost: 14.25
                    unit_cost_source: fifo
                    potential_amount: 42.75
                    currency: USD
                    reimbursed_amount: null
                    idempotency_key: warehouse_lost:3:X002QDR3V7:2026-05-14
                    source_reference_type: ledger_event
                    source_reference_id: 88213
                    evidence:
                      ledger_event_ids:
                      - 88213
                      lost_on: '2026-05-14'
                    claim_text: 3 units of FNSKU X002QDR3V7 were recorded as lost
                      in the FBA ledger on 2026-05-14 and have not been reimbursed
                      or found.
                    dismissed_reason: null
                    assigned_user_id: 7
                    created_at: '2026-06-14T02:15:33+00:00'
                    updated_at: '2026-07-06T11:42:18+00:00'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      assigned_user_id:
                        type: array
                        items:
                          type: string
                example:
                  message: The selected assigned user id is invalid.
                  errors:
                    assigned_user_id:
                    - The selected assigned user id is invalid.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-amazon-unified-reimbursement-cases-reimbursementcase-assign
  /api/amazon/unified/reimbursement-cases/{reimbursementCase}/notes:
    get:
      tags:
      - Amazon
      summary: List Reimbursement Case Notes
      description: 'Returns all notes on a reimbursement case, newest first. Notes
        have a `note_type` of `user` (written by a person) or `system` (recorded automatically
        for status transitions, submissions and reconciliation matches; `user_id`
        and `user_name` are null for system notes). Not paginated.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: reimbursementCase
        in: path
        schema:
          type: string
        required: true
        description: Reimbursement case ID
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        amazon_reimbursement_case_id:
                          type: integer
                        user_id:
                          type: integer
                        user_name:
                          type: string
                        body:
                          type: string
                        note_type:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                example:
                  data:
                  - id: 311
                    amazon_reimbursement_case_id: 42
                    user_id: 7
                    user_name: Dana Whitfield
                    body: Called Seller Support — they asked for the ledger export
                      before opening the case.
                    note_type: user
                    created_at: '2026-06-19T08:14:02+00:00'
                    updated_at: '2026-06-19T08:14:02+00:00'
                  - id: 309
                    amazon_reimbursement_case_id: 42
                    user_id: null
                    user_name: null
                    body: Status changed from potential to under_review by Dana Whitfield
                    note_type: system
                    created_at: '2026-06-19T08:12:44+00:00'
                    updated_at: '2026-06-19T08:12:44+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-unified-reimbursement-cases-reimbursementcase-notes
    post:
      tags:
      - Amazon
      summary: Create Reimbursement Case Note
      description: 'Adds a user note to a reimbursement case. The note is attributed
        to the authenticated user and stored with `note_type` of `user`.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Request body fields:

        - `body` (required, string, min 1 character) — the note text.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                body:
                  type: string
              example:
                body: Ledger export uploaded to the Seller Central case as supporting
                  evidence.
      parameters:
      - name: reimbursementCase
        in: path
        schema:
          type: string
        required: true
        description: Reimbursement case ID
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      amazon_reimbursement_case_id:
                        type: integer
                      user_id:
                        type: integer
                      body:
                        type: string
                      note_type:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 312
                    amazon_reimbursement_case_id: 42
                    user_id: 7
                    body: Ledger export uploaded to the Seller Central case as supporting
                      evidence.
                    note_type: user
                    created_at: '2026-07-06T11:45:31+00:00'
                    updated_at: '2026-07-06T11:45:31+00:00'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      body:
                        type: array
                        items:
                          type: string
                example:
                  message: The body field is required.
                  errors:
                    body:
                    - The body field is required.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-amazon-unified-reimbursement-cases-reimbursementcase-notes
  /api/amazon/unified/reimbursement-cases/{reimbursementCase}/activity-log:
    get:
      tags:
      - Amazon
      summary: List Reimbursement Case Activity Log
      description: 'Paginated audit trail for a reimbursement case, newest first.
        Includes create/update events on the case itself and on its notes. Each entry
        exposes the event name, the changed attributes (with old values where applicable)
        in `properties`, and the name of the user who caused the change (`causer_name`,
        null for system changes).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Pagination: `page` and `per_page` (default 15).

        Filtering: `filter[search]` matches the causer name, the event name, the change
        properties and the subject type.'
      parameters:
      - name: reimbursementCase
        in: path
        schema:
          type: string
        required: true
        description: Reimbursement case ID
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        description:
                          type: string
                        event:
                          type: string
                        subject_type:
                          type: string
                        subject_id:
                          type: integer
                        properties:
                          type: object
                          properties:
                            attributes:
                              type: object
                              properties:
                                status:
                                  type: string
                            old:
                              type: object
                              properties:
                                status:
                                  type: string
                        causer_name:
                          type: string
                        created_at:
                          type: string
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                    items:
                      type: object
                      properties:
                        url:
                          type: string
                          nullable: true
                        label:
                          type: string
                        active:
                          type: boolean
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 5121
                    description: updated
                    event: updated
                    subject_type: AmazonReimbursementCase
                    subject_id: 42
                    properties:
                      attributes:
                        status: under_review
                      old:
                        status: potential
                    causer_name: Dana Whitfield
                    created_at: '2026-06-19T08:12:44.000000Z'
                  - id: 5119
                    description: created
                    event: created
                    subject_type: AmazonReimbursementCaseNote
                    subject_id: 311
                    properties:
                      attributes:
                        body: Called Seller Support — they asked for the ledger export
                          before opening the case.
                        note_type: user
                    causer_name: Dana Whitfield
                    created_at: '2026-06-19T08:14:02.000000Z'
                  first_page_url: '{{protocol}}://{{domain}}/api/amazon/unified/reimbursement-cases/42/activity-log?page=1'
                  from: 1
                  last_page: 1
                  last_page_url: '{{protocol}}://{{domain}}/api/amazon/unified/reimbursement-cases/42/activity-log?page=1'
                  links:
                  - url: null
                    label: '&laquo; Previous'
                    active: false
                  - url: '{{protocol}}://{{domain}}/api/amazon/unified/reimbursement-cases/42/activity-log?page=1'
                    label: '1'
                    active: true
                  - url: null
                    label: Next &raquo;
                    active: false
                  next_page_url: null
                  path: '{{protocol}}://{{domain}}/api/amazon/unified/reimbursement-cases/42/activity-log'
                  per_page: 15
                  prev_page_url: null
                  to: 2
                  total: 2
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-unified-reimbursement-cases-reimbursementcase-activity-log
  /api/amazon/inventory-valuation/dashboard:
    get:
      tags:
      - Amazon
      summary: Get Dashboard Data
      description: 'Get the Amazon inventory and valuation dashboard data, aggregated
        across integration instances.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Query params:

        - integration_instance_ids: comma-separated IDs to filter (optional)'
      parameters:
      - name: integration_instance_ids
        in: query
        schema:
          type: string
        description: 'Optional: comma-separated integration instance IDs to filter'
        example: 1,2
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      total_inventory_value:
                        type: number
                      total_units:
                        type: integer
                      by_integration:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            value:
                              type: number
                            units:
                              type: integer
                      cost_confidence:
                        type: object
                        properties:
                          high:
                            type: integer
                          medium:
                            type: integer
                          low:
                            type: integer
                example:
                  data:
                    total_inventory_value: 850000.0
                    total_units: 12500
                    by_integration:
                    - id: 1
                      name: US Store
                      value: 650000.0
                      units: 9500
                    cost_confidence:
                      high: 8200
                      medium: 2300
                      low: 2000
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-amazon-inventory-valuation-dashboard
  /api/amazon/inventory-valuation/dashboard/refresh-reports:
    post:
      tags:
      - Amazon
      summary: Refresh Reports
      description: 'Dispatch a background job to refresh inventory reports for a specific
        integration instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Required fields:

        - integration_instance_id: int (required)


        Returns a tracked_job_log_id to monitor progress.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                integration_instance_id:
                  type: integer
              example:
                integration_instance_id: 1
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                example:
                  message: Report refresh started for US Store
                  data:
                    tracked_job_log_id: 42
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-amazon-inventory-valuation-dashboard-refresh-reports
  /api/amazon/inventory-valuation/cost-source-breakdown:
    get:
      tags:
      - Amazon
      summary: Cost Source Breakdown
      description: 'Get cost confidence breakdown by cogs_source.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integration_instance_ids
        in: query
        schema:
          type: string
        example: 1,2
        description: Comma-separated integration instance IDs to scope the query.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        cogs_source:
                          type: string
                        count:
                          type: integer
                        total_value:
                          type: number
                example:
                  data:
                  - cogs_source: purchase_order
                    count: 5200
                    total_value: 650000.0
                  - cogs_source: manual
                    count: 3000
                    total_value: 200000.0
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-amazon-inventory-valuation-cost-source-breakdown
  /api/amazon/inventory-valuation/cost-source-event-breakdown:
    get:
      tags:
      - Amazon
      summary: Cost Source Event Breakdown
      description: 'Get event type breakdown for a specific cost source.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Required params:

        - cogs_source: string'
      parameters:
      - name: cogs_source
        in: query
        schema:
          type: string
        description: 'Required: COGS source to break down by event type'
        example: purchase_order
      - name: integration_instance_ids
        in: query
        schema:
          type: string
        example: 1,2
        description: Comma-separated integration instance IDs to scope the query.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        event_type:
                          type: string
                        count:
                          type: integer
                        total_value:
                          type: number
                example:
                  data:
                  - event_type: RECEIPT
                    count: 3000
                    total_value: 400000.0
                  - event_type: TRANSFER
                    count: 2200
                    total_value: 250000.0
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-amazon-inventory-valuation-cost-source-event-breakdown
  /api/amazon/inventory-valuation/cost-source-layer-drilldown:
    get:
      tags:
      - Amazon
      summary: Cost Source Layer Drilldown
      description: 'Get paginated individual FIFO layers for a cost source drilldown.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Required:

        - cogs_source: string


        Optional:

        - source_type: string

        - event_type: string

        - integration_instance_ids: comma-separated

        - search: string

        - page, per_page'
      parameters:
      - name: cogs_source
        in: query
        schema:
          type: string
        description: 'Required: COGS source'
        example: purchase_order
      - name: source_type
        in: query
        schema:
          type: string
        description: 'Optional: source type filter'
        example: ledger
      - name: event_type
        in: query
        schema:
          type: string
        description: 'Optional: event type filter'
        example: RECEIPT
      - name: page
        in: query
        schema:
          type: integer
        example: '1'
        description: Page number (default 1).
      - name: per_page
        in: query
        schema:
          type: integer
        example: '15'
        description: Results per page (default 10).
      - name: search
        in: query
        schema:
          type: string
        description: Free-text search across the resource’s searchable fields.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        fnsku:
                          type: string
                        date:
                          type: string
                        cogs:
                          type: number
                        quantity:
                          type: integer
                  current_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 101
                    fnsku: X001ABC123
                    date: '2024-03-01'
                    cogs: 12.5
                    quantity: 100
                  current_page: 1
                  per_page: 15
                  total: 3000
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-amazon-inventory-valuation-cost-source-layer-drilldown
  /api/amazon/inventory-valuation/fifo-layers/{layerId}/revert-eligibility:
    get:
      tags:
      - Amazon
      summary: Check FIFO Layer Revert Eligibility
      description: 'Check if a FIFO layer''s manual override can be reverted.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: layerId
        in: path
        schema:
          type: integer
        required: true
        example: '101'
        description: The layer ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      eligible:
                        type: boolean
                      reason:
                        type: string
                        nullable: true
                      original_cogs:
                        type: number
                example:
                  data:
                    eligible: true
                    reason: null
                    original_cogs: 11.25
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-inventory-valuation-fifo-layers-layerid-revert-eligibility
  /api/amazon/inventory-valuation/fifo-layers/{layerId}/revert:
    post:
      tags:
      - Amazon
      summary: Revert FIFO Layer Override
      description: 'Revert a manual cost override on a FIFO layer back to its automatically
        calculated value.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters:
      - name: layerId
        in: path
        schema:
          type: integer
        required: true
        example: '101'
        description: The layer ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      cogs:
                        type: number
                      cogs_source:
                        type: string
                example:
                  data:
                    id: 101
                    cogs: 11.25
                    cogs_source: purchase_order
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-amazon-inventory-valuation-fifo-layers-layerid-revert
  /api/amazon/inventory-valuation/fifo-layers/batch-revert-eligibility:
    post:
      tags:
      - Amazon
      summary: Batch Check Revert Eligibility
      description: 'Check revert eligibility for multiple FIFO layers at once (max
        100).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Required fields:

        - layer_ids: array of integers (max 100)'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                layer_ids:
                  type: array
                  items:
                    type: integer
              example:
                layer_ids:
                - 101
                - 102
                - 103
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        layer_id:
                          type: integer
                        eligible:
                          type: boolean
                example:
                  data:
                  - layer_id: 101
                    eligible: true
                  - layer_id: 102
                    eligible: false
                    reason: Already at original cost
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-amazon-inventory-valuation-fifo-layers-batch-revert-eligibility
  /api/amazon/inventory-valuation/fifo-layers/bulk-revert:
    post:
      tags:
      - Amazon
      summary: Bulk Revert Manual Overrides
      description: 'Bulk revert all eligible manual COGS overrides matching the given
        filters.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Optional fields:

        - source_type: string filter

        - event_type: string filter

        - integration_instance_ids: comma-separated string'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                source_type:
                  type: string
                event_type:
                  type: string
                integration_instance_ids:
                  type: string
              example:
                source_type: ledger
                event_type: RECEIPT
                integration_instance_ids: 1,2
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      reverted:
                        type: integer
                      skipped:
                        type: integer
                example:
                  data:
                    reverted: 48
                    skipped: 12
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-amazon-inventory-valuation-fifo-layers-bulk-revert
  /api/amazon/unified/fifo-layers/cogs:
    get:
      tags:
      - Amazon
      summary: List FIFO Layers
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        example: '1'
        description: Page number (default 1).
      - name: per_page
        in: query
        schema:
          type: integer
        example: '10'
        description: Results per page (default 10).
      - name: search
        in: query
        schema:
          type: string
        description: Free-text search across the resource’s searchable fields.
      - name: integration_instance_ids
        in: query
        schema:
          type: string
        description: Comma-separated integration instance IDs to scope the query.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      description: 'List FIFO Layers


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      operationId: get-api-amazon-unified-fifo-layers-cogs
  /api/amazon/unified/fifo-layers/cogs/{id}:
    get:
      tags:
      - Amazon
      summary: Show FIFO Layer detail
      description: 'Returns detail for a single Amazon FIFO layer, including source
        links, parent/child layers, cost breakdown, and manual override tracking.
        404 if not found.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      fifo_layer_date:
                        type: string
                      source_type:
                        type: string
                      source_type_label:
                        type: string
                      fnsku:
                        type: string
                      location:
                        type: string
                      disposition:
                        type: string
                      cost_locked:
                        type: boolean
                      cost_editable:
                        type: boolean
                      cogs_source:
                        type: string
                      quantity:
                        type: integer
                      consumed_quantity:
                        type: integer
                      available_quantity:
                        type: integer
                      cogs:
                        type: number
                      extended_cogs:
                        type: integer
                      cost_breakdown:
                        type: object
                        properties:
                          landed_unit_cost:
                            type: number
                          freight:
                            type: integer
                          duty:
                            type: integer
                      reference_id:
                        type: string
                      source_reference_id:
                        type: string
                      amazon_ledger_id:
                        type: integer
                      amazon_awd_ledger_id:
                        type: string
                        nullable: true
                      amazon_ledger_summary_discrepancy_id:
                        type: string
                        nullable: true
                      ledger:
                        type: object
                        properties:
                          id:
                            type: integer
                          event_type:
                            type: string
                          reference_id:
                            type: string
                          reference_link:
                            type: object
                            properties:
                              route:
                                type: string
                              label:
                                type: string
                      awd_ledger:
                        type: string
                        nullable: true
                      discrepancy:
                        type: string
                        nullable: true
                      product:
                        type: object
                        properties:
                          id:
                            type: integer
                          sku:
                            type: string
                          name:
                            type: string
                      fnsku_product:
                        type: object
                        properties:
                          id:
                            type: integer
                          fnsku:
                            type: string
                          asin:
                            type: string
                          msku:
                            type: string
                          product_id:
                            type: integer
                      warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      integration_instance:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      parent_fifo_layer:
                        type: string
                        nullable: true
                      child_fifo_layers:
                        type: array
                      previous_cogs:
                        type: number
                      previous_cogs_source:
                        type: string
                      cogs_overridden_by:
                        type: integer
                      cogs_overridden_by_name:
                        type: string
                      cogs_overridden_at:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 12345
                    fifo_layer_date: '2026-05-20'
                    source_type: ledger
                    source_type_label: Inventory Ledger
                    fnsku: X001ABC123
                    location: AMZ
                    disposition: SELLABLE
                    cost_locked: false
                    cost_editable: true
                    cogs_source: oldest_active_fifo
                    quantity: 100
                    consumed_quantity: 25
                    available_quantity: 75
                    cogs: 9.99
                    extended_cogs: 999
                    cost_breakdown:
                      landed_unit_cost: 9.99
                      freight: 0
                      duty: 0
                    reference_id: FBA15ABCDEFG
                    source_reference_id: FBA15ABCDEFG
                    amazon_ledger_id: 90001
                    amazon_awd_ledger_id: null
                    amazon_ledger_summary_discrepancy_id: null
                    ledger:
                      id: 90001
                      event_type: Receipts
                      reference_id: FBA15ABCDEFG
                      reference_link:
                        route: /integrations/amazon/fba/inbound-shipments/new?filter[search]=FBA15ABCDEFG&search_columns=shipmentConfirmationId&search_strict_columns=shipmentConfirmationId
                        label: Inbound Shipment
                    awd_ledger: null
                    discrepancy: null
                    product:
                      id: 555
                      sku: SKU-001
                      name: Widget Pro
                    fnsku_product:
                      id: 4321
                      fnsku: X001ABC123
                      asin: B07XYZ1234
                      msku: MSKU-001
                      product_id: 555
                    warehouse:
                      id: 7
                      name: Amazon FBA US
                    integration_instance:
                      id: 1
                      name: Amazon US
                    parent_fifo_layer: null
                    child_fifo_layers: []
                    previous_cogs: 8.5
                    previous_cogs_source: unit_cost
                    cogs_overridden_by: 12
                    cogs_overridden_by_name: Jane Doe
                    cogs_overridden_at: '2026-05-21T14:30:00+00:00'
                    created_at: '2026-05-20T10:00:00+00:00'
                    updated_at: '2026-05-21T14:30:00+00:00'
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Amazon FIFO layer not found.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-amazon-unified-fifo-layers-cogs-id
  /api/amazon/unified/fifo-layers/cogs/consumptions:
    get:
      tags:
      - Amazon
      summary: List Consumptions across all FIFO Layers (paginated)
      description: 'Cross-layer paginated consumption listing. Each item is transformed
        via Amazon fifo consumption object; the fifo_layer relation is included for
        cross-layer context.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        effective_at:
                          type: string
                        quantity:
                          type: integer
                        cogs:
                          type: number
                        extended_cogs:
                          type: number
                        cost_locked:
                          type: boolean
                        cost_editable:
                          type: boolean
                        fnsku:
                          type: string
                        location:
                          type: string
                        disposition:
                          type: string
                        amazon_ledger_id:
                          type: integer
                        amazon_awd_ledger_id:
                          type: string
                          nullable: true
                        product:
                          type: object
                          properties:
                            id:
                              type: integer
                            sku:
                              type: string
                            name:
                              type: string
                        ledger:
                          type: object
                          properties:
                            id:
                              type: integer
                            date:
                              type: string
                            event_type:
                              type: string
                            reference_id:
                              type: string
                        awd_ledger:
                          type: string
                          nullable: true
                        fifo_layer:
                          type: object
                          properties:
                            id:
                              type: integer
                            fifo_layer_date:
                              type: string
                            source_type:
                              type: string
                            source_type_label:
                              type: string
                            quantity:
                              type: integer
                            cogs:
                              type: number
                            integration_instance_name:
                              type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                  next_page_url:
                    type: string
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 778899
                    effective_at: '2026-05-22'
                    quantity: 5
                    cogs: 9.99
                    extended_cogs: 49.95
                    cost_locked: false
                    cost_editable: true
                    fnsku: X001ABC123
                    location: AMZ
                    disposition: SELLABLE
                    amazon_ledger_id: 90002
                    amazon_awd_ledger_id: null
                    product:
                      id: 555
                      sku: SKU-001
                      name: Widget Pro
                    ledger:
                      id: 90002
                      date: '2026-05-22'
                      event_type: CustomerReturns
                      reference_id: 112-1234567-1234567
                    awd_ledger: null
                    fifo_layer:
                      id: 12345
                      fifo_layer_date: '2026-05-20'
                      source_type: ledger
                      source_type_label: Inventory Ledger
                      quantity: 100
                      cogs: 9.99
                      integration_instance_name: Amazon US
                    created_at: '2026-05-22T09:00:00+00:00'
                    updated_at: '2026-05-22T09:00:00+00:00'
                  first_page_url: https://example.test/api/amazon/unified/fifo-layers/cogs/consumptions?page=1
                  from: 1
                  last_page: 10
                  last_page_url: https://example.test/api/amazon/unified/fifo-layers/cogs/consumptions?page=10
                  links: []
                  next_page_url: https://example.test/api/amazon/unified/fifo-layers/cogs/consumptions?page=2
                  path: https://example.test/api/amazon/unified/fifo-layers/cogs/consumptions
                  per_page: 15
                  prev_page_url: null
                  to: 15
                  total: 150
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-amazon-unified-fifo-layers-cogs-consumptions
  /api/amazon/unified/fifo-layers/cogs/{id}/consumptions:
    get:
      tags:
      - Amazon
      summary: List Consumptions for a Specific FIFO Layer (paginated)
      description: 'Paginated consumption records for one FIFO layer. 404 if the layer
        doesn''t exist.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        effective_at:
                          type: string
                        quantity:
                          type: integer
                        cogs:
                          type: number
                        extended_cogs:
                          type: number
                        cost_locked:
                          type: boolean
                        cost_editable:
                          type: boolean
                        fnsku:
                          type: string
                        location:
                          type: string
                        disposition:
                          type: string
                        amazon_ledger_id:
                          type: integer
                        amazon_awd_ledger_id:
                          type: string
                          nullable: true
                        product:
                          type: object
                          properties:
                            id:
                              type: integer
                            sku:
                              type: string
                            name:
                              type: string
                        ledger:
                          type: object
                          properties:
                            id:
                              type: integer
                            date:
                              type: string
                            event_type:
                              type: string
                            reference_id:
                              type: string
                        awd_ledger:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                  next_page_url:
                    type: string
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 778899
                    effective_at: '2026-05-22'
                    quantity: 5
                    cogs: 9.99
                    extended_cogs: 49.95
                    cost_locked: false
                    cost_editable: true
                    fnsku: X001ABC123
                    location: AMZ
                    disposition: SELLABLE
                    amazon_ledger_id: 90002
                    amazon_awd_ledger_id: null
                    product:
                      id: 555
                      sku: SKU-001
                      name: Widget Pro
                    ledger:
                      id: 90002
                      date: '2026-05-22'
                      event_type: CustomerReturns
                      reference_id: 112-1234567-1234567
                    awd_ledger: null
                    created_at: '2026-05-22T09:00:00+00:00'
                    updated_at: '2026-05-22T09:00:00+00:00'
                  first_page_url: https://example.test/api/amazon/unified/fifo-layers/cogs/12345/consumptions?page=1
                  from: 1
                  last_page: 2
                  last_page_url: https://example.test/api/amazon/unified/fifo-layers/cogs/12345/consumptions?page=2
                  links: []
                  next_page_url: https://example.test/api/amazon/unified/fifo-layers/cogs/12345/consumptions?page=2
                  path: https://example.test/api/amazon/unified/fifo-layers/cogs/12345/consumptions
                  per_page: 15
                  prev_page_url: null
                  to: 15
                  total: 25
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Amazon FIFO layer not found.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-amazon-unified-fifo-layers-cogs-id-consumptions
  /api/amazon/unified/fifo-layers/cogs/{id}/activity-log:
    get:
      tags:
      - Amazon
      summary: Activity Log for a FIFO Layer (paginated)
      description: 'Returns paginated Spatie activity-log entries for the given FIFO
        layer, newest first. Uses the AppliesActivityLogFilters trait for filter[event],
        filter[source], filter[batch_uuid]. 404 if the layer doesn''t exist (findOrFail).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        description:
                          type: string
                        event:
                          type: string
                        properties:
                          type: object
                          properties:
                            source:
                              type: string
                            attributes:
                              type: object
                              properties:
                                cogs:
                                  type: number
                                cogs_source:
                                  type: string
                            old:
                              type: object
                              properties:
                                cogs:
                                  type: number
                                cogs_source:
                                  type: string
                        causer_name:
                          type: string
                        created_at:
                          type: string
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 1002
                    description: COGS updated from 8.50 to 9.99
                    event: updated
                    properties:
                      source: manual
                      attributes:
                        cogs: 9.99
                        cogs_source: manual
                      old:
                        cogs: 8.5
                        cogs_source: unit_cost
                    causer_name: Jane Doe
                    created_at: '2026-05-21T14:30:00.000000Z'
                  - id: 1001
                    description: FIFO layer created from ledger event
                    event: created
                    properties:
                      source: amazon_sync
                      attributes:
                        cogs: 8.5
                        quantity: 100
                    causer_name: null
                    created_at: '2026-05-20T10:00:00.000000Z'
                  first_page_url: https://example.test/api/amazon/unified/fifo-layers/cogs/12345/activity-log?page=1
                  from: 1
                  last_page: 1
                  last_page_url: https://example.test/api/amazon/unified/fifo-layers/cogs/12345/activity-log?page=1
                  links: []
                  next_page_url: null
                  path: https://example.test/api/amazon/unified/fifo-layers/cogs/12345/activity-log
                  per_page: 15
                  prev_page_url: null
                  to: 2
                  total: 2
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-unified-fifo-layers-cogs-id-activity-log
  /api/amazon/unified/fifo-layers/cogs/bulk-update:
    post:
      tags:
      - Amazon
      summary: Bulk Update COGS
      description: 'Bulk-set the same COGS value on multiple FIFO layers. Validation
        (BulkUpdateFifoLayerCogsData): layer_ids required array min:1; layer_ids.*
        required integer exists:amazon_fifo_layers,id; cogs required numeric min:0.
        Additionally, all selected layers MUST belong to the same product or a 422
        is returned. Returns the updated_count and a success message.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                layer_ids:
                  type: array
                  items:
                    type: integer
                cogs:
                  type: number
              example:
                layer_ids:
                - 12345
                - 12346
                - 12347
                cogs: 9.99
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  updated_count:
                    type: integer
                example:
                  message: COGS updated successfully
                  updated_count: 3
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 422 Same-Product Constraint
                  value:
                    message: All selected layers must belong to the same product for
                      bulk COGS update.
                    errors:
                      layer_ids:
                      - All selected layers must belong to the same product for bulk
                        COGS update.
                example-1:
                  summary: 422 Validation
                  value:
                    message: At least one FIFO layer must be selected.
                    errors:
                      layer_ids:
                      - At least one FIFO layer must be selected.
                      cogs:
                      - COGS value is required.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-amazon-unified-fifo-layers-cogs-bulk-update
  /api/amazon/unified/fifo-layers/cogs/export:
    get:
      tags:
      - Amazon
      summary: Export FIFO Layers
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      description: 'Export FIFO Layers


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      operationId: get-api-amazon-unified-fifo-layers-cogs-export
  /api/amazon/unified/fifo-layers/cogs/import/template:
    get:
      tags:
      - Amazon
      summary: Download COGS Import Template (CSV)
      description: 'Streams a CSV template (fifo-layer-cogs-import-template.csv) with
        headers: layer_id, cogs. Includes one sample row (12345, 9.99).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: text/csv
            Content-Disposition:
              schema:
                type: string
                example: attachment; filename=fifo-layer-cogs-import-template.csv
          content:
            text/plain:
              schema:
                type: string
                example: 'layer_id,cogs

                  12345,9.99

                  '
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-amazon-unified-fifo-layers-cogs-import-template
  /api/amazon/unified/fifo-layers/cogs/import/validate:
    post:
      tags:
      - Amazon
      summary: Validate COGS Import
      description: 'Validates a parsed CSV import payload BEFORE committing. Validation
        rules: rows required array min:1; rows.*.layer_id present; rows.*.cogs present.
        Per-row business validation checks layer existence and cogs >= 0. Returns
        valid_rows, error_rows, and summary counts.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                rows:
                  type: array
                  items:
                    type: object
                    properties:
                      layer_id:
                        type: integer
                      cogs:
                        type: number
              example:
                rows:
                - layer_id: 12345
                  cogs: 9.99
                - layer_id: 12346
                  cogs: 0
                - layer_id: ''
                  cogs: abc
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  valid_rows:
                    type: array
                    items:
                      type: object
                      properties:
                        row_number:
                          type: integer
                        layer_id:
                          type: integer
                        cogs:
                          type: number
                        errors:
                          type: array
                        layer:
                          type: object
                          properties:
                            id:
                              type: integer
                            fnsku:
                              type: string
                            product_sku:
                              type: string
                            current_cogs:
                              type: number
                            qty:
                              type: integer
                  error_rows:
                    type: array
                    items:
                      type: object
                      properties:
                        row_number:
                          type: integer
                        layer_id:
                          type: string
                          nullable: true
                        cogs:
                          type: string
                          nullable: true
                        errors:
                          type: array
                          items:
                            type: string
                  summary:
                    type: object
                    properties:
                      total:
                        type: integer
                      valid:
                        type: integer
                      errors:
                        type: integer
                example:
                  valid_rows:
                  - row_number: 1
                    layer_id: 12345
                    cogs: 9.99
                    errors: []
                    layer:
                      id: 12345
                      fnsku: X001ABC123
                      product_sku: SKU-001
                      current_cogs: 8.5
                      qty: 100
                  - row_number: 2
                    layer_id: 12346
                    cogs: 0
                    errors: []
                    layer:
                      id: 12346
                      fnsku: X001DEF456
                      product_sku: SKU-002
                      current_cogs: 0
                      qty: 50
                  error_rows:
                  - row_number: 3
                    layer_id: null
                    cogs: null
                    errors:
                    - Layer ID is required.
                    - COGS must be a numeric value.
                  summary:
                    total: 3
                    valid: 2
                    errors: 1
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      rows:
                        type: array
                        items:
                          type: string
                example:
                  message: The rows field is required.
                  errors:
                    rows:
                    - The rows field is required.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-amazon-unified-fifo-layers-cogs-import-validate
  /api/amazon/unified/fifo-layers/cogs/import:
    post:
      tags:
      - Amazon
      summary: Execute COGS Import
      description: 'Executes a validated COGS import. Validation rules: rows required
        array min:1; rows.*.layer_id required integer; rows.*.cogs required numeric
        min:0. Each row updates the layer''s cogs and propagates the change to consumptions,
        discrepancies, provisional layers, and pending inbounds. Wrapped in a DB transaction.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                rows:
                  type: array
                  items:
                    type: object
                    properties:
                      layer_id:
                        type: integer
                      cogs:
                        type: number
              example:
                rows:
                - layer_id: 12345
                  cogs: 9.99
                - layer_id: 12346
                  cogs: 4.5
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 OK
                  value:
                    updated_count: 2
                    errors: []
                example-1:
                  summary: 200 OK (with row-level errors)
                  value:
                    updated_count: 1
                    errors:
                    - layer_id: 99999
                      message: Layer not found.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-amazon-unified-fifo-layers-cogs-import
  /api/amazon/unified/fifo-inventory-valuation:
    get:
      tags:
      - Amazon
      summary: Get FIFO Inventory Valuation
      parameters:
      - name: integration_instance_ids
        in: query
        schema:
          type: string
        description: Comma-separated integration instance IDs to scope the query.
      - name: date
        in: query
        schema:
          type: string
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      description: 'Get FIFO Inventory Valuation


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      operationId: get-api-amazon-unified-fifo-inventory-valuation
  /api/amazon/unified/fifo-inventory-valuation/max-date:
    get:
      tags:
      - Amazon
      summary: Get Max Report Date
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      description: 'Get Max Report Date


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      operationId: get-api-amazon-unified-fifo-inventory-valuation-max-date
  /api/amazon/unified/valuation-snapshots:
    get:
      tags:
      - Amazon
      summary: List Valuation Snapshots
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        example: '1'
        description: Page number (default 1).
      - name: per_page
        in: query
        schema:
          type: integer
        example: '10'
        description: Results per page (default 10).
      - name: integration_instance_ids
        in: query
        schema:
          type: string
        description: Comma-separated integration instance IDs to scope the query.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      description: 'List Valuation Snapshots


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      operationId: get-api-amazon-unified-valuation-snapshots
  /api/amazon/unified/valuation-snapshots/totals:
    get:
      tags:
      - Amazon
      summary: Get Valuation Totals
      parameters:
      - name: integration_instance_ids
        in: query
        schema:
          type: string
        description: Comma-separated integration instance IDs to scope the query.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      description: 'Get Valuation Totals


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      operationId: get-api-amazon-unified-valuation-snapshots-totals
  /api/amazon/{integrationInstance}/products:
    get:
      tags:
      - Amazon
      summary: List Amazon Products for Integration
      description: 'Paginated list of `AmazonProduct` rows for one Amazon integration
        instance. Powers the application UI **Amazon → Products** listing page (`AmazonProductsPage`).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Uses Spatie QueryBuilder with `GroupedFilterSupport`, eager-loading `productListing.product.defaultFinancialLineType`
        so the SKU.io mapping is rendered inline.


        **Default behavior:** archived products are hidden (`archived=0`) unless `filter[archived]`
        is supplied. Default sort is `-id`. Default page size is `10`.


        **legacy mode:** when the request carries `table_specifications`, the controller
        falls back to the legacy `abstractIndexForIntegration` list view response
        shape used by the Vue 2 page.


        **Allowed sorts:** `id`, `seller_sku`, `asin1`, `item_name`, `price`, `quantity`,
        `status`, `fulfillment_channel`, `brand`, `product_type`, `created_at`, `updated_at`.


        **Advanced filter operators** are also supported on `seller_sku`, `asin1`,
        `item_name`, `brand`, `product_type` (text), `price` (numeric), `created_at`,
        `updated_at` (datetime) via `filter[<column>][<operator>]=<value>`.


        **Response shape:** standard Laravel paginator wrapping Amazon product object.
        Each row includes catalog attributes, FBA flags, dimensions/weight, and a
        `sku_product` block populated from the linked SKU.io product (when mapped).'
      parameters:
      - name: per_page
        in: query
        schema:
          type: integer
        description: Items per page (default 10)
        example: '10'
      - name: page
        in: query
        schema:
          type: integer
        description: Page number (1-indexed)
        example: '1'
      - name: sort
        in: query
        schema:
          type: string
        description: 'Allowed: id, seller_sku, asin1, item_name, price, quantity,
          status, fulfillment_channel, brand, product_type, created_at, updated_at.
          Prefix with `-` for descending. Default: -id.'
        example: -id
      - name: filter[archived]
        in: query
        schema:
          type: integer
        description: 0 = active (default), 1 (or `true`) = archived only, `only` =
          archived only, `all` = include both.
        example: '0'
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Amazon integration instance ID.
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        seller_sku:
                          type: string
                        asin1:
                          type: string
                        item_name:
                          type: string
                        price:
                          type: number
                        quantity:
                          type: integer
                        status:
                          type: string
                        fulfillment_channel:
                          type: string
                        is_fba:
                          type: boolean
                        label_owner:
                          type: string
                        prep_owner:
                          type: string
                        country_code:
                          type: string
                        brand:
                          type: string
                        manufacturer:
                          type: string
                        model:
                          type: string
                        part_number:
                          type: string
                        product_type:
                          type: string
                        sales_rank:
                          type: integer
                        color:
                          type: string
                        size:
                          type: string
                        style:
                          type: string
                        department:
                          type: string
                        material:
                          type: string
                        package_length:
                          type: number
                        package_width:
                          type: integer
                        package_height:
                          type: integer
                        package_dimensions_unit:
                          type: string
                        package_weight:
                          type: number
                        package_weight_unit:
                          type: string
                        item_length:
                          type: number
                        item_width:
                          type: number
                        item_height:
                          type: number
                        item_dimensions_unit:
                          type: string
                        item_weight:
                          type: number
                        item_weight_unit:
                          type: string
                        item_description:
                          type: string
                        merchant_shipping_group:
                          type: string
                        image_url:
                          type: string
                        main_image:
                          type: string
                        listing_id:
                          type: string
                        open_date:
                          type: string
                        removed_from_amazon:
                          type: boolean
                        was_catalog_data_sync_attempted:
                          type: boolean
                        catalog_data_last_sync:
                          type: string
                        catalog_data:
                          type: object
                          properties:
                            attributes:
                              type: object
                              properties: {}
                        listing_url:
                          type: string
                        is_listing_suppressed:
                          type: boolean
                        has_listing_issues:
                          type: boolean
                        realtime_listing_issues:
                          type: array
                        realtime_listing_status:
                          type: string
                          nullable: true
                        archived_at:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                        updated_at:
                          type: string
                        sku_product:
                          type: object
                          properties:
                            id:
                              type: integer
                            sku:
                              type: string
                            name:
                              type: string
                            barcode:
                              type: string
                            price:
                              type: number
                            type:
                              type: string
                            default_financial_line_type_id:
                              type: string
                              nullable: true
                            default_financial_line_type:
                              type: string
                              nullable: true
                  current_page:
                    type: integer
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                  next_page_url:
                    type: string
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 41201
                    integration_instance_id: 1
                    seller_sku: ABC-001-RED
                    asin1: B0CXYZ1234
                    item_name: Acme Widget — Red, 8oz
                    price: 24.99
                    quantity: 152
                    status: Active
                    fulfillment_channel: AMAZON_NA
                    is_fba: true
                    label_owner: AMAZON
                    prep_owner: AMAZON
                    country_code: US
                    brand: Acme
                    manufacturer: Acme Mfg.
                    model: WID-8
                    part_number: WID-8-RED
                    product_type: BEAUTY
                    sales_rank: 4821
                    color: Red
                    size: 8oz
                    style: Classic
                    department: unisex-adult
                    material: Plastic
                    package_length: 6.5
                    package_width: 4
                    package_height: 3
                    package_dimensions_unit: inches
                    package_weight: 0.45
                    package_weight_unit: pounds
                    item_length: 5.5
                    item_width: 3.5
                    item_height: 2.5
                    item_dimensions_unit: inches
                    item_weight: 0.4
                    item_weight_unit: pounds
                    item_description: Premium red widget.
                    merchant_shipping_group: Migrated Template
                    image_url: https://m.media-amazon.com/images/I/abc.jpg
                    main_image: https://m.media-amazon.com/images/I/abc.jpg
                    listing_id: 0501XXXX1234
                    open_date: '2024-09-12T17:32:00+00:00'
                    removed_from_amazon: false
                    was_catalog_data_sync_attempted: true
                    catalog_data_last_sync: '2026-05-28T14:01:33+00:00'
                    catalog_data:
                      attributes: {}
                    listing_url: https://www.amazon.com/dp/B0CXYZ1234
                    is_listing_suppressed: false
                    has_listing_issues: false
                    realtime_listing_issues: []
                    realtime_listing_status: null
                    archived_at: null
                    created_at: '2024-09-12T17:32:00+00:00'
                    updated_at: '2026-05-28T14:01:33+00:00'
                    sku_product:
                      id: 33421
                      sku: ABC-001-RED
                      name: Acme Widget Red 8oz
                      barcode: 012345678905
                      price: 24.99
                      type: standard
                      default_financial_line_type_id: null
                      default_financial_line_type: null
                  - id: 41205
                    integration_instance_id: 1
                    seller_sku: ABC-002-BLU
                    asin1: B0CXYZ5678
                    item_name: Acme Widget — Blue, 8oz
                    price: 24.99
                    quantity: 0
                    status: Inactive
                    fulfillment_channel: null
                    is_fba: false
                    sku_product: null
                    is_listing_suppressed: false
                    has_listing_issues: false
                    realtime_listing_issues: []
                    realtime_listing_status: null
                  current_page: 1
                  first_page_url: https://example.com/api/amazon/1/products?page=1
                  from: 1
                  last_page: 84
                  last_page_url: https://example.com/api/amazon/1/products?page=84
                  links: []
                  next_page_url: https://example.com/api/amazon/1/products?page=2
                  path: https://example.com/api/amazon/1/products
                  per_page: 2
                  prev_page_url: null
                  to: 2
                  total: 168
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-integrationinstance-products
  /api/amazon/{integrationInstance}/products/{product}:
    get:
      tags:
      - Amazon
      summary: Show Amazon Product
      description: 'Returns a single `AmazonProduct` wrapped in the SKU.io response
        envelope. Delegates to the abstract sales-channel show — the response body
        contains the full Amazon product object payload (same fields as the list endpoint).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        This endpoint is registered automatically by the `Route::salesChannel` macro
        as an `apiResource` (`except index`), so the standard show / store / update
        / destroy routes exist for `/api/amazon/:integrationInstance/products`.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Amazon integration instance ID.
        example: '1'
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: AmazonProduct ID.
        example: '41201'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      seller_sku:
                        type: string
                      asin1:
                        type: string
                      item_name:
                        type: string
                      price:
                        type: number
                      quantity:
                        type: integer
                      status:
                        type: string
                      is_fba:
                        type: boolean
                      listing_url:
                        type: string
                      is_listing_suppressed:
                        type: boolean
                      has_listing_issues:
                        type: boolean
                      realtime_listing_issues:
                        type: array
                      realtime_listing_status:
                        type: string
                        nullable: true
                      sku_product:
                        type: string
                        nullable: true
                example:
                  data:
                    id: 41201
                    integration_instance_id: 1
                    seller_sku: ABC-001-RED
                    asin1: B0CXYZ1234
                    item_name: Acme Widget — Red, 8oz
                    price: 24.99
                    quantity: 152
                    status: Active
                    is_fba: true
                    listing_url: https://www.amazon.com/dp/B0CXYZ1234
                    is_listing_suppressed: false
                    has_listing_issues: false
                    realtime_listing_issues: []
                    realtime_listing_status: null
                    sku_product: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-integrationinstance-products-product
  /api/amazon/product/{product}/update-metadata:
    put:
      tags:
      - Amazon
      summary: Update Single Product Metadata (Label / Prep Owner)
      description: 'Patches the `metadata.label_owner` / `metadata.prep_owner` fields
        on the Amazon product associated with a SKU.io `ProductListing`. Used by the
        FBA prep configuration UI.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Body (both optional, but at least one should be supplied — `nullable|string`
        validation):**

        - `label_owner` (string|null) — typically `AMAZON` or `SELLER`.

        - `prep_owner` (string|null) — typically `AMAZON` or `SELLER`.


        **Note:** the route binds `ProductListing` (not `AmazonProduct`) — the controller
        resolves the Amazon listing via `$product->amazonListing` and merges the fields
        into its existing `metadata` array before saving.


        Named route: `amazon.product.update-metadata` (note the singular `product`
        — distinct from the bulk `amazon.products.*` namespace).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                label_owner:
                  type: string
                prep_owner:
                  type: string
              example:
                label_owner: AMAZON
                prep_owner: SELLER
      parameters:
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: ProductListing ID (NOT AmazonProduct ID). The bound model is
          `ProductListing`; the controller updates the related `amazonListing` (`amazon_products`)
          row's `metadata` JSON column.
        example: '9871'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Metadata updated successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-amazon-product-product-update-metadata
  /api/amazon/{integrationInstance}/products/{product}/archive:
    post:
      tags:
      - Amazon
      summary: Archive Single Product
      description: 'Archives a single Amazon product. The product is reloaded with
        `productListing.product.defaultFinancialLineType` + `productListing.subscriptionOffering`
        and returned as an Amazon product object.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Named route: `amazon.products.archive` (single — distinct from the bulk PUT
        `/archive` endpoint above).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties: {}
              example: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Amazon integration instance ID.
        example: '1'
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: AmazonProduct ID.
        example: '41201'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      seller_sku:
                        type: string
                      asin1:
                        type: string
                      item_name:
                        type: string
                      status:
                        type: string
                      archived_at:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 41201
                    seller_sku: ABC-001-RED
                    asin1: B0CXYZ1234
                    item_name: Acme Widget — Red, 8oz
                    status: Active
                    archived_at: '2026-05-29T10:14:22+00:00'
                  message: Product archived successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-amazon-integrationinstance-products-product-archive
  /api/amazon/{integrationInstance}/products/{product}/unarchive:
    post:
      tags:
      - Amazon
      summary: Unarchive Single Product
      description: 'Unarchives a single Amazon product. Returns the refreshed product
        as an Amazon product object.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Named route: `amazon.products.unarchive` (single).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties: {}
              example: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Amazon integration instance ID.
        example: '1'
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: AmazonProduct ID.
        example: '41201'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      seller_sku:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                  message:
                    type: string
                example:
                  data:
                    id: 41201
                    seller_sku: ABC-001-RED
                    archived_at: null
                  message: Product unarchived successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-amazon-integrationinstance-products-product-unarchive
  /api/amazon/{integrationInstance}/products/{product}/refresh:
    post:
      tags:
      - Amazon
      summary: Refresh Single Product (Catalog Lookup)
      description: 'Refreshes a single product''s catalog data directly from Amazon''s
        SP-API catalog endpoint. Updates `catalog_data`, `catalog_data_last_sync`,
        `was_catalog_data_sync_attempted`, and `removed_from_amazon` in place, then
        returns the refreshed Amazon product object.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Returns HTTP 403 when the product does not belong to the given integration
        instance, HTTP 500 on Amazon API failure (with error message in `error`).


        Named route: `amazon.products.refresh` (single).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties: {}
              example: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Amazon integration instance ID.
        example: '1'
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: AmazonProduct ID.
        example: '41201'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      seller_sku:
                        type: string
                      asin1:
                        type: string
                      was_catalog_data_sync_attempted:
                        type: boolean
                      catalog_data_last_sync:
                        type: string
                      removed_from_amazon:
                        type: boolean
                  message:
                    type: string
                example:
                  data:
                    id: 41201
                    seller_sku: ABC-001-RED
                    asin1: B0CXYZ1234
                    was_catalog_data_sync_attempted: true
                    catalog_data_last_sync: '2026-05-29T10:14:22+00:00'
                    removed_from_amazon: false
                  message: Product refreshed successfully.
        '403':
          description: Forbidden
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: Product does not belong to this integration instance
        '429': *id001
        '401': *id002
        '404': *id004
        '422': *id005
      operationId: post-api-amazon-integrationinstance-products-product-refresh
  /api/amazon/{integrationInstance}/products/{product}/raw:
    get:
      tags:
      - Amazon
      summary: Get Raw Catalog Data from Amazon
      description: 'Forces a live catalog lookup against Amazon for a single product
        and then returns the *raw* sync output: ASIN, `catalog_data`, `catalog_data_last_sync`,
        `was_catalog_data_sync_attempted`, `removed_from_amazon`, and the underlying
        `json_object` for the row.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Used by the **Debug Raw** drawer on the products page.


        **Errors:**

        - `403` — the product does not belong to the given integration instance.

        - `422` — the product has no `asin1` to look up.

        - `500` — Amazon API call failed (error message returned in `message`).


        Named route: `amazon.products.raw`.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Amazon integration instance ID.
        example: '1'
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: AmazonProduct ID.
        example: '41201'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      asin:
                        type: string
                      catalog_data:
                        type: object
                        properties:
                          summaries:
                            type: array
                            items:
                              type: object
                              properties:
                                marketplaceId:
                                  type: string
                                itemName:
                                  type: string
                                brandName:
                                  type: string
                      catalog_data_last_sync:
                        type: string
                      was_catalog_data_sync_attempted:
                        type: boolean
                      removed_from_amazon:
                        type: boolean
                      json_object:
                        type: object
                        properties:
                          seller-sku:
                            type: string
                          asin1:
                            type: string
                example:
                  data:
                    asin: B0CXYZ1234
                    catalog_data:
                      summaries:
                      - marketplaceId: ATVPDKIKX0DER
                        itemName: Acme Widget — Red, 8oz
                        brandName: Acme
                    catalog_data_last_sync: '2026-05-29T10:14:22+00:00'
                    was_catalog_data_sync_attempted: true
                    removed_from_amazon: false
                    json_object:
                      seller-sku: ABC-001-RED
                      asin1: B0CXYZ1234
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: Product has no ASIN to look up.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-integrationinstance-products-product-raw
  /api/amazon/{integrationInstance}/products/{product}/create-sku-product:
    post:
      tags:
      - Amazon
      summary: Create SKU.io Product from Amazon Product
      description: 'Single-row variant of the bulk Create-SKU-Products endpoint. Used
        by the per-row **Create SKU.io Product** button in the unified mapping modal
        (Amazon parity with Faire/Shopify).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Behavior:

        - If the Amazon product already has a mapping (`productListing`), returns
        HTTP 422.

        - If a SKU.io `products.sku` row already exists matching the Amazon `seller_sku`,
        the existing product is linked (no duplicate is created) — `linked_existing:
        true` in the response.

        - Otherwise, a new SKU.io product is created and mapped.


        Returns HTTP 201 in both link and create cases, with the refreshed Amazon
        product object.


        Named route: `amazon.products.create-sku-product`.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties: {}
              example: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Amazon integration instance ID.
        example: '1'
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: AmazonProduct ID.
        example: '41201'
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: Success — New SKU.io Product Created
                  value:
                    data:
                      id: 41201
                      seller_sku: ABC-001-RED
                      asin1: B0CXYZ1234
                      item_name: Acme Widget — Red, 8oz
                      sku_product:
                        id: 33425
                        sku: ABC-001-RED
                        name: Acme Widget — Red, 8oz
                        type: standard
                    linked_existing: false
                    message: SKU product created and mapped successfully.
                example-1:
                  summary: Success — Linked to Existing SKU.io Product
                  value:
                    data:
                      id: 41201
                      seller_sku: ABC-001-RED
                      sku_product:
                        id: 33421
                        sku: ABC-001-RED
                        name: Acme Widget Red 8oz
                        type: standard
                    linked_existing: true
                    message: Product linked to existing SKU product successfully.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: Product is already mapped. Unmap it first.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-amazon-integrationinstance-products-product-create-sku-product
  /api/amazon/{integrationInstance}/products/{product}/map:
    post:
      tags:
      - Amazon
      summary: Map Single Product to SKU.io Product
      description: 'Per-row mapping endpoint used by the unified products mapping
        modal (Faire/Shopify parity). Maps a single Amazon product to either an existing
        SKU.io product (`product_id`) or a subscription offering (`subscription_offering_id`).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Body (one of, required):**

        - `product_id` (int, required_without:subscription_offering_id, must exist
        in `products`) — link to a SKU.io product.

        - `subscription_offering_id` (int, required_without:product_id, must exist
        in `subscription_offerings`) — link to a subscription offering.


        Behavior:

        - If the Amazon product is already mapped (`productListing` exists), the existing
        row is updated in place — supports the Remap flow.

        - Otherwise a new `ProductListing` row is created with `sales_channel_id`
        = the instance''s sales channel, `listing_sku` = `seller_sku`, `document_type`
        = `AmazonProduct::class`.

        - After mapping, any unmapped `SalesOrderLine` rows matching this listing
        are dispatched to a background job so back-fill happens automatically.


        Returns HTTP 201 with the refreshed Amazon product object.


        Named route: `amazon.products.map` (single).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                product_id:
                  type: integer
              example:
                product_id: 33421
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Amazon integration instance ID.
        example: '1'
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: AmazonProduct ID.
        example: '41201'
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      seller_sku:
                        type: string
                      asin1:
                        type: string
                      item_name:
                        type: string
                      sku_product:
                        type: object
                        properties:
                          id:
                            type: integer
                          sku:
                            type: string
                          name:
                            type: string
                          type:
                            type: string
                  message:
                    type: string
                example:
                  data:
                    id: 41201
                    seller_sku: ABC-001-RED
                    asin1: B0CXYZ1234
                    item_name: Acme Widget — Red, 8oz
                    sku_product:
                      id: 33421
                      sku: ABC-001-RED
                      name: Acme Widget Red 8oz
                      type: standard
                  message: Product mapped successfully.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      product_id:
                        type: array
                        items:
                          type: string
                      subscription_offering_id:
                        type: array
                        items:
                          type: string
                example:
                  message: The product id field is required when subscription offering
                    id is not present.
                  errors:
                    product_id:
                    - The product id field is required when subscription offering
                      id is not present.
                    subscription_offering_id:
                    - The subscription offering id field is required when product
                      id is not present.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-amazon-integrationinstance-products-product-map
    delete:
      tags:
      - Amazon
      summary: Unmap Single Product
      description: 'Removes the existing `ProductListing` link between an Amazon product
        and its SKU.io product. Returns HTTP 422 with `Product is not mapped.` when
        no mapping exists.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Returns the refreshed Amazon product object (with `sku_product: null`).


        Named route: `amazon.products.unmap`.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Amazon integration instance ID.
        example: '1'
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: AmazonProduct ID.
        example: '41201'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      seller_sku:
                        type: string
                      asin1:
                        type: string
                      sku_product:
                        type: string
                        nullable: true
                  message:
                    type: string
                example:
                  data:
                    id: 41201
                    seller_sku: ABC-001-RED
                    asin1: B0CXYZ1234
                    sku_product: null
                  message: Product unmapped successfully.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: Product is not mapped.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-amazon-integrationinstance-products-product-map
  /api/amazon/{integrationInstance}/products/{product}/orders:
    get:
      tags:
      - Amazon
      summary: Get Orders for Product
      description: 'Paginated list of Amazon orders (`AmazonOrder`) that include a
        line item with this product''s `seller_sku`. Orders are returned sorted by
        `PurchaseDate` (newest first) and wrapped in Amazon order object. Used by
        the **Recent Orders** lazy-loading tab on the product detail/mapping modal.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Returns HTTP 403 when the product does not belong to the given integration
        instance.


        **Note:** the response shape is hand-built (not a Laravel paginator dump)
        — it includes `current_page`, `last_page`, `per_page`, `total`, `from`, `to`
        alongside the `data` array.


        Named route: `amazon.products.orders`.'
      parameters:
      - name: per_page
        in: query
        schema:
          type: integer
        description: Items per page (default 10).
        example: '10'
      - name: page
        in: query
        schema:
          type: integer
        description: Page number (default 1).
        example: '1'
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Amazon integration instance ID.
        example: '1'
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: AmazonProduct ID.
        example: '41201'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        AmazonOrderId:
                          type: string
                        PurchaseDate:
                          type: string
                        OrderStatus:
                          type: string
                        OrderTotal:
                          type: object
                          properties:
                            Amount:
                              type: string
                            CurrencyCode:
                              type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - id: 990125
                    AmazonOrderId: 114-1234567-1234567
                    PurchaseDate: '2026-05-25T18:42:11+00:00'
                    OrderStatus: Shipped
                    OrderTotal:
                      Amount: '24.99'
                      CurrencyCode: USD
                  current_page: 1
                  last_page: 3
                  per_page: 10
                  total: 22
                  from: 1
                  to: 10
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-integrationinstance-products-product-orders
  /api/amazon/{integrationInstance}/products/latest-sync-info:
    get:
      tags:
      - Amazon
      summary: Get Latest Sync Info
      description: 'Sync summary card data for the **Amazon → Products** page header
        chip — last sync timestamp, total/ mapped/unmapped product counts, and the
        title/date of the most recently updated product.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Named route: `amazon.products.latest-sync-info`.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Amazon integration instance ID.
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      latest_product_title:
                        type: string
                      latest_product_date:
                        type: string
                      total_products:
                        type: integer
                      mapped_products:
                        type: integer
                      unmapped_products:
                        type: integer
                      last_synced_at:
                        type: string
                example:
                  data:
                    latest_product_title: Acme Widget — Red, 8oz
                    latest_product_date: '2026-05-28T14:01:33+00:00'
                    total_products: 168
                    mapped_products: 142
                    unmapped_products: 26
                    last_synced_at: '2026-05-28T14:01:33'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-integrationinstance-products-latest-sync-info
  /api/amazon/{integrationInstance}/products/refresh:
    post:
      tags:
      - Amazon
      summary: Refresh All Products (Tracked)
      description: 'Triggers an asynchronous Amazon report request to refresh the
        catalog. Returns immediately with a queued-message; progress is surfaced via
        the tracked job log endpoints (a background job).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Named route: `amazon.products.refresh`.


        Returns **409 Conflict** when an Amazon `GET_MERCHANT_LISTINGS_ALL_DATA` report
        is already in progress for this integration instance (Amazon SP-API permits
        only one report of a given type at a time). The response includes a `conflicting_report`
        object with the in-progress report''s id, type, processing status, and creation
        time.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties: {}
              example: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Amazon integration instance ID.
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: string
                    nullable: true
                  message:
                    type: string
                example:
                  data: null
                  message: Added to queue, products will be refreshed shortly.
        '409':
          description: Conflict
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  conflicting_report:
                    type: object
                    properties:
                      id:
                        type: integer
                      report_type:
                        type: string
                      processing_status:
                        type: string
                      created_at:
                        type: string
                example:
                  message: A products refresh is already in progress. Please wait
                    for it to finish before starting another.
                  conflicting_report:
                    id: 505714
                    report_type: GET_MERCHANT_LISTINGS_ALL_DATA
                    processing_status: IN_QUEUE
                    created_at: '2026-06-28T13:16:42+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-amazon-integrationinstance-products-refresh
  /api/amazon/{integrationInstance}/products/export:
    get:
      tags:
      - Amazon
      summary: Export Products
      description: 'Streams an export of the integration instance''s Amazon products
        (CSV/XLSX) using the abstract sales-channel exporter. Returns a `BinaryFileResponse`,
        a `RedirectResponse` (when async export is dispatched), or the SKU.io response
        envelope on failure.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Throws `ExportingEmptyDataException` (handled by the global error handler)
        if the result set is empty.


        Named route: `amazon.products.export`.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Amazon integration instance ID.
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: text/csv
            Content-Disposition:
              schema:
                type: string
                example: attachment; filename="amazon-products.csv"
          content:
            text/plain:
              schema:
                type: string
                example: 'id,seller_sku,asin1,item_name,price,quantity,status,fulfillment_channel

                  41201,ABC-001-RED,B0CXYZ1234,"Acme Widget — Red, 8oz",24.99,152,Active,AMAZON_NA

                  '
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-integrationinstance-products-export
  /api/amazon/{integrationInstance}/products/create-sku-products:
    post:
      tags:
      - Amazon
      summary: Create SKU.io Products (Bulk)
      description: 'Bulk-creates SKU.io products from a selection of Amazon products.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Body (`CreateSkuProductsFromSalesChannelData`):**

        - `create_all_products` (bool, required) — when true, all products for this
        integration instance are queued.

        - `ids` (`array<int>`, required unless `create_all_products` or `filters`
        is supplied) — explicit AmazonProduct IDs.

        - `mappings` (`array<DataImportMappingData>`, optional) — `{ original_name,
        stored_name }` entries persisted.

        - `filters` (string|null, optional) — when present, IDs are resolved from
        the filter set instead of from `ids`.

        - `initial_mapping` (bool, default false) — internal flag used by the import
        wizard.


        Returns immediately with a queued message; the manager job actually creates
        the SKU.io products and the corresponding `ProductListing` mappings.


        Named route: `amazon.products.create-sku-products`.


        Bulk selection contract:

        - {"create_all_products": false, "ids": [1, 2]} — create for the given channel
        product IDs

        - {"create_all_products": true} — create for all unmapped products on the
        integration instance

        - {"create_all_products": true, "filters": {...}} — create only for products
        matching the filters. The filters object accepts the same filter keys as the
        corresponding products list endpoint (bare column keys) and/or a "filter_groups"
        tree (base64-encoded JSON). When filters match no products, nothing is created
        and the response message is "No products to create".

        - create_all_products is required; ids is required when create_all_products
        is false and no filters are sent.

        - Legacy {"conjunction", "filterSet"} filter payloads are rejected with 422.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                create_all_products:
                  type: boolean
                ids:
                  type: array
                  items:
                    type: integer
                mappings:
                  type: array
                initial_mapping:
                  type: boolean
              example:
                create_all_products: false
                ids:
                - 41201
                - 41205
                mappings: []
                initial_mapping: false
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Amazon integration instance ID.
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: string
                    nullable: true
                  message:
                    type: string
                example:
                  data: null
                  message: Added to queue, products will be created shortly.
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: object
                    properties:
                      apiErrors:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: array
                example:
                  errors:
                    apiErrors:
                    - message: Amazon product (ID 1234) has no SKU and cannot be imported.
                      code: Missing SKU
                      data: []
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-amazon-integrationinstance-products-create-sku-products
  /api/amazon/{integrationInstance}/products/map:
    put:
      tags:
      - Amazon
      summary: Map Products to SKU.io Products (Bulk)
      description: "Bulk-maps Amazon products to existing SKU.io products (or `subscription_offering_id`)\
        \ in a single call. Used by the legacy import wizard.\n\n:::info[Authorization]\n\
        Any valid API token can call this endpoint — no specific scope required. [Manage\
        \ tokens](https://app.sku.io/settings/api).\n:::\n\n**Body (`SalesChannelProductToSkuProductMappingCollectionData`):**\n\
        - `mapping` (array, min 1) — each item is a `SalesChannelProductToSkuProductMappingData`:\n\
        \  - `sales_channel_listing_id` (string, required) — usually the Amazon `seller_sku`.\n\
        \  - `mapped_sku` (string|null) — SKU.io `products.sku` to map to. Empty string\
        \ is coerced to null (i.e. an unmap).\n  - `product_listing_id` (int|null,\
        \ optional) — existing `product_listings` row to update.\n  - `subscription_offering_id`\
        \ (int|null, optional) — map to a subscription offering instead of a product.\n\
        \n**Validation:** `salesChannelProductMappingsValidation()` enforces that\
        \ FBA listings can only be mapped to `standard`, `kit`, or `blemished` product\
        \ types, and that non-FBA listings additionally accept `bundle`. Returns HTTP\
        \ 402 with an error message on violation.\n\nThrows `SalesChannelProductMappingException`\
        \ → HTTP 400 with the exception message.\n\nNamed route: `amazon.products.map`."
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                mapping:
                  type: array
                  items:
                    type: object
                    properties:
                      sales_channel_listing_id:
                        type: string
                      mapped_sku:
                        type: string
              example:
                mapping:
                - sales_channel_listing_id: ABC-001-RED
                  mapped_sku: ABC-001-RED
                - sales_channel_listing_id: ABC-002-BLU
                  mapped_sku: WID-BLU-8
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Amazon integration instance ID.
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: string
                example:
                  data: Successfully mapped sales channel products to sku products
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-amazon-integrationinstance-products-map
  /api/amazon/{integrationInstance}/products/import-mappings:
    post:
      tags:
      - Amazon
      summary: Import Mappings (CSV/XLSX)
      description: 'Queues a background job on the `serial` queue to apply Amazon
        → SKU.io product mappings from a previously uploaded file.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Body (`SalesChannelProductImportMappingData`):**

        - `original_name` (string, required) — original filename as uploaded.

        - `stored_name` (string, required) — server-side filename (returned by the
        file upload endpoint).


        Named route: `amazon.products.import-mappings`.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                original_name:
                  type: string
                stored_name:
                  type: string
              example:
                original_name: amazon-mappings-2026-05.csv
                stored_name: uploads/imports/amazon-mappings-2026-05-xyz123.csv
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Amazon integration instance ID.
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: string
                    nullable: true
                  message:
                    type: string
                example:
                  data: null
                  message: Added to queue, mappings will be imported shortly.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-amazon-integrationinstance-products-import-mappings
  /api/amazon/{integrationInstance}/products/archive:
    put:
      tags:
      - Amazon
      summary: Archive Products (Bulk)
      description: 'Bulk-archives Amazon products. Body accepts either an explicit
        ID list, or `mode: "all"` to archive every product for this integration instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Body:**

        - `ids` (`array<int>`, required unless `mode = all`) — validated against existing
        IDs for this integration instance.

        - `mode` (string, optional) — set to `"all"` to bypass `ids` and operate on
        every product.


        Named route: `amazon.products.archive`.


        Bulk selection contract:

        - {"ids": [1, 2]} — act on the given channel product IDs

        - {"mode": "all"} — act on all products for the integration instance

        - {"apply_to_all": true, "filters": {...}} — act only on products matching
        the filters. The filters object accepts the same filter keys as the corresponding
        products list endpoint (bare column keys) and/or a "filter_groups" tree (base64-encoded
        JSON). With apply_to_all and no filters, all products for the instance are
        targeted.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 41201
                - 41205
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Amazon integration instance ID.
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: string
                    nullable: true
                  message:
                    type: string
                example:
                  data: null
                  message: Products archived successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-amazon-integrationinstance-products-archive
  /api/amazon/{integrationInstance}/products/unarchive:
    put:
      tags:
      - Amazon
      summary: Unarchive Products (Bulk)
      description: 'Bulk-unarchives previously archived Amazon products. Same body
        shape as the bulk Archive endpoint (`ids` or `mode = "all"`).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Named route: `amazon.products.unarchive`.


        Bulk selection contract:

        - {"ids": [1, 2]} — act on the given channel product IDs

        - {"mode": "all"} — act on all products for the integration instance

        - {"apply_to_all": true, "filters": {...}} — act only on products matching
        the filters. The filters object accepts the same filter keys as the corresponding
        products list endpoint (bare column keys) and/or a "filter_groups" tree (base64-encoded
        JSON). With apply_to_all and no filters, all products for the instance are
        targeted.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 41201
                - 41205
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Amazon integration instance ID.
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: string
                    nullable: true
                  message:
                    type: string
                example:
                  data: null
                  message: Products unarchived successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-amazon-integrationinstance-products-unarchive
  /api/amazon/{integrationInstance}/products/archiveable:
    post:
      tags:
      - Amazon
      summary: Check Archiveable
      description: 'Pre-flight check that returns per-product status (`can_archive`
        / reason if not) for the supplied selection. Used by the UI to disable Archive
        in bulk-action menus when some rows can''t be archived (e.g. they have open
        orders).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Body:** same as the bulk Archive endpoint — `ids` (array) or `mode: "all"`.


        Named route: `amazon.products.archiveable`.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 41201
                - 41205
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Amazon integration instance ID.
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        can_archive:
                          type: boolean
                        reason:
                          type: string
                          nullable: true
                example:
                  data:
                  - id: 41201
                    can_archive: true
                    reason: null
                  - id: 41205
                    can_archive: false
                    reason: Product has linked orders.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-amazon-integrationinstance-products-archiveable
  /api/amazon/{integrationInstance}/products/delete:
    put:
      tags:
      - Amazon
      summary: Delete Products (Bulk)
      description: 'Bulk-deletes Amazon product records (and their `ProductListing`
        rows). Body accepts `ids` (array) or `mode: "all"`.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Named route: `amazon.products.delete`.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 41201
                - 41205
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Amazon integration instance ID.
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: string
                    nullable: true
                  message:
                    type: string
                example:
                  data: null
                  message: Products deleted successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-amazon-integrationinstance-products-delete
  /api/amazon/{integrationInstance}/products/deleteable:
    put:
      tags:
      - Amazon
      summary: Check Deleteable
      description: 'Pre-flight check for the bulk-delete action. Returns per-product
        `can_delete` / `reason` so the UI can disable Delete in the bulk-action menu
        when some rows can''t be removed (typically because they have linked orders
        or inventory movements).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Body:** `ids` (array) or `mode: "all"`.


        Named route: `amazon.products.deleteable`.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 41201
                - 41205
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Amazon integration instance ID.
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        can_delete:
                          type: boolean
                        reason:
                          type: string
                          nullable: true
                example:
                  data:
                  - id: 41201
                    can_delete: true
                    reason: null
                  - id: 41205
                    can_delete: false
                    reason: Product has linked orders.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-amazon-integrationinstance-products-deleteable
  /api/amazon/{integrationInstance}/products/sync-inventory:
    post:
      tags:
      - Amazon
      summary: Sync Inventory to Amazon
      description: 'Submits the supplied SKU.io `product_listings` IDs to Amazon as
        an inventory feed. The controller groups listings by Amazon marketplace country
        code and dispatches one sync per group so that each marketplace gets its own
        feed.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Body:**

        - `ids` (`array<int>`, optional) — `product_listings.id` values to sync. When
        omitted, the underlying manager defaults are used.


        Named route: `amazon.products.sync-inventory`.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 9871
                - 9872
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Amazon integration instance ID.
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: string
                    nullable: true
                  message:
                    type: string
                example:
                  data: null
                  message: Successfully submitted to sales channel.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-amazon-integrationinstance-products-sync-inventory
  /api/amazon/{integrationInstance}/fnsku-products/{fnskuProduct}:
    get:
      tags:
      - Amazon
      summary: Show FNSKU Product
      description: 'Get details of a specific FNSKU product.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: fnskuProduct
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The fnsku product ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      fnsku:
                        type: string
                      location:
                        type: string
                      disposition:
                        type: string
                      initial_unit_cost:
                        type: number
                      product:
                        type: object
                        properties:
                          id:
                            type: integer
                          sku:
                            type: string
                example:
                  data:
                    id: 1
                    fnsku: X001ABC123
                    location: US
                    disposition: SELLABLE
                    initial_unit_cost: 12.5
                    product:
                      id: 42
                      sku: WIDGET-RED
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-integrationinstance-fnsku-products-fnskuproduct
  /api/amazon/{integrationInstance}/fnsku-products/create:
    post:
      tags:
      - Amazon
      summary: Generate FNSKU Products
      description: 'Generate FNSKU product records from inventory data.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      created:
                        type: integer
                      skipped:
                        type: integer
                example:
                  message: FNSKU products generated successfully
                  data:
                    created: 15
                    skipped: 5
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-amazon-integrationinstance-fnsku-products-create
  /api/amazon/{integrationInstance}/fnsku-products/link-to-product:
    post:
      tags:
      - Amazon
      summary: Link FNSKU to Product
      description: 'Link a FNSKU product to an internal product.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                fnsku_product_id:
                  type: integer
                product_id:
                  type: integer
              example:
                fnsku_product_id: 1
                product_id: 42
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: FNSKU product linked to product successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-amazon-integrationinstance-fnsku-products-link-to-product
  /api/amazon/{integrationInstance}/fnsku-products/bulk-map-by-asin:
    post:
      tags:
      - Amazon
      summary: Bulk Map by ASIN
      description: 'Bulk map FNSKU products by ASIN to internal products.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                mappings:
                  type: array
                  items:
                    type: object
                    properties:
                      asin:
                        type: string
                      product_id:
                        type: integer
              example:
                mappings:
                - asin: B08XYZ1234
                  product_id: 42
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      mapped:
                        type: integer
                example:
                  message: Bulk ASIN mapping completed
                  data:
                    mapped: 10
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-amazon-integrationinstance-fnsku-products-bulk-map-by-asin
  /api/amazon/{integrationInstance}/fnsku-products/auto-mapping-settings:
    get:
      tags:
      - Amazon
      summary: Get Auto-Mapping Settings
      description: 'Get FNSKU auto-mapping settings for an integration instance. Returns
        whether new FNSKUs are automatically mapped to a product when a matching ASIN
        mapping already exists. Email and in-app alerts for unmapped FNSKUs are configured
        separately via alert notification preferences.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  data:
                    type: object
                    properties:
                      is_fnsku_auto_mapping_enabled:
                        type: boolean
                example:
                  status: success
                  data:
                    is_fnsku_auto_mapping_enabled: true
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-integrationinstance-fnsku-products-auto-mapping-settings
    put:
      tags:
      - Amazon
      summary: Update Auto-Mapping Settings
      description: 'Update FNSKU auto-mapping settings for an integration instance.
        Accepts `is_fnsku_auto_mapping_enabled` (boolean) to control whether new FNSKUs
        are automatically mapped when a matching ASIN mapping exists. Email and in-app
        alerts for unmapped FNSKUs are configured separately via alert notification
        preferences.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                is_fnsku_auto_mapping_enabled:
                  type: boolean
              example:
                is_fnsku_auto_mapping_enabled: true
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                example:
                  status: success
                  message: Auto-mapping settings updated successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-amazon-integrationinstance-fnsku-products-auto-mapping-settings
  /api/amazon/{integrationInstance}/fnsku-products/activity-log:
    get:
      tags:
      - Amazon
      summary: Get Activity Log
      description: 'Get FNSKU product mapping activity log for an integration instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        example: '1'
        description: Page number (default 1).
      - name: per_page
        in: query
        schema:
          type: integer
        example: '20'
        description: Results per page (default 10).
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        event:
                          type: string
                        fnsku:
                          type: string
                        product_sku:
                          type: string
                        created_at:
                          type: string
                  current_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 1
                    event: mapped
                    fnsku: X001ABC123
                    product_sku: WIDGET-RED
                    created_at: '2024-06-01T10:00:00.000Z'
                  current_page: 1
                  total: 50
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-integrationinstance-fnsku-products-activity-log
  /api/amazon/{integrationInstance}/fba-inventory/{id}:
    get:
      tags:
      - Amazon
      summary: Show FBA Inventory Record
      description: 'Get a specific FBA inventory report record.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: id
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The record ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      fnsku:
                        type: string
                      asin:
                        type: string
                      sellable_quantity:
                        type: integer
                      unsellable_quantity:
                        type: integer
                example:
                  data:
                    id: 1
                    fnsku: X001ABC123
                    asin: B08XYZ1234
                    sellable_quantity: 250
                    unsellable_quantity: 5
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-integrationinstance-fba-inventory-id
  /api/amazon/{integrationInstance}/ledger-summaries/{id}:
    get:
      tags:
      - Amazon
      summary: Show Ledger Summary
      description: 'Get a specific ledger summary record.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: id
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The record ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      date:
                        type: string
                      fnsku:
                        type: string
                      starting_warehouse_balance:
                        type: integer
                      ending_warehouse_balance:
                        type: integer
                      receipts:
                        type: integer
                      customer_shipments:
                        type: integer
                example:
                  data:
                    id: 1
                    date: '2024-06-01'
                    fnsku: X001ABC123
                    starting_warehouse_balance: 200
                    ending_warehouse_balance: 250
                    receipts: 60
                    customer_shipments: 10
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-integrationinstance-ledger-summaries-id
  /api/amazon/{integrationInstance}/ledgers/customer-returns/{customer_return}:
    get:
      tags:
      - Amazon
      summary: Get Customer Return (Per Instance)
      description: 'Get a single FBA customer return report row by ID. Rows are imported
        from the Amazon FBA customer returns report and describe one returned unit
        event: order_id, sku, asin, fnsku, product_name, quantity, fulfillment_center_id,
        detailed_disposition (e.g. SELLABLE, CUSTOMER_DAMAGED), reason, status, license_plate_number,
        customer_comments, plus review metadata (reviewed_at) and the return timestamps
        (return_date, event_datetime) in UTC ISO 8601 format.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        linked_sales_order is populated on the list endpoints (where matching sales
        orders are resolved in bulk) and is null on this detail endpoint. Returns
        404 for an unknown ID.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Amazon integration instance ID
        example: '1'
      - name: customer_return
        in: path
        schema:
          type: integer
        required: true
        description: Customer return record ID
        example: '5121'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      event_datetime:
                        type: string
                      order_id:
                        type: string
                      sku:
                        type: string
                      asin:
                        type: string
                      fnsku:
                        type: string
                      product_name:
                        type: string
                      quantity:
                        type: integer
                      fulfillment_center_id:
                        type: string
                      detailed_disposition:
                        type: string
                      reason:
                        type: string
                      status:
                        type: string
                      license_plate_number:
                        type: string
                      customer_comments:
                        type: string
                        nullable: true
                      reviewed_at:
                        type: string
                        nullable: true
                      linked_sales_order:
                        type: string
                        nullable: true
                      integration_instance_id:
                        type: integer
                      return_date:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                  status:
                    type: string
                example:
                  data:
                    id: 5121
                    event_datetime: '2026-05-14T10:22:00.000000Z'
                    order_id: 113-9184620-7712345
                    sku: LS-RAZOR-BLK
                    asin: B08K4F9TXQ
                    fnsku: X002ABCDE1
                    product_name: Leaf Razor, Black
                    quantity: 1
                    fulfillment_center_id: PHX7
                    detailed_disposition: SELLABLE
                    reason: NO_REASON_GIVEN
                    status: Unit returned to inventory
                    license_plate_number: LPNRR902184713
                    customer_comments: null
                    reviewed_at: null
                    linked_sales_order: null
                    integration_instance_id: 1
                    return_date: '2026-05-14T10:22:00.000000Z'
                    created_at: '2026-05-15T02:10:11.000000Z'
                    updated_at: '2026-05-15T02:10:11.000000Z'
                  status: success
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Not Found
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-amazon-integrationinstance-ledgers-customer-returns-customer-return
  /api/amazon/{integrationInstance}/ledgers/shipments/{shipment}:
    get:
      tags:
      - Amazon
      summary: Get FBA Shipment Record (Per Instance)
      description: 'Get a single Amazon-fulfilled shipment report row by ID. Rows
        are imported from the Amazon fulfilled shipments report and describe one shipped
        order item: Amazon order/item identifiers, purchase, payment, shipment and
        reporting timestamps (UTC ISO 8601), buyer and recipient details, ship-to
        and bill-to addresses, item/shipping/gift-wrap prices and taxes, promotion
        discounts, carrier and tracking number, fulfillment center, fulfillment channel
        and sales channel.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Returns 404 for an unknown ID.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Amazon integration instance ID
        example: '1'
      - name: shipment
        in: path
        schema:
          type: integer
        required: true
        description: FBA shipment report record ID
        example: '90233'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      amazon_order_id:
                        type: string
                      merchant_order_id:
                        type: string
                        nullable: true
                      shipment_id:
                        type: string
                      shipment_item_id:
                        type: string
                      amazon_order_item_id:
                        type: string
                      merchant_order_item_id:
                        type: string
                        nullable: true
                      purchase_date:
                        type: string
                      payments_date:
                        type: string
                      shipment_date:
                        type: string
                      reporting_date:
                        type: string
                      event_datetime:
                        type: string
                      buyer_name:
                        type: string
                      buyer_phone_number:
                        type: string
                        nullable: true
                      sku:
                        type: string
                      product_name:
                        type: string
                      quantity_shipped:
                        type: integer
                      currency:
                        type: string
                      item_price:
                        type: integer
                      item_tax:
                        type: number
                      shipping_price:
                        type: integer
                      shipping_tax:
                        type: integer
                      gift_wrap_price:
                        type: integer
                      gift_wrap_tax:
                        type: integer
                      ship_service_level:
                        type: string
                      recipient_name:
                        type: string
                      ship_address_1:
                        type: string
                      ship_address_2:
                        type: string
                        nullable: true
                      ship_address_3:
                        type: string
                        nullable: true
                      ship_city:
                        type: string
                      ship_state:
                        type: string
                      ship_postal_code:
                        type: string
                      ship_country:
                        type: string
                      ship_phone_number:
                        type: string
                        nullable: true
                      bill_address_1:
                        type: string
                      bill_address_2:
                        type: string
                        nullable: true
                      bill_address_3:
                        type: string
                        nullable: true
                      bill_city:
                        type: string
                      bill_state:
                        type: string
                      bill_postal_code:
                        type: string
                      bill_country:
                        type: string
                      item_promotion_discount:
                        type: integer
                      ship_promotion_discount:
                        type: integer
                      carrier:
                        type: string
                      tracking_number:
                        type: string
                      estimated_arrival_date:
                        type: string
                      fulfillment_center_id:
                        type: string
                      fulfillment_channel:
                        type: string
                      sales_channel:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                  status:
                    type: string
                example:
                  data:
                    id: 90233
                    amazon_order_id: 249-1234567-1234567
                    merchant_order_id: null
                    shipment_id: DkNqXvmZN
                    shipment_item_id: DwLnkWvZR
                    amazon_order_item_id: '68812291234567'
                    merchant_order_item_id: null
                    purchase_date: '2026-05-12T18:03:41.000000Z'
                    payments_date: '2026-05-12T18:03:41.000000Z'
                    shipment_date: '2026-05-13T09:44:02.000000Z'
                    reporting_date: '2026-05-13T11:02:55.000000Z'
                    event_datetime: '2026-05-13T09:44:02.000000Z'
                    buyer_name: John Carter
                    buyer_phone_number: null
                    sku: LS-RAZOR-BLK
                    product_name: Leaf Razor, Black
                    quantity_shipped: 1
                    currency: USD
                    item_price: 84
                    item_tax: 6.93
                    shipping_price: 0
                    shipping_tax: 0
                    gift_wrap_price: 0
                    gift_wrap_tax: 0
                    ship_service_level: Expedited
                    recipient_name: John Carter
                    ship_address_1: 410 Terry Ave N
                    ship_address_2: null
                    ship_address_3: null
                    ship_city: Seattle
                    ship_state: WA
                    ship_postal_code: 98109-5210
                    ship_country: US
                    ship_phone_number: null
                    bill_address_1: 410 Terry Ave N
                    bill_address_2: null
                    bill_address_3: null
                    bill_city: Seattle
                    bill_state: WA
                    bill_postal_code: 98109-5210
                    bill_country: US
                    item_promotion_discount: 0
                    ship_promotion_discount: 0
                    carrier: AMZN_US
                    tracking_number: TBA312845067201
                    estimated_arrival_date: '2026-05-16T03:00:00.000000Z'
                    fulfillment_center_id: SMF3
                    fulfillment_channel: AFN
                    sales_channel: Amazon.com
                    created_at: '2026-05-14T02:31:44.000000Z'
                    updated_at: '2026-05-14T02:31:44.000000Z'
                  status: success
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Not Found
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-amazon-integrationinstance-ledgers-shipments-shipment
  /api/amazon/{integrationInstance}/restock-report/{restock_report}:
    get:
      tags:
      - Amazon
      summary: Get Restock Report Row (Per Instance)
      description: 'Get a single row of the Amazon restock inventory recommendations
        report by ID. Each row is one FNSKU/marketplace combination with Amazon''s
        replenishment guidance: identification (fnsku, merchant_sku, asin, product_name,
        condition, country), pricing and sales velocity (price, sales_last_30_days,
        units_sold_last_30_days), current inventory position (total_units, inbound,
        available, fc_transfer, fc_processing, customer_order, unfulfillable, working,
        shipped, receiving), days of supply, alerts, and Amazon''s recommended_replenishment_qty
        and recommended_ship_date (Y-m-d).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        amazon_product is a cross-link to the matching Amazon product; it is resolved
        on the list endpoint and null here when no product matches the row''s merchant
        SKU. json_object holds the raw report row as imported. Returns 404 for an
        unknown ID.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Amazon integration instance ID
        example: '1'
      - name: restock_report
        in: path
        schema:
          type: integer
        required: true
        description: Restock report row ID
        example: '3311'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      amazon_product:
                        type: string
                        nullable: true
                      checksum:
                        type: string
                      amazon_report_id:
                        type: integer
                      country:
                        type: string
                      product_name:
                        type: string
                      fnsku:
                        type: string
                      merchant_sku:
                        type: string
                      asin:
                        type: string
                      condition:
                        type: string
                      supplier:
                        type: string
                        nullable: true
                      supplier_part_no:
                        type: string
                        nullable: true
                      currency_code:
                        type: string
                      fulfilled_by:
                        type: string
                        nullable: true
                      total_days_of_supply:
                        type: string
                      days_of_supply_at_amazon_fulfillment_network:
                        type: string
                      alert:
                        type: string
                        nullable: true
                      json_object:
                        type: object
                        properties:
                          country:
                            type: string
                          product_name:
                            type: string
                          fnsku:
                            type: string
                          merchant_sku:
                            type: string
                          asin:
                            type: string
                          condition:
                            type: string
                          price:
                            type: string
                          available:
                            type: string
                          recommended_replenishment_qty:
                            type: string
                          recommended_ship_date:
                            type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      working:
                        type: integer
                      shipped:
                        type: integer
                      receiving:
                        type: integer
                      recommended_replenishment_qty:
                        type: integer
                      recommended_ship_date:
                        type: string
                      price:
                        type: integer
                      sales_last_30_days:
                        type: integer
                      units_sold_last_30_days:
                        type: integer
                      total_units:
                        type: integer
                      inbound:
                        type: integer
                      available:
                        type: integer
                      fc_transfer:
                        type: integer
                      fc_processing:
                        type: integer
                      customer_order:
                        type: integer
                      unfulfillable:
                        type: integer
                  status:
                    type: string
                example:
                  data:
                    id: 3311
                    integration_instance_id: 1
                    amazon_product: null
                    checksum: b1946ac92492d2347c6235b4d2611184
                    amazon_report_id: 512
                    country: US
                    product_name: Leaf Razor, Black
                    fnsku: X002ABCDE1
                    merchant_sku: LS-RAZOR-BLK
                    asin: B08K4F9TXQ
                    condition: New
                    supplier: null
                    supplier_part_no: null
                    currency_code: USD
                    fulfilled_by: null
                    total_days_of_supply: '45'
                    days_of_supply_at_amazon_fulfillment_network: '38'
                    alert: null
                    json_object:
                      country: US
                      product_name: Leaf Razor, Black
                      fnsku: X002ABCDE1
                      merchant_sku: LS-RAZOR-BLK
                      asin: B08K4F9TXQ
                      condition: New
                      price: '84.00'
                      available: '119'
                      recommended_replenishment_qty: '150'
                      recommended_ship_date: '2026-07-21'
                    created_at: '2026-07-01T06:12:30.000000Z'
                    updated_at: '2026-07-01T06:12:30.000000Z'
                    working: 0
                    shipped: 24
                    receiving: 0
                    recommended_replenishment_qty: 150
                    recommended_ship_date: '2026-07-21'
                    price: 84
                    sales_last_30_days: 2520
                    units_sold_last_30_days: 30
                    total_units: 143
                    inbound: 24
                    available: 119
                    fc_transfer: 0
                    fc_processing: 0
                    customer_order: 0
                    unfulfillable: 0
                  status: success
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Not Found
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-amazon-integrationinstance-restock-report-restock-report
  /api/amazon/{integrationInstance}/finances/settlement-data/{id}:
    get:
      tags:
      - Amazon
      summary: Show Settlement Data
      description: 'Get a specific settlement data record.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: id
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The record ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      settlement_id:
                        type: string
                      total_amount:
                        type: number
                      currency:
                        type: string
                example:
                  data:
                    id: 1
                    settlement_id: '12345678'
                    total_amount: 5432.1
                    currency: USD
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-integrationinstance-finances-settlement-data-id
  /api/amazon/{integrationInstance}/finances/settlement-data/type-mappings:
    get:
      tags:
      - Amazon
      summary: Get Type Mappings
      description: 'Get settlement type mappings for an integration instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        example: '1'
        description: Page number (default 1).
      - name: per_page
        in: query
        schema:
          type: integer
        example: '20'
        description: Results per page (default 10).
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        transaction_type:
                          type: string
                        amount_type:
                          type: string
                        financial_code:
                          type: string
                        nominal_code_id:
                          type: integer
                  current_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 1
                    transaction_type: Order
                    amount_type: Principal
                    financial_code: revenue
                    nominal_code_id: 10
                  current_page: 1
                  total: 85
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-integrationinstance-finances-settlement-data-type-mappings
    put:
      tags:
      - Amazon
      summary: Map Settlement Types
      description: 'Update settlement type mappings (maps transaction types to nominal
        codes).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                mappings:
                  type: array
                  items:
                    type: object
                    properties:
                      id:
                        type: integer
                      nominal_code_id:
                        type: integer
                      amazon_settlement_mapping_group_id:
                        type: string
                        nullable: true
              example:
                mappings:
                - id: 1
                  nominal_code_id: 10
                  amazon_settlement_mapping_group_id: null
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Settlement type mappings updated successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-amazon-integrationinstance-finances-settlement-data-type-mappings
  /api/amazon/{integrationInstance}/finances/settlement-data/type-mappings/lookups:
    get:
      tags:
      - Amazon
      summary: Get Type Mapping Lookups
      description: 'Get lookup data (nominal codes, mapping groups) for the settlement
        type mapping form.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  nominal_codes:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        code:
                          type: string
                        name:
                          type: string
                  mapping_groups:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                example:
                  nominal_codes:
                  - id: 10
                    code: '4000'
                    name: Sales Revenue
                  mapping_groups:
                  - id: 1
                    name: Standard Group
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-integrationinstance-finances-settlement-data-type-mappings-lookups
  /api/amazon/{integrationInstance}/finances/settlement-data/type-mappings/bulk-assign:
    put:
      tags:
      - Amazon
      summary: Bulk Assign Type Mappings
      description: 'Bulk assign a nominal code or mapping group to multiple settlement
        type mappings.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
                nominal_code_id:
                  type: integer
                amazon_settlement_mapping_group_id:
                  type: string
                  nullable: true
              example:
                ids:
                - 1
                - 2
                - 3
                nominal_code_id: 10
                amazon_settlement_mapping_group_id: null
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      updated:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    updated: 3
                  message: 3 type mapping(s) updated successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-amazon-integrationinstance-finances-settlement-data-type-mappings-bulk-assign
  /api/amazon/{integrationInstance}/finances/settlement-data/type-mappings/import:
    post:
      tags:
      - Amazon
      summary: Import Settlement Types
      description: 'Import settlement type mappings from a CSV file.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                file:
                  type: string
                  description: CSV file with settlement type mappings
                  format: binary
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      imported:
                        type: integer
                example:
                  message: Import completed
                  data:
                    imported: 42
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-amazon-integrationinstance-finances-settlement-data-type-mappings-import
  /api/amazon/{integrationInstance}/finances/settlement-data/type-mappings/export:
    get:
      tags:
      - Amazon
      summary: Export Settlement Types
      description: 'Export settlement type mappings as CSV/Excel.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
          content:
            text/plain:
              schema:
                type: string
                example: (binary file content)
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-integrationinstance-finances-settlement-data-type-mappings-export
  /api/amazon/{integrationInstance}/finances/settlement-finance-settings:
    get:
      tags:
      - Amazon
      summary: Get Fallback Settings (Per Instance)
      description: 'Get fallback finance settings (default nominal codes) for an Amazon
        integration instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  fallback_revenue_nominal_code_id:
                    type: integer
                  fallback_expense_nominal_code_id:
                    type: integer
                  landed_cost_bill_mode:
                    type: string
                  landed_cost_proration_strategy:
                    type: string
                example:
                  fallback_revenue_nominal_code_id: 10
                  fallback_expense_nominal_code_id: 20
                  landed_cost_bill_mode: auto_create
                  landed_cost_proration_strategy: cost_based
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-integrationinstance-finances-settlement-finance-settings
    put:
      tags:
      - Amazon
      summary: Update Fallback Settings (Per Instance)
      description: 'Update fallback finance settings for an integration instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        fields:

        - fallback_revenue_nominal_code_id: nullable int

        - fallback_expense_nominal_code_id: nullable int

        - landed_cost_bill_mode: auto_create | manual

        - landed_cost_proration_strategy: cost_based | equal'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                fallback_revenue_nominal_code_id:
                  type: integer
                fallback_expense_nominal_code_id:
                  type: integer
                landed_cost_bill_mode:
                  type: string
                landed_cost_proration_strategy:
                  type: string
              example:
                fallback_revenue_nominal_code_id: 10
                fallback_expense_nominal_code_id: 20
                landed_cost_bill_mode: auto_create
                landed_cost_proration_strategy: cost_based
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Fallback settings updated successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-amazon-integrationinstance-finances-settlement-finance-settings
  /api/amazon/{integrationInstance}/finances/settlement-mapping-groups:
    get:
      tags:
      - Amazon
      summary: List Mapping Groups
      description: 'List settlement mapping groups for an integration instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        position:
                          type: integer
                        nominal_code_id:
                          type: integer
                example:
                  data:
                  - id: 1
                    name: FBA Fees
                    position: 1
                    nominal_code_id: 20
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-integrationinstance-finances-settlement-mapping-groups
    post:
      tags:
      - Amazon
      summary: Create Mapping Group
      description: 'Create a new settlement mapping group.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                nominal_code_id:
                  type: integer
              example:
                name: FBA Fees
                nominal_code_id: 20
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      position:
                        type: integer
                      nominal_code_id:
                        type: integer
                example:
                  data:
                    id: 3
                    name: FBA Fees
                    position: 3
                    nominal_code_id: 20
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-amazon-integrationinstance-finances-settlement-mapping-groups
  /api/amazon/{integrationInstance}/finances/settlement-mapping-groups/{settlementMappingGroup}:
    put:
      tags:
      - Amazon
      summary: Update Mapping Group
      description: 'Update a settlement mapping group.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                nominal_code_id:
                  type: integer
              example:
                name: Updated Group Name
                nominal_code_id: 21
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: settlementMappingGroup
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The settlement mapping group ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                example:
                  data:
                    id: 1
                    name: Updated Group Name
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-amazon-integrationinstance-finances-settlement-mapping-groups-settlementmappinggroup
    delete:
      tags:
      - Amazon
      summary: Delete Mapping Group
      description: 'Delete a settlement mapping group.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: settlementMappingGroup
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The settlement mapping group ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Mapping group deleted successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-amazon-integrationinstance-finances-settlement-mapping-groups-settlementmappinggroup
  /api/amazon/{integrationInstance}/finances/settlement-mapping-groups/reorder:
    put:
      tags:
      - Amazon
      summary: Reorder Mapping Groups
      description: 'Reorder settlement mapping groups by providing an ordered list
        of IDs.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 3
                - 1
                - 2
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Mapping groups reordered successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-amazon-integrationinstance-finances-settlement-mapping-groups-reorder
  /api/amazon/{integrationInstance}/awd/ledgers/{awdLedger}:
    get:
      tags:
      - Amazon
      summary: Show AWD Ledger
      description: 'Get a specific AWD ledger entry.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: awdLedger
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The awd ledger ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      date:
                        type: string
                      event_type:
                        type: string
                      quantity:
                        type: integer
                      sku:
                        type: string
                example:
                  data:
                    id: 1
                    date: '2024-03-01'
                    event_type: RECEIPT
                    quantity: 100
                    sku: WIDGET-RED
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-integrationinstance-awd-ledgers-awdledger
  /api/amazon/{integrationInstance}/awd/ledgers/import:
    post:
      tags:
      - Amazon
      summary: Import AWD Ledger
      description: 'Import AWD ledger data from a CSV file.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                file:
                  type: string
                  description: CSV file with AWD ledger data
                  format: binary
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      imported:
                        type: integer
                example:
                  message: AWD ledger imported successfully
                  data:
                    imported: 250
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-amazon-integrationinstance-awd-ledgers-import
  /api/amazon/{integrationInstance}/awd/ledgers/reconcile-all:
    post:
      tags:
      - Amazon
      summary: Reconcile All AWD Ledgers
      description: 'Reconcile all unreconciled AWD ledger entries.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      reconciled:
                        type: integer
                example:
                  message: All AWD ledgers reconciled
                  data:
                    reconciled: 48
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-amazon-integrationinstance-awd-ledgers-reconcile-all
  /api/amazon/{integrationInstance}/awd/ledgers/reconcile:
    post:
      tags:
      - Amazon
      summary: Reconcile AWD Ledgers
      description: 'Reconcile specific AWD ledger entries.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1
                - 2
                - 3
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      reconciled:
                        type: integer
                example:
                  message: Ledgers reconciled
                  data:
                    reconciled: 3
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-amazon-integrationinstance-awd-ledgers-reconcile
  /api/amazon/{integrationInstance}/awd/ledgers/unreconcile:
    post:
      tags:
      - Amazon
      summary: Unreconcile AWD Ledgers
      description: 'Unreconcile specific AWD ledger entries.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1
                - 2
                - 3
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      unreconciled:
                        type: integer
                example:
                  message: Ledgers unreconciled
                  data:
                    unreconciled: 3
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-amazon-integrationinstance-awd-ledgers-unreconcile
  /api/amazon/{integrationInstance}/awd/ledgers:
    delete:
      tags:
      - Amazon
      summary: Delete AWD Ledgers
      description: 'Delete specific AWD ledger entries.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: AWD ledgers deleted
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-amazon-integrationinstance-awd-ledgers
  /api/amazon/{integrationInstance}/awd/ledgers/{awdLedger}/linkable-sales-order-lines:
    get:
      tags:
      - Amazon
      summary: Get Linkable Sales Order Lines
      description: 'Get sales order lines that can be linked to an AWD ledger entry.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: awdLedger
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The awd ledger ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        sales_order_number:
                          type: string
                        sku:
                          type: string
                        quantity:
                          type: integer
                example:
                  data:
                  - id: 5
                    sales_order_number: SO-2024-001
                    sku: WIDGET-RED
                    quantity: 100
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-integrationinstance-awd-ledgers-awdledger-linkable-sales-order-lines
  /api/amazon/{integrationInstance}/awd/ledgers/{awdLedger}/link-sales-order-line:
    post:
      tags:
      - Amazon
      summary: Link to Sales Order Line
      description: 'Link an AWD ledger entry to a sales order line.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                sales_order_line_id:
                  type: integer
              example:
                sales_order_line_id: 5
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: awdLedger
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The awd ledger ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Linked to sales order line successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-amazon-integrationinstance-awd-ledgers-awdledger-link-sales-order-line
  /api/amazon/{integrationInstance}/awd/ledgers/{awdLedger}/unlink-sales-order-line:
    post:
      tags:
      - Amazon
      summary: Unlink from Sales Order Line
      description: 'Unlink an AWD ledger entry from its sales order line.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: awdLedger
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The awd ledger ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Unlinked from sales order line successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-amazon-integrationinstance-awd-ledgers-awdledger-unlink-sales-order-line
  /api/amazon/{integrationInstance}/awd/ledgers/linkable-for-sales-order-line/{salesOrderLineId}:
    get:
      tags:
      - Amazon
      summary: Get Linkable Ledgers for Sales Order Line
      description: 'Get AWD ledger entries that can be linked to a specific sales
        order line.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: salesOrderLineId
        in: path
        schema:
          type: integer
        required: true
        example: '5'
        description: The sales order line ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        date:
                          type: string
                        event_type:
                          type: string
                        quantity:
                          type: integer
                example:
                  data:
                  - id: 1
                    date: '2024-03-01'
                    event_type: RECEIPT
                    quantity: 100
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-integrationinstance-awd-ledgers-linkable-for-sales-order-line-salesorderlineid
  /api/amazon/{integrationInstance}/awd/ledgers/{awdLedger}/linkable-destination-warehouses:
    get:
      tags:
      - Amazon
      summary: Get Linkable Destination Warehouses
      description: 'Get warehouses that can serve as transfer destinations for an
        AWD ledger entry.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: awdLedger
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The awd ledger ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        code:
                          type: string
                example:
                  data:
                  - id: 3
                    name: Main Warehouse
                    code: WH-MAIN
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-integrationinstance-awd-ledgers-awdledger-linkable-destination-warehouses
  /api/amazon/{integrationInstance}/awd/ledgers/{awdLedger}/link-warehouse-transfer:
    post:
      tags:
      - Amazon
      summary: Link to Warehouse Transfer
      description: 'Link an AWD ledger entry to a warehouse transfer.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                warehouse_id:
                  type: integer
              example:
                warehouse_id: 3
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: awdLedger
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The awd ledger ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Linked to warehouse transfer successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-amazon-integrationinstance-awd-ledgers-awdledger-link-warehouse-transfer
  /api/amazon/{integrationInstance}/awd/ledgers/{awdLedger}/unlink-warehouse-transfer:
    post:
      tags:
      - Amazon
      summary: Unlink from Warehouse Transfer
      description: 'Unlink an AWD ledger entry from its warehouse transfer.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: awdLedger
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The awd ledger ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Unlinked from warehouse transfer
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-amazon-integrationinstance-awd-ledgers-awdledger-unlink-warehouse-transfer
  /api/amazon/{integrationInstance}/finances/nominal-code-mappings:
    get:
      tags:
      - Amazon
      summary: List Nominal Code Mappings
      description: 'List financial event type to nominal code mappings for an integration
        instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        financial_event_type:
                          type: string
                        nominal_code_id:
                          type: integer
                        nominal_code:
                          type: string
                example:
                  data:
                  - id: 1
                    financial_event_type: Order
                    nominal_code_id: 10
                    nominal_code: '4000'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-integrationinstance-finances-nominal-code-mappings
    post:
      tags:
      - Amazon
      summary: Create Nominal Code Mapping
      description: 'Create a new financial event type to nominal code mapping.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                financial_event_type:
                  type: string
                nominal_code_id:
                  type: integer
              example:
                financial_event_type: Order
                nominal_code_id: 10
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      financial_event_type:
                        type: string
                      nominal_code_id:
                        type: integer
                example:
                  data:
                    id: 5
                    financial_event_type: Order
                    nominal_code_id: 10
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-amazon-integrationinstance-finances-nominal-code-mappings
  /api/amazon/{integrationInstance}/reports/get-info:
    get:
      tags:
      - Amazon
      summary: Get Report Info
      description: 'Get report configuration and status information for an integration
        instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      reports:
                        type: array
                        items:
                          type: object
                          properties:
                            type:
                              type: string
                            status:
                              type: string
                            last_synced_at:
                              type: string
                example:
                  data:
                    reports:
                    - type: GET_FBA_MYI_UNSUPPRESSED_INVENTORY_DATA
                      status: enabled
                      last_synced_at: '2024-06-01T10:00:00.000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-integrationinstance-reports-get-info
  /api/amazon/{integrationInstance}/reports/{report}/sync:
    post:
      tags:
      - Amazon
      summary: Sync Report
      description: 'Trigger a sync for a specific Amazon report.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: report
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The report ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Report sync started
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-amazon-integrationinstance-reports-report-sync
  /api/amazon/{integrationInstance}/reports/create:
    post:
      tags:
      - Amazon
      summary: Create Report
      description: 'Request a new Amazon report.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                report_type:
                  type: string
                data_start_time:
                  type: string
                data_end_time:
                  type: string
              example:
                report_type: GET_FBA_MYI_UNSUPPRESSED_INVENTORY_DATA
                data_start_time: '2024-01-01'
                data_end_time: '2024-01-31'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      report_id:
                        type: string
                example:
                  message: Report creation started
                  data:
                    report_id: RPT-12345
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-amazon-integrationinstance-reports-create
  /api/amazon/unified/finance-dashboard:
    get:
      tags:
      - Amazon
      summary: Get Finance Dashboard
      parameters:
      - name: integration_instance_ids
        in: query
        schema:
          type: string
        description: Comma-separated integration instance IDs to scope the query.
      - name: date_from
        in: query
        schema:
          type: string
        description: Start of the date range (see the Dates & Timezones guide for
          formats).
      - name: date_to
        in: query
        schema:
          type: string
        description: End of the date range (see the Dates & Timezones guide for formats).
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      description: 'Get Finance Dashboard


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      operationId: get-api-amazon-unified-finance-dashboard
  /api/amazon/{integrationInstance}/new-ledgers/bulk-cogs-suggestions:
    post:
      tags:
      - Amazon
      summary: New Ledger Bulk COGS Suggestions
      description: 'Get COGS suggestions for multiple new ledger entries in bulk.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ledger_ids:
                  type: array
                  items:
                    type: integer
              example:
                ledger_ids:
                - 1
                - 2
                - 3
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        ledger_id:
                          type: integer
                        suggested_cogs:
                          type: number
                example:
                  data:
                  - ledger_id: 1
                    suggested_cogs: 12.5
                  - ledger_id: 2
                    suggested_cogs: 8.75
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-amazon-integrationinstance-new-ledgers-bulk-cogs-suggestions
  /api/amazon/{integrationInstance}/report-requests/create-next:
    post:
      tags:
      - Amazon
      summary: Create Next Report Request
      description: 'Create the next pending report request for a report type on this
        integration instance. Computes the next data window — from the last synced
        data point up to the newest safe end time (Amazon report data is delayed by
        up to 72 hours depending on report type) — and stores a report request row
        without calling Amazon yet. Submit it with the Create Report from Request
        endpoint. If an identical pending request already exists it is returned instead
        of creating a duplicate. Report types with long windows are split into multiple
        requests; the first created request is returned.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Body fields:

        - reportType (string, required) — one of: GET_MERCHANT_LISTINGS_ALL_DATA,
        GET_FBA_MYI_UNSUPPRESSED_INVENTORY_DATA, GET_AMAZON_FULFILLED_SHIPMENTS_DATA_GENERAL,
        GET_FBA_FULFILLMENT_REMOVAL_SHIPMENT_DETAIL_DATA, GET_FBA_FULFILLMENT_REMOVAL_ORDER_DETAIL_DATA,
        GET_FBA_FULFILLMENT_CUSTOMER_RETURNS_DATA, GET_LEDGER_SUMMARY_VIEW_DATA, GET_LEDGER_DETAIL_VIEW_DATA,
        GET_RESTOCK_INVENTORY_RECOMMENDATIONS_REPORT, GET_V2_SETTLEMENT_REPORT_DATA_FLAT_FILE_V2,
        GET_SELLER_FEEDBACK_DATA, GET_FBA_ESTIMATED_FBA_FEES_TXT_DATA, GET_FLAT_FILE_RETURNS_DATA_BY_RETURN_DATE,
        GET_FBA_REIMBURSEMENTS_DATA, GET_FBA_STORAGE_FEE_CHARGES_DATA, GET_FBA_FULFILLMENT_LONGTERM_STORAGE_FEE_CHARGES_DATA.


        Returns the stored report request (dataStartTime/dataEndTime in UTC ISO 8601;
        options and marketplaceIds are derived from the report type and instance).
        Fails when another report of the same type is still being processed (settlement
        and shipment reports excepted; stuck reports older than 4 hours are automatically
        failed so the request can proceed). Returns 422 for an unknown report type.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                reportType:
                  type: string
              example:
                reportType: GET_LEDGER_SUMMARY_VIEW_DATA
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Amazon integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      integration_instance_id:
                        type: integer
                      reportType:
                        type: string
                      dataStartTime:
                        type: string
                      dataEndTime:
                        type: string
                      options:
                        type: object
                        properties:
                          aggregatedByTimePeriod:
                            type: string
                      marketplaceIds:
                        type: array
                        items:
                          type: string
                      disallow_duplicates:
                        type: boolean
                      updated_at:
                        type: string
                      created_at:
                        type: string
                      id:
                        type: integer
                  status:
                    type: string
                example:
                  data:
                    integration_instance_id: 1
                    reportType: GET_LEDGER_SUMMARY_VIEW_DATA
                    dataStartTime: '2026-06-01T00:00:00.000000Z'
                    dataEndTime: '2026-07-05T14:02:11.000000Z'
                    options:
                      aggregatedByTimePeriod: DAILY
                    marketplaceIds:
                    - ATVPDKIKX0DER
                    disallow_duplicates: false
                    updated_at: '2026-07-06T14:02:11.000000Z'
                    created_at: '2026-07-06T14:02:11.000000Z'
                    id: 291
                  status: success
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      reportType:
                        type: array
                        items:
                          type: string
                  status:
                    type: string
                example:
                  message: The selected report type is invalid.
                  errors:
                    reportType:
                    - The selected report type is invalid.
                  status: failure
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-amazon-integrationinstance-report-requests-create-next
  /api/amazon/{integrationInstance}/report-requests/{reportRequest}/create-report:
    post:
      tags:
      - Amazon
      summary: Create Report from Request
      description: 'Submit a stored report request to Amazon, creating the actual
        report. Calls the Amazon Selling Partner API to create a report for the request''s
        type, data window, options and marketplaces, stores the resulting report record
        with its Amazon report id, and deletes the report request. The report''s processing
        status is subsequently updated by the scheduled report sync, and its rows
        are imported once Amazon finishes generating it.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        No request body. Fails when an existing non-failed report already overlaps
        the requested data range, unless the request was created with overlapping
        pulls permitted (in which case row-level checksum de-duplication applies on
        import). Returns 404 for an unknown report request ID.'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Amazon integration instance ID
        example: '1'
      - name: reportRequest
        in: path
        schema:
          type: integer
        required: true
        description: Report request ID (from Create Next Report Request)
        example: '291'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      reportId:
                        type: string
                      integration_instance_id:
                        type: integer
                      reportType:
                        type: string
                      dataStartTime:
                        type: string
                      dataEndTime:
                        type: string
                      options:
                        type: object
                        properties:
                          aggregatedByTimePeriod:
                            type: string
                      marketplaceIds:
                        type: array
                        items:
                          type: string
                      disallow_duplicates:
                        type: boolean
                      updated_at:
                        type: string
                      created_at:
                        type: string
                      id:
                        type: integer
                  status:
                    type: string
                example:
                  data:
                    reportId: '1468239482093'
                    integration_instance_id: 1
                    reportType: GET_LEDGER_SUMMARY_VIEW_DATA
                    dataStartTime: '2026-06-01T00:00:00.000000Z'
                    dataEndTime: '2026-07-05T14:02:11.000000Z'
                    options:
                      aggregatedByTimePeriod: DAILY
                    marketplaceIds:
                    - ATVPDKIKX0DER
                    disallow_duplicates: false
                    updated_at: '2026-07-06T14:05:40.000000Z'
                    created_at: '2026-07-06T14:05:40.000000Z'
                    id: 6021
                  status: success
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Not Found
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-amazon-integrationinstance-report-requests-reportrequest-create-report
  /api/amazon/{integrationInstance}/finances/event-groups/{id}:
    get:
      tags:
      - Amazon
      summary: Show Financial Event Group
      description: 'Get a specific financial event group.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: id
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The record ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      financial_event_group_id:
                        type: string
                      processing_status:
                        type: string
                example:
                  data:
                    id: 1
                    financial_event_group_id: FEG-123
                    processing_status: Closed
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-integrationinstance-finances-event-groups-id
  /api/amazon/unified/fnsku-products:
    get:
      tags:
      - Amazon
      summary: List FNSKU Products (paginated, with reconciliation data)
      description: 'Returns a paginated list of FNSKU products across all integration
        instances, enriched with per-record reconciliation_data (total_ledgers, reconciled_ledgers,
        reconciliation_percentage, initial_inventory_reconciled, unreconciled_discrepancies_count,
        reconciliation_status).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        fnskuProduct:
                          type: object
                          properties:
                            id:
                              type: integer
                            fnsku:
                              type: string
                            location:
                              type: string
                            disposition:
                              type: string
                            initial_unit_cost:
                              type: number
                        integration_instance:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        product:
                          type: object
                          properties:
                            id:
                              type: integer
                            sku:
                              type: string
                            name:
                              type: string
                        reconciliation_data:
                          type: object
                          properties:
                            total_ledgers:
                              type: integer
                            reconciled_ledgers:
                              type: integer
                            reconciliation_percentage:
                              type: integer
                            initial_inventory_reconciled:
                              type: boolean
                            unreconciled_discrepancies_count:
                              type: integer
                            reconciliation_status:
                              type: string
                        initial_inventory_fifo_layer_id:
                          type: integer
                        created_at:
                          type: string
                        updated_at:
                          type: string
                        last_reconciled:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                  first_page_url:
                    type: string
                  last_page_url:
                    type: string
                  next_page_url:
                    type: string
                  prev_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  links:
                    type: array
                example:
                  data:
                  - fnskuProduct:
                      id: 101
                      fnsku: X001ABCDEF
                      location: US
                      disposition: SELLABLE
                      initial_unit_cost: 4.25
                    integration_instance:
                      id: 1
                      name: Amazon US (Production)
                    product:
                      id: 9001
                      sku: SKU-123
                      name: Widget
                    reconciliation_data:
                      total_ledgers: 120
                      reconciled_ledgers: 118
                      reconciliation_percentage: 98
                      initial_inventory_reconciled: true
                      unreconciled_discrepancies_count: 0
                      reconciliation_status: fully_reconciled
                    initial_inventory_fifo_layer_id: 5512
                    created_at: '2026-01-15T10:24:00.000000Z'
                    updated_at: '2026-05-01T08:15:00.000000Z'
                    last_reconciled: '2026-05-01T08:15:00.000000Z'
                  current_page: 1
                  last_page: 7
                  per_page: 15
                  total: 102
                  from: 1
                  to: 15
                  first_page_url: https://example.test/api/amazon/unified/fnsku-products?page=1
                  last_page_url: https://example.test/api/amazon/unified/fnsku-products?page=7
                  next_page_url: https://example.test/api/amazon/unified/fnsku-products?page=2
                  prev_page_url: null
                  path: https://example.test/api/amazon/unified/fnsku-products
                  links: []
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-amazon-unified-fnsku-products
  /api/amazon/unified/fnsku-products/{fnskuProductId}:
    get:
      tags:
      - Amazon
      summary: Show FNSKU Product Detail
      description: 'Returns detail payload for a single FNSKU product (including reconciliation_data,
        initial_fba_inventory, inventory_summary, related_counts).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: fnskuProductId
        in: path
        required: true
        schema:
          type: string
        description: The fnskuProductId identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      fnskuProduct:
                        type: object
                        properties:
                          id:
                            type: integer
                          fnsku:
                            type: string
                          location:
                            type: string
                          disposition:
                            type: string
                          created_at:
                            type: string
                          updated_at:
                            type: string
                      integration_instance:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      product:
                        type: object
                        properties:
                          id:
                            type: integer
                          sku:
                            type: string
                          name:
                            type: string
                      reconciliation_data:
                        type: object
                        properties:
                          total_ledgers:
                            type: integer
                          reconciled_ledgers:
                            type: integer
                          reconciliation_percentage:
                            type: integer
                          initial_inventory_reconciled:
                            type: boolean
                          unreconciled_discrepancies_count:
                            type: integer
                          reconciliation_status:
                            type: string
                      initial_fba_inventory:
                        type: object
                        properties:
                          id:
                            type: integer
                          date:
                            type: string
                          ending_inventory:
                            type: integer
                          total_inventory:
                            type: integer
                          in_transit_between_warehouses:
                            type: integer
                          disposition:
                            type: string
                          location:
                            type: string
                          reconciled_at:
                            type: string
                          fifo_layer:
                            type: object
                            properties:
                              id:
                                type: integer
                              cogs:
                                type: number
                              cogs_source:
                                type: string
                      inventory_summary:
                        type: object
                        properties:
                          last_reconciled_date:
                            type: string
                          pending_ledgers_count:
                            type: integer
                      default_as_of_date:
                        type: string
                      related_counts:
                        type: object
                        properties:
                          discrepancies:
                            type: integer
                          ledgers:
                            type: integer
                          summary_ledgers:
                            type: integer
                          removal_orders:
                            type: integer
                          removal_shipments:
                            type: integer
                  message:
                    type: string
                example:
                  data:
                    fnskuProduct:
                      id: 101
                      fnsku: X001ABCDEF
                      location: US
                      disposition: SELLABLE
                      created_at: '2026-01-15T10:24:00.000000Z'
                      updated_at: '2026-05-01T08:15:00.000000Z'
                    integration_instance:
                      id: 1
                      name: Amazon US (Production)
                    product:
                      id: 9001
                      sku: SKU-123
                      name: Widget
                    reconciliation_data:
                      total_ledgers: 120
                      reconciled_ledgers: 118
                      reconciliation_percentage: 98
                      initial_inventory_reconciled: true
                      unreconciled_discrepancies_count: 0
                      reconciliation_status: fully_reconciled
                    initial_fba_inventory:
                      id: 555
                      date: '2026-01-01'
                      ending_inventory: 250
                      total_inventory: 260
                      in_transit_between_warehouses: 10
                      disposition: SELLABLE
                      location: US
                      reconciled_at: '2026-05-01T08:15:00.000000Z'
                      fifo_layer:
                        id: 5512
                        cogs: 4.25
                        cogs_source: product_unit_cost
                    inventory_summary:
                      last_reconciled_date: '2026-05-01T08:15:00.000000Z'
                      pending_ledgers_count: 2
                    default_as_of_date: '2026-05-15'
                    related_counts:
                      discrepancies: 1
                      ledgers: 120
                      summary_ledgers: 30
                      removal_orders: 2
                      removal_shipments: 2
                  message: Success
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: array
                    items:
                      type: object
                      properties:
                        code:
                          type: string
                        message:
                          type: string
                example:
                  errors:
                  - code: fnsku_product_not_found
                    message: FNSKU product not found
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-amazon-unified-fnsku-products-fnskuproductid
  /api/amazon/unified/fnsku-products/stats:
    get:
      tags:
      - Amazon
      summary: Get ASIN mapping statistics
      description: 'Returns aggregate counts of mapped vs unmapped FNSKUs and ASIN
        groups.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      mapped_fnsku_count:
                        type: integer
                      unmapped_fnsku_count:
                        type: integer
                      total_fnsku_count:
                        type: integer
                      mapped_asin_count:
                        type: integer
                      unmapped_asin_count:
                        type: integer
                      total_asin_count:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    mapped_fnsku_count: 320
                    unmapped_fnsku_count: 47
                    total_fnsku_count: 367
                    mapped_asin_count: 210
                    unmapped_asin_count: 22
                    total_asin_count: 232
                  message: Success
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-amazon-unified-fnsku-products-stats
  /api/amazon/unified/fnsku-products/search:
    get:
      tags:
      - Amazon
      summary: Search FNSKU products
      description: 'Lightweight FNSKU search (up to 50 results), used for manual discrepancy
        creation.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: fnsku
        in: query
        schema:
          type: string
        description: Required. Partial FNSKU string to search by (min 1 char)
        example: X001
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      results:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            fnsku:
                              type: string
                            location:
                              type: string
                            disposition:
                              type: string
                            integration_instance:
                              type: object
                              properties:
                                id:
                                  type: integer
                                name:
                                  type: string
                            product:
                              type: object
                              properties:
                                id:
                                  type: integer
                                sku:
                                  type: string
                                name:
                                  type: string
                            initial_unit_cost:
                              type: number
                      total:
                        type: integer
                example:
                  data:
                    results:
                    - id: 101
                      fnsku: X001ABCDEF
                      location: US
                      disposition: SELLABLE
                      integration_instance:
                        id: 1
                        name: Amazon US (Production)
                      product:
                        id: 9001
                        sku: SKU-123
                        name: Widget
                      initial_unit_cost: 4.25
                    total: 1
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-amazon-unified-fnsku-products-search
  /api/amazon/unified/fnsku-products/unmapped:
    get:
      tags:
      - Amazon
      summary: List Unmapped FNSKU Products (paginated)
      description: 'Paginated list of FNSKU products that are not yet mapped to a
        product. Uses unified Amazon FNSKU product mapper object.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        fnsku:
                          type: string
                        integration_instance_id:
                          type: integer
                        integration_instance_name:
                          type: string
                        location:
                          type: string
                        disposition:
                          type: string
                        product:
                          type: string
                          nullable: true
                        matches:
                          type: array
                          items:
                            type: object
                            properties:
                              asin:
                                type: string
                              msku:
                                type: string
                                nullable: true
                              title:
                                type: string
                                nullable: true
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                  first_page_url:
                    type: string
                  last_page_url:
                    type: string
                  next_page_url:
                    type: string
                  prev_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  links:
                    type: array
                example:
                  data:
                  - id: 542
                    fnsku: X001UNMAPPED
                    integration_instance_id: 1
                    integration_instance_name: Amazon US (Production)
                    location: US
                    disposition: SELLABLE
                    product: null
                    matches:
                    - asin: B0123ABCDE
                      msku: null
                      title: null
                    created_at: '2026-03-01T10:00:00.000000Z'
                    updated_at: '2026-03-01T10:00:00.000000Z'
                  current_page: 1
                  last_page: 4
                  per_page: 15
                  total: 47
                  from: 1
                  to: 15
                  first_page_url: https://example.test/api/amazon/unified/fnsku-products/unmapped?page=1
                  last_page_url: https://example.test/api/amazon/unified/fnsku-products/unmapped?page=4
                  next_page_url: https://example.test/api/amazon/unified/fnsku-products/unmapped?page=2
                  prev_page_url: null
                  path: https://example.test/api/amazon/unified/fnsku-products/unmapped
                  links: []
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-amazon-unified-fnsku-products-unmapped
  /api/amazon/unified/fnsku-products/mapped:
    get:
      tags:
      - Amazon
      summary: List Mapped FNSKU Products (paginated)
      description: 'Paginated list of FNSKU products already mapped to a product.
        Uses unified Amazon FNSKU product mapper object.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        fnsku:
                          type: string
                        integration_instance_id:
                          type: integer
                        integration_instance_name:
                          type: string
                        location:
                          type: string
                        disposition:
                          type: string
                        product:
                          type: object
                          properties:
                            id:
                              type: integer
                            sku:
                              type: string
                            name:
                              type: string
                        matches:
                          type: array
                          items:
                            type: object
                            properties:
                              asin:
                                type: string
                              msku:
                                type: string
                                nullable: true
                              title:
                                type: string
                                nullable: true
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                  first_page_url:
                    type: string
                  last_page_url:
                    type: string
                  next_page_url:
                    type: string
                  prev_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  links:
                    type: array
                example:
                  data:
                  - id: 101
                    fnsku: X001ABCDEF
                    integration_instance_id: 1
                    integration_instance_name: Amazon US (Production)
                    location: US
                    disposition: SELLABLE
                    product:
                      id: 9001
                      sku: SKU-123
                      name: Widget
                    matches:
                    - asin: B0123ABCDE
                      msku: null
                      title: null
                    created_at: '2026-01-15T10:24:00.000000Z'
                    updated_at: '2026-05-01T08:15:00.000000Z'
                  current_page: 1
                  last_page: 22
                  per_page: 15
                  total: 320
                  from: 1
                  to: 15
                  first_page_url: https://example.test/api/amazon/unified/fnsku-products/mapped?page=1
                  last_page_url: https://example.test/api/amazon/unified/fnsku-products/mapped?page=22
                  next_page_url: https://example.test/api/amazon/unified/fnsku-products/mapped?page=2
                  prev_page_url: null
                  path: https://example.test/api/amazon/unified/fnsku-products/mapped
                  links: []
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-amazon-unified-fnsku-products-mapped
  /api/amazon/unified/fnsku-products/unmapped-by-asin:
    get:
      tags:
      - Amazon
      summary: List Unmapped FNSKUs Grouped by ASIN
      description: 'FNSKUs grouped by ASIN where at least one FNSKU is unmapped. Includes
        FNSKUs without ASINs grouped as ''No ASIN''.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        asin:
                          type: string
                        msku:
                          type: string
                        title:
                          type: string
                        total_fnskus:
                          type: integer
                        total_instances:
                          type: integer
                        mapped_product:
                          type: string
                          nullable: true
                        mapping_status:
                          type: string
                        fnsku_records:
                          type: array
                          items:
                            type: object
                            properties:
                              id:
                                type: integer
                              fnsku:
                                type: string
                              integration_instance_id:
                                type: integer
                              integration_instance_name:
                                type: string
                              product_id:
                                type: string
                                nullable: true
                              product:
                                type: string
                                nullable: true
                              location:
                                type: string
                              disposition:
                                type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                  path:
                    type: string
                  links:
                    type: array
                example:
                  data:
                  - asin: B0123ABCDE
                    msku: SELLER-SKU-A
                    title: Widget Black
                    total_fnskus: 3
                    total_instances: 2
                    mapped_product: null
                    mapping_status: unmapped
                    fnsku_records:
                    - id: 542
                      fnsku: X001UNMAPPED
                      integration_instance_id: 1
                      integration_instance_name: Amazon US (Production)
                      product_id: null
                      product: null
                      location: US
                      disposition: SELLABLE
                  current_page: 1
                  last_page: 2
                  per_page: 15
                  total: 22
                  from: 1
                  to: 15
                  path: https://example.test/api/amazon/unified/fnsku-products/unmapped-by-asin
                  links: []
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-amazon-unified-fnsku-products-unmapped-by-asin
  /api/amazon/unified/fnsku-products/mapped-by-asin:
    get:
      tags:
      - Amazon
      summary: List Mapped FNSKUs Grouped by ASIN
      description: 'FNSKUs grouped by ASIN where at least one FNSKU is mapped. mapping_status
        is ''mapped'' or ''partially_mapped''.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        asin:
                          type: string
                        msku:
                          type: string
                        title:
                          type: string
                        total_fnskus:
                          type: integer
                        total_instances:
                          type: integer
                        mapped_product:
                          type: object
                          properties:
                            id:
                              type: integer
                            sku:
                              type: string
                            name:
                              type: string
                        mapping_status:
                          type: string
                        fnsku_records:
                          type: array
                          items:
                            type: object
                            properties:
                              id:
                                type: integer
                              fnsku:
                                type: string
                              integration_instance_id:
                                type: integer
                              integration_instance_name:
                                type: string
                              product_id:
                                type: integer
                              product:
                                type: object
                                properties:
                                  id:
                                    type: integer
                                  sku:
                                    type: string
                                  name:
                                    type: string
                              location:
                                type: string
                              disposition:
                                type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                  path:
                    type: string
                  links:
                    type: array
                example:
                  data:
                  - asin: B0987FGHIJ
                    msku: SELLER-SKU-B
                    title: Widget Red
                    total_fnskus: 4
                    total_instances: 2
                    mapped_product:
                      id: 9001
                      sku: SKU-123
                      name: Widget
                    mapping_status: mapped
                    fnsku_records:
                    - id: 101
                      fnsku: X001ABCDEF
                      integration_instance_id: 1
                      integration_instance_name: Amazon US (Production)
                      product_id: 9001
                      product:
                        id: 9001
                        sku: SKU-123
                        name: Widget
                      location: US
                      disposition: SELLABLE
                  current_page: 1
                  last_page: 14
                  per_page: 15
                  total: 210
                  from: 1
                  to: 15
                  path: https://example.test/api/amazon/unified/fnsku-products/mapped-by-asin
                  links: []
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-amazon-unified-fnsku-products-mapped-by-asin
  /api/amazon/unified/fnsku-products/export:
    get:
      tags:
      - Amazon
      summary: Export FNSKU Products (unpaginated)
      description: 'Returns ALL FNSKU products with reconciliation data (forces per_page=10000).
        Same filters as the paginated index.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        fnskuProduct:
                          type: object
                          properties:
                            id:
                              type: integer
                            fnsku:
                              type: string
                            location:
                              type: string
                            disposition:
                              type: string
                            initial_unit_cost:
                              type: number
                        integration_instance:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        product:
                          type: object
                          properties:
                            id:
                              type: integer
                            sku:
                              type: string
                            name:
                              type: string
                        reconciliation_data:
                          type: object
                          properties:
                            total_ledgers:
                              type: integer
                            reconciled_ledgers:
                              type: integer
                            reconciliation_percentage:
                              type: integer
                            initial_inventory_reconciled:
                              type: boolean
                            unreconciled_discrepancies_count:
                              type: integer
                            reconciliation_status:
                              type: string
                        initial_inventory_fifo_layer_id:
                          type: integer
                        created_at:
                          type: string
                        updated_at:
                          type: string
                        last_reconciled:
                          type: string
                example:
                  data:
                  - fnskuProduct:
                      id: 101
                      fnsku: X001ABCDEF
                      location: US
                      disposition: SELLABLE
                      initial_unit_cost: 4.25
                    integration_instance:
                      id: 1
                      name: Amazon US (Production)
                    product:
                      id: 9001
                      sku: SKU-123
                      name: Widget
                    reconciliation_data:
                      total_ledgers: 120
                      reconciled_ledgers: 118
                      reconciliation_percentage: 98
                      initial_inventory_reconciled: true
                      unreconciled_discrepancies_count: 0
                      reconciliation_status: fully_reconciled
                    initial_inventory_fifo_layer_id: 5512
                    created_at: '2026-01-15T10:24:00.000000Z'
                    updated_at: '2026-05-01T08:15:00.000000Z'
                    last_reconciled: '2026-05-01T08:15:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-amazon-unified-fnsku-products-export
  /api/amazon/unified/fnsku-products/activity-log:
    get:
      tags:
      - Amazon
      summary: Auto-Mapping Activity Log
      description: 'Paginated activity log of FNSKU auto-mapping events across all
        integrations.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        amazon_fnsku_product_id:
                          type: integer
                        product_id:
                          type: integer
                        matched_from_fnsku_id:
                          type: integer
                        asin:
                          type: string
                        mapping_type:
                          type: string
                        integration_instance:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        amazon_fnsku_product:
                          type: object
                          properties:
                            id:
                              type: integer
                            fnsku:
                              type: string
                        product:
                          type: object
                          properties:
                            id:
                              type: integer
                            sku:
                              type: string
                            name:
                              type: string
                        matched_from_fnsku:
                          type: object
                          properties:
                            id:
                              type: integer
                            fnsku:
                              type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                  path:
                    type: string
                  links:
                    type: array
                example:
                  data:
                  - id: 8821
                    integration_instance_id: 1
                    amazon_fnsku_product_id: 101
                    product_id: 9001
                    matched_from_fnsku_id: 99
                    asin: B0123ABCDE
                    mapping_type: auto
                    integration_instance:
                      id: 1
                      name: Amazon US (Production)
                    amazon_fnsku_product:
                      id: 101
                      fnsku: X001ABCDEF
                    product:
                      id: 9001
                      sku: SKU-123
                      name: Widget
                    matched_from_fnsku:
                      id: 99
                      fnsku: X001ORIGREF
                    created_at: '2026-05-12T13:45:00.000000Z'
                    updated_at: '2026-05-12T13:45:00.000000Z'
                  current_page: 1
                  last_page: 5
                  per_page: 10
                  total: 47
                  from: 1
                  to: 10
                  path: https://example.test/api/amazon/unified/fnsku-products/activity-log
                  links: []
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-amazon-unified-fnsku-products-activity-log
  /api/amazon/unified/fnsku-products/{fnskuProduct}/discrepancies:
    get:
      tags:
      - Amazon
      summary: FNSKU Discrepancies (paginated)
      description: 'Paginated discrepancies for an FNSKU product (route-model-bound
        by id). Adds computed `status` field (reconciled|unreconciled).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: fnskuProduct
        in: path
        required: true
        schema:
          type: string
        description: The fnskuProduct identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        amazon_fnsku_product_id:
                          type: integer
                        reason_type:
                          type: string
                        discrepancy_date:
                          type: string
                        quantity:
                          type: integer
                        reconciled_at:
                          type: string
                          nullable: true
                        status:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 9111
                    amazon_fnsku_product_id: 101
                    reason_type: ledger_summary_mismatch
                    discrepancy_date: '2026-04-10'
                    quantity: 5
                    reconciled_at: null
                    status: unreconciled
                    created_at: '2026-04-10T12:00:00.000000Z'
                    updated_at: '2026-04-10T12:00:00.000000Z'
                  current_page: 1
                  last_page: 1
                  per_page: 15
                  total: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-unified-fnsku-products-fnskuproduct-discrepancies
  /api/amazon/unified/fnsku-products/{fnskuProduct}/ledgers:
    get:
      tags:
      - Amazon
      summary: FNSKU Ledgers (paginated)
      description: 'Paginated FBA ledger entries for an FNSKU product, formatted via
        unified Amazon FNSKU product ledger object.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: fnskuProduct
        in: path
        required: true
        schema:
          type: string
        description: The fnskuProduct identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        amazon_fnsku_product_id:
                          type: integer
                        event_type:
                          type: string
                        event_datetime:
                          type: string
                        quantity:
                          type: integer
                        asin:
                          type: string
                        msku:
                          type: string
                        title:
                          type: string
                        reconciled_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 70011
                    amazon_fnsku_product_id: 101
                    event_type: Receipts
                    event_datetime: '2026-02-01T10:00:00.000000Z'
                    quantity: 100
                    asin: B0123ABCDE
                    msku: SELLER-SKU-A
                    title: Widget Black
                    reconciled_at: '2026-02-02T08:00:00.000000Z'
                  current_page: 1
                  last_page: 8
                  per_page: 15
                  total: 120
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-unified-fnsku-products-fnskuproduct-ledgers
  /api/amazon/unified/fnsku-products/{fnskuProductId}/inventory-tally-summary:
    get:
      tags:
      - Amazon
      summary: Inventory Tally Summary
      description: 'Computes ledger vs summary inventory variance for a specific as-of
        date, with event-type and discrepancy reason breakdowns.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: fnskuProductId
        in: path
        required: true
        schema:
          type: string
        description: The fnskuProductId identifier
      - name: as_of_date
        in: query
        schema:
          type: string
        description: Required. Y-m-d format. Must not exceed the latest summary report
          date.
        example: '2026-05-01'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      as_of_date:
                        type: string
                      initial_inventory:
                        type: object
                        properties:
                          date:
                            type: string
                          quantity:
                            type: integer
                      summary_warehouse_inventory:
                        type: integer
                      summary_in_transit:
                        type: integer
                      ledger_current:
                        type: integer
                      discrepancies_reconciled:
                        type: integer
                      discrepancies_unreconciled:
                        type: integer
                      variance:
                        type: object
                        properties:
                          quantity:
                            type: integer
                          percentage:
                            type: integer
                      reconciliation_status:
                        type: object
                        properties:
                          percentage:
                            type: integer
                          last_reconciled:
                            type: string
                          unreconciled_ledgers:
                            type: integer
                      event_types_summary:
                        type: object
                        properties:
                          Receipts:
                            type: integer
                          Customer Shipments:
                            type: integer
                          Customer Returns:
                            type: integer
                          Vendor Returns:
                            type: integer
                          Warehouse Transfer In Out:
                            type: integer
                          Adjustments:
                            type: object
                            properties:
                              Found:
                                type: integer
                              Lost:
                                type: integer
                              Damaged:
                                type: integer
                              Disposed:
                                type: integer
                              Other Events:
                                type: integer
                          Unknown Events:
                            type: integer
                      event_types_ledger:
                        type: object
                        properties:
                          Receipts:
                            type: integer
                          Shipments:
                            type: integer
                          Customer Returns:
                            type: integer
                      discrepancy_reasons:
                        type: object
                        properties:
                          Ledger Summary Mismatch:
                            type: integer
                  message:
                    type: string
                example:
                  data:
                    as_of_date: '2026-05-01'
                    initial_inventory:
                      date: '2026-01-01'
                      quantity: 250
                    summary_warehouse_inventory: 245
                    summary_in_transit: 10
                    ledger_current: 250
                    discrepancies_reconciled: 0
                    discrepancies_unreconciled: 1
                    variance:
                      quantity: 5
                      percentage: 2
                    reconciliation_status:
                      percentage: 98
                      last_reconciled: '2026-05-01T08:15:00.000000Z'
                      unreconciled_ledgers: 2
                    event_types_summary:
                      Receipts: 100
                      Customer Shipments: -90
                      Customer Returns: 5
                      Vendor Returns: 0
                      Warehouse Transfer In Out: 0
                      Adjustments:
                        Found: 0
                        Lost: 0
                        Damaged: 0
                        Disposed: 0
                        Other Events: 0
                      Unknown Events: 0
                    event_types_ledger:
                      Receipts: 100
                      Shipments: -90
                      Customer Returns: 5
                    discrepancy_reasons:
                      Ledger Summary Mismatch: 0
                  message: Success
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: array
                    items:
                      type: object
                      properties:
                        code:
                          type: string
                        message:
                          type: string
                example:
                  errors:
                  - code: missing_parameter
                    message: as_of_date parameter is required
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: array
                    items:
                      type: object
                      properties:
                        code:
                          type: string
                        message:
                          type: string
                example:
                  errors:
                  - code: tally_summary_error
                    message: FNSKU product not found
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-amazon-unified-fnsku-products-fnskuproductid-inventory-tally-summary
  /api/amazon/unified/fnsku-products/map-single-fnsku:
    post:
      tags:
      - Amazon
      summary: Map Single FNSKU to a Product
      description: 'Map a single FNSKU product to a product. Pass product_id=null
        to unmap (also triggers unreconciliation). When linking, dispatches a tracked
        reconciliation job.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                fnsku_product_id:
                  type: integer
                product_id:
                  type: integer
              example:
                fnsku_product_id: 101
                product_id: 9001
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      fnsku_product_id:
                        type: integer
                      product_id:
                        type: integer
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    fnsku_product_id: 101
                    product_id: 9001
                    tracked_job_log_id: 4521
                  message: Mapped FNSKU product 101 to product ID 9001
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-amazon-unified-fnsku-products-map-single-fnsku
  /api/amazon/unified/fnsku-products/map-by-asin:
    post:
      tags:
      - Amazon
      summary: Map all FNSKUs for an ASIN to a Product
      description: 'Map every FNSKU with the given ASIN to a product. Pass product_id=null
        to unmap.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                asin:
                  type: string
                product_id:
                  type: integer
                integration_instance_ids:
                  type: array
                  items:
                    type: integer
              example:
                asin: B0123ABCDE
                product_id: 9001
                integration_instance_ids:
                - 1
                - 2
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      mapped_count:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    mapped_count: 3
                  message: Mapped 3 FNSKU products with ASIN B0123ABCDE to product
                    ID 9001
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-amazon-unified-fnsku-products-map-by-asin
  /api/amazon/unified/fnsku-products/bulk-reconcile:
    post:
      tags:
      - Amazon
      summary: Bulk Reconcile
      description: 'Dispatch bulk reconciliation for the given FNSKU product IDs,
        or for all IDs matching `filters` when `apply_to_all=true`.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                fnsku_product_ids:
                  type: array
                  items:
                    type: integer
                apply_to_all:
                  type: boolean
                filters:
                  type: object
                  properties:
                    integration_instance_ids:
                      type: string
                    reconciliation_status:
                      type: string
              example:
                fnsku_product_ids:
                - 101
                - 102
                - 103
                apply_to_all: false
                filters:
                  integration_instance_ids: 1,2
                  reconciliation_status: needs_attention
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      total:
                        type: integer
                      dispatched:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    total: 3
                    dispatched: 3
                  message: 'Bulk reconciliation dispatched: 3 FNSKU products'
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-amazon-unified-fnsku-products-bulk-reconcile
  /api/amazon/unified/fnsku-products/bulk-unreconcile:
    post:
      tags:
      - Amazon
      summary: Bulk Unreconcile
      description: 'Dispatch bulk unreconciliation for the given FNSKU product IDs,
        or for all IDs matching `filters` when `apply_to_all=true`.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                fnsku_product_ids:
                  type: array
                  items:
                    type: integer
                apply_to_all:
                  type: boolean
                filters:
                  type: object
                  properties:
                    integration_instance_ids:
                      type: string
              example:
                fnsku_product_ids:
                - 101
                - 102
                - 103
                apply_to_all: false
                filters:
                  integration_instance_ids: 1,2
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      total:
                        type: integer
                      dispatched:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    total: 3
                    dispatched: 3
                  message: 'Bulk unreconciliation dispatched: 3 FNSKU products'
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-amazon-unified-fnsku-products-bulk-unreconcile
  /api/amazon/unified/fnsku-products/reconcile-all:
    post:
      tags:
      - Amazon
      summary: Reconcile All (tracked job)
      description: 'Dispatches a tracked a background job. Returns the tracked_job_log_id
        so the frontend can monitor progress via the tracked job log endpoints.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties: {}
              example: {}
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 4523
                  message: Reconciliation job started
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-amazon-unified-fnsku-products-reconcile-all
  /api/amazon/unified/fnsku-products/bulk-link:
    post:
      tags:
      - Amazon
      summary: Bulk Link (to single product)
      description: 'Link the given FNSKU products to a single product (or all filtered
        IDs when apply_to_all=true). Dispatches a tracked reconciliation job.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                fnsku_product_ids:
                  type: array
                  items:
                    type: integer
                apply_to_all:
                  type: boolean
                filters:
                  type: object
                  properties:
                    integration_instance_ids:
                      type: string
                product_id:
                  type: integer
              example:
                fnsku_product_ids:
                - 101
                - 102
                - 103
                apply_to_all: false
                filters:
                  integration_instance_ids: 1,2
                product_id: 9001
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      linked:
                        type: integer
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    linked: 3
                    tracked_job_log_id: 4522
                  message: Linked 3 FNSKU product(s) to product ID 9001
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-amazon-unified-fnsku-products-bulk-link
  /api/amazon/unified/fnsku-products/{fnskuProductId}/initial-unit-cost:
    patch:
      tags:
      - Amazon
      summary: Update Initial Unit Cost (single)
      description: 'Update the initial unit cost for a single FNSKU product.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                initial_unit_cost:
                  type: number
              example:
                initial_unit_cost: 4.25
      parameters:
      - name: fnskuProductId
        in: path
        required: true
        schema:
          type: string
        description: The fnskuProductId identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      fnsku_product_id:
                        type: integer
                      initial_unit_cost:
                        type: number
                  message:
                    type: string
                example:
                  data:
                    fnsku_product_id: 101
                    initial_unit_cost: 4.25
                  message: Initial unit cost updated successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: patch-api-amazon-unified-fnsku-products-fnskuproductid-initial-unit-cost
  /api/amazon/unified/fnsku-products/auto-mapping-settings:
    post:
      tags:
      - Amazon
      summary: Update Auto-Mapping Settings (Bulk)
      description: 'Bulk update FNSKU auto-mapping settings across multiple integration
        instances. Provide `ids` (array of integration instance IDs) and `is_fnsku_auto_mapping_enabled`
        (boolean). Email and in-app alerts for unmapped FNSKUs are configured separately
        via alert notification preferences.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
                is_fnsku_auto_mapping_enabled:
                  type: boolean
              example:
                ids:
                - 1
                - 2
                - 3
                is_fnsku_auto_mapping_enabled: true
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      updated_count:
                        type: integer
                example:
                  status: success
                  message: Successfully updated auto-mapping settings for 3 integration
                    instances
                  data:
                    updated_count: 3
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-amazon-unified-fnsku-products-auto-mapping-settings
  /api/amazon/unified/fnsku-products/complete-partial-mapping:
    post:
      tags:
      - Amazon
      summary: Complete Partial Mapping (by ASIN)
      description: 'For an ASIN that has some FNSKUs mapped and some unmapped, link
        the unmapped ones to the most-common existing product.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                asin:
                  type: string
                integration_instance_ids:
                  type: array
                  items:
                    type: integer
              example:
                asin: B0987FGHIJ
                integration_instance_ids:
                - 1
                - 2
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      mapped_count:
                        type: integer
                      product_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    mapped_count: 2
                    product_id: 9001
                  message: 'Completed partial mapping: mapped 2 FNSKU products with
                    ASIN B0987FGHIJ to product ID 9001'
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-amazon-unified-fnsku-products-complete-partial-mapping
  /api/amazon/unified/fnsku-products/{id}/summary-ledgers:
    get:
      tags:
      - Amazon
      summary: FNSKU Summary Ledgers (paginated)
      description: 'Paginated FBA inventory ledger summary rows for an FNSKU product.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        date:
                          type: string
                        fnsku:
                          type: string
                        asin:
                          type: string
                        msku:
                          type: string
                        location:
                          type: string
                        disposition:
                          type: string
                        ending_warehouse_balance:
                          type: integer
                        in_transit_between_warehouses:
                          type: integer
                        receipts:
                          type: integer
                        customer_shipments:
                          type: integer
                        customer_returns:
                          type: integer
                        vendor_returns:
                          type: integer
                        warehouse_transfer_in_out:
                          type: integer
                        found:
                          type: integer
                        lost:
                          type: integer
                        damaged:
                          type: integer
                        disposed:
                          type: integer
                        other_events:
                          type: integer
                        unknown_events:
                          type: integer
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 31001
                    date: '2026-05-01'
                    fnsku: X001ABCDEF
                    asin: B0123ABCDE
                    msku: SELLER-SKU-A
                    location: US
                    disposition: SELLABLE
                    ending_warehouse_balance: 245
                    in_transit_between_warehouses: 10
                    receipts: 50
                    customer_shipments: -45
                    customer_returns: 5
                    vendor_returns: 0
                    warehouse_transfer_in_out: 0
                    found: 0
                    lost: 0
                    damaged: 0
                    disposed: 0
                    other_events: 0
                    unknown_events: 0
                  current_page: 1
                  last_page: 2
                  per_page: 15
                  total: 30
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-unified-fnsku-products-id-summary-ledgers
  /api/amazon/unified/fnsku-products/{id}/removal-orders:
    get:
      tags:
      - Amazon
      summary: FNSKU Removal Orders (paginated)
      description: 'Paginated removal orders associated with an FNSKU product.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        order_id:
                          type: string
                        order_status:
                          type: string
                        order_type:
                          type: string
                        requested_quantity:
                          type: integer
                        cancelled_quantity:
                          type: integer
                        disposed_quantity:
                          type: integer
                        shipped_quantity:
                          type: integer
                        in_process_quantity:
                          type: integer
                        requested_date:
                          type: string
                        last_updated_date:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 4001
                    order_id: REM-2026-0001
                    order_status: Completed
                    order_type: Return
                    requested_quantity: 25
                    cancelled_quantity: 0
                    disposed_quantity: 0
                    shipped_quantity: 25
                    in_process_quantity: 0
                    requested_date: '2026-04-01'
                    last_updated_date: '2026-04-05'
                  current_page: 1
                  last_page: 1
                  per_page: 15
                  total: 2
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-unified-fnsku-products-id-removal-orders
  /api/amazon/unified/fnsku-products/{id}/removal-shipments:
    get:
      tags:
      - Amazon
      summary: FNSKU Removal Shipments (paginated)
      description: 'Paginated removal shipments associated with an FNSKU product.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        order_id:
                          type: string
                        shipment_date:
                          type: string
                        tracking_number:
                          type: string
                        carrier:
                          type: string
                        shipped_quantity:
                          type: integer
                        disposition:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 5001
                    order_id: REM-2026-0001
                    shipment_date: '2026-04-05T10:00:00.000000Z'
                    tracking_number: 1Z999AA10123456784
                    carrier: UPS
                    shipped_quantity: 25
                    disposition: SELLABLE
                  current_page: 1
                  last_page: 1
                  per_page: 15
                  total: 2
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-unified-fnsku-products-id-removal-shipments
  /api/amazon/unified/fnsku-products/{id}/reconciliation-timeline:
    get:
      tags:
      - Amazon
      summary: Reconciliation Timeline (paginated)
      description: 'Chronological reconciliation stream (ledger entries + discrepancies)
        with running tally, FIFO layer data, and summary balances.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        type:
                          type: string
                        id:
                          type: integer
                        event_datetime:
                          type: string
                        event_type:
                          type: string
                        quantity:
                          type: integer
                        running_tally:
                          type: integer
                        reconciled_at:
                          type: string
                        fifo_layer:
                          type: object
                          properties:
                            id:
                              type: integer
                            cogs:
                              type: number
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - type: ledger
                    id: 70011
                    event_datetime: '2026-02-01T10:00:00.000000Z'
                    event_type: Receipts
                    quantity: 100
                    running_tally: 100
                    reconciled_at: '2026-02-02T08:00:00.000000Z'
                    fifo_layer:
                      id: 5512
                      cogs: 4.25
                  - type: discrepancy
                    id: 9111
                    discrepancy_date: '2026-04-10'
                    reason_type: ledger_summary_mismatch
                    quantity: 5
                    reconciled_at: null
                  current_page: 1
                  last_page: 3
                  per_page: 50
                  total: 121
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-unified-fnsku-products-id-reconciliation-timeline
  /api/amazon/unified/fnsku-products/{id}/reconciliation-sync-status:
    get:
      tags:
      - Amazon
      summary: Reconciliation Sync Status
      description: 'Summary statistics about how many entries are reconciled.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      total_ledgers:
                        type: integer
                      reconciled_ledgers:
                        type: integer
                      unreconciled_ledgers:
                        type: integer
                      reconciliation_percentage:
                        type: integer
                      last_reconciled_at:
                        type: string
                      unreconciled_discrepancies:
                        type: integer
                example:
                  data:
                    total_ledgers: 120
                    reconciled_ledgers: 118
                    unreconciled_ledgers: 2
                    reconciliation_percentage: 98
                    last_reconciled_at: '2026-05-01T08:15:00.000000Z'
                    unreconciled_discrepancies: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-unified-fnsku-products-id-reconciliation-sync-status
  /api/amazon/unified/fnsku-products/{id}/reconciliation-chart-data:
    get:
      tags:
      - Amazon
      summary: Reconciliation Chart Data
      description: 'Time-series data points for the reconciliation chart for a single
        FNSKU product.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      labels:
                        type: array
                        items:
                          type: string
                      datasets:
                        type: array
                        items:
                          type: object
                          properties:
                            label:
                              type: string
                            data:
                              type: array
                              items:
                                type: integer
                example:
                  data:
                    labels:
                    - 2026-01
                    - 2026-02
                    - 2026-03
                    - 2026-04
                    - 2026-05
                    datasets:
                    - label: Ledger Balance
                      data:
                      - 250
                      - 305
                      - 280
                      - 260
                      - 250
                    - label: Summary Balance
                      data:
                      - 250
                      - 300
                      - 275
                      - 255
                      - 245
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-unified-fnsku-products-id-reconciliation-chart-data
  /api/amazon/unified/fnsku-products/bulk-unlink:
    post:
      tags:
      - Amazon
      summary: Bulk Unlink
      description: 'Unlink the given FNSKU products from their products (or all filtered
        IDs when apply_to_all=true). Each is also auto-unreconciled.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                fnsku_product_ids:
                  type: array
                  items:
                    type: integer
                apply_to_all:
                  type: boolean
                filters:
                  type: object
                  properties:
                    integration_instance_ids:
                      type: string
              example:
                fnsku_product_ids:
                - 101
                - 102
                - 103
                apply_to_all: false
                filters:
                  integration_instance_ids: 1,2
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      unlinked:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    unlinked: 3
                  message: Unlinked 3 FNSKU product(s)
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-amazon-unified-fnsku-products-bulk-unlink
  /api/amazon/unified/fnsku-products/unreconcile-all:
    post:
      tags:
      - Amazon
      summary: Unreconcile All (tracked job)
      description: 'Dispatches a tracked a background job. Returns the tracked_job_log_id
        for progress monitoring.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties: {}
              example: {}
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 4524
                  message: Unreconciliation job started
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-amazon-unified-fnsku-products-unreconcile-all
  /api/amazon/unified/fnsku-products/{id}/reconcile:
    post:
      tags:
      - Amazon
      summary: Reconcile Single FNSKU
      description: 'Synchronously reconcile a single FNSKU product''s COGS. Long-running
        (time limit raised to 300s).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties: {}
              example: {}
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: FNSKU product reconciled successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-amazon-unified-fnsku-products-id-reconcile
  /api/amazon/unified/fnsku-products/{id}/unreconcile:
    post:
      tags:
      - Amazon
      summary: Unreconcile Single FNSKU
      description: 'Synchronously unreconcile a single FNSKU product''s COGS.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties: {}
              example: {}
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: FNSKU product unreconciled successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-amazon-unified-fnsku-products-id-unreconcile
  /api/amazon/unified/fnsku-products/bulk-update-initial-unit-cost:
    post:
      tags:
      - Amazon
      summary: Bulk Update Initial Unit Cost
      description: 'Apply the same initial unit cost to multiple FNSKU products.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                fnsku_product_ids:
                  type: array
                  items:
                    type: integer
                initial_unit_cost:
                  type: number
              example:
                fnsku_product_ids:
                - 101
                - 102
                - 103
                initial_unit_cost: 4.25
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      updated_count:
                        type: integer
                      initial_unit_cost:
                        type: number
                  message:
                    type: string
                example:
                  data:
                    updated_count: 3
                    initial_unit_cost: 4.25
                  message: Updated initial unit cost for 3 FNSKU product(s)
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-amazon-unified-fnsku-products-bulk-update-initial-unit-cost
  /api/amazon/unified/fnsku-products/{id}/suggested-initial-unit-cost:
    get:
      tags:
      - Amazon
      summary: Suggested Initial Unit Cost (single)
      description: 'Returns suggestions for the initial unit cost: from the mapped
        product''s unit_cost and from sibling FNSKUs (same product + same country/location).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      product_suggestion:
                        type: object
                        properties:
                          source:
                            type: string
                          value:
                            type: number
                          product_id:
                            type: integer
                          product_sku:
                            type: string
                          product_name:
                            type: string
                      sibling_suggestions:
                        type: array
                        items:
                          type: object
                          properties:
                            source:
                              type: string
                            value:
                              type: number
                            fnsku_product_id:
                              type: integer
                            fnsku:
                              type: string
                            location:
                              type: string
                            disposition:
                              type: string
                            integration_instance_name:
                              type: string
                  message:
                    type: string
                example:
                  data:
                    product_suggestion:
                      source: product
                      value: 4.25
                      product_id: 9001
                      product_sku: SKU-123
                      product_name: Widget
                    sibling_suggestions:
                    - source: sibling_fnsku
                      value: 4.3
                      fnsku_product_id: 102
                      fnsku: X001SIBLING
                      location: US
                      disposition: SELLABLE
                      integration_instance_name: Amazon US (Production)
                  message: Success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-unified-fnsku-products-id-suggested-initial-unit-cost
  /api/amazon/unified/fnsku-products/{id}/asin-suggestion:
    get:
      tags:
      - Amazon
      summary: ASIN Suggestion (single)
      description: 'Looks up the ASIN/MSKU/title for the given FNSKU and checks if
        another FNSKU with the same ASIN is already mapped to a product.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      asin:
                        type: string
                      msku:
                        type: string
                      title:
                        type: string
                      suggested_product:
                        type: object
                        properties:
                          id:
                            type: integer
                          sku:
                            type: string
                          name:
                            type: string
                  message:
                    type: string
                example:
                  data:
                    asin: B0123ABCDE
                    msku: SELLER-SKU-A
                    title: Widget Black
                    suggested_product:
                      id: 9001
                      sku: SKU-123
                      name: Widget
                  message: Success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-unified-fnsku-products-id-asin-suggestion
  /api/amazon/unified/fnsku-products/bulk-suggested-initial-unit-cost:
    post:
      tags:
      - Amazon
      summary: Bulk Suggested Initial Unit Cost
      description: 'Returns per-FNSKU initial unit cost suggestions with pre-computed
        `recommended_value` and `is_uniform` flags for bulk editing.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                fnsku_product_ids:
                  type: array
                  items:
                    type: integer
              example:
                fnsku_product_ids:
                - 101
                - 102
                - 103
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        fnsku_product_id:
                          type: integer
                        suggestions:
                          type: object
                          properties:
                            product_suggestion:
                              type: object
                              properties:
                                source:
                                  type: string
                                value:
                                  type: number
                                product_id:
                                  type: integer
                                product_sku:
                                  type: string
                                product_name:
                                  type: string
                            sibling_suggestions:
                              type: array
                              items:
                                type: object
                                properties:
                                  source:
                                    type: string
                                  value:
                                    type: number
                                  fnsku_product_id:
                                    type: integer
                                  fnsku:
                                    type: string
                                  location:
                                    type: string
                                  disposition:
                                    type: string
                                  integration_instance_name:
                                    type: string
                        recommended_value:
                          type: number
                        all_suggestion_values:
                          type: array
                          items:
                            type: number
                        is_uniform:
                          type: boolean
                  message:
                    type: string
                example:
                  data:
                  - fnsku_product_id: 101
                    suggestions:
                      product_suggestion:
                        source: product
                        value: 4.25
                        product_id: 9001
                        product_sku: SKU-123
                        product_name: Widget
                      sibling_suggestions:
                      - source: sibling_fnsku
                        value: 4.25
                        fnsku_product_id: 102
                        fnsku: X001SIBLING
                        location: US
                        disposition: SELLABLE
                        integration_instance_name: Amazon US (Production)
                    recommended_value: 4.25
                    all_suggestion_values:
                    - 4.25
                    - 4.25
                    is_uniform: true
                  message: Success
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-amazon-unified-fnsku-products-bulk-suggested-initial-unit-cost
  /api/amazon/unified/fnsku-products/create-fifo-layers:
    post:
      tags:
      - Amazon
      summary: Create FIFO Layers for Initial Inventory
      description: 'Create FIFO layers for initial inventory. Specific IDs run synchronously;
        `apply_to_all=true` dispatches a tracked a background job.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                fnsku_product_ids:
                  type: array
                  items:
                    type: integer
                apply_to_all:
                  type: boolean
                filters:
                  type: object
                  properties:
                    integration_instance_ids:
                      type: string
                    fifo_layer_status:
                      type: string
              example:
                fnsku_product_ids:
                - 101
                - 102
                - 103
                apply_to_all: false
                filters:
                  integration_instance_ids: 1,2
                  fifo_layer_status: no_fifo_layer
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 OK (synchronous mode)
                  value:
                    data:
                      created: 2
                      skipped: 1
                      failed: 0
                      errors: []
                    message: 'FIFO layers created: 2, skipped: 1, failed: 0'
                example-1:
                  summary: 200 OK (apply_to_all -> tracked job)
                  value:
                    data:
                      tracked_job_log_id: 4525
                    message: Initialization job started
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-amazon-unified-fnsku-products-create-fifo-layers
  /api/amazon/unified/ledgers:
    get:
      tags:
      - Amazon
      summary: List Ledgers
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        example: '1'
        description: Page number (default 1).
      - name: per_page
        in: query
        schema:
          type: integer
        example: '10'
        description: Results per page (default 10).
      - name: search
        in: query
        schema:
          type: string
        description: Free-text search across the resource’s searchable fields.
      - name: integration_instance_ids
        in: query
        schema:
          type: string
        description: Comma-separated IDs
      - name: date_from
        in: query
        schema:
          type: string
        description: m/d/Y format
      - name: date_to
        in: query
        schema:
          type: string
        description: m/d/Y format
      - name: event_type
        in: query
        schema:
          type: string
      - name: status
        in: query
        schema:
          type: string
      - name: sort
        in: query
        schema:
          type: string
        description: Prefix with - for descending
        example: -id
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      description: 'List Ledgers


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      operationId: get-api-amazon-unified-ledgers
  /api/amazon/unified/ledgers/{id}:
    get:
      tags:
      - Amazon
      summary: Get Ledger
      parameters:
      - name: id
        in: path
        schema:
          type: string
        required: true
        description: The record ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      description: 'Get Ledger


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      operationId: get-api-amazon-unified-ledgers-id
  /api/amazon/unified/ledgers/{id}/activity-log:
    get:
      tags:
      - Amazon
      summary: Get Ledger Activity Log
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        example: '1'
        description: Page number (default 1).
      - name: per_page
        in: query
        schema:
          type: integer
        example: '15'
        description: Results per page (default 10).
      - name: id
        in: path
        schema:
          type: string
        required: true
        description: The record ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      description: 'Get Ledger Activity Log


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      operationId: get-api-amazon-unified-ledgers-id-activity-log
  /api/amazon/unified/ledgers/export:
    get:
      tags:
      - Amazon
      summary: Export Ledgers
      parameters:
      - name: integration_instance_ids
        in: query
        schema:
          type: string
        description: Comma-separated integration instance IDs to scope the query.
      - name: search
        in: query
        schema:
          type: string
        description: Free-text search across the resource’s searchable fields.
      - name: date_from
        in: query
        schema:
          type: string
        description: Start of the date range (see the Dates & Timezones guide for
          formats).
      - name: date_to
        in: query
        schema:
          type: string
        description: End of the date range (see the Dates & Timezones guide for formats).
      - name: event_type
        in: query
        schema:
          type: string
      - name: status
        in: query
        schema:
          type: string
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      description: 'Export Ledgers


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      operationId: get-api-amazon-unified-ledgers-export
  /api/amazon/unified/summary-ledgers:
    get:
      tags:
      - Amazon
      summary: List Summary Ledgers
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        example: '1'
        description: Page number (default 1).
      - name: per_page
        in: query
        schema:
          type: integer
        example: '10'
        description: Results per page (default 10).
      - name: search
        in: query
        schema:
          type: string
        description: Free-text search across the resource’s searchable fields.
      - name: integration_instance_ids
        in: query
        schema:
          type: string
        description: Comma-separated integration instance IDs to scope the query.
      - name: date_from
        in: query
        schema:
          type: string
        description: Start of the date range (see the Dates & Timezones guide for
          formats).
      - name: date_to
        in: query
        schema:
          type: string
        description: End of the date range (see the Dates & Timezones guide for formats).
      - name: disposition
        in: query
        schema:
          type: string
      - name: status
        in: query
        schema:
          type: string
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      description: 'List Summary Ledgers


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      operationId: get-api-amazon-unified-summary-ledgers
  /api/amazon/unified/summary-ledgers/{id}:
    get:
      tags:
      - Amazon
      summary: Get Summary Ledger
      parameters:
      - name: id
        in: path
        schema:
          type: string
        required: true
        description: The record ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      description: 'Get Summary Ledger


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      operationId: get-api-amazon-unified-summary-ledgers-id
  /api/amazon/unified/summary-ledgers/current-summary:
    get:
      tags:
      - Amazon
      summary: Get Current Summary
      parameters:
      - name: integration_instance_ids
        in: query
        schema:
          type: string
        description: Comma-separated integration instance IDs to scope the query.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      description: 'Get Current Summary


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      operationId: get-api-amazon-unified-summary-ledgers-current-summary
  /api/amazon/unified/summary-ledgers/export:
    get:
      tags:
      - Amazon
      summary: Export Summary Ledgers
      parameters:
      - name: integration_instance_ids
        in: query
        schema:
          type: string
        description: Comma-separated integration instance IDs to scope the query.
      - name: search
        in: query
        schema:
          type: string
        description: Free-text search across the resource’s searchable fields.
      - name: date_from
        in: query
        schema:
          type: string
        description: Start of the date range (see the Dates & Timezones guide for
          formats).
      - name: date_to
        in: query
        schema:
          type: string
        description: End of the date range (see the Dates & Timezones guide for formats).
      - name: disposition
        in: query
        schema:
          type: string
      - name: status
        in: query
        schema:
          type: string
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      description: 'Export Summary Ledgers


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      operationId: get-api-amazon-unified-summary-ledgers-export
  /api/amazon/unified/summary-ledgers/{id}/activity-log:
    get:
      tags:
      - Amazon
      summary: Get Summary Ledger Activity Log
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        example: '1'
        description: Page number (default 1).
      - name: per_page
        in: query
        schema:
          type: integer
        example: '15'
        description: Results per page (default 10).
      - name: id
        in: path
        schema:
          type: string
        required: true
        description: The record ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      description: 'Get Summary Ledger Activity Log


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      operationId: get-api-amazon-unified-summary-ledgers-id-activity-log
  /api/amazon/unified/customer-returns:
    get:
      tags:
      - Amazon
      summary: List FBA Customer Returns (Across Instances)
      description: 'Returns a paginated list of Amazon FBA customer returns aggregated
        across all (or selected) Amazon integration instances.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Supports Spatie QueryBuilder filtering, sorting, and pagination. Defaults
        to 10 items per page. Eager-loads the related `integrationInstance` and `reviewedBy`
        user.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_name:
                          type: string
                        event_datetime:
                          type: string
                        order_id:
                          type: string
                        sku:
                          type: string
                        asin:
                          type: string
                        fnsku:
                          type: string
                        amazon_product:
                          type: object
                          properties:
                            id:
                              type: integer
                        product_name:
                          type: string
                        quantity:
                          type: integer
                        fulfillment_center_id:
                          type: string
                        detailed_disposition:
                          type: string
                        reason:
                          type: string
                        status:
                          type: string
                        license_plate_number:
                          type: string
                        customer_comments:
                          type: string
                        reviewed_at:
                          type: string
                        reviewed_by:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                    items:
                      type: object
                      properties:
                        url:
                          type: string
                          nullable: true
                        label:
                          type: string
                        active:
                          type: boolean
                  next_page_url:
                    type: string
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 12345
                    integration_instance_name: Amazon US Marketplace
                    event_datetime: '2026-05-20T14:32:11.000000Z'
                    order_id: 112-1234567-1234567
                    sku: WIDGET-RED-LG
                    asin: B07XYZ1234
                    fnsku: X0012345AB
                    amazon_product:
                      id: 789
                    product_name: Acme Red Widget - Large
                    quantity: 1
                    fulfillment_center_id: PHX7
                    detailed_disposition: CUSTOMER_DAMAGED
                    reason: DAMAGED_BY_CARRIER
                    status: Reimbursed
                    license_plate_number: LPN9876543210
                    customer_comments: Arrived with a torn box and a scratched item.
                    reviewed_at: '2026-05-22T09:15:42.000000Z'
                    reviewed_by:
                      id: 7
                      name: Jane Doe
                    created_at: '2026-05-20T14:35:00.000000Z'
                    updated_at: '2026-05-22T09:15:42.000000Z'
                  current_page: 1
                  first_page_url: https://example.test/api/amazon/unified/customer-returns?page=1
                  from: 1
                  last_page: 12
                  last_page_url: https://example.test/api/amazon/unified/customer-returns?page=12
                  links:
                  - url: null
                    label: '&laquo; Previous'
                    active: false
                  - url: https://example.test/api/amazon/unified/customer-returns?page=1
                    label: '1'
                    active: true
                  - url: https://example.test/api/amazon/unified/customer-returns?page=2
                    label: Next &raquo;
                    active: false
                  next_page_url: https://example.test/api/amazon/unified/customer-returns?page=2
                  path: https://example.test/api/amazon/unified/customer-returns
                  per_page: 10
                  prev_page_url: null
                  to: 10
                  total: 117
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-amazon-unified-customer-returns
  /api/amazon/unified/customer-returns/bulk-mark-reviewed:
    post:
      tags:
      - Amazon
      summary: Bulk Mark Customer Returns as Reviewed
      description: 'Dispatches a tracked background job to mark the given Amazon FBA
        customer return records as reviewed by the authenticated user.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Request body:

        - `ids` (required, array, 1-1000 integers): IDs of `amazon_fba_report_customer_returns`
        records to mark reviewed.


        Returns a `tracked_job_log_id` that the frontend can subscribe to via the
        tracked job log endpoints.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 12345
                - 12346
                - 12347
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 4821
                  message: Bulk mark reviewed started
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      ids:
                        type: array
                        items:
                          type: string
                example:
                  message: The ids field is required.
                  errors:
                    ids:
                    - The ids field is required.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-amazon-unified-customer-returns-bulk-mark-reviewed
  /api/amazon/unified/customer-returns/bulk-mark-unreviewed:
    post:
      tags:
      - Amazon
      summary: Bulk Mark Customer Returns as Unreviewed
      description: 'Dispatches a tracked background job to mark the given Amazon FBA
        customer return records as NOT reviewed (clearing `reviewed_at` and `reviewed_by_user_id`).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Request body:

        - `ids` (required, array, 1-1000 integers): IDs of `amazon_fba_report_customer_returns`
        records to mark unreviewed.


        Returns a `tracked_job_log_id` that the frontend can subscribe to via the
        tracked job log endpoints.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 12345
                - 12346
                - 12347
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 4822
                  message: Bulk mark unreviewed started
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      ids:
                        type: array
                        items:
                          type: string
                example:
                  message: At least one id is required.
                  errors:
                    ids:
                    - At least one id is required.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-amazon-unified-customer-returns-bulk-mark-unreviewed
  /api/amazon/unified/customer-returns/kpi-stats:
    get:
      tags:
      - Amazon
      summary: Get Customer Return KPI Stats
      description: 'Returns headline counts for FBA customer returns across integration
        instances:

        - total: all customer return rows

        - unreviewed: rows not yet marked as reviewed

        - damaged: rows whose detailed disposition is CARRIER_DAMAGED, CUSTOMER_DAMAGED,
        DAMAGED, or DEFECTIVE


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Query parameters: integration_instance_ids (optional, comma-separated instance
        IDs; omit to count across all instances).'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      total:
                        type: integer
                      unreviewed:
                        type: integer
                      damaged:
                        type: integer
                  status:
                    type: string
                example:
                  data:
                    total: 1284
                    unreviewed: 211
                    damaged: 96
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-amazon-unified-customer-returns-kpi-stats
  /api/amazon/unified/customer-returns/{customerReturn}:
    get:
      tags:
      - Amazon
      summary: Get Customer Return
      description: 'Returns a single FBA customer return report row with its cross-links
        resolved:

        - amazon_product: the matching Amazon listing ({id}), when the SKU resolves

        - reviewed_by: the user who marked the row reviewed ({id, name}), null-fielded
        when unreviewed

        - linked_sales_order: the SKU.io sales order created from the original Amazon
        order ({id, sales_order_number, order_status}), or null when no match


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Other fields include order_id (the Amazon order ID), sku, asin, fnsku, product_name,
        quantity, fulfillment_center_id, detailed_disposition (e.g. SELLABLE, CUSTOMER_DAMAGED),
        reason (Amazon''s return reason code), status, license_plate_number (LPN),
        customer_comments, reviewed_at, return_date and event_datetime (UTC).


        Optional query parameters included / excluded (URL-encoded JSON arrays of
        column names) limit which columns are returned.'
      parameters:
      - name: customerReturn
        in: path
        schema:
          type: string
        required: true
        description: Customer return row ID
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_name:
                        type: string
                      event_datetime:
                        type: string
                      order_id:
                        type: string
                      sku:
                        type: string
                      asin:
                        type: string
                      fnsku:
                        type: string
                      amazon_product:
                        type: object
                        properties:
                          id:
                            type: integer
                      product_name:
                        type: string
                      quantity:
                        type: integer
                      fulfillment_center_id:
                        type: string
                      detailed_disposition:
                        type: string
                      reason:
                        type: string
                      status:
                        type: string
                      license_plate_number:
                        type: string
                      customer_comments:
                        type: string
                      reviewed_at:
                        type: string
                      reviewed_by:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      linked_sales_order:
                        type: object
                        properties:
                          id:
                            type: integer
                          sales_order_number:
                            type: string
                          order_status:
                            type: string
                      integration_instance_id:
                        type: integer
                      return_date:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                  status:
                    type: string
                example:
                  data:
                    id: 55107
                    integration_instance_name: Amazon US
                    event_datetime: '2026-06-20T14:35:22.000000Z'
                    order_id: 113-9876543-1234567
                    sku: WIDGET-BLUE-M
                    asin: B08XYZAB12
                    fnsku: X002ABCDE1
                    amazon_product:
                      id: 5512
                    product_name: Blue Widget - Medium
                    quantity: 1
                    fulfillment_center_id: TUL2
                    detailed_disposition: SELLABLE
                    reason: NO_LONGER_NEEDED
                    status: Unit returned to inventory
                    license_plate_number: LPNRR123456789
                    customer_comments: Ordered the wrong size
                    reviewed_at: '2026-06-21T08:12:45.000000Z'
                    reviewed_by:
                      id: 12
                      name: Jane Doe
                    linked_sales_order:
                      id: 88213
                      sales_order_number: SO-102431
                      order_status: completed
                    integration_instance_id: 3
                    return_date: '2026-06-20T00:00:00.000000Z'
                    created_at: '2026-06-21T03:05:12.000000Z'
                    updated_at: '2026-06-21T08:12:45.000000Z'
                  status: success
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: object
                    properties:
                      Modules\Amazon\Entities\AmazonFbaReportCustomerReturn:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: array
                  status:
                    type: string
                  message:
                    type: string
                example:
                  errors:
                    Modules\Amazon\Entities\AmazonFbaReportCustomerReturn:
                    - message: No query results for model [Modules\Amazon\Entities\AmazonFbaReportCustomerReturn]
                        99999
                      code: NotFound
                      data: []
                  status: failure
                  message: No query results for model [Modules\Amazon\Entities\AmazonFbaReportCustomerReturn]
                    99999
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-amazon-unified-customer-returns-customerreturn
  /api/amazon/unified/customer-returns/{customerReturn}/activity-log:
    get:
      tags:
      - Amazon
      summary: Get Customer Return Activity Log
      description: 'Returns the activity log for a single FBA customer return row:
        the most recent 200 entries, newest first (not paginated). Each entry contains
        id, description, event (created / updated / deleted), causer ({id, name, email}
        of the user who made the change, or null for system changes), properties (old
        and attributes objects with the changed field values), and created_at (UTC).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: customerReturn
        in: path
        schema:
          type: string
        required: true
        description: Customer return row ID
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        description:
                          type: string
                        event:
                          type: string
                        causer:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            email:
                              type: string
                        properties:
                          type: object
                          properties:
                            old:
                              type: object
                              properties:
                                reviewed_at:
                                  type: string
                                  nullable: true
                                reviewed_by_user_id:
                                  type: string
                                  nullable: true
                            attributes:
                              type: object
                              properties:
                                reviewed_at:
                                  type: string
                                reviewed_by_user_id:
                                  type: integer
                        created_at:
                          type: string
                example:
                  data:
                  - id: 40233
                    description: updated
                    event: updated
                    causer:
                      id: 12
                      name: Jane Doe
                      email: jane@example.com
                    properties:
                      old:
                        reviewed_at: null
                        reviewed_by_user_id: null
                      attributes:
                        reviewed_at: '2026-06-21T08:12:45.000000Z'
                        reviewed_by_user_id: 12
                    created_at: '2026-06-21T08:12:45.000000Z'
                  - id: 39871
                    description: created
                    event: created
                    causer: null
                    properties:
                      old: null
                      attributes:
                        order_id: 113-9876543-1234567
                        fnsku: X002ABCDE1
                        quantity: 1
                    created_at: '2026-06-21T03:05:12.000000Z'
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: object
                    properties:
                      Modules\Amazon\Entities\AmazonFbaReportCustomerReturn:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: array
                  status:
                    type: string
                  message:
                    type: string
                example:
                  errors:
                    Modules\Amazon\Entities\AmazonFbaReportCustomerReturn:
                    - message: No query results for model [Modules\Amazon\Entities\AmazonFbaReportCustomerReturn]
                        99999
                      code: NotFound
                      data: []
                  status: failure
                  message: No query results for model [Modules\Amazon\Entities\AmazonFbaReportCustomerReturn]
                    99999
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-amazon-unified-customer-returns-customerreturn-activity-log
  /api/amazon/unified/removal-orders:
    get:
      tags:
      - Amazon
      summary: List Removal Orders (Grouped Across Instances)
      description: 'Returns paginated removal orders grouped by (order_id, integration_instance_id).
        Each row is a SUMMARY with aggregated quantities, a representative status/type/disposition,
        line_count, and a lines array containing line-level rows for expandable UI.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Each row also carries is_straddle (the order''s shipment predates the FBA
        inventory tracking start date) and has_pending_straddle (a straddle line still
        has pending quantity to reconcile). Use filter[needs_attention]=true to list
        only orders with pending straddle quantity.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        order_id:
                          type: string
                        request_date:
                          type: string
                        order_status:
                          type: string
                        order_type:
                          type: string
                        last_updated_date:
                          type: string
                        sku:
                          type: string
                        fnsku:
                          type: string
                        disposition:
                          type: string
                        requested_quantity:
                          type: integer
                        cancelled_quantity:
                          type: integer
                        disposed_quantity:
                          type: integer
                        shipped_quantity:
                          type: integer
                        in_process_quantity:
                          type: integer
                        removal_fee:
                          type: string
                        currency:
                          type: string
                        is_unknown_item:
                          type: boolean
                        archived_at:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                        updated_at:
                          type: string
                        line_count:
                          type: integer
                        integration_instance:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        integration_instance_id:
                          type: integer
                        integration_instance_name:
                          type: string
                        receiving_status:
                          type: string
                        is_straddle:
                          type: boolean
                        has_pending_straddle:
                          type: boolean
                        sku_links:
                          type: array
                        fnsku_product:
                          type: object
                          properties:
                            id:
                              type: integer
                            fnsku:
                              type: string
                            location:
                              type: string
                            disposition:
                              type: string
                            product:
                              type: object
                              properties:
                                id:
                                  type: integer
                                sku:
                                  type: string
                                name:
                                  type: string
                        lines:
                          type: array
                          items:
                            type: object
                            properties:
                              id:
                                type: integer
                              order_id:
                                type: string
                              sku:
                                type: string
                              fnsku:
                                type: string
                              disposition:
                                type: string
                              requested_quantity:
                                type: integer
                              shipped_quantity:
                                type: integer
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                  first_page_url:
                    type: string
                  last_page_url:
                    type: string
                  next_page_url:
                    type: string
                  prev_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  links:
                    type: array
                example:
                  data:
                  - id: 1234
                    order_id: D-1234567
                    request_date: '2026-04-12T14:30:00.000000Z'
                    order_status: Completed
                    order_type: Disposal
                    last_updated_date: '2026-04-14T08:15:00.000000Z'
                    sku: SKU-100
                    fnsku: X001ABCD12
                    disposition: Sellable
                    requested_quantity: 50
                    cancelled_quantity: 0
                    disposed_quantity: 0
                    shipped_quantity: 50
                    in_process_quantity: 0
                    removal_fee: '7.50'
                    currency: USD
                    is_unknown_item: false
                    archived_at: null
                    created_at: '2026-04-12T14:30:00.000000Z'
                    updated_at: '2026-04-14T08:15:00.000000Z'
                    line_count: 3
                    integration_instance:
                      id: 1
                      name: Amazon US
                    integration_instance_id: 1
                    integration_instance_name: Amazon US
                    receiving_status: pending
                    is_straddle: false
                    has_pending_straddle: false
                    sku_links: []
                    fnsku_product:
                      id: 42
                      fnsku: X001ABCD12
                      location: BIN-A1
                      disposition: Sellable
                      product:
                        id: 99
                        sku: SKU-100
                        name: Sample Widget
                    lines:
                    - id: 1234
                      order_id: D-1234567
                      sku: SKU-100
                      fnsku: X001ABCD12
                      disposition: Sellable
                      requested_quantity: 20
                      shipped_quantity: 20
                  current_page: 1
                  last_page: 5
                  per_page: 10
                  total: 47
                  from: 1
                  to: 10
                  first_page_url: https://app.example.com/api/amazon/unified/removal-orders?page=1
                  last_page_url: https://app.example.com/api/amazon/unified/removal-orders?page=5
                  next_page_url: https://app.example.com/api/amazon/unified/removal-orders?page=2
                  prev_page_url: null
                  path: https://app.example.com/api/amazon/unified/removal-orders
                  links: []
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-amazon-unified-removal-orders
  /api/amazon/unified/removal-orders/{id}:
    get:
      tags:
      - Amazon
      summary: Show Removal Order
      description: 'Returns a single removal order line-level row, with integrationInstance
        and amazonFnskuProduct.product eager-loaded.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      order_id:
                        type: string
                      request_date:
                        type: string
                      order_status:
                        type: string
                      order_type:
                        type: string
                      last_updated_date:
                        type: string
                      sku:
                        type: string
                      fnsku:
                        type: string
                      disposition:
                        type: string
                      requested_quantity:
                        type: integer
                      cancelled_quantity:
                        type: integer
                      disposed_quantity:
                        type: integer
                      shipped_quantity:
                        type: integer
                      in_process_quantity:
                        type: integer
                      removal_fee:
                        type: string
                      currency:
                        type: string
                      is_unknown_item:
                        type: boolean
                      archived_at:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      integration_instance:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      integration_instance_id:
                        type: integer
                      integration_instance_name:
                        type: string
                      is_straddle:
                        type: boolean
                      has_pending_straddle:
                        type: boolean
                      fnsku_product:
                        type: object
                        properties:
                          id:
                            type: integer
                          fnsku:
                            type: string
                          location:
                            type: string
                          disposition:
                            type: string
                          product:
                            type: object
                            properties:
                              id:
                                type: integer
                              sku:
                                type: string
                              name:
                                type: string
                example:
                  data:
                    id: 1234
                    order_id: D-1234567
                    request_date: '2026-04-12T14:30:00.000000Z'
                    order_status: Completed
                    order_type: Disposal
                    last_updated_date: '2026-04-14T08:15:00.000000Z'
                    sku: SKU-100
                    fnsku: X001ABCD12
                    disposition: Sellable
                    requested_quantity: 20
                    cancelled_quantity: 0
                    disposed_quantity: 0
                    shipped_quantity: 20
                    in_process_quantity: 0
                    removal_fee: '2.50'
                    currency: USD
                    is_unknown_item: false
                    archived_at: null
                    created_at: '2026-04-12T14:30:00.000000Z'
                    updated_at: '2026-04-14T08:15:00.000000Z'
                    integration_instance:
                      id: 1
                      name: Amazon US
                    integration_instance_id: 1
                    integration_instance_name: Amazon US
                    is_straddle: false
                    has_pending_straddle: false
                    fnsku_product:
                      id: 42
                      fnsku: X001ABCD12
                      location: BIN-A1
                      disposition: Sellable
                      product:
                        id: 99
                        sku: SKU-100
                        name: Sample Widget
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-unified-removal-orders-id
  /api/amazon/unified/removal-orders/export:
    get:
      tags:
      - Amazon
      summary: Export Removal Orders
      description: 'Exports ALL removal orders (line-level) across integration instances
        as a JSON collection (no pagination). Used by frontend export flow.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        order_id:
                          type: string
                        request_date:
                          type: string
                        order_status:
                          type: string
                        order_type:
                          type: string
                        last_updated_date:
                          type: string
                        sku:
                          type: string
                        fnsku:
                          type: string
                        disposition:
                          type: string
                        requested_quantity:
                          type: integer
                        cancelled_quantity:
                          type: integer
                        disposed_quantity:
                          type: integer
                        shipped_quantity:
                          type: integer
                        in_process_quantity:
                          type: integer
                        removal_fee:
                          type: string
                        currency:
                          type: string
                        is_unknown_item:
                          type: boolean
                        archived_at:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                        updated_at:
                          type: string
                        integration_instance:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        integration_instance_id:
                          type: integer
                        integration_instance_name:
                          type: string
                example:
                  data:
                  - id: 1234
                    order_id: D-1234567
                    request_date: '2026-04-12T14:30:00.000000Z'
                    order_status: Completed
                    order_type: Disposal
                    last_updated_date: '2026-04-14T08:15:00.000000Z'
                    sku: SKU-100
                    fnsku: X001ABCD12
                    disposition: Sellable
                    requested_quantity: 20
                    cancelled_quantity: 0
                    disposed_quantity: 0
                    shipped_quantity: 20
                    in_process_quantity: 0
                    removal_fee: '2.50'
                    currency: USD
                    is_unknown_item: false
                    archived_at: null
                    created_at: '2026-04-12T14:30:00.000000Z'
                    updated_at: '2026-04-14T08:15:00.000000Z'
                    integration_instance:
                      id: 1
                      name: Amazon US
                    integration_instance_id: 1
                    integration_instance_name: Amazon US
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-amazon-unified-removal-orders-export
  /api/amazon/unified/removal-orders/bulk-archive:
    post:
      tags:
      - Amazon
      summary: Bulk Archive Removal Orders
      description: 'Dispatches a tracked job to bulk-archive removal orders. Body:
        { ids: int[] } (required, min 1, max 1000). Returns tracked_job_log_id.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1234
                - 1235
                - 1236
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 5678
                  message: Bulk archive started
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-amazon-unified-removal-orders-bulk-archive
  /api/amazon/unified/removal-orders/bulk-unarchive:
    post:
      tags:
      - Amazon
      summary: Bulk Unarchive Removal Orders
      description: 'Dispatches a tracked job to bulk-unarchive removal orders. Body:
        { ids: int[] } (required, min 1, max 1000). Returns tracked_job_log_id.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1234
                - 1235
                - 1236
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 5679
                  message: Bulk unarchive started
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-amazon-unified-removal-orders-bulk-unarchive
  /api/amazon/unified/removal-orders/bulk-unprocess:
    post:
      tags:
      - Amazon
      summary: Bulk Unprocess Removal Orders
      description: 'Dispatches a tracked job to bulk-unprocess removal orders (undo
        all receipts). Body: { ids: int[] } (required, min 1, max 1000). Returns tracked_job_log_id.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1234
                - 1235
                - 1236
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 5680
                  message: Bulk unprocess started
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-amazon-unified-removal-orders-bulk-unprocess
  /api/amazon/unified/removal-shipments:
    get:
      tags:
      - Amazon
      summary: List Removal Shipments (paginated, across instances)
      description: 'Returns a paginated list of Amazon FBA removal shipments aggregated
        across integration instances. Excludes archived shipments by default unless
        filter[archived]=all|only is provided. Eager-loads integrationInstance and
        amazonFnskuProduct.product.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        removal_shipment_id:
                          type: integer
                        order_id:
                          type: string
                        request_date:
                          type: string
                        shipment_date:
                          type: string
                        event_datetime:
                          type: string
                        sku:
                          type: string
                        fnsku:
                          type: string
                        disposition:
                          type: string
                        shipped_quantity:
                          type: integer
                        qty_discarded:
                          type: integer
                        carrier:
                          type: string
                        tracking_number:
                          type: string
                        removal_order_type:
                          type: string
                        created_at:
                          type: string
                        integration_instance:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        fnsku_product:
                          type: object
                          properties:
                            id:
                              type: integer
                            fnsku:
                              type: string
                            location:
                              type: string
                            disposition:
                              type: string
                            product:
                              type: object
                              properties:
                                id:
                                  type: integer
                                sku:
                                  type: string
                                name:
                                  type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                  first_page_url:
                    type: string
                  last_page_url:
                    type: string
                  next_page_url:
                    type: string
                  prev_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  links:
                    type: array
                example:
                  data:
                  - id: 1001
                    removal_shipment_id: 1001
                    order_id: '5012345678'
                    request_date: '2025-04-12T00:00:00.000000Z'
                    shipment_date: '2025-04-15T00:00:00.000000Z'
                    event_datetime: '2025-04-15T14:30:00.000000Z'
                    sku: SKU-ABC-001
                    fnsku: X001ABCDEF
                    disposition: Sellable
                    shipped_quantity: 10
                    qty_discarded: 0
                    carrier: UPS
                    tracking_number: 1Z999AA10123456784
                    removal_order_type: Return
                    created_at: '2025-04-16T08:15:00.000000Z'
                    integration_instance:
                      id: 1
                      name: US Amazon Seller
                    fnsku_product:
                      id: 501
                      fnsku: X001ABCDEF
                      location: FTW1
                      disposition: Sellable
                      product:
                        id: 7001
                        sku: INTERNAL-SKU-001
                        name: Sample Product Name
                  current_page: 1
                  last_page: 4
                  per_page: 15
                  total: 60
                  from: 1
                  to: 15
                  first_page_url: https://example.com/api/amazon/unified/removal-shipments?page=1
                  last_page_url: https://example.com/api/amazon/unified/removal-shipments?page=4
                  next_page_url: https://example.com/api/amazon/unified/removal-shipments?page=2
                  prev_page_url: null
                  path: https://example.com/api/amazon/unified/removal-shipments
                  links: []
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-amazon-unified-removal-shipments
  /api/amazon/unified/removal-shipments/{id}:
    get:
      tags:
      - Amazon
      summary: Show Removal Shipment
      description: 'Returns a single Amazon FBA removal shipment by id. Eager-loads
        integrationInstance and amazonFnskuProduct.product.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      removal_shipment_id:
                        type: integer
                      order_id:
                        type: string
                      request_date:
                        type: string
                      shipment_date:
                        type: string
                      event_datetime:
                        type: string
                      sku:
                        type: string
                      fnsku:
                        type: string
                      disposition:
                        type: string
                      shipped_quantity:
                        type: integer
                      qty_discarded:
                        type: integer
                      carrier:
                        type: string
                      tracking_number:
                        type: string
                      removal_order_type:
                        type: string
                      created_at:
                        type: string
                      integration_instance:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      fnsku_product:
                        type: object
                        properties:
                          id:
                            type: integer
                          fnsku:
                            type: string
                          location:
                            type: string
                          disposition:
                            type: string
                          product:
                            type: object
                            properties:
                              id:
                                type: integer
                              sku:
                                type: string
                              name:
                                type: string
                example:
                  data:
                    id: 1001
                    removal_shipment_id: 1001
                    order_id: '5012345678'
                    request_date: '2025-04-12T00:00:00.000000Z'
                    shipment_date: '2025-04-15T00:00:00.000000Z'
                    event_datetime: '2025-04-15T14:30:00.000000Z'
                    sku: SKU-ABC-001
                    fnsku: X001ABCDEF
                    disposition: Sellable
                    shipped_quantity: 10
                    qty_discarded: 0
                    carrier: UPS
                    tracking_number: 1Z999AA10123456784
                    removal_order_type: Return
                    created_at: '2025-04-16T08:15:00.000000Z'
                    integration_instance:
                      id: 1
                      name: US Amazon Seller
                    fnsku_product:
                      id: 501
                      fnsku: X001ABCDEF
                      location: FTW1
                      disposition: Sellable
                      product:
                        id: 7001
                        sku: INTERNAL-SKU-001
                        name: Sample Product Name
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-unified-removal-shipments-id
  /api/amazon/unified/removal-shipments/export:
    get:
      tags:
      - Amazon
      summary: Export Removal Shipments (across instances)
      description: 'Returns all matching Amazon removal shipments (not paginated)
        across integration instances for export purposes. Results are sorted by shipment_date
        descending. Note: these are flat top-level query parameters (not Spatie filter[*]
        format).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        removal_shipment_id:
                          type: integer
                        order_id:
                          type: string
                        request_date:
                          type: string
                        shipment_date:
                          type: string
                        event_datetime:
                          type: string
                        sku:
                          type: string
                        fnsku:
                          type: string
                        disposition:
                          type: string
                        shipped_quantity:
                          type: integer
                        qty_discarded:
                          type: integer
                        carrier:
                          type: string
                        tracking_number:
                          type: string
                        removal_order_type:
                          type: string
                        created_at:
                          type: string
                        integration_instance:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        fnsku_product:
                          type: object
                          properties:
                            id:
                              type: integer
                            fnsku:
                              type: string
                            location:
                              type: string
                            disposition:
                              type: string
                            product:
                              type: object
                              properties:
                                id:
                                  type: integer
                                sku:
                                  type: string
                                name:
                                  type: string
                example:
                  data:
                  - id: 1001
                    removal_shipment_id: 1001
                    order_id: '5012345678'
                    request_date: '2025-04-12T00:00:00.000000Z'
                    shipment_date: '2025-04-15T00:00:00.000000Z'
                    event_datetime: '2025-04-15T14:30:00.000000Z'
                    sku: SKU-ABC-001
                    fnsku: X001ABCDEF
                    disposition: Sellable
                    shipped_quantity: 10
                    qty_discarded: 0
                    carrier: UPS
                    tracking_number: 1Z999AA10123456784
                    removal_order_type: Return
                    created_at: '2025-04-16T08:15:00.000000Z'
                    integration_instance:
                      id: 1
                      name: US Amazon Seller
                    fnsku_product:
                      id: 501
                      fnsku: X001ABCDEF
                      location: FTW1
                      disposition: Sellable
                      product:
                        id: 7001
                        sku: INTERNAL-SKU-001
                        name: Sample Product Name
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-amazon-unified-removal-shipments-export
  /api/amazon/unified/removal-shipments/bulk-archive:
    post:
      tags:
      - Amazon
      summary: Bulk Archive Removal Shipments
      description: 'Dispatches a tracked background job to bulk-archive the specified
        removal shipments. Body: `ids` (required array, min 1, max 1000 integers).
        Returns the tracked_job_log_id so the frontend can subscribe to job progress
        via the tracked job log endpoints.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1001
                - 1002
                - 1003
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 4521
                  message: Bulk archive started
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-amazon-unified-removal-shipments-bulk-archive
  /api/amazon/unified/removal-shipments/bulk-unarchive:
    post:
      tags:
      - Amazon
      summary: Bulk Unarchive Removal Shipments
      description: 'Dispatches a tracked background job to bulk-unarchive the specified
        removal shipments. Body: `ids` (required array, min 1, max 1000 integers).
        Returns the tracked_job_log_id so the frontend can subscribe to job progress
        via the tracked job log endpoints.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1001
                - 1002
                - 1003
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 4522
                  message: Bulk unarchive started
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-amazon-unified-removal-shipments-bulk-unarchive
  /api/amazon/unified/removal-shipments/{removalShipment}/activity-log:
    get:
      tags:
      - Amazon
      summary: Get Removal Shipment Activity Log
      description: 'Returns the activity log for a single FBA removal shipment row:
        the most recent 200 entries, newest first (not paginated). Each entry contains
        id, description, event (created / updated / deleted), causer ({id, name, email}
        of the user who made the change, or null for system changes), properties (old
        and attributes objects with the changed field values), and created_at (UTC).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: removalShipment
        in: path
        schema:
          type: string
        required: true
        description: Removal shipment row ID
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        description:
                          type: string
                        event:
                          type: string
                        causer:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            email:
                              type: string
                        properties:
                          type: object
                          properties:
                            old:
                              type: object
                              properties:
                                qty_discarded:
                                  type: integer
                            attributes:
                              type: object
                              properties:
                                qty_discarded:
                                  type: integer
                        created_at:
                          type: string
                example:
                  data:
                  - id: 61233
                    description: updated
                    event: updated
                    causer:
                      id: 12
                      name: Jane Doe
                      email: jane@example.com
                    properties:
                      old:
                        qty_discarded: 0
                      attributes:
                        qty_discarded: 2
                    created_at: '2026-06-25T15:20:31.000000Z'
                  - id: 60874
                    description: created
                    event: created
                    causer: null
                    properties:
                      old: null
                      attributes:
                        order_id: S01234567
                        fnsku: X002ABCDE1
                        shipped_quantity: 12
                    created_at: '2026-06-24T06:10:02.000000Z'
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: object
                    properties:
                      Modules\Amazon\Entities\AmazonFbaReportRemovalShipment:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: array
                  status:
                    type: string
                  message:
                    type: string
                example:
                  errors:
                    Modules\Amazon\Entities\AmazonFbaReportRemovalShipment:
                    - message: No query results for model [Modules\Amazon\Entities\AmazonFbaReportRemovalShipment]
                        99999
                      code: NotFound
                      data: []
                  status: failure
                  message: No query results for model [Modules\Amazon\Entities\AmazonFbaReportRemovalShipment]
                    99999
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-amazon-unified-removal-shipments-removalshipment-activity-log
  /api/amazon/unified/removal-shipments/bulk-unprocess:
    post:
      tags:
      - Amazon
      summary: Bulk Unprocess Removal Shipments
      description: 'Undoes receipt processing for the selected removal shipments —
        removing the warehouse receipts and inventory movements created when the shipments
        were processed. Queues a background job and returns a tracked_job_log_id for
        polling progress.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Body fields:

        - ids (required, array of integers): removal shipment row IDs to unprocess
        (min 1, max 1000)'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 61201
                - 61207
                - 61233
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 4512
                  message: Bulk unprocess started
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: object
                    properties:
                      ids:
                        type: array
                        items:
                          type: string
                  message:
                    type: string
                  status:
                    type: string
                example:
                  errors:
                    ids:
                    - The ids field is required.
                  message: The ids field is required.
                  status: failure
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-amazon-unified-removal-shipments-bulk-unprocess
  /api/amazon/unified/transactions:
    get:
      tags:
      - Amazon
      summary: List Transactions (paginated, cross-instance)
      description: 'Get paginated Amazon transactions across all (or filtered) integration
        instances. Response wraps standard Laravel pagination plus an `unfiltered_total`
        field showing the true catalog size for the ExportModal ''All records'' option.
        By default, superseded transactions are excluded — pass filter[include_superseded]=true
        to include them.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        transaction_id:
                          type: string
                        transaction_type:
                          type: string
                        transaction_status:
                          type: string
                        description:
                          type: string
                        posted_date:
                          type: string
                        total_amount:
                          type: number
                        currency_code:
                          type: string
                        marketplace_id:
                          type: string
                        amazon_order_id:
                          type: string
                        is_mcf_order:
                          type: boolean
                        settlement_id:
                          type: string
                        financial_event_group_id:
                          type: string
                        shipment_id:
                          type: string
                          nullable: true
                        processed_at:
                          type: string
                          nullable: true
                        linked_sales_order:
                          type: object
                          properties:
                            id:
                              type: integer
                            sales_order_number:
                              type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                        json_object:
                          type: object
                          properties:
                            some:
                              type: string
                        integration_instance:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        items:
                          type: array
                          items:
                            type: object
                            properties:
                              id:
                                type: integer
                              item_index:
                                type: integer
                              description:
                                type: string
                              total_amount:
                                type: number
                              currency_code:
                                type: string
                              sku:
                                type: string
                              asin:
                                type: string
                              quantity:
                                type: integer
                              breakdowns:
                                type: array
                                items:
                                  type: object
                                  properties:
                                    id:
                                      type: integer
                                    breakdown_path:
                                      type: string
                                    breakdown_type:
                                      type: string
                                    top_level_type:
                                      type: string
                                    depth:
                                      type: integer
                                    amount:
                                      type: number
                                    currency_code:
                                      type: string
                        breakdowns:
                          type: array
                          items:
                            type: object
                            properties:
                              id:
                                type: integer
                              breakdown_path:
                                type: string
                              breakdown_type:
                                type: string
                              top_level_type:
                                type: string
                              depth:
                                type: integer
                              amount:
                                type: number
                              currency_code:
                                type: string
                        breakdown_totals:
                          type: array
                          items:
                            type: object
                            properties:
                              type:
                                type: string
                              total:
                                type: number
                              currency_code:
                                type: string
                        processed_entities:
                          type: array
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                  first_page_url:
                    type: string
                  last_page_url:
                    type: string
                  next_page_url:
                    type: string
                  prev_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  links:
                    type: array
                  unfiltered_total:
                    type: integer
                example:
                  data:
                  - id: 1234
                    transaction_id: abc-123-def-456
                    transaction_type: Shipment
                    transaction_status: RELEASED
                    description: Order Payment
                    posted_date: '2026-02-15T08:30:00.000000Z'
                    total_amount: 49.99
                    currency_code: USD
                    marketplace_id: ATVPDKIKX0DER
                    amazon_order_id: 701-1234567-1234567
                    is_mcf_order: false
                    settlement_id: '99999'
                    financial_event_group_id: fg-xyz
                    shipment_id: null
                    processed_at: null
                    linked_sales_order:
                      id: 5678
                      sales_order_number: SO-1001
                    created_at: '2026-02-15T09:00:00.000000Z'
                    updated_at: '2026-02-15T09:00:00.000000Z'
                    json_object:
                      some: raw amazon api fields
                    integration_instance:
                      id: 1
                      name: Amazon US
                    items:
                    - id: 9001
                      item_index: 0
                      description: Widget SKU-001
                      total_amount: 49.99
                      currency_code: USD
                      sku: SKU-001
                      asin: B0ABCDEFGH
                      quantity: 1
                      breakdowns:
                      - id: 7001
                        breakdown_path: PRODUCTCHARGES.PRINCIPAL
                        breakdown_type: PRINCIPAL
                        top_level_type: PRODUCTCHARGES
                        depth: 1
                        amount: 49.99
                        currency_code: USD
                    breakdowns:
                    - id: 7100
                      breakdown_path: AMAZONFEES.FBAFEES
                      breakdown_type: FBAFEES
                      top_level_type: AMAZONFEES
                      depth: 1
                      amount: -3.5
                      currency_code: USD
                    breakdown_totals:
                    - type: PRODUCTCHARGES
                      total: 49.99
                      currency_code: USD
                    - type: AMAZONFEES
                      total: -3.5
                      currency_code: USD
                    processed_entities: []
                  current_page: 1
                  last_page: 10
                  per_page: 15
                  total: 150
                  from: 1
                  to: 15
                  first_page_url: https://example.test/api/amazon/unified/transactions?page=1
                  last_page_url: https://example.test/api/amazon/unified/transactions?page=10
                  next_page_url: https://example.test/api/amazon/unified/transactions?page=2
                  prev_page_url: null
                  path: https://example.test/api/amazon/unified/transactions
                  links: []
                  unfiltered_total: 1234
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-amazon-unified-transactions
  /api/amazon/unified/transactions/{id}:
    get:
      tags:
      - Amazon
      summary: Show Transaction
      description: 'Get a single Amazon transaction with full details: integration
        instance, items + their breakdowns, transaction-level breakdowns, breakdown
        totals grouped by top-level type, and any entities created when it was processed
        (SalesCredit, FinancialLine, etc.).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      transaction_id:
                        type: string
                      transaction_type:
                        type: string
                      transaction_status:
                        type: string
                      description:
                        type: string
                      posted_date:
                        type: string
                      total_amount:
                        type: number
                      currency_code:
                        type: string
                      marketplace_id:
                        type: string
                      amazon_order_id:
                        type: string
                      is_mcf_order:
                        type: boolean
                      settlement_id:
                        type: string
                      financial_event_group_id:
                        type: string
                      shipment_id:
                        type: string
                        nullable: true
                      processed_at:
                        type: string
                      linked_sales_order:
                        type: object
                        properties:
                          id:
                            type: integer
                          sales_order_number:
                            type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      json_object:
                        type: object
                        properties:
                          some:
                            type: string
                      integration_instance:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      items:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            item_index:
                              type: integer
                            description:
                              type: string
                            total_amount:
                              type: number
                            currency_code:
                              type: string
                            sku:
                              type: string
                            asin:
                              type: string
                            quantity:
                              type: integer
                            breakdowns:
                              type: array
                              items:
                                type: object
                                properties:
                                  id:
                                    type: integer
                                  breakdown_path:
                                    type: string
                                  breakdown_type:
                                    type: string
                                  top_level_type:
                                    type: string
                                  depth:
                                    type: integer
                                  amount:
                                    type: number
                                  currency_code:
                                    type: string
                      breakdowns:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            breakdown_path:
                              type: string
                            breakdown_type:
                              type: string
                            top_level_type:
                              type: string
                            depth:
                              type: integer
                            amount:
                              type: number
                            currency_code:
                              type: string
                      breakdown_totals:
                        type: array
                        items:
                          type: object
                          properties:
                            type:
                              type: string
                            total:
                              type: number
                            currency_code:
                              type: string
                      processed_entities:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            entity_type:
                              type: string
                            entity_id:
                              type: integer
                            created_at:
                              type: string
                            entity:
                              type: object
                              properties:
                                sales_credit_number:
                                  type: string
                                credit_status:
                                  type: string
                                total_credit:
                                  type: number
                                credit_date:
                                  type: string
                example:
                  data:
                    id: 1234
                    transaction_id: abc-123-def-456
                    transaction_type: Shipment
                    transaction_status: RELEASED
                    description: Order Payment
                    posted_date: '2026-02-15T08:30:00.000000Z'
                    total_amount: 49.99
                    currency_code: USD
                    marketplace_id: ATVPDKIKX0DER
                    amazon_order_id: 701-1234567-1234567
                    is_mcf_order: false
                    settlement_id: '99999'
                    financial_event_group_id: fg-xyz
                    shipment_id: null
                    processed_at: '2026-02-16T12:00:00.000000Z'
                    linked_sales_order:
                      id: 5678
                      sales_order_number: SO-1001
                    created_at: '2026-02-15T09:00:00.000000Z'
                    updated_at: '2026-02-16T12:00:00.000000Z'
                    json_object:
                      some: raw amazon api fields
                    integration_instance:
                      id: 1
                      name: Amazon US
                    items:
                    - id: 9001
                      item_index: 0
                      description: Widget SKU-001
                      total_amount: 49.99
                      currency_code: USD
                      sku: SKU-001
                      asin: B0ABCDEFGH
                      quantity: 1
                      breakdowns:
                      - id: 7001
                        breakdown_path: PRODUCTCHARGES.PRINCIPAL
                        breakdown_type: PRINCIPAL
                        top_level_type: PRODUCTCHARGES
                        depth: 1
                        amount: 49.99
                        currency_code: USD
                    breakdowns:
                    - id: 7100
                      breakdown_path: AMAZONFEES.FBAFEES
                      breakdown_type: FBAFEES
                      top_level_type: AMAZONFEES
                      depth: 1
                      amount: -3.5
                      currency_code: USD
                    breakdown_totals:
                    - type: PRODUCTCHARGES
                      total: 49.99
                      currency_code: USD
                    - type: AMAZONFEES
                      total: -3.5
                      currency_code: USD
                    processed_entities:
                    - id: 4400
                      entity_type: App\Models\SalesCredit
                      entity_id: 222
                      created_at: '2026-02-16T12:00:00.000000Z'
                      entity:
                        sales_credit_number: SC-001
                        credit_status: approved
                        total_credit: 49.99
                        credit_date: '2026-02-16'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-unified-transactions-id
  /api/amazon/unified/transactions/statistics:
    get:
      tags:
      - Amazon
      summary: Statistics (grouped breakdowns)
      description: 'Returns breakdown statistics grouped into business categories
        (sales, fees, refunds, other, net) — amounts per currency — plus available
        filter values for dropdowns. Excludes superseded transactions to prevent double-counting.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      sales:
                        type: object
                        properties:
                          PRODUCTCHARGES:
                            type: object
                            properties:
                              amount:
                                type: number
                              count:
                                type: integer
                          SALES:
                            type: object
                            properties:
                              amount:
                                type: integer
                              count:
                                type: integer
                      fees:
                        type: object
                        properties:
                          AMAZONFEES:
                            type: object
                            properties:
                              amount:
                                type: number
                              count:
                                type: integer
                          DIGITALSERVICESFEE:
                            type: object
                            properties:
                              amount:
                                type: integer
                              count:
                                type: integer
                      refunds:
                        type: object
                        properties:
                          REFUNDEDSALES:
                            type: object
                            properties:
                              amount:
                                type: integer
                              count:
                                type: integer
                          PROMOREBATES:
                            type: object
                            properties:
                              amount:
                                type: integer
                              count:
                                type: integer
                      other:
                        type: object
                        properties:
                          ADJUSTMENT:
                            type: object
                            properties:
                              amount:
                                type: integer
                              count:
                                type: integer
                      net:
                        type: object
                        properties:
                          USD:
                            type: number
                      available_filters:
                        type: object
                        properties:
                          transaction_types:
                            type: array
                            items:
                              type: string
                          transaction_statuses:
                            type: array
                            items:
                              type: string
                          integration_instances:
                            type: array
                            items:
                              type: object
                              properties:
                                id:
                                  type: integer
                                name:
                                  type: string
                example:
                  data:
                    sales:
                      PRODUCTCHARGES:
                        amount: 12345.67
                        count: 320
                      SALES:
                        amount: 2200
                        count: 18
                    fees:
                      AMAZONFEES:
                        amount: -1500.5
                        count: 320
                      DIGITALSERVICESFEE:
                        amount: -75
                        count: 32
                    refunds:
                      REFUNDEDSALES:
                        amount: -250
                        count: 5
                      PROMOREBATES:
                        amount: -30
                        count: 2
                    other:
                      ADJUSTMENT:
                        amount: 10
                        count: 1
                    net:
                      USD: 10700.17
                    available_filters:
                      transaction_types:
                      - Shipment
                      - Refund
                      - Service Fee
                      transaction_statuses:
                      - DEFERRED
                      - DEFERRED_RELEASED
                      - RELEASED
                      integration_instances:
                      - id: 1
                        name: Amazon US
                      - id: 2
                        name: Amazon CA
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-amazon-unified-transactions-statistics
  /api/amazon/unified/transactions/sync:
    post:
      tags:
      - Amazon
      summary: Sync Transactions (background job)
      description: 'Dispatch a background job for each active Amazon integration instance
        (or only those specified via integration_instance_ids, comma-separated). Returns
        the count of dispatched jobs.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                integration_instance_ids:
                  type: string
              example:
                integration_instance_ids: 1,2
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      message:
                        type: string
                      instances_count:
                        type: integer
                example:
                  data:
                    message: Sync jobs dispatched for 2 integration instance(s)
                    instances_count: 2
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: object
                    properties:
                      integration_instances:
                        type: array
                        items:
                          type: string
                example:
                  errors:
                    integration_instances:
                    - No Amazon integration instances found
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-amazon-unified-transactions-sync
  /api/amazon/unified/transactions/{transaction}/process:
    post:
      tags:
      - Amazon
      summary: Process Transaction
      description: 'Process a single transaction — creates the appropriate financial
        entities (SalesCredit, FinancialLine, etc.) and triggers a financials recalculation
        for affected sales order lines. Returns 422 with an error when the transaction
        is invalid or has no linked sales order.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties: {}
              example: {}
      parameters:
      - name: transaction
        in: path
        schema:
          type: integer
        required: true
        description: AmazonTransaction ID
        example: '1234'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      transaction_id:
                        type: string
                      transaction_type:
                        type: string
                      transaction_status:
                        type: string
                      processed_at:
                        type: string
                      linked_sales_order:
                        type: object
                        properties:
                          id:
                            type: integer
                          sales_order_number:
                            type: string
                      processed_entities:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            entity_type:
                              type: string
                            entity_id:
                              type: integer
                            created_at:
                              type: string
                            entity:
                              type: object
                              properties:
                                sales_credit_number:
                                  type: string
                                credit_status:
                                  type: string
                                total_credit:
                                  type: number
                                credit_date:
                                  type: string
                example:
                  data:
                    id: 1234
                    transaction_id: abc-123-def-456
                    transaction_type: Shipment
                    transaction_status: RELEASED
                    processed_at: '2026-05-30T10:00:00.000000Z'
                    linked_sales_order:
                      id: 5678
                      sales_order_number: SO-1001
                    processed_entities:
                    - id: 4400
                      entity_type: App\Models\SalesCredit
                      entity_id: 222
                      created_at: '2026-05-30T10:00:00.000000Z'
                      entity:
                        sales_credit_number: SC-001
                        credit_status: approved
                        total_credit: 49.99
                        credit_date: '2026-05-30'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: object
                    properties:
                      transaction:
                        type: array
                        items:
                          type: string
                example:
                  errors:
                    transaction:
                    - No linked sales order found for this transaction
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-amazon-unified-transactions-transaction-process
  /api/amazon/unified/transactions/{transaction}/unprocess:
    post:
      tags:
      - Amazon
      summary: Unprocess Transaction
      description: 'Reverse processing for a single transaction — deletes/reverses
        all entities created when the transaction was originally processed. Returns
        the refreshed transaction resource.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties: {}
              example: {}
      parameters:
      - name: transaction
        in: path
        schema:
          type: integer
        required: true
        description: AmazonTransaction ID
        example: '1234'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      transaction_id:
                        type: string
                      processed_at:
                        type: string
                        nullable: true
                      processed_entities:
                        type: array
                example:
                  data:
                    id: 1234
                    transaction_id: abc-123-def-456
                    processed_at: null
                    processed_entities: []
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-amazon-unified-transactions-transaction-unprocess
  /api/amazon/unified/transactions/bulk-process:
    post:
      tags:
      - Amazon
      summary: Bulk Process Transactions
      description: 'Process multiple transactions in one request. Required: transaction_ids
        (array, min 1, each must exist in amazon_transactions.id). Triggers a financials
        recalculation after completion.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                transaction_ids:
                  type: array
                  items:
                    type: integer
              example:
                transaction_ids:
                - 1234
                - 1235
                - 1236
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      processed_count:
                        type: integer
                      failed_count:
                        type: integer
                      failures:
                        type: array
                        items:
                          type: object
                          properties:
                            transaction_id:
                              type: integer
                            reason:
                              type: string
                example:
                  data:
                    processed_count: 2
                    failed_count: 1
                    failures:
                    - transaction_id: 1236
                      reason: No linked sales order found
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-amazon-unified-transactions-bulk-process
  /api/amazon/unified/transactions/bulk-unprocess:
    post:
      tags:
      - Amazon
      summary: Bulk Unprocess Transactions
      description: 'Reverse processing for multiple transactions. Required: transaction_ids
        (array, min 1, each must exist).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                transaction_ids:
                  type: array
                  items:
                    type: integer
              example:
                transaction_ids:
                - 1234
                - 1235
                - 1236
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      unprocessed_count:
                        type: integer
                      failed_count:
                        type: integer
                      failures:
                        type: array
                example:
                  data:
                    unprocessed_count: 3
                    failed_count: 0
                    failures: []
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-amazon-unified-transactions-bulk-unprocess
  /api/amazon/unified/transactions/process-all:
    post:
      tags:
      - Amazon
      summary: Process All (background job)
      description: 'Dispatch a background job — processes all unprocessed transactions
        matching the optional filters. Returns the tracked job log ID so the frontend
        can poll progress via /process-all/status or the tracked job log endpoints.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties: {}
              example: {}
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      message:
                        type: string
                      job_id:
                        type: integer
                example:
                  data:
                    message: Process all job has been started
                    job_id: 8842
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-amazon-unified-transactions-process-all
  /api/amazon/unified/transactions/process-all/status:
    get:
      tags:
      - Amazon
      summary: Process All Status
      description: 'Returns the most recent a background job status for the authenticated
        user — pulled from TrackedJobLog. If a Laravel Bus batch is attached, includes
        per-batch progress (total/pending/processed/failed jobs, finished/cancelled
        flags, progress percentage).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 OK (running)
                  value:
                    data:
                      job_id: 8842
                      status: processing
                      total_items: 1500
                      processed_items: 425
                      progress_percentage: 28.33
                      results:
                        batch_id: 01HX7Z2YQH...
                      messages:
                      - Dispatching batch of 1500 transactions
                      created_at: '2026-05-30T10:15:00.000000Z'
                      completed_at: null
                      batch_progress:
                        total_jobs: 1500
                        pending_jobs: 1075
                        processed_jobs: 425
                        failed_jobs: 2
                        finished: false
                        cancelled: false
                        progress_percentage: 28.33
                example-1:
                  summary: 200 OK (no job)
                  value:
                    data:
                      status: null
                      message: No process all job found
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-amazon-unified-transactions-process-all-status
  /api/amazon/unified/transactions/export:
    get:
      tags:
      - Amazon
      summary: Export Transactions (background job)
      description: 'Dispatch a background job — generates an xlsx/csv export honouring
        the current filters (or a selected ID list). Returns a tracked_job_log_id;
        once complete, download the result via /export/download?file=...


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                example:
                  data:
                    tracked_job_log_id: 9921
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-amazon-unified-transactions-export
  /api/amazon/unified/transactions/export/download:
    get:
      tags:
      - Amazon
      summary: Download Export File
      description: 'Download a completed export file from the model-exports disk.
        Returns the binary file with Content-Type set based on extension (text/csv
        for .csv, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
        for .xlsx). 404 if file is missing.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: file
        in: query
        schema:
          type: string
        description: Required — filename produced by the export job (basename only;
          path components stripped)
        example: amazon-transactions-2026-05-30-101500.xlsx
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
            Content-Disposition:
              schema:
                type: string
                example: attachment; filename=amazon-transactions-2026-05-30-101500.xlsx
          content:
            text/plain:
              schema:
                type: string
                example: <binary xlsx file contents>
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Not Found
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-amazon-unified-transactions-export-download
  /api/amazon/unified/shipments:
    get:
      tags:
      - Amazon
      summary: List FBA Shipments Detail (paginated, across instances)
      description: 'Paginated list of FBA shipments-detail rows aggregated across
        Amazon integration instances. Each row represents one shipped item line from
        the GET_AMAZON_FULFILLED_SHIPMENTS_DATA_GENERAL report. Filtering uses Spatie
        QueryBuilder with AdvancedSearchFilter (search across order/shipment/product/tracking/recipient
        fields) plus ~25 text filters, ~9 numeric filters, and ~8 datetime filters.
        Response includes linked_sales_order (bulk-resolved via amazon_order_id →
        amazon_orders → sales_orders join) and amazon_product (bulk-resolved by integration_instance_id
        + seller_sku). Default sort: -shipment_date.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        integration_instance_name:
                          type: string
                        amazon_order_id:
                          type: string
                        merchant_order_id:
                          type: string
                          nullable: true
                        shipment_id:
                          type: string
                        shipment_item_id:
                          type: string
                        amazon_order_item_id:
                          type: string
                        merchant_order_item_id:
                          type: string
                          nullable: true
                        purchase_date:
                          type: string
                        payments_date:
                          type: string
                        shipment_date:
                          type: string
                        reporting_date:
                          type: string
                        estimated_arrival_date:
                          type: string
                        event_datetime:
                          type: string
                        sku:
                          type: string
                        product_name:
                          type: string
                        quantity_shipped:
                          type: integer
                        currency:
                          type: string
                        item_price:
                          type: number
                        item_tax:
                          type: number
                        shipping_price:
                          type: number
                        shipping_tax:
                          type: integer
                        gift_wrap_price:
                          type: integer
                        gift_wrap_tax:
                          type: integer
                        item_promotion_discount:
                          type: integer
                        ship_promotion_discount:
                          type: integer
                        recipient_name:
                          type: string
                          nullable: true
                        ship_address_1:
                          type: string
                          nullable: true
                        ship_address_2:
                          type: string
                          nullable: true
                        ship_address_3:
                          type: string
                          nullable: true
                        ship_city:
                          type: string
                        ship_state:
                          type: string
                        ship_postal_code:
                          type: string
                        ship_country:
                          type: string
                        ship_phone_number:
                          type: string
                          nullable: true
                        bill_address_1:
                          type: string
                          nullable: true
                        bill_address_2:
                          type: string
                          nullable: true
                        bill_address_3:
                          type: string
                          nullable: true
                        bill_city:
                          type: string
                          nullable: true
                        bill_state:
                          type: string
                          nullable: true
                        bill_postal_code:
                          type: string
                          nullable: true
                        bill_country:
                          type: string
                          nullable: true
                        buyer_name:
                          type: string
                          nullable: true
                        buyer_phone_number:
                          type: string
                          nullable: true
                        buyer_email:
                          type: string
                          nullable: true
                        fulfillment_channel:
                          type: string
                        sales_channel:
                          type: string
                        ship_service_level:
                          type: string
                        carrier:
                          type: string
                        tracking_number:
                          type: string
                        fulfillment_center_id:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                        linked_sales_order:
                          type: object
                          properties:
                            id:
                              type: integer
                            sales_order_number:
                              type: string
                            order_status:
                              type: string
                        amazon_product:
                          type: object
                          properties:
                            id:
                              type: integer
                  current_page:
                    type: integer
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                  next_page_url:
                    type: string
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 44453
                    integration_instance_id: 1
                    integration_instance_name: BCK - North America
                    amazon_order_id: 112-7606445-9266668
                    merchant_order_id: null
                    shipment_id: P4p8yWlvp
                    shipment_item_id: DPrGkyYSzz01R
                    amazon_order_item_id: '158578633674281'
                    merchant_order_item_id: null
                    purchase_date: '2026-04-25T20:31:00.000000Z'
                    payments_date: '2026-04-25T22:42:00.000000Z'
                    shipment_date: '2026-04-25T22:49:00.000000Z'
                    reporting_date: '2026-04-26T00:00:00.000000Z'
                    estimated_arrival_date: '2026-04-26T06:00:00.000000Z'
                    event_datetime: '2026-04-25T22:49:00.000000Z'
                    sku: ZE-LN56-F7UA
                    product_name: BIGCAT ROAR Predator Hunter — Patented Handmade
                      Damascus Steel Fixed Blade Hunting Knife
                    quantity_shipped: 1
                    currency: USD
                    item_price: 49.99
                    item_tax: 3.5
                    shipping_price: 1.49
                    shipping_tax: 0
                    gift_wrap_price: 0
                    gift_wrap_tax: 0
                    item_promotion_discount: 0
                    ship_promotion_discount: 0
                    recipient_name: null
                    ship_address_1: null
                    ship_address_2: null
                    ship_address_3: null
                    ship_city: COLUMBIA CITY
                    ship_state: IN
                    ship_postal_code: 46725-1507
                    ship_country: US
                    ship_phone_number: null
                    bill_address_1: null
                    bill_address_2: null
                    bill_address_3: null
                    bill_city: null
                    bill_state: null
                    bill_postal_code: null
                    bill_country: null
                    buyer_name: null
                    buyer_phone_number: null
                    buyer_email: null
                    fulfillment_channel: Amazon
                    sales_channel: amazon.com
                    ship_service_level: Expedited
                    carrier: AMZN_US
                    tracking_number: TBA338512244849
                    fulfillment_center_id: FWA6
                    created_at: '2026-04-26T00:05:12.000000Z'
                    updated_at: '2026-04-26T00:05:12.000000Z'
                    linked_sales_order:
                      id: 5678
                      sales_order_number: SO-1001
                      order_status: shipped
                    amazon_product:
                      id: 9012
                  current_page: 1
                  first_page_url: '{{protocol}}{{domain}}/api/amazon/unified/shipments?page=1'
                  from: 1
                  last_page: 30
                  last_page_url: '{{protocol}}{{domain}}/api/amazon/unified/shipments?page=30'
                  links: []
                  next_page_url: '{{protocol}}{{domain}}/api/amazon/unified/shipments?page=2'
                  path: '{{protocol}}{{domain}}/api/amazon/unified/shipments'
                  per_page: 15
                  prev_page_url: null
                  to: 15
                  total: 450
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-amazon-unified-shipments
  /api/amazon/unified/shipments/kpi-stats:
    get:
      tags:
      - Amazon
      summary: FBA Shipments Detail — KPI Stats
      description: 'Cross-instance KPI summary for the FBA Shipments Detail listing.
        Returns total_shipments (row count), total_units (sum of quantity_shipped),
        total_revenue (sum of item_price), and unique_orders (distinct amazon_order_id
        count). Used to drive the dashboard-card row above the listing.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      total_shipments:
                        type: integer
                      total_units:
                        type: integer
                      total_revenue:
                        type: number
                      unique_orders:
                        type: integer
                example:
                  data:
                    total_shipments: 12450
                    total_units: 18792
                    total_revenue: 619437.21
                    unique_orders: 9874
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-amazon-unified-shipments-kpi-stats
  /api/amazon/unified/shipments/{shipment}:
    get:
      tags:
      - Amazon
      summary: Show FBA Shipment Detail Row
      description: 'Single FBA shipment-detail row by ID with eager-loaded integrationInstance
        and bulk-resolved cross-links: linked_sales_order (via amazon_order_id) and
        amazon_product (via integration_instance_id + seller SKU). Use this to power
        the detail page.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: shipment
        in: path
        schema:
          type: integer
        required: true
        description: Numeric AmazonFbaReportShipment ID
        example: '44453'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      integration_instance_name:
                        type: string
                      amazon_order_id:
                        type: string
                      merchant_order_id:
                        type: string
                        nullable: true
                      shipment_id:
                        type: string
                      shipment_item_id:
                        type: string
                      amazon_order_item_id:
                        type: string
                      merchant_order_item_id:
                        type: string
                        nullable: true
                      purchase_date:
                        type: string
                      payments_date:
                        type: string
                      shipment_date:
                        type: string
                      reporting_date:
                        type: string
                      estimated_arrival_date:
                        type: string
                      event_datetime:
                        type: string
                      sku:
                        type: string
                      product_name:
                        type: string
                      quantity_shipped:
                        type: integer
                      currency:
                        type: string
                      item_price:
                        type: number
                      item_tax:
                        type: number
                      shipping_price:
                        type: number
                      shipping_tax:
                        type: integer
                      gift_wrap_price:
                        type: integer
                      gift_wrap_tax:
                        type: integer
                      item_promotion_discount:
                        type: integer
                      ship_promotion_discount:
                        type: integer
                      recipient_name:
                        type: string
                        nullable: true
                      ship_address_1:
                        type: string
                        nullable: true
                      ship_address_2:
                        type: string
                        nullable: true
                      ship_address_3:
                        type: string
                        nullable: true
                      ship_city:
                        type: string
                      ship_state:
                        type: string
                      ship_postal_code:
                        type: string
                      ship_country:
                        type: string
                      ship_phone_number:
                        type: string
                        nullable: true
                      bill_address_1:
                        type: string
                        nullable: true
                      bill_address_2:
                        type: string
                        nullable: true
                      bill_address_3:
                        type: string
                        nullable: true
                      bill_city:
                        type: string
                        nullable: true
                      bill_state:
                        type: string
                        nullable: true
                      bill_postal_code:
                        type: string
                        nullable: true
                      bill_country:
                        type: string
                        nullable: true
                      buyer_name:
                        type: string
                        nullable: true
                      buyer_phone_number:
                        type: string
                        nullable: true
                      buyer_email:
                        type: string
                        nullable: true
                      fulfillment_channel:
                        type: string
                      sales_channel:
                        type: string
                      ship_service_level:
                        type: string
                      carrier:
                        type: string
                      tracking_number:
                        type: string
                      fulfillment_center_id:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      linked_sales_order:
                        type: object
                        properties:
                          id:
                            type: integer
                          sales_order_number:
                            type: string
                          order_status:
                            type: string
                      amazon_product:
                        type: object
                        properties:
                          id:
                            type: integer
                example:
                  data:
                    id: 44453
                    integration_instance_id: 1
                    integration_instance_name: BCK - North America
                    amazon_order_id: 112-7606445-9266668
                    merchant_order_id: null
                    shipment_id: P4p8yWlvp
                    shipment_item_id: DPrGkyYSzz01R
                    amazon_order_item_id: '158578633674281'
                    merchant_order_item_id: null
                    purchase_date: '2026-04-25T20:31:00.000000Z'
                    payments_date: '2026-04-25T22:42:00.000000Z'
                    shipment_date: '2026-04-25T22:49:00.000000Z'
                    reporting_date: '2026-04-26T00:00:00.000000Z'
                    estimated_arrival_date: '2026-04-26T06:00:00.000000Z'
                    event_datetime: '2026-04-25T22:49:00.000000Z'
                    sku: ZE-LN56-F7UA
                    product_name: BIGCAT ROAR Predator Hunter Knife
                    quantity_shipped: 1
                    currency: USD
                    item_price: 49.99
                    item_tax: 3.5
                    shipping_price: 1.49
                    shipping_tax: 0
                    gift_wrap_price: 0
                    gift_wrap_tax: 0
                    item_promotion_discount: 0
                    ship_promotion_discount: 0
                    recipient_name: null
                    ship_address_1: null
                    ship_address_2: null
                    ship_address_3: null
                    ship_city: COLUMBIA CITY
                    ship_state: IN
                    ship_postal_code: 46725-1507
                    ship_country: US
                    ship_phone_number: null
                    bill_address_1: null
                    bill_address_2: null
                    bill_address_3: null
                    bill_city: null
                    bill_state: null
                    bill_postal_code: null
                    bill_country: null
                    buyer_name: null
                    buyer_phone_number: null
                    buyer_email: null
                    fulfillment_channel: Amazon
                    sales_channel: amazon.com
                    ship_service_level: Expedited
                    carrier: AMZN_US
                    tracking_number: TBA338512244849
                    fulfillment_center_id: FWA6
                    created_at: '2026-04-26T00:05:12.000000Z'
                    updated_at: '2026-04-26T00:05:12.000000Z'
                    linked_sales_order:
                      id: 5678
                      sales_order_number: SO-1001
                      order_status: shipped
                    amazon_product:
                      id: 9012
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No query results for model [Modules\Amazon\Entities\AmazonFbaReportShipment]
                    99999999
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-amazon-unified-shipments-shipment
  /api/amazon/unified/fba-inventory:
    get:
      tags:
      - Amazon
      summary: List FBA Inventory
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        example: '1'
        description: Page number (default 1).
      - name: per_page
        in: query
        schema:
          type: integer
        example: '10'
        description: Results per page (default 10).
      - name: search
        in: query
        schema:
          type: string
        description: Free-text search across the resource’s searchable fields.
      - name: integration_instance_ids
        in: query
        schema:
          type: string
        description: Comma-separated integration instance IDs to scope the query.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      description: 'List FBA Inventory


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      operationId: get-api-amazon-unified-fba-inventory
  /api/amazon/unified/fba-inventory/{inventory}:
    get:
      tags:
      - Amazon
      summary: Get FBA Inventory Record
      description: 'Returns a single FBA-managed inventory report row (from Amazon''s
        FBA inventory report) with cross-links resolved:

        - sku: {value, amazon_product_id} — the seller SKU and the matching Amazon
        listing ID when one resolves

        - fnsku_product: {id} of the matching FNSKU product record for the same integration
        instance, or null when the FNSKU is not mapped


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Quantity fields cover the fulfillment network position: afn_warehouse_quantity,
        afn_fulfillable_quantity, afn_unsellable_quantity, afn_reserved_quantity,
        afn_total_quantity, the inbound pipeline (afn_inbound_working_quantity, afn_inbound_shipped_quantity,
        afn_inbound_receiving_quantity), afn_researching_quantity and future-supply
        fields, plus merchant-fulfilled counterparts (mfn_listing_exists, mfn_fulfillable_quantity).
        Also includes country_code, condition, your_price and per_unit_volume.


        Optional query parameters included / excluded (URL-encoded JSON arrays of
        column names) limit which columns are returned.'
      parameters:
      - name: inventory
        in: path
        schema:
          type: string
        required: true
        description: FBA inventory row ID
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_name:
                        type: string
                      country_code:
                        type: string
                      sku:
                        type: object
                        properties:
                          value:
                            type: string
                          amazon_product_id:
                            type: integer
                      fnsku:
                        type: string
                      product_name:
                        type: string
                      condition:
                        type: string
                      your_price:
                        type: string
                      mfn_listing_exists:
                        type: string
                      mfn_fulfillable_quantity:
                        type: integer
                      afn_listing_exists:
                        type: string
                      afn_warehouse_quantity:
                        type: string
                      afn_fulfillable_quantity:
                        type: integer
                      afn_unsellable_quantity:
                        type: integer
                      afn_reserved_quantity:
                        type: integer
                      afn_total_quantity:
                        type: integer
                      per_unit_volume:
                        type: number
                      afn_inbound_working_quantity:
                        type: integer
                      afn_inbound_shipped_quantity:
                        type: integer
                      afn_inbound_receiving_quantity:
                        type: integer
                      afn_researching_quantity:
                        type: integer
                      afn_reserved_future_supply:
                        type: integer
                      afn_future_supply_buyable:
                        type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      fnsku_product:
                        type: object
                        properties:
                          id:
                            type: integer
                  status:
                    type: string
                example:
                  data:
                    id: 90211
                    integration_instance_name: Amazon US
                    country_code: US
                    sku:
                      value: WIDGET-BLUE-M
                      amazon_product_id: 5512
                    fnsku: X002ABCDE1
                    product_name: Blue Widget - Medium
                    condition: New
                    your_price: '24.99'
                    mfn_listing_exists: 'No'
                    mfn_fulfillable_quantity: 0
                    afn_listing_exists: 'Yes'
                    afn_warehouse_quantity: '380'
                    afn_fulfillable_quantity: 352
                    afn_unsellable_quantity: 4
                    afn_reserved_quantity: 24
                    afn_total_quantity: 580
                    per_unit_volume: 0.42
                    afn_inbound_working_quantity: 100
                    afn_inbound_shipped_quantity: 80
                    afn_inbound_receiving_quantity: 20
                    afn_researching_quantity: 2
                    afn_reserved_future_supply: 0
                    afn_future_supply_buyable: 0
                    created_at: '2026-07-05T06:00:14.000000Z'
                    updated_at: '2026-07-06T06:00:22.000000Z'
                    fnsku_product:
                      id: 1592
                  status: success
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: object
                    properties:
                      Modules\Amazon\Entities\AmazonFbaReportInventory:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: array
                  status:
                    type: string
                  message:
                    type: string
                example:
                  errors:
                    Modules\Amazon\Entities\AmazonFbaReportInventory:
                    - message: No query results for model [Modules\Amazon\Entities\AmazonFbaReportInventory]
                        99999
                      code: NotFound
                      data: []
                  status: failure
                  message: No query results for model [Modules\Amazon\Entities\AmazonFbaReportInventory]
                    99999
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-amazon-unified-fba-inventory-inventory
  /api/amazon/unified/new-inbound-shipments:
    get:
      tags:
      - Amazon
      summary: List Shipments
      description: 'Returns a paginated `LengthAwarePaginator` of new (v2) FBA inbound
        shipments across one or more Amazon integration instances. Each item is transformed
        by Amazon new FBA inbound shipment object and includes identifier fields (`shipmentId`,
        `shipmentConfirmationId`, `amazonReferenceId`, `name`, `sourceName`), status
        info (`status`, `pending_status`, `errorLog`, `is_archived`), destination
        block (`destinationCountry`, `destinationWarehouse`, `destinationType`, `destination`),
        transportation IDs, the `sku_link` block (linked Purchase Order or Warehouse
        Transfer), `actual_source` (resolved supplier/from-warehouse derived from
        the SKU link), and `ship_from_mapping` (the mapping that *would* be applied
        today — used to surface divergence client-side). When the relevant relations
        are eager-loaded the resource also returns `pending_inbound`, `receipts`,
        and `items`. Defaults to excluding archived shipments unless `filter[archived]`
        is provided.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        integration_instance_name:
                          type: string
                        shipmentId:
                          type: string
                        shipmentConfirmationId:
                          type: string
                        amazonReferenceId:
                          type: string
                        name:
                          type: string
                        sourceName:
                          type: string
                        status:
                          type: string
                        pending_status:
                          type: string
                          nullable: true
                        errorLog:
                          type: string
                          nullable: true
                        is_before_initial_count:
                          type: boolean
                        is_archived:
                          type: boolean
                        archived_at:
                          type: string
                          nullable: true
                        destinationCountry:
                          type: string
                        destinationWarehouse:
                          type: string
                        destinationType:
                          type: string
                        destinationAddress:
                          type: object
                          properties:
                            name:
                              type: string
                            addressLine1:
                              type: string
                            city:
                              type: string
                            stateOrProvinceCode:
                              type: string
                            postalCode:
                              type: string
                            countryCode:
                              type: string
                        destination:
                          type: object
                          properties:
                            warehouseId:
                              type: string
                            address:
                              type: object
                              properties:
                                name:
                                  type: string
                                addressLine1:
                                  type: string
                                city:
                                  type: string
                                stateOrProvinceCode:
                                  type: string
                                postalCode:
                                  type: string
                                countryCode:
                                  type: string
                        selectedTransportationOptionId:
                          type: string
                        placementOptionId:
                          type: string
                        cached_shipment_date:
                          type: string
                        sku_link:
                          type: object
                          properties:
                            id:
                              type: integer
                            type:
                              type: string
                            name:
                              type: string
                            displayType:
                              type: string
                        actual_source:
                          type: object
                          properties:
                            name:
                              type: string
                            type:
                              type: string
                            link_type:
                              type: string
                            link_id:
                              type: integer
                            route:
                              type: string
                        ship_from_mapping:
                          type: object
                          properties:
                            name:
                              type: string
                            mapping_id:
                              type: integer
                            target:
                              type: object
                              properties:
                                name:
                                  type: string
                                type:
                                  type: string
                                link_type:
                                  type: string
                                link_id:
                                  type: integer
                                route:
                                  type: string
                        pending_inbound:
                          type: object
                          properties:
                            id:
                              type: integer
                            status:
                              type: string
                            shipped_at:
                              type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                  first_page_url:
                    type: string
                  last_page_url:
                    type: string
                  next_page_url:
                    type: string
                  prev_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  links:
                    type: array
                    items:
                      type: object
                      properties:
                        url:
                          type: string
                          nullable: true
                        label:
                          type: string
                        active:
                          type: boolean
                example:
                  data:
                  - id: 1024
                    integration_instance_id: 1
                    integration_instance_name: US Marketplace
                    shipmentId: FBA15ABCDEFG
                    shipmentConfirmationId: FBA15ABCDEFG
                    amazonReferenceId: AMZN-REF-123
                    name: FBA (07/14/2025 18:22) - 1
                    sourceName: SKU Warehouse - California
                    status: SHIPPED
                    pending_status: null
                    errorLog: null
                    is_before_initial_count: false
                    is_archived: false
                    archived_at: null
                    destinationCountry: US
                    destinationWarehouse: ONT8
                    destinationType: FC
                    destinationAddress:
                      name: Amazon.com Services, Inc.
                      addressLine1: 24300 Nandina Ave
                      city: Moreno Valley
                      stateOrProvinceCode: CA
                      postalCode: '92551'
                      countryCode: US
                    destination:
                      warehouseId: ONT8
                      address:
                        name: Amazon.com Services, Inc.
                        addressLine1: 24300 Nandina Ave
                        city: Moreno Valley
                        stateOrProvinceCode: CA
                        postalCode: '92551'
                        countryCode: US
                    selectedTransportationOptionId: toid_8a1b9d2e
                    placementOptionId: pid_3c0a771e
                    cached_shipment_date: '2025-07-14T18:22:00.000000Z'
                    sku_link:
                      id: 442
                      type: App\Models\PurchaseOrder
                      name: PO-2025-0442
                      displayType: Purchase Order
                    actual_source:
                      name: Acme Supplies Co.
                      type: Supplier
                      link_type: App\Models\Supplier
                      link_id: 18
                      route: /crm/suppliers/18
                    ship_from_mapping:
                      name: SKU Warehouse - California
                      mapping_id: 7
                      target:
                        name: SKU Warehouse - California
                        type: Warehouse
                        link_type: App\Models\Warehouse
                        link_id: 3
                        route: /crm/warehouses/3
                    pending_inbound:
                      id: 91
                      status: shipped
                      shipped_at: '2025-07-14T18:22:00.000000Z'
                    created_at: '2025-07-14T18:22:00.000000Z'
                    updated_at: '2025-07-15T02:11:00.000000Z'
                  current_page: 1
                  last_page: 12
                  per_page: 10
                  total: 117
                  from: 1
                  to: 10
                  first_page_url: https://example.test/api/amazon/unified/new-inbound-shipments?page=1
                  last_page_url: https://example.test/api/amazon/unified/new-inbound-shipments?page=12
                  next_page_url: https://example.test/api/amazon/unified/new-inbound-shipments?page=2
                  prev_page_url: null
                  path: https://example.test/api/amazon/unified/new-inbound-shipments
                  links:
                  - url: null
                    label: '&laquo; Previous'
                    active: false
                  - url: https://example.test/api/amazon/unified/new-inbound-shipments?page=1
                    label: '1'
                    active: true
                  - url: https://example.test/api/amazon/unified/new-inbound-shipments?page=2
                    label: Next &raquo;
                    active: false
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-amazon-unified-new-inbound-shipments
  /api/amazon/unified/new-inbound-shipments/export:
    get:
      tags:
      - Amazon
      summary: Export Shipment Items (CSV)
      description: 'Streams a CSV download of new inbound shipment items (line-level
        rows) across the supplied integration instances. Each row represents one line
        item with its parent shipment info repeated. Columns: `sr_no`, `confirmation_id`,
        `shipment_id`, `shipment_name`, `status`, `source_name`, `destination_country`,
        `destination_warehouse`, `integration`, `msku`, `fnsku`, `asin`, `quantity_sent`,
        `quantity_received`, `shipment_created_at`.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        When the resulting item set is empty the endpoint returns a JSON message instead
        of a file (`You can''t export empty data`).'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: text/csv
            Content-Disposition:
              schema:
                type: string
                example: attachment; filename=new-inbound-shipment-items-2026-05-29-101542.csv
          content:
            text/plain:
              schema:
                type: string
                example: 'sr_no,confirmation_id,shipment_id,shipment_name,status,source_name,destination_country,destination_warehouse,integration,msku,fnsku,asin,quantity_sent,quantity_received,shipment_created_at

                  1,FBA15ABCDEFG,FBA15ABCDEFG,"FBA (07/14/2025 18:22) - 1",SHIPPED,"SKU
                  Warehouse - California",US,ONT8,"US Marketplace",MY-MSKU-001,X001ABC123,B0CXYZ1234,50,50,"2025-07-14
                  18:22:00"

                  2,FBA15ABCDEFG,FBA15ABCDEFG,"FBA (07/14/2025 18:22) - 1",SHIPPED,"SKU
                  Warehouse - California",US,ONT8,"US Marketplace",MY-MSKU-002,X002DEF456,B0CXYZ5678,25,24,"2025-07-14
                  18:22:00"'
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: boolean
                  data:
                    type: string
                    nullable: true
                  message:
                    type: string
                example:
                  status: true
                  data: null
                  message: You can't export empty data
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-amazon-unified-new-inbound-shipments-export
  /api/amazon/unified/new-inbound-shipments/refresh:
    post:
      tags:
      - Amazon
      summary: Refresh All (Sync from Amazon)
      description: 'Dispatches a background job to (re)sync new FBA inbound shipments
        (via their plans) from Amazon for one or more integration instances. Returns
        immediately with a `tracked_job_log_id` that the frontend uses to render progress
        via the tracked job log endpoints.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Body / query params:**

        - `integration_instance_ids` (optional) — comma-separated string or array
        of AmazonIntegrationInstance IDs. When omitted, the job runs for every Amazon
        integration instance.


        The job name is `Sync FBA New Inbound Shipments: <instance name | N Integrations>`
        — frontend watchers should match on that `startsWith`.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                integration_instance_ids:
                  type: string
              example:
                integration_instance_ids: 1,2
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: boolean
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                      integration_instance_count:
                        type: integer
                  message:
                    type: string
                example:
                  status: true
                  data:
                    tracked_job_log_id: 8821
                    integration_instance_count: 2
                  message: Refresh started — track progress in the job tray
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-amazon-unified-new-inbound-shipments-refresh
  /api/amazon/unified/new-inbound-shipments/process-all:
    post:
      tags:
      - Amazon
      summary: Process All (Apply Unprocessed Shipments)
      description: 'Dispatches a background job which links unprocessed new FBA inbound
        shipments to their SKU.io source records (Purchase Orders / Warehouse Transfers
        via ship-from mappings) and processes cancellations across one or more integration
        instances. Returns immediately with a `tracked_job_log_id` for the tracked
        job log endpoints.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Body / query params:**

        - `integration_instance_ids` (optional) — comma-separated string or array
        of AmazonIntegrationInstance IDs. When omitted, the job runs for every Amazon
        integration instance.


        The job name is `Process FBA New Inbound Shipments: <instance name | N Integrations>`
        — frontend watchers should match on that `startsWith`.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                integration_instance_ids:
                  type: string
              example:
                integration_instance_ids: 1,2
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: boolean
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                      integration_instance_count:
                        type: integer
                  message:
                    type: string
                example:
                  status: true
                  data:
                    tracked_job_log_id: 8822
                    integration_instance_count: 2
                  message: Processing started — track progress in the job tray
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-amazon-unified-new-inbound-shipments-process-all
  /api/amazon/unified/new-inbound-shipments/kpi-stats:
    get:
      tags:
      - Amazon
      summary: KPI Stats
      description: 'Returns KPI counts for the New Inbound Shipments page, scoped
        to active (non-archived) shipments only. Counts are computed across the provided
        integration instances (or all instances when none supplied). Response keys:


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        - `awaiting_over_14_days` — shipments in SHIPPED / IN_TRANSIT / DELIVERED
        / CHECKED_IN / RECEIVING status whose `cached_shipment_date` is older than
        14 days.

        - `discrepancies` — shipments in MIXED status.

        - `errored` — shipments whose `errorLog` is set and non-empty.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: boolean
                  data:
                    type: object
                    properties:
                      awaiting_over_14_days:
                        type: integer
                      discrepancies:
                        type: integer
                      errored:
                        type: integer
                  message:
                    type: string
                example:
                  status: true
                  data:
                    awaiting_over_14_days: 12
                    discrepancies: 3
                    errored: 1
                  message: ''
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-amazon-unified-new-inbound-shipments-kpi-stats
  /api/amazon/unified/legacy-inbound-shipments:
    get:
      tags:
      - Amazon
      summary: List Legacy FBA Inbound Shipments
      description: 'Returns a paginated list of legacy `AmazonFbaInboundShipment`
        records aggregated across one or more integration instances. Eager loads `integrationInstance`
        and `skuLink`.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Supports both flat `filter[...]` syntax and grouped advanced filters via the
        `filter_groups` payload (POST-style array). Allowed sorts include id, ShipmentId,
        ShipmentName, ShipFromName, DestinationFulfillmentCenterId, ShipmentStatus,
        LabelPrepType, BoxContentsSource, errorLog, is_before_initial_count, created_at,
        updated_at.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        integration_instance_name:
                          type: string
                        ShipmentId:
                          type: string
                        ShipmentName:
                          type: string
                        ShipFromName:
                          type: string
                        DestinationFulfillmentCenterId:
                          type: string
                        ShipmentStatus:
                          type: string
                        LabelPrepType:
                          type: string
                        BoxContentsSource:
                          type: string
                        errorLog:
                          type: string
                          nullable: true
                        is_before_initial_count:
                          type: boolean
                        sku_link:
                          type: object
                          properties:
                            id:
                              type: integer
                            type:
                              type: string
                            name:
                              type: string
                            displayType:
                              type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  links:
                    type: object
                    properties:
                      first:
                        type: string
                      last:
                        type: string
                      prev:
                        type: string
                        nullable: true
                      next:
                        type: string
                  meta:
                    type: object
                    properties:
                      current_page:
                        type: integer
                      from:
                        type: integer
                      last_page:
                        type: integer
                      path:
                        type: string
                      per_page:
                        type: integer
                      to:
                        type: integer
                      total:
                        type: integer
                example:
                  data:
                  - id: 1024
                    integration_instance_id: 1
                    integration_instance_name: US Marketplace
                    ShipmentId: FBA15ABC123
                    ShipmentName: Replenishment 2026-05
                    ShipFromName: Main Warehouse
                    DestinationFulfillmentCenterId: ONT8
                    ShipmentStatus: SHIPPED
                    LabelPrepType: SELLER_LABEL
                    BoxContentsSource: BOX_CONTENT_PROVIDED
                    errorLog: null
                    is_before_initial_count: false
                    sku_link:
                      id: 4471
                      type: App\Models\WarehouseTransfer
                      name: WT-000123
                      displayType: Warehouse Transfer
                    created_at: '2026-05-10T14:22:31.000000Z'
                    updated_at: '2026-05-22T09:11:08.000000Z'
                  links:
                    first: https://example.test/api/amazon/unified/legacy-inbound-shipments?page=1
                    last: https://example.test/api/amazon/unified/legacy-inbound-shipments?page=12
                    prev: null
                    next: https://example.test/api/amazon/unified/legacy-inbound-shipments?page=2
                  meta:
                    current_page: 1
                    from: 1
                    last_page: 12
                    path: https://example.test/api/amazon/unified/legacy-inbound-shipments
                    per_page: 10
                    to: 10
                    total: 113
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-amazon-unified-legacy-inbound-shipments
  /api/amazon/unified/legacy-inbound-shipments/export:
    get:
      tags:
      - Amazon
      summary: Export Shipment Items (CSV)
      description: 'Exports legacy inbound shipment items (line-level) across the
        specified integration instances as a CSV file download. One row per `AmazonFbaInboundShipmentItem`
        with shipment metadata repeated per line.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Response is a CSV file (Content-Type: text/csv) with filename pattern `legacy-inbound-shipment-items-YYYY-MM-DD-HHmmss.csv`.
        The file is auto-deleted server-side after send.


        Columns: sr_no, shipment_id, shipment_name, status, ship_from_name, destination_fc,
        from_country_code, integration, seller_sku, fnsku, quantity_shipped, quantity_received_api,
        quantity_received_calculated, shipment_created_at.


        If no items match, returns a JSON response with message `You can''t export
        empty data` instead of a file.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: text/csv
            Content-Disposition:
              schema:
                type: string
                example: attachment; filename="legacy-inbound-shipment-items-2026-05-29-101530.csv"
          content:
            text/plain:
              schema:
                type: string
                example: 'sr_no,shipment_id,shipment_name,status,ship_from_name,destination_fc,from_country_code,integration,seller_sku,fnsku,quantity_shipped,quantity_received_api,quantity_received_calculated,shipment_created_at

                  1,FBA15ABC123,Replenishment 2026-05,SHIPPED,Main Warehouse,ONT8,US,US
                  Marketplace,SKU-001,X0001ABCDE,50,48,48,2026-05-10 14:22:31

                  2,FBA15ABC123,Replenishment 2026-05,SHIPPED,Main Warehouse,ONT8,US,US
                  Marketplace,SKU-002,X0002ABCDE,30,30,30,2026-05-10 14:22:31

                  '
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                  message:
                    type: string
                  status:
                    type: boolean
                example:
                  data: []
                  message: You can't export empty data
                  status: true
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-amazon-unified-legacy-inbound-shipments-export
  /api/amazon/unified/legacy-inbound-shipments/refresh:
    post:
      tags:
      - Amazon
      summary: Refresh All Shipments (dispatch tracked job)
      description: 'Dispatches a background job to refresh legacy inbound shipments
        from Amazon across the specified integration instances.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Request body / query accepts `integration_instance_ids` as either:

        - A JSON array of ints: `[1, 2]`

        - A comma-separated string: `"1,2"`


        If omitted, ALL `AmazonIntegrationInstance` IDs are used.


        Returns immediately with a `tracked_job_log_id` that the frontend uses to
        display progress via the tracked job log endpoints.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                integration_instance_ids:
                  type: array
                  items:
                    type: integer
              example:
                integration_instance_ids:
                - 1
                - 2
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                      integration_instance_count:
                        type: integer
                  message:
                    type: string
                  status:
                    type: boolean
                example:
                  data:
                    tracked_job_log_id: 88231
                    integration_instance_count: 2
                  message: Refresh started — track progress in the job tray
                  status: true
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-amazon-unified-legacy-inbound-shipments-refresh
  /api/amazon/unified/legacy-inbound-shipments/process-all:
    post:
      tags:
      - Amazon
      summary: Process All Unprocessed Shipments (dispatch tracked job)
      description: 'Dispatches a background job to process unprocessed legacy inbound
        shipments across the specified integration instances. Processing handles SKU
        linking, ledger entries, and cancellation reconciliation.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Request body / query accepts `integration_instance_ids` as either:

        - A JSON array of ints: `[1, 2]`

        - A comma-separated string: `"1,2"`


        If omitted, ALL `AmazonIntegrationInstance` IDs are used.


        Returns immediately with a `tracked_job_log_id` that the frontend uses to
        display progress via the tracked job log endpoints.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                integration_instance_ids:
                  type: array
                  items:
                    type: integer
              example:
                integration_instance_ids:
                - 1
                - 2
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                      integration_instance_count:
                        type: integer
                  message:
                    type: string
                  status:
                    type: boolean
                example:
                  data:
                    tracked_job_log_id: 88232
                    integration_instance_count: 2
                  message: Processing started — track progress in the job tray
                  status: true
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-amazon-unified-legacy-inbound-shipments-process-all
  /api/amazon/unified/legacy-inbound-shipments/kpi-stats:
    get:
      tags:
      - Amazon
      summary: Get KPI Stats
      description: 'Returns KPI counts for legacy inbound shipments aggregated across
        the specified integration instances:


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        - `awaiting_over_14_days` — count of shipments in SHIPPED/IN_TRANSIT/DELIVERED/CHECKED_IN/RECEIVING
        status whose cached_shipment_date is older than 14 days.

        - `discrepancies` — currently hardcoded to 0 (placeholder).

        - `errored` — count of shipments in ERROR status or with a non-empty errorLog.


        Archived shipments (`archived_at IS NOT NULL`) are excluded.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      awaiting_over_14_days:
                        type: integer
                      discrepancies:
                        type: integer
                      errored:
                        type: integer
                  message:
                    type: string
                  status:
                    type: boolean
                example:
                  data:
                    awaiting_over_14_days: 7
                    discrepancies: 0
                    errored: 3
                  message: ''
                  status: true
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-amazon-unified-legacy-inbound-shipments-kpi-stats
  /api/amazon/unified/discrepancies:
    get:
      tags:
      - Amazon
      summary: List Discrepancies
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        example: '1'
        description: Page number (default 1).
      - name: per_page
        in: query
        schema:
          type: integer
        example: '10'
        description: Results per page (default 10).
      - name: search
        in: query
        schema:
          type: string
        description: Free-text search across the resource’s searchable fields.
      - name: integration_instance_ids
        in: query
        schema:
          type: string
        description: Comma-separated integration instance IDs to scope the query.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      description: 'List Discrepancies


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      operationId: get-api-amazon-unified-discrepancies
    post:
      tags:
      - Amazon
      summary: Create Discrepancy
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties: {}
              example: {}
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      description: 'Create Discrepancy


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      operationId: post-api-amazon-unified-discrepancies
  /api/amazon/unified/discrepancies/{id}:
    get:
      tags:
      - Amazon
      summary: Get Discrepancy
      parameters:
      - name: id
        in: path
        schema:
          type: string
        required: true
        description: The record ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      description: 'Get Discrepancy


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      operationId: get-api-amazon-unified-discrepancies-id
  /api/amazon/unified/discrepancies/export:
    get:
      tags:
      - Amazon
      summary: Export Discrepancies
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      description: 'Export Discrepancies


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      operationId: get-api-amazon-unified-discrepancies-export
  /api/amazon/unified/discrepancies/statistics:
    get:
      tags:
      - Amazon
      summary: Get Discrepancy Statistics
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      description: 'Get Discrepancy Statistics


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      operationId: get-api-amazon-unified-discrepancies-statistics
  /api/amazon/unified/discrepancies/{discrepancy}/recheck:
    post:
      tags:
      - Amazon
      summary: Recheck Discrepancy
      requestBody:
        content: {}
      parameters:
      - name: discrepancy
        in: path
        schema:
          type: string
        required: true
        description: The discrepancy ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      description: 'Recheck Discrepancy


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      operationId: post-api-amazon-unified-discrepancies-discrepancy-recheck
  /api/amazon/unified/discrepancies/recheck-all-async:
    post:
      tags:
      - Amazon
      summary: Recheck All Discrepancies (Async)
      requestBody:
        content: {}
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      description: 'Recheck All Discrepancies (Async)


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      operationId: post-api-amazon-unified-discrepancies-recheck-all-async
  /api/amazon/unified/discrepancies/{discrepancy}/investigation-status:
    put:
      tags:
      - Amazon
      summary: Update Investigation Status
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                investigation_status:
                  type: string
              example:
                investigation_status: investigating
      parameters:
      - name: discrepancy
        in: path
        schema:
          type: string
        required: true
        description: The discrepancy ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      description: 'Update Investigation Status


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      operationId: put-api-amazon-unified-discrepancies-discrepancy-investigation-status
  /api/amazon/unified/discrepancies/recheck-progress/{trackedJobLogId}:
    get:
      tags:
      - Amazon
      summary: Get Discrepancy Recheck Progress
      description: 'Polls the progress of a queued discrepancy recheck background
        job. Start the job with POST /api/amazon/unified/discrepancies/recheck-all-async,
        which returns a tracked_job_log_id to use as the path parameter here.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        The response reports:

        - status: pending, processing, completed, failed, or cancelled

        - total_items / processed_items and progress_percentage (0-100)

        - results: aggregated recheck counters — by_status (resolved, deleted, still_exist,
        updated, skipped, failed) and by_reason_type (the same counters per discrepancy
        reason type, e.g. ledger_summary_mismatch)

        - messages: the latest progress message emitted by the job


        Poll this endpoint until status is completed, failed, or cancelled.'
      parameters:
      - name: trackedJobLogId
        in: path
        schema:
          type: string
        required: true
        description: Tracked job log ID returned by the asynchronous recheck-all endpoint
          (tracked_job_log_id)
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      status:
                        type: string
                      total_items:
                        type: integer
                      processed_items:
                        type: integer
                      progress_percentage:
                        type: integer
                      results:
                        type: object
                        properties:
                          by_status:
                            type: object
                            properties:
                              resolved:
                                type: integer
                              deleted:
                                type: integer
                              still_exist:
                                type: integer
                              updated:
                                type: integer
                              skipped:
                                type: integer
                              failed:
                                type: integer
                          by_reason_type:
                            type: object
                            properties:
                              ledger_summary_mismatch:
                                type: object
                                properties:
                                  deleted:
                                    type: integer
                                  still_exist:
                                    type: integer
                                  updated:
                                    type: integer
                                  skipped:
                                    type: integer
                                  failed:
                                    type: integer
                              internal_report_missing:
                                type: object
                                properties:
                                  deleted:
                                    type: integer
                                  still_exist:
                                    type: integer
                                  updated:
                                    type: integer
                                  skipped:
                                    type: integer
                                  failed:
                                    type: integer
                      messages:
                        type: string
                  status:
                    type: string
                example:
                  data:
                    status: processing
                    total_items: 250
                    processed_items: 120
                    progress_percentage: 48
                    results:
                      by_status:
                        resolved: 34
                        deleted: 34
                        still_exist: 78
                        updated: 11
                        skipped: 8
                        failed: 0
                      by_reason_type:
                        ledger_summary_mismatch:
                          deleted: 34
                          still_exist: 78
                          updated: 11
                          skipped: 0
                          failed: 0
                        internal_report_missing:
                          deleted: 0
                          still_exist: 0
                          updated: 0
                          skipped: 8
                          failed: 0
                    messages: Rechecking discrepancies
                  status: success
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: object
                    properties:
                      App\Models\TrackedJobLog:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: array
                  status:
                    type: string
                  message:
                    type: string
                example:
                  errors:
                    App\Models\TrackedJobLog:
                    - message: No query results for model [App\Models\TrackedJobLog]
                        99999
                      code: NotFound
                      data: []
                  status: failure
                  message: No query results for model [App\Models\TrackedJobLog] 99999
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-amazon-unified-discrepancies-recheck-progress-trackedjoblogid
  /api/amazon/unified/discrepancies/{discrepancy}/activity-log:
    get:
      tags:
      - Amazon
      summary: Get Discrepancy Activity Log
      description: 'Returns the paginated activity log for a single FBA inventory
        ledger discrepancy, newest first. Each entry contains id, description, event
        (created / updated / deleted / bulk_upsert), properties (the recorded old
        and new attribute values plus the change source), causer_name (the user who
        made the change, null for system changes), and created_at (UTC).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Query parameters: page, per_page (default 15), filter[event], filter[source],
        filter[batch_uuid].'
      parameters:
      - name: discrepancy
        in: path
        schema:
          type: string
        required: true
        description: Discrepancy ID
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        description:
                          type: string
                        event:
                          type: string
                        properties:
                          type: object
                          properties:
                            old:
                              type: object
                              properties:
                                investigation_status:
                                  type: string
                            attributes:
                              type: object
                              properties:
                                investigation_status:
                                  type: string
                            source:
                              type: string
                        causer_name:
                          type: string
                        created_at:
                          type: string
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                    items:
                      type: object
                      properties:
                        url:
                          type: string
                          nullable: true
                        label:
                          type: string
                        active:
                          type: boolean
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 3021
                    description: updated
                    event: updated
                    properties:
                      old:
                        investigation_status: new
                      attributes:
                        investigation_status: investigating
                      source: manual
                    causer_name: Jane Doe
                    created_at: '2026-06-18T09:41:32.000000Z'
                  - id: 2874
                    description: created
                    event: created
                    properties:
                      attributes:
                        quantity: -3
                        reason_type: ledger_summary_mismatch
                        event_type: Shipments
                      source: amazon_sync
                    causer_name: null
                    created_at: '2026-05-15T02:10:44.000000Z'
                  first_page_url: https://app.sku.io/api/amazon/unified/discrepancies/4821/activity-log?page=1
                  from: 1
                  last_page: 1
                  last_page_url: https://app.sku.io/api/amazon/unified/discrepancies/4821/activity-log?page=1
                  links:
                  - url: null
                    label: '&laquo; Previous'
                    active: false
                  - url: https://app.sku.io/api/amazon/unified/discrepancies/4821/activity-log?page=1
                    label: '1'
                    active: true
                  - url: null
                    label: Next &raquo;
                    active: false
                  next_page_url: null
                  path: https://app.sku.io/api/amazon/unified/discrepancies/4821/activity-log
                  per_page: 15
                  prev_page_url: null
                  to: 2
                  total: 2
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: object
                    properties:
                      Modules\Amazon\Entities\AmazonLedgerSummaryDiscrepancy:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: array
                  status:
                    type: string
                  message:
                    type: string
                example:
                  errors:
                    Modules\Amazon\Entities\AmazonLedgerSummaryDiscrepancy:
                    - message: No query results for model [Modules\Amazon\Entities\AmazonLedgerSummaryDiscrepancy]
                        99999
                      code: NotFound
                      data: []
                  status: failure
                  message: No query results for model [Modules\Amazon\Entities\AmazonLedgerSummaryDiscrepancy]
                    99999
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-amazon-unified-discrepancies-discrepancy-activity-log
  /api/amazon/unified/discrepancies/{discrepancy}/detailed-data:
    get:
      tags:
      - Amazon
      summary: Get Discrepancy Detailed Data
      description: 'Returns a discrepancy together with the contextual data needed
        to investigate it. All dates are Y-m-d in the application timezone.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Always included (when the discrepancy is linked to an FNSKU product):

        - discrepancy: the full discrepancy record

        - related_discrepancies: other discrepancies for the same FNSKU product within
        10 days either side of the discrepancy date

        - summary_reports: the daily inventory ledger summary rows for the same window
        (starting/ending warehouse balances, receipts, customer shipments, customer
        returns, vendor returns, warehouse transfers, adjustments)

        - date_range: start_date, end_date and discrepancy_date of the window


        For ledger_summary_mismatch discrepancies, also includes:

        - ledger_summary: the mismatched daily summary row

        - ledgers: the individual ledger events for the discrepancy date and event
        type

        - current_calculations: per event type (Receipts, Shipments, CustomerReturns,
        VendorReturns, WhseTransfers, Adjustments), the summary value vs the ledger
        total and the current difference


        For internal_report_missing discrepancies, also includes:

        - summary_report_dates: a per-day existence map covering 30 days either side
        of the discrepancy date

        - summary_report_statistics: total_days, days_with_summary, days_missing and
        the date range

        - last_report_before_gap: the most recent summary row before the gap, when
        one exists'
      parameters:
      - name: discrepancy
        in: path
        schema:
          type: string
        required: true
        description: Discrepancy ID
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      discrepancy:
                        type: object
                        properties:
                          id:
                            type: integer
                          integration_instance_id:
                            type: integer
                          integration_instance:
                            type: object
                            properties:
                              id:
                                type: integer
                              name:
                                type: string
                          amazon_fnsku_product_id:
                            type: integer
                          amazon_fba_report_inventory_ledger_summary_id:
                            type: integer
                          fnsku:
                            type: string
                          product:
                            type: object
                            properties:
                              id:
                                type: integer
                              sku:
                                type: string
                              name:
                                type: string
                          location:
                            type: string
                          disposition:
                            type: string
                          discrepancy_date:
                            type: string
                          reason_type:
                            type: string
                          event_type:
                            type: string
                          quantity:
                            type: integer
                          cogs:
                            type: number
                          extended_cogs:
                            type: number
                          reconciled_at:
                            type: string
                            nullable: true
                          investigation_status:
                            type: string
                          notes:
                            type: string
                          investigation_notes:
                            type: string
                          auto_resolved_at:
                            type: string
                            nullable: true
                          status:
                            type: string
                          created_at:
                            type: string
                          updated_at:
                            type: string
                      related_discrepancies:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            discrepancy_date:
                              type: string
                            reason_type:
                              type: string
                            event_type:
                              type: string
                            quantity:
                              type: integer
                            cogs:
                              type: number
                            extended_cogs:
                              type: number
                            status:
                              type: string
                            notes:
                              type: string
                            is_current_discrepancy:
                              type: boolean
                      summary_reports:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            date:
                              type: string
                            starting_warehouse_balance:
                              type: integer
                            ending_warehouse_balance:
                              type: integer
                            in_transit_between_warehouses:
                              type: integer
                            receipts:
                              type: integer
                            customer_shipments:
                              type: integer
                            customer_returns:
                              type: integer
                            vendor_returns:
                              type: integer
                            warehouse_transfer_in_out:
                              type: integer
                            adjustments:
                              type: integer
                            is_discrepancy_date:
                              type: boolean
                      date_range:
                        type: object
                        properties:
                          start_date:
                            type: string
                          end_date:
                            type: string
                          discrepancy_date:
                            type: string
                      ledger_summary:
                        type: object
                        properties:
                          id:
                            type: integer
                          date:
                            type: string
                          receipts:
                            type: integer
                          customer_shipments:
                            type: integer
                          customer_returns:
                            type: integer
                          vendor_returns:
                            type: integer
                          warehouse_transfer_in_out:
                            type: integer
                          adjustments:
                            type: integer
                      ledgers:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            event_type:
                              type: string
                            quantity:
                              type: integer
                            reference_id:
                              type: string
                            fulfillment_center:
                              type: string
                            reason:
                              type: string
                              nullable: true
                            event_datetime:
                              type: string
                      current_calculations:
                        type: object
                        properties:
                          Receipts:
                            type: object
                            properties:
                              summary_value:
                                type: integer
                              ledger_value:
                                type: integer
                              discrepancy:
                                type: integer
                          Shipments:
                            type: object
                            properties:
                              summary_value:
                                type: integer
                              ledger_value:
                                type: integer
                              discrepancy:
                                type: integer
                          CustomerReturns:
                            type: object
                            properties:
                              summary_value:
                                type: integer
                              ledger_value:
                                type: integer
                              discrepancy:
                                type: integer
                          VendorReturns:
                            type: object
                            properties:
                              summary_value:
                                type: integer
                              ledger_value:
                                type: integer
                              discrepancy:
                                type: integer
                          WhseTransfers:
                            type: object
                            properties:
                              summary_value:
                                type: integer
                              ledger_value:
                                type: integer
                              discrepancy:
                                type: integer
                          Adjustments:
                            type: object
                            properties:
                              summary_value:
                                type: integer
                              ledger_value:
                                type: integer
                              discrepancy:
                                type: integer
                  status:
                    type: string
                example:
                  data:
                    discrepancy:
                      id: 4821
                      integration_instance_id: 3
                      integration_instance:
                        id: 3
                        name: Amazon US
                      amazon_fnsku_product_id: 1592
                      amazon_fba_report_inventory_ledger_summary_id: 88214
                      fnsku: X002ABCDE1
                      product:
                        id: 731
                        sku: WIDGET-BLUE-M
                        name: Blue Widget - Medium
                      location: US
                      disposition: SELLABLE
                      discrepancy_date: '2026-05-14'
                      reason_type: ledger_summary_mismatch
                      event_type: Shipments
                      quantity: -3
                      cogs: 12.45
                      extended_cogs: -37.35
                      reconciled_at: null
                      investigation_status: investigating
                      notes: 'Discrepancy in Shipments on 2026-05-14: Summary Report
                        = -120, Ledgers = -117'
                      investigation_notes: Case 12345678901 opened with Amazon seller
                        support
                      auto_resolved_at: null
                      status: unreconciled
                      created_at: '2026-05-15T02:10:44.000Z'
                      updated_at: '2026-06-18T09:41:32.000Z'
                    related_discrepancies:
                    - id: 4821
                      discrepancy_date: '2026-05-14'
                      reason_type: ledger_summary_mismatch
                      event_type: Shipments
                      quantity: -3
                      cogs: 12.45
                      extended_cogs: -37.35
                      status: unreconciled
                      notes: 'Discrepancy in Shipments on 2026-05-14: Summary Report
                        = -120, Ledgers = -117'
                      is_current_discrepancy: true
                    - id: 4836
                      discrepancy_date: '2026-05-19'
                      reason_type: ledger_summary_mismatch
                      event_type: Adjustments
                      quantity: 1
                      cogs: 12.45
                      extended_cogs: 12.45
                      status: reconciled
                      notes: 'Discrepancy in Adjustments on 2026-05-19: Summary Report
                        = 1, Ledgers = 0'
                      is_current_discrepancy: false
                    summary_reports:
                    - id: 88214
                      date: '2026-05-14'
                      starting_warehouse_balance: 265
                      ending_warehouse_balance: 145
                      in_transit_between_warehouses: 8
                      receipts: 0
                      customer_shipments: -120
                      customer_returns: 2
                      vendor_returns: 0
                      warehouse_transfer_in_out: -2
                      adjustments: 0
                      is_discrepancy_date: true
                    - id: 88342
                      date: '2026-05-15'
                      starting_warehouse_balance: 145
                      ending_warehouse_balance: 141
                      in_transit_between_warehouses: 8
                      receipts: 0
                      customer_shipments: -5
                      customer_returns: 1
                      vendor_returns: 0
                      warehouse_transfer_in_out: 0
                      adjustments: 0
                      is_discrepancy_date: false
                    date_range:
                      start_date: '2026-05-04'
                      end_date: '2026-05-24'
                      discrepancy_date: '2026-05-14'
                    ledger_summary:
                      id: 88214
                      date: '2026-05-14T00:00:00.000000Z'
                      receipts: 0
                      customer_shipments: -120
                      customer_returns: 2
                      vendor_returns: 0
                      warehouse_transfer_in_out: -2
                      adjustments: 0
                    ledgers:
                    - id: 771203
                      event_type: Shipments
                      quantity: -2
                      reference_id: 113-9876543-1234567
                      fulfillment_center: TUL2
                      reason: null
                      event_datetime: '2026-05-14T16:22:05.000000Z'
                    - id: 771208
                      event_type: Shipments
                      quantity: -1
                      reference_id: 112-4455667-8899001
                      fulfillment_center: BNA2
                      reason: null
                      event_datetime: '2026-05-14T19:03:47.000000Z'
                    current_calculations:
                      Receipts:
                        summary_value: 0
                        ledger_value: 0
                        discrepancy: 0
                      Shipments:
                        summary_value: -120
                        ledger_value: -117
                        discrepancy: -3
                      CustomerReturns:
                        summary_value: 2
                        ledger_value: 2
                        discrepancy: 0
                      VendorReturns:
                        summary_value: 0
                        ledger_value: 0
                        discrepancy: 0
                      WhseTransfers:
                        summary_value: -2
                        ledger_value: -2
                        discrepancy: 0
                      Adjustments:
                        summary_value: 0
                        ledger_value: 0
                        discrepancy: 0
                  status: success
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: object
                    properties:
                      Modules\Amazon\Entities\AmazonLedgerSummaryDiscrepancy:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: array
                  status:
                    type: string
                  message:
                    type: string
                example:
                  errors:
                    Modules\Amazon\Entities\AmazonLedgerSummaryDiscrepancy:
                    - message: No query results for model [Modules\Amazon\Entities\AmazonLedgerSummaryDiscrepancy]
                        99999
                      code: NotFound
                      data: []
                  status: failure
                  message: No query results for model [Modules\Amazon\Entities\AmazonLedgerSummaryDiscrepancy]
                    99999
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-amazon-unified-discrepancies-discrepancy-detailed-data
  /api/amazon/unified/discrepancies/{discrepancy}/impact-analysis:
    get:
      tags:
      - Amazon
      summary: Get Discrepancy Impact Analysis
      description: 'Compares SKU.io''s cost-layer-derived inventory position for the
        discrepancy''s FNSKU product against Amazon''s daily inventory ledger summary
        balances, so you can see whether the discrepancy still affects on-hand inventory.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Returns an impact block for the discrepancy date and, when a more recent summary
        row exists, a second impact block for the most recent summary date (most_recent_date_impact
        is null when the discrepancy date is already the latest, or when no summary
        exists for that date). Each impact block contains: warehouse_qty, in_transit_qty
        and total_qty (SKU.io side), summary_warehouse_qty, summary_in_transit_qty
        and summary_total_qty (Amazon ledger summary side), and the calculated warehouse_discrepancy,
        in_transit_discrepancy and total_discrepancy differences.


        Returns 400 when the discrepancy has no linked FNSKU product. Dates are Y-m-d.'
      parameters:
      - name: discrepancy
        in: path
        schema:
          type: string
        required: true
        description: Discrepancy ID
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      discrepancy_date:
                        type: string
                      discrepancy_date_impact:
                        type: object
                        properties:
                          warehouse_qty:
                            type: integer
                          in_transit_qty:
                            type: integer
                          total_qty:
                            type: integer
                          summary_warehouse_qty:
                            type: integer
                          summary_in_transit_qty:
                            type: integer
                          summary_total_qty:
                            type: integer
                          warehouse_discrepancy:
                            type: integer
                          in_transit_discrepancy:
                            type: integer
                          total_discrepancy:
                            type: integer
                      most_recent_summary_date:
                        type: string
                      most_recent_date_impact:
                        type: object
                        properties:
                          warehouse_qty:
                            type: integer
                          in_transit_qty:
                            type: integer
                          total_qty:
                            type: integer
                          summary_warehouse_qty:
                            type: integer
                          summary_in_transit_qty:
                            type: integer
                          summary_total_qty:
                            type: integer
                          warehouse_discrepancy:
                            type: integer
                          in_transit_discrepancy:
                            type: integer
                          total_discrepancy:
                            type: integer
                  status:
                    type: string
                example:
                  data:
                    discrepancy_date: '2026-05-14'
                    discrepancy_date_impact:
                      warehouse_qty: 142
                      in_transit_qty: 8
                      total_qty: 150
                      summary_warehouse_qty: 145
                      summary_in_transit_qty: 8
                      summary_total_qty: 153
                      warehouse_discrepancy: -3
                      in_transit_discrepancy: 0
                      total_discrepancy: -3
                    most_recent_summary_date: '2026-07-05'
                    most_recent_date_impact:
                      warehouse_qty: 117
                      in_transit_qty: 12
                      total_qty: 129
                      summary_warehouse_qty: 120
                      summary_in_transit_qty: 12
                      summary_total_qty: 132
                      warehouse_discrepancy: -3
                      in_transit_discrepancy: 0
                      total_discrepancy: -3
                  status: success
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: object
                    properties:
                      ? ''
                      : type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: array
                  status:
                    type: string
                  message:
                    type: string
                example:
                  errors:
                    ? ''
                    : - message: FNSKU product not found for this discrepancy
                        code: '400'
                        data: []
                  status: failure
                  message: FNSKU product not found for this discrepancy
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: object
                    properties:
                      Modules\Amazon\Entities\AmazonLedgerSummaryDiscrepancy:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: array
                  status:
                    type: string
                  message:
                    type: string
                example:
                  errors:
                    Modules\Amazon\Entities\AmazonLedgerSummaryDiscrepancy:
                    - message: No query results for model [Modules\Amazon\Entities\AmazonLedgerSummaryDiscrepancy]
                        99999
                      code: NotFound
                      data: []
                  status: failure
                  message: No query results for model [Modules\Amazon\Entities\AmazonLedgerSummaryDiscrepancy]
                    99999
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-amazon-unified-discrepancies-discrepancy-impact-analysis
  /api/amazon/unified/discrepancies/{discrepancy}/related-ledgers:
    get:
      tags:
      - Amazon
      summary: List Related Discrepancy Ledgers
      description: 'Returns the paginated individual ledger events recorded for the
        discrepancy''s FNSKU product around the discrepancy date (default: 7 days
        either side, adjustable with days_range), newest first. Useful for spotting
        the specific ledger rows behind a summary mismatch.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Each row contains: id, date (Y-m-d), event_datetime (UTC), event_type (Adjustments,
        CustomerReturns, Receipts, Shipments, VendorReturns, WhseTransfers), quantity,
        reference_id (e.g. the Amazon order ID or shipment reference), fulfillment_center,
        reason, status (reconciled or unreconciled), reconciled_at, and the linked
        cost-layer values cogs, extended_cogs and fifo_id (null when the event has
        no cost layer yet).


        Query parameters: page, per_page (default 15), days_range (default 7), event_type.
        Returns an empty page when the discrepancy has no linked FNSKU product.'
      parameters:
      - name: discrepancy
        in: path
        schema:
          type: string
        required: true
        description: Discrepancy ID
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        date:
                          type: string
                        event_datetime:
                          type: string
                        event_type:
                          type: string
                        quantity:
                          type: integer
                        reference_id:
                          type: string
                        fulfillment_center:
                          type: string
                        reason:
                          type: string
                          nullable: true
                        status:
                          type: string
                        reconciled_at:
                          type: string
                        cogs:
                          type: number
                        extended_cogs:
                          type: number
                        fifo_id:
                          type: integer
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                    items:
                      type: object
                      properties:
                        url:
                          type: string
                          nullable: true
                        label:
                          type: string
                        active:
                          type: boolean
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 771208
                    date: '2026-05-14'
                    event_datetime: '2026-05-14T19:03:47.000000Z'
                    event_type: Shipments
                    quantity: -1
                    reference_id: 112-4455667-8899001
                    fulfillment_center: BNA2
                    reason: null
                    status: reconciled
                    reconciled_at: '2026-05-16T04:12:09.000000Z'
                    cogs: 12.45
                    extended_cogs: -12.45
                    fifo_id: 30412
                  - id: 771203
                    date: '2026-05-14'
                    event_datetime: '2026-05-14T16:22:05.000000Z'
                    event_type: Shipments
                    quantity: -2
                    reference_id: 113-9876543-1234567
                    fulfillment_center: TUL2
                    reason: null
                    status: unreconciled
                    reconciled_at: null
                    cogs: null
                    extended_cogs: null
                    fifo_id: null
                  first_page_url: https://app.sku.io/api/amazon/unified/discrepancies/4821/related-ledgers?page=1
                  from: 1
                  last_page: 1
                  last_page_url: https://app.sku.io/api/amazon/unified/discrepancies/4821/related-ledgers?page=1
                  links:
                  - url: null
                    label: '&laquo; Previous'
                    active: false
                  - url: https://app.sku.io/api/amazon/unified/discrepancies/4821/related-ledgers?page=1
                    label: '1'
                    active: true
                  - url: null
                    label: Next &raquo;
                    active: false
                  next_page_url: null
                  path: https://app.sku.io/api/amazon/unified/discrepancies/4821/related-ledgers
                  per_page: 15
                  prev_page_url: null
                  to: 2
                  total: 2
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: object
                    properties:
                      Modules\Amazon\Entities\AmazonLedgerSummaryDiscrepancy:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: array
                  status:
                    type: string
                  message:
                    type: string
                example:
                  errors:
                    Modules\Amazon\Entities\AmazonLedgerSummaryDiscrepancy:
                    - message: No query results for model [Modules\Amazon\Entities\AmazonLedgerSummaryDiscrepancy]
                        99999
                      code: NotFound
                      data: []
                  status: failure
                  message: No query results for model [Modules\Amazon\Entities\AmazonLedgerSummaryDiscrepancy]
                    99999
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-amazon-unified-discrepancies-discrepancy-related-ledgers
  /api/amazon/unified/discrepancies/{discrepancy}/investigation-notes:
    patch:
      tags:
      - Amazon
      summary: Update Discrepancy Investigation Notes
      description: 'Updates the free-text investigation notes on a single discrepancy.
        Send investigation_notes as a string of up to 5000 characters, or null to
        clear the notes. The investigation status is not changed by this endpoint
        (use the investigation-status endpoints for that).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Returns the updated discrepancy record.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                investigation_notes:
                  type: string
              example:
                investigation_notes: Case 12345678901 opened with Amazon seller support
                  on 2026-06-18. Awaiting reimbursement decision.
      parameters:
      - name: discrepancy
        in: path
        schema:
          type: string
        required: true
        description: Discrepancy ID
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      amazon_fnsku_product_id:
                        type: integer
                      amazon_fba_report_inventory_ledger_summary_id:
                        type: integer
                      fnsku:
                        type: string
                      location:
                        type: string
                      disposition:
                        type: string
                      discrepancy_date:
                        type: string
                      reason_type:
                        type: string
                      event_type:
                        type: string
                      quantity:
                        type: integer
                      cogs:
                        type: number
                      extended_cogs:
                        type: number
                      reconciled_at:
                        type: string
                        nullable: true
                      investigation_status:
                        type: string
                      notes:
                        type: string
                      investigation_notes:
                        type: string
                      auto_resolved_at:
                        type: string
                        nullable: true
                      status:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                  message:
                    type: string
                  status:
                    type: string
                example:
                  data:
                    id: 4821
                    integration_instance_id: 3
                    amazon_fnsku_product_id: 1592
                    amazon_fba_report_inventory_ledger_summary_id: 88214
                    fnsku: X002ABCDE1
                    location: US
                    disposition: SELLABLE
                    discrepancy_date: '2026-05-14'
                    reason_type: ledger_summary_mismatch
                    event_type: Shipments
                    quantity: -3
                    cogs: 12.45
                    extended_cogs: -37.35
                    reconciled_at: null
                    investigation_status: investigating
                    notes: 'Discrepancy in Shipments on 2026-05-14: Summary Report
                      = -120, Ledgers = -117'
                    investigation_notes: Case 12345678901 opened with Amazon seller
                      support
                    auto_resolved_at: null
                    status: unreconciled
                    created_at: '2026-05-15T02:10:44.000Z'
                    updated_at: '2026-06-18T09:41:32.000Z'
                  message: Investigation notes updated
                  status: success
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: object
                    properties:
                      Modules\Amazon\Entities\AmazonLedgerSummaryDiscrepancy:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: array
                  status:
                    type: string
                  message:
                    type: string
                example:
                  errors:
                    Modules\Amazon\Entities\AmazonLedgerSummaryDiscrepancy:
                    - message: No query results for model [Modules\Amazon\Entities\AmazonLedgerSummaryDiscrepancy]
                        99999
                      code: NotFound
                      data: []
                  status: failure
                  message: No query results for model [Modules\Amazon\Entities\AmazonLedgerSummaryDiscrepancy]
                    99999
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: object
                    properties:
                      investigation_notes:
                        type: array
                        items:
                          type: string
                  message:
                    type: string
                  status:
                    type: string
                example:
                  errors:
                    investigation_notes:
                    - The investigation notes field must not be greater than 5000
                      characters.
                  message: The investigation notes field must not be greater than
                    5000 characters.
                  status: failure
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: patch-api-amazon-unified-discrepancies-discrepancy-investigation-notes
  /api/amazon/unified/discrepancies/bulk-investigation-status:
    post:
      tags:
      - Amazon
      summary: Bulk Update Discrepancy Investigation Status
      description: 'Sets the investigation status on multiple discrepancies in one
        call.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Body fields:

        - discrepancy_ids (required, array of integers): IDs of existing discrepancies
        to update (min 1)

        - investigation_status (required, string): one of new, investigating, case_opened,
        reimbursed, written_off, resolved

        - investigation_notes (optional, string, max 5000): when provided, the same
        notes are written to every selected discrepancy


        Runs synchronously and returns a message with the number of discrepancies
        updated.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                discrepancy_ids:
                  type: array
                  items:
                    type: integer
                investigation_status:
                  type: string
                investigation_notes:
                  type: string
              example:
                discrepancy_ids:
                - 4821
                - 4836
                - 4901
                investigation_status: investigating
                investigation_notes: 'Batch review 2026-07-06: escalated to Amazon
                  seller support.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  status:
                    type: string
                example:
                  message: Updated investigation status to investigating for 3 discrepancies
                  status: success
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: object
                    properties:
                      discrepancy_ids:
                        type: array
                        items:
                          type: string
                      investigation_status:
                        type: array
                        items:
                          type: string
                  message:
                    type: string
                  status:
                    type: string
                example:
                  errors:
                    discrepancy_ids:
                    - The discrepancy ids field is required.
                    investigation_status:
                    - The investigation status field is required.
                  message: The discrepancy ids field is required. (and 1 more error)
                  status: failure
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-amazon-unified-discrepancies-bulk-investigation-status
  /api/amazon/unified/discrepancies/bulk-recheck:
    post:
      tags:
      - Amazon
      summary: Bulk Recheck Discrepancies
      description: 'Re-evaluates the selected discrepancies against the current ledger
        summary and ledger event data, synchronously (results are returned in the
        same request).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Body fields:

        - discrepancy_ids (required, array of integers): IDs of existing discrepancies
        to recheck (min 1)


        Only ledger_summary_mismatch discrepancies are rechecked; other reason types
        (and rows whose summary no longer exists) are counted as skipped. For each
        rechecked row: if the summary-vs-ledger difference is now zero the discrepancy
        is deleted (and the product''s cost history is recalculated when needed);
        if the difference changed, the discrepancy''s quantity and notes are updated
        in place.


        Returns counters: resolved, deleted, still_exist, updated, skipped.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                discrepancy_ids:
                  type: array
                  items:
                    type: integer
              example:
                discrepancy_ids:
                - 4821
                - 4836
                - 4901
                - 4922
                - 4930
                - 4954
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      resolved:
                        type: integer
                      deleted:
                        type: integer
                      still_exist:
                        type: integer
                      updated:
                        type: integer
                      skipped:
                        type: integer
                  message:
                    type: string
                  status:
                    type: string
                example:
                  data:
                    resolved: 2
                    deleted: 2
                    still_exist: 3
                    updated: 1
                    skipped: 1
                  message: Rechecked 6 discrepancies
                  status: success
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: object
                    properties:
                      discrepancy_ids:
                        type: array
                        items:
                          type: string
                  message:
                    type: string
                  status:
                    type: string
                example:
                  errors:
                    discrepancy_ids:
                    - The discrepancy ids field is required.
                  message: The discrepancy ids field is required.
                  status: failure
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-amazon-unified-discrepancies-bulk-recheck
  /api/amazon/unified/discrepancies/recheck-all:
    post:
      tags:
      - Amazon
      summary: Recheck All Discrepancies
      description: 'Re-evaluates every ledger_summary_mismatch discrepancy matching
        the filters against the current ledger summary and ledger event data. This
        variant runs synchronously in the request — with large numbers of discrepancies
        it can be slow; prefer POST /api/amazon/unified/discrepancies/recheck-all-async,
        which queues a background job and returns a tracked_job_log_id for polling
        progress.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Body fields (all optional):

        - include_reconciled (boolean, default false): also recheck discrepancies
        that have already been reconciled

        - integration_instance_ids (string): comma-separated integration instance
        IDs to scope the recheck (e.g. "1,3"); omit for all instances


        For each rechecked row: if the summary-vs-ledger difference is now zero the
        discrepancy is deleted (and the product''s cost history is recalculated when
        needed); if the difference changed, the quantity and notes are updated in
        place. Returns counters (resolved, deleted, still_exist, updated, skipped),
        or a message-only response when no discrepancies match the criteria.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                include_reconciled:
                  type: boolean
                integration_instance_ids:
                  type: string
              example:
                include_reconciled: false
                integration_instance_ids: 1,3
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 OK
                  value:
                    data:
                      resolved: 34
                      deleted: 34
                      still_exist: 78
                      updated: 11
                      skipped: 8
                    message: Rechecked 120 discrepancies
                    status: success
                example-1:
                  summary: 200 OK (no matches)
                  value:
                    message: No discrepancies found matching the criteria
                    status: success
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: object
                    properties:
                      include_reconciled:
                        type: array
                        items:
                          type: string
                  message:
                    type: string
                  status:
                    type: string
                example:
                  errors:
                    include_reconciled:
                    - The include reconciled field must be true or false.
                  message: The include reconciled field must be true or false.
                  status: failure
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-amazon-unified-discrepancies-recheck-all
  /api/amazon/unified/financial-event-groups:
    get:
      tags:
      - Amazon
      summary: List Financial Event Groups
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        example: '1'
        description: Page number (default 1).
      - name: per_page
        in: query
        schema:
          type: integer
        example: '10'
        description: Results per page (default 10).
      - name: search
        in: query
        schema:
          type: string
        description: Free-text search across the resource’s searchable fields.
      - name: integration_instance_ids
        in: query
        schema:
          type: string
        description: Comma-separated integration instance IDs to scope the query.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      description: 'List Financial Event Groups


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      operationId: get-api-amazon-unified-financial-event-groups
  /api/amazon/unified/financial-event-groups/{id}:
    get:
      tags:
      - Amazon
      summary: Get Financial Event Group
      parameters:
      - name: id
        in: path
        schema:
          type: string
        required: true
        description: The record ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      description: 'Get Financial Event Group


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      operationId: get-api-amazon-unified-financial-event-groups-id
  /api/amazon/unified/financial-event-groups/export:
    get:
      tags:
      - Amazon
      summary: Export Financial Event Groups
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      description: 'Export Financial Event Groups


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      operationId: get-api-amazon-unified-financial-event-groups-export
  /api/amazon/unified/financial-event-groups/{financialEventGroup}/generate-accounting-transactions:
    post:
      tags:
      - Amazon
      summary: Generate Accounting Transactions
      requestBody:
        content: {}
      parameters:
      - name: financialEventGroup
        in: path
        schema:
          type: string
        required: true
        description: The financial event group ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      description: 'Generate Accounting Transactions


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      operationId: post-api-amazon-unified-financial-event-groups-financialeventgroup-generate-accounting-transactions
  /api/amazon/unified/financial-event-groups/{financialEventGroup}/accounting-transactions:
    delete:
      tags:
      - Amazon
      summary: Delete Accounting Transactions
      parameters:
      - name: financialEventGroup
        in: path
        schema:
          type: string
        required: true
        description: The financial event group ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      description: 'Delete Accounting Transactions


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      operationId: delete-api-amazon-unified-financial-event-groups-financialeventgroup-accounting-transactions
  /api/amazon/unified/financial-event-groups/bulk-generate:
    post:
      tags:
      - Amazon
      summary: Bulk Generate
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                financial_event_group_ids:
                  type: array
                  items:
                    type: integer
              example:
                financial_event_group_ids:
                - 1
                - 2
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      description: 'Bulk Generate


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      operationId: post-api-amazon-unified-financial-event-groups-bulk-generate
  /api/amazon/unified/financial-event-groups/{financialEventGroup}/base-currency-rate:
    put:
      tags:
      - Amazon
      summary: Update Base Currency Rate
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                base_currency_rate:
                  type: number
                deposit_amount:
                  type: string
                  nullable: true
              example:
                base_currency_rate: 1.25
                deposit_amount: null
      parameters:
      - name: financialEventGroup
        in: path
        schema:
          type: string
        required: true
        description: The financial event group ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      description: 'Update Base Currency Rate


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      operationId: put-api-amazon-unified-financial-event-groups-financialeventgroup-base-currency-rate
  /api/amazon/unified/financial-event-groups/bulk-manage/preflight:
    get:
      tags:
      - Amazon
      summary: Get Bulk Manage Preflight for Financial Event Groups
      description: 'Returns a read-only preview for the Bulk Manage Financial Event
        Groups action, without making any changes. Financial event groups are Amazon
        settlement (bank transaction) groupings used to generate accounting transactions
        in SKU.io.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        The response contains:

        - `ready_groups_count` - the number of financial event groups currently eligible
        ("ready") for accounting transaction generation.

        - `transactions` - every existing accounting transaction linked to a financial
        event group (`source_type` = `group`) or to a settlement landed-cost bill
        (`source_type` = `landed_cost_bill`). Each entry includes the transaction
        type, total, reference, whether it is pushed to an external accounting integration
        (`has_integration_link`), and the Amazon financial event group identifier
        it belongs to (`group_financial_event_group_id`).


        Use this preview to decide which transaction IDs to pass to `POST /api/amazon/unified/financial-event-groups/bulk-manage`
        and whether to regenerate afterwards. Runs synchronously.


        Query parameters:

        - `integration_instance_ids` (optional) - comma-separated integration instance
        IDs to scope the preview.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      ready_groups_count:
                        type: integer
                      transactions:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            type:
                              type: string
                            total:
                              type: number
                            reference:
                              type: string
                            has_integration_link:
                              type: boolean
                            integration_link_type:
                              type: string
                              nullable: true
                            source_type:
                              type: string
                            source_id:
                              type: integer
                            group_financial_event_group_id:
                              type: string
                  status:
                    type: string
                example:
                  data:
                    ready_groups_count: 4
                    transactions:
                    - id: 8123
                      type: sales_order_invoice
                      total: 15321.44
                      reference: 16130199621 - Sales Revenue - 8123
                      has_integration_link: false
                      integration_link_type: null
                      source_type: group
                      source_id: 42
                      group_financial_event_group_id: '16130199621'
                    - id: 8124
                      type: bill
                      total: 2140.12
                      reference: 16130199621 - Amazon Fees - 8124
                      has_integration_link: true
                      integration_link_type: invoice
                      source_type: landed_cost_bill
                      source_id: 913
                      group_financial_event_group_id: '16130199621'
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-amazon-unified-financial-event-groups-bulk-manage-preflight
  /api/amazon/unified/financial-event-groups/bulk-manage:
    post:
      tags:
      - Amazon
      summary: Bulk Manage Financial Event Groups
      description: 'Bulk manages accounting transactions for Amazon financial event
        groups (settlement/bank-transaction groupings): selectively deletes the specified
        accounting transactions (including their lines, and clearing settlement-data
        links back to them), then optionally generates accounting transactions for
        every eligible ("ready") group.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Runs synchronously in the request - this endpoint does NOT queue a background
        job; the summary in the response reflects completed work.


        Body fields:

        - `transaction_ids_to_delete` (optional, array of integers) - accounting transaction
        IDs to delete. Use `GET .../bulk-manage/preflight` to list candidates.

        - `confirmation` (optional, string) - must be exactly `DELETE` when any selected
        transaction is linked to an external accounting integration; otherwise the
        request fails with 422.

        - `generate` (optional, boolean, default false) - when true, generates accounting
        transactions for all ready groups after the deletions.

        - `integration_instance_ids` (optional, array of integers or comma-separated
        string) - scopes the generation step to specific Amazon integration instances.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                transaction_ids_to_delete:
                  type: array
                  items:
                    type: integer
                confirmation:
                  type: string
                generate:
                  type: boolean
                integration_instance_ids:
                  type: array
                  items:
                    type: integer
              example:
                transaction_ids_to_delete:
                - 8123
                - 8124
                confirmation: DELETE
                generate: true
                integration_instance_ids:
                - 1
                - 3
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      deleted:
                        type: integer
                      deleted_had_links:
                        type: integer
                      generated:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            group_id:
                              type: string
                      failed:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            group_id:
                              type: string
                            error:
                              type: string
                      summary:
                        type: object
                        properties:
                          deleted:
                            type: integer
                          generated:
                            type: integer
                          failed:
                            type: integer
                  status:
                    type: string
                example:
                  data:
                    deleted: 2
                    deleted_had_links: 1
                    generated:
                    - id: 42
                      group_id: '16130199621'
                    - id: 45
                      group_id: '16171123908'
                    failed:
                    - id: 47
                      group_id: '16204581122'
                      error: 'Cannot generate accounting transactions. Blocked by:
                        All lines mapped'
                    summary:
                      deleted: 2
                      generated: 2
                      failed: 1
                  status: success
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      confirmation:
                        type: array
                        items:
                          type: string
                  status:
                    type: string
                example:
                  message: You must type DELETE to confirm deletion of integration-linked
                    transactions.
                  errors:
                    confirmation:
                    - You must type DELETE to confirm deletion of integration-linked
                      transactions.
                  status: failure
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-amazon-unified-financial-event-groups-bulk-manage
  /api/amazon/unified/financial-event-groups/bulk-regenerate/preflight:
    get:
      tags:
      - Amazon
      summary: Get Bulk Regenerate Preflight for Financial Event Groups
      description: 'Returns a read-only impact summary for the Bulk Regenerate Accounting
        Transactions action, without making any changes. It inspects every financial
        event group that currently has accounting transactions and reports:


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        - `total` - number of groups that have accounting transactions.

        - `eligible` - groups whose transactions can be safely deleted and regenerated
        (none are linked to an external accounting integration).

        - `has_integration_links` - groups that will be SKIPPED by the bulk regenerate
        because one or more of their transactions were pushed to an accounting integration
        (each with its internal `id`, the Amazon `group_id`, and `linked_count`).


        Runs synchronously.


        Query parameters:

        - `integration_instance_ids` (optional) - comma-separated integration instance
        IDs to scope the preview.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      total:
                        type: integer
                      eligible:
                        type: integer
                      has_integration_links:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            group_id:
                              type: string
                            linked_count:
                              type: integer
                  status:
                    type: string
                example:
                  data:
                    total: 12
                    eligible: 10
                    has_integration_links:
                    - id: 42
                      group_id: '16130199621'
                      linked_count: 2
                    - id: 51
                      group_id: '16171123908'
                      linked_count: 1
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-amazon-unified-financial-event-groups-bulk-regenerate-preflight
  /api/amazon/unified/financial-event-groups/bulk-regenerate:
    post:
      tags:
      - Amazon
      summary: Bulk Regenerate Accounting Transactions
      description: 'Deletes and regenerates accounting transactions for every Amazon
        financial event group that currently has them. Groups with transactions linked
        to an external accounting integration are skipped (they are never deleted
        by this action). Use `GET .../bulk-regenerate/preflight` first to see how
        many groups are eligible and which will be skipped.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Runs synchronously in the request - this endpoint does NOT queue a background
        job; the response summary reflects completed work.


        Body fields:

        - `confirmation` (required, string) - must be exactly `YES`.

        - `integration_instance_ids` (optional, array of integers or comma-separated
        string) - scopes the operation to specific Amazon integration instances.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                confirmation:
                  type: string
                integration_instance_ids:
                  type: array
                  items:
                    type: integer
              example:
                confirmation: 'YES'
                integration_instance_ids:
                - 1
                - 3
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      regenerated:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            group_id:
                              type: string
                      skipped:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            group_id:
                              type: string
                            reason:
                              type: string
                      failed:
                        type: array
                      summary:
                        type: object
                        properties:
                          total:
                            type: integer
                          regenerated:
                            type: integer
                          skipped:
                            type: integer
                          failed:
                            type: integer
                  status:
                    type: string
                example:
                  data:
                    regenerated:
                    - id: 42
                      group_id: '16130199621'
                    - id: 45
                      group_id: '16171123908'
                    skipped:
                    - id: 51
                      group_id: '16204581122'
                      reason: Has integration-linked accounting transactions
                    failed: []
                    summary:
                      total: 3
                      regenerated: 2
                      skipped: 1
                      failed: 0
                  status: success
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      confirmation:
                        type: array
                        items:
                          type: string
                  status:
                    type: string
                example:
                  message: The confirmation field is required.
                  errors:
                    confirmation:
                    - The confirmation field is required.
                  status: failure
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-amazon-unified-financial-event-groups-bulk-regenerate
  /api/amazon/unified/financial-event-groups/purge-pre-start/preflight:
    get:
      tags:
      - Amazon
      summary: Get Purge Pre-Start Preflight for Financial Event Groups
      description: 'Dry run of the purge-pre-start action: lists the Amazon financial
        event groups whose settlement period starts BEFORE the account''s inventory
        start date. These are historical records that will never have matching settlement
        reports imported. No changes are made.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        The response contains:

        - `purged` - the number of groups that WOULD be deleted (dry-run count).

        - `groups` - details for each group: internal `id`, Amazon `group_id`, integration
        name, period `start_date` (ISO 8601), and how many settlement data rows and
        accounting transactions it currently has.

        - `inventory_start_date` - the account''s inventory start date (ISO 8601,
        UTC) used as the cutoff.

        - `dry_run` - always true for this endpoint.


        Query parameters:

        - `integration_instance_ids` (optional) - comma-separated integration instance
        IDs to scope the preview.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      purged:
                        type: integer
                      groups:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            group_id:
                              type: string
                            integration:
                              type: string
                            start_date:
                              type: string
                            settlement_data_count:
                              type: integer
                            accounting_transactions_count:
                              type: integer
                      inventory_start_date:
                        type: string
                      dry_run:
                        type: boolean
                  status:
                    type: string
                example:
                  data:
                    purged: 2
                    groups:
                    - id: 7
                      group_id: '14988201455'
                      integration: Amazon US
                      start_date: '2023-11-02T00:00:00+00:00'
                      settlement_data_count: 1542
                      accounting_transactions_count: 0
                    - id: 8
                      group_id: '15012349876'
                      integration: Amazon CA
                      start_date: '2023-11-16T00:00:00+00:00'
                      settlement_data_count: 388
                      accounting_transactions_count: 0
                    inventory_start_date: '2024-01-01T00:00:00+00:00'
                    dry_run: true
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-amazon-unified-financial-event-groups-purge-pre-start-preflight
  /api/amazon/unified/financial-event-groups/purge-pre-start:
    post:
      tags:
      - Amazon
      summary: Purge Pre-Start Financial Event Groups
      description: 'Queues a background job that deletes every Amazon financial event
        group (settlement transaction) whose settlement period starts BEFORE the account''s
        inventory start date, along with its settlement data. These historical records
        predate inventory tracking and will never have matching settlement reports.
        Run `GET .../purge-pre-start/preflight` first to review exactly which groups
        will be removed.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        The deletion happens asynchronously after this request returns; the response
        only confirms that the background job was dispatched (no job id is returned).


        Body fields:

        - `confirmation` (required, string) - must be exactly `PURGE`.

        - `integration_instance_ids` (optional, array of integers or comma-separated
        string) - scopes the purge to specific Amazon integration instances.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                confirmation:
                  type: string
                integration_instance_ids:
                  type: array
                  items:
                    type: integer
              example:
                confirmation: PURGE
                integration_instance_ids:
                - 1
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      message:
                        type: string
                  status:
                    type: string
                example:
                  data:
                    message: Purge job has been dispatched. Settlement transactions
                      will be deleted in the background.
                  status: success
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      confirmation:
                        type: array
                        items:
                          type: string
                  status:
                    type: string
                example:
                  message: The confirmation field is required.
                  errors:
                    confirmation:
                    - The confirmation field is required.
                  status: failure
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-amazon-unified-financial-event-groups-purge-pre-start
  /api/amazon/unified/reports:
    get:
      tags:
      - Amazon
      summary: List Reports
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        example: '1'
        description: Page number (default 1).
      - name: per_page
        in: query
        schema:
          type: integer
        example: '10'
        description: Results per page (default 10).
      - name: integration_instance_ids
        in: query
        schema:
          type: string
        description: Comma-separated integration instance IDs to scope the query.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      description: 'List Reports


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      operationId: get-api-amazon-unified-reports
  /api/amazon/unified/reports/{reportId}:
    get:
      tags:
      - Amazon
      summary: Get Report
      parameters:
      - name: reportId
        in: path
        schema:
          type: string
        required: true
        description: The report ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      description: 'Get Report


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      operationId: get-api-amazon-unified-reports-reportid
  /api/amazon/unified/reports/statistics:
    get:
      tags:
      - Amazon
      summary: Get Report Statistics
      parameters:
      - name: integration_instance_ids
        in: query
        schema:
          type: string
        description: Comma-separated integration instance IDs to scope the query.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      description: 'Get Report Statistics


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      operationId: get-api-amazon-unified-reports-statistics
  /api/amazon/unified/reports/available-types:
    get:
      tags:
      - Amazon
      summary: Get Available Report Types
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      description: 'Get Available Report Types


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      operationId: get-api-amazon-unified-reports-available-types
  /api/amazon/unified/reports/{reportId}/process:
    post:
      tags:
      - Amazon
      summary: Process Report
      requestBody:
        content: {}
      parameters:
      - name: reportId
        in: path
        schema:
          type: string
        required: true
        description: The report ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      description: 'Process Report


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      operationId: post-api-amazon-unified-reports-reportid-process
  /api/amazon/unified/reports/{reportId}/request-raw-data-download:
    post:
      tags:
      - Amazon
      summary: Request Raw Data Download
      description: 'Queues an asynchronous a background job to fetch the report''s
        raw data from the SP-API. The job broadcasts an `amazon.report-raw-data.ready`
        event (status `ready` or `failed`) on the requesting user''s private channel
        (`App.Models.User.{tenantId}.{userId}`) when it finishes, so the SPA can refetch
        the raw data without polling. Returns immediately with 200 once the job is
        dispatched, or 404 if the report does not exist.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters:
      - name: reportId
        in: path
        schema:
          type: string
        required: true
        description: ID of the Amazon report to download raw data for
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                example:
                  success: true
                  message: Raw data download started. This page will update automatically
                    when it is ready.
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                example:
                  success: false
                  message: Report not found
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-amazon-unified-reports-reportid-request-raw-data-download
  /api/amazon/unified/reports/{reportId}/raw-data:
    get:
      tags:
      - Amazon
      summary: Get Report Raw Data
      description: 'Returns the raw file content of a downloaded Amazon SP-API report
        as a string, together with its stored filename. Amazon reports are typically
        tab-separated (TSV) text.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        The raw file must already have been downloaded from Amazon (see `POST .../reports/:reportId/request-raw-data-download`).
        Returns 404 when the report does not exist, the file has not been downloaded
        yet, or the file exceeds the 50 MB safety limit for in-memory loading.'
      parameters:
      - name: reportId
        in: path
        schema:
          type: integer
        required: true
        description: The SKU.io internal report record ID (not the Amazon report ID).
        example: '512'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      raw_data:
                        type: string
                      filename:
                        type: string
                example:
                  success: true
                  message: Success
                  data:
                    raw_data: "Date\tFNSKU\tASIN\tMSKU\tTitle\tEvent Type\tReference\
                      \ ID\tQuantity\tFulfillment Center\tDisposition\tReason\tCountry\n\
                      2026-05-14\tX002QK7F5T\tB08XYZL4M2\tWIDGET-BLK-12\tWidget Pro\
                      \ 12-Pack, Black\tShipments\tDnMKQ8pnN\t-2\tONT8\tSELLABLE\t\
                      \tUS"
                    filename: 1466394018495.tsv
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                example:
                  success: false
                  message: Raw data not available for this report
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-amazon-unified-reports-reportid-raw-data
  /api/amazon/unified/reports/{reportId}/associated-data:
    get:
      tags:
      - Amazon
      summary: List Report Associated Data
      description: 'Returns the paginated data rows that were imported into SKU.io
        from a specific Amazon SP-API report. Currently supported for ledger-based
        report types (inventory ledger detail, FBA inventory, removal orders and removal
        shipments reports); for those the response contains the Amazon inventory ledger
        entries created from the report, sorted by event date descending. Report types
        without associated data return 422.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Query parameters:

        - `page` (optional, default 1) and `per_page` (optional, default 15) - standard
        pagination.

        - `filter[search]` (optional) - matches ledger ID exactly, or event type /
        reference ID / fulfillment center partially.

        - `filter[date_from]` / `filter[date_to]` (optional) - event date range, format
        m/d/Y; invalid dates are ignored.


        Each row includes reconciliation state (`reconciled_quantity`, `unreconciled_quantity`,
        `status` of `reconciled` or `unreconciled`) and FIFO costing fields (`fifo_id`,
        `cogs`, `extended_cogs`) when a FIFO layer is linked.'
      parameters:
      - name: reportId
        in: path
        schema:
          type: integer
        required: true
        description: The SKU.io internal report record ID (not the Amazon report ID).
        example: '512'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        checksum:
                          type: string
                        integration_instance_id:
                          type: integer
                        amazon_product_id:
                          type: integer
                        amazon_report_id:
                          type: integer
                        errorLog:
                          type: string
                          nullable: true
                        date:
                          type: string
                        blocked_by_ledger_id:
                          type: string
                          nullable: true
                        event_datetime:
                          type: string
                        fnsku:
                          type: string
                        country:
                          type: string
                        disposition:
                          type: string
                        asin:
                          type: string
                        msku:
                          type: string
                        title:
                          type: string
                        event_type:
                          type: string
                        reference_id:
                          type: string
                        quantity:
                          type: integer
                        fulfillment_center:
                          type: string
                        reason:
                          type: string
                          nullable: true
                        reconciled_quantity:
                          type: integer
                        unreconciled_quantity:
                          type: integer
                        last_reconciliation_attempted_at:
                          type: string
                        reconciled_at:
                          type: string
                        status:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                        fnsku_product_id:
                          type: integer
                        fifo_id:
                          type: integer
                        cogs:
                          type: number
                        extended_cogs:
                          type: number
                        error_count:
                          type: integer
                        report_line_number:
                          type: integer
                        is_from_reattempted_report:
                          type: boolean
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                    items:
                      type: object
                      properties:
                        url:
                          type: string
                          nullable: true
                        label:
                          type: string
                        active:
                          type: boolean
                  next_page_url:
                    type: string
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 90211
                    checksum: c0b7d1f2a3e45f6890ab12cd34ef5678
                    integration_instance_id: 3
                    amazon_product_id: 4521
                    amazon_report_id: 512
                    errorLog: null
                    date: '2026-05-14'
                    blocked_by_ledger_id: null
                    event_datetime: '2026-05-14T10:22:00.000000Z'
                    fnsku: X002QK7F5T
                    country: US
                    disposition: SELLABLE
                    asin: B08XYZL4M2
                    msku: WIDGET-BLK-12
                    title: Widget Pro 12-Pack, Black
                    event_type: Shipments
                    reference_id: DnMKQ8pnN
                    quantity: -2
                    fulfillment_center: ONT8
                    reason: null
                    reconciled_quantity: 2
                    unreconciled_quantity: 0
                    last_reconciliation_attempted_at: '2026-05-15T02:10:11.000000Z'
                    reconciled_at: '2026-05-15T02:10:11.000000Z'
                    status: reconciled
                    created_at: '2026-05-15T02:00:41.000000Z'
                    updated_at: '2026-05-15T02:10:11.000000Z'
                    fnsku_product_id: 55
                    fifo_id: 7742
                    cogs: 4.25
                    extended_cogs: 8.5
                    error_count: 0
                    report_line_number: 118
                    is_from_reattempted_report: false
                  first_page_url: '{{protocol}}://{{domain}}/api/amazon/unified/reports/512/associated-data?page=1'
                  from: 1
                  last_page: 23
                  last_page_url: '{{protocol}}://{{domain}}/api/amazon/unified/reports/512/associated-data?page=23'
                  links:
                  - url: null
                    label: '&laquo; Previous'
                    active: false
                  - url: '{{protocol}}://{{domain}}/api/amazon/unified/reports/512/associated-data?page=1'
                    label: '1'
                    active: true
                  - url: '{{protocol}}://{{domain}}/api/amazon/unified/reports/512/associated-data?page=2'
                    label: '2'
                    active: false
                  - url: '{{protocol}}://{{domain}}/api/amazon/unified/reports/512/associated-data?page=2'
                    label: Next &raquo;
                    active: false
                  next_page_url: '{{protocol}}://{{domain}}/api/amazon/unified/reports/512/associated-data?page=2'
                  path: '{{protocol}}://{{domain}}/api/amazon/unified/reports/512/associated-data'
                  per_page: 15
                  prev_page_url: null
                  to: 15
                  total: 341
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Associated data not available for this report type
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-unified-reports-reportid-associated-data
  /api/amazon/unified/reports/{reportId}/status:
    get:
      tags:
      - Amazon
      summary: Get Report Status
      description: 'Returns the current lifecycle status of an Amazon SP-API report
        record for progress monitoring/polling.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Side effect: before responding, SKU.io attempts to sync the report record
        from Amazon so the returned state is current (best-effort - if the Amazon
        call fails, the stored state is returned).


        Response `data` fields:

        - `status` - one of `pending`, `in_progress`, `retrying`, `downloading`, `processing`,
        `completed`, `cancelled`, `failed`.

        - `message` - human-readable progress message (includes the Amazon report
        ID when assigned).

        - `progress` - 0-100 progress indicator.

        - `processing_status` - raw Amazon processing status (`IN_QUEUE`, `IN_PROGRESS`,
        `DONE`, `CANCELLED`, `FATAL`, or the internal `RETRY`).

        - `has_raw_data` - whether the report file has been downloaded.

        - `is_processed` - whether the report data has been imported into SKU.io.

        - `created_time`, `processed_at` - ISO 8601 timestamps (nullable).'
      parameters:
      - name: reportId
        in: path
        schema:
          type: integer
        required: true
        description: The SKU.io internal report record ID (not the Amazon report ID).
        example: '512'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      status:
                        type: string
                      message:
                        type: string
                      progress:
                        type: integer
                      report_id:
                        type: integer
                      processing_status:
                        type: string
                      has_raw_data:
                        type: boolean
                      is_processed:
                        type: boolean
                      created_time:
                        type: string
                      processed_at:
                        type: string
                        nullable: true
                example:
                  success: true
                  message: Success
                  data:
                    status: in_progress
                    message: 'Amazon is generating the report... (Report ID: 1466394018495)'
                    progress: 25
                    report_id: 512
                    processing_status: IN_PROGRESS
                    has_raw_data: false
                    is_processed: false
                    created_time: '2026-06-02T04:15:11+00:00'
                    processed_at: null
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                example:
                  success: false
                  message: Report not found
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-amazon-unified-reports-reportid-status
  /api/amazon/unified/reports/{reportId}/clone:
    post:
      tags:
      - Amazon
      summary: Clone Report
      description: 'Clones an existing Amazon SP-API report record: immediately requests
        a NEW report from Amazon with the same report type, data date range, marketplaces
        and options as the original, but with duplicate protection enabled (`disallow_duplicates`
        = true, so rows already imported from earlier reports are skipped when the
        clone is processed).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        This calls the Amazon SP-API synchronously to create the report request; the
        report itself is then generated by Amazon asynchronously - poll `GET .../reports/:reportId/status`
        on the returned record to track it.


        No request body. Returns the newly created report record. Returns 404 when
        the source report does not exist and 400 when Amazon rejects the request (for
        example when a report of the same type is already in progress).'
      requestBody:
        content: {}
      parameters:
      - name: reportId
        in: path
        schema:
          type: integer
        required: true
        description: The SKU.io internal report record ID (not the Amazon report ID).
        example: '512'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      integration_instance_id:
                        type: integer
                      reportType:
                        type: string
                      dataStartTime:
                        type: string
                      dataEndTime:
                        type: string
                      marketplaceIds:
                        type: array
                        items:
                          type: string
                      options:
                        type: string
                        nullable: true
                      reportId:
                        type: string
                      processingStatus:
                        type: string
                      createdTime:
                        type: string
                      disallow_duplicates:
                        type: boolean
                      updated_at:
                        type: string
                      created_at:
                        type: string
                      id:
                        type: integer
                example:
                  success: true
                  message: Report cloned successfully
                  data:
                    integration_instance_id: 3
                    reportType: GET_LEDGER_DETAIL_VIEW_DATA
                    dataStartTime: '2026-05-01T00:00:00.000000Z'
                    dataEndTime: '2026-05-31T23:59:59.000000Z'
                    marketplaceIds:
                    - ATVPDKIKX0DER
                    options: null
                    reportId: '1466512018622'
                    processingStatus: IN_QUEUE
                    createdTime: '2026-06-03T09:41:52.000000Z'
                    disallow_duplicates: true
                    updated_at: '2026-06-03T09:41:52.000000Z'
                    created_at: '2026-06-03T09:41:52.000000Z'
                    id: 519
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                example:
                  success: false
                  message: 'Failed to clone report: A report of this type is already
                    in progress.'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-amazon-unified-reports-reportid-clone
  /api/amazon/unified/reports/{reportId}/cancel:
    post:
      tags:
      - Amazon
      summary: Cancel Report
      description: 'Cancels an in-progress Amazon SP-API report record in SKU.io by
        marking its processing status as `CANCELLED`. This is a local status change
        only - it does not cancel the report request on Amazon''s side. Use it to
        unblock creating a new report request of the same type when a previous request
        is stuck.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        No request body. Returns the updated report record.'
      requestBody:
        content: {}
      parameters:
      - name: reportId
        in: path
        schema:
          type: integer
        required: true
        description: The SKU.io internal report record ID (not the Amazon report ID).
        example: '512'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      reportId:
                        type: string
                      reportType:
                        type: string
                      dataStartTime:
                        type: string
                      dataEndTime:
                        type: string
                      options:
                        type: string
                        nullable: true
                      reportScheduledId:
                        type: string
                        nullable: true
                      createdTime:
                        type: string
                      processingStatus:
                        type: string
                      processingStartTime:
                        type: string
                        nullable: true
                      processingEndTime:
                        type: string
                        nullable: true
                      marketplaceIds:
                        type: array
                        items:
                          type: string
                      reportDocumentId:
                        type: string
                        nullable: true
                      filename:
                        type: string
                        nullable: true
                      processed_at:
                        type: string
                        nullable: true
                      disallow_duplicates:
                        type: boolean
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  success: true
                  message: Report cancelled
                  data:
                    id: 512
                    integration_instance_id: 3
                    reportId: '1466394018495'
                    reportType: GET_LEDGER_DETAIL_VIEW_DATA
                    dataStartTime: '2026-05-01T00:00:00.000000Z'
                    dataEndTime: '2026-05-31T23:59:59.000000Z'
                    options: null
                    reportScheduledId: null
                    createdTime: '2026-06-02T04:15:11.000000Z'
                    processingStatus: CANCELLED
                    processingStartTime: null
                    processingEndTime: null
                    marketplaceIds:
                    - ATVPDKIKX0DER
                    reportDocumentId: null
                    filename: null
                    processed_at: null
                    disallow_duplicates: false
                    created_at: '2026-06-02T04:15:11.000000Z'
                    updated_at: '2026-06-03T10:02:07.000000Z'
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                example:
                  success: false
                  message: Report not found
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-amazon-unified-reports-reportid-cancel
  /api/amazon/unified/settlement-data:
    get:
      tags:
      - Amazon
      summary: List Settlement Data
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        example: '1'
        description: Page number (default 1).
      - name: per_page
        in: query
        schema:
          type: integer
        example: '10'
        description: Results per page (default 10).
      - name: search
        in: query
        schema:
          type: string
        description: Free-text search across the resource’s searchable fields.
      - name: integration_instance_ids
        in: query
        schema:
          type: string
        description: Comma-separated integration instance IDs to scope the query.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      description: 'List Settlement Data


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      operationId: get-api-amazon-unified-settlement-data
  /api/amazon/unified/settlement-data/lookups:
    get:
      tags:
      - Amazon
      summary: Get Settlement Data Lookups
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      description: 'Get Settlement Data Lookups


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      operationId: get-api-amazon-unified-settlement-data-lookups
  /api/amazon/unified/settlement-type-mappings:
    get:
      tags:
      - Amazon
      summary: List Type Mappings
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        example: '1'
        description: Page number (default 1).
      - name: per_page
        in: query
        schema:
          type: integer
        example: '10'
        description: Results per page (default 10).
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      description: 'List Type Mappings


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      operationId: get-api-amazon-unified-settlement-type-mappings
  /api/amazon/unified/settlement-type-mappings/lookups:
    get:
      tags:
      - Amazon
      summary: Get Type Mapping Lookups
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      description: 'Get Type Mapping Lookups


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      operationId: get-api-amazon-unified-settlement-type-mappings-lookups
  /api/amazon/unified/settlement-type-mappings/bulk-assign:
    put:
      tags:
      - Amazon
      summary: Bulk Assign Type Mappings
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                mappings:
                  type: array
              example:
                mappings: []
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      description: 'Bulk Assign Type Mappings


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      operationId: put-api-amazon-unified-settlement-type-mappings-bulk-assign
  /api/amazon/unified/settlement-type-mappings/export:
    get:
      tags:
      - Amazon
      summary: Export Type Mappings
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      description: 'Export Type Mappings


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      operationId: get-api-amazon-unified-settlement-type-mappings-export
  /api/amazon/unified/settlement-type-mappings/import:
    post:
      tags:
      - Amazon
      summary: Import Type Mappings
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                file:
                  type: string
                  format: binary
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      description: 'Import Type Mappings


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      operationId: post-api-amazon-unified-settlement-type-mappings-import
  /api/amazon/unified/settlement-type-mappings/instances:
    get:
      tags:
      - Amazon
      summary: List Settlement Type Mapping Instances by Financial Code
      description: 'Returns the resolved settlement type mapping for a single financial
        code, per Amazon integration instance. Settlement type mappings map Amazon
        settlement fee/transaction types to nominal codes (and settlement mapping
        groups) used when generating accounting transactions; overrides are per-instance
        exceptions to the global mapping.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        One row is returned per instance with the EFFECTIVE values - the per-instance
        override when one exists, otherwise the global default:

        - `integration_instance` - `{id, name}` of the Amazon integration instance.

        - `nominalCode` - resolved nominal code `{id, code, name}` or null when unmapped.

        - `mappingGroup` - resolved settlement mapping group `{id, name, document_type}`
        (document_type is `invoice` or `bill`) or null.

        - `is_override` - true when the row comes from a per-instance override rather
        than the global mapping.

        - `override_id` - the override record ID (use it with `DELETE .../overrides/:id`),
        or null.


        Query parameters:

        - `financial_code` (required, string).

        - `integration_instance_ids[]` (optional, array of integers) - limit to specific
        instances.'
      parameters:
      - name: financial_code
        in: query
        schema:
          type: string
        description: 'Required. The settlement financial code to resolve, in the format
          "{transaction_type}: {amount_type} - {amount_description}" (e.g. "Order:
          ItemFees - Commission").'
        example: 'Order: ItemFees - Commission'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        integration_instance:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        nominalCode:
                          type: object
                          properties:
                            id:
                              type: integer
                            code:
                              type: string
                            name:
                              type: string
                        mappingGroup:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            document_type:
                              type: string
                        is_override:
                          type: boolean
                        override_id:
                          type: string
                          nullable: true
                example:
                  data:
                  - integration_instance:
                      id: 1
                      name: Amazon US
                    nominalCode:
                      id: 45
                      code: '4000'
                      name: Amazon Sales
                    mappingGroup:
                      id: 3
                      name: Sales Revenue
                      document_type: invoice
                    is_override: false
                    override_id: null
                  - integration_instance:
                      id: 3
                      name: Amazon CA
                    nominalCode:
                      id: 61
                      code: '5015'
                      name: Amazon Commission Fees
                    mappingGroup:
                      id: 4
                      name: Amazon Fees
                      document_type: bill
                    is_override: true
                    override_id: 812
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      financial_code:
                        type: array
                        items:
                          type: string
                  status:
                    type: string
                example:
                  message: The financial code field is required.
                  errors:
                    financial_code:
                    - The financial code field is required.
                  status: failure
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-amazon-unified-settlement-type-mappings-instances
  /api/amazon/unified/settlement-type-mappings/overrides:
    post:
      tags:
      - Amazon
      summary: Create Settlement Type Mapping Override
      description: 'Creates a per-instance override for a settlement financial code,
        replacing the global mapping for that Amazon integration instance only. If
        an override already exists for the same instance and financial code, it is
        updated in place (upsert). The global mapping row for the financial code must
        already exist - otherwise a 404 is returned.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Only the keys present in the request body are applied to the override, so
        you can override just the nominal code, just the mapping group, or both.


        Body fields:

        - `integration_instance_id` (required, integer) - the Amazon integration instance
        the override applies to. Must exist.

        - `financial_code` (required, string) - format "{transaction_type}: {amount_type}
        - {amount_description}".

        - `nominal_code_id` (optional, integer or null) - nominal code to use for
        this instance. Must exist when provided.

        - `amazon_settlement_mapping_group_id` (optional, integer or null) - settlement
        mapping group to route this code to for this instance. Must exist when provided.


        Returns the created/updated override with its resolved `nominalCode` and `mappingGroup`.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                integration_instance_id:
                  type: integer
                financial_code:
                  type: string
                nominal_code_id:
                  type: integer
                amazon_settlement_mapping_group_id:
                  type: integer
              example:
                integration_instance_id: 3
                financial_code: 'Order: ItemFees - Commission'
                nominal_code_id: 61
                amazon_settlement_mapping_group_id: 4
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      transaction_type:
                        type: string
                      amount_type:
                        type: string
                      amount_description:
                        type: string
                      financial_code:
                        type: string
                      typical_amount_sign:
                        type: string
                      amazon_settlement_mapping_group_id:
                        type: integer
                      nominalCode:
                        type: object
                        properties:
                          id:
                            type: integer
                          code:
                            type: string
                          name:
                            type: string
                      mappingGroup:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          document_type:
                            type: string
                      is_override:
                        type: boolean
                      created_at:
                        type: string
                      updated_at:
                        type: string
                  message:
                    type: string
                  status:
                    type: string
                example:
                  data:
                    id: 812
                    transaction_type: Order
                    amount_type: ItemFees
                    amount_description: Commission
                    financial_code: 'Order: ItemFees - Commission'
                    typical_amount_sign: '-'
                    amazon_settlement_mapping_group_id: 4
                    nominalCode:
                      id: 61
                      code: '5015'
                      name: Amazon Commission Fees
                    mappingGroup:
                      id: 4
                      name: Amazon Fees
                      document_type: bill
                    is_override: false
                    created_at: '2026-06-12T18:04:31.000000Z'
                    updated_at: '2026-06-12T18:04:31.000000Z'
                  message: Override created successfully.
                  status: success
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      integration_instance_id:
                        type: array
                        items:
                          type: string
                  status:
                    type: string
                example:
                  message: The integration instance id field is required.
                  errors:
                    integration_instance_id:
                    - The integration instance id field is required.
                  status: failure
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-amazon-unified-settlement-type-mappings-overrides
  /api/amazon/unified/settlement-type-mappings/overrides/{id}:
    delete:
      tags:
      - Amazon
      summary: Delete Settlement Type Mapping Override
      description: 'Deletes a per-instance settlement type mapping override. The affected
        Amazon integration instance falls back to the global mapping for that financial
        code. Only override records (rows tied to an integration instance) can be
        deleted - passing the ID of a global mapping returns 404.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: id
        in: path
        schema:
          type: integer
        required: true
        description: The override record ID (see override_id from the instances endpoint).
          Must be a per-instance override; global mappings cannot be deleted here.
        example: '812'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  status:
                    type: string
                example:
                  message: Override deleted successfully.
                  status: success
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: object
                    properties:
                      Modules\Amazon\Entities\AmazonReportSettlementTypeMapping:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: array
                  status:
                    type: string
                  message:
                    type: string
                example:
                  errors:
                    Modules\Amazon\Entities\AmazonReportSettlementTypeMapping:
                    - message: No query results for model [Modules\Amazon\Entities\AmazonReportSettlementTypeMapping].
                      code: NotFound
                      data: []
                  status: failure
                  message: No query results for model [Modules\Amazon\Entities\AmazonReportSettlementTypeMapping].
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: delete-api-amazon-unified-settlement-type-mappings-overrides-id
  /api/amazon/unified/settlement-fallback-settings:
    get:
      tags:
      - Amazon
      summary: Get Fallback Settings
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      description: 'Get Fallback Settings


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      operationId: get-api-amazon-unified-settlement-fallback-settings
    put:
      tags:
      - Amazon
      summary: Update Fallback Settings
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties: {}
              example: {}
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      description: 'Update Fallback Settings


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      operationId: put-api-amazon-unified-settlement-fallback-settings
  /api/amazon/unified/settlement-mapping-groups:
    get:
      tags:
      - Amazon
      summary: List Mapping Groups
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      description: 'List Mapping Groups


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      operationId: get-api-amazon-unified-settlement-mapping-groups
    post:
      tags:
      - Amazon
      summary: Create Mapping Group
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
              example:
                name: ''
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      description: 'Create Mapping Group


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      operationId: post-api-amazon-unified-settlement-mapping-groups
  /api/amazon/unified/settlement-mapping-groups/{settlementMappingGroup}:
    put:
      tags:
      - Amazon
      summary: Update Mapping Group
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
              example:
                name: ''
      parameters:
      - name: settlementMappingGroup
        in: path
        schema:
          type: string
        required: true
        description: The settlement mapping group ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      description: 'Update Mapping Group


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      operationId: put-api-amazon-unified-settlement-mapping-groups-settlementmappinggroup
    delete:
      tags:
      - Amazon
      summary: Delete Mapping Group
      parameters:
      - name: settlementMappingGroup
        in: path
        schema:
          type: string
        required: true
        description: The settlement mapping group ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      description: 'Delete Mapping Group


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      operationId: delete-api-amazon-unified-settlement-mapping-groups-settlementmappinggroup
  /api/amazon/unified/settlement-mapping-groups/reorder:
    put:
      tags:
      - Amazon
      summary: Reorder Settlement Mapping Groups
      description: 'Reorders the global Amazon settlement mapping groups. Mapping
        groups control how settlement lines are grouped into generated accounting
        documents (each group produces one invoice or bill per settlement), and their
        order determines display/processing order.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Body fields:

        - `ids` (required, array of integers, min 1) - settlement mapping group IDs
        in the desired order. Each ID must exist; the new sort order is assigned from
        the array position.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 3
                - 4
                - 7
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  status:
                    type: string
                example:
                  message: Groups reordered successfully.
                  status: success
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      ids:
                        type: array
                        items:
                          type: string
                  status:
                    type: string
                example:
                  message: The ids field is required.
                  errors:
                    ids:
                    - The ids field is required.
                  status: failure
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: put-api-amazon-unified-settlement-mapping-groups-reorder
  /api/amazon/unified/awd/initial-inventory/status:
    get:
      tags:
      - Amazon
      summary: Get AWD initial inventory status
      description: 'Returns the AWD initial inventory setup status for each NA-region
        Amazon integration instance, including the as-of date (day before fba_inventory_tracking_start_date).
        The as-of date is converted from UTC to the app timezone for display.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        integration_instance_id:
                          type: integer
                        integration_instance_name:
                          type: string
                        awd_sync_enabled:
                          type: boolean
                        awd_initial_inventory_imported:
                          type: boolean
                        awd_initial_inventory_confirmed_no_inventory:
                          type: boolean
                        is_awd_sync_allowed:
                          type: boolean
                        awd_access_denied:
                          type: boolean
                        as_of_date:
                          type: string
                        as_of_date_formatted:
                          type: string
                        fba_inventory_tracking_start_date:
                          type: string
                        fba_inventory_tracking_start_date_formatted:
                          type: string
                example:
                  data:
                  - integration_instance_id: 1
                    integration_instance_name: Amazon US
                    awd_sync_enabled: true
                    awd_initial_inventory_imported: true
                    awd_initial_inventory_confirmed_no_inventory: false
                    is_awd_sync_allowed: true
                    awd_access_denied: false
                    as_of_date: '2024-04-21'
                    as_of_date_formatted: Apr 21, 2024
                    fba_inventory_tracking_start_date: '2024-04-22'
                    fba_inventory_tracking_start_date_formatted: Apr 22, 2024
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-amazon-unified-awd-initial-inventory-status
  /api/amazon/unified/awd/initial-inventory/summary:
    get:
      tags:
      - Amazon
      summary: Get AWD initial inventory summary
      description: 'Returns aggregated AWD initial inventory summary statistics (counts,
        totals, unique FNSKUs/countries) for each integration instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        integration_instance_id:
                          type: integer
                        integration_instance_name:
                          type: string
                        total_entries:
                          type: integer
                        total_units:
                          type: integer
                        reconciled_entries:
                          type: integer
                        unreconciled_entries:
                          type: integer
                        unique_fnskus:
                          type: integer
                        unique_countries:
                          type: integer
                example:
                  data:
                  - integration_instance_id: 1
                    integration_instance_name: Amazon US
                    total_entries: 124
                    total_units: 8420
                    reconciled_entries: 110
                    unreconciled_entries: 14
                    unique_fnskus: 95
                    unique_countries: 1
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-amazon-unified-awd-initial-inventory-summary
  /api/amazon/unified/awd/shipments:
    get:
      tags:
      - Amazon
      summary: List AWD shipments (paginated)
      description: 'Paginated AWD shipments across integration instances. Eager loads
        integrationInstance and items, and calls loadUnitQuantitiesForItems() per
        shipment.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        integration_instance_name:
                          type: string
                        shipment_id:
                          type: string
                        shipment_status:
                          type: string
                        order_id:
                          type: string
                        items:
                          type: array
                        sku_link:
                          type: string
                          nullable: true
                        pending_inbound:
                          type: string
                          nullable: true
                        destination_country:
                          type: string
                        destination_name:
                          type: string
                        origin_name:
                          type: string
                        origin_warehouse_id:
                          type: string
                          nullable: true
                        origin_supplier_id:
                          type: integer
                        origin_warehouse_name:
                          type: string
                          nullable: true
                        origin_supplier_name:
                          type: string
                        origin_address:
                          type: object
                          properties:
                            name:
                              type: string
                            addressLine1:
                              type: string
                            city:
                              type: string
                            stateOrRegion:
                              type: string
                            countryCode:
                              type: string
                            postalCode:
                              type: string
                        destination_address:
                          type: object
                          properties:
                            name:
                              type: string
                            addressLine1:
                              type: string
                            city:
                              type: string
                            stateOrRegion:
                              type: string
                            countryCode:
                              type: string
                            postalCode:
                              type: string
                        carrier_code:
                          type: string
                        tracking_id:
                          type: string
                        external_reference_id:
                          type: string
                          nullable: true
                        warehouse_reference_id:
                          type: string
                          nullable: true
                        ship_by_date:
                          type: string
                        api_created_at:
                          type: string
                        api_updated_at:
                          type: string
                        details_fetched_at:
                          type: string
                        received_quantity:
                          type: integer
                        expected_quantity:
                          type: integer
                        discrepancy_quantity:
                          type: integer
                        received_quantity_details:
                          type: array
                        expected_quantity_details:
                          type: array
                        discrepancy_quantity_details:
                          type: array
                        shipment_container_quantities:
                          type: array
                        shipment_container_details:
                          type: array
                        shipment_charges:
                          type: array
                        is_active:
                          type: boolean
                        is_completed:
                          type: boolean
                        is_cancelled:
                          type: boolean
                        is_processable:
                          type: boolean
                        is_processed:
                          type: boolean
                        needs_detail_sync:
                          type: boolean
                        error_log:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - id: 1001
                    integration_instance_id: 1
                    integration_instance_name: Amazon US
                    shipment_id: FBA15ABCD123
                    shipment_status: SHIPPED
                    order_id: ORD-99
                    items: []
                    sku_link: null
                    pending_inbound: null
                    destination_country: US
                    destination_name: Amazon Warehouse ABE2
                    origin_name: Supplier ACME
                    origin_warehouse_id: null
                    origin_supplier_id: 22
                    origin_warehouse_name: null
                    origin_supplier_name: ACME Co.
                    origin_address:
                      name: Supplier ACME
                      addressLine1: 123 Main St
                      city: Reno
                      stateOrRegion: NV
                      countryCode: US
                      postalCode: '89501'
                    destination_address:
                      name: Amazon Warehouse ABE2
                      addressLine1: 500 McCarthy Dr
                      city: Lehigh Valley
                      stateOrRegion: PA
                      countryCode: US
                      postalCode: '18031'
                    carrier_code: UPS
                    tracking_id: 1Z999AA10123456784
                    external_reference_id: null
                    warehouse_reference_id: null
                    ship_by_date: '2024-05-15'
                    api_created_at: '2024-04-22T07:00:00Z'
                    api_updated_at: '2024-04-25T07:00:00Z'
                    details_fetched_at: '2024-04-25T08:00:00.000000Z'
                    received_quantity: 0
                    expected_quantity: 100
                    discrepancy_quantity: 0
                    received_quantity_details: []
                    expected_quantity_details: []
                    discrepancy_quantity_details: []
                    shipment_container_quantities: []
                    shipment_container_details: []
                    shipment_charges: []
                    is_active: true
                    is_completed: false
                    is_cancelled: false
                    is_processable: true
                    is_processed: false
                    needs_detail_sync: false
                    error_log: null
                    created_at: '2024-04-22T08:00:00.000000Z'
                    updated_at: '2024-04-25T08:00:00.000000Z'
                  current_page: 1
                  last_page: 5
                  per_page: 10
                  total: 47
                  from: 1
                  to: 10
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-amazon-unified-awd-shipments
    delete:
      tags:
      - Amazon
      summary: Delete AWD shipments
      description: 'Deletes selected AWD shipments by IDs. Same validation pattern
        as process/unprocess: ids array OR apply_to_all + filters.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      deleted:
                        type: integer
                example:
                  message: Deleted 2 shipment(s)
                  data:
                    deleted: 2
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: delete-api-amazon-unified-awd-shipments
  /api/amazon/unified/awd/shipments/{id}:
    get:
      tags:
      - Amazon
      summary: Show AWD shipment
      description: 'Returns a single AWD shipment with items, origin warehouse, origin
        supplier, integrationInstance, and full quantity/inventory data eager-loaded.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      integration_instance_name:
                        type: string
                      shipment_id:
                        type: string
                      shipment_status:
                        type: string
                      order_id:
                        type: string
                      items:
                        type: array
                      sku_link:
                        type: string
                        nullable: true
                      pending_inbound:
                        type: string
                        nullable: true
                      destination_country:
                        type: string
                      destination_name:
                        type: string
                      origin_name:
                        type: string
                      origin_warehouse_id:
                        type: string
                        nullable: true
                      origin_supplier_id:
                        type: integer
                      origin_warehouse_name:
                        type: string
                        nullable: true
                      origin_supplier_name:
                        type: string
                      origin_address:
                        type: object
                        properties: {}
                      destination_address:
                        type: object
                        properties: {}
                      carrier_code:
                        type: string
                      tracking_id:
                        type: string
                      external_reference_id:
                        type: string
                        nullable: true
                      warehouse_reference_id:
                        type: string
                        nullable: true
                      ship_by_date:
                        type: string
                      api_created_at:
                        type: string
                      api_updated_at:
                        type: string
                      details_fetched_at:
                        type: string
                      received_quantity:
                        type: integer
                      expected_quantity:
                        type: integer
                      discrepancy_quantity:
                        type: integer
                      received_quantity_details:
                        type: array
                      expected_quantity_details:
                        type: array
                      discrepancy_quantity_details:
                        type: array
                      shipment_container_quantities:
                        type: array
                      shipment_container_details:
                        type: array
                      shipment_charges:
                        type: array
                      is_active:
                        type: boolean
                      is_completed:
                        type: boolean
                      is_cancelled:
                        type: boolean
                      is_processable:
                        type: boolean
                      is_processed:
                        type: boolean
                      needs_detail_sync:
                        type: boolean
                      error_log:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 1001
                    integration_instance_id: 1
                    integration_instance_name: Amazon US
                    shipment_id: FBA15ABCD123
                    shipment_status: SHIPPED
                    order_id: ORD-99
                    items: []
                    sku_link: null
                    pending_inbound: null
                    destination_country: US
                    destination_name: Amazon Warehouse ABE2
                    origin_name: Supplier ACME
                    origin_warehouse_id: null
                    origin_supplier_id: 22
                    origin_warehouse_name: null
                    origin_supplier_name: ACME Co.
                    origin_address: {}
                    destination_address: {}
                    carrier_code: UPS
                    tracking_id: 1Z999AA10123456784
                    external_reference_id: null
                    warehouse_reference_id: null
                    ship_by_date: '2024-05-15'
                    api_created_at: '2024-04-22T07:00:00Z'
                    api_updated_at: '2024-04-25T07:00:00Z'
                    details_fetched_at: '2024-04-25T08:00:00.000000Z'
                    received_quantity: 0
                    expected_quantity: 100
                    discrepancy_quantity: 0
                    received_quantity_details: []
                    expected_quantity_details: []
                    discrepancy_quantity_details: []
                    shipment_container_quantities: []
                    shipment_container_details: []
                    shipment_charges: []
                    is_active: true
                    is_completed: false
                    is_cancelled: false
                    is_processable: true
                    is_processed: false
                    needs_detail_sync: false
                    error_log: null
                    created_at: '2024-04-22T08:00:00.000000Z'
                    updated_at: '2024-04-25T08:00:00.000000Z'
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Shipment not found
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-amazon-unified-awd-shipments-id
  /api/amazon/unified/awd/ledgers:
    get:
      tags:
      - Amazon
      summary: List AWD ledgers (paginated)
      description: 'Paginated AWD ledger entries across integration instances. Eager-loads
        integrationInstance, fnskuProduct.product, fifoLayer, fifoConsumptions, salesOrderLines.salesOrder/product,
        warehouseTransferLines.warehouseTransfer, fbaWarehouseTransfer.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        integration_instance_name:
                          type: string
                        checksum:
                          type: string
                        date:
                          type: string
                        fnsku:
                          type: string
                        asin:
                          type: string
                        msku:
                          type: string
                        title:
                          type: string
                        event_type:
                          type: string
                        reference_id:
                          type: string
                        quantity:
                          type: integer
                        fulfillment_center:
                          type: string
                        disposition:
                          type: string
                        reason:
                          type: string
                          nullable: true
                        reconciled_quantity:
                          type: integer
                        unreconciled_quantity:
                          type: integer
                        reconciled_at:
                          type: string
                        is_reconciled:
                          type: boolean
                        amazon_fnsku_product_id:
                          type: integer
                        amazon_fifo_layer_id:
                          type: integer
                        fnsku_product:
                          type: object
                          properties:
                            id:
                              type: integer
                            fnsku:
                              type: string
                            asin:
                              type: string
                            msku:
                              type: string
                            product_id:
                              type: integer
                            product:
                              type: object
                              properties:
                                id:
                                  type: integer
                                sku:
                                  type: string
                                name:
                                  type: string
                        fifo_layer:
                          type: object
                          properties:
                            id:
                              type: integer
                            quantity:
                              type: integer
                            cogs:
                              type: number
                            fifo_layer_date:
                              type: string
                        fifo_consumptions_count:
                          type: integer
                        has_provisional_cogs:
                          type: boolean
                        is_sales_order_type:
                          type: boolean
                        is_linked_to_sales_order:
                          type: boolean
                        sales_order_line:
                          type: string
                          nullable: true
                        is_linked_to_warehouse_transfer:
                          type: boolean
                        warehouse_transfer_line:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - id: 7777
                    integration_instance_id: 1
                    integration_instance_name: Amazon US
                    checksum: a1b2c3d4e5f6
                    date: '2024-05-01T07:00:00+00:00'
                    fnsku: X001ABCD23
                    asin: B0ABCDEF12
                    msku: SKU-001
                    title: Example Product Title
                    event_type: RECEIVED
                    reference_id: FBA15ABCD123
                    quantity: 100
                    fulfillment_center: AWD1
                    disposition: SELLABLE
                    reason: null
                    reconciled_quantity: 100
                    unreconciled_quantity: 0
                    reconciled_at: '2024-05-02T08:00:00+00:00'
                    is_reconciled: true
                    amazon_fnsku_product_id: 401
                    amazon_fifo_layer_id: 9012
                    fnsku_product:
                      id: 401
                      fnsku: X001ABCD23
                      asin: B0ABCDEF12
                      msku: SKU-001
                      product_id: 5005
                      product:
                        id: 5005
                        sku: SKU-001
                        name: Example Product
                    fifo_layer:
                      id: 9012
                      quantity: 100
                      cogs: 4.25
                      fifo_layer_date: '2024-05-01T07:00:00+00:00'
                    fifo_consumptions_count: 0
                    has_provisional_cogs: false
                    is_sales_order_type: false
                    is_linked_to_sales_order: false
                    sales_order_line: null
                    is_linked_to_warehouse_transfer: false
                    warehouse_transfer_line: null
                    created_at: '2024-05-02T08:00:00+00:00'
                    updated_at: '2024-05-02T08:00:00+00:00'
                  current_page: 1
                  last_page: 8
                  per_page: 15
                  total: 117
                  from: 1
                  to: 15
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-amazon-unified-awd-ledgers
    delete:
      tags:
      - Amazon
      summary: Delete AWD ledgers
      description: 'Deletes AWD ledger entries by IDs. Same validation pattern as
        other bulk ledger ops.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      count:
                        type: integer
                example:
                  message: 2 AWD ledger entries deleted.
                  data:
                    count: 2
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: delete-api-amazon-unified-awd-ledgers
  /api/amazon/unified/awd/refresh:
    post:
      tags:
      - Amazon
      summary: Refresh AWD shipments (dispatch jobs)
      description: 'Dispatches a background job for each instance. Skips non-NA region,
        AWD-sync-disabled, and AWD-access-denied instances. Blocks instances whose
        initial inventory has not been handled. The job fetches the shipment list,
        dispatches detail-fetch jobs, then auto-processes.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      results:
                        type: array
                        items:
                          type: object
                          properties:
                            integration_instance_id:
                              type: integer
                            integration_instance_name:
                              type: string
                            status:
                              type: string
                            message:
                              type: string
                      summary:
                        type: object
                        properties:
                          total:
                            type: integer
                          dispatched:
                            type: integer
                          blocked:
                            type: integer
                          skipped:
                            type: integer
                          failed:
                            type: integer
                example:
                  message: AWD refresh jobs dispatched for 1 integration(s). Shipments
                    will be synced and processed in the background.
                  data:
                    results:
                    - integration_instance_id: 1
                      integration_instance_name: Amazon US
                      status: dispatched
                      message: AWD refresh job dispatched
                    summary:
                      total: 1
                      dispatched: 1
                      blocked: 0
                      skipped: 0
                      failed: 0
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      results:
                        type: array
                      summary:
                        type: object
                        properties:
                          total:
                            type: integer
                          dispatched:
                            type: integer
                          blocked:
                            type: integer
                          skipped:
                            type: integer
                          failed:
                            type: integer
                example:
                  message: AWD refresh blocked for all instances. Initial inventory
                    must be handled before syncing.
                  data:
                    results: []
                    summary:
                      total: 1
                      dispatched: 0
                      blocked: 1
                      skipped: 0
                      failed: 0
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-amazon-unified-awd-refresh
  /api/amazon/unified/awd/shipments/process:
    post:
      tags:
      - Amazon
      summary: Process AWD shipments
      description: 'Processes selected AWD shipments by IDs (creates WT/PO links based
        on ship-from mappings). Pass ids: [...] for explicit selection, OR apply_to_all:
        true + filters: {...} to operate on every shipment matching the filter set.
        Validation: apply_to_all (sometimes|boolean), filters (required_if:apply_to_all,true|array),
        ids (required_without:apply_to_all|array), ids.* (integer).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                apply_to_all:
                  type: boolean
                ids:
                  type: array
                  items:
                    type: integer
                filters:
                  type: object
                  properties:
                    integration_instance_ids:
                      type: string
                    process_status:
                      type: string
              example:
                apply_to_all: false
                ids:
                - 1001
                - 1002
                - 1003
                filters:
                  integration_instance_ids: 1,2
                  process_status: processable
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      shipments:
                        type: array
                example:
                  message: Processed 3 shipment(s)
                  data:
                    shipments: []
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-amazon-unified-awd-shipments-process
  /api/amazon/unified/awd/ship-from-mappings:
    get:
      tags:
      - Amazon
      summary: List ship-from mappings (paginated)
      description: 'Paginated AWD/FBA ship-from mappings across integration instances.
        Eager loads integrationInstance and the polymorphic link (Supplier or Warehouse).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        integration_instance_name:
                          type: string
                        name:
                          type: string
                        link_id:
                          type: integer
                        link_type:
                          type: string
                        link_type_label:
                          type: string
                        link_name:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - id: 12
                    integration_instance_id: 1
                    integration_instance_name: Amazon US
                    name: Supplier ACME
                    link_id: 22
                    link_type: App\Models\Supplier
                    link_type_label: Supplier
                    link_name: ACME Co.
                    created_at: '2024-03-01T12:00:00+00:00'
                    updated_at: '2024-04-12T08:00:00+00:00'
                  current_page: 1
                  last_page: 3
                  per_page: 10
                  total: 28
                  from: 1
                  to: 10
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-amazon-unified-awd-ship-from-mappings
  /api/amazon/unified/awd/initial-inventory/details:
    get:
      tags:
      - Amazon
      summary: Get AWD initial inventory details
      description: 'Returns detailed AWD initial inventory entries with their FIFO
        layer data (unit_cost, total_value, fifo_layer_id, cogs_source) for the specified
        integration instances.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integration_instance_ids
        in: query
        schema:
          type: integer
        description: Comma-separated integration instance IDs (REQUIRED).
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        integration_instance_id:
                          type: integer
                        integration_instance_name:
                          type: string
                        entries:
                          type: array
                          items:
                            type: object
                            properties:
                              id:
                                type: integer
                              fnsku:
                                type: string
                              asin:
                                type: string
                              msku:
                                type: string
                              title:
                                type: string
                              purchase_order_id:
                                type: string
                                nullable: true
                              country:
                                type: string
                              date:
                                type: string
                              ending_units:
                                type: integer
                              package_quantity:
                                type: integer
                              ending_warehouse_balance:
                                type: integer
                              unit_cost:
                                type: number
                              total_value:
                                type: integer
                              fifo_layer_id:
                                type: integer
                              cogs_source:
                                type: string
                              reconciled_at:
                                type: string
                example:
                  data:
                  - integration_instance_id: 1
                    integration_instance_name: Amazon US
                    entries:
                    - id: 501
                      fnsku: X001ABCD23
                      asin: B0ABCDEF12
                      msku: SKU-001
                      title: Example Product Title
                      purchase_order_id: null
                      country: US
                      date: '2024-04-21'
                      ending_units: 120
                      package_quantity: 10
                      ending_warehouse_balance: 120
                      unit_cost: 4.25
                      total_value: 510
                      fifo_layer_id: 9012
                      cogs_source: manual
                      reconciled_at: '2024-04-22T07:00:00+00:00'
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No integration instance IDs provided
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-amazon-unified-awd-initial-inventory-details
  /api/amazon/unified/awd/initial-inventory/confirm-no-inventory:
    post:
      tags:
      - Amazon
      summary: Confirm no AWD initial inventory
      description: 'Marks the specified integration instances as having no AWD initial
        inventory. Sets awd_initial_inventory_confirmed_no_inventory=true so AWD sync
        can proceed.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters:
      - name: integration_instance_ids
        in: query
        schema:
          type: string
        description: Comma-separated integration instance IDs (REQUIRED).
        example: 1,2
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      results:
                        type: array
                        items:
                          type: object
                          properties:
                            integration_instance_id:
                              type: integer
                            integration_instance_name:
                              type: string
                            status:
                              type: string
                            message:
                              type: string
                      summary:
                        type: object
                        properties:
                          total:
                            type: integer
                          confirmed:
                            type: integer
                example:
                  message: Confirmed no initial inventory for 1 integration(s)
                  data:
                    results:
                    - integration_instance_id: 1
                      integration_instance_name: Amazon US
                      status: confirmed
                      message: Confirmed no AWD initial inventory
                    summary:
                      total: 1
                      confirmed: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-amazon-unified-awd-initial-inventory-confirm-no-inventory
  /api/amazon/unified/awd/initial-inventory/import:
    post:
      tags:
      - Amazon
      summary: Import AWD initial inventory
      description: 'Imports AWD initial inventory from a previously uploaded CSV file
        (AWD Inventory Ledger - Summary report). The integration instance is auto-detected
        from FNSKU data; integration_instance_id is used as a fallback if auto-detection
        fails. Required field: stored_name (string). Optional: integration_instance_id
        (integer). The endpoint validates that FNSKUs are mapped before proceeding.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                stored_name:
                  type: string
                integration_instance_id:
                  type: integer
              example:
                stored_name: uploads/awd-initial-inventory-20260529-abcdef.csv
                integration_instance_id: 1
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: Success
                  value:
                    message: 'AWD initial inventory import completed for Amazon US.
                      200 rows processed: 180 created, 10 duplicates, 5 invalid, 5
                      zero balance skipped. 180 FIFO layers created. 5400 total units.'
                    data:
                      total_rows: 200
                      created: 180
                      skipped_duplicates: 10
                      skipped_invalid: 5
                      skipped_zero_balance: 5
                      fifo_layers_created: 180
                      total_units: 5400
                      errors: []
                example-1:
                  summary: Unmapped FNSKUs require mapping
                  value:
                    message: 3 FNSKU(s) need to be mapped to products before import
                      can proceed. Please map them in the FNSKU Product Mapper.
                    data:
                      unmapped_fnskus:
                      - X001ABC123
                      - X001DEF456
                      - X001GHI789
                      created_count: 3
                      fnsku_mapper_url: /v2/integrations/amazon/fba/fnsku-mapper/unmapped
                      needs_mapping: true
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-amazon-unified-awd-initial-inventory-import
  /api/amazon/unified/awd/initial-inventory:
    delete:
      tags:
      - Amazon
      summary: Delete AWD initial inventory
      description: 'Deletes all AWD initial inventory entries (and their FIFO layers)
        for the specified integration instances. Resets the awd_initial_inventory_imported
        and awd_initial_inventory_confirmed_no_inventory flags so initial inventory
        can be re-imported or re-confirmed.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integration_instance_ids
        in: query
        schema:
          type: string
        description: Comma-separated integration instance IDs (REQUIRED).
        example: 1,2
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      results:
                        type: array
                        items:
                          type: object
                          properties:
                            integration_instance_id:
                              type: integer
                            integration_instance_name:
                              type: string
                            status:
                              type: string
                            deleted:
                              type: integer
                      total_deleted:
                        type: integer
                example:
                  message: Deleted 124 AWD initial inventory entries
                  data:
                    results:
                    - integration_instance_id: 1
                      integration_instance_name: Amazon US
                      status: deleted
                      deleted: 124
                    total_deleted: 124
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: delete-api-amazon-unified-awd-initial-inventory
  /api/amazon/unified/awd/sync-enabled:
    post:
      tags:
      - Amazon
      summary: Update AWD sync enabled
      description: 'Enables or disables AWD sync per integration instance (stored
        in integration_settings, replaces the legacy AMAZON_AWD_SYNC_ENABLED env var).
        Required fields: integration_instance_ids (array of integers, min 1, each
        must exist in integration_instances.id), awd_sync_enabled (boolean).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                integration_instance_ids:
                  type: array
                  items:
                    type: integer
                awd_sync_enabled:
                  type: boolean
              example:
                integration_instance_ids:
                - 1
                - 2
                awd_sync_enabled: true
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      results:
                        type: array
                        items:
                          type: object
                          properties:
                            integration_instance_id:
                              type: integer
                            integration_instance_name:
                              type: string
                            awd_sync_enabled:
                              type: boolean
                      summary:
                        type: object
                        properties:
                          total:
                            type: integer
                          awd_sync_enabled:
                            type: boolean
                example:
                  message: AWD sync enabled for 2 integration(s).
                  data:
                    results:
                    - integration_instance_id: 1
                      integration_instance_name: Amazon US
                      awd_sync_enabled: true
                    - integration_instance_id: 2
                      integration_instance_name: Amazon CA
                      awd_sync_enabled: true
                    summary:
                      total: 2
                      awd_sync_enabled: true
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-amazon-unified-awd-sync-enabled
  /api/amazon/unified/awd/shipments/unprocess:
    post:
      tags:
      - Amazon
      summary: Unprocess AWD shipments
      description: 'Unlinks (unprocesses) selected AWD shipments by IDs, clearing
        their sku_link. Same validation pattern as process: pass ids or use apply_to_all
        + filters.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                apply_to_all:
                  type: boolean
                ids:
                  type: array
                  items:
                    type: integer
                filters:
                  type: object
                  properties:
                    integration_instance_ids:
                      type: string
              example:
                apply_to_all: false
                ids:
                - 1001
                - 1002
                filters:
                  integration_instance_ids: '1'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: array
                example:
                  message: Unprocessed 2 shipment(s)
                  data: []
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-amazon-unified-awd-shipments-unprocess
  /api/amazon/unified/awd/shipments/{id}/eligible-purchase-orders:
    get:
      tags:
      - Amazon
      summary: Get eligible purchase orders for AWD shipment
      description: 'Returns the purchase orders eligible for linking to the given
        AWD shipment, with PO line summaries.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        purchase_order_number:
                          type: string
                        purchase_order_date:
                          type: string
                        supplier_id:
                          type: integer
                        supplier_name:
                          type: string
                        destination_warehouse:
                          type: string
                        order_status:
                          type: string
                        receipt_status:
                          type: string
                        total_quantity:
                          type: integer
                        lines:
                          type: array
                          items:
                            type: object
                            properties:
                              id:
                                type: integer
                              product_id:
                                type: integer
                              product_sku:
                                type: string
                              product_name:
                                type: string
                              quantity:
                                type: integer
                              received_quantity:
                                type: integer
                example:
                  data:
                  - id: 4001
                    purchase_order_number: PO-2024-001
                    purchase_order_date: '2024-03-15T00:00:00+00:00'
                    supplier_id: 22
                    supplier_name: ACME Co.
                    destination_warehouse: AWD Origin Warehouse
                    order_status: approved
                    receipt_status: partial
                    total_quantity: 500
                    lines:
                    - id: 8801
                      product_id: 5005
                      product_sku: SKU-001
                      product_name: Example Product
                      quantity: 500
                      received_quantity: 100
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Shipment not found
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-amazon-unified-awd-shipments-id-eligible-purchase-orders
  /api/amazon/unified/awd/shipments/{id}/link-purchase-order:
    post:
      tags:
      - Amazon
      summary: Link AWD shipment to purchase order
      description: 'Links the AWD shipment to an existing purchase order. Required:
        purchase_order_id (integer, must exist in purchase_orders.id).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                purchase_order_id:
                  type: integer
              example:
                purchase_order_id: 4001
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      shipment:
                        type: object
                        properties:
                          id:
                            type: integer
                          shipment_id:
                            type: string
                          sku_link:
                            type: object
                            properties:
                              id:
                                type: integer
                              type:
                                type: string
                              name:
                                type: string
                              displayType:
                                type: string
                      warnings:
                        type: array
                example:
                  message: Shipment linked to purchase order successfully.
                  data:
                    shipment:
                      id: 1001
                      shipment_id: FBA15ABCD123
                      sku_link:
                        id: 4001
                        type: App\Models\PurchaseOrder
                        name: PO-2024-001
                        displayType: Purchase Order
                    warnings: []
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-amazon-unified-awd-shipments-id-link-purchase-order
  /api/amazon/unified/awd/shipments/{id}/unlink-purchase-order:
    post:
      tags:
      - Amazon
      summary: Unlink AWD shipment from purchase order
      description: 'Unlinks an AWD shipment from its linked purchase order, clearing
        the sku_link reference. No body required.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      shipment_id:
                        type: string
                      sku_link:
                        type: string
                        nullable: true
                example:
                  message: Shipment unlinked from purchase order successfully.
                  data:
                    id: 1001
                    shipment_id: FBA15ABCD123
                    sku_link: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-amazon-unified-awd-shipments-id-unlink-purchase-order
  /api/amazon/unified/awd/ledgers/import:
    post:
      tags:
      - Amazon
      summary: Import AWD ledger CSV
      description: 'Imports an AWD ledger CSV file. Integration instance is auto-detected
        from the FNSKU/Reference ID data in the CSV. Required: stored_name (string).
        Optional: integration_instance_id (integer) as fallback when auto-detection
        fails. Checks for unmapped FNSKUs before processing.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                stored_name:
                  type: string
                integration_instance_id:
                  type: integer
              example:
                stored_name: uploads/awd-ledger-20260529-abcdef.csv
                integration_instance_id: 1
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      total_rows:
                        type: integer
                      created:
                        type: integer
                      skipped_duplicates:
                        type: integer
                      skipped_invalid:
                        type: integer
                      reconciled:
                        type: integer
                      errors:
                        type: array
                example:
                  message: 'AWD ledger import completed. 500 rows processed: 480 created,
                    15 duplicates skipped, 5 invalid skipped, 460 reconciled.'
                  data:
                    total_rows: 500
                    created: 480
                    skipped_duplicates: 15
                    skipped_invalid: 5
                    reconciled: 460
                    errors: []
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-amazon-unified-awd-ledgers-import
  /api/amazon/unified/awd/ledgers/reconcile:
    post:
      tags:
      - Amazon
      summary: Reconcile AWD ledgers
      description: 'Reconciles AWD ledger entries by IDs. Groups by integration instance
        internally. Same validation as other bulk ops: ids array OR apply_to_all +
        filters.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                apply_to_all:
                  type: boolean
                ids:
                  type: array
                  items:
                    type: integer
                filters:
                  type: object
                  properties:
                    integration_instance_ids:
                      type: string
                    event_type:
                      type: string
                    reconciled:
                      type: string
              example:
                apply_to_all: false
                ids:
                - 7777
                - 7778
                - 7779
                filters:
                  integration_instance_ids: 1,2
                  event_type: RECEIVED
                  reconciled: '0'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      processed:
                        type: integer
                      skipped:
                        type: integer
                      fifo_layers_created:
                        type: integer
                      consumptions_created:
                        type: integer
                example:
                  message: AWD ledger reconciliation completed. 3 processed, 0 skipped,
                    3 FIFO layers created, 0 consumptions created.
                  data:
                    processed: 3
                    skipped: 0
                    fifo_layers_created: 3
                    consumptions_created: 0
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-amazon-unified-awd-ledgers-reconcile
  /api/amazon/unified/awd/ledgers/unreconcile:
    post:
      tags:
      - Amazon
      summary: Unreconcile AWD ledgers
      description: 'Unreconciles AWD ledger entries by IDs. Clears reconciled_at,
        reconciled_quantity, and amazon_fifo_layer_id. Same validation pattern.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                apply_to_all:
                  type: boolean
                ids:
                  type: array
                  items:
                    type: integer
                filters:
                  type: object
                  properties:
                    integration_instance_ids:
                      type: string
                    reconciled:
                      type: string
              example:
                apply_to_all: false
                ids:
                - 7777
                - 7778
                filters:
                  integration_instance_ids: '1'
                  reconciled: '1'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      count:
                        type: integer
                example:
                  message: 2 AWD ledger entries unreconciled.
                  data:
                    count: 2
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-amazon-unified-awd-ledgers-unreconcile
  /api/amazon/unified/awd/ship-from-mappings/{id}:
    put:
      tags:
      - Amazon
      summary: Update ship-from mapping
      description: 'Updates a ship-from mapping''s link target. Optional: link_id
        (integer, nullable), link_type (string, nullable, must be ''App\\Models\\Supplier''
        or ''App\\Models\\Warehouse''). Pass null link_id to clear the mapping.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                link_id:
                  type: integer
                link_type:
                  type: string
              example:
                link_id: 22
                link_type: App\Models\Supplier
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      integration_instance_name:
                        type: string
                      name:
                        type: string
                      link_id:
                        type: integer
                      link_type:
                        type: string
                      link_type_label:
                        type: string
                      link_name:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  message: Mapping updated successfully
                  data:
                    id: 12
                    integration_instance_id: 1
                    integration_instance_name: Amazon US
                    name: Supplier ACME
                    link_id: 22
                    link_type: App\Models\Supplier
                    link_type_label: Supplier
                    link_name: ACME Co.
                    created_at: '2024-03-01T12:00:00+00:00'
                    updated_at: '2024-05-29T12:00:00+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-amazon-unified-awd-ship-from-mappings-id
  /api/amazon/unified/awd/ship-from-mappings/bulk-update:
    post:
      tags:
      - Amazon
      summary: Bulk update ship-from mappings
      description: 'Bulk updates ship-from mappings. Two modes: (1) explicit ids:
        [...] OR (2) apply_to_all: true + filters: {...}. Validation: apply_to_all
        (sometimes|boolean), filters (required_if:apply_to_all,true|array), ids (required_without:apply_to_all|array),
        ids.* (integer, must exist in amazon_fba_inbound_ship_from_mappings.id), link_id
        (nullable|integer), link_type (nullable|string|in:App\\Models\\Supplier,App\\Models\\Warehouse).
        Pass null link_id to clear mappings.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                apply_to_all:
                  type: boolean
                ids:
                  type: array
                  items:
                    type: integer
                filters:
                  type: object
                  properties:
                    integration_instance_ids:
                      type: string
                    link_status:
                      type: string
                link_id:
                  type: integer
                link_type:
                  type: string
              example:
                apply_to_all: false
                ids:
                - 12
                - 13
                - 14
                filters:
                  integration_instance_ids: '1'
                  link_status: unmapped
                link_id: 22
                link_type: App\Models\Supplier
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        integration_instance_name:
                          type: string
                        name:
                          type: string
                        link_id:
                          type: integer
                        link_type:
                          type: string
                        link_type_label:
                          type: string
                        link_name:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                example:
                  message: 3 mapping(s) updated successfully
                  data:
                  - id: 12
                    integration_instance_id: 1
                    integration_instance_name: Amazon US
                    name: Supplier ACME
                    link_id: 22
                    link_type: App\Models\Supplier
                    link_type_label: Supplier
                    link_name: ACME Co.
                    created_at: '2024-03-01T12:00:00+00:00'
                    updated_at: '2024-05-29T12:00:00+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-amazon-unified-awd-ship-from-mappings-bulk-update
  /api/amazon/unified/awd/reset-access:
    post:
      tags:
      - Amazon
      summary: Reset AWD Access
      description: 'Resets the stored "AWD access denied" flag for the specified Amazon
        integration instances. An instance is flagged as access-denied when Amazon''s
        AWD (Amazon Warehousing & Distribution) API returns a 403 for it; while flagged,
        AWD syncing is skipped for that instance. Resetting the flag causes the next
        AWD sync to re-probe Amazon and re-check eligibility.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Runs synchronously and returns a per-instance result with one of three statuses:
        `reset` (flag cleared), `not_denied` (nothing to reset), or `error` (instance
        not found).


        Body fields:

        - `integration_instance_ids` (required, array of integers or comma-separated
        string) - the Amazon integration instances to reset. Returns 400 when omitted
        or empty.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                integration_instance_ids:
                  type: array
                  items:
                    type: integer
              example:
                integration_instance_ids:
                - 2
                - 5
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      results:
                        type: array
                        items:
                          type: object
                          properties:
                            integration_instance_id:
                              type: integer
                            integration_instance_name:
                              type: string
                            status:
                              type: string
                            message:
                              type: string
                      summary:
                        type: object
                        properties:
                          total:
                            type: integer
                          reset:
                            type: integer
                  status:
                    type: string
                example:
                  message: Reset AWD access for 1 integration(s). The next sync will
                    re-check AWD availability.
                  data:
                    results:
                    - integration_instance_id: 2
                      integration_instance_name: Amazon US
                      status: reset
                      message: AWD access flag reset - will re-check on next sync
                    - integration_instance_id: 5
                      integration_instance_name: Amazon CA
                      status: not_denied
                      message: AWD access is not currently denied
                    summary:
                      total: 2
                      reset: 1
                  status: success
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  status:
                    type: string
                example:
                  message: No integration instance IDs provided
                  status: failure
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-amazon-unified-awd-reset-access
  /api/amazon/unified/restock-report:
    get:
      tags:
      - Amazon
      summary: List Restock Report
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        example: '1'
        description: Page number (default 1).
      - name: per_page
        in: query
        schema:
          type: integer
        example: '10'
        description: Results per page (default 10).
      - name: search
        in: query
        schema:
          type: string
        description: Free-text search across the resource’s searchable fields.
      - name: integration_instance_ids
        in: query
        schema:
          type: string
        description: Comma-separated integration instance IDs to scope the query.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      description: 'List Restock Report


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      operationId: get-api-amazon-unified-restock-report
  /api/amazon/unified/restock-report/{restockReport}:
    get:
      tags:
      - Amazon
      summary: Get Restock Report Row
      description: 'Returns a single row from Amazon''s FBA restock recommendations
        report, with the amazon_product cross-link resolved ({id} of the Amazon listing
        matching the row''s merchant SKU on the same integration instance, or null
        when no match).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Fields include Amazon''s replenishment guidance (recommended_replenishment_qty,
        recommended_ship_date, alert), sales velocity (sales_last_30_days, units_sold_last_30_days),
        the current inventory position (total_units, inbound, available, fc_transfer,
        fc_processing, customer_order, unfulfillable, working, shipped, receiving),
        days of supply (total_days_of_supply, days_of_supply_at_amazon_fulfillment_network),
        and identifiers (merchant_sku, fnsku, asin, country, condition, supplier,
        supplier_part_no, currency_code, price, fulfilled_by).


        Optional query parameters included / excluded (URL-encoded JSON arrays of
        column names) limit which columns are returned.'
      parameters:
      - name: restockReport
        in: path
        schema:
          type: string
        required: true
        description: Restock report row ID
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      integration_instance_name:
                        type: string
                      amazon_product:
                        type: object
                        properties:
                          id:
                            type: integer
                      recommended_replenishment_qty:
                        type: integer
                      recommended_ship_date:
                        type: string
                      product_name:
                        type: string
                      merchant_sku:
                        type: string
                      fnsku:
                        type: string
                      asin:
                        type: string
                      country:
                        type: string
                      condition:
                        type: string
                      supplier:
                        type: string
                      supplier_part_no:
                        type: string
                      currency_code:
                        type: string
                      price:
                        type: number
                      sales_last_30_days:
                        type: number
                      units_sold_last_30_days:
                        type: integer
                      total_units:
                        type: integer
                      inbound:
                        type: integer
                      available:
                        type: integer
                      fc_transfer:
                        type: integer
                      fc_processing:
                        type: integer
                      customer_order:
                        type: integer
                      unfulfillable:
                        type: integer
                      working:
                        type: integer
                      shipped:
                        type: integer
                      receiving:
                        type: integer
                      fulfilled_by:
                        type: string
                      total_days_of_supply:
                        type: string
                      days_of_supply_at_amazon_fulfillment_network:
                        type: string
                      alert:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                  status:
                    type: string
                example:
                  data:
                    id: 30455
                    integration_instance_id: 3
                    integration_instance_name: Amazon US
                    amazon_product:
                      id: 5512
                    recommended_replenishment_qty: 250
                    recommended_ship_date: '2026-07-15T00:00:00.000000Z'
                    product_name: Blue Widget - Medium
                    merchant_sku: WIDGET-BLUE-M
                    fnsku: X002ABCDE1
                    asin: B08XYZAB12
                    country: US
                    condition: New
                    supplier: Acme Supply Co
                    supplier_part_no: ACM-4432
                    currency_code: USD
                    price: 24.99
                    sales_last_30_days: 3120.55
                    units_sold_last_30_days: 125
                    total_units: 640
                    inbound: 200
                    available: 380
                    fc_transfer: 24
                    fc_processing: 12
                    customer_order: 24
                    unfulfillable: 0
                    working: 100
                    shipped: 80
                    receiving: 20
                    fulfilled_by: AMAZON
                    total_days_of_supply: '45.2'
                    days_of_supply_at_amazon_fulfillment_network: '38.6'
                    alert: Low inventory
                    created_at: '2026-07-05T06:00:14.000000Z'
                    updated_at: '2026-07-06T06:00:22.000000Z'
                  status: success
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: object
                    properties:
                      Modules\Amazon\Entities\AmazonFbaReportRestock:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: array
                  status:
                    type: string
                  message:
                    type: string
                example:
                  errors:
                    Modules\Amazon\Entities\AmazonFbaReportRestock:
                    - message: No query results for model [Modules\Amazon\Entities\AmazonFbaReportRestock]
                        99999
                      code: NotFound
                      data: []
                  status: failure
                  message: No query results for model [Modules\Amazon\Entities\AmazonFbaReportRestock]
                    99999
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-amazon-unified-restock-report-restockreport
  /api/amazon/unified/fulfillment-orders:
    get:
      tags:
      - Amazon
      summary: List Unified MCF Fulfillment Orders
      description: 'Returns a paginated list of MCF (Multi-Channel Fulfillment) orders
        aggregated across all Amazon integration instances the user has access to.
        Supports Spatie QueryBuilder filters and sorts. Each item includes related
        integration instance, sales order fulfillment, items, and shipments.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        sales_order_fulfillment_id:
                          type: integer
                        seller_fulfillment_order_id:
                          type: string
                        displayable_order_id:
                          type: string
                        displayable_order_date:
                          type: string
                        displayable_order_comment:
                          type: string
                        marketplace_id:
                          type: string
                        shipping_speed_category:
                          type: string
                        delivery_window:
                          type: object
                          properties:
                            startDate:
                              type: string
                            endDate:
                              type: string
                        destination_address:
                          type: object
                          properties:
                            name:
                              type: string
                            addressLine1:
                              type: string
                            city:
                              type: string
                            stateOrRegion:
                              type: string
                            postalCode:
                              type: string
                            countryCode:
                              type: string
                        fulfillment_action:
                          type: string
                        fulfillment_policy:
                          type: string
                        cod_settings:
                          type: string
                          nullable: true
                        received_date:
                          type: string
                        fulfillment_order_status:
                          type: string
                        status_updated_date:
                          type: string
                        notification_emails:
                          type: array
                          items:
                            type: string
                        feature_constraints:
                          type: array
                          items:
                            type: object
                            properties:
                              featureName:
                                type: string
                              featureFulfillmentPolicy:
                                type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                        integration_instance:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        integration_instance_name:
                          type: string
                        sales_order_fulfillment:
                          type: object
                          properties:
                            id:
                              type: integer
                            sales_order_id:
                              type: integer
                        item_count:
                          type: integer
                        items:
                          type: array
                          items:
                            type: object
                            properties:
                              id:
                                type: integer
                              seller_sku:
                                type: string
                              seller_fulfillment_order_item_id:
                                type: string
                              quantity:
                                type: integer
                              cancelled_quantity:
                                type: integer
                              unfulfillable_quantity:
                                type: integer
                              displayable_comment:
                                type: string
                                nullable: true
                              gift_message:
                                type: string
                                nullable: true
                              fulfillment_network_sku:
                                type: string
                              estimated_ship_date:
                                type: string
                              estimated_arrival_date:
                                type: string
                              per_unit_price_currency_code:
                                type: string
                              per_unit_price_currency_value:
                                type: string
                              per_unit_tax_currency_code:
                                type: string
                              per_unit_tax_value:
                                type: string
                              per_unit_declared_value_currency_code:
                                type: string
                              per_unit_declared_value_value:
                                type: string
                        shipment_count:
                          type: integer
                        shipments:
                          type: array
                          items:
                            type: object
                            properties:
                              id:
                                type: integer
                              amazon_shipment_id:
                                type: string
                              fulfillment_center_id:
                                type: string
                              fulfillment_shipment_status:
                                type: string
                              shipping_date:
                                type: string
                              estimated_arrival_date:
                                type: string
                              shipping_notes:
                                type: string
                                nullable: true
                  current_page:
                    type: integer
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  next_page_url:
                    type: string
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                  links:
                    type: array
                    items:
                      type: object
                      properties:
                        url:
                          type: string
                          nullable: true
                        label:
                          type: string
                        active:
                          type: boolean
                example:
                  data:
                  - id: 1024
                    integration_instance_id: 7
                    sales_order_fulfillment_id: 5510
                    seller_fulfillment_order_id: SO-12345
                    displayable_order_id: AMZ-0001
                    displayable_order_date: '2026-05-15T14:32:00.000000Z'
                    displayable_order_comment: Thanks for your order!
                    marketplace_id: ATVPDKIKX0DER
                    shipping_speed_category: Standard
                    delivery_window:
                      startDate: '2026-05-20T00:00:00Z'
                      endDate: '2026-05-22T00:00:00Z'
                    destination_address:
                      name: Jane Doe
                      addressLine1: 123 Main St
                      city: Seattle
                      stateOrRegion: WA
                      postalCode: '98101'
                      countryCode: US
                    fulfillment_action: Ship
                    fulfillment_policy: FillOrKill
                    cod_settings: null
                    received_date: '2026-05-15T14:32:10.000000Z'
                    fulfillment_order_status: COMPLETE
                    status_updated_date: '2026-05-17T22:08:45.000000Z'
                    notification_emails:
                    - customer@example.com
                    feature_constraints:
                    - featureName: BLANK_BOX
                      featureFulfillmentPolicy: Required
                    created_at: '2026-05-15T14:33:00.000000Z'
                    updated_at: '2026-05-17T22:08:45.000000Z'
                    integration_instance:
                      id: 7
                      name: Amazon US — Hitlights
                    integration_instance_name: Amazon US — Hitlights
                    sales_order_fulfillment:
                      id: 5510
                      sales_order_id: 9871
                    item_count: 2
                    items:
                    - id: 8001
                      seller_sku: SKU-ABC-001
                      seller_fulfillment_order_item_id: ITEM-001
                      quantity: 2
                      cancelled_quantity: 0
                      unfulfillable_quantity: 0
                      displayable_comment: null
                      gift_message: null
                      fulfillment_network_sku: X0001ABCDE
                      estimated_ship_date: '2026-05-16T08:00:00.000000Z'
                      estimated_arrival_date: '2026-05-20T18:00:00.000000Z'
                      per_unit_price_currency_code: USD
                      per_unit_price_currency_value: '19.99'
                      per_unit_tax_currency_code: USD
                      per_unit_tax_value: '1.80'
                      per_unit_declared_value_currency_code: USD
                      per_unit_declared_value_value: '19.99'
                    - id: 8002
                      seller_sku: SKU-XYZ-009
                      seller_fulfillment_order_item_id: ITEM-002
                      quantity: 1
                      cancelled_quantity: 0
                      unfulfillable_quantity: 0
                      displayable_comment: null
                      gift_message: null
                      fulfillment_network_sku: X0009XYZAB
                      estimated_ship_date: '2026-05-16T08:00:00.000000Z'
                      estimated_arrival_date: '2026-05-20T18:00:00.000000Z'
                      per_unit_price_currency_code: USD
                      per_unit_price_currency_value: '34.50'
                      per_unit_tax_currency_code: USD
                      per_unit_tax_value: '3.10'
                      per_unit_declared_value_currency_code: USD
                      per_unit_declared_value_value: '34.50'
                    shipment_count: 1
                    shipments:
                    - id: 4400
                      amazon_shipment_id: AMZ-SHIP-998877
                      fulfillment_center_id: PHX7
                      fulfillment_shipment_status: SHIPPED
                      shipping_date: '2026-05-16T09:15:00.000000Z'
                      estimated_arrival_date: '2026-05-20T18:00:00.000000Z'
                      shipping_notes: null
                  current_page: 1
                  first_page_url: https://example.test/api/amazon/unified/fulfillment-orders?page=1
                  from: 1
                  last_page: 12
                  last_page_url: https://example.test/api/amazon/unified/fulfillment-orders?page=12
                  next_page_url: https://example.test/api/amazon/unified/fulfillment-orders?page=2
                  path: https://example.test/api/amazon/unified/fulfillment-orders
                  per_page: 10
                  prev_page_url: null
                  to: 10
                  total: 117
                  links:
                  - url: null
                    label: '&laquo; Previous'
                    active: false
                  - url: https://example.test/api/amazon/unified/fulfillment-orders?page=1
                    label: '1'
                    active: true
                  - url: https://example.test/api/amazon/unified/fulfillment-orders?page=2
                    label: Next &raquo;
                    active: false
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-amazon-unified-fulfillment-orders
  /api/amazon/unified/fulfillment-orders/{fulfillmentOrder}:
    get:
      tags:
      - Amazon
      summary: Show Unified MCF Fulfillment Order
      description: 'Returns a single MCF fulfillment order with full detail, including
        the integration instance, related sales order fulfillment, all order items,
        shipments, and return authorizations. Response is wrapped in the application''s
        standard envelope (top-level `data`).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: fulfillmentOrder
        in: path
        schema:
          type: integer
        required: true
        description: AmazonFulfillmentOrder ID (resolved via route model binding).
        example: '1024'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      sales_order_fulfillment_id:
                        type: integer
                      seller_fulfillment_order_id:
                        type: string
                      displayable_order_id:
                        type: string
                      displayable_order_date:
                        type: string
                      displayable_order_comment:
                        type: string
                      marketplace_id:
                        type: string
                      shipping_speed_category:
                        type: string
                      delivery_window:
                        type: object
                        properties:
                          startDate:
                            type: string
                          endDate:
                            type: string
                      destination_address:
                        type: object
                        properties:
                          name:
                            type: string
                          addressLine1:
                            type: string
                          addressLine2:
                            type: string
                            nullable: true
                          city:
                            type: string
                          stateOrRegion:
                            type: string
                          postalCode:
                            type: string
                          countryCode:
                            type: string
                          phone:
                            type: string
                      fulfillment_action:
                        type: string
                      fulfillment_policy:
                        type: string
                      cod_settings:
                        type: string
                        nullable: true
                      received_date:
                        type: string
                      fulfillment_order_status:
                        type: string
                      status_updated_date:
                        type: string
                      notification_emails:
                        type: array
                        items:
                          type: string
                      feature_constraints:
                        type: array
                        items:
                          type: object
                          properties:
                            featureName:
                              type: string
                            featureFulfillmentPolicy:
                              type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      integration_instance:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      integration_instance_name:
                        type: string
                      sales_order_fulfillment:
                        type: object
                        properties:
                          id:
                            type: integer
                          sales_order_id:
                            type: integer
                      item_count:
                        type: integer
                      items:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            seller_sku:
                              type: string
                            seller_fulfillment_order_item_id:
                              type: string
                            quantity:
                              type: integer
                            cancelled_quantity:
                              type: integer
                            unfulfillable_quantity:
                              type: integer
                            displayable_comment:
                              type: string
                              nullable: true
                            gift_message:
                              type: string
                              nullable: true
                            fulfillment_network_sku:
                              type: string
                            estimated_ship_date:
                              type: string
                            estimated_arrival_date:
                              type: string
                            per_unit_price_currency_code:
                              type: string
                            per_unit_price_currency_value:
                              type: string
                            per_unit_tax_currency_code:
                              type: string
                            per_unit_tax_value:
                              type: string
                            per_unit_declared_value_currency_code:
                              type: string
                            per_unit_declared_value_value:
                              type: string
                      shipment_count:
                        type: integer
                      shipments:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            amazon_shipment_id:
                              type: string
                            fulfillment_center_id:
                              type: string
                            fulfillment_shipment_status:
                              type: string
                            shipping_date:
                              type: string
                            estimated_arrival_date:
                              type: string
                            shipping_notes:
                              type: string
                              nullable: true
                example:
                  data:
                    id: 1024
                    integration_instance_id: 7
                    sales_order_fulfillment_id: 5510
                    seller_fulfillment_order_id: SO-12345
                    displayable_order_id: AMZ-0001
                    displayable_order_date: '2026-05-15T14:32:00.000000Z'
                    displayable_order_comment: Thanks for your order!
                    marketplace_id: ATVPDKIKX0DER
                    shipping_speed_category: Standard
                    delivery_window:
                      startDate: '2026-05-20T00:00:00Z'
                      endDate: '2026-05-22T00:00:00Z'
                    destination_address:
                      name: Jane Doe
                      addressLine1: 123 Main St
                      addressLine2: null
                      city: Seattle
                      stateOrRegion: WA
                      postalCode: '98101'
                      countryCode: US
                      phone: +1-555-123-4567
                    fulfillment_action: Ship
                    fulfillment_policy: FillOrKill
                    cod_settings: null
                    received_date: '2026-05-15T14:32:10.000000Z'
                    fulfillment_order_status: COMPLETE
                    status_updated_date: '2026-05-17T22:08:45.000000Z'
                    notification_emails:
                    - customer@example.com
                    feature_constraints:
                    - featureName: BLANK_BOX
                      featureFulfillmentPolicy: Required
                    created_at: '2026-05-15T14:33:00.000000Z'
                    updated_at: '2026-05-17T22:08:45.000000Z'
                    integration_instance:
                      id: 7
                      name: Amazon US — Hitlights
                    integration_instance_name: Amazon US — Hitlights
                    sales_order_fulfillment:
                      id: 5510
                      sales_order_id: 9871
                    item_count: 2
                    items:
                    - id: 8001
                      seller_sku: SKU-ABC-001
                      seller_fulfillment_order_item_id: ITEM-001
                      quantity: 2
                      cancelled_quantity: 0
                      unfulfillable_quantity: 0
                      displayable_comment: null
                      gift_message: null
                      fulfillment_network_sku: X0001ABCDE
                      estimated_ship_date: '2026-05-16T08:00:00.000000Z'
                      estimated_arrival_date: '2026-05-20T18:00:00.000000Z'
                      per_unit_price_currency_code: USD
                      per_unit_price_currency_value: '19.99'
                      per_unit_tax_currency_code: USD
                      per_unit_tax_value: '1.80'
                      per_unit_declared_value_currency_code: USD
                      per_unit_declared_value_value: '19.99'
                    - id: 8002
                      seller_sku: SKU-XYZ-009
                      seller_fulfillment_order_item_id: ITEM-002
                      quantity: 1
                      cancelled_quantity: 0
                      unfulfillable_quantity: 0
                      displayable_comment: null
                      gift_message: null
                      fulfillment_network_sku: X0009XYZAB
                      estimated_ship_date: '2026-05-16T08:00:00.000000Z'
                      estimated_arrival_date: '2026-05-20T18:00:00.000000Z'
                      per_unit_price_currency_code: USD
                      per_unit_price_currency_value: '34.50'
                      per_unit_tax_currency_code: USD
                      per_unit_tax_value: '3.10'
                      per_unit_declared_value_currency_code: USD
                      per_unit_declared_value_value: '34.50'
                    shipment_count: 1
                    shipments:
                    - id: 4400
                      amazon_shipment_id: AMZ-SHIP-998877
                      fulfillment_center_id: PHX7
                      fulfillment_shipment_status: SHIPPED
                      shipping_date: '2026-05-16T09:15:00.000000Z'
                      estimated_arrival_date: '2026-05-20T18:00:00.000000Z'
                      shipping_notes: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-unified-fulfillment-orders-fulfillmentorder
  /api/amazon/unified/fulfillment-orders/{fulfillmentOrder}/activity-log:
    get:
      tags:
      - Amazon
      summary: Get Fulfillment Order Activity Log
      description: 'Returns the activity log for a single multi-channel fulfillment
        (MCF) order: the most recent 200 entries, newest first (not paginated). Each
        entry contains id, description, event (created / updated / deleted), causer
        ({id, name, email} of the user who made the change, or null for system changes),
        properties (old and attributes objects with the changed field values), and
        created_at (UTC).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: fulfillmentOrder
        in: path
        schema:
          type: string
        required: true
        description: Multi-channel fulfillment order ID
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        description:
                          type: string
                        event:
                          type: string
                        causer:
                          type: string
                          nullable: true
                        properties:
                          type: object
                          properties:
                            old:
                              type: object
                              properties:
                                fulfillment_order_status:
                                  type: string
                            attributes:
                              type: object
                              properties:
                                fulfillment_order_status:
                                  type: string
                        created_at:
                          type: string
                example:
                  data:
                  - id: 51204
                    description: updated
                    event: updated
                    causer: null
                    properties:
                      old:
                        fulfillment_order_status: PROCESSING
                      attributes:
                        fulfillment_order_status: COMPLETE
                    created_at: '2026-06-28T17:44:09.000000Z'
                  - id: 50981
                    description: created
                    event: created
                    causer:
                      id: 12
                      name: Jane Doe
                      email: jane@example.com
                    properties:
                      old: null
                      attributes:
                        seller_fulfillment_order_id: SO-102431
                        fulfillment_order_status: RECEIVED
                    created_at: '2026-06-27T10:02:51.000000Z'
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: object
                    properties:
                      Modules\Amazon\Entities\AmazonFulfillmentOrder:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: array
                  status:
                    type: string
                  message:
                    type: string
                example:
                  errors:
                    Modules\Amazon\Entities\AmazonFulfillmentOrder:
                    - message: No query results for model [Modules\Amazon\Entities\AmazonFulfillmentOrder]
                        99999
                      code: NotFound
                      data: []
                  status: failure
                  message: No query results for model [Modules\Amazon\Entities\AmazonFulfillmentOrder]
                    99999
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-amazon-unified-fulfillment-orders-fulfillmentorder-activity-log
  /api/amazon/unified/fba-storage-fees:
    get:
      tags:
      - Amazon
      summary: List FBA Storage Fees (Across Instances)
      description: 'Paginated monthly FBA storage fee report rows (GET_FBA_STORAGE_FEE_CHARGES_DATA)
        aggregated across all Amazon integration instances. One row per FNSKU per
        fulfillment center per charge month.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires a Bearer token (Personal Access Token).


        Filters: integration_instance_ids (comma-separated), currency, country_code,
        month_of_charge (single Y-m-d month), search (fnsku/asin/product_name/fulfillment_center/product_size_tier/integration
        name), plus advanced text filters (fnsku, asin, product_name, fulfillment_center,
        country_code, product_size_tier — each with a *_op operator), advanced numeric
        filters (average_quantity_on_hand, base_rate, estimated_monthly_storage_fee),
        and advanced datetime filters (month_of_charge, created_at, updated_at).


        Pagination: page (default 1), per_page (default 10, min 1).


        Cost entries: importing these rows has no accounting impact unless the per-instance
        ''Automatically create cost entries from FBA storage fee reports'' setting
        is enabled, in which case each month''s report becomes a cost entry with per-product
        allocations.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        integration_instance_name:
                          type: string
                        amazon_report_id:
                          type: integer
                        month_of_charge:
                          type: string
                        asin:
                          type: string
                        fnsku:
                          type: string
                        product_name:
                          type: string
                        amazon_fnsku_product_id:
                          type: integer
                        fulfillment_center:
                          type: string
                        country_code:
                          type: string
                        average_quantity_on_hand:
                          type: number
                        product_size_tier:
                          type: string
                        base_rate:
                          type: number
                        estimated_monthly_storage_fee:
                          type: integer
                        currency:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                        cost_entry_id:
                          type: integer
                        cost_entry:
                          type: object
                          properties:
                            id:
                              type: integer
                            reference_number:
                              type: string
                            amount:
                              type: number
                            route:
                              type: string
                        cost_allocation:
                          type: object
                          properties:
                            id:
                              type: integer
                            amount:
                              type: integer
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - id: 1024
                    integration_instance_id: 3
                    integration_instance_name: AMZ partusa
                    amazon_report_id: 8841
                    month_of_charge: '2026-03-01'
                    asin: B0TEST0001
                    fnsku: X00TESTAA1
                    product_name: Widget A
                    amazon_fnsku_product_id: 551
                    fulfillment_center: PHX3
                    country_code: US
                    average_quantity_on_hand: 120.5
                    product_size_tier: Large standard-size
                    base_rate: 0.78
                    estimated_monthly_storage_fee: 18
                    currency: USD
                    created_at: '2026-04-05T09:15:00+00:00'
                    updated_at: '2026-04-05T09:15:00+00:00'
                    cost_entry_id: 1
                    cost_entry:
                      id: 1
                      reference_number: AMZ-STORAGE-3-2026-05
                      amount: 361.32
                      route: /accounting/cost-entries/1
                    cost_allocation:
                      id: 5012
                      amount: 18
                  current_page: 1
                  last_page: 12
                  per_page: 10
                  total: 118
                  from: 1
                  to: 10
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-amazon-unified-fba-storage-fees
  /api/amazon/unified/fba-storage-fees/currencies:
    get:
      tags:
      - Amazon
      summary: List Storage Fee Currencies
      description: 'Distinct currency codes present across storage fee rows, optionally
        scoped to specific integration instances. Used to populate the Currency filter
        on the Storage Fees report page.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires a Bearer token (Personal Access Token).'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: string
                example:
                  data:
                  - USD
                  - CAD
                  - GBP
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-amazon-unified-fba-storage-fees-currencies
  /api/amazon/unified/fba-storage-fees/sync:
    post:
      tags:
      - Amazon
      summary: Request Latest Storage Fee Report (Sync)
      description: 'Request the FBA storage fee report (GET_FBA_STORAGE_FEE_CHARGES_DATA)
        from Amazon, backfilling from the instance''s FBA inventory tracking start
        month forward. Per instance, only the next contiguous block of charge months
        with NO data yet is requested (a single report covers a multi-month window),
        so months already imported are never re-requested. When every month through
        the last completed month is already present, no report is requested and the
        response carries requested=false.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Scope with filter[integration_instance_ids] (comma-separated) or integration_instance_ids.
        Returns 409 if a storage fee report is already in progress. Dispatches a tracked
        a background job per request (track via the tracked job log endpoints). Requires
        Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                integration_instance_ids:
                  type: string
              example:
                integration_instance_ids: 1,2
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 OK — report requested
                  value:
                    data:
                      requested: true
                      tracked_job_log_id: 12345
                      tracked_job_log_ids:
                      - 12345
                    message: Storage fee report requested
                example-1:
                  summary: 200 OK — already up to date
                  value:
                    data:
                      requested: false
                      tracked_job_log_id: null
                      tracked_job_log_ids: []
                    message: Storage fee data is already up to date — no new months
                      to request.
        '409':
          description: Conflict
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                  conflicting_report:
                    type: object
                    properties:
                      id:
                        type: integer
                      report_type:
                        type: string
                      report_type_label:
                        type: string
                      processing_status:
                        type: string
                      integration_instance_id:
                        type: integer
                      created_at:
                        type: string
                example:
                  success: false
                  message: An FBA Storage Fee report is already in progress.
                  conflicting_report:
                    id: 8842
                    report_type: GET_FBA_STORAGE_FEE_CHARGES_DATA
                    report_type_label: FBA Storage Fee Charges
                    processing_status: processing
                    integration_instance_id: 3
                    created_at: '2026-04-05T08:00:00+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-amazon-unified-fba-storage-fees-sync
  /api/amazon/unified/fba-storage-fees/cost-entry-setting:
    get:
      tags:
      - Amazon
      summary: Get Cost Entry Creation Setting
      description: 'Aggregate state of the per-instance "create cost entries from
        FBA storage fee reports" setting across the selected Amazon integrations.
        The same setting gates both the storage fee and aged-inventory surcharge reports.
        `enabled` is true when every instance has it on, false when all off, and null
        when mixed.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires a Bearer token (Personal Access Token).'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      enabled:
                        type: boolean
                      instance_count:
                        type: integer
                example:
                  data:
                    enabled: true
                    instance_count: 1
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-amazon-unified-fba-storage-fees-cost-entry-setting
    post:
      tags:
      - Amazon
      summary: Update Cost Entry Creation Setting
      description: 'Enable or disable cost entry creation across the selected Amazon
        integrations (omit integration_instance_ids to apply to all). Returns the
        resulting aggregate state. When enabled, future report runs turn each month''s
        report into a cost entry with per-product allocations.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Body: enabled (required boolean), integration_instance_ids (optional, comma-separated).


        Authentication: Requires a Bearer token (Personal Access Token).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                enabled:
                  type: boolean
                integration_instance_ids:
                  type: string
              example:
                enabled: true
                integration_instance_ids: 1,2
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      enabled:
                        type: boolean
                      instance_count:
                        type: integer
                example:
                  data:
                    enabled: true
                    instance_count: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-amazon-unified-fba-storage-fees-cost-entry-setting
  /api/amazon/unified/fba-storage-fees/schedule:
    get:
      tags:
      - Amazon
      summary: Get Report Schedule (Next Run)
      description: 'Report-pipeline status for the daily FBA storage fee and aged-inventory
        surcharge report requests, powering the always-visible status strip on each
        report page. Scoped to the selected (FBA-enabled) integration instances via
        the optional `integration_instance_ids` filter.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        For each report type (`storage_fee`, `aged_inventory_surcharge`) the response
        returns:

        - `cron` / `next_run` — the configured cron and next scheduled run (absolute
        ISO 8601), for the live countdown.

        - `state` — one of `in_progress`, `failed`, `idle` (up to date / healthy),
        `never_run`.

        - `looks_stuck` (bool) — true when an in-progress run has been pending longer
        than `stuck_threshold_hours`.

        - `stuck_threshold_hours` (int) — hours after which an in-progress run is
        flagged as stuck.

        - `in_progress_since` (ISO 8601|null) — when the oldest in-flight run was
        requested.

        - `last_success_at` (ISO 8601|null) — when the last report was successfully
        imported.

        - `last_failure_at` (ISO 8601|null) — when the last run failed (FATAL), if
        the most recent run failed.

        - `data_through_month` (YYYY-MM|null) — latest charge month the imported data
        covers.

        - `expected_through_month` (YYYY-MM) — the most recent charge month Amazon
        has finalised, which the data is expected to cover. Amazon finalises a month''s
        storage fees between the 7th and 15th of the following month (the aged-inventory
        surcharge is assessed on the 15th), so before the monthly `report_ready_day`
        this is the month *before* last; on/after it, the previous calendar month.

        - `awaiting_month` (YYYY-MM|null) — the latest calendar month still pending
        Amazon''s mid-month finalisation and not yet imported, or null when nothing
        is awaited. When set, the pipeline is correctly waiting on Amazon (not behind);
        the report is auto-requested once that month becomes ready.

        - `report_ready_day` (int) — day of the month (default 16) from which the
        previous month''s data is expected and requested.

        - `is_behind` (bool) — true when `data_through_month` is older than `expected_through_month`.

        - `instance_count` (int) — number of FBA-enabled instances in scope.


        Authentication: Requires a Bearer token (Personal Access Token).'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 OK
                  value:
                    data:
                      storage_fee:
                        cron: 40 1 * * *
                        next_run: '2026-07-01T01:40:00+00:00'
                        state: in_progress
                        looks_stuck: true
                        stuck_threshold_hours: 6
                        in_progress_since: '2026-06-10T01:40:12+00:00'
                        last_success_at: '2026-05-02T01:42:55+00:00'
                        last_failure_at: null
                        data_through_month: 2026-04
                        expected_through_month: 2026-05
                        awaiting_month: null
                        report_ready_day: 16
                        is_behind: true
                        instance_count: 2
                      aged_inventory_surcharge:
                        cron: 50 1 * * *
                        next_run: '2026-07-01T01:50:00+00:00'
                        state: idle
                        looks_stuck: false
                        stuck_threshold_hours: 6
                        in_progress_since: null
                        last_success_at: '2026-06-01T01:51:30+00:00'
                        last_failure_at: null
                        data_through_month: 2026-05
                        expected_through_month: 2026-05
                        awaiting_month: null
                        report_ready_day: 16
                        is_behind: false
                        instance_count: 2
                example-1:
                  summary: 200 OK (early in the month — awaiting Amazon finalisation)
                  value:
                    data:
                      storage_fee:
                        cron: 40 1 * * *
                        next_run: '2026-06-11T01:40:00+00:00'
                        state: idle
                        looks_stuck: false
                        stuck_threshold_hours: 6
                        in_progress_since: null
                        last_success_at: '2026-05-18T01:42:55+00:00'
                        last_failure_at: null
                        data_through_month: 2026-04
                        expected_through_month: 2026-04
                        awaiting_month: 2026-05
                        report_ready_day: 16
                        is_behind: false
                        instance_count: 2
                      aged_inventory_surcharge:
                        cron: 50 1 * * *
                        next_run: '2026-06-11T01:50:00+00:00'
                        state: idle
                        looks_stuck: false
                        stuck_threshold_hours: 6
                        in_progress_since: null
                        last_success_at: '2026-05-18T01:51:30+00:00'
                        last_failure_at: null
                        data_through_month: 2026-04
                        expected_through_month: 2026-04
                        awaiting_month: 2026-05
                        report_ready_day: 16
                        is_behind: false
                        instance_count: 2
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-amazon-unified-fba-storage-fees-schedule
  /api/amazon/unified/fba-storage-fees/process-cost-entries:
    post:
      tags:
      - Amazon
      summary: Process Cost Entries Now
      description: 'Runs the storage fee cost entry creation logic now on already-imported
        report data — building/refreshing one cost entry per month with per-product
        allocations, per FBA-enabled instance. Does NOT re-fetch from Amazon. The
        manual counterpart to the automatic per-instance setting. Returns tracked
        job log IDs so the UI can follow progress via the tracked job log endpoints.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Body: integration_instance_ids (optional, comma-separated; omit for all Amazon
        instances).


        Authentication: Requires a Bearer token (Personal Access Token).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                integration_instance_ids:
                  type: string
              example:
                integration_instance_ids: 1,2
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                      tracked_job_log_ids:
                        type: array
                        items:
                          type: integer
                example:
                  message: Cost entry processing started
                  data:
                    tracked_job_log_id: 90620
                    tracked_job_log_ids:
                    - 90620
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-amazon-unified-fba-storage-fees-process-cost-entries
  /api/amazon/cost-entries/{costEntry}/unmatched-fnskus:
    get:
      tags:
      - Amazon
      summary: Get Unmatched FNSKUs for Cost Entry
      description: 'For a cost entry automatically created from an Amazon storage
        fee report (monthly storage fees or the long-term/aged inventory surcharge),
        returns the per-FNSKU fee rows that could not be allocated to a product because
        the FNSKU has no product mapping.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        The unmatched breakdown is not persisted on the cost entry; it is recomputed
        on demand by re-aggregating the source report''s per-FNSKU fees for the entry''s
        source month with the same logic that built the original allocations. FNSKUs
        whose fee rounds to zero, or that have since been mapped to a product, are
        excluded.


        Each row contains: fnsku, product_name (as reported by Amazon, may be null),
        and fee (in major currency units). Returns 404 when the cost entry was not
        created from an Amazon report, when it is not a storage fee entry type, or
        when the source report no longer exists. This endpoint is not scoped to an
        integration instance.'
      parameters:
      - name: costEntry
        in: path
        schema:
          type: integer
        required: true
        description: Cost entry ID
        example: '801'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        fnsku:
                          type: string
                        product_name:
                          type: string
                        fee:
                          type: number
                  status:
                    type: string
                example:
                  data:
                  - fnsku: X002ABCDE1
                    product_name: Leaf Razor, Black
                    fee: 12.34
                  - fnsku: X003QWERT7
                    product_name: Shave Soap Refill 3-Pack
                    fee: 3.08
                  status: success
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: object
                    properties:
                      url:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: array
                  message:
                    type: string
                  status:
                    type: string
                example:
                  errors:
                    url:
                    - message: Cost entry was not created from an Amazon report.
                      code: NotFound
                      data: []
                  message: Cost entry was not created from an Amazon report.
                  status: failure
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-amazon-cost-entries-costentry-unmatched-fnskus
  /api/amazon/unified/fba-longterm-storage-fees:
    get:
      tags:
      - Amazon
      summary: List FBA Aged Inventory Surcharges (Across Instances)
      description: 'Paginated FBA aged-inventory surcharge (long-term storage fee)
        report rows (GET_FBA_FULFILLMENT_LONGTERM_STORAGE_FEE_CHARGES_DATA) aggregated
        across all Amazon integration instances. One row per aged-inventory snapshot
        per SKU.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires a Bearer token (Personal Access Token).


        Filters: integration_instance_ids, currency, country, surcharge_age_tier,
        snapshot_date (single Y-m-d), search (sku/fnsku/asin/product_name/surcharge_age_tier/integration
        name), plus advanced text filters (sku, fnsku, asin, product_name, condition,
        surcharge_age_tier, country — each with a *_op operator), advanced numeric
        filters (qty_charged, rate_surcharge, amount_charged), and advanced datetime
        filters (snapshot_date, created_at, updated_at).


        Pagination: page (default 1), per_page (default 10, min 1).


        Cost entries: importing these rows has no accounting impact unless the per-instance
        ''Automatically create cost entries from FBA storage fee reports'' setting
        is enabled, in which case each month''s surcharge becomes a cost entry with
        per-product allocations.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        integration_instance_name:
                          type: string
                        amazon_report_id:
                          type: integer
                        snapshot_date:
                          type: string
                        sku:
                          type: string
                        fnsku:
                          type: string
                        asin:
                          type: string
                        product_name:
                          type: string
                        amazon_fnsku_product_id:
                          type: integer
                        condition:
                          type: string
                        qty_charged:
                          type: integer
                        rate_surcharge:
                          type: number
                        amount_charged:
                          type: number
                        surcharge_age_tier:
                          type: string
                        currency:
                          type: string
                        country:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                        cost_entry_id:
                          type: integer
                        cost_entry:
                          type: object
                          properties:
                            id:
                              type: integer
                            reference_number:
                              type: string
                            amount:
                              type: number
                            route:
                              type: string
                        cost_allocation:
                          type: object
                          properties:
                            id:
                              type: integer
                            amount:
                              type: integer
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - id: 512
                    integration_instance_id: 3
                    integration_instance_name: AMZ partusa
                    amazon_report_id: 8902
                    snapshot_date: '2026-03-15'
                    sku: SKU-LT-1
                    fnsku: X00LTSFAA1
                    asin: B0LTSF0001
                    product_name: Aged Widget A
                    amazon_fnsku_product_id: 551
                    condition: SELLABLE
                    qty_charged: 4
                    rate_surcharge: 1.55
                    amount_charged: 6.2
                    surcharge_age_tier: 365+ days
                    currency: USD
                    country: US
                    created_at: '2026-04-05T09:15:00+00:00'
                    updated_at: '2026-04-05T09:15:00+00:00'
                    cost_entry_id: 1
                    cost_entry:
                      id: 1
                      reference_number: AMZ-LTSF-3-2026-05
                      amount: 361.32
                      route: /accounting/cost-entries/1
                    cost_allocation:
                      id: 5012
                      amount: 18
                  current_page: 1
                  last_page: 4
                  per_page: 10
                  total: 37
                  from: 1
                  to: 10
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-amazon-unified-fba-longterm-storage-fees
  /api/amazon/unified/fba-longterm-storage-fees/currencies:
    get:
      tags:
      - Amazon
      summary: List Aged Inventory Surcharge Currencies
      description: 'Distinct currency codes present across aged-inventory surcharge
        rows, optionally scoped to specific integration instances. Used to populate
        the Currency filter.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires a Bearer token (Personal Access Token).'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: string
                example:
                  data:
                  - USD
                  - CAD
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-amazon-unified-fba-longterm-storage-fees-currencies
  /api/amazon/unified/fba-longterm-storage-fees/sync:
    post:
      tags:
      - Amazon
      summary: Request Latest Aged Inventory Surcharge Report (Sync)
      description: 'Request the FBA aged inventory surcharge / long-term storage fee
        report (GET_FBA_FULFILLMENT_LONGTERM_STORAGE_FEE_CHARGES_DATA) from Amazon,
        backfilling from the instance''s FBA inventory tracking start month forward.
        Per instance, only the next contiguous block of charge months with NO data
        yet is requested (a single report covers a multi-month window), so months
        already imported are never re-requested. When every month through the last
        completed month is already present, no report is requested and the response
        carries requested=false.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Scope with filter[integration_instance_ids] (comma-separated) or integration_instance_ids.
        Returns 409 if an aged inventory surcharge report is already in progress.
        Dispatches a tracked a background job per request (track via the tracked job
        log endpoints). Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                integration_instance_ids:
                  type: string
              example:
                integration_instance_ids: 1,2
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 OK — report requested
                  value:
                    data:
                      requested: true
                      tracked_job_log_id: 12346
                      tracked_job_log_ids:
                      - 12346
                    message: Aged inventory surcharge report requested
                example-1:
                  summary: 200 OK — already up to date
                  value:
                    data:
                      requested: false
                      tracked_job_log_id: null
                      tracked_job_log_ids: []
                    message: Aged inventory surcharge data is already up to date —
                      no new months to request.
        '409':
          description: Conflict
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                  conflicting_report:
                    type: object
                    properties:
                      id:
                        type: integer
                      report_type:
                        type: string
                      report_type_label:
                        type: string
                      processing_status:
                        type: string
                      integration_instance_id:
                        type: integer
                      created_at:
                        type: string
                example:
                  success: false
                  message: An FBA Aged Inventory Surcharge report is already in progress.
                  conflicting_report:
                    id: 8903
                    report_type: GET_FBA_FULFILLMENT_LONGTERM_STORAGE_FEE_CHARGES_DATA
                    report_type_label: FBA Aged Inventory Surcharge
                    processing_status: processing
                    integration_instance_id: 3
                    created_at: '2026-04-05T08:00:00+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-amazon-unified-fba-longterm-storage-fees-sync
  /api/amazon/unified/fba-longterm-storage-fees/process-cost-entries:
    post:
      tags:
      - Amazon
      summary: Process Cost Entries Now
      description: 'Runs the aged inventory surcharge cost entry creation logic now
        on already-imported report data — building/refreshing one cost entry per month
        with per-product allocations, per FBA-enabled instance. Does NOT re-fetch
        from Amazon. The manual counterpart to the automatic per-instance setting.
        Returns tracked job log IDs so the UI can follow progress via the tracked
        job log endpoints.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Body: integration_instance_ids (optional, comma-separated; omit for all Amazon
        instances).


        Authentication: Requires a Bearer token (Personal Access Token).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                integration_instance_ids:
                  type: string
              example:
                integration_instance_ids: 1,2
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                      tracked_job_log_ids:
                        type: array
                        items:
                          type: integer
                example:
                  message: Cost entry processing started
                  data:
                    tracked_job_log_id: 90620
                    tracked_job_log_ids:
                    - 90620
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-amazon-unified-fba-longterm-storage-fees-process-cost-entries
  /api/amazon/unified/fulfillment-centers:
    get:
      tags:
      - Amazon
      summary: List Fulfillment Centers (Across Instances)
      description: 'Distinct fulfillment centers across all five FC-bearing sources
        (storage fees, ledger, customer returns, shipments, inbound shipments). A
        fulfillment center is a virtual entity keyed by (integration instance, normalized
        FC code); every aggregate is computed in a single derived query, so the list
        is fully sortable and filterable on any aggregate column.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Each row carries: per-source counts (storage_fee_rows, ledger_events, customer_returns,
        shipments, inbound_shipments), total estimated storage fee (storage_fee_total),
        current on-hand units (inventory_quantity) and their approximate value at
        weighted-average cost (inventory_value), derived country (display only — not
        sortable/filterable), and last_activity (max created_at across sources).


        Filters: filter[search] / filter[code.*] on the FC code; filter[integration_instance_ids]
        (comma-separated); numeric advanced filters on storage_fee_rows, storage_fee_total,
        ledger_events, customer_returns, shipments, inbound_shipments, inventory_quantity,
        inventory_value (operators: is, is_not, is_one_of, greater_than, less_than,
        greater_than_or_equal, less_than_or_equal, between, is_empty, is_not_empty);
        datetime filter on last_activity (before, after, on_or_before, on_or_after,
        between, today, past_week, past_month, past_year, ...).


        Sort (sort=, prefix - for DESC). Allowed sorts: code, integration_instance_id,
        storage_fee_rows, storage_fee_total, ledger_events, customer_returns, shipments,
        inbound_shipments, inventory_quantity, inventory_value, last_activity. Default:
        code ASC.


        Paginated (per_page default 10). Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        code:
                          type: string
                        integration_instance_id:
                          type: integer
                        integration_instance_name:
                          type: string
                        country:
                          type: string
                        storage_fee_rows:
                          type: integer
                        ledger_events:
                          type: integer
                        customer_returns:
                          type: integer
                        shipments:
                          type: integer
                        inbound_shipments:
                          type: integer
                        storage_fee_total:
                          type: number
                        inventory_quantity:
                          type: integer
                        inventory_value:
                          type: number
                        last_activity:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - code: BNA2
                    integration_instance_id: 3
                    integration_instance_name: AMZ partusa
                    country: US
                    storage_fee_rows: 4
                    ledger_events: 41
                    customer_returns: 0
                    shipments: 25
                    inbound_shipments: 2
                    storage_fee_total: 4.55
                    inventory_quantity: 2
                    inventory_value: 2075.17
                    last_activity: '2026-06-12T21:26:17+00:00'
                  current_page: 1
                  last_page: 37
                  per_page: 10
                  total: 370
                  from: 1
                  to: 10
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-amazon-unified-fulfillment-centers
  /api/amazon/unified/fulfillment-centers/{code}:
    get:
      tags:
      - Amazon
      summary: Get Fulfillment Center Overview
      description: 'Aggregate KPIs for one fulfillment center: country, storage fee
        total, and counts of storage rows, ledger events, customer returns, shipments,
        and inbound shipments.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: code
        in: path
        schema:
          type: string
        required: true
        description: Fulfillment center code (case-insensitive; quotes auto-stripped)
        example: BNA2
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      code:
                        type: string
                      integration_instance_id:
                        type: integer
                      integration_instance_name:
                        type: string
                      country:
                        type: string
                      storage_fee_rows:
                        type: integer
                      ledger_events:
                        type: integer
                      customer_returns:
                        type: integer
                      shipments:
                        type: integer
                      inbound_shipments:
                        type: integer
                      storage_fee_total:
                        type: number
                      last_activity:
                        type: string
                example:
                  data:
                    code: BNA2
                    integration_instance_id: 3
                    integration_instance_name: AMZ partusa
                    country: US
                    storage_fee_rows: 4
                    ledger_events: 114
                    customer_returns: 0
                    shipments: 43
                    inbound_shipments: 2
                    storage_fee_total: 0.26
                    last_activity: '2026-06-12T21:26:17+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-unified-fulfillment-centers-code
  /api/amazon/unified/fulfillment-centers/{code}/storage-fees:
    get:
      tags:
      - Amazon
      summary: Storage Fees at FC
      description: 'Paginated monthly storage fee rows at this fulfillment center
        (normalized FC match).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: code
        in: path
        schema:
          type: string
        required: true
        description: Fulfillment center code (case-insensitive; quotes auto-stripped)
        example: BNA2
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                example:
                  data: []
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-unified-fulfillment-centers-code-storage-fees
  /api/amazon/unified/fulfillment-centers/{code}/ledgers:
    get:
      tags:
      - Amazon
      summary: Ledger Events at FC
      description: 'Paginated FBA inventory ledger events at this fulfillment center.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: code
        in: path
        schema:
          type: string
        required: true
        description: Fulfillment center code (case-insensitive; quotes auto-stripped)
        example: BNA2
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                example:
                  data: []
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-unified-fulfillment-centers-code-ledgers
  /api/amazon/unified/fulfillment-centers/{code}/customer-returns:
    get:
      tags:
      - Amazon
      summary: Customer Returns at FC
      description: 'Paginated customer returns processed at this fulfillment center.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: code
        in: path
        schema:
          type: string
        required: true
        description: Fulfillment center code (case-insensitive; quotes auto-stripped)
        example: BNA2
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                example:
                  data: []
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-unified-fulfillment-centers-code-customer-returns
  /api/amazon/unified/fulfillment-centers/{code}/shipments:
    get:
      tags:
      - Amazon
      summary: Shipments from FC
      description: 'Paginated outbound (customer) shipment lines from this fulfillment
        center.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: code
        in: path
        schema:
          type: string
        required: true
        description: Fulfillment center code (case-insensitive; quotes auto-stripped)
        example: BNA2
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                example:
                  data: []
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-unified-fulfillment-centers-code-shipments
  /api/amazon/unified/fulfillment-centers/{code}/inbound-shipments:
    get:
      tags:
      - Amazon
      summary: Inbound Shipments to FC
      description: 'Paginated inbound shipments destined for this fulfillment center.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: code
        in: path
        schema:
          type: string
        required: true
        description: Fulfillment center code (case-insensitive; quotes auto-stripped)
        example: BNA2
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                example:
                  data: []
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-unified-fulfillment-centers-code-inbound-shipments
  /api/amazon/unified/fba-reimbursements:
    get:
      tags:
      - Amazon
      summary: List FBA Reimbursements
      description: 'Paginated list of FBA reimbursements Amazon has already paid,
        unified across all Amazon integration instances. Rows are ingested from the
        FBA reimbursements report and form the authoritative payout log that reimbursement
        cases are reconciled against; `amazon_reimbursement_case_id` (and the embedded
        `reimbursement_case` object) is set when a row has been matched to a tracked
        case.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Pagination: `page` and `per_page` (default 10).

        Sorting: `sort=<field>` ascending or `sort=-<field>` descending. Sortable
        fields: id, reimbursement_id, approval_date, case_id, amazon_order_id, reason,
        reason_category, sku, fnsku, asin, amount_per_unit, amount_total, currency,
        quantity_reimbursed_cash, quantity_reimbursed_inventory, quantity_reimbursed_total,
        created_at, updated_at.


        Simple filters:

        - `filter[search]` — fuzzy search across reimbursement_id, case_id, amazon_order_id,
        sku, asin, fnsku, reason and the integration instance name. Restrict with
        `search_columns` and force exact matching per column with `search_strict_columns`.

        - `filter[integration_instance_ids]` — comma-separated Amazon integration
        instance IDs.

        - `filter[reason_category]` — comma-separated list of normalized reason categories.

        - `filter[currency]` — comma-separated list of currency codes.

        - `filter[has_case_id]` — true/false (also accepts 1/0, yes/no): rows that
        do or do not carry an Amazon case ID.

        - `filter[has_linked_case]` — true/false (also accepts 1/0, yes/no): rows
        that are or are not linked to a SKU.io reimbursement case.


        Advanced operator filters use the syntax `filter[column.operator]=value`;
        a bare `filter[column]=value` is treated as the `is` operator.

        - Text columns (reimbursement_id, case_id, amazon_order_id, reason, reason_category,
        sku, fnsku, asin, condition) support: contains, does_not_contain, is, is_not,
        is_one_of, is_not_one_of, starts_with, does_not_start_with, ends_with, does_not_end_with,
        is_empty, is_not_empty.

        - Numeric columns (amount_per_unit, amount_total, quantity_reimbursed_cash,
        quantity_reimbursed_inventory, quantity_reimbursed_total) support: is, is_not,
        is_one_of, is_not_one_of, greater_than, less_than, greater_than_or_equal,
        less_than_or_equal, between, is_empty, is_not_empty.

        - Date columns (approval_date, created_at, updated_at) support: is, is_not,
        before, after, on_or_before, on_or_after, between, is_empty, is_not_empty,
        today, yesterday, tomorrow, past_week, past_month, past_year, next_week, next_month,
        next_year, days_ago, days_from_now, past_days, next_days. Date values use
        ISO 8601 / Y-m-d; `between` takes two comma-separated values.


        Complex AND/OR filter trees can be sent via `filter_groups` (base64-encoded
        JSON tree of conditions and nested groups).'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        integration_instance_name:
                          type: string
                        reimbursement_id:
                          type: string
                        approval_date:
                          type: string
                        case_id:
                          type: string
                        amazon_order_id:
                          type: string
                        reason:
                          type: string
                        reason_category:
                          type: string
                        sku:
                          type: string
                        fnsku:
                          type: string
                        asin:
                          type: string
                        condition:
                          type: string
                        product_id:
                          type: integer
                        amazon_fnsku_product_id:
                          type: integer
                        amount_per_unit:
                          type: number
                        amount_total:
                          type: number
                        currency:
                          type: string
                        quantity_reimbursed_cash:
                          type: integer
                        quantity_reimbursed_inventory:
                          type: integer
                        quantity_reimbursed_total:
                          type: integer
                        amazon_reimbursement_case_id:
                          type: integer
                        reimbursement_case:
                          type: object
                          properties:
                            id:
                              type: integer
                            status:
                              type: string
                            amazon_case_id:
                              type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                    items:
                      type: object
                      properties:
                        url:
                          type: string
                          nullable: true
                        label:
                          type: string
                        active:
                          type: boolean
                  next_page_url:
                    type: string
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 1187
                    integration_instance_id: 3
                    integration_instance_name: Amazon US
                    reimbursement_id: '6740912345'
                    approval_date: '2026-06-02T00:00:00+00:00'
                    case_id: '17389245671'
                    amazon_order_id: 113-4092817-5544312
                    reason: CustomerReturn
                    reason_category: customer_return_not_received
                    sku: LEAF-RAZOR-STD
                    fnsku: X001M8KQZ3
                    asin: B0B7H2JKLM
                    condition: SELLABLE
                    product_id: 655
                    amazon_fnsku_product_id: 1994
                    amount_per_unit: 18.9
                    amount_total: 18.9
                    currency: USD
                    quantity_reimbursed_cash: 1
                    quantity_reimbursed_inventory: 0
                    quantity_reimbursed_total: 1
                    amazon_reimbursement_case_id: 38
                    reimbursement_case:
                      id: 38
                      status: reimbursed
                      amazon_case_id: '17389245671'
                    created_at: '2026-06-03T04:10:22+00:00'
                    updated_at: '2026-06-03T04:10:22+00:00'
                  - id: 1163
                    integration_instance_id: 3
                    integration_instance_name: Amazon US
                    reimbursement_id: '6738554821'
                    approval_date: '2026-05-27T00:00:00+00:00'
                    case_id: null
                    amazon_order_id: null
                    reason: Lost_Warehouse
                    reason_category: warehouse_lost
                    sku: BCK-CANISTER-16OZ
                    fnsku: X002QDR3V7
                    asin: B08XYZ4Q2M
                    condition: SELLABLE
                    product_id: 918
                    amazon_fnsku_product_id: 2451
                    amount_per_unit: 14.25
                    amount_total: 28.5
                    currency: USD
                    quantity_reimbursed_cash: 2
                    quantity_reimbursed_inventory: 0
                    quantity_reimbursed_total: 2
                    amazon_reimbursement_case_id: null
                    reimbursement_case: null
                    created_at: '2026-05-28T04:09:47+00:00'
                    updated_at: '2026-05-28T04:09:47+00:00'
                  first_page_url: '{{protocol}}://{{domain}}/api/amazon/unified/fba-reimbursements?page=1'
                  from: 1
                  last_page: 22
                  last_page_url: '{{protocol}}://{{domain}}/api/amazon/unified/fba-reimbursements?page=22'
                  links:
                  - url: null
                    label: '&laquo; Previous'
                    active: false
                  - url: '{{protocol}}://{{domain}}/api/amazon/unified/fba-reimbursements?page=1'
                    label: '1'
                    active: true
                  - url: '{{protocol}}://{{domain}}/api/amazon/unified/fba-reimbursements?page=2'
                    label: '2'
                    active: false
                  - url: '{{protocol}}://{{domain}}/api/amazon/unified/fba-reimbursements?page=2'
                    label: Next &raquo;
                    active: false
                  next_page_url: '{{protocol}}://{{domain}}/api/amazon/unified/fba-reimbursements?page=2'
                  path: '{{protocol}}://{{domain}}/api/amazon/unified/fba-reimbursements'
                  per_page: 10
                  prev_page_url: null
                  to: 2
                  total: 214
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-amazon-unified-fba-reimbursements
  /api/amazon/unified/fba-reimbursements/currencies:
    get:
      tags:
      - Amazon
      summary: List FBA Reimbursement Currencies
      description: 'Returns the distinct currency codes present in the stored FBA
        reimbursements, sorted alphabetically — useful for populating a currency filter.
        Optionally scope to specific instances with `integration_instance_ids` (comma-separated).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: string
                example:
                  data:
                  - CAD
                  - USD
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-amazon-unified-fba-reimbursements-currencies
  /api/amazon/unified/fba-reimbursements/sync:
    post:
      tags:
      - Amazon
      summary: Sync FBA Reimbursements
      description: 'Requests a fresh FBA reimbursements report from Amazon for every
        Amazon integration instance (or the subset given in `integration_instance_ids`)
        and ingests the rows into the unified payout log. Queues a background job;
        returns a job id (`tracked_job_log_id`) for polling progress.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Amazon only allows one FBA reimbursements report in flight per account, so
        if a matching report is already being generated the request is rejected with
        HTTP 409 and details of the conflicting report.


        `integration_instance_ids` accepts an array of integers or a comma-separated
        string; omit it (or send an empty value) to sync every Amazon instance.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                integration_instance_ids:
                  type: array
                  items:
                    type: integer
              example:
                integration_instance_ids:
                - 3
                - 7
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                example:
                  message: Reimbursement sync started
                  data:
                    tracked_job_log_id: 15240
        '409':
          description: Conflict
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                  conflicting_report:
                    type: object
                    properties:
                      id:
                        type: integer
                      report_type:
                        type: string
                      report_type_label:
                        type: string
                      processing_status:
                        type: string
                      integration_instance_id:
                        type: integer
                      created_at:
                        type: string
                example:
                  success: false
                  message: An FBA Reimbursements report is already in progress.
                  conflicting_report:
                    id: 5123
                    report_type: GET_FBA_REIMBURSEMENTS_DATA
                    report_type_label: FBA Reimbursements
                    processing_status: IN_PROGRESS
                    integration_instance_id: 3
                    created_at: '2026-07-06T18:04:11+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-amazon-unified-fba-reimbursements-sync
  /api/amazon/instances/{integrationInstance}/notification-subscriptions:
    get:
      tags:
      - Amazon
      summary: List Notification Subscriptions (with health)
      description: 'List every SP-API push-notification subscription (any status)
        for the given Amazon integration instance, each with a computed `healthy`
        flag. A subscription is healthy when it is ACTIVE and has seen an event (or,
        if brand-new, been alive) within the `window_minutes` silence window (config
        `amazon.notifications.health_window_minutes`, default 120). Backs the per-instance
        Notification Health panel. Requires an initialized tenant context.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Amazon integration instance ID
        example: '3'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        notification_type:
                          type: string
                        phase:
                          type: integer
                        channel:
                          type: string
                        subscription_id:
                          type: string
                        destination_id:
                          type: string
                        payload_version:
                          type: string
                        status:
                          type: string
                        last_event_at:
                          type: string
                        healthy:
                          type: boolean
                        window_minutes:
                          type: integer
                        created_at:
                          type: string
                        updated_at:
                          type: string
                example:
                  data:
                  - id: 12
                    integration_instance_id: 3
                    notification_type: ORDER_CHANGE
                    phase: 2
                    channel: sqs
                    subscription_id: b1d4c0e2-9f3a-4d5b-8c7e-1a2b3c4d5e6f
                    destination_id: 9a8b7c6d-5e4f-3210-fedc-ba9876543210
                    payload_version: '1.0'
                    status: active
                    last_event_at: '2026-06-09T11:42:00+00:00'
                    healthy: true
                    window_minutes: 120
                    created_at: '2026-06-01T08:00:00+00:00'
                    updated_at: '2026-06-09T11:42:00+00:00'
                  - id: 13
                    integration_instance_id: 3
                    notification_type: LISTINGS_ITEM_ISSUES_CHANGE
                    phase: 5
                    channel: eventbridge
                    subscription_id: c2e5d1f3-0a4b-5e6c-9d8f-2b3c4d5e6f70
                    destination_id: 0b9c8d7e-6f50-4321-0edc-cb9876543211
                    payload_version: '1.0'
                    status: active
                    last_event_at: null
                    healthy: true
                    window_minutes: 120
                    created_at: '2026-06-09T11:30:00+00:00'
                    updated_at: '2026-06-09T11:30:00+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-instances-integrationinstance-notification-subscriptions
    delete:
      tags:
      - Amazon
      summary: Tear Down All Subscriptions
      description: 'Tear down every active subscription for the instance. Best-effort
        on Amazon''s side (per-type), always marked deleted locally. Returns the count
        of subscriptions unsubscribed. Requires an initialized tenant context.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Amazon integration instance ID
        example: '3'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      unsubscribed:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    unsubscribed: 4
                  message: Subscriptions torn down
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-amazon-instances-integrationinstance-notification-subscriptions
  /api/amazon/instances/{integrationInstance}/notification-subscriptions/resync:
    post:
      tags:
      - Amazon
      summary: Resync (Reconcile) Subscriptions
      description: 'Force a reconcile: converge the instance''s live subscriptions
        onto exactly what its enabled phase flags imply — create newly-enabled notification
        types, re-point relocated SQS/EventBridge destinations, and tear down disabled
        types. Idempotent and safe to re-run after a partial failure; degrades per-type
        rather than aborting, so one failing type never blocks the rest. Returns counts
        of what changed. Requires an initialized tenant context.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Amazon integration instance ID
        example: '3'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      subscribed:
                        type: integer
                      unsubscribed:
                        type: integer
                      skipped:
                        type: integer
                      failed:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    subscribed: 3
                    unsubscribed: 1
                    skipped: 9
                    failed: 0
                  message: Subscriptions reconciled
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-amazon-instances-integrationinstance-notification-subscriptions-resync
  /api/amazon/notification-events:
    get:
      tags:
      - Amazon
      summary: List Notification Events (audit log, paginated)
      description: 'Paginated debug/audit log of delivered SP-API notification events
        across all Amazon instances, newest first. Read-only — lets support staff
        inspect exactly what Amazon delivered and how each event was processed (pending/processing/processed/failed,
        plus the raw payload and any error) when reconciling a missed or mis-handled
        notification. Filter by notification_type, processing_status, integration_instance_ids,
        or a free-text search over notification_id/error.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        integration_instance_name:
                          type: string
                        notification_id:
                          type: string
                        notification_type:
                          type: string
                        phase:
                          type: integer
                        payload_version:
                          type: string
                        event_time:
                          type: string
                        processing_status:
                          type: string
                        processed_at:
                          type: string
                        error:
                          type: string
                          nullable: true
                        payload:
                          type: object
                          properties:
                            NotificationType:
                              type: string
                            Payload:
                              type: object
                              properties:
                                OrderChangeNotification:
                                  type: object
                                  properties:
                                    AmazonOrderId:
                                      type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - id: 5012
                    integration_instance_id: 3
                    integration_instance_name: Amazon US - Main
                    notification_id: a1b2c3d4-0000-1111-2222-333344445555
                    notification_type: ORDER_CHANGE
                    phase: 2
                    payload_version: '1.0'
                    event_time: '2026-06-09T11:42:00+00:00'
                    processing_status: processed
                    processed_at: '2026-06-09T11:42:03+00:00'
                    error: null
                    payload:
                      NotificationType: ORDER_CHANGE
                      Payload:
                        OrderChangeNotification:
                          AmazonOrderId: 111-2223334-5556667
                    created_at: '2026-06-09T11:42:01+00:00'
                    updated_at: '2026-06-09T11:42:03+00:00'
                  - id: 5011
                    integration_instance_id: 3
                    integration_instance_name: Amazon US - Main
                    notification_id: b2c3d4e5-1111-2222-3333-444455556666
                    notification_type: LISTINGS_ITEM_ISSUES_CHANGE
                    phase: 5
                    payload_version: '1.0'
                    event_time: '2026-06-09T11:40:00+00:00'
                    processing_status: failed
                    processed_at: '2026-06-09T11:40:02+00:00'
                    error: No matching AmazonProduct for SKU ABC-123
                    payload:
                      NotificationType: LISTINGS_ITEM_ISSUES_CHANGE
                      Payload: {}
                    created_at: '2026-06-09T11:40:01+00:00'
                    updated_at: '2026-06-09T11:40:02+00:00'
                  current_page: 1
                  last_page: 12
                  per_page: 10
                  total: 118
                  from: 1
                  to: 10
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-amazon-notification-events
  /api/amazon/{integrationInstance}/replenishment:
    get:
      tags:
      - Amazon
      summary: Replenishment Grid
      description: 'Paginated FBA replenishment grid for an Amazon integration instance.
        Rows start from listed Amazon products (so products without existing FBA inventory
        or a restock report still appear), enriched with:


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        - FBA stock position (available, inbound, reserved) from the FBA inventory
        report

        - Amazon restock recommendation data (GET_RESTOCK_INVENTORY_RECOMMENDATIONS_REPORT)
        when present

        - Channel-scoped sales velocity (this instance''s sales channel) and other-channel
        velocity

        - Origin warehouse availability + other-warehouse stock (warehouse transfer
        mode)

        - Supplier stock, MOQ and lead time (purchase order mode)

        - Quantity already committed on open draft inbound plans and open backorders

        - A calculated suggestion: TargetUnits = ceil(velocity x (target_days + lead_time
        + buffer)) minus net at Amazon, capped by origin/supplier availability, rounded
        down to case packs, with MOQ handling in PO mode


        Sorted by Amazon''s recommended replenishment quantity (desc, nulls last),
        then product SKU.


        Authentication: Bearer token.


        Validation: source_mode is required; origin_warehouse_id is required for WAREHOUSE_TRANSFER;
        supplier_id is required for PURCHASE_ORDER.


        Each row includes `amazon_product_id` (the AmazonProduct row id) for deep-linking
        to the Amazon product detail page.


        Supports server `sort` and advanced `filter_groups` (GroupedFilterSupport).
        In PURCHASE_ORDER mode with `supplier_id`, rows are scoped to that supplier''s
        catalog and each row carries `is_default_supplier` (false = supplier carries
        the product but isn''t its default). Rows also include `amazon_fnsku_product_id`,
        `unit_weight_lb`, and `unit_volume_cuft` (for cart weight/volume/pallet estimates).
        Each row''s `case_pack_qty` / `case_pack_rounding` come from the product''s
        replenishment settings override, falling back to the instance default. Rows
        also carry the product''s master-carton data — `units_per_case`, `case_weight_lb`,
        `case_volume_cuft` (normalized from the product''s case-pack dimensions) —
        used to estimate cartons, pallet weight and pallet count in the cart.'
      parameters:
      - name: source_mode
        in: query
        schema:
          type: string
        description: Required. WAREHOUSE_TRANSFER or PURCHASE_ORDER — determines sourcing
          context for suggestions
        example: WAREHOUSE_TRANSFER
      - name: origin_warehouse_id
        in: query
        schema:
          type: integer
        description: Required when source_mode=WAREHOUSE_TRANSFER. Warehouse the transfer
          ships from
        example: '3'
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        amazon_product_id:
                          type: integer
                        amazon_fnsku_product_id:
                          type: integer
                        is_default_supplier:
                          type: string
                          nullable: true
                        unit_weight_lb:
                          type: number
                        unit_volume_cuft:
                          type: number
                        units_per_case:
                          type: integer
                        case_weight_lb:
                          type: integer
                        case_volume_cuft:
                          type: number
                        product_id:
                          type: integer
                        product_sku:
                          type: string
                        product_name:
                          type: string
                        product_image_url:
                          type: string
                        msku:
                          type: string
                        asin:
                          type: string
                        fnsku:
                          type: string
                        country_code:
                          type: string
                        fba_available:
                          type: integer
                        fba_inbound:
                          type: integer
                        fba_reserved:
                          type: integer
                        velocity:
                          type: number
                        velocity_window_days:
                          type: integer
                        other_channel_velocity:
                          type: number
                        planned_unshipped:
                          type: integer
                        open_backorders:
                          type: integer
                        origin_available:
                          type: integer
                        other_warehouse_stock:
                          type: integer
                        on_purchase_order:
                          type: integer
                        supplier_stock_qty:
                          type: string
                          nullable: true
                        supplier_in_stock:
                          type: string
                          nullable: true
                        supplier_lead_time_days:
                          type: string
                          nullable: true
                        minimum_order_quantity:
                          type: string
                          nullable: true
                        case_pack_qty:
                          type: integer
                        case_pack_rounding:
                          type: string
                        target_days_of_supply:
                          type: integer
                        buffer_days:
                          type: integer
                        lead_time_days:
                          type: integer
                        restock_units_sold_last_30_days:
                          type: integer
                        restock_total_days_of_supply:
                          type: number
                        restock_alert:
                          type: string
                        restock_recommended_qty:
                          type: integer
                        restock_recommended_ship_date:
                          type: string
                        suggestion:
                          type: object
                          properties:
                            target_units:
                              type: integer
                            net_at_amazon:
                              type: integer
                            raw_suggested:
                              type: integer
                            reserve_other:
                              type: integer
                            cap:
                              type: integer
                            suggested_quantity:
                              type: integer
                            pre_rounding_quantity:
                              type: integer
                            is_overstocked:
                              type: boolean
                            is_capped:
                              type: boolean
                            is_case_pack_rounded:
                              type: boolean
                            moq_bumped:
                              type: boolean
                            below_moq:
                              type: boolean
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                  next_page_url:
                    type: string
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - amazon_product_id: 184
                    amazon_fnsku_product_id: 91
                    is_default_supplier: null
                    unit_weight_lb: 1.3
                    unit_volume_cuft: 0.05
                    units_per_case: 4
                    case_weight_lb: 36
                    case_volume_cuft: 6.15
                    product_id: 101
                    product_sku: WIDGET-001
                    product_name: Blue Widget
                    product_image_url: https://cdn.example.com/widget.jpg
                    msku: WIDGET-001-FBA
                    asin: B00WIDGET1
                    fnsku: X00WIDGET1
                    country_code: US
                    fba_available: 42
                    fba_inbound: 24
                    fba_reserved: 3
                    velocity: 4.5
                    velocity_window_days: 30
                    other_channel_velocity: 1.2
                    planned_unshipped: 12
                    open_backorders: 5
                    origin_available: 320
                    other_warehouse_stock: 80
                    on_purchase_order: 150
                    supplier_stock_qty: null
                    supplier_in_stock: null
                    supplier_lead_time_days: null
                    minimum_order_quantity: null
                    case_pack_qty: 6
                    case_pack_rounding: always_round_down
                    target_days_of_supply: 30
                    buffer_days: 7
                    lead_time_days: 0
                    restock_units_sold_last_30_days: 135
                    restock_total_days_of_supply: 14.6
                    restock_alert: Low inventory
                    restock_recommended_qty: 120
                    restock_recommended_ship_date: '2026-06-20'
                    suggestion:
                      target_units: 167
                      net_at_amazon: 78
                      raw_suggested: 89
                      reserve_other: 0
                      cap: 320
                      suggested_quantity: 84
                      pre_rounding_quantity: 89
                      is_overstocked: false
                      is_capped: false
                      is_case_pack_rounded: true
                      moq_bumped: false
                      below_moq: false
                  first_page_url: https://sku.test/api/amazon/1/replenishment?page=1
                  from: 1
                  last_page: 4
                  last_page_url: https://sku.test/api/amazon/1/replenishment?page=4
                  links: []
                  next_page_url: https://sku.test/api/amazon/1/replenishment?page=2
                  path: https://sku.test/api/amazon/1/replenishment
                  per_page: 25
                  prev_page_url: null
                  to: 25
                  total: 93
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      origin_warehouse_id:
                        type: array
                        items:
                          type: string
                example:
                  message: An origin warehouse is required for warehouse transfer
                    plans.
                  errors:
                    origin_warehouse_id:
                    - An origin warehouse is required for warehouse transfer plans.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-integrationinstance-replenishment
  /api/amazon/{integrationInstance}/replenishment/refresh:
    post:
      tags:
      - Amazon
      summary: Refresh Restock Report
      description: 'Request a fresh GET_RESTOCK_INVENTORY_RECOMMENDATIONS_REPORT from
        Amazon for this instance. The report is created immediately and monitored
        via a tracked job — use the returned tracked_job_log_id with the tracked job
        log endpoints.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Returns 409 Conflict when a restock report request is already in progress
        for this instance, including details of the conflicting report.


        Authentication: Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 5512
                  message: Restock report refresh started
        '409':
          description: Conflict
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  conflicting_report:
                    type: object
                    properties:
                      id:
                        type: integer
                      report_type:
                        type: string
                      processing_status:
                        type: string
                      created_at:
                        type: string
                example:
                  message: A report of this type is already being processed
                  conflicting_report:
                    id: 991
                    report_type: GET_RESTOCK_INVENTORY_RECOMMENDATIONS_REPORT
                    processing_status: IN_PROGRESS
                    created_at: '2026-06-12T14:05:00+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-amazon-integrationinstance-replenishment-refresh
  /api/amazon/{integrationInstance}/replenishment/settings:
    get:
      tags:
      - Amazon
      summary: Get Replenishment Settings
      description: 'Replenishment settings for this instance: the instance-level default
        (product_id null) plus any per-product overrides, and the timestamp of the
        last restock report refresh.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Settings control the suggestion formula: target_days_of_supply, buffer_days,
        velocity_window_days, case_pack_qty, min_shelf_life_days and blackout_dates.


        Authentication: Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      default:
                        type: object
                        properties:
                          id:
                            type: integer
                          integration_instance_id:
                            type: integer
                          product_id:
                            type: string
                            nullable: true
                          target_days_of_supply:
                            type: integer
                          buffer_days:
                            type: integer
                          velocity_window_days:
                            type: integer
                          case_pack_qty:
                            type: string
                            nullable: true
                          min_shelf_life_days:
                            type: string
                            nullable: true
                          blackout_dates:
                            type: string
                            nullable: true
                          created_at:
                            type: string
                          updated_at:
                            type: string
                          case_pack_rounding:
                            type: string
                      overrides:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            integration_instance_id:
                              type: integer
                            product_id:
                              type: integer
                            target_days_of_supply:
                              type: integer
                            buffer_days:
                              type: integer
                            velocity_window_days:
                              type: integer
                            case_pack_qty:
                              type: integer
                            min_shelf_life_days:
                              type: integer
                            blackout_dates:
                              type: string
                              nullable: true
                            created_at:
                              type: string
                            updated_at:
                              type: string
                            case_pack_rounding:
                              type: string
                      restock_report_generated_at:
                        type: string
                example:
                  data:
                    default:
                      id: 1
                      integration_instance_id: 1
                      product_id: null
                      target_days_of_supply: 30
                      buffer_days: 7
                      velocity_window_days: 30
                      case_pack_qty: null
                      min_shelf_life_days: null
                      blackout_dates: null
                      created_at: '2026-06-10T09:00:00.000000Z'
                      updated_at: '2026-06-10T09:00:00.000000Z'
                      case_pack_rounding: always_round_down
                    overrides:
                    - id: 2
                      integration_instance_id: 1
                      product_id: 101
                      target_days_of_supply: 21
                      buffer_days: 3
                      velocity_window_days: 14
                      case_pack_qty: 6
                      min_shelf_life_days: 90
                      blackout_dates: null
                      created_at: '2026-06-11T10:00:00.000000Z'
                      updated_at: '2026-06-11T10:00:00.000000Z'
                      case_pack_rounding: always_round_down
                    restock_report_generated_at: '2026-06-12T03:15:42+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-integrationinstance-replenishment-settings
    put:
      tags:
      - Amazon
      summary: Update Replenishment Settings
      description: 'Upsert replenishment settings. Omit product_id (or send null)
        to update the instance-level default; send a product_id to create/update a
        per-product override.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Fields:

        - product_id: optional integer, must exist in products. Null = instance default

        - target_days_of_supply: required integer 1-365. Days of FBA coverage to target

        - buffer_days: required integer 0-365. Safety buffer added to the planning
        horizon

        - velocity_window_days: required integer 1-365. Trailing sales window used
        to compute daily velocity

        - case_pack_qty: optional integer >= 1. Suggestions round DOWN to whole case
        packs

        - min_shelf_life_days: optional integer >= 0

        - blackout_dates: optional array of dates


        Authentication: Bearer token.


        **`case_pack_rounding`** (string, optional) — how suggested quantities round
        to full cases for products with a `case_pack_qty`: `always_round_down` (default
        — never exceed the target/cap), `always_round_up` (ship full cases; may overshoot
        the coverage target but never the origin/supplier stock cap), or `round_nearest`.


        case_pack_rounding accepts: always_round_up, always_round_down, round_nearest,
        none (send the exact suggested quantity, no case-pack rounding).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                product_id:
                  type: integer
                target_days_of_supply:
                  type: integer
                buffer_days:
                  type: integer
                velocity_window_days:
                  type: integer
                case_pack_qty:
                  type: integer
                min_shelf_life_days:
                  type: integer
                blackout_dates:
                  type: array
                  items:
                    type: string
                case_pack_rounding:
                  type: string
              example:
                product_id: 101
                target_days_of_supply: 21
                buffer_days: 3
                velocity_window_days: 14
                case_pack_qty: 6
                min_shelf_life_days: 90
                blackout_dates:
                - '2026-11-26'
                - '2026-12-25'
                case_pack_rounding: always_round_up
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      product_id:
                        type: integer
                      target_days_of_supply:
                        type: integer
                      buffer_days:
                        type: integer
                      velocity_window_days:
                        type: integer
                      case_pack_qty:
                        type: integer
                      min_shelf_life_days:
                        type: integer
                      blackout_dates:
                        type: array
                        items:
                          type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      case_pack_rounding:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 2
                    integration_instance_id: 1
                    product_id: 101
                    target_days_of_supply: 21
                    buffer_days: 3
                    velocity_window_days: 14
                    case_pack_qty: 6
                    min_shelf_life_days: 90
                    blackout_dates:
                    - '2026-11-26'
                    - '2026-12-25'
                    created_at: '2026-06-11T10:00:00.000000Z'
                    updated_at: '2026-06-11T10:00:00.000000Z'
                    case_pack_rounding: always_round_down
                  message: Replenishment settings saved
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      target_days_of_supply:
                        type: array
                        items:
                          type: string
                      buffer_days:
                        type: array
                        items:
                          type: string
                      velocity_window_days:
                        type: array
                        items:
                          type: string
                example:
                  message: The target days of supply field is required. (and 2 more
                    errors)
                  errors:
                    target_days_of_supply:
                    - The target days of supply field is required.
                    buffer_days:
                    - The buffer days field is required.
                    velocity_window_days:
                    - The velocity window days field is required.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: put-api-amazon-integrationinstance-replenishment-settings
  /api/amazon-ads/{integrationInstance}/settings:
    put:
      tags:
      - Amazon
      summary: Update Amazon Ads Settings
      description: 'Update per-connection Amazon Ads settings. Currently this toggles
        whether a spend sync turns ad spend into cost entries (type "Amazon Advertising")
        with per-product cost allocations on mapped SKUs.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Cost-entry creation is opt-in and disabled by default. When enabled, each
        Sync Amazon Ads Spend creates/refreshes per-day cost entries and product allocations.
        When disabled (the default), the spend ledger still updates but has no accounting
        impact, and a sync removes any cost entries a prior sync created for the synced
        window.


        Body:

        - cost_entry_creation_enabled (boolean, required): turn cost-entry creation
        on/off.


        Returns the updated Amazon Ads connection resource. Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                cost_entry_creation_enabled:
                  type: boolean
              example:
                cost_entry_creation_enabled: false
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Amazon Ads integration instance id
        example: '7'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      region:
                        type: string
                      is_connected:
                        type: boolean
                      is_automatic_sync_enabled:
                        type: boolean
                      sync_status:
                        type: string
                      profiles:
                        type: array
                        items:
                          type: object
                          properties:
                            profileId:
                              type: integer
                            countryCode:
                              type: string
                            currencyCode:
                              type: string
                            timezone:
                              type: string
                            accountInfo:
                              type: object
                              properties:
                                marketplaceStringId:
                                  type: string
                                id:
                                  type: string
                                type:
                                  type: string
                                name:
                                  type: string
                      selected_profile_ids:
                        type: array
                        items:
                          type: integer
                      cost_entry_creation_enabled:
                        type: boolean
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 7
                    name: Amazon Ads
                    region: NA
                    is_connected: true
                    is_automatic_sync_enabled: true
                    sync_status: active
                    profiles:
                    - profileId: 3902568284010101
                      countryCode: US
                      currencyCode: USD
                      timezone: America/Los_Angeles
                      accountInfo:
                        marketplaceStringId: ATVPDKIKX0DER
                        id: A1X7T0NB572XNW
                        type: seller
                        name: PartUSA
                    selected_profile_ids:
                    - 3902568284010101
                    cost_entry_creation_enabled: false
                    created_at: '2026-06-13T15:02:11.000000Z'
                    updated_at: '2026-06-16T01:40:55.000000Z'
        '422':
          description: Unprocessable Content
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      cost_entry_creation_enabled:
                        type: array
                        items:
                          type: string
                example:
                  message: The cost entry creation enabled field is required.
                  errors:
                    cost_entry_creation_enabled:
                    - The cost entry creation enabled field is required.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: put-api-amazon-ads-integrationinstance-settings
  /api/amazon-ads/{integrationInstance}/spend/sync:
    post:
      tags:
      - Amazon
      summary: Sync Amazon Ads Spend
      description: 'Dispatch an Amazon Ads Sponsored Products spend sync for this
        advertiser connection. Fire-and-forget: it queues a background job and returns
        the tracked-job log id so the frontend can follow progress via the tracked
        job log endpoints. The job is idempotent — re-syncing an overlapping window
        restates spend rather than double-counting it (Amazon revises attribution
        within ~14 days).


        Body (all optional):

        - profile_ids[]: limit to specific advertiser profile ids (default: the instance''s
        selected profiles, falling back to all)

        - start_date / end_date (Y-m-d): explicit window. Both required together;
        end_date must be >= start_date. Omit both for the default trailing 14-day
        window ending yesterday.


        Requires Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                profile_ids:
                  type: array
                  items:
                    type: string
                start_date:
                  type: string
                end_date:
                  type: string
              example:
                profile_ids:
                - '3902568284010101'
                start_date: '2026-05-30'
                end_date: '2026-06-12'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Amazon Ads integration instance id
        example: '7'
      responses:
        '202':
          description: Accepted
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 88412
                  message: Amazon Ads spend sync started — track progress in the job
                    tray.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      end_date:
                        type: array
                        items:
                          type: string
                example:
                  message: An end_date is required when a start_date is provided.
                  errors:
                    end_date:
                    - An end_date is required when a start_date is provided.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-amazon-ads-integrationinstance-spend-sync
  /api/amazon-ads/{integrationInstance}/spend:
    get:
      tags:
      - Amazon
      summary: List Amazon Ads Spend Records
      description: 'Paginated per-ASIN/SKU Amazon Ads spend ledger for this advertiser
        connection. Each row carries spend, 7-day attributed sales, clicks, impressions,
        7-day purchases, the computed ACoS, and whether the advertised SKU/ASIN mapped
        to a SKU.io product (is_mapped + product_* cross-link). Uses Spatie QueryBuilder
        filters/sorts.


        Allowed sorts: id, spend, attributed_sales_7d, clicks, impressions, purchases_7d,
        period_start, period_end, advertised_sku, advertised_asin, created_at, updated_at
        (default -spend).


        Requires Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Amazon Ads integration instance id
        example: '7'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        profile_id:
                          type: string
                        ad_product:
                          type: string
                        advertised_sku:
                          type: string
                        advertised_asin:
                          type: string
                        product_id:
                          type: integer
                        is_mapped:
                          type: boolean
                        product_sku:
                          type: string
                        product_name:
                          type: string
                        product_route:
                          type: string
                        period_start:
                          type: string
                        period_end:
                          type: string
                        currency_code:
                          type: string
                        spend:
                          type: number
                        attributed_sales_7d:
                          type: number
                        clicks:
                          type: integer
                        impressions:
                          type: integer
                        purchases_7d:
                          type: integer
                        acos:
                          type: number
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                  first_page_url:
                    type: string
                  last_page_url:
                    type: string
                  next_page_url:
                    type: string
                  prev_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  links:
                    type: array
                example:
                  data:
                  - id: 1012
                    integration_instance_id: 7
                    profile_id: '3902568284010101'
                    ad_product: SPONSORED_PRODUCTS
                    advertised_sku: WIDGET-RED-001
                    advertised_asin: B07XYZ1234
                    product_id: 4521
                    is_mapped: true
                    product_sku: WIDGET-RED-001
                    product_name: Red Widget — 10 pack
                    product_route: /products/4521
                    period_start: '2026-05-30'
                    period_end: '2026-06-12'
                    currency_code: USD
                    spend: 142.87
                    attributed_sales_7d: 921.5
                    clicks: 318
                    impressions: 20544
                    purchases_7d: 27
                    acos: 15.5
                    created_at: '2026-06-13T05:00:11.000000Z'
                    updated_at: '2026-06-13T05:00:11.000000Z'
                  - id: 1013
                    integration_instance_id: 7
                    profile_id: '3902568284010101'
                    ad_product: SPONSORED_PRODUCTS
                    advertised_sku: OLD-SKU-999
                    advertised_asin: B09AAA0000
                    product_id: null
                    is_mapped: false
                    product_sku: null
                    product_name: null
                    product_route: null
                    period_start: '2026-05-30'
                    period_end: '2026-06-12'
                    currency_code: USD
                    spend: 58.2
                    attributed_sales_7d: 0
                    clicks: 91
                    impressions: 7321
                    purchases_7d: 0
                    acos: null
                    created_at: '2026-06-13T05:00:11.000000Z'
                    updated_at: '2026-06-13T05:00:11.000000Z'
                  current_page: 1
                  last_page: 3
                  per_page: 10
                  total: 24
                  from: 1
                  to: 10
                  first_page_url: '...'
                  last_page_url: '...'
                  next_page_url: '...'
                  prev_page_url: null
                  path: '...'
                  links: []
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-ads-integrationinstance-spend
  /api/amazon-ads/{integrationInstance}/spend/summary:
    get:
      tags:
      - Amazon
      summary: Amazon Ads Spend Summary
      description: 'Aggregate Amazon Ads spend/attribution summary for this advertiser
        connection over an optional date window + profile — feeds the summary cards.
        Returns total spend, 7-day attributed sales, ACoS, mapped vs unmapped spend
        split, the unmapped distinct SKU/ASIN count, and click/impression/purchase
        totals. The window defaults to a trailing 14-day range ending yesterday (matching
        the sync job''s default pull) when no bounds are given.


        Requires Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Amazon Ads integration instance id
        example: '7'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      period_start:
                        type: string
                      period_end:
                        type: string
                      profile_id:
                        type: string
                        nullable: true
                      spend_total:
                        type: number
                      attributed_sales_total:
                        type: number
                      mapped_spend:
                        type: number
                      unmapped_spend:
                        type: number
                      clicks_total:
                        type: integer
                      impressions_total:
                        type: integer
                      purchases_total:
                        type: integer
                      unmapped_sku_count:
                        type: integer
                      acos:
                        type: number
                example:
                  data:
                    period_start: '2026-05-30'
                    period_end: '2026-06-12'
                    profile_id: null
                    spend_total: 1842.55
                    attributed_sales_total: 11920.4
                    mapped_spend: 1620.1
                    unmapped_spend: 222.45
                    clicks_total: 4120
                    impressions_total: 285330
                    purchases_total: 341
                    unmapped_sku_count: 3
                    acos: 15.46
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-ads-integrationinstance-spend-summary
  /api/amazon-ads:
    get:
      tags:
      - Amazon
      summary: List Amazon Ads Connections
      description: 'List every Amazon Advertising connection on the account. Each
        connection is a per-seller Login with Amazon authorization for the Amazon
        Ads API, holding the advertiser profiles discovered for that seller and the
        subset selected for spend syncing.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        `is_connected` reflects whether a valid authorization is stored; `region`
        is the Ads API region the connection was made in (NA, EU, or FE).


        Connections are created by authorizing through the SKU.io web app (Settings
        → Integrations → Amazon Ads); this API manages existing connections.


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        region:
                          type: string
                        is_connected:
                          type: boolean
                        is_automatic_sync_enabled:
                          type: boolean
                        sync_status:
                          type: string
                        profiles:
                          type: array
                          items:
                            type: object
                            properties:
                              profileId:
                                type: integer
                              countryCode:
                                type: string
                              currencyCode:
                                type: string
                              timezone:
                                type: string
                              accountInfo:
                                type: object
                                properties:
                                  marketplaceStringId:
                                    type: string
                                  id:
                                    type: string
                                  type:
                                    type: string
                                  name:
                                    type: string
                        selected_profile_ids:
                          type: array
                          items:
                            type: integer
                        cost_entry_creation_enabled:
                          type: boolean
                        created_at:
                          type: string
                        updated_at:
                          type: string
                example:
                  data:
                  - id: 7
                    name: Amazon Ads
                    region: NA
                    is_connected: true
                    is_automatic_sync_enabled: true
                    sync_status: active
                    profiles:
                    - profileId: 3902568284010101
                      countryCode: US
                      currencyCode: USD
                      timezone: America/Los_Angeles
                      accountInfo:
                        marketplaceStringId: ATVPDKIKX0DER
                        id: A1X7T0NB572XNW
                        type: seller
                        name: PartUSA
                    selected_profile_ids:
                    - 3902568284010101
                    cost_entry_creation_enabled: false
                    created_at: '2026-06-13T15:02:11.000000Z'
                    updated_at: '2026-06-16T01:40:55.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-amazon-ads
  /api/amazon-ads/{integrationInstance}:
    get:
      tags:
      - Amazon
      summary: Get Amazon Ads Connection
      description: 'Get a single Amazon Advertising connection, including its discovered
        advertiser profiles, the profile ids selected for syncing, and whether spend
        syncs create cost entries.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Amazon Ads integration instance id
        example: '7'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      region:
                        type: string
                      is_connected:
                        type: boolean
                      is_automatic_sync_enabled:
                        type: boolean
                      sync_status:
                        type: string
                      profiles:
                        type: array
                        items:
                          type: object
                          properties:
                            profileId:
                              type: integer
                            countryCode:
                              type: string
                            currencyCode:
                              type: string
                            timezone:
                              type: string
                            accountInfo:
                              type: object
                              properties:
                                marketplaceStringId:
                                  type: string
                                id:
                                  type: string
                                type:
                                  type: string
                                name:
                                  type: string
                      selected_profile_ids:
                        type: array
                        items:
                          type: integer
                      cost_entry_creation_enabled:
                        type: boolean
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 7
                    name: Amazon Ads
                    region: NA
                    is_connected: true
                    is_automatic_sync_enabled: true
                    sync_status: active
                    profiles:
                    - profileId: 3902568284010101
                      countryCode: US
                      currencyCode: USD
                      timezone: America/Los_Angeles
                      accountInfo:
                        marketplaceStringId: ATVPDKIKX0DER
                        id: A1X7T0NB572XNW
                        type: seller
                        name: PartUSA
                    selected_profile_ids:
                    - 3902568284010101
                    cost_entry_creation_enabled: false
                    created_at: '2026-06-13T15:02:11.000000Z'
                    updated_at: '2026-06-16T01:40:55.000000Z'
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Record not found.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-amazon-ads-integrationinstance
    delete:
      tags:
      - Amazon
      summary: Delete Amazon Ads Connection
      description: 'Delete an Amazon Advertising connection. The stored authorization
        and profile selection are removed; already-ingested spend records are kept.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Returns 204 No Content on success.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Amazon Ads integration instance id
        example: '7'
      responses:
        '204':
          description: No Content
          headers:
            Content-Type:
              schema:
                type: string
                example: text/plain
          content:
            text/plain:
              schema:
                type: string
                example: ''
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-amazon-ads-integrationinstance
  /api/amazon-ads/{integrationInstance}/profiles:
    get:
      tags:
      - Amazon
      summary: List Advertiser Profiles
      description: 'List the advertiser profiles stored for this connection along
        with the profile ids the user has opted into for spend syncing. Profiles are
        discovered from the Amazon Ads API when the connection is authorized and can
        be re-fetched with Refresh Advertiser Profiles.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Amazon Ads integration instance id
        example: '7'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      profiles:
                        type: array
                        items:
                          type: object
                          properties:
                            profileId:
                              type: integer
                            countryCode:
                              type: string
                            currencyCode:
                              type: string
                            timezone:
                              type: string
                            accountInfo:
                              type: object
                              properties:
                                marketplaceStringId:
                                  type: string
                                id:
                                  type: string
                                type:
                                  type: string
                                name:
                                  type: string
                      selected_profile_ids:
                        type: array
                        items:
                          type: integer
                example:
                  data:
                    profiles:
                    - profileId: 3902568284010101
                      countryCode: US
                      currencyCode: USD
                      timezone: America/Los_Angeles
                      accountInfo:
                        marketplaceStringId: ATVPDKIKX0DER
                        id: A1X7T0NB572XNW
                        type: seller
                        name: PartUSA
                    selected_profile_ids:
                    - 3902568284010101
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-amazon-ads-integrationinstance-profiles
    put:
      tags:
      - Amazon
      summary: Update Selected Advertiser Profiles
      description: 'Persist which advertiser profiles are selected for spend syncing
        on this connection. Only selected profiles are pulled during a spend sync.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Body fields:**

        - `profile_ids` (required, array) — the Amazon profile ids to sync. Send an
        empty array to clear the selection.


        Returns the updated connection.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                profile_ids:
                  type: array
                  items:
                    type: integer
              example:
                profile_ids:
                - 3902568284010101
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Amazon Ads integration instance id
        example: '7'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      region:
                        type: string
                      is_connected:
                        type: boolean
                      is_automatic_sync_enabled:
                        type: boolean
                      sync_status:
                        type: string
                      profiles:
                        type: array
                        items:
                          type: object
                          properties:
                            profileId:
                              type: integer
                            countryCode:
                              type: string
                            currencyCode:
                              type: string
                            timezone:
                              type: string
                            accountInfo:
                              type: object
                              properties:
                                marketplaceStringId:
                                  type: string
                                id:
                                  type: string
                                type:
                                  type: string
                                name:
                                  type: string
                      selected_profile_ids:
                        type: array
                        items:
                          type: integer
                      cost_entry_creation_enabled:
                        type: boolean
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 7
                    name: Amazon Ads
                    region: NA
                    is_connected: true
                    is_automatic_sync_enabled: true
                    sync_status: active
                    profiles:
                    - profileId: 3902568284010101
                      countryCode: US
                      currencyCode: USD
                      timezone: America/Los_Angeles
                      accountInfo:
                        marketplaceStringId: ATVPDKIKX0DER
                        id: A1X7T0NB572XNW
                        type: seller
                        name: PartUSA
                    selected_profile_ids:
                    - 3902568284010101
                    cost_entry_creation_enabled: false
                    created_at: '2026-06-13T15:02:11.000000Z'
                    updated_at: '2026-06-16T01:40:55.000000Z'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      profile_ids:
                        type: array
                        items:
                          type: string
                example:
                  message: The profile_ids field is required (send an empty array
                    to clear the selection).
                  errors:
                    profile_ids:
                    - The profile_ids field is required (send an empty array to clear
                      the selection).
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: put-api-amazon-ads-integrationinstance-profiles
  /api/amazon-ads/{integrationInstance}/profiles/refresh:
    post:
      tags:
      - Amazon
      summary: Refresh Advertiser Profiles
      description: 'Re-fetch the advertiser profiles from the Amazon Ads API and persist
        them on the connection. Use this when the seller has gained (or lost) access
        to advertiser profiles since connecting.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        A failed upstream call is reported as a 422 with an actionable message: a
        rejected authorization (Amazon answers 401/403) prompts a reconnect, any other
        upstream failure asks to retry.


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Amazon Ads integration instance id
        example: '7'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      profiles:
                        type: array
                        items:
                          type: object
                          properties:
                            profileId:
                              type: integer
                            countryCode:
                              type: string
                            currencyCode:
                              type: string
                            timezone:
                              type: string
                            accountInfo:
                              type: object
                              properties:
                                marketplaceStringId:
                                  type: string
                                id:
                                  type: string
                                type:
                                  type: string
                                name:
                                  type: string
                      selected_profile_ids:
                        type: array
                        items:
                          type: integer
                example:
                  data:
                    profiles:
                    - profileId: 3902568284010101
                      countryCode: US
                      currencyCode: USD
                      timezone: America/Los_Angeles
                      accountInfo:
                        marketplaceStringId: ATVPDKIKX0DER
                        id: A1X7T0NB572XNW
                        type: seller
                        name: PartUSA
                    selected_profile_ids:
                    - 3902568284010101
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: object
                    properties:
                      profiles:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: array
                example:
                  errors:
                    profiles:
                    - message: Amazon rejected the saved authorization for this connection.
                        Reconnect the account to refresh access, then try again.
                      code: IntegrationApiError
                      data: []
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-amazon-ads-integrationinstance-profiles-refresh
  /api/shopify/config:
    get:
      tags:
      - Shopify
      summary: Get OAuth Config
      description: 'Returns the Shopify OAuth configuration that tells the frontend
        which connection mode to render.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Response fields:

        - custom_app_mode (bool): when true, per-instance Client ID/Secret are used
        (custom app). When false, SKU.io''s central public app credentials are used.

        - legacy_custom_app_mode (bool): when true, the merchant pastes an Admin API
        access token directly (no OAuth).

        - scopes (string): comma-separated OAuth scopes requested.

        - redirect_url (string): the OAuth callback URL ({app_url}/shopify/callback).


        Mode matrix:

        - Public OAuth: custom_app_mode=false, legacy_custom_app_mode=false (no credentials
        entered; merchant just authorizes).

        - Custom-app OAuth: custom_app_mode=true, legacy_custom_app_mode=false.

        - Legacy custom app: legacy_custom_app_mode=true.


        Note: custom_app_mode and legacy_custom_app_mode are resolved per-tenant.
        A tenant may override either flag (operators set this via the shopify:set-app-mode
        artisan command); when no override is present the global config default applies.
        The response shape is identical regardless of how the values resolve, so different
        tenants may legitimately return different mode values.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  custom_app_mode:
                    type: boolean
                  legacy_custom_app_mode:
                    type: boolean
                  scopes:
                    type: string
                  redirect_url:
                    type: string
                example:
                  custom_app_mode: false
                  legacy_custom_app_mode: false
                  scopes: write_customers,read_customers,write_orders,read_orders,read_all_orders,write_products,read_products,write_inventory,read_inventory,write_fulfillments,read_fulfillments,write_returns,read_returns
                  redirect_url: https://app.sku.io/shopify/callback
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-shopify-config
  /api/shopify:
    post:
      tags:
      - Shopify
      summary: Create Integration
      description: 'Create a new Shopify integration instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Request body:

        - name (string, required, unique across integration_instances.name)

        - connection_settings.url (string, required): full store URL, must start with
        https:// and not end with /. e.g. https://my-store.myshopify.com

        - connection_settings.consumer_key (string, OPTIONAL): only for legacy custom-app
        (API key) and custom-app OAuth (Client ID) modes. OMIT in public OAuth mode
        — SKU.io''s central credentials are used.

        - connection_settings.consumer_secret (string, OPTIONAL): only for legacy
        custom-app (Admin API access token) and custom-app OAuth (Secret) modes. OMIT
        in public OAuth mode.

        - connection_settings.key_id (int, optional), user_id (string, optional),
        key_permissions (string, optional)

        - integration_settings.start_date (string, required, Y-m-d; must be on/after
        the inventory start date if configured)

        - integration_settings.store_id (int, required, must exist in stores)

        - integration_settings.auto_link_products (bool), auto_create_products (bool)

        - integration_settings.*_nominal_code_id (int|null): sales, cogs, shipping_revenue,
        shipping_refund, sales_returns_allowances, fees

        - integration_settings.download_archived_products (bool), download_draft_products
        (bool), require_mapped_products_for_sales_order (bool)

        - is_automatic_sync_enabled (bool, default false)


        Behavior by mode:

        - Public OAuth & Custom-app OAuth: response includes a redirect_url; the frontend
        then calls GET /api/shopify/{id}/authorization-url and redirects the merchant
        to Shopify. Init jobs run after the OAuth callback.

        - Legacy custom app: no OAuth; init jobs run immediately and the instance
        is marked ACTIVE.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                connection_settings:
                  type: object
                  properties:
                    url:
                      type: string
                    consumer_key:
                      type: string
                    consumer_secret:
                      type: string
                integration_settings:
                  type: object
                  properties:
                    start_date:
                      type: string
                    store_id:
                      type: integer
                    auto_link_products:
                      type: boolean
                    auto_create_products:
                      type: boolean
                    sales_nominal_code_id:
                      type: string
                      nullable: true
                    cogs_nominal_code_id:
                      type: string
                      nullable: true
                    shipping_revenue_nominal_code_id:
                      type: string
                      nullable: true
                    shipping_refund_nominal_code_id:
                      type: string
                      nullable: true
                    sales_returns_allowances_nominal_code_id:
                      type: string
                      nullable: true
                    download_archived_products:
                      type: boolean
                    download_draft_products:
                      type: boolean
                    require_mapped_products_for_sales_order:
                      type: boolean
                is_automatic_sync_enabled:
                  type: boolean
              example:
                name: Main Shopify Store
                connection_settings:
                  url: https://my-store.myshopify.com
                  consumer_key: 8e894995d119436434f0f28e8ec69eb4
                  consumer_secret: shpss_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
                integration_settings:
                  start_date: '2024-01-01'
                  store_id: 1
                  auto_link_products: false
                  auto_create_products: false
                  sales_nominal_code_id: null
                  cogs_nominal_code_id: null
                  shipping_revenue_nominal_code_id: null
                  shipping_refund_nominal_code_id: null
                  sales_returns_allowances_nominal_code_id: null
                  download_archived_products: false
                  download_draft_products: false
                  require_mapped_products_for_sales_order: false
                is_automatic_sync_enabled: true
      parameters: []
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      integration_id:
                        type: integer
                      sync_status:
                        type: string
                      is_automatic_sync_enabled:
                        type: boolean
                      connection_settings:
                        type: object
                        properties:
                          url:
                            type: string
                      integration_settings:
                        type: object
                        properties:
                          start_date:
                            type: string
                          store_id:
                            type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                  redirect_url:
                    type: string
                example:
                  data:
                    id: 12
                    name: Main Shopify Store
                    integration_id: 3
                    sync_status: pending
                    is_automatic_sync_enabled: true
                    connection_settings:
                      url: https://my-store.myshopify.com
                    integration_settings:
                      start_date: '2024-01-01'
                      store_id: 1
                    created_at: '2026-06-03T10:15:00.000000Z'
                    updated_at: '2026-06-03T10:15:00.000000Z'
                  redirect_url: https://my-store.myshopify.com/admin/oauth/authorize?client_id=8e894995d119436434f0f28e8ec69eb4&scope=...&redirect_uri=https%3A%2F%2Fapp.sku.io%2Fshopify%2Fcallback&state=acme_12
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      name:
                        type: array
                        items:
                          type: string
                      connection_settings.url:
                        type: array
                        items:
                          type: string
                example:
                  message: The name has already been taken.
                  errors:
                    name:
                    - The name has already been taken.
                    connection_settings.url:
                    - The connection_settings.url field must start with https://.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-shopify
    get:
      tags:
      - Shopify
      summary: List Integrations
      description: 'Lists every Shopify integration instance connected to the account.
        Returns a lightweight summary per instance; use Get Integration for the full
        configuration.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        This endpoint is not paginated - all instances are returned in a single response.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        is_automatic_sync_enabled:
                          type: boolean
                        use_location_mapping_for_new_orders:
                          type: boolean
                        created_at:
                          type: string
                        updated_at:
                          type: string
                example:
                  data:
                  - id: 1
                    name: Main Shopify Store
                    is_automatic_sync_enabled: true
                    use_location_mapping_for_new_orders: false
                    created_at: '2024-01-05T09:12:00.000000Z'
                    updated_at: '2025-06-20T14:03:00.000000Z'
                  - id: 2
                    name: EU Shopify Store
                    is_automatic_sync_enabled: false
                    use_location_mapping_for_new_orders: true
                    created_at: '2024-03-11T10:30:00.000000Z'
                    updated_at: '2025-06-18T08:41:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-shopify
  /api/shopify/{integrationInstance}/authorization-url:
    get:
      tags:
      - Shopify
      summary: Get Authorization URL
      description: 'Returns the Shopify OAuth authorization URL for an integration
        instance. The frontend redirects the merchant''s browser to this URL to begin
        authorization.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Path params:

        - integrationInstance (int, required): the integration instance id.


        Notes:

        - Requires connection_settings.url (or legacy shop_url) to be set on the instance.

        - Uses per-instance credentials in custom-app mode, otherwise SKU.io''s central
        public-app Client ID.

        - A tenant-aware state is generated so the central-domain callback can rehydrate
        tenancy.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '12'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: string
                example:
                  data: https://my-store.myshopify.com/admin/oauth/authorize?client_id=8e894995d119436434f0f28e8ec69eb4&scope=write_orders%2Cread_orders%2Cwrite_products%2Cread_products&redirect_uri=https%3A%2F%2Fapp.sku.io%2Fshopify%2Fcallback&state=acme_12
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shopify-integrationinstance-authorization-url
  /api/shopify/{integrationInstance}:
    get:
      tags:
      - Shopify
      summary: Get Integration
      description: 'Returns the full configuration of a Shopify integration instance,
        including its linked store and sales channel, integration settings, granular
        sync controls (which capabilities sync automatically), and whether the sync
        schedule is paused.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      sync_status:
                        type: string
                      is_automatic_sync_enabled:
                        type: boolean
                      use_location_mapping_for_new_orders:
                        type: boolean
                      integration_name:
                        type: string
                      sales_channel_id:
                        type: integer
                      store:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      sync_controls:
                        type: object
                        properties:
                          orders:
                            type: object
                            properties:
                              download:
                                type: boolean
                              upload:
                                type: boolean
                          products:
                            type: object
                            properties:
                              download:
                                type: boolean
                          inventory:
                            type: object
                            properties:
                              upload:
                                type: boolean
                          fulfillments:
                            type: object
                            properties:
                              upload:
                                type: boolean
                      applicable_sync_capabilities:
                        type: array
                        items:
                          type: string
                      is_sync_schedule_paused:
                        type: boolean
                      integration_settings:
                        type: object
                        properties:
                          start_date:
                            type: string
                          store_id:
                            type: integer
                          auto_link_products:
                            type: boolean
                          auto_create_products:
                            type: boolean
                          shipping_method_field:
                            type: string
                          override_shipping_method:
                            type: boolean
                          allow_negative_inventory:
                            type: boolean
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 1
                    name: Main Shopify Store
                    sync_status: active
                    is_automatic_sync_enabled: true
                    use_location_mapping_for_new_orders: false
                    integration_name: shopify
                    sales_channel_id: 12
                    store:
                      id: 4
                      name: Main Shopify Store
                    sync_controls:
                      orders:
                        download: true
                        upload: true
                      products:
                        download: true
                      inventory:
                        upload: true
                      fulfillments:
                        upload: true
                    applicable_sync_capabilities:
                    - orders
                    - products
                    - inventory
                    - fulfillments
                    is_sync_schedule_paused: false
                    integration_settings:
                      start_date: '2024-01-01'
                      store_id: 4
                      auto_link_products: true
                      auto_create_products: false
                      shipping_method_field: title
                      override_shipping_method: true
                      allow_negative_inventory: false
                    created_at: '2024-01-05T09:12:00.000000Z'
                    updated_at: '2025-06-20T14:03:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shopify-integrationinstance
    put:
      tags:
      - Shopify
      summary: Update Integration
      description: 'Updates a Shopify integration instance. All fields are optional
        - send only what you want to change.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        PATCH is also accepted at this URL. With PATCH, nested connection_settings
        and integration_settings objects are deep-merged with the stored values (JSON
        merge semantics), while PUT replaces each settings object you provide. Inventory
        location arrays are always replaced in full, never merged.


        Side effects: changing start_date re-anchors order syncing; changing store_id
        re-links the sales channel''s store; changing the pricing master or inventory
        settings queues background cache rebuilds; toggling the accounting sync flags
        re-evaluates which historical transactions sync to accounting.


        Body fields:

        - name (string): display name (must stay unique).

        - connection_settings (object): url (https, no trailing slash), consumer_key,
        consumer_secret (custom-app modes only).

        - integration_settings (object): start_date (Y-m-d, must be on/after the inventory
        start date), store_id, auto_link_products, auto_create_products, sales/cogs/shipping_revenue/shipping_refund/sales_returns_allowances_nominal_code_id,
        pricing, inventory, emailCustomers, proforma_marketplace_cost_percentage,
        proforma_payment_cost_percentage, sync_sales_order_invoices_to_accounting,
        sync_sales_credit_to_accounting, download_archived_products, download_draft_products,
        download_unlisted_products, shipping_method_field (title|code), override_shipping_method,
        fallback_shipping_method_id (id of a shipping method applied when a Shopify
        order has no resolvable shipping method), pickup_sync (sync_ready_for_pickup,
        notify_customer_ready_for_pickup, notify_customer_picked_up), settings (nested,
        e.g. orders.delivery_ship_dates), orders (e.g. hold_and_ship_by_date), returns
        (return receipt sync), allow_negative_inventory.

        - is_automatic_sync_enabled (boolean).

        - use_location_mapping_for_new_orders (boolean): route new orders to warehouses
        via location mappings.


        integration_settings.cost_sync.fallback_to_default_cost (boolean): when a
        product has no average cost, fall back to its default cost for the cost push.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                is_automatic_sync_enabled:
                  type: boolean
                use_location_mapping_for_new_orders:
                  type: boolean
                connection_settings:
                  type: object
                  properties:
                    url:
                      type: string
                integration_settings:
                  type: object
                  properties:
                    start_date:
                      type: string
                    store_id:
                      type: integer
                    auto_link_products:
                      type: boolean
                    auto_create_products:
                      type: boolean
                    sales_nominal_code_id:
                      type: integer
                    cogs_nominal_code_id:
                      type: integer
                    shipping_revenue_nominal_code_id:
                      type: integer
                    shipping_refund_nominal_code_id:
                      type: integer
                    sales_returns_allowances_nominal_code_id:
                      type: integer
                    sync_sales_order_invoices_to_accounting:
                      type: boolean
                    sync_sales_credit_to_accounting:
                      type: boolean
                    download_archived_products:
                      type: boolean
                    download_draft_products:
                      type: boolean
                    download_unlisted_products:
                      type: boolean
                    shipping_method_field:
                      type: string
                    override_shipping_method:
                      type: boolean
                    fallback_shipping_method_id:
                      type: integer
                    allow_negative_inventory:
                      type: boolean
                    pickup_sync:
                      type: object
                      properties:
                        sync_ready_for_pickup:
                          type: boolean
                        notify_customer_ready_for_pickup:
                          type: boolean
                        notify_customer_picked_up:
                          type: boolean
                    cost_sync:
                      type: object
                      properties:
                        fallback_to_default_cost:
                          type: boolean
              example:
                name: Main Shopify Store
                is_automatic_sync_enabled: true
                use_location_mapping_for_new_orders: true
                connection_settings:
                  url: https://my-store.myshopify.com
                integration_settings:
                  start_date: '2024-01-01'
                  store_id: 4
                  auto_link_products: true
                  auto_create_products: false
                  sales_nominal_code_id: 12
                  cogs_nominal_code_id: 18
                  shipping_revenue_nominal_code_id: 14
                  shipping_refund_nominal_code_id: 15
                  sales_returns_allowances_nominal_code_id: 16
                  sync_sales_order_invoices_to_accounting: true
                  sync_sales_credit_to_accounting: true
                  download_archived_products: false
                  download_draft_products: false
                  download_unlisted_products: false
                  shipping_method_field: title
                  override_shipping_method: true
                  fallback_shipping_method_id: 5
                  allow_negative_inventory: false
                  pickup_sync:
                    sync_ready_for_pickup: true
                    notify_customer_ready_for_pickup: false
                    notify_customer_picked_up: false
                  cost_sync:
                    fallback_to_default_cost: true
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      sync_status:
                        type: string
                      is_automatic_sync_enabled:
                        type: boolean
                      use_location_mapping_for_new_orders:
                        type: boolean
                      integration_name:
                        type: string
                      sales_channel_id:
                        type: integer
                      store:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      sync_controls:
                        type: object
                        properties:
                          orders:
                            type: object
                            properties:
                              download:
                                type: boolean
                              upload:
                                type: boolean
                          products:
                            type: object
                            properties:
                              download:
                                type: boolean
                          inventory:
                            type: object
                            properties:
                              upload:
                                type: boolean
                          fulfillments:
                            type: object
                            properties:
                              upload:
                                type: boolean
                      applicable_sync_capabilities:
                        type: array
                        items:
                          type: string
                      is_sync_schedule_paused:
                        type: boolean
                      integration_settings:
                        type: object
                        properties:
                          start_date:
                            type: string
                          store_id:
                            type: integer
                          auto_link_products:
                            type: boolean
                          auto_create_products:
                            type: boolean
                          shipping_method_field:
                            type: string
                          override_shipping_method:
                            type: boolean
                          allow_negative_inventory:
                            type: boolean
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 1
                    name: Main Shopify Store
                    sync_status: active
                    is_automatic_sync_enabled: true
                    use_location_mapping_for_new_orders: false
                    integration_name: shopify
                    sales_channel_id: 12
                    store:
                      id: 4
                      name: Main Shopify Store
                    sync_controls:
                      orders:
                        download: true
                        upload: true
                      products:
                        download: true
                      inventory:
                        upload: true
                      fulfillments:
                        upload: true
                    applicable_sync_capabilities:
                    - orders
                    - products
                    - inventory
                    - fulfillments
                    is_sync_schedule_paused: false
                    integration_settings:
                      start_date: '2024-01-01'
                      store_id: 4
                      auto_link_products: true
                      auto_create_products: false
                      shipping_method_field: title
                      override_shipping_method: true
                      allow_negative_inventory: false
                    created_at: '2024-01-05T09:12:00.000000Z'
                    updated_at: '2025-06-20T14:03:00.000000Z'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      integration_settings.start_date:
                        type: array
                        items:
                          type: string
                example:
                  message: The integration settings.start date field must be a date
                    after or equal to 2024-01-01.
                  errors:
                    integration_settings.start_date:
                    - The integration settings.start date field must be a date after
                      or equal to 2024-01-01.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: put-api-shopify-integrationinstance
    delete:
      tags:
      - Shopify
      summary: Delete Integration
      description: 'Disconnects a Shopify integration instance. The webhooks SKU.io
        registered on the shop are removed first, then deletion of the instance and
        its synced data is queued as a background operation - the endpoint returns
        immediately with 204 while cleanup continues asynchronously.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Warning: this is irreversible. Synced Shopify orders, products, and mappings
        for the instance are removed.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '204':
          description: No Content
          headers:
            Content-Type:
              schema:
                type: string
                example: text/csv
          content:
            text/plain:
              schema:
                type: string
                example: ''
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-shopify-integrationinstance
  /api/shopify/{integrationInstance}/auth-settings:
    get:
      tags:
      - Shopify
      summary: Get Auth Settings
      description: 'Returns the connection settings for an integration instance with
        secrets masked (only the last 4 characters are visible), plus the current
        sync status and shop URL. Useful for showing connection state without exposing
        credentials.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      connection_settings:
                        type: object
                        properties:
                          url:
                            type: string
                          consumer_key:
                            type: string
                          consumer_secret:
                            type: string
                      sync_status:
                        type: string
                      shop_url:
                        type: string
                      name:
                        type: string
                      is_automatic_sync_enabled:
                        type: boolean
                example:
                  data:
                    connection_settings:
                      url: https://my-store.myshopify.com
                      consumer_key: 8e894995d119436434f0f28e8ec69eb4
                      consumer_secret: '********************************ab12'
                    sync_status: active
                    shop_url: https://my-store.myshopify.com
                    name: Main Shopify Store
                    is_automatic_sync_enabled: true
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shopify-integrationinstance-auth-settings
  /api/shopify/install/{claimToken}:
    get:
      tags:
      - Shopify
      summary: Show Install (Claim Page)
      description: 'PUBLIC (no authentication). Reveals the Shopify store being connected
        on the claim page after an App Store cold install.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        The opaque `claimToken` in the path IS the credential — it is minted after
        OAuth and redirected to `app.sku.io/connect/shopify?claim=<token>`. This endpoint
        deliberately exposes only the shop''s display identity and lifecycle status;
        the stashed offline token, scopes, shop email/country, and all internal ids
        are NEVER returned.


        Throttled to 30 req/min to blunt token-guessing.


        Response fields (under `data`):

        - shop_domain (string): the *.myshopify.com domain being connected.

        - shop_name (string): the shop''s display name (or a humanized subdomain fallback).

        - status (string): lifecycle status — one of pending_auth, awaiting_claim,
        claiming, claimed, claim_failed, failed, expired, abandoned.


        Returns 404 when the token matches nothing (invalid or already-consumed).'
      parameters:
      - name: claimToken
        in: path
        schema:
          type: string
        required: true
        description: Opaque 256-bit claim token from the /connect/shopify?claim= redirect.
        example: 5f3a...e91c
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      shop_domain:
                        type: string
                      shop_name:
                        type: string
                      status:
                        type: string
                example:
                  data:
                    shop_domain: acme-supplies.myshopify.com
                    shop_name: Acme Supplies
                    status: awaiting_claim
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: This connection link is invalid or has already been used.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-shopify-install-claimtoken
  /api/shopify/install/{claimToken}/claim:
    post:
      tags:
      - Shopify
      summary: Claim Install (Attach to Existing Workspace)
      description: 'AUTHENTICATED. Attaches a stashed cold install to a workspace
        the signed-in merchant already belongs to. The merchant MUST already have
        a SKU.io account — this flow never creates users or tenants.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        The bearer user is resolved from auth:sanctum manually (no route middleware),
        so the claim page stays anonymous until the merchant signs in; a Bearer token
        is therefore REQUIRED and an anonymous request is rejected with 401.


        Resolves synchronously and returns 200 with the cross-subdomain tenant-switch
        handoff, which the claim page uses to drop the merchant onto their tenant,
        authenticated. A re-install into a tenant that already has an instance for
        the shop refreshes that instance''s token in place (no duplicate).


        Throttled to 30 req/min.


        Request fields:

        - tenant_id (string, required): the id of a workspace the signed-in merchant
        already belongs to; validated against the central tenants table.


        Responses:

        - 200 OK: handoff payload — status=claimed, switch_token, target_host, tenant_id,
        instance_id, landing_path.

        - 401 Unauthorized: no signed-in user (the merchant must sign in first).

        - 404 Not Found: unknown/consumed claim token.

        - 409 Conflict: the store is already being connected (lost the atomic claim
        race) or already claimed.

        - 410 Gone: the claim link has expired (reinstall from the App Store).

        - 422 Unprocessable: validation error (e.g. unknown tenant_id).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                tenant_id:
                  type: string
              example:
                tenant_id: acme
      parameters:
      - name: claimToken
        in: path
        schema:
          type: string
        required: true
        description: Opaque claim token.
        example: 5f3a...e91c
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      status:
                        type: string
                      switch_token:
                        type: string
                      target_host:
                        type: string
                      tenant_id:
                        type: string
                      instance_id:
                        type: integer
                      landing_path:
                        type: string
                example:
                  data:
                    status: claimed
                    switch_token: eyJ0eXAiOiJ...handoff
                    target_host: acme.sku.io
                    tenant_id: acme
                    instance_id: 42
                    landing_path: /integrations/shopify/dashboard
        '401':
          description: Unauthorized
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: You must be signed in to connect this store to your workspace.
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: This connection link is invalid or has already been used.
        '409':
          description: Conflict
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: This store is already being connected.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      tenant_id:
                        type: array
                        items:
                          type: string
                example:
                  message: The selected workspace could not be found.
                  errors:
                    tenant_id:
                    - The selected workspace could not be found.
        '429': *id001
        '403': *id003
      operationId: post-api-shopify-install-claimtoken-claim
  /api/shopify/{integrationInstance}/orders:
    get:
      tags:
      - Shopify
      summary: List Orders
      description: 'List Shopify orders for an integration instance with advanced
        filtering, sorting, and pagination.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Default: returns non-archived orders sorted by -id.


        Sort fields: id, name, email, total_price, created_at, shopify_created_at,
        shopify_updated_at, shopify_processed_at, financial_status, fulfillment_status,
        legacy_resource_id, currency, shopify_cancelled_at, billing_name, shipping_name,
        payment_gateway, sales_order, shipping_method


        Filter system uses both simple (filter[field]) and AdvancedFilterBuilder operators
        (filter[field.op]).'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        description: 'Page number (default: 1)'
        example: '1'
      - name: per_page
        in: query
        schema:
          type: integer
        description: 'Items per page (default: 15)'
        example: '15'
      - name: sort
        in: query
        schema:
          type: string
        description: 'Sort field. Allowed: id, name, email, total_price, created_at,
          shopify_created_at, shopify_updated_at, shopify_processed_at, financial_status,
          fulfillment_status, legacy_resource_id, currency, shopify_cancelled_at,
          billing_name, shipping_name, payment_gateway, sales_order, shipping_method'
        example: -id
      - name: filter[search]
        in: query
        schema:
          type: string
        description: Search across order name, email, Shopify ID, SKU SO#, SKU line
          items, shipping method
        example: '#1001'
      - name: filter[financial_status]
        in: query
        schema:
          type: string
        description: 'Exact match: pending, authorized, partially_paid, paid, partially_refunded,
          refunded, voided'
        example: paid
      - name: filter[fulfillment_status]
        in: query
        schema:
          type: string
        description: 'Exact match: fulfilled, null, partial, restocked'
        example: fulfilled
      - name: filter[currency]
        in: query
        schema:
          type: string
        description: Exact match on currency code
        example: USD
      - name: filter[source_name]
        in: query
        schema:
          type: string
        description: Exact match on source name
        example: web
      - name: filter[payment_gateway]
        in: query
        schema:
          type: string
        description: Filter by payment gateway (via transactions)
        example: shopify_payments
      - name: filter[status]
        in: query
        schema:
          type: string
        description: active (non-archived) or archived
        example: active
      - name: filter[has_sku_order]
        in: query
        schema:
          type: boolean
        description: true = has linked SKU sales order, false = no SKU order
        example: 'true'
      - name: filter[has_unmapped_items]
        in: query
        schema:
          type: boolean
        description: true = has unmapped line items
        example: 'false'
      - name: filter[has_non_product_items]
        in: query
        schema:
          type: boolean
        description: true = has non-product line items
        example: 'false'
      - name: filter[cancelled]
        in: query
        schema:
          type: boolean
        description: true = cancelled orders only, false = exclude cancelled
        example: 'false'
      - name: filter[name.contains]
        in: query
        schema:
          type: integer
        description: Advanced text filter on order name
        example: '1001'
      - name: filter[email.contains]
        in: query
        schema:
          type: string
        description: Advanced text filter on email
        example: john
      - name: filter[total_price.gte]
        in: query
        schema:
          type: integer
        description: 'Numeric filter: total_price >= value'
        example: '50'
      - name: filter[shopify_created_at.gte]
        in: query
        schema:
          type: string
        description: Datetime filter on shopify_created_at
        example: '2024-01-01'
      - name: filter[shopify_processed_at.lte]
        in: query
        schema:
          type: string
        description: Datetime filter on shopify_processed_at
        example: '2024-12-31'
      - name: search_columns
        in: query
        schema:
          type: string
        description: Comma-separated columns for targeted search (name, email, legacy_resource_id,
          etc.)
        example: name,email
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        email:
                          type: string
                        financial_status:
                          type: string
                        fulfillment_status:
                          type: string
                        total_price:
                          type: string
                        currency:
                          type: string
                        legacy_resource_id:
                          type: string
                        source_name:
                          type: string
                        shopify_created_at:
                          type: string
                        shopify_updated_at:
                          type: string
                        shopify_processed_at:
                          type: string
                        shopify_cancelled_at:
                          type: string
                          nullable: true
                        billing_name:
                          type: string
                        shipping_name:
                          type: string
                        shopify_admin_url:
                          type: string
                        payment_gateway:
                          type: string
                        shipping_method:
                          type: string
                        source_identifier:
                          type: string
                          nullable: true
                        sku_sales_order_updated_at:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - id: 501
                    name: '#1001'
                    email: customer@example.com
                    financial_status: paid
                    fulfillment_status: fulfilled
                    total_price: '89.97'
                    currency: USD
                    legacy_resource_id: '5001234567890'
                    source_name: web
                    shopify_created_at: '2024-03-01T09:00:00+00:00'
                    shopify_updated_at: '2024-03-02T10:00:00+00:00'
                    shopify_processed_at: '2024-03-01T09:05:00+00:00'
                    shopify_cancelled_at: null
                    billing_name: John Smith
                    shipping_name: John Smith
                    shopify_admin_url: https://admin.shopify.com/store/mystore/orders/5001234567890
                    payment_gateway: shopify_payments
                    shipping_method: Standard Shipping
                    source_identifier: null
                    sku_sales_order_updated_at: '2024-03-01T09:10:00+00:00'
                    created_at: '2024-03-01T09:00:00+00:00'
                    updated_at: '2024-03-02T10:00:00+00:00'
                  current_page: 1
                  last_page: 10
                  per_page: 15
                  total: 145
                  from: 1
                  to: 15
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shopify-integrationinstance-orders
  /api/shopify/{integrationInstance}/orders/{order}:
    get:
      tags:
      - Shopify
      summary: Get Order
      description: 'Returns a synced Shopify order by its SKU.io row ID, including
        its line items (with the mapped SKU.io product for each), the linked SKU.io
        sales order with its fulfillments, computed billing/shipping names, payment
        gateways, shipping methods, and a direct Shopify admin link.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: order
        in: path
        schema:
          type: integer
        required: true
        example: '501'
        description: The order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      legacy_resource_id:
                        type: string
                      name:
                        type: string
                      email:
                        type: string
                      currency:
                        type: string
                      financial_status:
                        type: string
                      fulfillment_status:
                        type: string
                      total_price:
                        type: string
                      subtotal_price:
                        type: string
                      total_tax:
                        type: string
                      total_discounts:
                        type: string
                      total_shipping_price:
                        type: string
                      source_name:
                        type: string
                      source_identifier:
                        type: string
                        nullable: true
                      billing_name:
                        type: string
                      shipping_name:
                        type: string
                      payment_gateway:
                        type: string
                      shipping_method:
                        type: string
                      shopify_admin_url:
                        type: string
                      shopify_created_at:
                        type: string
                      shopify_updated_at:
                        type: string
                      sku_sales_order_updated_at:
                        type: string
                      sku_sales_order:
                        type: object
                        properties:
                          id:
                            type: integer
                          number:
                            type: string
                          order_status:
                            type: string
                          fulfillment_status:
                            type: string
                          payment_status:
                            type: string
                          fulfillments:
                            type: array
                            items:
                              type: object
                              properties:
                                id:
                                  type: integer
                                status:
                                  type: string
                                fulfillment_type:
                                  type: string
                                tracking_number:
                                  type: string
                                cost:
                                  type: string
                                  nullable: true
                                fulfilled_at:
                                  type: string
                                submitted_to_sales_channel_at:
                                  type: string
                                warehouse:
                                  type: object
                                  properties:
                                    id:
                                      type: integer
                                    name:
                                      type: string
                                shipping_method:
                                  type: object
                                  properties:
                                    id:
                                      type: integer
                                    name:
                                      type: string
                                line_items:
                                  type: array
                                  items:
                                    type: object
                                    properties:
                                      id:
                                        type: integer
                                      quantity:
                                        type: integer
                                      product_name:
                                        type: string
                                      sku:
                                        type: string
                      order_items:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            legacy_resource_id:
                              type: string
                            name:
                              type: string
                            sku:
                              type: string
                            quantity:
                              type: integer
                            price:
                              type: string
                            mapped_product:
                              type: object
                              properties:
                                id:
                                  type: integer
                                sku:
                                  type: string
                                name:
                                  type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 501
                    integration_instance_id: 1
                    legacy_resource_id: '6001098342'
                    name: '#1001'
                    email: jane@example.com
                    currency: USD
                    financial_status: paid
                    fulfillment_status: fulfilled
                    total_price: '59.90'
                    subtotal_price: '49.90'
                    total_tax: '4.50'
                    total_discounts: '0.00'
                    total_shipping_price: '5.50'
                    source_name: web
                    source_identifier: null
                    billing_name: Jane Doe
                    shipping_name: Jane Doe
                    payment_gateway: shopify_payments
                    shipping_method: Standard Shipping
                    shopify_admin_url: https://admin.shopify.com/store/my-store/orders/6001098342
                    shopify_created_at: '2025-05-20T16:05:00+00:00'
                    shopify_updated_at: '2025-05-22T08:30:00+00:00'
                    sku_sales_order_updated_at: '2025-05-22T08:31:00+00:00'
                    sku_sales_order:
                      id: 9001
                      number: SO-1001
                      order_status: completed
                      fulfillment_status: fulfilled
                      payment_status: paid
                      fulfillments:
                      - id: 3301
                        status: fulfilled
                        fulfillment_type: warehouse
                        tracking_number: 1Z999AA10123456784
                        cost: null
                        fulfilled_at: '2025-05-21T18:00:00.000000Z'
                        submitted_to_sales_channel_at: '2025-05-21T18:05:00.000000Z'
                        warehouse:
                          id: 2
                          name: Main Warehouse
                        shipping_method:
                          id: 8
                          name: Ground
                        line_items:
                        - id: 8801
                          quantity: 2
                          product_name: Blue T-Shirt (M)
                          sku: TSHIRT-M-BLUE
                    order_items:
                    - id: 7001
                      legacy_resource_id: '14000123'
                      name: Blue T-Shirt (M)
                      sku: TSHIRT-M-BLUE
                      quantity: 2
                      price: '24.95'
                      mapped_product:
                        id: 301
                        sku: TSHIRT-M-BLUE
                        name: Blue T-Shirt (M)
                    created_at: '2025-05-20T16:07:00+00:00'
                    updated_at: '2025-05-22T08:31:00+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shopify-integrationinstance-orders-order
    delete:
      tags:
      - Shopify
      summary: Delete Single Order
      description: 'Delete a single Shopify order from the local database.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: order
        in: path
        schema:
          type: integer
        required: true
        example: '501'
        description: The order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Order deleted successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-shopify-integrationinstance-orders-order
  /api/shopify/{integrationInstance}/orders/latest-sync-info:
    get:
      tags:
      - Shopify
      summary: Get Latest Sync Info
      description: 'Get aggregate stats about order sync status. Returns total counts,
        SKU order coverage, and the sync cursor used for incremental syncs.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        The sync_cursor_at should be used (not latest_order_date) for incremental
        refreshes to avoid gaps caused by manual single-order syncs.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      latest_order_name:
                        type: string
                      latest_order_date:
                        type: string
                      sync_cursor_at:
                        type: string
                      total_orders:
                        type: integer
                      total_with_sku_order:
                        type: integer
                      total_without_sku_order:
                        type: integer
                      last_sync_at:
                        type: string
                example:
                  data:
                    latest_order_name: '#2045'
                    latest_order_date: '2024-03-20T14:30:00.000000Z'
                    sync_cursor_at: '2024-03-20T12:00:00.000000Z'
                    total_orders: 2045
                    total_with_sku_order: 1980
                    total_without_sku_order: 65
                    last_sync_at: '2024-03-20 12:00:00'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shopify-integrationinstance-orders-latest-sync-info
  /api/shopify/{integrationInstance}/orders/search-shopify:
    post:
      tags:
      - Shopify
      summary: Search Shopify Orders
      description: 'Search for orders directly in the Shopify store via GraphQL API.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Validation:

        - search_by: required, in: order_number, order_id, email

        - query: required, string, max:255'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                search_by:
                  type: string
                query:
                  type: string
              example:
                search_by: order_number
                query: '1001'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        legacy_resource_id:
                          type: string
                        name:
                          type: string
                        email:
                          type: string
                        shopify_created_at:
                          type: string
                        shopify_updated_at:
                          type: string
                        financial_status:
                          type: string
                        fulfillment_status:
                          type: string
                        total_price:
                          type: object
                          properties:
                            amount:
                              type: string
                            currencyCode:
                              type: string
                        currency:
                          type: string
                        exists_in_database:
                          type: boolean
                        database_id:
                          type: integer
                example:
                  data:
                  - legacy_resource_id: '5001234567890'
                    name: '#1001'
                    email: customer@example.com
                    shopify_created_at: '2024-03-01T09:00:00Z'
                    shopify_updated_at: '2024-03-02T10:00:00Z'
                    financial_status: PAID
                    fulfillment_status: FULFILLED
                    total_price:
                      amount: '89.97'
                      currencyCode: USD
                    currency: USD
                    exists_in_database: true
                    database_id: 501
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-shopify-integrationinstance-orders-search-shopify
  /api/shopify/{integrationInstance}/orders/{order}/detailed:
    get:
      tags:
      - Shopify
      summary: Get Order Detail
      description: 'Get the full ShipHero order detail for the order detail page (by
        local row id via route-model binding). Returns structured header fields (status,
        tracking, and `shipping_method` — the requested method/carrier/price from
        the order''s shipping lines), the SKU.io fulfillment cross-link, line items,
        shipping labels and address, plus the full decoded `json_object`. `has_detailed_data`
        is false when no raw payload has been cached yet.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: order
        in: path
        schema:
          type: integer
        required: true
        example: '501'
        description: The order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      shiphero_id:
                        type: string
                      order_number:
                        type: string
                      external_url:
                        type: string
                      fulfillment_status:
                        type: string
                      fulfillment_status_label:
                        type: string
                      fulfillment_status_color:
                        type: string
                      order_date:
                        type: string
                      tracking_number:
                        type: string
                      carrier:
                        type: string
                      shipped_at:
                        type: string
                      shipping_method:
                        type: object
                        properties:
                          method:
                            type: string
                          carrier:
                            type: string
                          price:
                            type: number
                      sku_fulfillment:
                        type: object
                        properties:
                          id:
                            type: integer
                          link_reference:
                            type: string
                          link_type_label:
                            type: string
                          link_id:
                            type: integer
                          link_route:
                            type: string
                          status:
                            type: string
                          sales_order_id:
                            type: integer
                          sales_order_number:
                            type: string
                          fulfillment_order_id:
                            type: integer
                      line_items:
                        type: array
                        items:
                          type: object
                          properties:
                            sku:
                              type: string
                            product_name:
                              type: string
                            quantity:
                              type: integer
                            product_id:
                              type: integer
                      shipping_labels:
                        type: array
                        items:
                          type: object
                          properties:
                            tracking_number:
                              type: string
                            carrier:
                              type: string
                            created_date:
                              type: string
                      shipping_address:
                        type: object
                        properties:
                          first_name:
                            type: string
                          last_name:
                            type: string
                          address1:
                            type: string
                          city:
                            type: string
                          state:
                            type: string
                          zip:
                            type: string
                          country:
                            type: string
                      has_detailed_data:
                        type: boolean
                      json_object:
                        type: object
                        properties:
                          order_number:
                            type: string
                          fulfillment_status:
                            type: string
                          order_date:
                            type: string
                          shipping_lines:
                            type: object
                            properties:
                              carrier:
                                type: string
                              method:
                                type: string
                              price:
                                type: string
                          shipping_labels:
                            type: array
                            items:
                              type: object
                              properties:
                                tracking_number:
                                  type: string
                                carrier:
                                  type: string
                                created_date:
                                  type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 1024
                    integration_instance_id: 8
                    shiphero_id: T3JkZXI6MTAwNTc0MjM1
                    order_number: SO-100245
                    external_url: https://app.shiphero.com/dashboard/orders/details/T3JkZXI6MTAwNTc0MjM1
                    fulfillment_status: fulfilled
                    fulfillment_status_label: Fulfilled
                    fulfillment_status_color: success
                    order_date: '2026-06-10'
                    tracking_number: 1Z999AA10123456784
                    carrier: UPS
                    shipped_at: '2026-06-11T14:32:00.000000Z'
                    shipping_method:
                      method: UPS Ground
                      carrier: ups
                      price: 8.5
                    sku_fulfillment:
                      id: 4501
                      link_reference: FUL-100245
                      link_type_label: Sales Order Fulfillment
                      link_id: 4501
                      link_route: /orders/sales-orders/fulfillments/4501
                      status: fulfilled
                      sales_order_id: 245
                      sales_order_number: SO-100245
                      fulfillment_order_id: 312
                    line_items:
                    - sku: WIDGET-01
                      product_name: Blue Widget
                      quantity: 2
                      product_id: 88
                    shipping_labels:
                    - tracking_number: 1Z999AA10123456784
                      carrier: UPS
                      created_date: '2026-06-11T14:32:00+00:00'
                    shipping_address:
                      first_name: Aaron
                      last_name: Rubin
                      address1: 120 W 45th St
                      city: New York
                      state: NY
                      zip: '10036'
                      country: US
                    has_detailed_data: true
                    json_object:
                      order_number: SO-100245
                      fulfillment_status: fulfilled
                      order_date: '2026-06-10T09:15:00+00:00'
                      shipping_lines:
                        carrier: ups
                        method: UPS Ground
                        price: '8.50'
                      shipping_labels:
                      - tracking_number: 1Z999AA10123456784
                        carrier: UPS
                        created_date: '2026-06-11T14:32:00+00:00'
                    created_at: '2026-06-10T09:15:00.000000Z'
                    updated_at: '2026-06-11T14:32:05.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shopify-integrationinstance-orders-order-detailed
  /api/shopify/{integrationInstance}/orders/{order}/raw:
    get:
      tags:
      - Shopify
      summary: Get Raw Order (REST)
      description: 'Fetch raw order data from the Shopify REST API for debugging.
        Data is not persisted.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        If Shopify can''t return the order — order older than 60 days without the
        read_all_orders scope, or an order deleted on Shopify — the endpoint returns
        HTTP 200 with `data: null` and an `unavailable_reason` string explaining why.
        Orders that originated as drafts (source_name = shopify_draft_order) are completed
        orders and are read from the standard orders endpoint with the read_orders
        scope.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: order
        in: path
        schema:
          type: integer
        required: true
        example: '501'
        description: The order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 OK
                  value:
                    data:
                      id: 5001234567890
                      order_number: 1001
                      name: '#1001'
                      financial_status: paid
                      line_items: []
                example-1:
                  summary: 200 OK (order unavailable)
                  value:
                    data: null
                    unavailable_reason: Shopify only returns orders from the last
                      60 days to apps without the "read_all_orders" access scope.
                      This order is 90 days old, so Shopify returned no data. Add
                      the scope to the Shopify app and reconnect the integration to
                      view older orders.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shopify-integrationinstance-orders-order-raw
  /api/shopify/{integrationInstance}/orders/{order}/raw-graphql:
    get:
      tags:
      - Shopify
      summary: Get Raw Order (GraphQL)
      description: 'Fetch order data from the Shopify GraphQL API (same query used
        for order sync). Orders that originated as drafts (source_name = shopify_draft_order)
        are completed orders and are read via the standard order query with the read_orders
        scope.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        If Shopify can''t return the order — older than 60 days without read_all_orders,
        or deleted — the response includes an `unavailable_reason` string and the
        order node is null.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: order
        in: path
        schema:
          type: integer
        required: true
        example: '501'
        description: The order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 OK
                  value:
                    data:
                      order:
                        id: gid://shopify/Order/5001234567890
                        name: '#1001'
                        legacyResourceId: '5001234567890'
                    extensions: {}
                    errors: null
                example-1:
                  summary: 200 OK (order unavailable)
                  value:
                    data:
                      order: null
                    extensions: {}
                    errors: []
                    unavailable_reason: Shopify only returns orders from the last
                      60 days to apps without the "read_all_orders" access scope.
                      This order is 90 days old, so Shopify returned no data. Add
                      the scope to the Shopify app and reconnect the integration to
                      view older orders.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shopify-integrationinstance-orders-order-raw-graphql
  /api/shopify/{integrationInstance}/orders/{order}/line-items:
    get:
      tags:
      - Shopify
      summary: Get Order Line Items
      description: 'Lazy-load order line items with taxes, discounts, refunds, fulfillment
        info, and SKU product mapping.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: order
        in: path
        schema:
          type: integer
        required: true
        example: '501'
        description: The order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        legacy_resource_id:
                          type: string
                        name:
                          type: string
                        sku:
                          type: string
                        quantity:
                          type: integer
                        price:
                          type: string
                        variant_id:
                          type: string
                        taxes:
                          type: array
                        discounts:
                          type: array
                        refunds:
                          type: array
                        fulfillment_lines:
                          type: array
                        shopify_product_variant:
                          type: object
                          properties:
                            id:
                              type: integer
                            sku:
                              type: string
                            product_listing:
                              type: object
                              properties:
                                product:
                                  type: object
                                  properties:
                                    id:
                                      type: integer
                                    sku:
                                      type: string
                example:
                  data:
                  - id: 2001
                    legacy_resource_id: '9876543210'
                    name: Classic Blue Shirt - Large
                    sku: SHIRT-BLU-LG
                    quantity: 2
                    price: '29.99'
                    variant_id: '45678901234'
                    taxes: []
                    discounts: []
                    refunds: []
                    fulfillment_lines: []
                    shopify_product_variant:
                      id: 1042
                      sku: SHIRT-BLU-LG
                      product_listing:
                        product:
                          id: 301
                          sku: SHIRT-BLU-LG
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shopify-integrationinstance-orders-order-line-items
  /api/shopify/{integrationInstance}/orders/{order}/shipping-lines:
    get:
      tags:
      - Shopify
      summary: Get Order Shipping Lines
      description: 'Lazy-load order shipping lines with taxes and discounts.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: order
        in: path
        schema:
          type: integer
        required: true
        example: '501'
        description: The order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        title:
                          type: string
                        code:
                          type: string
                        price:
                          type: string
                        taxes:
                          type: array
                        discounts:
                          type: array
                example:
                  data:
                  - id: 3001
                    title: Standard Shipping
                    code: STD
                    price: '9.99'
                    taxes: []
                    discounts: []
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shopify-integrationinstance-orders-order-shipping-lines
  /api/shopify/{integrationInstance}/orders/{order}/refunds:
    get:
      tags:
      - Shopify
      summary: Get Order Refunds
      description: 'Lazy-load order refunds with line items, shipping lines, and adjustments.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: order
        in: path
        schema:
          type: integer
        required: true
        example: '501'
        description: The order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                example:
                  data: []
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shopify-integrationinstance-orders-order-refunds
  /api/shopify/{integrationInstance}/orders/{order}/fulfillments:
    get:
      tags:
      - Shopify
      summary: Get Order Fulfillments
      description: 'Lazy-load order fulfillments with line items and Shopify location
        info.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: order
        in: path
        schema:
          type: integer
        required: true
        example: '501'
        description: The order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        legacy_resource_id:
                          type: string
                        name:
                          type: string
                        service:
                          type: string
                        status:
                          type: string
                        tracking_company:
                          type: string
                        tracking_numbers:
                          type: array
                          items:
                            type: string
                        tracking_urls:
                          type: array
                          items:
                            type: string
                        tracking_number:
                          type: string
                        tracking_url:
                          type: string
                        shopify_created_at:
                          type: string
                        shopify_updated_at:
                          type: string
                        location:
                          type: string
                          nullable: true
                        line_items:
                          type: array
                        total_quantity:
                          type: integer
                example:
                  data:
                  - id: 5001
                    legacy_resource_id: '1234567890'
                    name: 'Fulfillment #1'
                    service: manual
                    status: success
                    tracking_company: UPS
                    tracking_numbers:
                    - 1Z999AA1234567890
                    tracking_urls:
                    - https://wwwapps.ups.com/...
                    tracking_number: 1Z999AA1234567890
                    tracking_url: https://wwwapps.ups.com/...
                    shopify_created_at: '2024-03-02T10:00:00+00:00'
                    shopify_updated_at: '2024-03-02T10:00:00+00:00'
                    location: null
                    line_items: []
                    total_quantity: 2
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shopify-integrationinstance-orders-order-fulfillments
  /api/shopify/{integrationInstance}/orders/{order}/transactions:
    get:
      tags:
      - Shopify
      summary: Get Order Transactions
      description: 'Lazy-load order transactions with Shopify Payments fees.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: order
        in: path
        schema:
          type: integer
        required: true
        example: '501'
        description: The order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        gateway:
                          type: string
                        amount:
                          type: string
                        currency:
                          type: string
                        status:
                          type: string
                        kind:
                          type: string
                        fees:
                          type: array
                example:
                  data:
                  - id: 4001
                    gateway: shopify_payments
                    amount: '89.97'
                    currency: USD
                    status: success
                    kind: sale
                    fees: []
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shopify-integrationinstance-orders-order-transactions
  /api/shopify/{integrationInstance}/orders/note-attribute-names:
    get:
      tags:
      - Shopify
      summary: Get Note Attribute Names
      description: 'Get unique note attribute names (keys) across all orders for this
        integration instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Used to populate delivery date field selector.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: string
                example:
                  data:
                  - deliver_by
                  - ship_by
                  - requested_delivery_date
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shopify-integrationinstance-orders-note-attribute-names
  /api/shopify/{integrationInstance}/orders/metafield-keys:
    get:
      tags:
      - Shopify
      summary: Get Metafield Keys
      description: 'Get unique metafield keys across all orders for this integration
        instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: string
                example:
                  data:
                  - custom.delivery_date
                  - custom.priority
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shopify-integrationinstance-orders-metafield-keys
  /api/shopify/{integrationInstance}/orders/delivery-date-preview:
    get:
      tags:
      - Shopify
      summary: Delivery Date Preview
      description: 'Preview how delivery date configuration rules would apply to existing
        orders.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Validation:

        - deliver_by_date_fields: required, comma-separated field names

        - ship_by_date_calculation_method: required, in: shipping_method, match_deliver_by_date,
        none

        - search: nullable, max:255

        - per_page: nullable, integer, min:1, max:100'
      parameters:
      - name: deliver_by_date_fields
        in: query
        schema:
          type: string
        description: Comma-separated note attribute or metafield keys to use for delivery
          date extraction
        example: deliver_by,custom.delivery_date
      - name: ship_by_date_calculation_method
        in: query
        schema:
          type: string
        description: 'in: shipping_method, match_deliver_by_date, none'
        example: shipping_method
      - name: per_page
        in: query
        schema:
          type: integer
        description: Items per page (max 100)
        example: '10'
      - name: matched_only
        in: query
        schema:
          type: boolean
        description: If true, return only orders that have a matching delivery date
          field
        example: 'false'
      - name: search
        in: query
        schema:
          type: string
        description: Optional search string
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        deliver_by_date:
                          type: string
                        ship_by_date:
                          type: string
                        matched_field:
                          type: string
                  current_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 501
                    name: '#1001'
                    deliver_by_date: '2024-04-01'
                    ship_by_date: '2024-03-29'
                    matched_field: deliver_by
                  current_page: 1
                  total: 12
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shopify-integrationinstance-orders-delivery-date-preview
  /api/shopify/{integrationInstance}/activity-log:
    get:
      tags:
      - Shopify
      summary: Get Instance Order Activity Log
      description: 'Paginated Spatie activity history for all Shopify orders belonging
        to this integration instance, newest first.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Filters:

        - filter[search] - partial match against causer (user) name, event name, or
        the properties JSON payload.


        Pagination: standard Laravel paginator (page, per_page; default 15 per page).


        Ordering: fixed, newest activity first (id DESC). No sort parameter.


        The order scoping is performed database-side via a subquery, so it is safe
        for instances with very large order counts.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Shopify integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        description:
                          type: string
                        event:
                          type: string
                        subject_type:
                          type: string
                        subject_id:
                          type: integer
                        properties:
                          type: object
                          properties:
                            attributes:
                              type: object
                              properties:
                                archived_at:
                                  type: string
                            old:
                              type: object
                              properties:
                                archived_at:
                                  type: string
                                  nullable: true
                        causer_name:
                          type: string
                        created_at:
                          type: string
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                  next_page_url:
                    type: string
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 48291
                    description: updated
                    event: updated
                    subject_type: ShopifyOrder
                    subject_id: 10234
                    properties:
                      attributes:
                        archived_at: '2026-06-01T14:22:09.000000Z'
                      old:
                        archived_at: null
                    causer_name: Jane Smith
                    created_at: '2026-06-01T14:22:09.000000Z'
                  - id: 48275
                    description: created
                    event: created
                    subject_type: ShopifyOrder
                    subject_id: 10233
                    properties:
                      attributes:
                        name: '#1052'
                        financial_status: paid
                    causer_name: null
                    created_at: '2026-06-01T13:58:41.000000Z'
                  first_page_url: https://sku7.test/api/shopify/1/activity-log?page=1
                  from: 1
                  last_page: 84
                  last_page_url: https://sku7.test/api/shopify/1/activity-log?page=84
                  links: []
                  next_page_url: https://sku7.test/api/shopify/1/activity-log?page=2
                  path: https://sku7.test/api/shopify/1/activity-log
                  per_page: 15
                  prev_page_url: null
                  to: 15
                  total: 1257
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shopify-integrationinstance-activity-log
  /api/shopify/{integrationInstance}/orders/{order}/activity-log:
    get:
      tags:
      - Shopify
      summary: Get Order Activity Log
      description: 'Returns a paginated activity log for a single synced Shopify order
        - sync events, status changes, and the user or system process that caused
        each one, newest first.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        filter[search] matches the actor name, the event name, and the recorded change
        payload. Pagination defaults to 15 per page.'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        description: 'Page number (default: 1)'
        example: '1'
      - name: per_page
        in: query
        schema:
          type: integer
        description: 'Items per page (default: 15)'
        example: '15'
      - name: filter[search]
        in: query
        schema:
          type: string
        description: Search actor name, event, or change details
        example: updated
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: order
        in: path
        schema:
          type: integer
        required: true
        example: '501'
        description: The order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        description:
                          type: string
                        event:
                          type: string
                        subject_type:
                          type: string
                        subject_id:
                          type: integer
                        properties:
                          type: object
                          properties:
                            attributes:
                              type: object
                              properties:
                                fulfillment_status:
                                  type: string
                            old:
                              type: object
                              properties:
                                fulfillment_status:
                                  type: string
                        causer:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        created_at:
                          type: string
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 4451
                    description: updated
                    event: updated
                    subject_type: ShopifyOrder
                    subject_id: 501
                    properties:
                      attributes:
                        fulfillment_status: fulfilled
                      old:
                        fulfillment_status: partial
                    causer:
                      id: 3
                      name: Jane Admin
                    created_at: '2025-05-22T08:30:00+00:00'
                  first_page_url: '{{protocol}}://{{domain}}/api/shopify/1/orders/501/activity-log?page=1'
                  from: 1
                  last_page: 1
                  last_page_url: '{{protocol}}://{{domain}}/api/shopify/1/orders/501/activity-log?page=1'
                  next_page_url: null
                  path: '{{protocol}}://{{domain}}/api/shopify/1/orders/501/activity-log'
                  per_page: 15
                  prev_page_url: null
                  to: 1
                  total: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shopify-integrationinstance-orders-order-activity-log
  /api/shopify/{integrationInstance}/orders/refresh-tracked:
    post:
      tags:
      - Shopify
      summary: Refresh Orders (Tracked)
      description: 'Start a tracked order refresh from Shopify. Returns a tracked_job_log_id
        for progress polling.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Requires at least one Shopify location to be mapped to a warehouse (422 if
        not configured).


        Authentication: Requires Bearer token.


        Validation:

        - days: nullable, integer, min:1, max:365

        - updated_at: nullable, date

        - created_at_min: nullable, date'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                days:
                  type: integer
                updated_at:
                  type: string
                  nullable: true
                created_at_min:
                  type: string
                  nullable: true
              example:
                days: 7
                updated_at: null
                created_at_min: null
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 4430
                  message: Order refresh job has been queued
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: At least one Shopify location must be mapped to a warehouse
                    before downloading orders. Go to Settings → Warehouse Mappings
                    to configure.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-shopify-integrationinstance-orders-refresh-tracked
  /api/shopify/{integrationInstance}/orders/refresh-progress/{trackedJobLogId}:
    get:
      tags:
      - Shopify
      summary: Get Refresh Progress
      description: 'Poll the progress of a tracked order refresh job.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: trackedJobLogId
        in: path
        schema:
          type: integer
        required: true
        example: '4430'
        description: The tracked job log ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      job_name:
                        type: string
                      status:
                        type: string
                      progress_current:
                        type: integer
                      progress_total:
                        type: integer
                      started_at:
                        type: string
                      completed_at:
                        type: string
                        nullable: true
                example:
                  data:
                    id: 4430
                    job_name: 'Refresh Shopify Orders: My Store'
                    status: processing
                    progress_current: 80
                    progress_total: 200
                    started_at: '2024-03-20T14:00:00+00:00'
                    completed_at: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shopify-integrationinstance-orders-refresh-progress-trackedjoblogid
  /api/shopify/{integrationInstance}/orders/refresh:
    post:
      tags:
      - Shopify
      summary: Refresh Orders
      description: 'Queues a background download of orders from Shopify. The endpoint
        returns immediately; orders are refreshed asynchronously. For a refresh with
        progress polling, use Refresh Orders (Tracked) instead.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Body fields (both optional - omit both to use the instance''s incremental
        sync cursor):

        - days (integer): refresh orders updated within the last N days.

        - updated_at (datetime string): refresh orders updated since this timestamp.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                days:
                  type: integer
              example:
                days: 7
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Added to queue, orders will be refreshed shortly.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-shopify-integrationinstance-orders-refresh
  /api/shopify/{integrationInstance}/orders/refresh-order:
    post:
      tags:
      - Shopify
      summary: Refresh Single Order from Shopify
      description: 'Fetches one order live from the Shopify Admin API by its Shopify
        order ID, updates the local copy synchronously, and returns the refreshed
        order.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Body fields:

        - uniqueId (string, required): the Shopify order ID (numeric ID from Shopify,
        not the SKU.io row ID).


        Returns 404 when the order cannot be found in Shopify.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                uniqueId:
                  type: string
              example:
                uniqueId: '6001098342'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      legacy_resource_id:
                        type: string
                      name:
                        type: string
                      email:
                        type: string
                      currency:
                        type: string
                      financial_status:
                        type: string
                      fulfillment_status:
                        type: string
                      total_price:
                        type: string
                      billing_name:
                        type: string
                      shipping_name:
                        type: string
                      shopify_admin_url:
                        type: string
                      shopify_created_at:
                        type: string
                      shopify_updated_at:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 501
                    integration_instance_id: 1
                    legacy_resource_id: '6001098342'
                    name: '#1001'
                    email: jane@example.com
                    currency: USD
                    financial_status: paid
                    fulfillment_status: fulfilled
                    total_price: '59.90'
                    billing_name: Jane Doe
                    shipping_name: Jane Doe
                    shopify_admin_url: https://admin.shopify.com/store/my-store/orders/6001098342
                    shopify_created_at: '2025-05-20T16:05:00+00:00'
                    shopify_updated_at: '2025-05-22T08:30:00+00:00'
                    created_at: '2025-05-20T16:07:00+00:00'
                    updated_at: '2025-06-30T11:00:00+00:00'
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Order not found
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-shopify-integrationinstance-orders-refresh-order
  /api/shopify/{integrationInstance}/orders/create-sku-orders:
    post:
      tags:
      - Shopify
      summary: Create SKU Orders
      description: 'Creates SKU.io sales orders from synced Shopify orders that do
        not have one yet. A single order is created synchronously; multiple orders
        are processed asynchronously and the response includes a tracked_job_log_id
        for polling progress.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Body fields:

        - ids (array of integers): SKU.io row IDs of the Shopify orders to convert.
        Required unless apply_to_all or create_all_orders is true.

        - apply_to_all / create_all_orders (boolean): convert every eligible order
        on the instance.

        - filters (object, optional): narrows the order set when converting all.


        Orders that are archived, already linked to a sales order, or (when location
        mapping is enabled) missing fulfillment order data are skipped automatically.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 501
                - 502
                - 503
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 OK (single order)
                  value:
                    message: 1 SKU order created successfully
                example-1:
                  summary: 200 OK (bulk queued)
                  value:
                    message: SKU order creation started for 25 orders
                    tracked_job_log_id: 991
                    total_orders: 25
                example-2:
                  summary: 200 OK (nothing to do)
                  value:
                    message: No orders to create
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-shopify-integrationinstance-orders-create-sku-orders
  /api/shopify/{integrationInstance}/orders/update-sku-orders:
    post:
      tags:
      - Shopify
      summary: Update SKU Orders
      description: 'Re-applies the latest synced Shopify order data to the linked
        SKU.io sales orders (statuses, line items, addresses). By default the work
        is queued in the background; set use_jobs to false to process synchronously.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Body fields:

        - update_all_orders (boolean, required): update every linked order on the
        instance.

        - ids (array of integers): SKU.io row IDs of specific Shopify orders to update
        (used when update_all_orders is false).

        - use_jobs (boolean, default true): process asynchronously (true) or inline
        (false).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                update_all_orders:
                  type: boolean
                ids:
                  type: array
                  items:
                    type: integer
                use_jobs:
                  type: boolean
              example:
                update_all_orders: false
                ids:
                - 501
                - 502
                use_jobs: true
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Sku.io sales orders successfully updated
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-shopify-integrationinstance-orders-update-sku-orders
  /api/shopify/{integrationInstance}/orders/bulk-archive:
    post:
      tags:
      - Shopify
      summary: Bulk Archive Orders
      description: 'Archive multiple Shopify orders. Supports filtering with apply_to_all.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Validation:

        - ids: required_without apply_to_all, array of integers

        - apply_to_all: boolean (use filters instead of ids)

        - filters: array'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 501
                - 502
                - 503
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  archived_count:
                    type: integer
                example:
                  message: 3 orders archived successfully
                  archived_count: 3
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-shopify-integrationinstance-orders-bulk-archive
  /api/shopify/{integrationInstance}/orders/bulk-unarchive:
    post:
      tags:
      - Shopify
      summary: Bulk Unarchive Orders
      description: 'Unarchive multiple Shopify orders.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 501
                - 502
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  unarchived_count:
                    type: integer
                example:
                  message: 2 orders unarchived successfully
                  unarchived_count: 2
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-shopify-integrationinstance-orders-bulk-unarchive
  /api/shopify/{integrationInstance}/orders/bulk-delete:
    post:
      tags:
      - Shopify
      summary: Bulk Delete Orders
      description: 'Delete multiple Shopify orders. Single orders deleted synchronously;
        multiple dispatches a tracked job.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 501
                - 502
                - 503
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  tracked_job_log_id:
                    type: integer
                  total_orders:
                    type: integer
                example:
                  message: Bulk delete job started
                  tracked_job_log_id: 4440
                  total_orders: 3
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-shopify-integrationinstance-orders-bulk-delete
  /api/shopify/{integrationInstance}/orders/bulk-delete-sku-orders:
    post:
      tags:
      - Shopify
      summary: Bulk Delete SKU Orders
      description: 'Bulk delete the linked SKU sales orders (keeps Shopify orders
        intact). Dispatches a tracked job for large batches.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Validation:

        - ids: required_without apply_to_all, array of integers

        - apply_to_all: boolean

        - filters: array

        - archive_shopify_orders: boolean (archive Shopify orders after deleting SKU
        orders)'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
                archive_shopify_orders:
                  type: boolean
              example:
                ids:
                - 501
                - 502
                archive_shopify_orders: false
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  tracked_job_log_id:
                    type: integer
                  total_orders:
                    type: integer
                example:
                  message: Bulk delete job started
                  tracked_job_log_id: 4441
                  total_orders: 2
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-shopify-integrationinstance-orders-bulk-delete-sku-orders
  /api/shopify/{integrationInstance}/orders/{order}/archive:
    post:
      tags:
      - Shopify
      summary: Archive Single Order
      description: 'Archive a single Shopify order.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: order
        in: path
        schema:
          type: integer
        required: true
        example: '501'
        description: The order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  archived:
                    type: boolean
                example:
                  message: Order archived successfully
                  archived: true
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-shopify-integrationinstance-orders-order-archive
  /api/shopify/{integrationInstance}/orders/{order}/unarchive:
    post:
      tags:
      - Shopify
      summary: Unarchive Single Order
      description: 'Unarchive a single Shopify order.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: order
        in: path
        schema:
          type: integer
        required: true
        example: '501'
        description: The order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  unarchived:
                    type: boolean
                example:
                  message: Order unarchived successfully
                  unarchived: true
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-shopify-integrationinstance-orders-order-unarchive
  /api/shopify/{integrationInstance}/orders/{order}/sku-order:
    delete:
      tags:
      - Shopify
      summary: Delete SKU Order (Keep Shopify Order)
      description: 'Delete the linked SKU sales order while keeping the Shopify order
        intact. Optionally archives the Shopify order.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Returns 404 if no SKU order is linked.


        Authentication: Requires Bearer token.'
      parameters:
      - name: archive_shopify_order
        in: query
        schema:
          type: boolean
        description: If true, also archive the Shopify order after deleting the SKU
          order
        example: 'false'
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: order
        in: path
        schema:
          type: integer
        required: true
        example: '501'
        description: The order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  archived_shopify_order:
                    type: boolean
                example:
                  message: SKU order deleted successfully
                  archived_shopify_order: false
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: No SKU order linked to this Shopify order
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: delete-api-shopify-integrationinstance-orders-order-sku-order
  /api/shopify/{integrationInstance}/fulfillments:
    get:
      tags:
      - Shopify
      summary: List Shopify Fulfillments
      description: 'List synced Shopify fulfillments for an integration instance (paginated).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        example: '1'
        description: Page number (default 1).
      - name: per_page
        in: query
        schema:
          type: integer
        example: '10'
        description: Results per page (default 10).
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        legacy_resource_id:
                          type: string
                        name:
                          type: string
                        service:
                          type: string
                        status:
                          type: string
                        tracking_company:
                          type: string
                        tracking_numbers:
                          type: array
                          items:
                            type: string
                        tracking_urls:
                          type: array
                          items:
                            type: string
                        tracking_number:
                          type: string
                        tracking_url:
                          type: string
                        shopify_created_at:
                          type: string
                        shopify_updated_at:
                          type: string
                        location:
                          type: string
                          nullable: true
                        line_items:
                          type: array
                        total_quantity:
                          type: integer
                        order:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            legacy_resource_id:
                              type: string
                            sales_order:
                              type: object
                              properties:
                                id:
                                  type: integer
                                sales_order_number:
                                  type: string
                                route:
                                  type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 5001
                    legacy_resource_id: '1234567890'
                    name: 'Fulfillment #1'
                    service: manual
                    status: success
                    tracking_company: UPS
                    tracking_numbers:
                    - 1Z999AA1234567890
                    tracking_urls:
                    - https://wwwapps.ups.com/...
                    tracking_number: 1Z999AA1234567890
                    tracking_url: https://wwwapps.ups.com/...
                    shopify_created_at: '2024-03-02T10:00:00+00:00'
                    shopify_updated_at: '2024-03-02T10:00:00+00:00'
                    location: null
                    line_items: []
                    total_quantity: 2
                    order:
                      id: 501
                      name: '#1001'
                      legacy_resource_id: '5001234567890'
                      sales_order:
                        id: 7421
                        sales_order_number: SO-0042
                        route: /orders/sales-orders/7421
                  current_page: 1
                  last_page: 5
                  per_page: 10
                  total: 48
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shopify-integrationinstance-fulfillments
  /api/shopify/{integrationInstance}/fulfillments/pending:
    get:
      tags:
      - Shopify
      summary: List Pending Fulfillments
      description: 'List pending SKU sales order fulfillments waiting to sync to Shopify.
        Includes mismatch data (unlinked Shopify fulfillments).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        example: '1'
        description: Page number (default 1).
      - name: per_page
        in: query
        schema:
          type: integer
        example: '10'
        description: Results per page (default 10).
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        fulfillment_number:
                          type: string
                        fulfillment_type:
                          type: string
                        status:
                          type: string
                        tracking_number:
                          type: string
                        cost:
                          type: string
                        fulfilled_at:
                          type: string
                        created_at:
                          type: string
                        carrier:
                          type: string
                        shipping_method_display:
                          type: string
                        sales_order:
                          type: object
                          properties:
                            id:
                              type: integer
                            sales_order_number:
                              type: string
                        shopify_order:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            legacy_resource_id:
                              type: string
                        warehouse:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        shopify_fulfillment_orders:
                          type: array
                        has_mismatch:
                          type: boolean
                        unlinked_shopify_fulfillments:
                          type: array
                  current_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 8001
                    fulfillment_number: FF-001
                    fulfillment_type: standard
                    status: ready
                    tracking_number: 1Z999AA1234567890
                    cost: '9.99'
                    fulfilled_at: '2024-03-20T08:00:00+00:00'
                    created_at: '2024-03-20T07:00:00+00:00'
                    carrier: UPS
                    shipping_method_display: UPS Ground
                    sales_order:
                      id: 601
                      sales_order_number: SO-2024-001
                    shopify_order:
                      id: 501
                      name: '#1001'
                      legacy_resource_id: '5001234567890'
                    warehouse:
                      id: 1
                      name: Main Warehouse
                    shopify_fulfillment_orders: []
                    has_mismatch: false
                    unlinked_shopify_fulfillments: []
                  current_page: 1
                  per_page: 10
                  total: 5
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shopify-integrationinstance-fulfillments-pending
  /api/shopify/{integrationInstance}/fulfillments/stats:
    get:
      tags:
      - Shopify
      summary: Get Fulfillment Stats
      description: 'Get fulfillment page stats: pending sync count, mismatch count,
        and automatic sync schedule info.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      pending_sync_count:
                        type: integer
                      mismatch_count:
                        type: integer
                      sync_schedule:
                        type: object
                        properties:
                          interval:
                            type: integer
                          unit:
                            type: string
                          description:
                            type: string
                example:
                  data:
                    pending_sync_count: 5
                    mismatch_count: 2
                    sync_schedule:
                      interval: 10
                      unit: minutes
                      description: Fulfillments are automatically synced every 10
                        minutes
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shopify-integrationinstance-fulfillments-stats
  /api/shopify/{integrationInstance}/fulfillments/{salesOrderFulfillment}/submit:
    post:
      tags:
      - Shopify
      summary: Submit Single Fulfillment
      description: 'Submit a single SKU sales order fulfillment to Shopify.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        In non-production environments, submission is skipped unless force_submit=true.


        Authentication: Requires Bearer token.


        Query parameters:

        - force_submit: boolean (bypass non-production check)'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                force_submit:
                  type: boolean
              example:
                force_submit: false
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: salesOrderFulfillment
        in: path
        schema:
          type: integer
        required: true
        example: '8001'
        description: The sales order fulfillment ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                example:
                  success: true
                  message: The fulfillment submitted successfully
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                example:
                  success: false
                  message: Fulfillment submission failed
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-shopify-integrationinstance-fulfillments-salesorderfulfillment-submit
  /api/shopify/{integrationInstance}/fulfillments/submit-bulk:
    post:
      tags:
      - Shopify
      summary: Submit Bulk Fulfillments
      description: 'Submit multiple selected SKU fulfillments to Shopify.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Validation:

        - ids: required, array of sales_order_fulfillments IDs

        - force_submit: boolean'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
                force_submit:
                  type: boolean
              example:
                ids:
                - 8001
                - 8002
                - 8003
                force_submit: false
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      submitted:
                        type: integer
                      failed:
                        type: integer
                  errors:
                    type: array
                  message:
                    type: string
                example:
                  success: true
                  data:
                    submitted: 3
                    failed: 0
                  errors: []
                  message: 3 fulfillment(s) submitted, 0 failed
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-shopify-integrationinstance-fulfillments-submit-bulk
  /api/shopify/{integrationInstance}/fulfillments/submit-all:
    post:
      tags:
      - Shopify
      summary: Submit All Pending Fulfillments
      description: 'Submit all pending SKU fulfillments to Shopify in one operation.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                force_submit:
                  type: boolean
              example:
                force_submit: false
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      submitted:
                        type: integer
                      failed:
                        type: integer
                  errors:
                    type: array
                  message:
                    type: string
                example:
                  success: true
                  data:
                    submitted: 5
                    failed: 0
                  errors: []
                  message: 5 fulfillment(s) submitted, 0 failed
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-shopify-integrationinstance-fulfillments-submit-all
  /api/shopify/{integrationInstance}/fulfill:
    post:
      tags:
      - Shopify
      summary: Submit Fulfillment to Shopify
      description: 'Pushes a SKU.io sales order fulfillment (tracking number, carrier,
        fulfilled items) to Shopify, marking the corresponding Shopify order as fulfilled.
        The fulfillment is identified in the request body rather than the URL.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Body fields:

        - sales_order_fulfillment_id (integer, required): the SKU.io fulfillment to
        submit; must exist.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                sales_order_fulfillment_id:
                  type: integer
              example:
                sales_order_fulfillment_id: 3301
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Successfully submitted to sales channel.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      sales_order_fulfillment_id:
                        type: array
                        items:
                          type: string
                example:
                  message: The selected sales order fulfillment id is invalid.
                  errors:
                    sales_order_fulfillment_id:
                    - The selected sales order fulfillment id is invalid.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-shopify-integrationinstance-fulfill
  /api/shopify/{integrationInstance}/fulfillments/mismatches:
    get:
      tags:
      - Shopify
      summary: List Fulfillment Mismatches
      description: 'List SKU fulfillments that have mismatches — not synced to Shopify
        but the order has unlinked Shopify fulfillments.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        example: '1'
        description: Page number (default 1).
      - name: per_page
        in: query
        schema:
          type: integer
        example: '10'
        description: Results per page (default 10).
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        fulfillment_number:
                          type: string
                        tracking_number:
                          type: string
                        cost:
                          type: string
                        status:
                          type: string
                        fulfilled_at:
                          type: string
                        carrier:
                          type: string
                        warehouse:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        sales_order:
                          type: object
                          properties:
                            id:
                              type: integer
                            sales_order_number:
                              type: string
                        shopify_order:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        unlinked_shopify_fulfillments:
                          type: array
                          items:
                            type: object
                            properties:
                              id:
                                type: integer
                              name:
                                type: string
                              tracking_numbers:
                                type: array
                                items:
                                  type: string
                              tracking_company:
                                type: string
                              status:
                                type: string
                              shopify_created_at:
                                type: string
                              tracking_matches:
                                type: boolean
                        created_at:
                          type: string
                  current_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 8002
                    fulfillment_number: FF-002
                    tracking_number: 1Z999AA1234567891
                    cost: '9.99'
                    status: ready
                    fulfilled_at: '2024-03-18T08:00:00+00:00'
                    carrier: FedEx
                    warehouse:
                      id: 1
                      name: Main Warehouse
                    sales_order:
                      id: 601
                      sales_order_number: SO-2024-001
                    shopify_order:
                      id: 501
                      name: '#1001'
                    unlinked_shopify_fulfillments:
                    - id: 5002
                      name: 'Fulfillment #2'
                      tracking_numbers:
                      - 1Z999AA1234567891
                      tracking_company: FedEx
                      status: success
                      shopify_created_at: '2024-03-18T09:00:00+00:00'
                      tracking_matches: true
                    created_at: '2024-03-18T07:00:00+00:00'
                  current_page: 1
                  per_page: 10
                  total: 2
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shopify-integrationinstance-fulfillments-mismatches
  /api/shopify/{integrationInstance}/fulfillments/{salesOrderFulfillment}/link/{shopifyFulfillment}:
    post:
      tags:
      - Shopify
      summary: Link Fulfillments
      description: 'Link a SKU fulfillment to an existing Shopify fulfillment to resolve
        a mismatch. Use force_link=true if tracking numbers differ.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                force_link:
                  type: boolean
              example:
                force_link: false
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: salesOrderFulfillment
        in: path
        schema:
          type: integer
        required: true
        example: '8002'
        description: The sales order fulfillment ID.
      - name: shopifyFulfillment
        in: path
        schema:
          type: integer
        required: true
        example: '5002'
        description: The shopify fulfillment ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                example:
                  success: true
                  message: Fulfillments linked successfully
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                example:
                  success: false
                  message: Tracking numbers do not match. Use force_link=true to link
                    anyway.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-shopify-integrationinstance-fulfillments-salesorderfulfillment-link-shopifyfulfillment
  /api/shopify/{integrationInstance}/fulfillments/{salesOrderFulfillment}/update-shopify/{shopifyFulfillment}:
    post:
      tags:
      - Shopify
      summary: Update Shopify Fulfillment from SKU
      description: 'Update Shopify fulfillment tracking info from the SKU fulfillment
        and link them.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: salesOrderFulfillment
        in: path
        schema:
          type: integer
        required: true
        example: '8002'
        description: The sales order fulfillment ID.
      - name: shopifyFulfillment
        in: path
        schema:
          type: integer
        required: true
        example: '5002'
        description: The shopify fulfillment ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                example:
                  success: true
                  message: Shopify fulfillment updated and linked successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-shopify-integrationinstance-fulfillments-salesorderfulfillment-update-shopify-shopifyfulfillment
  /api/shopify/{integrationInstance}/fulfillments/{salesOrderFulfillment}/create-from-shopify/{shopifyFulfillment}:
    post:
      tags:
      - Shopify
      summary: Delete SKU Create from Shopify
      description: 'Delete the SKU fulfillment and create a new one from the Shopify
        fulfillment data. Resolves mismatches where Shopify is the source of truth.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: salesOrderFulfillment
        in: path
        schema:
          type: integer
        required: true
        example: '8002'
        description: The sales order fulfillment ID.
      - name: shopifyFulfillment
        in: path
        schema:
          type: integer
        required: true
        example: '5002'
        description: The shopify fulfillment ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                example:
                  success: true
                  message: SKU fulfillment replaced with Shopify fulfillment data
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-shopify-integrationinstance-fulfillments-salesorderfulfillment-create-from-shopify-shopifyfulfillment
  /api/shopify/{integrationInstance}/fulfillments/{fulfillment}/detailed:
    get:
      tags:
      - Shopify
      summary: Get Fulfillment Detailed
      description: 'Get a single Shopify fulfillment with all relationships eager-loaded
        (order, location, line items + their order line item, and the related fulfillment
        orders with their location and line items). The SKU-internal sales order fulfillment
        this Shopify fulfillment is linked to (`sales_order_fulfillment`), including
        that fulfillment''s internal fulfillment order, is included when present.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Returns 403 if the fulfillment does not belong to the given integration instance.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: fulfillment
        in: path
        schema:
          type: integer
        required: true
        example: '5001'
        description: The fulfillment ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      legacy_resource_id:
                        type: string
                      name:
                        type: string
                      service:
                        type: string
                      status:
                        type: string
                      tracking_company:
                        type: string
                      tracking_numbers:
                        type: array
                        items:
                          type: string
                      tracking_urls:
                        type: array
                        items:
                          type: string
                      tracking_number:
                        type: string
                      tracking_url:
                        type: string
                      shopify_created_at:
                        type: string
                      shopify_updated_at:
                        type: string
                      location:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          address1:
                            type: string
                          city:
                            type: string
                          province:
                            type: string
                          country:
                            type: string
                          country_code:
                            type: string
                      line_items:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            legacy_resource_id:
                              type: string
                            quantity:
                              type: integer
                            order_line_item:
                              type: object
                              properties:
                                id:
                                  type: integer
                                legacy_resource_id:
                                  type: string
                                variant_id:
                                  type: string
                                name:
                                  type: string
                                sku:
                                  type: string
                                quantity:
                                  type: integer
                      total_quantity:
                        type: integer
                      order:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          legacy_resource_id:
                            type: string
                          sales_order:
                            type: object
                            properties:
                              id:
                                type: integer
                              sales_order_number:
                                type: string
                              route:
                                type: string
                      fulfillment_orders:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            legacy_resource_id:
                              type: string
                            status:
                              type: string
                            shopify_created_at:
                              type: string
                            shopify_updated_at:
                              type: string
                            location:
                              type: object
                              properties:
                                id:
                                  type: integer
                                name:
                                  type: string
                                address1:
                                  type: string
                                city:
                                  type: string
                                province:
                                  type: string
                                country:
                                  type: string
                                country_code:
                                  type: string
                            line_items:
                              type: array
                              items:
                                type: object
                                properties:
                                  id:
                                    type: integer
                                  legacy_resource_id:
                                    type: string
                                  total_quantity:
                                    type: integer
                                  remaining_quantity:
                                    type: integer
                                  order_line_item:
                                    type: object
                                    properties:
                                      id:
                                        type: integer
                                      legacy_resource_id:
                                        type: string
                                      variant_id:
                                        type: string
                                      name:
                                        type: string
                                      sku:
                                        type: string
                                      quantity:
                                        type: integer
                            total_quantity:
                              type: integer
                      sales_order_fulfillment:
                        type: object
                        properties:
                          id:
                            type: integer
                          fulfillment_number:
                            type: string
                          status:
                            type: string
                          route:
                            type: string
                          fulfillment_order:
                            type: object
                            properties:
                              id:
                                type: integer
                              reference:
                                type: string
                              status:
                                type: string
                              request_status:
                                type: string
                              route:
                                type: string
                example:
                  data:
                    id: 5001
                    legacy_resource_id: '1234567890'
                    name: 'Fulfillment #1'
                    service: manual
                    status: success
                    tracking_company: UPS
                    tracking_numbers:
                    - 1Z999AA1234567890
                    tracking_urls:
                    - https://wwwapps.ups.com/tracking/1Z999AA1234567890
                    tracking_number: 1Z999AA1234567890
                    tracking_url: https://wwwapps.ups.com/tracking/1Z999AA1234567890
                    shopify_created_at: '2024-03-02T10:05:00+00:00'
                    shopify_updated_at: '2024-03-02T10:05:00+00:00'
                    location:
                      id: 12
                      name: Main Warehouse
                      address1: 123 Commerce St
                      city: Austin
                      province: Texas
                      country: United States
                      country_code: US
                    line_items:
                    - id: 61001
                      legacy_resource_id: '222333444'
                      quantity: 2
                      order_line_item:
                        id: 71001
                        legacy_resource_id: '5550001111'
                        variant_id: '40123456789'
                        name: Premium Caviar 50g
                        sku: CAV-50G
                        quantity: 2
                    total_quantity: 2
                    order:
                      id: 501
                      name: '#1001'
                      legacy_resource_id: '5001234567890'
                      sales_order:
                        id: 7421
                        sales_order_number: SO-0042
                        route: /orders/sales-orders/7421
                    fulfillment_orders:
                    - id: 8001
                      legacy_resource_id: '9876543210'
                      status: closed
                      shopify_created_at: '2024-03-02T10:00:00+00:00'
                      shopify_updated_at: '2024-03-02T10:06:00+00:00'
                      location:
                        id: 12
                        name: Main Warehouse
                        address1: 123 Commerce St
                        city: Austin
                        province: Texas
                        country: United States
                        country_code: US
                      line_items:
                      - id: 41001
                        legacy_resource_id: '111222333'
                        total_quantity: 2
                        remaining_quantity: 0
                        order_line_item:
                          id: 71001
                          legacy_resource_id: '5550001111'
                          variant_id: '40123456789'
                          name: Premium Caviar 50g
                          sku: CAV-50G
                          quantity: 2
                      total_quantity: 2
                    sales_order_fulfillment:
                      id: 19112
                      fulfillment_number: F-1001-1
                      status: fulfilled
                      route: /orders/sales-orders/fulfillments/19112
                      fulfillment_order:
                        id: 14098
                        reference: SO-1001.1
                        status: open
                        request_status: submitted
                        route: /orders/fulfillment-orders/14098
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shopify-integrationinstance-fulfillments-fulfillment-detailed
  /api/shopify/{integrationInstance}/fulfillment-orders:
    get:
      tags:
      - Shopify
      summary: List Fulfillment Orders
      description: 'List synced Shopify fulfillment orders for an integration instance
        (paginated, default 10 per page).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Filters (Spatie QueryBuilder):

        - filter[search] — free-text across legacy_resource_id, status, order name,
        location name

        - filter[status] — text operators on the fulfillment order status (e.g. open,
        in_progress, scheduled, cancelled, on_hold, incomplete, closed)

        - filter[id] — numeric operators on the primary key

        - filter[total_quantity] — numeric operators on the summed line-item total_quantity

        - filter[order_name] — text operators on the related Shopify order name

        - filter[location_name] — text operators on the related location name

        - filter[order_id] — exact match on shopify_order_id

        - filter[shopify_created_at] / filter[shopify_updated_at] — datetime operators


        Sort (sort=): id, status, shopify_created_at, shopify_updated_at (prefix with
        - for descending). Default: -id.


        Pagination: page, per_page.


        Authentication: Requires Bearer token.'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        example: '1'
        description: Page number (default 1).
      - name: per_page
        in: query
        schema:
          type: integer
        example: '10'
        description: Results per page (default 10).
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        legacy_resource_id:
                          type: string
                        status:
                          type: string
                        shopify_created_at:
                          type: string
                        shopify_updated_at:
                          type: string
                        location:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            address1:
                              type: string
                            city:
                              type: string
                            province:
                              type: string
                            country:
                              type: string
                            country_code:
                              type: string
                        line_items:
                          type: array
                          items:
                            type: object
                            properties:
                              id:
                                type: integer
                              legacy_resource_id:
                                type: string
                              total_quantity:
                                type: integer
                              remaining_quantity:
                                type: integer
                              order_line_item:
                                type: string
                                nullable: true
                        total_quantity:
                          type: integer
                        order:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            legacy_resource_id:
                              type: string
                            sales_order:
                              type: object
                              properties:
                                id:
                                  type: integer
                                sales_order_number:
                                  type: string
                                route:
                                  type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 8001
                    legacy_resource_id: '9876543210'
                    status: open
                    shopify_created_at: '2024-03-02T10:00:00+00:00'
                    shopify_updated_at: '2024-03-02T10:00:00+00:00'
                    location:
                      id: 12
                      name: Main Warehouse
                      address1: 123 Commerce St
                      city: Austin
                      province: Texas
                      country: United States
                      country_code: US
                    line_items:
                    - id: 41001
                      legacy_resource_id: '111222333'
                      total_quantity: 2
                      remaining_quantity: 0
                      order_line_item: null
                    total_quantity: 2
                    order:
                      id: 501
                      name: '#1001'
                      legacy_resource_id: '5001234567890'
                      sales_order:
                        id: 7421
                        sales_order_number: SO-0042
                        route: /orders/sales-orders/7421
                  current_page: 1
                  last_page: 7
                  per_page: 10
                  total: 65
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shopify-integrationinstance-fulfillment-orders
  /api/shopify/{integrationInstance}/fulfillment-orders/{fulfillmentOrder}/detailed:
    get:
      tags:
      - Shopify
      summary: Get Fulfillment Order Detailed
      description: 'Get a single Shopify fulfillment order with all relationships
        eager-loaded (order, location, line items + their order line item, and the
        related fulfillments with their location and line items). Each related fulfillment
        includes its linked SKU-internal sales order fulfillment (`sales_order_fulfillment`)
        and that fulfillment''s internal fulfillment order when present.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Returns 403 if the fulfillment order does not belong to the given integration
        instance.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: fulfillmentOrder
        in: path
        schema:
          type: integer
        required: true
        example: '8001'
        description: The fulfillment order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      legacy_resource_id:
                        type: string
                      status:
                        type: string
                      shopify_created_at:
                        type: string
                      shopify_updated_at:
                        type: string
                      location:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          address1:
                            type: string
                          city:
                            type: string
                          province:
                            type: string
                          country:
                            type: string
                          country_code:
                            type: string
                      line_items:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            legacy_resource_id:
                              type: string
                            total_quantity:
                              type: integer
                            remaining_quantity:
                              type: integer
                            order_line_item:
                              type: object
                              properties:
                                id:
                                  type: integer
                                legacy_resource_id:
                                  type: string
                                variant_id:
                                  type: string
                                name:
                                  type: string
                                sku:
                                  type: string
                                quantity:
                                  type: integer
                      total_quantity:
                        type: integer
                      order:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          legacy_resource_id:
                            type: string
                          sales_order:
                            type: object
                            properties:
                              id:
                                type: integer
                              sales_order_number:
                                type: string
                              route:
                                type: string
                      fulfillments:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            legacy_resource_id:
                              type: string
                            name:
                              type: string
                            service:
                              type: string
                            status:
                              type: string
                            tracking_company:
                              type: string
                            tracking_numbers:
                              type: array
                              items:
                                type: string
                            tracking_urls:
                              type: array
                              items:
                                type: string
                            tracking_number:
                              type: string
                            tracking_url:
                              type: string
                            shopify_created_at:
                              type: string
                            shopify_updated_at:
                              type: string
                            location:
                              type: object
                              properties:
                                id:
                                  type: integer
                                name:
                                  type: string
                                address1:
                                  type: string
                                city:
                                  type: string
                                province:
                                  type: string
                                country:
                                  type: string
                                country_code:
                                  type: string
                            line_items:
                              type: array
                              items:
                                type: object
                                properties:
                                  id:
                                    type: integer
                                  legacy_resource_id:
                                    type: string
                                  quantity:
                                    type: integer
                                  order_line_item:
                                    type: object
                                    properties:
                                      id:
                                        type: integer
                                      legacy_resource_id:
                                        type: string
                                      variant_id:
                                        type: string
                                      name:
                                        type: string
                                      sku:
                                        type: string
                                      quantity:
                                        type: integer
                            total_quantity:
                              type: integer
                            sales_order_fulfillment:
                              type: object
                              properties:
                                id:
                                  type: integer
                                fulfillment_number:
                                  type: string
                                status:
                                  type: string
                                route:
                                  type: string
                                fulfillment_order:
                                  type: object
                                  properties:
                                    id:
                                      type: integer
                                    reference:
                                      type: string
                                    status:
                                      type: string
                                    request_status:
                                      type: string
                                    route:
                                      type: string
                example:
                  data:
                    id: 8001
                    legacy_resource_id: '9876543210'
                    status: open
                    shopify_created_at: '2024-03-02T10:00:00+00:00'
                    shopify_updated_at: '2024-03-02T10:00:00+00:00'
                    location:
                      id: 12
                      name: Main Warehouse
                      address1: 123 Commerce St
                      city: Austin
                      province: Texas
                      country: United States
                      country_code: US
                    line_items:
                    - id: 41001
                      legacy_resource_id: '111222333'
                      total_quantity: 2
                      remaining_quantity: 0
                      order_line_item:
                        id: 71001
                        legacy_resource_id: '5550001111'
                        variant_id: '40123456789'
                        name: Premium Caviar 50g
                        sku: CAV-50G
                        quantity: 2
                    total_quantity: 2
                    order:
                      id: 501
                      name: '#1001'
                      legacy_resource_id: '5001234567890'
                      sales_order:
                        id: 7421
                        sales_order_number: SO-0042
                        route: /orders/sales-orders/7421
                    fulfillments:
                    - id: 5001
                      legacy_resource_id: '1234567890'
                      name: 'Fulfillment #1'
                      service: manual
                      status: success
                      tracking_company: UPS
                      tracking_numbers:
                      - 1Z999AA1234567890
                      tracking_urls:
                      - https://wwwapps.ups.com/tracking/1Z999AA1234567890
                      tracking_number: 1Z999AA1234567890
                      tracking_url: https://wwwapps.ups.com/tracking/1Z999AA1234567890
                      shopify_created_at: '2024-03-02T10:05:00+00:00'
                      shopify_updated_at: '2024-03-02T10:05:00+00:00'
                      location:
                        id: 12
                        name: Main Warehouse
                        address1: 123 Commerce St
                        city: Austin
                        province: Texas
                        country: United States
                        country_code: US
                      line_items:
                      - id: 61001
                        legacy_resource_id: '222333444'
                        quantity: 2
                        order_line_item:
                          id: 71001
                          legacy_resource_id: '5550001111'
                          variant_id: '40123456789'
                          name: Premium Caviar 50g
                          sku: CAV-50G
                          quantity: 2
                      total_quantity: 2
                      sales_order_fulfillment:
                        id: 19112
                        fulfillment_number: F-1001-1
                        status: fulfilled
                        route: /orders/sales-orders/fulfillments/19112
                        fulfillment_order:
                          id: 14098
                          reference: SO-1001.1
                          status: open
                          request_status: submitted
                          route: /orders/fulfillment-orders/14098
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shopify-integrationinstance-fulfillment-orders-fulfillmentorder-detailed
  /api/shopify/{integrationInstance}/inventory:
    get:
      tags:
      - Shopify
      summary: List Inventory Comparison
      description: 'Get paginated inventory comparison data showing SKU.io quantities
        vs Shopify quantities per product/location.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        example: '1'
        description: Page number (default 1).
      - name: per_page
        in: query
        schema:
          type: integer
        example: '10'
        description: Results per page (default 10).
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        product_listing_id:
                          type: integer
                        document_id:
                          type: integer
                        listing_sku:
                          type: string
                        title:
                          type: string
                        product:
                          type: object
                          properties:
                            id:
                              type: integer
                            sku:
                              type: string
                            name:
                              type: string
                        subscription_offering:
                          type: string
                          nullable: true
                        location_id:
                          type: string
                        location_name:
                          type: string
                        location_is_active:
                          type: boolean
                        sku_quantity:
                          type: integer
                        sales_channel_quantity:
                          type: integer
                        variance:
                          type: integer
                        status:
                          type: string
                        is_sku_recalculation_needed:
                          type: boolean
                        sku_quantity_updated_at:
                          type: string
                        sales_channel_quantity_updated_at:
                          type: string
                        sales_channel_quantity_synced_at:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 701
                    product_listing_id: 201
                    document_id: 1042
                    listing_sku: SHIRT-BLU-LG
                    title: Classic Blue Shirt - Large
                    product:
                      id: 301
                      sku: SHIRT-BLU-LG
                      name: Classic Blue Shirt - Large
                    subscription_offering: null
                    location_id: '12345678'
                    location_name: Main Warehouse
                    location_is_active: true
                    sku_quantity: 50
                    sales_channel_quantity: 50
                    variance: 0
                    status: synced
                    is_sku_recalculation_needed: false
                    sku_quantity_updated_at: '2024-03-20T12:00:00+00:00'
                    sales_channel_quantity_updated_at: '2024-03-20T11:55:00+00:00'
                    sales_channel_quantity_synced_at: '2024-03-20T11:55:00+00:00'
                    created_at: '2024-01-15T10:00:00+00:00'
                    updated_at: '2024-03-20T12:00:00+00:00'
                  current_page: 1
                  last_page: 12
                  per_page: 10
                  total: 120
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shopify-integrationinstance-inventory
  /api/shopify/{integrationInstance}/inventory/summary:
    get:
      tags:
      - Shopify
      summary: Get Inventory Summary
      description: 'Get inventory summary statistics: synced count, variance count,
        needs recalculation count.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      total:
                        type: integer
                      synced:
                        type: integer
                      variance:
                        type: integer
                      needs_recalculation:
                        type: integer
                example:
                  data:
                    total: 120
                    synced: 100
                    variance: 15
                    needs_recalculation: 5
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shopify-integrationinstance-inventory-summary
  /api/shopify/{integrationInstance}/inventory/locations:
    get:
      tags:
      - Shopify
      summary: Get Inventory Locations
      description: 'Get available Shopify locations for inventory filtering.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        legacy_resource_id:
                          type: string
                        is_active:
                          type: boolean
                example:
                  data:
                  - id: 1
                    name: Main Warehouse
                    legacy_resource_id: '12345678'
                    is_active: true
                  - id: 2
                    name: Secondary Location
                    legacy_resource_id: '23456789'
                    is_active: true
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shopify-integrationinstance-inventory-locations
  /api/shopify/{integrationInstance}/inventory/recache:
    post:
      tags:
      - Shopify
      summary: Trigger Inventory Recache
      description: 'Trigger a job to recache SKU.io inventory quantities. Returns
        tracked_job_log_id for progress polling.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                example:
                  message: Inventory recache job has been queued
                  data:
                    tracked_job_log_id: 4450
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-shopify-integrationinstance-inventory-recache
  /api/shopify/{integrationInstance}/inventory/recache-progress/{trackedJobLogId}:
    get:
      tags:
      - Shopify
      summary: Get Recache Progress
      description: 'Poll progress of an inventory recache job.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: trackedJobLogId
        in: path
        schema:
          type: integer
        required: true
        example: '4450'
        description: The tracked job log ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      status:
                        type: string
                      progress_current:
                        type: integer
                      progress_total:
                        type: integer
                example:
                  data:
                    id: 4450
                    status: completed
                    progress_current: 120
                    progress_total: 120
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shopify-integrationinstance-inventory-recache-progress-trackedjoblogid
  /api/shopify/{integrationInstance}/inventory/sync:
    post:
      tags:
      - Shopify
      summary: Trigger Inventory Sync
      description: 'Trigger a job to sync SKU.io inventory quantities to Shopify.
        Returns tracked_job_log_id.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                example:
                  message: Inventory sync job has been queued
                  data:
                    tracked_job_log_id: 4451
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-shopify-integrationinstance-inventory-sync
  /api/shopify/{integrationInstance}/inventory/sync-progress/{trackedJobLogId}:
    get:
      tags:
      - Shopify
      summary: Get Sync Progress
      description: 'Poll progress of an inventory sync job.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: trackedJobLogId
        in: path
        schema:
          type: integer
        required: true
        example: '4451'
        description: The tracked job log ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      status:
                        type: string
                      progress_current:
                        type: integer
                      progress_total:
                        type: integer
                example:
                  data:
                    id: 4451
                    status: processing
                    progress_current: 60
                    progress_total: 120
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shopify-integrationinstance-inventory-sync-progress-trackedjoblogid
  /api/shopify/{integrationInstance}/inventory/fetch-live:
    post:
      tags:
      - Shopify
      summary: Fetch Live Inventory
      description: 'Trigger a job to fetch live inventory quantities directly from
        Shopify. Returns tracked_job_log_id.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                example:
                  message: Fetch live inventory job has been queued
                  data:
                    tracked_job_log_id: 4452
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-shopify-integrationinstance-inventory-fetch-live
  /api/shopify/{integrationInstance}/inventory/fetch-live-progress/{trackedJobLogId}:
    get:
      tags:
      - Shopify
      summary: Get Fetch Live Progress
      description: 'Poll progress of a fetch-live-inventory job.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: trackedJobLogId
        in: path
        schema:
          type: integer
        required: true
        example: '4452'
        description: The tracked job log ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      status:
                        type: string
                      progress_current:
                        type: integer
                      progress_total:
                        type: integer
                example:
                  data:
                    id: 4452
                    status: completed
                    progress_current: 120
                    progress_total: 120
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shopify-integrationinstance-inventory-fetch-live-progress-trackedjoblogid
  /api/shopify/{integrationInstance}/webhook-events:
    get:
      tags:
      - Shopify
      summary: List Webhook Events
      description: 'List webhook events for an integration instance with pagination.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        example: '1'
        description: Page number (default 1).
      - name: per_page
        in: query
        schema:
          type: integer
        example: '10'
        description: Results per page (default 10).
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        topic:
                          type: string
                        unique_id:
                          type: string
                        processing_status:
                          type: string
                        processing_attempts:
                          type: integer
                        last_processing_attempt_at:
                          type: string
                        processing_error:
                          type: string
                          nullable: true
                        payload_date:
                          type: string
                        created_at:
                          type: string
                        processed_at:
                          type: string
                        processing_completed_at:
                          type: string
                        integration_instance:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                  current_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 9001
                    topic: orders/create
                    unique_id: shopify-webhook-abc123
                    processing_status: processed
                    processing_attempts: 1
                    last_processing_attempt_at: '2024-03-20T10:00:00+00:00'
                    processing_error: null
                    payload_date: '2024-03-20T09:59:00+00:00'
                    created_at: '2024-03-20T09:59:30+00:00'
                    processed_at: '2024-03-20T10:00:00+00:00'
                    processing_completed_at: '2024-03-20T10:00:02+00:00'
                    integration_instance:
                      id: 1
                      name: My Shopify Store
                  current_page: 1
                  per_page: 10
                  total: 250
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shopify-integrationinstance-webhook-events
  /api/shopify/webhook-events/{eventId}:
    get:
      tags:
      - Shopify
      summary: Get Webhook Event Details
      description: 'Get full details of a specific webhook event including the raw
        payload JSON.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: eventId
        in: path
        schema:
          type: integer
        required: true
        example: '9001'
        description: The event ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      topic:
                        type: string
                      unique_id:
                        type: string
                      processing_status:
                        type: string
                      processing_attempts:
                        type: integer
                      last_processing_attempt_at:
                        type: string
                      processing_started_at:
                        type: string
                      processing_completed_at:
                        type: string
                      processing_error:
                        type: string
                        nullable: true
                      payload_date:
                        type: string
                      created_at:
                        type: string
                      processed_at:
                        type: string
                      json_data:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                example:
                  success: true
                  data:
                    id: 9001
                    integration_instance_id: 1
                    topic: orders/create
                    unique_id: shopify-webhook-abc123
                    processing_status: processed
                    processing_attempts: 1
                    last_processing_attempt_at: '2024-03-20T10:00:00+00:00'
                    processing_started_at: '2024-03-20T09:59:55+00:00'
                    processing_completed_at: '2024-03-20T10:00:02+00:00'
                    processing_error: null
                    payload_date: '2024-03-20T09:59:00+00:00'
                    created_at: '2024-03-20T09:59:30+00:00'
                    processed_at: '2024-03-20T10:00:00+00:00'
                    json_data:
                      id: 5001234567890
                      name: '#1001'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shopify-webhook-events-eventid
  /api/shopify/{integrationInstance}/webhook-events/stats:
    get:
      tags:
      - Shopify
      summary: Get Processing Stats
      description: 'Get webhook event processing statistics: counts by status, failure
        rates, etc.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      total:
                        type: integer
                      pending:
                        type: integer
                      processed:
                        type: integer
                      failed:
                        type: integer
                      processing:
                        type: integer
                  integration_instance:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                example:
                  success: true
                  data:
                    total: 5000
                    pending: 12
                    processed: 4950
                    failed: 38
                    processing: 0
                  integration_instance:
                    id: 1
                    name: My Shopify Store
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shopify-integrationinstance-webhook-events-stats
  /api/shopify/{integrationInstance}/webhook-events/process:
    post:
      tags:
      - Shopify
      summary: Process Pending Events
      description: 'Manually trigger processing of pending webhook events for an integration
        instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Validation:

        - topic: nullable, string — in: full topic names (orders/create, products/update,
        etc.) or short prefixes (orders, products, inventory_items, order_transactions)

        - limit: nullable, integer, min:1, max:100'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                topic:
                  type: string
                limit:
                  type: integer
              example:
                topic: orders
                limit: 50
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      processed:
                        type: integer
                      failed:
                        type: integer
                      skipped:
                        type: integer
                  message:
                    type: string
                example:
                  success: true
                  data:
                    processed: 10
                    failed: 0
                    skipped: 2
                  message: Processing completed successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-shopify-integrationinstance-webhook-events-process
  /api/shopify/{integrationInstance}/webhook-events/retry-failed:
    post:
      tags:
      - Shopify
      summary: Retry Failed Events
      description: 'Retry failed webhook events for an integration instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Validation:

        - limit: nullable, integer, min:1, max:100'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                limit:
                  type: integer
              example:
                limit: 25
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      processed:
                        type: integer
                      failed:
                        type: integer
                      skipped:
                        type: integer
                  message:
                    type: string
                example:
                  success: true
                  data:
                    processed: 5
                    failed: 2
                    skipped: 0
                  message: Retry completed successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-shopify-integrationinstance-webhook-events-retry-failed
  /api/shopify/webhook-events/{eventId}/process:
    post:
      tags:
      - Shopify
      summary: Process Event by ID
      description: 'Process a specific pending webhook event by ID.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: eventId
        in: path
        schema:
          type: integer
        required: true
        example: '9001'
        description: The event ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      event_id:
                        type: integer
                      status:
                        type: string
                  message:
                    type: string
                example:
                  success: true
                  data:
                    event_id: 9001
                    status: processed
                  message: Event processing completed successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-shopify-webhook-events-eventid-process
  /api/shopify/webhook-events/{eventId}/reprocess:
    post:
      tags:
      - Shopify
      summary: Reprocess Event by ID
      description: 'Reprocess a webhook event including already-processed events (force
        retry).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: eventId
        in: path
        schema:
          type: integer
        required: true
        example: '9001'
        description: The event ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      event_id:
                        type: integer
                      status:
                        type: string
                  message:
                    type: string
                example:
                  success: true
                  data:
                    event_id: 9001
                    status: processed
                  message: Event reprocessing completed successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-shopify-webhook-events-eventid-reprocess
  /api/shopify/webhook-events/bulk-reprocess:
    post:
      tags:
      - Shopify
      summary: Bulk Reprocess Events
      description: 'Bulk reprocess multiple webhook events by IDs or by filter.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Validation:

        - event_ids: required_without apply_to_all, array of integers (must exist
        in shopify_webhook_events)

        - apply_to_all: nullable, boolean

        - filters: nullable, array

        - integration_instance_id: required_if apply_to_all=true, integer'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                event_ids:
                  type: array
                  items:
                    type: integer
              example:
                event_ids:
                - 9001
                - 9002
                - 9003
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      processed_count:
                        type: integer
                      failed_count:
                        type: integer
                  message:
                    type: string
                example:
                  success: true
                  data:
                    processed_count: 3
                    failed_count: 0
                  message: Bulk reprocessing completed successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-shopify-webhook-events-bulk-reprocess
  /api/shopify/webhook-events/bulk-delete:
    delete:
      tags:
      - Shopify
      summary: Bulk Delete Events
      description: 'Bulk delete webhook events by IDs or by filter. Requires confirmation=''YES''
        to proceed.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Validation:

        - event_ids: required_without apply_to_all, array of integers

        - apply_to_all: nullable, boolean

        - filters: nullable, array

        - integration_instance_id: required_if apply_to_all=true

        - confirmation: required, must be ''YES'''
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      deleted_count:
                        type: integer
                  message:
                    type: string
                example:
                  success: true
                  data:
                    deleted_count: 2
                  message: 2 webhook event(s) deleted successfully
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: delete-api-shopify-webhook-events-bulk-delete
  /api/shopify/{integrationInstance}/webhook-events/delete-all:
    delete:
      tags:
      - Shopify
      summary: Delete All Events for Integration
      description: 'Delete ALL webhook events for an integration instance. Requires
        confirmation=''YES''.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Validation:

        - confirmation: required, must be ''YES'''
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      deleted_count:
                        type: integer
                  message:
                    type: string
                example:
                  success: true
                  data:
                    deleted_count: 5000
                  message: 5000 webhook event(s) deleted successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-shopify-integrationinstance-webhook-events-delete-all
  /api/shopify/{integrationInstance}/pre-start-date-orders:
    get:
      tags:
      - Shopify
      summary: List Pre-Start-Date Orders
      description: 'Queries the Shopify Admin API live for orders created before the
        account''s inventory start date and returns them with an eligibility assessment
        for historical import (eligible, already imported, or the reason they cannot
        be imported). Orders imported this way are flagged as pre-start-date imports
        and do not affect inventory.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Note: this performs live Shopify API requests and can be slow for wide date
        ranges.


        Query parameters:

        - created_at_min (date, required): start of the window; must be before the
        inventory start date.

        - created_at_max (date, optional): end of the window; defaults to the day
        before the inventory start date; must be before the inventory start date and
        not before created_at_min.

        - fulfillment_status (string, optional): unfulfilled, partial, fulfilled,
        or any.


        Returns 422 if the inventory start date has not been set or the dates are
        out of range.'
      parameters:
      - name: created_at_min
        in: query
        schema:
          type: string
        description: Required. Earliest order creation date (must be before the inventory
          start date)
        example: '2023-10-01'
      - name: created_at_max
        in: query
        schema:
          type: string
        description: Latest order creation date (defaults to the day before the inventory
          start date)
        example: '2023-12-31'
      - name: fulfillment_status
        in: query
        schema:
          type: string
        description: unfulfilled, partial, fulfilled, or any
        example: any
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        shopify_order_id:
                          type: integer
                        name:
                          type: string
                        email:
                          type: string
                        created_at:
                          type: string
                        financial_status:
                          type: string
                        fulfillment_status:
                          type: string
                        total_price:
                          type: string
                        currency:
                          type: string
                        eligible:
                          type: boolean
                        already_imported:
                          type: boolean
                        ineligible_reason:
                          type: string
                          nullable: true
                  inventory_start_date:
                    type: string
                  meta:
                    type: object
                    properties:
                      total_queried:
                        type: integer
                      eligible_count:
                        type: integer
                      already_imported_count:
                        type: integer
                example:
                  data:
                  - shopify_order_id: 6000012345
                    name: '#985'
                    email: sam@example.com
                    created_at: '2023-11-02T15:04:05Z'
                    financial_status: paid
                    fulfillment_status: fulfilled
                    total_price: '120.00'
                    currency: USD
                    eligible: true
                    already_imported: false
                    ineligible_reason: null
                  inventory_start_date: '2024-01-01'
                  meta:
                    total_queried: 40
                    eligible_count: 32
                    already_imported_count: 3
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      created_at_min:
                        type: array
                        items:
                          type: string
                example:
                  message: Created at min must be before the inventory start date.
                  errors:
                    created_at_min:
                    - Created at min must be before the inventory start date.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shopify-integrationinstance-pre-start-date-orders
  /api/shopify/{integrationInstance}/pre-start-date-orders/search:
    get:
      tags:
      - Shopify
      summary: Search Pre-Start-Date Orders
      description: 'Searches the Shopify Admin API live for specific orders created
        before the inventory start date, by order number, Shopify order ID, or customer
        email. Returns the same shape and eligibility flags as List Pre-Start-Date
        Orders.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Query parameters:

        - search_by (string, required): order_number, order_id, or email.

        - search_term (string, required, max 255).


        Returns 422 if the inventory start date has not been set.'
      parameters:
      - name: search_by
        in: query
        schema:
          type: string
        description: Required. order_number, order_id, or email
        example: order_number
      - name: search_term
        in: query
        schema:
          type: integer
        description: Required. Value to search for
        example: '985'
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        shopify_order_id:
                          type: integer
                        name:
                          type: string
                        email:
                          type: string
                        created_at:
                          type: string
                        financial_status:
                          type: string
                        fulfillment_status:
                          type: string
                        total_price:
                          type: string
                        currency:
                          type: string
                        eligible:
                          type: boolean
                        already_imported:
                          type: boolean
                        ineligible_reason:
                          type: string
                          nullable: true
                  inventory_start_date:
                    type: string
                  meta:
                    type: object
                    properties:
                      total_queried:
                        type: integer
                      eligible_count:
                        type: integer
                      already_imported_count:
                        type: integer
                example:
                  data:
                  - shopify_order_id: 6000012345
                    name: '#985'
                    email: sam@example.com
                    created_at: '2023-11-02T15:04:05Z'
                    financial_status: paid
                    fulfillment_status: fulfilled
                    total_price: '120.00'
                    currency: USD
                    eligible: true
                    already_imported: false
                    ineligible_reason: null
                  inventory_start_date: '2024-01-01'
                  meta:
                    total_queried: 1
                    eligible_count: 1
                    already_imported_count: 0
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shopify-integrationinstance-pre-start-date-orders-search
  /api/shopify/{integrationInstance}/pre-start-date-orders/import:
    post:
      tags:
      - Shopify
      summary: Import Pre-Start-Date Orders
      description: 'Imports selected pre-start-date orders from Shopify. Each order
        is fetched from Shopify individually, so the import runs asynchronously: this
        endpoint enqueues the work and immediately returns a tracked job id. Poll
        the tracked jobs API with that id to follow progress and read the final imported/skipped
        counts. Full order data is downloaded and stored flagged as a pre-start-date
        import so it stays out of inventory calculations. Orders that already exist
        locally are flagged instead of being re-imported.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Body fields:

        - shopify_order_ids (array of integers, required, 1-10000): Shopify order
        IDs as returned by the list/search endpoints.


        Returns the tracked job id. Returns 422 when the inventory start date is not
        set or more than 10,000 orders are requested.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                shopify_order_ids:
                  type: array
                  items:
                    type: integer
              example:
                shopify_order_ids:
                - 6000012345
                - 6000012346
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 4821
                  message: Importing 2 pre-start-date orders.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      shopify_order_ids:
                        type: array
                        items:
                          type: string
                example:
                  message: A maximum of 10,000 orders can be imported at once.
                  errors:
                    shopify_order_ids:
                    - A maximum of 10,000 orders can be imported at once.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-shopify-integrationinstance-pre-start-date-orders-import
  /api/shopify/{integrationInstance}/pre-start-date-orders/search-all:
    post:
      tags:
      - Shopify
      summary: Search All Pre-Start-Date Orders (Async)
      description: 'Start a background search for every order created before the inventory
        start date. Unlike the synchronous browse endpoint, this fetches ALL matching
        orders with no page cap and returns a tracked job id immediately. Poll the
        tracked jobs API with that id; when it completes, read the full result set
        from the results endpoint.


        Authentication: Requires Bearer token.


        Body fields:

        - created_at_min (date, required): only orders created on or after this date
        are searched. Must be before the inventory start date.

        - created_at_max (date, optional): upper bound; defaults to the inventory
        start date.

        - fulfillment_status (string, optional): any | unfulfilled | partial | fulfilled.
        Defaults to any.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                created_at_min:
                  type: string
                created_at_max:
                  type: string
                fulfillment_status:
                  type: string
              example:
                created_at_min: '2024-10-01'
                created_at_max: '2024-12-31'
                fulfillment_status: any
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 4821
                  message: Searching Shopify for pre-start-date orders.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-shopify-integrationinstance-pre-start-date-orders-search-all
  /api/shopify/{integrationInstance}/pre-start-date-orders/results/{trackedJobLogId}:
    get:
      tags:
      - Shopify
      summary: Get Pre-Start-Date Order Search Results
      description: 'Return the cached result set produced by a completed Search All
        job. By default the full set is returned in one response; pass page and per_page
        for server-side pagination. Results are cached for one hour after the search
        completes.


        Authentication: Requires Bearer token.


        Path params:

        - trackedJobLogId (integer): the tracked job id returned by Search All.


        Query params:

        - eligible_only (0/1, optional): return only orders eligible for import.

        - page (integer, optional): page number; when omitted the full set is returned.

        - per_page (integer, optional, max 1000): items per page when page is set.


        Returns 404 when the cached results have expired.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: trackedJobLogId
        in: path
        schema:
          type: integer
        required: true
        example: '4821'
        description: The tracked job log ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        shopify_order_id:
                          type: integer
                        name:
                          type: string
                        email:
                          type: string
                        created_at:
                          type: string
                        fulfillment_status:
                          type: string
                        financial_status:
                          type: string
                        total_price:
                          type: string
                        currency:
                          type: string
                        fulfillments:
                          type: array
                        line_items:
                          type: array
                          items:
                            type: object
                            properties:
                              title:
                                type: string
                              sku:
                                type: string
                              quantity:
                                type: integer
                              current_quantity:
                                type: integer
                              price:
                                type: string
                              variant_title:
                                type: string
                                nullable: true
                        eligible:
                          type: boolean
                        eligibility_reason:
                          type: string
                          nullable: true
                        already_imported:
                          type: boolean
                  inventory_start_date:
                    type: string
                  meta:
                    type: object
                    properties:
                      total_queried:
                        type: integer
                      eligible_count:
                        type: integer
                      already_imported_count:
                        type: integer
                      has_more:
                        type: boolean
                example:
                  data:
                  - shopify_order_id: 6000012345
                    name: '#1001'
                    email: customer@example.com
                    created_at: '2024-11-01T10:00:00Z'
                    fulfillment_status: UNFULFILLED
                    financial_status: PAID
                    total_price: '99.99'
                    currency: USD
                    fulfillments: []
                    line_items:
                    - title: Widget
                      sku: WID-1
                      quantity: 2
                      current_quantity: 2
                      price: '49.99'
                      variant_title: null
                    eligible: true
                    eligibility_reason: null
                    already_imported: false
                  inventory_start_date: '2025-01-01'
                  meta:
                    total_queried: 9197
                    eligible_count: 9176
                    already_imported_count: 21
                    has_more: false
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: Search results are no longer available. Please run the search
                    again.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-shopify-integrationinstance-pre-start-date-orders-results-trackedjoblogid
  /api/shopify/{integrationInstance}/products:
    get:
      tags:
      - Shopify
      summary: List Products
      description: 'List Shopify products for an integration instance with advanced
        filtering, sorting, and pagination.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Filter System: Uses Spatie QueryBuilder with both simple (filter[field]) and
        advanced (filter[field.operator]) forms.


        Default: returns non-archived products sorted by -id.


        Sort fields: id, sku, barcode, shopify_product_id, shopify_product_title,
        shopify_variant_title, shopify_variant_id, price, status, shopify_product_created_at,
        shopify_product_updated_at, shopify_variant_created_at, shopify_variant_updated_at'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        description: 'Page number (default: 1)'
        example: '1'
      - name: per_page
        in: query
        schema:
          type: integer
        description: 'Items per page (default: 10)'
        example: '10'
      - name: sort
        in: query
        schema:
          type: string
        description: 'Sort field. Prefix with - for descending. Allowed: id, sku,
          barcode, shopify_product_id, shopify_product_title, shopify_variant_title,
          shopify_variant_id, price, status, shopify_product_created_at, shopify_product_updated_at,
          shopify_variant_created_at, shopify_variant_updated_at'
        example: -id
      - name: filter[search]
        in: query
        schema:
          type: string
        description: Full-text search across sku, barcode, shopify_product_title,
          shopify_variant_title, shopify_variant_id, shopify_product_id, inventory_item_id
        example: shirt
      - name: filter[mapped]
        in: query
        schema:
          type: boolean
        description: 'Filter by mapping status: true = mapped, false = unmapped'
        example: 'true'
      - name: filter[archived]
        in: query
        schema:
          type: boolean
        description: 'Filter archived products: true = archived, false = active (default:
          false)'
        example: 'false'
      - name: filter[status]
        in: query
        schema:
          type: string
        description: 'Filter by Shopify product status: active, draft, archived, all'
        example: active
      - name: filter[vendor]
        in: query
        schema:
          type: string
        description: Partial match filter on vendor
        example: Nike
      - name: filter[product_type]
        in: query
        schema:
          type: string
        description: Partial match filter on product_type
        example: apparel
      - name: filter[sku]
        in: query
        schema:
          type: string
        description: Partial match filter on SKU
        example: SKU-001
      - name: filter[barcode]
        in: query
        schema:
          type: integer
        description: Partial match filter on barcode
        example: '1234567890'
      - name: filter[price.gte]
        in: query
        schema:
          type: integer
        description: 'Numeric filter on price. Suffixes: .gte, .lte, .gt, .lt'
        example: '10'
      - name: filter[date_from]
        in: query
        schema:
          type: string
        description: 'Filter: shopify_variant_created_at >= this date'
        example: '2024-01-01'
      - name: filter[date_to]
        in: query
        schema:
          type: string
        description: 'Filter: shopify_variant_created_at <= this date 23:59:59'
        example: '2024-12-31'
      - name: filter[mapping_status]
        in: query
        schema:
          type: string
        description: 'Legacy: mapped or unmapped'
        example: unmapped
      - name: filter[sku_status]
        in: query
        schema:
          type: string
        description: 'Legacy: has_sku or empty_sku'
        example: has_sku
      - name: filter[has_sku]
        in: query
        schema:
          type: boolean
        description: Filter products that have (true) or lack (false) a SKU value
        example: 'true'
      - name: filter[vendor.contains]
        in: query
        schema:
          type: string
        description: 'Advanced text filter on vendor. Operators: .is, .is_not, .contains,
          .does_not_contain, .starts_with, .ends_with, .is_empty, .is_not_empty, .is_one_of'
        example: sport
      - name: filter[sku_product.is]
        in: query
        schema:
          type: string
        description: Filter by linked SKU product SKU code
        example: ABC-001
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        shopify_parent_product_id:
                          type: integer
                        shopify_variant_id:
                          type: integer
                        shopify_product_id:
                          type: integer
                        inventory_item_id:
                          type: integer
                        sku:
                          type: string
                        shopify_product_title:
                          type: string
                        shopify_variant_title:
                          type: string
                        shopify_product_unified_title:
                          type: string
                        barcode:
                          type: string
                        price:
                          type: string
                        status:
                          type: string
                        product_type:
                          type: string
                        vendor:
                          type: string
                        image_url:
                          type: string
                        weight:
                          type: number
                        weight_unit:
                          type: string
                        unit_cost:
                          type: string
                        unit_cost_currency:
                          type: string
                        shopify_product_created_at:
                          type: string
                        shopify_product_updated_at:
                          type: string
                        shopify_variant_created_at:
                          type: string
                        shopify_variant_updated_at:
                          type: string
                        shopify_inventory_item_created_at:
                          type: string
                        shopify_inventory_item_updated_at:
                          type: string
                        archived_at:
                          type: string
                          nullable: true
                        removed_from_shopify:
                          type: boolean
                        sync_source:
                          type: string
                        last_sync_source:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                        sku_product:
                          type: object
                          properties:
                            id:
                              type: integer
                            sku:
                              type: string
                            name:
                              type: string
                            barcode:
                              type: string
                            price:
                              type: string
                            type:
                              type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - id: 1042
                    shopify_parent_product_id: 8123456789
                    shopify_variant_id: 45678901234
                    shopify_product_id: 8123456789
                    inventory_item_id: 98765432
                    sku: SHIRT-BLU-LG
                    shopify_product_title: Classic Blue Shirt
                    shopify_variant_title: Large
                    shopify_product_unified_title: Classic Blue Shirt - Large
                    barcode: 0123456789012
                    price: '29.99'
                    status: active
                    product_type: Apparel
                    vendor: Acme Clothing
                    image_url: https://cdn.shopify.com/s/files/1/0001/product.jpg
                    weight: 0.5
                    weight_unit: kg
                    unit_cost: '12.50'
                    unit_cost_currency: USD
                    shopify_product_created_at: '2024-01-15T10:00:00+00:00'
                    shopify_product_updated_at: '2024-03-20T14:30:00+00:00'
                    shopify_variant_created_at: '2024-01-15T10:00:00+00:00'
                    shopify_variant_updated_at: '2024-03-20T14:30:00+00:00'
                    shopify_inventory_item_created_at: '2024-01-15T10:00:00+00:00'
                    shopify_inventory_item_updated_at: '2024-03-20T14:30:00+00:00'
                    archived_at: null
                    removed_from_shopify: false
                    sync_source: webhook
                    last_sync_source: webhook
                    created_at: '2024-01-15T10:00:00+00:00'
                    updated_at: '2024-03-20T14:30:00+00:00'
                    sku_product:
                      id: 301
                      sku: SHIRT-BLU-LG
                      name: Classic Blue Shirt - Large
                      barcode: 0123456789012
                      price: '29.99'
                      type: product
                  current_page: 1
                  last_page: 5
                  per_page: 10
                  total: 48
                  from: 1
                  to: 10
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shopify-integrationinstance-products
  /api/shopify/{integrationInstance}/products/latest-sync-info:
    get:
      tags:
      - Shopify
      summary: Get Latest Sync Info
      description: 'Get aggregate stats about product sync status for an integration
        instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Returns total product count, mapped/unmapped counts, last sync timestamp,
        and latest product info.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      latest_product_title:
                        type: string
                      latest_product_date:
                        type: string
                      total_products:
                        type: integer
                      mapped_products:
                        type: integer
                      unmapped_products:
                        type: integer
                      last_synced_at:
                        type: string
                example:
                  data:
                    latest_product_title: Classic Blue Shirt - Large
                    latest_product_date: '2024-03-20T14:30:00.000000Z'
                    total_products: 1250
                    mapped_products: 1100
                    unmapped_products: 150
                    last_synced_at: '2024-03-20 14:30:00'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shopify-integrationinstance-products-latest-sync-info
  /api/shopify/{integrationInstance}/products/{product}:
    get:
      tags:
      - Shopify
      summary: Get Product
      description: 'Returns a synced Shopify product variant by its SKU.io row ID,
        including the mapped SKU.io product (if linked), the Shopify inventory item
        with per-location inventory levels, and SKU.io''s cached quantities per Shopify
        location.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: product
        in: path
        schema:
          type: integer
        required: true
        example: '101'
        description: The product ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      shopify_product_id:
                        type: string
                      shopify_parent_product_id:
                        type: integer
                      shopify_variant_id:
                        type: string
                      inventory_item_id:
                        type: string
                      sku:
                        type: string
                      shopify_product_title:
                        type: string
                      shopify_variant_title:
                        type: string
                      shopify_product_unified_title:
                        type: string
                      barcode:
                        type: string
                      price:
                        type: string
                      status:
                        type: string
                      product_type:
                        type: string
                      vendor:
                        type: string
                      image_url:
                        type: string
                      weight:
                        type: number
                      weight_unit:
                        type: string
                      unit_cost:
                        type: string
                      unit_cost_currency:
                        type: string
                      product_listing_id:
                        type: integer
                      mapped_sku:
                        type: string
                      mapped_at:
                        type: string
                      product:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          sku:
                            type: string
                          listing_id:
                            type: integer
                          default_financial_line_type_id:
                            type: integer
                          default_financial_line_type:
                            type: object
                            properties:
                              id:
                                type: integer
                              name:
                                type: string
                              classification:
                                type: string
                      subscription_offering:
                        type: string
                        nullable: true
                      inventory_item:
                        type: object
                        properties:
                          id:
                            type: integer
                          inventory_item_id:
                            type: string
                          weight_value:
                            type: number
                          weight_unit:
                            type: string
                          unit_cost_amount:
                            type: string
                          unit_cost_currency_code:
                            type: string
                          shopify_created_at:
                            type: string
                          shopify_updated_at:
                            type: string
                          inventory_levels:
                            type: array
                            items:
                              type: object
                              properties:
                                id:
                                  type: integer
                                inventory_item_id:
                                  type: string
                                location_id:
                                  type: string
                                location_name:
                                  type: string
                                location_is_active:
                                  type: boolean
                      inventory_caches:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            sales_channel_location_id:
                              type: string
                            location_name:
                              type: string
                            location_is_active:
                              type: boolean
                            sku_quantity:
                              type: integer
                            is_sku_recalculation_needed:
                              type: boolean
                      archived_at:
                        type: string
                        nullable: true
                      removed_from_shopify:
                        type: boolean
                      sync_source:
                        type: string
                      last_sync_source:
                        type: string
                      shopify_product_created_at:
                        type: string
                      shopify_product_updated_at:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 101
                    integration_instance_id: 1
                    shopify_product_id: '8500001111'
                    shopify_parent_product_id: 55
                    shopify_variant_id: '45123456789'
                    inventory_item_id: '48111222333'
                    sku: TSHIRT-M-BLUE
                    shopify_product_title: Blue T-Shirt
                    shopify_variant_title: M
                    shopify_product_unified_title: Blue T-Shirt - M
                    barcode: 0123456789012
                    price: '24.95'
                    status: active
                    product_type: Apparel
                    vendor: Acme Apparel
                    image_url: https://cdn.shopify.com/s/files/1/0001/products/blue-tshirt.jpg
                    weight: 0.2
                    weight_unit: kg
                    unit_cost: '8.50'
                    unit_cost_currency: USD
                    product_listing_id: 501
                    mapped_sku: TSHIRT-M-BLUE
                    mapped_at: '2025-04-01T10:00:00.000000Z'
                    product:
                      id: 301
                      name: Blue T-Shirt (M)
                      sku: TSHIRT-M-BLUE
                      listing_id: 501
                      default_financial_line_type_id: 2
                      default_financial_line_type:
                        id: 2
                        name: Product Sales
                        classification: revenue
                    subscription_offering: null
                    inventory_item:
                      id: 61
                      inventory_item_id: '48111222333'
                      weight_value: 0.2
                      weight_unit: kg
                      unit_cost_amount: '8.50'
                      unit_cost_currency_code: USD
                      shopify_created_at: '2024-02-01T09:00:00+00:00'
                      shopify_updated_at: '2025-06-01T10:00:00+00:00'
                      inventory_levels:
                      - id: 71
                        inventory_item_id: '48111222333'
                        location_id: '74469278'
                        location_name: Main Warehouse
                        location_is_active: true
                    inventory_caches:
                    - id: 81
                      sales_channel_location_id: '74469278'
                      location_name: Main Warehouse
                      location_is_active: true
                      sku_quantity: 42
                      is_sku_recalculation_needed: false
                    archived_at: null
                    removed_from_shopify: false
                    sync_source: webhook
                    last_sync_source: webhook
                    shopify_product_created_at: '2024-02-01T09:00:00+00:00'
                    shopify_product_updated_at: '2025-06-01T10:00:00+00:00'
                    created_at: '2024-02-01T09:05:00+00:00'
                    updated_at: '2025-06-01T10:02:00+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shopify-integrationinstance-products-product
  /api/shopify/{integrationInstance}/products/{product}/smart-match:
    post:
      tags:
      - Shopify
      summary: Smart Match
      description: 'Find matching SKU products for a Shopify product using SKU, barcode,
        and fuzzy matching.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Returns exact_match (by SKU), barcode_match, and up to 5 similar_matches (fuzzy).


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: product
        in: path
        schema:
          type: integer
        required: true
        example: '1042'
        description: The product ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      exact_match:
                        type: object
                        properties:
                          id:
                            type: integer
                          sku:
                            type: string
                          name:
                            type: string
                          barcode:
                            type: string
                          price:
                            type: string
                          type:
                            type: string
                          match_type:
                            type: string
                      barcode_match:
                        type: string
                        nullable: true
                      similar_matches:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            sku:
                              type: string
                            name:
                              type: string
                            barcode:
                              type: string
                            price:
                              type: string
                            type:
                              type: string
                            match_type:
                              type: string
                example:
                  data:
                    exact_match:
                      id: 301
                      sku: SHIRT-BLU-LG
                      name: Classic Blue Shirt - Large
                      barcode: 0123456789012
                      price: '29.99'
                      type: product
                      match_type: sku
                    barcode_match: null
                    similar_matches:
                    - id: 305
                      sku: SHIRT-BLU-MD
                      name: Classic Blue Shirt - Medium
                      barcode: 0123456789013
                      price: '29.99'
                      type: product
                      match_type: fuzzy
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-shopify-integrationinstance-products-product-smart-match
  /api/shopify/{integrationInstance}/products/{product}/map:
    post:
      tags:
      - Shopify
      summary: Map Product
      description: 'Map a Shopify product variant to a SKU product (or subscription
        offering).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        If the product is already mapped, updates the existing mapping (remap). Dispatches
        a job to map any unresolved sales order lines matching this listing.


        Authentication: Requires Bearer token.


        Validation:

        - product_id: required_without subscription_offering_id, integer, must exist
        in products

        - subscription_offering_id: required_without product_id, integer, must exist
        in subscription_offerings'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                product_id:
                  type: integer
              example:
                product_id: 301
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: product
        in: path
        schema:
          type: integer
        required: true
        example: '1042'
        description: The product ID.
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      sku:
                        type: string
                      shopify_product_unified_title:
                        type: string
                      sku_product:
                        type: object
                        properties:
                          id:
                            type: integer
                          sku:
                            type: string
                          name:
                            type: string
                          barcode:
                            type: string
                          price:
                            type: string
                          type:
                            type: string
                  message:
                    type: string
                example:
                  data:
                    id: 1042
                    sku: SHIRT-BLU-LG
                    shopify_product_unified_title: Classic Blue Shirt - Large
                    sku_product:
                      id: 301
                      sku: SHIRT-BLU-LG
                      name: Classic Blue Shirt - Large
                      barcode: 0123456789012
                      price: '29.99'
                      type: product
                  message: Product mapped successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-shopify-integrationinstance-products-product-map
    delete:
      tags:
      - Shopify
      summary: Unmap Product
      description: 'Remove the mapping between a Shopify product and its SKU product.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Deletes the product listing record. Returns 422 if the product is not currently
        mapped.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: product
        in: path
        schema:
          type: integer
        required: true
        example: '1042'
        description: The product ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      sku:
                        type: string
                      sku_product:
                        type: string
                        nullable: true
                  message:
                    type: string
                example:
                  data:
                    id: 1042
                    sku: SHIRT-BLU-LG
                    sku_product: null
                  message: Product unmapped successfully.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: Product is not mapped.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-shopify-integrationinstance-products-product-map
  /api/shopify/{integrationInstance}/products/{product}/create-sku-product:
    post:
      tags:
      - Shopify
      summary: Create SKU Product
      description: 'Create a new SKU product from a Shopify product and map it. If
        a SKU product with the same SKU already exists, links to it instead.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Returns 422 if the product is already mapped.


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: product
        in: path
        schema:
          type: integer
        required: true
        example: '1042'
        description: The product ID.
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      sku:
                        type: string
                      sku_product:
                        type: object
                        properties:
                          id:
                            type: integer
                          sku:
                            type: string
                          name:
                            type: string
                  linked_existing:
                    type: boolean
                  message:
                    type: string
                example:
                  data:
                    id: 1042
                    sku: SHIRT-BLU-LG
                    sku_product:
                      id: 310
                      sku: SHIRT-BLU-LG
                      name: Classic Blue Shirt - Large
                  linked_existing: false
                  message: SKU product created and mapped successfully.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: Product is already mapped. Unmap it first.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-shopify-integrationinstance-products-product-create-sku-product
  /api/shopify/{integrationInstance}/products/{product}/archive:
    post:
      tags:
      - Shopify
      summary: Archive Single Product
      description: 'Archive a single Shopify product (sets archived_at timestamp).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: product
        in: path
        schema:
          type: integer
        required: true
        example: '1042'
        description: The product ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      archived_at:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 1042
                    archived_at: '2024-03-20T14:30:00+00:00'
                  message: Product archived successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-shopify-integrationinstance-products-product-archive
  /api/shopify/{integrationInstance}/products/{product}/unarchive:
    post:
      tags:
      - Shopify
      summary: Unarchive Single Product
      description: 'Unarchive a single Shopify product (clears archived_at timestamp).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: product
        in: path
        schema:
          type: integer
        required: true
        example: '1042'
        description: The product ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      archived_at:
                        type: string
                        nullable: true
                  message:
                    type: string
                example:
                  data:
                    id: 1042
                    archived_at: null
                  message: Product unarchived successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-shopify-integrationinstance-products-product-unarchive
  /api/shopify/{integrationInstance}/products/{product}/raw:
    get:
      tags:
      - Shopify
      summary: Get Raw Product from Shopify
      description: 'Fetch the raw Shopify REST API response for a product. Used for
        debugging and transparency.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        The data is not persisted — it reflects the live Shopify state.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: product
        in: path
        schema:
          type: integer
        required: true
        example: '1042'
        description: The product ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      title:
                        type: string
                      status:
                        type: string
                      vendor:
                        type: string
                      product_type:
                        type: string
                      variants:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            title:
                              type: string
                            sku:
                              type: string
                            price:
                              type: string
                            barcode:
                              type: string
                            inventory_item_id:
                              type: integer
                example:
                  data:
                    id: 8123456789
                    title: Classic Blue Shirt
                    status: active
                    vendor: Acme Clothing
                    product_type: Apparel
                    variants:
                    - id: 45678901234
                      title: Large
                      sku: SHIRT-BLU-LG
                      price: '29.99'
                      barcode: 0123456789012
                      inventory_item_id: 98765432
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shopify-integrationinstance-products-product-raw
  /api/shopify/{integrationInstance}/products/{product}/raw-graphql:
    get:
      tags:
      - Shopify
      summary: Get Raw Product (GraphQL)
      description: 'Fetch product data from the Shopify GraphQL API (the same query
        used for product sync), including variants, inventory items and inventory
        levels. The data is not persisted — it reflects the live Shopify state.


        If Shopify can''t return the product — deleted, or the app is missing the
        required access scope — the response includes an `unavailable_reason` string
        and the product node is null.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: product
        in: path
        schema:
          type: integer
        required: true
        example: '1042'
        description: The product ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 OK
                  value:
                    data:
                      product:
                        legacyResourceId: '8123456789'
                        title: Classic Blue Shirt
                        status: ACTIVE
                        productType: Apparel
                        vendor: Acme Clothing
                        variants:
                          edges:
                          - node:
                              legacyResourceId: '45678901234'
                              title: Large
                              sku: SHIRT-BLU-LG
                              barcode: 0123456789012
                              price: '29.99'
                              image:
                                url: https://cdn.shopify.com/s/files/1/products/blue-shirt-lg.jpg
                    extensions:
                      cost:
                        requestedQueryCost: 12
                        actualQueryCost: 8
                    errors: null
                example-1:
                  summary: 200 OK (product unavailable)
                  value:
                    data:
                      product: null
                    extensions: {}
                    errors: []
                    unavailable_reason: Shopify returned no data for this product.
                      It may have been deleted on Shopify, or the app is missing the
                      access scope required to read it.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shopify-integrationinstance-products-product-raw-graphql
  /api/shopify/{integrationInstance}/products/{product}/orders:
    get:
      tags:
      - Shopify
      summary: Get Orders for Product
      description: 'Get paginated Shopify orders that contain this product variant
        (matched by variant_id).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Used for lazy loading order history in the product detail view.


        Authentication: Requires Bearer token.'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        description: Page number
        example: '1'
      - name: per_page
        in: query
        schema:
          type: integer
        description: 'Items per page (default: 10)'
        example: '10'
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: product
        in: path
        schema:
          type: integer
        required: true
        example: '1042'
        description: The product ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        financial_status:
                          type: string
                        fulfillment_status:
                          type: string
                        total_price:
                          type: string
                        currency:
                          type: string
                        shopify_created_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - id: 501
                    name: '#1001'
                    financial_status: paid
                    fulfillment_status: fulfilled
                    total_price: '89.97'
                    currency: USD
                    shopify_created_at: '2024-03-01T09:00:00+00:00'
                  current_page: 1
                  last_page: 3
                  per_page: 10
                  total: 25
                  from: 1
                  to: 10
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shopify-integrationinstance-products-product-orders
  /api/shopify/{integrationInstance}/products/search-shopify:
    post:
      tags:
      - Shopify
      summary: Search Shopify Products
      description: 'Search for products directly in the Shopify store via GraphQL
        API.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Search by SKU, title, or product_id. Returns results including whether each
        product already exists in the local database.


        Authentication: Requires Bearer token.


        Validation:

        - search_by: required, in: sku, title, product_id

        - query: required, string, max:255'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                search_by:
                  type: string
                query:
                  type: string
              example:
                search_by: sku
                query: SHIRT-BLU
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        legacy_resource_id:
                          type: string
                        product_id:
                          type: string
                        title:
                          type: string
                        sku:
                          type: string
                        barcode:
                          type: string
                        price:
                          type: string
                        status:
                          type: string
                        product_type:
                          type: string
                        vendor:
                          type: string
                        shopify_created_at:
                          type: string
                        shopify_updated_at:
                          type: string
                        exists_in_database:
                          type: boolean
                        database_id:
                          type: integer
                example:
                  data:
                  - legacy_resource_id: '45678901234'
                    product_id: '8123456789'
                    title: Classic Blue Shirt - Large
                    sku: SHIRT-BLU-LG
                    barcode: 0123456789012
                    price: '29.99'
                    status: ACTIVE
                    product_type: Apparel
                    vendor: Acme Clothing
                    shopify_created_at: '2024-01-15T10:00:00Z'
                    shopify_updated_at: '2024-03-20T14:30:00Z'
                    exists_in_database: true
                    database_id: 1042
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-shopify-integrationinstance-products-search-shopify
  /api/shopify/{integrationInstance}/products/refresh-product:
    post:
      tags:
      - Shopify
      summary: Refresh Single Product from Shopify
      description: 'Fetch and sync a single Shopify product (all variants) from Shopify
        by its parent product ID.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        The product_id is the Shopify parent product legacyResourceId. The optional
        variant_id narrows the returned result to a specific variant.


        Authentication: Requires Bearer token.


        Validation:

        - product_id: required, string (Shopify legacy resource ID)

        - variant_id: nullable, string (Shopify variant legacy resource ID)'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                product_id:
                  type: string
                variant_id:
                  type: string
              example:
                product_id: '8123456789'
                variant_id: '45678901234'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      sku:
                        type: string
                      shopify_product_unified_title:
                        type: string
                      status:
                        type: string
                      price:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 1042
                    sku: SHIRT-BLU-LG
                    shopify_product_unified_title: Classic Blue Shirt - Large
                    status: active
                    price: '29.99'
                  message: Product synced successfully.
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: Product not found in Shopify
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-shopify-integrationinstance-products-refresh-product
  /api/shopify/{integrationInstance}/products/refresh-tracked:
    post:
      tags:
      - Shopify
      summary: Refresh Products (Tracked)
      description: 'Start a tracked product refresh job from Shopify. Returns a tracked_job_log_id
        to poll for progress.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Validation:

        - days: nullable, integer, min:1, max:365 — fetch products updated in last
        N days

        - updated_at: nullable, date — fetch products updated since this date'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                days:
                  type: integer
                updated_at:
                  type: string
                  nullable: true
              example:
                days: 7
                updated_at: null
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 4421
                  message: Product refresh job has been queued
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-shopify-integrationinstance-products-refresh-tracked
  /api/shopify/{integrationInstance}/products/refresh-progress/{trackedJobLogId}:
    get:
      tags:
      - Shopify
      summary: Get Refresh Progress
      description: 'Poll the progress of a tracked product refresh job.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: trackedJobLogId
        in: path
        schema:
          type: integer
        required: true
        example: '4421'
        description: The tracked job log ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      job_name:
                        type: string
                      status:
                        type: string
                      progress_current:
                        type: integer
                      progress_total:
                        type: integer
                      started_at:
                        type: string
                      completed_at:
                        type: string
                        nullable: true
                example:
                  data:
                    id: 4421
                    job_name: 'Refresh Shopify Products: My Store'
                    status: processing
                    progress_current: 150
                    progress_total: 500
                    started_at: '2024-03-20T14:00:00+00:00'
                    completed_at: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shopify-integrationinstance-products-refresh-progress-trackedjoblogid
  /api/shopify/{integrationInstance}/products/refresh-sync:
    post:
      tags:
      - Shopify
      summary: Refresh from Shopify (Enhanced)
      description: 'Enhanced product refresh from Shopify with mode control. Dispatches
        a background job.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Validation:

        - mode: sometimes, in: incremental, full, date_range

        - date_type: required_if mode=date_range, in: updated_at, created_at

        - date_from: required_if mode=date_range, date

        - date_to: required_if mode=date_range, date

        - include_archived: sometimes, boolean

        - product_ids: sometimes, array of Shopify product IDs'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                mode:
                  type: string
                date_type:
                  type: string
                  nullable: true
                date_from:
                  type: string
                  nullable: true
                date_to:
                  type: string
                  nullable: true
                include_archived:
                  type: boolean
                product_ids:
                  type: array
              example:
                mode: incremental
                date_type: null
                date_from: null
                date_to: null
                include_archived: false
                product_ids: []
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Product refresh initiated. Products will be synced shortly.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-shopify-integrationinstance-products-refresh-sync
  /api/shopify/{integrationInstance}/products/refresh:
    post:
      tags:
      - Shopify
      summary: Refresh Products
      description: 'Queues a background download of the product catalog from Shopify.
        The endpoint returns immediately with no payload; products are refreshed asynchronously.
        For a refresh with progress polling, use Refresh Products (Tracked) instead.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties: {}
                example: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-shopify-integrationinstance-products-refresh
  /api/shopify/{integrationInstance}/products/sync-inventory:
    post:
      tags:
      - Shopify
      summary: Sync Inventory to Shopify
      description: 'Pushes SKU.io inventory levels to Shopify for mapped products.
        With no body, all mapped listings on the instance are synced; pass ids to
        limit the push to specific products.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Body fields:

        - ids (array of integers, optional): SKU.io row IDs of the Shopify products
        to sync.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 101
                - 102
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Successfully submitted to sales channel.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-shopify-integrationinstance-products-sync-inventory
  /api/shopify/{integrationInstance}/products/bulk:
    post:
      tags:
      - Shopify
      summary: Bulk Operation
      description: 'Execute a bulk operation on Shopify products synchronously.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Validation:

        - action: required, in: map, unmap, create, remap, archive, unarchive, delete,
        refresh

        - selection.type: required, in: selected, visible, filtered

        - selection.ids: required_if type=selected, array of integers

        - selection.filters: sometimes, array of filter key-value pairs

        - options.match_by: sometimes, in: sku, barcode (for map/remap)

        - options.create_if_no_match: sometimes, boolean (for map action)

        - options.field_mappings: sometimes, array of {shopify_field, sku_field}'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                action:
                  type: string
                selection:
                  type: object
                  properties:
                    type:
                      type: string
                    ids:
                      type: array
                      items:
                        type: integer
                options:
                  type: object
                  properties:
                    match_by:
                      type: string
                    create_if_no_match:
                      type: boolean
              example:
                action: map
                selection:
                  type: selected
                  ids:
                  - 1042
                  - 1043
                  - 1044
                options:
                  match_by: sku
                  create_if_no_match: false
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      processed:
                        type: integer
                      failed:
                        type: integer
                      skipped:
                        type: integer
                      mapped_count:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    processed: 3
                    failed: 0
                    skipped: 0
                    mapped_count: 3
                  message: 'Bulk map completed. Processed: 3, Failed: 0, Skipped:
                    0'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-shopify-integrationinstance-products-bulk
  /api/shopify/{integrationInstance}/products/bulk-tracked:
    post:
      tags:
      - Shopify
      summary: Bulk Operation (Tracked)
      description: 'Start a tracked bulk operation on Shopify products. Returns a
        tracked_job_log_id for progress polling.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Same validation as /products/bulk but dispatches a background job. Poll /products/bulk-progress/:id
        for status.


        Authentication: Requires Bearer token.


        Actions: map, unmap, create, remap, archive, unarchive, delete'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                action:
                  type: string
                selection:
                  type: object
                  properties:
                    type:
                      type: string
                    filters:
                      type: object
                      properties:
                        mapped:
                          type: boolean
                        status:
                          type: string
                options:
                  type: object
                  properties: {}
              example:
                action: create
                selection:
                  type: filtered
                  filters:
                    mapped: false
                    status: active
                options: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 4425
                  message: Bulk operation job has been queued
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-shopify-integrationinstance-products-bulk-tracked
  /api/shopify/{integrationInstance}/products/bulk-progress/{trackedJobLogId}:
    get:
      tags:
      - Shopify
      summary: Get Bulk Progress
      description: 'Poll the progress of a tracked bulk product operation job.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: trackedJobLogId
        in: path
        schema:
          type: integer
        required: true
        example: '4425'
        description: The tracked job log ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      job_name:
                        type: string
                      status:
                        type: string
                      progress_current:
                        type: integer
                      progress_total:
                        type: integer
                      started_at:
                        type: string
                      completed_at:
                        type: string
                example:
                  data:
                    id: 4425
                    job_name: 'Bulk Product Operation: My Store'
                    status: completed
                    progress_current: 250
                    progress_total: 250
                    started_at: '2024-03-20T14:00:00+00:00'
                    completed_at: '2024-03-20T14:05:00+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shopify-integrationinstance-products-bulk-progress-trackedjoblogid
  /api/shopify/{integrationInstance}/products/bulk-archive:
    post:
      tags:
      - Shopify
      summary: Bulk Archive
      description: 'Archive multiple Shopify products by their IDs.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Validation:

        - ids: required, array, min:1

        - ids.*: integer'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1042
                - 1043
                - 1044
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      archived_count:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    archived_count: 3
                  message: 3 products archived successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-shopify-integrationinstance-products-bulk-archive
  /api/shopify/{integrationInstance}/products/bulk-delete:
    post:
      tags:
      - Shopify
      summary: Bulk Delete
      description: 'Delete multiple Shopify products from the local database (does
        not delete in Shopify).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Validation:

        - ids: required, array, min:1

        - ids.*: integer'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1042
                - 1043
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      deleted_count:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    deleted_count: 2
                  message: 2 products deleted successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-shopify-integrationinstance-products-bulk-delete
  /api/shopify/{integrationInstance}/products/map:
    put:
      tags:
      - Shopify
      summary: Map Products to SKU Products
      description: 'Links Shopify product variants to SKU.io products in bulk by SKU.
        Each entry pairs a Shopify variant ID with a SKU.io product SKU; passing mapped_sku
        as null (or an empty string) unmaps the variant. Mappings are applied synchronously.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Body fields:

        - mapping (array, required, min 1): objects with sales_channel_listing_id
        (string, required - the Shopify variant ID), mapped_sku (string or null -
        the SKU.io product SKU to link, null to unmap), product_listing_id (integer,
        optional - existing listing to update), and subscription_offering_id (integer,
        optional - map to a subscription offering instead of a product).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                mapping:
                  type: array
                  items:
                    type: object
                    properties:
                      sales_channel_listing_id:
                        type: string
                      mapped_sku:
                        type: string
              example:
                mapping:
                - sales_channel_listing_id: '45123456789'
                  mapped_sku: TSHIRT-M-BLUE
                - sales_channel_listing_id: '45123456790'
                  mapped_sku: null
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: string
                example:
                  data: Successfully mapped sales channel products to sku products
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-shopify-integrationinstance-products-map
  /api/shopify/{integrationInstance}/products/create-sku-products:
    post:
      tags:
      - Shopify
      summary: Create SKU Products
      description: 'Queues creation of SKU.io products from synced Shopify products,
        using the supplied field mappings to populate product fields. The endpoint
        returns immediately; products are created in the background.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Body fields:

        - create_all_products (boolean, required): create from every eligible Shopify
        product on the instance.

        - ids (array of integers): SKU.io row IDs of specific Shopify products. Required
        when create_all_products is false and no filters are given.

        - mappings (array, optional): field mapping rows (listing_field, sku_field,
        parsers) to persist and use for this creation.

        - filters (string, optional): serialized filter set used to resolve the product
        IDs server-side.

        - initial_mapping (boolean, default false).


        Returns 400 when a selected Shopify product has no resolvable SKU.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                create_all_products:
                  type: boolean
                ids:
                  type: array
                  items:
                    type: integer
                mappings:
                  type: array
                  items:
                    type: object
                    properties:
                      listing_field:
                        type: string
                      sku_field:
                        type: string
                      parsers:
                        type: array
              example:
                create_all_products: false
                ids:
                - 101
                - 102
                - 103
                mappings:
                - listing_field: sku
                  sku_field: sku
                  parsers: []
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Added to queue, products will be created shortly.
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  apiErrors:
                    type: array
                    items:
                      type: object
                      properties:
                        title:
                          type: string
                        detail:
                          type: string
                example:
                  apiErrors:
                  - title: Missing SKU
                    detail: Shopify product 45123456789 has no SKU; set a SKU in Shopify
                      or map it to an existing product.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-shopify-integrationinstance-products-create-sku-products
  /api/shopify/{integrationInstance}/products/archive:
    put:
      tags:
      - Shopify
      summary: Archive Products
      description: 'Archives the given synced Shopify products in SKU.io (hides them
        from active listings; nothing is changed in Shopify). Use Check Archiveable
        Products first to see which products can be archived.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Body fields:

        - ids (array of integers): SKU.io row IDs of Shopify products on this instance.
        Required unless mode is "all".

        - mode (string, optional): "all" targets every product on the instance and
        ignores ids.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 101
                - 102
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Products archived successfully.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      ids:
                        type: array
                        items:
                          type: string
                example:
                  message: The ids field is required.
                  errors:
                    ids:
                    - The ids field is required.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: put-api-shopify-integrationinstance-products-archive
  /api/shopify/{integrationInstance}/products/unarchive:
    put:
      tags:
      - Shopify
      summary: Unarchive Products
      description: 'Restores previously archived Shopify products in SKU.io.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Body fields:

        - ids (array of integers): SKU.io row IDs of Shopify products on this instance.
        Required unless mode is "all".

        - mode (string, optional): "all" targets every product on the instance and
        ignores ids.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 101
                - 102
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Products unarchived successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-shopify-integrationinstance-products-unarchive
  /api/shopify/{integrationInstance}/products/archiveable:
    post:
      tags:
      - Shopify
      summary: Check Archiveable Products
      description: 'Checks which of the given Shopify products can be archived. Products
        that appear on synced Shopify orders cannot be archived; the response lists
        each product with a boolean and the blocking reason (false when archiveable).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Body fields:

        - ids (array of integers): SKU.io row IDs of Shopify products on this instance.
        Required unless mode is "all".

        - mode (string, optional): "all" targets every product on the instance and
        ignores ids.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 101
                - 102
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        archiveable:
                          type: boolean
                        reason:
                          type: boolean
                example:
                  data:
                  - id: 101
                    archiveable: true
                    reason: false
                  - id: 102
                    archiveable: false
                    reason: Sales Channel Product has Sales Channel Orders
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-shopify-integrationinstance-products-archiveable
  /api/shopify/{integrationInstance}/products/delete:
    put:
      tags:
      - Shopify
      summary: Delete Products
      description: 'Deletes the local synced copies of the given Shopify products
        from SKU.io, including their product mappings/listings. The products are not
        deleted from Shopify - a later product refresh may re-import them if they
        still exist there.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Body fields:

        - ids (array of integers): SKU.io row IDs of Shopify products on this instance.
        Required unless mode is "all".

        - mode (string, optional): "all" targets every product on the instance and
        ignores ids.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 101
                - 102
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Products deleted successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-shopify-integrationinstance-products-delete
  /api/shopify/{integrationInstance}/products/deleteable:
    put:
      tags:
      - Shopify
      summary: Check Deleteable Products
      description: 'Checks which of the given Shopify products can be deleted from
        SKU.io. The response lists each product with a boolean and the blocking reason
        (false when deleteable).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Body fields:

        - ids (array of integers): SKU.io row IDs of Shopify products on this instance.
        Required unless mode is "all".

        - mode (string, optional): "all" targets every product on the instance and
        ignores ids.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 101
                - 102
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        deleteable:
                          type: boolean
                        reason:
                          type: boolean
                example:
                  data:
                  - id: 101
                    deleteable: true
                    reason: false
                  - id: 102
                    deleteable: true
                    reason: false
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-shopify-integrationinstance-products-deleteable
  /api/shopify/{integrationInstance}/products/bulk-mapping-csv/download:
    post:
      tags:
      - Shopify
      summary: Download Bulk Mapping CSV Template
      description: 'Download a CSV template pre-filled with Shopify product data and
        current mappings. Users fill in the map_to_sku column and upload back.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Response is a CSV file download (Content-Type: text/csv).


        Authentication: Requires Bearer token.


        Validation:

        - scope: required, in: selected, unmapped, all

        - ids: required_if scope=selected, array of integers

        - filters: sometimes, array (supports mapping_status key)'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                scope:
                  type: string
                ids:
                  type: array
                filters:
                  type: object
                  properties: {}
              example:
                scope: unmapped
                ids: []
                filters: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: text/csv
            Content-Disposition:
              schema:
                type: string
                example: attachment; filename="shopify-product-mappings-unmapped-2024-03-20.csv"
          content:
            text/plain:
              schema:
                type: string
                example: 'shopify_product_id,shopify_sku,shopify_title,barcode,price,map_to_sku

                  1042,SHIRT-BLU-LG,Classic Blue Shirt - Large,0123456789012,29.99,

                  1043,SHIRT-RED-SM,Classic Red Shirt - Small,0123456789013,29.99,'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-shopify-integrationinstance-products-bulk-mapping-csv-download
  /api/shopify/{integrationInstance}/products/bulk-mapping-csv/validate:
    post:
      tags:
      - Shopify
      summary: Validate Bulk Mapping CSV
      description: 'Validate an uploaded CSV mapping file. Returns validation results
        including valid mappings and invalid rows.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Request: multipart/form-data


        Authentication: Requires Bearer token.


        Validation:

        - file: required, file, mimes: csv/txt, max: 10240 (10MB)


        CSV must have columns: shopify_product_id, map_to_sku'
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                file:
                  type: string
                  description: 'CSV file (max 10MB, mimes: csv, txt)'
                  format: binary
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      valid_count:
                        type: integer
                      invalid_rows:
                        type: array
                        items:
                          type: object
                          properties:
                            row_number:
                              type: integer
                            shopify_product_id:
                              type: string
                            map_to_sku:
                              type: string
                            error:
                              type: string
                      skipped_count:
                        type: integer
                      mappings:
                        type: array
                        items:
                          type: object
                          properties:
                            shopify_product_id:
                              type: integer
                            sku_product_id:
                              type: integer
                example:
                  data:
                    valid_count: 45
                    invalid_rows:
                    - row_number: 5
                      shopify_product_id: '9999'
                      map_to_sku: NONEXISTENT
                      error: 'No SKU product found with code: NONEXISTENT'
                    skipped_count: 3
                    mappings:
                    - shopify_product_id: 1042
                      sku_product_id: 301
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-shopify-integrationinstance-products-bulk-mapping-csv-validate
  /api/shopify/{integrationInstance}/products/bulk-mapping-csv/apply:
    post:
      tags:
      - Shopify
      summary: Apply Bulk Mapping CSV
      description: 'Apply validated CSV mappings — creates or updates product listings
        for each mapping pair.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Validation:

        - mappings: required, array, min:1

        - mappings.*.shopify_product_id: required, integer

        - mappings.*.sku_product_id: required, integer, exists in products table'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                mappings:
                  type: array
                  items:
                    type: object
                    properties:
                      shopify_product_id:
                        type: integer
                      sku_product_id:
                        type: integer
              example:
                mappings:
                - shopify_product_id: 1042
                  sku_product_id: 301
                - shopify_product_id: 1043
                  sku_product_id: 302
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      mapped_count:
                        type: integer
                      failed_count:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    mapped_count: 44
                    failed_count: 1
                  message: Applied 44 mappings successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-shopify-integrationinstance-products-bulk-mapping-csv-apply
  /api/shopify/{integrationInstance}/products/import-mappings:
    post:
      tags:
      - Shopify
      summary: Import Product Mappings
      description: 'Queues a background import of product mappings from a previously
        uploaded CSV file (referenced by its stored name from the file upload step).
        Rows are keyed by the Shopify variant ID column and link each variant to a
        SKU.io product. The endpoint returns immediately.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Body fields:

        - original_name (string, required): the original client-side file name.

        - stored_name (string, required): the server-side stored file name returned
        by the upload step.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                original_name:
                  type: string
                stored_name:
                  type: string
              example:
                original_name: shopify-mappings.csv
                stored_name: d41d8cd98f00b204e9800998ecf8427e.csv
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Added to queue, mappings will be imported shortly.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-shopify-integrationinstance-products-import-mappings
  /api/shopify/{integrationInstance}/products/{product}/revenue-conversion/preview:
    get:
      tags:
      - Shopify
      summary: Preview Revenue Conversion
      description: 'Preview the impact of retroactively converting this product''s
        historical sales-order lines (scoped to **this Shopify integration instance**)
        into revenue financial lines. Read-only — nothing is changed.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Returns counts, total revenue that would move, and warning counts for fulfilled
        and returned/credited lines.


        **Requires Bearer token.**


        **Errors:**

        - 403: product does not belong to the given integration instance'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: product
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The product ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      orders:
                        type: integer
                      lines:
                        type: integer
                      revenue_total:
                        type: number
                      fulfilled_lines:
                        type: integer
                      credited_lines:
                        type: integer
                      blocked_returns:
                        type: integer
                      is_noop:
                        type: boolean
                example:
                  data:
                    orders: 12
                    lines: 15
                    revenue_total: 1124.5
                    fulfilled_lines: 9
                    credited_lines: 1
                    blocked_returns: 2
                    is_noop: false
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shopify-integrationinstance-products-product-revenue-conversion-preview
  /api/shopify/{integrationInstance}/products/{product}/revenue-conversion/affected-orders:
    get:
      tags:
      - Shopify
      summary: Get Affected Orders
      description: 'Paginated list of sales orders that would be affected by a revenue-line
        conversion for this product (scoped to this Shopify integration instance).
        Powers the conversion wizard''s impact step.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Each row links to the sales order detail page via `link_route`.


        **Requires Bearer token.**


        **Errors:**

        - 403: product does not belong to the given integration instance'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: product
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The product ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        sales_order_number:
                          type: string
                        order_date:
                          type: string
                        converted_lines_count:
                          type: integer
                        link_reference:
                          type: string
                        link_type_label:
                          type: string
                        link_route:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - id: 4821
                    sales_order_number: SO-10231
                    order_date: '2024-11-04T00:00:00.000000Z'
                    converted_lines_count: 1
                    link_reference: SO-10231
                    link_type_label: Sales Order
                    link_route: /orders/sales-orders/4821
                  - id: 4805
                    sales_order_number: SO-10219
                    order_date: '2024-11-02T00:00:00.000000Z'
                    converted_lines_count: 2
                    link_reference: SO-10219
                    link_type_label: Sales Order
                    link_route: /orders/sales-orders/4805
                  current_page: 1
                  last_page: 2
                  per_page: 10
                  total: 12
                  from: 1
                  to: 10
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shopify-integrationinstance-products-product-revenue-conversion-affected-orders
  /api/shopify/{integrationInstance}/products/{product}/revenue-conversion:
    post:
      tags:
      - Shopify
      summary: Convert Product Lines to Revenue
      description: 'Flag this product as a revenue line and retroactively convert
        its historical sales-order lines (scoped to this Shopify integration instance)
        into revenue financial lines via a tracked background job.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        The job creates an equivalent revenue financial line for each affected sales-order
        line, deletes the line (reversing fulfillment/allocations/inventory/credits
        via the model cascade), then rebuilds the line + daily financial caches and
        the accounting batch summaries (and any linked QBO journals).


        **Request body:**

        - `financial_line_type_id` (integer, **required**) — must be a REVENUE-classified
        financial line type. The product''s `default_financial_line_type_id` is set
        to this value.

        - `date_from` (date, optional, Y-m-d) — only convert orders on/after this
        date.

        - `date_to` (date, optional, Y-m-d) — only convert orders on/before this date.

        - `sales_order_ids` (int[], optional) — convert ONLY these sales orders (the
        ''pick specific orders'' mode). Omit to convert all matching.

        - `confirm` (boolean, **required**) — must be `true`.


        Returns the `tracked_job_log_id` so progress can be followed via the tracked
        job log endpoints.


        **Requires Bearer token.**


        **Errors:**

        - 403: product does not belong to the given integration instance

        - 422: product is not mapped to a SKU product, or `financial_line_type_id`
        is not a revenue type, or `confirm` not accepted'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                financial_line_type_id:
                  type: integer
                date_from:
                  type: string
                date_to:
                  type: string
                sales_order_ids:
                  type: array
                  items:
                    type: integer
                confirm:
                  type: boolean
              example:
                financial_line_type_id: 7
                date_from: '2024-01-01'
                date_to: '2024-12-31'
                sales_order_ids:
                - 4821
                - 4805
                confirm: true
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: product
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The product ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 3391
                  message: Revenue line conversion started — track progress in the
                    job tray.
        '422':
          description: Unprocessable Content
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: Product is not mapped to a SKU product.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-shopify-integrationinstance-products-product-revenue-conversion
  /api/shopify/{integrationInstance}/costs/sync:
    post:
      tags:
      - Shopify
      summary: Sync Costs to Shopify
      description: 'Push each mapped listing''s average cost to the Shopify variant''s
        "Cost per item" field. Runs asynchronously; poll Get Cost Sync Progress with
        the returned tracked_job_log_id.


        Costs are pushed in the store''s currency (converted from your base currency
        using your configured exchange rate). Products with no average cost are skipped,
        never zeroed. Bundles push the sum of component costs; a bundle is skipped
        when any component has no cost. Values already matching Shopify are skipped.


        Requires the "Push costs" sync capability to be enabled for the integration
        instance.


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                example:
                  message: Cost sync job has been queued
                  data:
                    tracked_job_log_id: 9134
        '422':
          description: Unprocessable Content
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      cost_sync:
                        type: array
                        items:
                          type: string
                example:
                  message: Cost sync is not enabled for this Shopify instance. Enable
                    "Push costs" in Settings first.
                  errors:
                    cost_sync:
                    - Cost sync is not enabled for this Shopify instance. Enable "Push
                      costs" in Settings first.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-shopify-integrationinstance-costs-sync
  /api/shopify/{integrationInstance}/costs/sync-progress/{trackedJobLogId}:
    get:
      tags:
      - Shopify
      summary: Get Cost Sync Progress
      description: 'Get the progress and results of a cost sync run. The results object
        reports pushed, skipped_unchanged, skipped_no_cost, skipped_bundle_component,
        skipped_currency, failed counts and an errors list.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: trackedJobLogId
        in: path
        schema:
          type: integer
        required: true
        example: '9134'
        description: The tracked job log ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      job_name:
                        type: string
                      status:
                        type: string
                      progress_percentage:
                        type: integer
                      messages:
                        type: string
                      results:
                        type: object
                        properties:
                          pushed:
                            type: integer
                          skipped_unchanged:
                            type: integer
                          skipped_no_cost:
                            type: integer
                          skipped_bundle_component:
                            type: integer
                          skipped_currency:
                            type: integer
                          failed:
                            type: integer
                          has_failures:
                            type: boolean
                          errors:
                            type: array
                            items:
                              type: string
                          completed_at:
                            type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 9134
                    job_name: 'Sync Costs to Shopify: My Store'
                    status: completed
                    progress_percentage: 100
                    messages: Pushed 1204 costs to Shopify (310 unchanged, 12 without
                      cost, 4 bundle-skipped, 0 currency-skipped, 2 failed)
                    results:
                      pushed: 1204
                      skipped_unchanged: 310
                      skipped_no_cost: 12
                      skipped_bundle_component: 4
                      skipped_currency: 0
                      failed: 2
                      has_failures: true
                      errors:
                      - 'SHIRT-BLU-LG: Variant not found on Shopify'
                      completed_at: '2026-07-17T06:02:14+00:00'
                    created_at: '2026-07-17T06:00:00+00:00'
                    updated_at: '2026-07-17T06:02:14+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shopify-integrationinstance-costs-sync-progress-trackedjoblogid
  /api/shopify/{integrationInstance}/costs/last-sync:
    get:
      tags:
      - Shopify
      summary: Get Last Cost Sync
      description: 'Get the most recent cost sync run for this instance (any status),
        or null when costs have never been synced. The response also includes a currency
        object (base_currency, store_currency, store_currency_rate, has_rate, differs)
        describing the base-vs-store currency conversion applied when pushing costs.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 OK
                  value:
                    data:
                      id: 9134
                      job_name: 'Sync Costs to Shopify: My Store'
                      status: completed
                      progress_percentage: 100
                      messages: Pushed 1204 costs to Shopify (310 unchanged, 12 without
                        cost, 4 bundle-skipped, 0 currency-skipped, 2 failed)
                      results:
                        pushed: 1204
                        skipped_unchanged: 310
                        skipped_no_cost: 12
                        skipped_bundle_component: 4
                        skipped_currency: 0
                        failed: 2
                        has_failures: true
                        errors:
                        - 'SHIRT-BLU-LG: Variant not found on Shopify'
                        completed_at: '2026-07-17T06:02:14+00:00'
                      created_at: '2026-07-17T06:00:00+00:00'
                      updated_at: '2026-07-17T06:02:14+00:00'
                    currency:
                      base_currency: USD
                      store_currency: GBP
                      store_currency_rate: 1.27
                      has_rate: true
                      differs: true
                example-1:
                  summary: 200 OK (Never Synced)
                  value:
                    data: null
                    currency:
                      base_currency: USD
                      store_currency: USD
                      store_currency_rate: 1
                      has_rate: true
                      differs: false
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shopify-integrationinstance-costs-last-sync
  /api/shopify/{integrationInstance}/customers:
    get:
      tags:
      - Shopify
      summary: List Customers
      description: 'Returns a paginated list of Shopify customers synced for the integration
        instance, including their default address and total synced order count.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Filterable columns: id, legacy_resource_id, email, first_name, last_name,
        phone, full_name, city, province, country_code, shopify_created_at, created_at,
        updated_at. filter[search] matches email, first name, last name, phone, and
        address city/province/country.


        Filtering: pass filter[column]=value for an exact match, or filter[column.operator]=value
        with operators such as contains, does_not_contain, is, is_not, is_one_of,
        starts_with, ends_with, is_empty, is_not_empty (text), greater_than, less_than,
        greater_than_or_equal, less_than_or_equal, between (numeric/date). Complex
        AND/OR trees can be sent as a base64-encoded JSON tree in the filter_groups
        parameter.


        Allowed sorts: id, email, first_name, last_name, shopify_created_at, created_at,
        updated_at (prefix with - for descending; default -id). Pagination defaults
        to 15 per page.'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        description: 'Page number (default: 1)'
        example: '1'
      - name: per_page
        in: query
        schema:
          type: integer
        description: 'Items per page (default: 15)'
        example: '15'
      - name: sort
        in: query
        schema:
          type: string
        description: 'Sort field. Allowed: id, email, first_name, last_name, shopify_created_at,
          created_at, updated_at'
        example: -id
      - name: filter[search]
        in: query
        schema:
          type: string
        description: Search email, name, phone, and address fields
        example: jane
      - name: filter[email.contains]
        in: query
        schema:
          type: string
        description: Example operator filter on email
        example: example.com
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        legacy_resource_id:
                          type: string
                        email:
                          type: string
                        first_name:
                          type: string
                        last_name:
                          type: string
                        full_name:
                          type: string
                        phone:
                          type: string
                        orders_count:
                          type: integer
                        default_address:
                          type: object
                          properties:
                            id:
                              type: integer
                            city:
                              type: string
                            province:
                              type: string
                            province_code:
                              type: string
                            country:
                              type: string
                            country_code:
                              type: string
                            zip:
                              type: string
                        location:
                          type: string
                        shopify_created_at:
                          type: string
                        shopify_updated_at:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  next_page_url:
                    type: string
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 44
                    legacy_resource_id: '7300112233'
                    email: jane@example.com
                    first_name: Jane
                    last_name: Doe
                    full_name: Jane Doe
                    phone: +1 415 555 0100
                    orders_count: 6
                    default_address:
                      id: 91
                      city: San Francisco
                      province: California
                      province_code: CA
                      country: United States
                      country_code: US
                      zip: '94105'
                    location: San Francisco, CA, US
                    shopify_created_at: '2024-02-10T18:22:00+00:00'
                    shopify_updated_at: '2025-06-01T07:15:00+00:00'
                    created_at: '2024-02-10T18:25:00+00:00'
                    updated_at: '2025-06-01T07:16:00+00:00'
                  first_page_url: '{{protocol}}://{{domain}}/api/shopify/1/customers?page=1'
                  from: 1
                  last_page: 8
                  last_page_url: '{{protocol}}://{{domain}}/api/shopify/1/customers?page=8'
                  next_page_url: '{{protocol}}://{{domain}}/api/shopify/1/customers?page=2'
                  path: '{{protocol}}://{{domain}}/api/shopify/1/customers'
                  per_page: 15
                  prev_page_url: null
                  to: 15
                  total: 112
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shopify-integrationinstance-customers
  /api/shopify/{integrationInstance}/refunds:
    get:
      tags:
      - Shopify
      summary: List Refunds
      description: 'Returns a paginated list of Shopify refunds synced for the integration
        instance, with the parent order summary and refund line item totals (quantity,
        subtotal, tax, and total refunded including adjustments).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Filterable columns: id, legacy_resource_id, note, order_name, shopify_created_at,
        shopify_processed_at, created_at, updated_at. filter[search] matches the refund
        ID, order number, and note.


        Filtering: pass filter[column]=value for an exact match, or filter[column.operator]=value
        with operators such as contains, does_not_contain, is, is_not, is_one_of,
        starts_with, ends_with, is_empty, is_not_empty (text), greater_than, less_than,
        greater_than_or_equal, less_than_or_equal, between (numeric/date). Complex
        AND/OR trees can be sent as a base64-encoded JSON tree in the filter_groups
        parameter.


        Allowed sorts: id, legacy_resource_id, note, shopify_created_at, shopify_processed_at,
        created_at, updated_at (default -id). Pagination defaults to 15 per page.'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        description: 'Page number (default: 1)'
        example: '1'
      - name: per_page
        in: query
        schema:
          type: integer
        description: 'Items per page (default: 15)'
        example: '15'
      - name: sort
        in: query
        schema:
          type: string
        description: 'Sort field. Allowed: id, legacy_resource_id, note, shopify_created_at,
          shopify_processed_at, created_at, updated_at'
        example: -id
      - name: filter[search]
        in: query
        schema:
          type: string
        description: Search refund ID, order number, or note
        example: '#1001'
      - name: filter[order_name]
        in: query
        schema:
          type: string
        description: Filter by order number
        example: '#1001'
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        legacy_resource_id:
                          type: string
                        note:
                          type: string
                        order:
                          type: object
                          properties:
                            id:
                              type: integer
                            legacy_resource_id:
                              type: string
                            name:
                              type: string
                            email:
                              type: string
                            shopify_created_at:
                              type: string
                        line_items_count:
                          type: integer
                        total_quantity_refunded:
                          type: integer
                        total_subtotal:
                          type: number
                        total_tax:
                          type: number
                        total_refunded:
                          type: number
                        adjustments_count:
                          type: integer
                        shopify_created_at:
                          type: string
                        shopify_processed_at:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  next_page_url:
                    type: string
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 21
                    legacy_resource_id: '902211334'
                    note: Damaged in transit
                    order:
                      id: 501
                      legacy_resource_id: '6001098342'
                      name: '#1001'
                      email: jane@example.com
                      shopify_created_at: '2025-05-20T16:05:00+00:00'
                    line_items_count: 1
                    total_quantity_refunded: 1
                    total_subtotal: 24.95
                    total_tax: 2.18
                    total_refunded: 27.13
                    adjustments_count: 0
                    shopify_created_at: '2025-05-25T10:00:00+00:00'
                    shopify_processed_at: '2025-05-25T10:00:05+00:00'
                    created_at: '2025-05-25T10:02:00+00:00'
                    updated_at: '2025-05-25T10:02:00+00:00'
                  first_page_url: '{{protocol}}://{{domain}}/api/shopify/1/refunds?page=1'
                  from: 1
                  last_page: 3
                  last_page_url: '{{protocol}}://{{domain}}/api/shopify/1/refunds?page=3'
                  next_page_url: '{{protocol}}://{{domain}}/api/shopify/1/refunds?page=2'
                  path: '{{protocol}}://{{domain}}/api/shopify/1/refunds'
                  per_page: 15
                  prev_page_url: null
                  to: 15
                  total: 34
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shopify-integrationinstance-refunds
  /api/shopify/{integrationInstance}/returns:
    get:
      tags:
      - Shopify
      summary: List Returns
      description: 'Returns a paginated list of Shopify returns synced for the integration
        instance, with the parent order summary, return line item counts, and the
        linked SKU.io RMA when one has been created.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Filterable columns: id, name, status, order_name, shopify_created_at, shopify_updated_at,
        created_at, updated_at. filter[search] matches the return number and order
        number.


        Filtering: pass filter[column]=value for an exact match, or filter[column.operator]=value
        with operators such as contains, does_not_contain, is, is_not, is_one_of,
        starts_with, ends_with, is_empty, is_not_empty (text), greater_than, less_than,
        greater_than_or_equal, less_than_or_equal, between (numeric/date). Complex
        AND/OR trees can be sent as a base64-encoded JSON tree in the filter_groups
        parameter.


        Allowed sorts: id, name, status, shopify_created_at, shopify_updated_at, created_at,
        updated_at (default -id). Pagination defaults to 15 per page.'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        description: 'Page number (default: 1)'
        example: '1'
      - name: per_page
        in: query
        schema:
          type: integer
        description: 'Items per page (default: 15)'
        example: '15'
      - name: sort
        in: query
        schema:
          type: string
        description: 'Sort field. Allowed: id, name, status, shopify_created_at, shopify_updated_at,
          created_at, updated_at'
        example: -id
      - name: filter[search]
        in: query
        schema:
          type: string
        description: Search return number or order number
        example: '#1001'
      - name: filter[status]
        in: query
        schema:
          type: string
        description: Filter by return status (e.g. OPEN, CLOSED)
        example: OPEN
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        legacy_resource_id:
                          type: string
                        name:
                          type: string
                        status:
                          type: string
                        order:
                          type: object
                          properties:
                            id:
                              type: integer
                            legacy_resource_id:
                              type: string
                            name:
                              type: string
                            email:
                              type: string
                            shopify_created_at:
                              type: string
                        line_items_count:
                          type: integer
                        total_items_returned:
                          type: integer
                        rma:
                          type: object
                          properties:
                            id:
                              type: integer
                            rma_number:
                              type: string
                            status:
                              type: string
                        alert:
                          type: string
                          nullable: true
                        shopify_created_at:
                          type: string
                        shopify_updated_at:
                          type: string
                        closed_at:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 9
                    legacy_resource_id: '4477001'
                    name: '#1001-R1'
                    status: OPEN
                    order:
                      id: 501
                      legacy_resource_id: '6001098342'
                      name: '#1001'
                      email: jane@example.com
                      shopify_created_at: '2025-05-20T16:05:00+00:00'
                    line_items_count: 1
                    total_items_returned: 1
                    rma:
                      id: 301
                      rma_number: RMA-301
                      status: open
                    alert: null
                    shopify_created_at: '2025-05-28T09:00:00+00:00'
                    shopify_updated_at: '2025-05-28T09:00:00+00:00'
                    closed_at: null
                    created_at: '2025-05-28T09:02:00+00:00'
                    updated_at: '2025-05-28T09:02:00+00:00'
                  first_page_url: '{{protocol}}://{{domain}}/api/shopify/1/returns?page=1'
                  from: 1
                  last_page: 1
                  last_page_url: '{{protocol}}://{{domain}}/api/shopify/1/returns?page=1'
                  next_page_url: null
                  path: '{{protocol}}://{{domain}}/api/shopify/1/returns'
                  per_page: 15
                  prev_page_url: null
                  to: 12
                  total: 12
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shopify-integrationinstance-returns
  /api/shopify/{integrationInstance}/transactions:
    get:
      tags:
      - Shopify
      summary: List Transactions
      description: 'Returns a paginated list of Shopify payment transactions synced
        for the integration instance, with the parent order summary and aggregated
        processing fee totals (converted to the shop currency).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Filterable columns: kind (authorization, capture, sale, void, refund), status
        (pending, failure, success, error), formatted_gateway, currency, amount, shopify_created_at,
        created_at. filter[search] matches the order number and gateway.


        Filtering: pass filter[column]=value for an exact match, or filter[column.operator]=value
        with operators such as contains, does_not_contain, is, is_not, is_one_of,
        starts_with, ends_with, is_empty, is_not_empty (text), greater_than, less_than,
        greater_than_or_equal, less_than_or_equal, between (numeric/date). Complex
        AND/OR trees can be sent as a base64-encoded JSON tree in the filter_groups
        parameter.


        Allowed sorts: id, amount, kind, status, formatted_gateway, currency, shopify_created_at,
        shopify_processed_at, created_at (default -id). Pagination defaults to 15
        per page.'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        description: 'Page number (default: 1)'
        example: '1'
      - name: per_page
        in: query
        schema:
          type: integer
        description: 'Items per page (default: 15)'
        example: '15'
      - name: sort
        in: query
        schema:
          type: string
        description: 'Sort field. Allowed: id, amount, kind, status, formatted_gateway,
          currency, shopify_created_at, shopify_processed_at, created_at'
        example: -id
      - name: filter[search]
        in: query
        schema:
          type: string
        description: Search order number or gateway
        example: '#1001'
      - name: filter[kind]
        in: query
        schema:
          type: string
        description: 'Filter by transaction kind: authorization, capture, sale, void,
          refund'
        example: sale
      - name: filter[status]
        in: query
        schema:
          type: string
        description: 'Filter by status: pending, failure, success, error'
        example: success
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        legacy_resource_id:
                          type: string
                        kind:
                          type: string
                        status:
                          type: string
                        amount:
                          type: string
                        presentment_amount:
                          type: string
                        presentment_currency:
                          type: string
                        has_currency_conversion:
                          type: boolean
                        gateway:
                          type: string
                        formatted_gateway:
                          type: string
                        currency:
                          type: string
                        order:
                          type: object
                          properties:
                            id:
                              type: integer
                            legacy_resource_id:
                              type: string
                            name:
                              type: string
                            email:
                              type: string
                            currency:
                              type: string
                            shopify_created_at:
                              type: string
                        fees_count:
                          type: integer
                        total_fees:
                          type: number
                        total_fee_tax:
                          type: integer
                        shopify_created_at:
                          type: string
                        shopify_processed_at:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  next_page_url:
                    type: string
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 77
                    legacy_resource_id: '5800223344'
                    kind: sale
                    status: success
                    amount: '59.90'
                    presentment_amount: '59.90'
                    presentment_currency: USD
                    has_currency_conversion: false
                    gateway: shopify_payments
                    formatted_gateway: Shopify Payments
                    currency: USD
                    order:
                      id: 501
                      legacy_resource_id: '6001098342'
                      name: '#1001'
                      email: jane@example.com
                      currency: USD
                      shopify_created_at: '2025-05-20T16:05:00+00:00'
                    fees_count: 1
                    total_fees: 2.04
                    total_fee_tax: 0
                    shopify_created_at: '2025-05-20T16:05:10+00:00'
                    shopify_processed_at: '2025-05-20T16:05:10+00:00'
                    created_at: '2025-05-20T16:07:00+00:00'
                    updated_at: '2025-05-20T16:07:00+00:00'
                  first_page_url: '{{protocol}}://{{domain}}/api/shopify/1/transactions?page=1'
                  from: 1
                  last_page: 17
                  last_page_url: '{{protocol}}://{{domain}}/api/shopify/1/transactions?page=17'
                  next_page_url: '{{protocol}}://{{domain}}/api/shopify/1/transactions?page=2'
                  path: '{{protocol}}://{{domain}}/api/shopify/1/transactions'
                  per_page: 15
                  prev_page_url: null
                  to: 15
                  total: 250
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shopify-integrationinstance-transactions
  /api/shopify/{integrationInstance}/transactions/{transaction}:
    get:
      tags:
      - Shopify
      summary: Get Transaction
      description: 'Returns full details of a single Shopify payment transaction:
        amounts in shop and presentment currency with the implied exchange rate, the
        raw gateway receipt, the parent order''s financial summary with a Shopify
        admin link, and each processing fee with its rate breakdown.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Returns 403 if the transaction does not belong to the given integration instance.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: transaction
        in: path
        schema:
          type: integer
        required: true
        example: '77'
        description: The transaction ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      legacy_resource_id:
                        type: string
                      kind:
                        type: string
                      status:
                        type: string
                      amount:
                        type: string
                      presentment_amount:
                        type: string
                      presentment_currency:
                        type: string
                      implied_exchange_rate:
                        type: string
                        nullable: true
                      has_currency_conversion:
                        type: boolean
                      gateway:
                        type: string
                      formatted_gateway:
                        type: string
                      receipt_json:
                        type: object
                        properties:
                          payment_id:
                            type: string
                          risk_level:
                            type: string
                      shopify_created_at:
                        type: string
                      shopify_processed_at:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      order:
                        type: object
                        properties:
                          id:
                            type: integer
                          legacy_resource_id:
                            type: string
                          name:
                            type: string
                          email:
                            type: string
                          phone:
                            type: string
                            nullable: true
                          currency:
                            type: string
                          financial_status:
                            type: string
                          fulfillment_status:
                            type: string
                          total_price:
                            type: string
                          subtotal_price:
                            type: string
                          total_tax:
                            type: string
                          total_discounts:
                            type: string
                          total_shipping_price:
                            type: string
                          shopify_created_at:
                            type: string
                          shopify_admin_url:
                            type: string
                      currency:
                        type: string
                      integration_instance:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          myshopify_domain:
                            type: string
                      fees:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            legacy_resource_id:
                              type: string
                            amount:
                              type: string
                            tax_amount:
                              type: string
                            flat_fee:
                              type: string
                            flat_fee_name:
                              type: string
                            rate:
                              type: string
                            rate_name:
                              type: string
                            type:
                              type: string
                            created_at:
                              type: string
                            updated_at:
                              type: string
                      fees_count:
                        type: integer
                      total_fees_presentment:
                        type: number
                      total_fees:
                        type: number
                      total_fee_tax:
                        type: integer
                example:
                  data:
                    id: 77
                    legacy_resource_id: '5800223344'
                    kind: sale
                    status: success
                    amount: '59.90'
                    presentment_amount: '59.90'
                    presentment_currency: USD
                    implied_exchange_rate: null
                    has_currency_conversion: false
                    gateway: shopify_payments
                    formatted_gateway: Shopify Payments
                    receipt_json:
                      payment_id: pi_3NxYz
                      risk_level: normal
                    shopify_created_at: '2025-05-20T16:05:10+00:00'
                    shopify_processed_at: '2025-05-20T16:05:10+00:00'
                    created_at: '2025-05-20T16:07:00+00:00'
                    updated_at: '2025-05-20T16:07:00+00:00'
                    order:
                      id: 501
                      legacy_resource_id: '6001098342'
                      name: '#1001'
                      email: jane@example.com
                      phone: null
                      currency: USD
                      financial_status: paid
                      fulfillment_status: fulfilled
                      total_price: '59.90'
                      subtotal_price: '49.90'
                      total_tax: '4.50'
                      total_discounts: '0.00'
                      total_shipping_price: '5.50'
                      shopify_created_at: '2025-05-20T16:05:00+00:00'
                      shopify_admin_url: https://admin.shopify.com/store/my-store/orders/6001098342
                    currency: USD
                    integration_instance:
                      id: 1
                      name: Main Shopify Store
                      myshopify_domain: my-store.myshopify.com
                    fees:
                    - id: 5
                      legacy_resource_id: '9911223'
                      amount: '2.04'
                      tax_amount: '0.00'
                      flat_fee: '0.30'
                      flat_fee_name: USD Flat Fee
                      rate: '0.029'
                      rate_name: Card Rate
                      type: payment
                      created_at: '2025-05-20T16:07:00+00:00'
                      updated_at: '2025-05-20T16:07:00+00:00'
                    fees_count: 1
                    total_fees_presentment: 2.04
                    total_fees: 2.04
                    total_fee_tax: 0
        '403':
          description: Forbidden
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: Transaction does not belong to this integration instance
        '429': *id001
        '401': *id002
        '404': *id004
      operationId: get-api-shopify-integrationinstance-transactions-transaction
  /api/shopify/mappings/available-fields:
    get:
      tags:
      - Shopify
      summary: List Available Mapping Fields
      description: 'Returns the vocabulary of fields that can be used when configuring
        field mappings: every mappable Shopify product field and every mappable SKU.io
        product field, each with a label, data type, description, and group. Use these
        field names in the mappings you send to Update Field Mappings.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        This endpoint is account-wide and does not require an integration instance.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      shopify_fields:
                        type: object
                        properties:
                          shopify_product_id:
                            type: object
                            properties:
                              name:
                                type: string
                              label:
                                type: string
                              type:
                                type: string
                              description:
                                type: string
                              group:
                                type: string
                          shopify_variant_id:
                            type: object
                            properties:
                              name:
                                type: string
                              label:
                                type: string
                              type:
                                type: string
                              description:
                                type: string
                              group:
                                type: string
                          sku:
                            type: object
                            properties:
                              name:
                                type: string
                              label:
                                type: string
                              type:
                                type: string
                              description:
                                type: string
                              group:
                                type: string
                          barcode:
                            type: object
                            properties:
                              name:
                                type: string
                              label:
                                type: string
                              type:
                                type: string
                              description:
                                type: string
                              group:
                                type: string
                          price:
                            type: object
                            properties:
                              name:
                                type: string
                              label:
                                type: string
                              type:
                                type: string
                              description:
                                type: string
                              group:
                                type: string
                      sku_fields:
                        type: object
                        properties:
                          sku:
                            type: object
                            properties:
                              name:
                                type: string
                              label:
                                type: string
                              type:
                                type: string
                              description:
                                type: string
                              group:
                                type: string
                          name:
                            type: object
                            properties:
                              name:
                                type: string
                              label:
                                type: string
                              type:
                                type: string
                              description:
                                type: string
                              group:
                                type: string
                          barcode:
                            type: object
                            properties:
                              name:
                                type: string
                              label:
                                type: string
                              type:
                                type: string
                              description:
                                type: string
                              group:
                                type: string
                          price:
                            type: object
                            properties:
                              name:
                                type: string
                              label:
                                type: string
                              type:
                                type: string
                              description:
                                type: string
                              group:
                                type: string
                example:
                  data:
                    shopify_fields:
                      shopify_product_id:
                        name: shopify_product_id
                        label: Shopify Product ID
                        type: integer
                        description: Unique Shopify product identifier
                        group: Identifiers
                      shopify_variant_id:
                        name: shopify_variant_id
                        label: Shopify Variant ID
                        type: integer
                        description: Unique Shopify variant identifier
                        group: Identifiers
                      sku:
                        name: sku
                        label: SKU
                        type: string
                        description: Variant SKU as entered in Shopify
                        group: Product Details
                      barcode:
                        name: barcode
                        label: Barcode
                        type: string
                        description: Variant barcode (UPC/EAN/ISBN)
                        group: Product Details
                      price:
                        name: price
                        label: Price
                        type: decimal
                        description: Variant price
                        group: Pricing
                    sku_fields:
                      sku:
                        name: sku
                        label: SKU
                        type: string
                        description: SKU.io product SKU
                        group: Product
                      name:
                        name: name
                        label: Name
                        type: string
                        description: SKU.io product name
                        group: Product
                      barcode:
                        name: barcode
                        label: Barcode
                        type: string
                        description: SKU.io product barcode
                        group: Product
                      price:
                        name: price
                        label: Price
                        type: decimal
                        description: SKU.io default sell price
                        group: Pricing
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-shopify-mappings-available-fields
  /api/shopify/{integrationInstance}/mappings:
    get:
      tags:
      - Shopify
      summary: Get Field Mappings
      description: 'Returns the field mapping configuration for an integration instance:
        the built-in default mappings, any custom overrides, and the effective mappings
        (defaults merged with overrides) that are actually applied when products are
        linked or created. Also includes the available field catalogs for building
        an editor.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      integration_instance_id:
                        type: integer
                      integration_name:
                        type: string
                      mappings:
                        type: array
                        items:
                          type: object
                          properties:
                            listing_field:
                              type: string
                            sku_field:
                              type: string
                            parsers:
                              type: array
                      available_shopify_fields:
                        type: object
                        properties:
                          shopify_product_id:
                            type: object
                            properties:
                              name:
                                type: string
                              label:
                                type: string
                              type:
                                type: string
                              description:
                                type: string
                              group:
                                type: string
                          shopify_variant_id:
                            type: object
                            properties:
                              name:
                                type: string
                              label:
                                type: string
                              type:
                                type: string
                              description:
                                type: string
                              group:
                                type: string
                          sku:
                            type: object
                            properties:
                              name:
                                type: string
                              label:
                                type: string
                              type:
                                type: string
                              description:
                                type: string
                              group:
                                type: string
                          barcode:
                            type: object
                            properties:
                              name:
                                type: string
                              label:
                                type: string
                              type:
                                type: string
                              description:
                                type: string
                              group:
                                type: string
                          price:
                            type: object
                            properties:
                              name:
                                type: string
                              label:
                                type: string
                              type:
                                type: string
                              description:
                                type: string
                              group:
                                type: string
                      available_sku_fields:
                        type: object
                        properties:
                          sku:
                            type: object
                            properties:
                              name:
                                type: string
                              label:
                                type: string
                              type:
                                type: string
                              description:
                                type: string
                              group:
                                type: string
                          name:
                            type: object
                            properties:
                              name:
                                type: string
                              label:
                                type: string
                              type:
                                type: string
                              description:
                                type: string
                              group:
                                type: string
                          barcode:
                            type: object
                            properties:
                              name:
                                type: string
                              label:
                                type: string
                              type:
                                type: string
                              description:
                                type: string
                              group:
                                type: string
                          price:
                            type: object
                            properties:
                              name:
                                type: string
                              label:
                                type: string
                              type:
                                type: string
                              description:
                                type: string
                              group:
                                type: string
                      default_mappings:
                        type: array
                        items:
                          type: object
                          properties:
                            listing_field:
                              type: string
                            sku_field:
                              type: string
                            parsers:
                              type: array
                      custom_mappings:
                        type: array
                        items:
                          type: object
                          properties:
                            listing_field:
                              type: string
                            sku_field:
                              type: string
                            parsers:
                              type: array
                      effective_mappings:
                        type: array
                        items:
                          type: object
                          properties:
                            listing_field:
                              type: string
                            sku_field:
                              type: string
                            parsers:
                              type: array
                example:
                  data:
                    integration_instance_id: 1
                    integration_name: Main Shopify Store
                    mappings:
                    - listing_field: sku
                      sku_field: sku
                      parsers: []
                    - listing_field: shopify_product_title
                      sku_field: name
                      parsers: []
                    - listing_field: barcode
                      sku_field: barcode
                      parsers: []
                    available_shopify_fields:
                      shopify_product_id:
                        name: shopify_product_id
                        label: Shopify Product ID
                        type: integer
                        description: Unique Shopify product identifier
                        group: Identifiers
                      shopify_variant_id:
                        name: shopify_variant_id
                        label: Shopify Variant ID
                        type: integer
                        description: Unique Shopify variant identifier
                        group: Identifiers
                      sku:
                        name: sku
                        label: SKU
                        type: string
                        description: Variant SKU as entered in Shopify
                        group: Product Details
                      barcode:
                        name: barcode
                        label: Barcode
                        type: string
                        description: Variant barcode (UPC/EAN/ISBN)
                        group: Product Details
                      price:
                        name: price
                        label: Price
                        type: decimal
                        description: Variant price
                        group: Pricing
                    available_sku_fields:
                      sku:
                        name: sku
                        label: SKU
                        type: string
                        description: SKU.io product SKU
                        group: Product
                      name:
                        name: name
                        label: Name
                        type: string
                        description: SKU.io product name
                        group: Product
                      barcode:
                        name: barcode
                        label: Barcode
                        type: string
                        description: SKU.io product barcode
                        group: Product
                      price:
                        name: price
                        label: Price
                        type: decimal
                        description: SKU.io default sell price
                        group: Pricing
                    default_mappings:
                    - listing_field: sku
                      sku_field: sku
                      parsers: []
                    - listing_field: shopify_product_title
                      sku_field: name
                      parsers: []
                    custom_mappings:
                    - listing_field: barcode
                      sku_field: barcode
                      parsers: []
                    effective_mappings:
                    - listing_field: sku
                      sku_field: sku
                      parsers: []
                    - listing_field: shopify_product_title
                      sku_field: name
                      parsers: []
                    - listing_field: barcode
                      sku_field: barcode
                      parsers: []
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shopify-integrationinstance-mappings
    put:
      tags:
      - Shopify
      summary: Update Field Mappings
      description: 'Replaces the custom field mappings for an integration instance.
        Each mapping pairs a Shopify field (listing_field) with a SKU.io field (sku_field)
        and an optional list of value parsers. Field names must come from List Available
        Mapping Fields.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Body fields:

        - mappings (array, required): objects with listing_field (string, required),
        sku_field (string, required), and parsers (array, required - may be empty).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                mappings:
                  type: array
                  items:
                    type: object
                    properties:
                      listing_field:
                        type: string
                      sku_field:
                        type: string
                      parsers:
                        type: array
              example:
                mappings:
                - listing_field: sku
                  sku_field: sku
                  parsers: []
                - listing_field: shopify_product_title
                  sku_field: name
                  parsers: []
                - listing_field: barcode
                  sku_field: barcode
                  parsers: []
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      integration_instance_id:
                        type: integer
                      integration_name:
                        type: string
                      mappings:
                        type: array
                        items:
                          type: object
                          properties:
                            listing_field:
                              type: string
                            sku_field:
                              type: string
                            parsers:
                              type: array
                      effective_mappings:
                        type: array
                        items:
                          type: object
                          properties:
                            listing_field:
                              type: string
                            sku_field:
                              type: string
                            parsers:
                              type: array
                  message:
                    type: string
                example:
                  data:
                    integration_instance_id: 1
                    integration_name: Main Shopify Store
                    mappings:
                    - listing_field: sku
                      sku_field: sku
                      parsers: []
                    - listing_field: shopify_product_title
                      sku_field: name
                      parsers: []
                    - listing_field: barcode
                      sku_field: barcode
                      parsers: []
                    effective_mappings:
                    - listing_field: sku
                      sku_field: sku
                      parsers: []
                    - listing_field: shopify_product_title
                      sku_field: name
                      parsers: []
                    - listing_field: barcode
                      sku_field: barcode
                      parsers: []
                  message: Field mappings updated successfully
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      mappings:
                        type: array
                        items:
                          type: string
                example:
                  message: The mappings field is required.
                  errors:
                    mappings:
                    - The mappings field is required.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: put-api-shopify-integrationinstance-mappings
  /api/shopify/{integrationInstance}/map-to-existing-skus:
    post:
      tags:
      - Shopify
      summary: Map Products to Existing SKUs
      description: 'Queues a background operation that links Shopify products to existing
        SKU.io products using the configured field mappings. No new products are created
        - only matches to products that already exist. The endpoint returns immediately
        with status "queued".


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Body - exactly one selection strategy is required:

        - ids (array of integers, max 1000): specific Shopify product IDs (SKU.io
        row IDs).

        - process_all (boolean): process every eligible product on the instance.

        - filters (object): server-side selection, e.g. {"unmapped_only": true, "created_after":
        "2024-01-01"}.


        Returns 400 if no strategy is given, if more than 1000 ids are sent, or if
        no field mappings are configured yet.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 101
                - 102
                - 103
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      integration_instance_id:
                        type: integer
                      message:
                        type: string
                      status:
                        type: string
                      selection_summary:
                        type: object
                        properties:
                          selection_type:
                            type: string
                          product_count:
                            type: integer
                          product_ids:
                            type: array
                            items:
                              type: integer
                example:
                  data:
                    integration_instance_id: 1
                    message: Processing 3 specific products - check queue status for
                      progress
                    status: queued
                    selection_summary:
                      selection_type: specific_products
                      product_count: 3
                      product_ids:
                      - 101
                      - 102
                      - 103
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                  message:
                    type: string
                  examples:
                    type: object
                    properties:
                      specific_products:
                        type: object
                        properties:
                          ids:
                            type: array
                            items:
                              type: integer
                      all_products:
                        type: object
                        properties:
                          process_all:
                            type: boolean
                      filtered_products:
                        type: object
                        properties:
                          filters:
                            type: object
                            properties:
                              unmapped_only:
                                type: boolean
                              created_after:
                                type: string
                example:
                  error: Invalid request parameters
                  message: Either "ids", "process_all", or "filters" must be specified
                  examples:
                    specific_products:
                      ids:
                      - 1
                      - 2
                      - 3
                    all_products:
                      process_all: true
                    filtered_products:
                      filters:
                        unmapped_only: true
                        created_after: '2024-01-01'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-shopify-integrationinstance-map-to-existing-skus
  /api/shopify/{integrationInstance}/create-products-from-mappings:
    post:
      tags:
      - Shopify
      summary: Create Products from Mappings
      description: 'Queues a background operation that creates new SKU.io products
        from unmapped Shopify products, populating fields according to the configured
        field mappings. The endpoint returns immediately with status "queued".


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Body - exactly one selection strategy is required:

        - ids (array of integers, max 1000): specific Shopify product IDs (SKU.io
        row IDs).

        - process_all (boolean): process every eligible product on the instance.

        - filters (object): server-side selection, e.g. {"unmapped_only": true, "created_after":
        "2024-01-01"}.


        Returns 400 if no strategy is given, if more than 1000 ids are sent, or if
        no field mappings are configured yet.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                filters:
                  type: object
                  properties:
                    unmapped_only:
                      type: boolean
                    created_after:
                      type: string
              example:
                filters:
                  unmapped_only: true
                  created_after: '2024-01-01'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      integration_instance_id:
                        type: integer
                      message:
                        type: string
                      status:
                        type: string
                      selection_summary:
                        type: object
                        properties:
                          selection_type:
                            type: string
                          filters:
                            type: object
                            properties:
                              unmapped_only:
                                type: boolean
                              created_after:
                                type: string
                example:
                  data:
                    integration_instance_id: 1
                    message: Processing filtered products - check queue status for
                      progress
                    status: queued
                    selection_summary:
                      selection_type: filtered_products
                      filters:
                        unmapped_only: true
                        created_after: '2024-01-01'
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                  message:
                    type: string
                example:
                  error: No field mappings found for this integration instance
                  message: Please configure field mappings before attempting to create
                    products
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-shopify-integrationinstance-create-products-from-mappings
  /api/shopify/{integrationInstance}/product-mappings/csv/download:
    get:
      tags:
      - Shopify
      summary: Download Product Mappings (CSV)
      description: 'Downloads every product mapping for the instance as a CSV file
        for bulk editing. Columns: shopify_variant_id, shopify_product_title, shopify_variant_title,
        price, shopify_sku, mapped_sku. Edit the mapped_sku column and re-upload via
        Upload Product Mappings (CSV); clearing mapped_sku unmaps the product.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        The response is a text/csv file download, not JSON. Returns 404 when the instance
        has no product mappings.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: text/csv
          content:
            text/plain:
              schema:
                type: string
                example: 'shopify_variant_id,shopify_product_title,shopify_variant_title,price,shopify_sku,mapped_sku

                  45123456789,Blue T-Shirt,M,24.95,TSHIRT-M-BLUE,TSHIRT-M-BLUE

                  45123456790,Blue T-Shirt,L,24.95,TSHIRT-L-BLUE,TSHIRT-L-BLUE

                  '
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shopify-integrationinstance-product-mappings-csv-download
  /api/shopify/{integrationInstance}/product-mappings/csv/upload:
    post:
      tags:
      - Shopify
      summary: Upload Product Mappings (CSV)
      description: 'Uploads a product mappings CSV (multipart/form-data) and applies
        it synchronously. Each row is keyed by shopify_variant_id (required). A non-empty
        mapped_sku links the Shopify product to that SKU.io product (creating or updating
        the listing); an empty mapped_sku removes the existing mapping. Optional listing_sku
        and price columns override the stored listing values.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Form fields:

        - file (file, required): CSV file, max 2MB, .csv or .txt.


        All rows are validated before anything is applied - if any row fails (unknown
        variant ID, unknown SKU), the whole upload is rejected with 422 and per-line
        errors.'
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                file:
                  type: string
                  description: CSV file with shopify_variant_id and mapped_sku columns
                    (max 2MB)
                  format: binary
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      integration_instance_id:
                        type: integer
                      integration_name:
                        type: string
                      total_processed:
                        type: integer
                      created_count:
                        type: integer
                      updated_count:
                        type: integer
                      deleted_count:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    integration_instance_id: 1
                    integration_name: Main Shopify Store
                    total_processed: 25
                    created_count: 10
                    updated_count: 12
                    deleted_count: 3
                  message: Product mappings processed successfully from CSV
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                  message:
                    type: string
                  errors:
                    type: array
                    items:
                      type: string
                example:
                  error: CSV validation failed
                  message: Please fix the following errors in your CSV file
                  errors:
                  - 'Line 3: Shopify product with variant ID 45999999999 not found'
                  - 'Line 7: SKU product with SKU ''UNKNOWN-SKU'' not found'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-shopify-integrationinstance-product-mappings-csv-upload
  /api/shopify/{integrationInstance}/locations:
    get:
      tags:
      - Shopify
      summary: List Locations
      description: 'Returns the shop''s locations. Note: this performs a live request
        to the Shopify Admin API on every call (it is not served from the local database),
        so responses reflect Shopify''s current state and count against Shopify API
        limits.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      locations:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: string
                            legacyResourceId:
                              type: string
                            name:
                              type: string
                            isActive:
                              type: boolean
                            address:
                              type: object
                              properties:
                                address1:
                                  type: string
                                city:
                                  type: string
                                provinceCode:
                                  type: string
                                countryCode:
                                  type: string
                                zip:
                                  type: string
                      success:
                        type: boolean
                example:
                  data:
                    locations:
                    - id: gid://shopify/Location/74469278
                      legacyResourceId: '74469278'
                      name: Main Warehouse
                      isActive: true
                      address:
                        address1: 500 Industrial Way
                        city: Reno
                        provinceCode: NV
                        countryCode: US
                        zip: '89502'
                    - id: gid://shopify/Location/74469279
                      legacyResourceId: '74469279'
                      name: Retail Store
                      isActive: true
                      address:
                        address1: 12 Market St
                        city: San Francisco
                        provinceCode: CA
                        countryCode: US
                        zip: '94105'
                    success: true
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shopify-integrationinstance-locations
    post:
      tags:
      - Shopify
      summary: Refresh Locations
      description: 'Fetches the shop''s locations live from the Shopify Admin API
        and returns them. Use this to re-pull locations after adding or renaming one
        in Shopify before assigning warehouse mappings.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      locations:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: string
                            legacyResourceId:
                              type: string
                            name:
                              type: string
                            isActive:
                              type: boolean
                            address:
                              type: object
                              properties:
                                address1:
                                  type: string
                                city:
                                  type: string
                                provinceCode:
                                  type: string
                                countryCode:
                                  type: string
                                zip:
                                  type: string
                      success:
                        type: boolean
                example:
                  data:
                    locations:
                    - id: gid://shopify/Location/74469278
                      legacyResourceId: '74469278'
                      name: Main Warehouse
                      isActive: true
                      address:
                        address1: 500 Industrial Way
                        city: Reno
                        provinceCode: NV
                        countryCode: US
                        zip: '89502'
                    - id: gid://shopify/Location/74469279
                      legacyResourceId: '74469279'
                      name: Retail Store
                      isActive: true
                      address:
                        address1: 12 Market St
                        city: San Francisco
                        provinceCode: CA
                        countryCode: US
                        zip: '94105'
                    success: true
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-shopify-integrationinstance-locations
  /api/shopify/{integrationInstance}/warehouse-location-mappings:
    get:
      tags:
      - Shopify
      summary: List Warehouse Location Mappings
      description: 'Lists every synced Shopify location with its current SKU.io warehouse
        mapping (warehouse_id is null for unmapped locations) plus full location address
        details. The meta block summarizes how many locations are mapped vs unmapped.
        These mappings drive fulfillment routing when use_location_mapping_for_new_orders
        is enabled on the integration.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        shopify_location_id:
                          type: integer
                        name:
                          type: string
                        is_active:
                          type: boolean
                        warehouse_id:
                          type: integer
                        warehouse_name:
                          type: string
                        address1:
                          type: string
                        address2:
                          type: string
                          nullable: true
                        city:
                          type: string
                        province:
                          type: string
                        province_code:
                          type: string
                        country:
                          type: string
                        country_code:
                          type: string
                        zip:
                          type: string
                        phone:
                          type: string
                        shopify_created_at:
                          type: string
                        shopify_updated_at:
                          type: string
                  meta:
                    type: object
                    properties:
                      total_locations:
                        type: integer
                      mapped_count:
                        type: integer
                      unmapped_count:
                        type: integer
                example:
                  success: true
                  data:
                  - shopify_location_id: 74469278
                    name: Main Warehouse
                    is_active: true
                    warehouse_id: 2
                    warehouse_name: Main Warehouse
                    address1: 500 Industrial Way
                    address2: null
                    city: Reno
                    province: Nevada
                    province_code: NV
                    country: United States
                    country_code: US
                    zip: '89502'
                    phone: +1 775 555 0101
                    shopify_created_at: '2023-08-01T10:00:00+00:00'
                    shopify_updated_at: '2025-05-01T09:30:00+00:00'
                  - shopify_location_id: 74469279
                    name: Retail Store
                    is_active: true
                    warehouse_id: null
                    warehouse_name: null
                    address1: 12 Market St
                    address2: null
                    city: San Francisco
                    province: California
                    province_code: CA
                    country: United States
                    country_code: US
                    zip: '94105'
                    phone: null
                    shopify_created_at: '2023-09-14T15:20:00+00:00'
                    shopify_updated_at: '2025-04-11T12:00:00+00:00'
                  meta:
                    total_locations: 2
                    mapped_count: 1
                    unmapped_count: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shopify-integrationinstance-warehouse-location-mappings
  /api/shopify/{integrationInstance}/warehouse-location-mappings/bulk-update:
    post:
      tags:
      - Shopify
      summary: Bulk Update Warehouse Location Mappings
      description: 'Sets or clears the SKU.io warehouse assigned to one or more Shopify
        locations in a single call. Send warehouse_id as null to clear a mapping.
        Each mapping is applied independently - the response reports per-location
        success or failure plus an overall summary.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Body fields:

        - mappings (array, required, min 1): objects with shopify_location_id (integer,
        required - the Shopify location''s numeric ID) and warehouse_id (integer or
        null - must be an existing warehouse).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                mappings:
                  type: array
                  items:
                    type: object
                    properties:
                      shopify_location_id:
                        type: integer
                      warehouse_id:
                        type: integer
              example:
                mappings:
                - shopify_location_id: 74469278
                  warehouse_id: 2
                - shopify_location_id: 74469279
                  warehouse_id: null
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      results:
                        type: array
                        items:
                          type: object
                          properties:
                            shopify_location_id:
                              type: integer
                            location_name:
                              type: string
                            success:
                              type: boolean
                            warehouse_id:
                              type: integer
                      summary:
                        type: object
                        properties:
                          total:
                            type: integer
                          successful:
                            type: integer
                          failed:
                            type: integer
                example:
                  success: true
                  message: Updated 2 mapping(s)
                  data:
                    results:
                    - shopify_location_id: 74469278
                      location_name: Main Warehouse
                      success: true
                      warehouse_id: 2
                    - shopify_location_id: 74469279
                      location_name: Retail Store
                      success: true
                      warehouse_id: null
                    summary:
                      total: 2
                      successful: 2
                      failed: 0
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      mappings:
                        type: array
                        items:
                          type: string
                example:
                  message: The mappings field is required.
                  errors:
                    mappings:
                    - The mappings field is required.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-shopify-integrationinstance-warehouse-location-mappings-bulk-update
  /api/shopify/{integrationInstance}/shipping-method-mappings:
    get:
      tags:
      - Shopify
      summary: List Shipping Method Mappings
      description: 'Lists the distinct shipping method values found on the instance''s
        synced Shopify orders together with their current SKU.io shipping method mapping
        (unmapped entries have a null shipping_method_id). The response also includes
        all active SKU.io shipping methods for building a mapping editor, and a meta
        summary of mapped vs unmapped counts.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        The values are read from the field selected by the instance''s shipping_method_field
        setting (title or code); pass the shipping_method_field query parameter to
        preview the list using the other field without saving the setting.'
      parameters:
      - name: shipping_method_field
        in: query
        schema:
          type: string
        description: 'Optional override of the stored setting for previewing: title
          or code'
        example: title
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      mappings:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            sales_channel_method:
                              type: string
                            shipping_method_id:
                              type: integer
                            shipping_method_name:
                              type: string
                      available_shipping_methods:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            full_name:
                              type: string
                      shipping_method_field:
                        type: string
                  meta:
                    type: object
                    properties:
                      sales_channel_id:
                        type: integer
                      total_mappings:
                        type: integer
                      mapped_count:
                        type: integer
                      unmapped_count:
                        type: integer
                example:
                  success: true
                  data:
                    mappings:
                    - id: 31
                      sales_channel_method: Express Shipping
                      shipping_method_id: 7
                      shipping_method_name: UPS Next Day Air
                    - id: null
                      sales_channel_method: Standard Shipping
                      shipping_method_id: null
                      shipping_method_name: null
                    available_shipping_methods:
                    - id: 7
                      name: Next Day Air
                      full_name: UPS Next Day Air
                    - id: 8
                      name: Ground
                      full_name: UPS Ground
                    shipping_method_field: title
                  meta:
                    sales_channel_id: 12
                    total_mappings: 2
                    mapped_count: 1
                    unmapped_count: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shopify-integrationinstance-shipping-method-mappings
  /api/shopify/{integrationInstance}/shipping-method-mappings/bulk-update:
    post:
      tags:
      - Shopify
      summary: Bulk Update Shipping Method Mappings
      description: 'Creates, updates, or removes shipping method mappings in bulk.
        Providing shipping_method_id maps the Shopify shipping method value to that
        SKU.io shipping method (upsert); sending null removes any existing mapping
        for that value. Each entry is processed independently with per-entry results.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Body fields:

        - mappings (array, required, min 1): objects with sales_channel_method (string,
        required - the shipping method value as it appears on Shopify orders), shipping_method_id
        (integer or null - must be an existing SKU.io shipping method), and id (integer,
        optional - existing mapping ID, informational).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                mappings:
                  type: array
                  items:
                    type: object
                    properties:
                      sales_channel_method:
                        type: string
                      shipping_method_id:
                        type: integer
              example:
                mappings:
                - sales_channel_method: Standard Shipping
                  shipping_method_id: 8
                - sales_channel_method: Economy
                  shipping_method_id: null
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      results:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            sales_channel_method:
                              type: string
                            success:
                              type: boolean
                            shipping_method_id:
                              type: integer
                            action:
                              type: string
                      summary:
                        type: object
                        properties:
                          total:
                            type: integer
                          successful:
                            type: integer
                          failed:
                            type: integer
                example:
                  success: true
                  message: Updated 2 mapping(s)
                  data:
                    results:
                    - id: 32
                      sales_channel_method: Standard Shipping
                      success: true
                      shipping_method_id: 8
                      action: mapped
                    - id: null
                      sales_channel_method: Economy
                      success: true
                      shipping_method_id: null
                      action: unmapped
                    summary:
                      total: 2
                      successful: 2
                      failed: 0
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-shopify-integrationinstance-shipping-method-mappings-bulk-update
  /api/shopify/{integrationInstance}/shipping-method-mappings/{mappingId}:
    delete:
      tags:
      - Shopify
      summary: Delete Shipping Method Mapping
      description: 'Removes a shipping method mapping by its ID. Orders imported afterwards
        with that Shopify shipping method value fall back to the default shipping
        method behavior.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: mappingId
        in: path
        schema:
          type: integer
        required: true
        example: '31'
        description: The mapping ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                example:
                  success: true
                  message: Shipping method mapping for 'Express Shipping' deleted
                    successfully
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                example:
                  success: false
                  message: Mapping not found
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: delete-api-shopify-integrationinstance-shipping-method-mappings-mappingid
  /api/shopify/{integrationInstance}/payment-method-mappings:
    get:
      tags:
      - Shopify
      summary: List Payment Method Mappings
      description: 'Lists the distinct payment gateways found on the instance''s synced
        Shopify order transactions together with their current SKU.io payment type
        mapping (unmapped entries have a null payment_type_id). Also returns all active
        SKU.io payment types and a meta summary of mapped vs unmapped counts. These
        mappings control which payment type is assigned to payments imported from
        Shopify.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      mappings:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            sales_channel_method:
                              type: string
                            formatted_gateway:
                              type: string
                            payment_type_id:
                              type: integer
                            payment_type_name:
                              type: string
                      available_payment_types:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                  meta:
                    type: object
                    properties:
                      sales_channel_id:
                        type: integer
                      total_mappings:
                        type: integer
                      mapped_count:
                        type: integer
                      unmapped_count:
                        type: integer
                example:
                  success: true
                  data:
                    mappings:
                    - id: 11
                      sales_channel_method: shopify_payments
                      formatted_gateway: Shopify Payments
                      payment_type_id: 3
                      payment_type_name: Credit Card
                    - id: null
                      sales_channel_method: paypal
                      formatted_gateway: PayPal
                      payment_type_id: null
                      payment_type_name: null
                    available_payment_types:
                    - id: 3
                      name: Credit Card
                    - id: 4
                      name: PayPal
                  meta:
                    sales_channel_id: 12
                    total_mappings: 2
                    mapped_count: 1
                    unmapped_count: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shopify-integrationinstance-payment-method-mappings
  /api/shopify/{integrationInstance}/payment-method-mappings/bulk-update:
    post:
      tags:
      - Shopify
      summary: Bulk Update Payment Method Mappings
      description: 'Creates, updates, or removes payment method mappings in bulk.
        Providing payment_type_id maps the Shopify gateway to that SKU.io payment
        type (upsert); sending null removes any existing mapping for that gateway.
        Each entry is processed independently with per-entry results.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Body fields:

        - mappings (array, required, min 1): objects with sales_channel_method (string,
        required - the gateway identifier from Shopify transactions, e.g. shopify_payments),
        payment_type_id (integer or null - must be an existing SKU.io payment type),
        and id (integer, optional - existing mapping ID, informational).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                mappings:
                  type: array
                  items:
                    type: object
                    properties:
                      sales_channel_method:
                        type: string
                      payment_type_id:
                        type: integer
              example:
                mappings:
                - sales_channel_method: paypal
                  payment_type_id: 4
                - sales_channel_method: gift_card
                  payment_type_id: null
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      results:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            sales_channel_method:
                              type: string
                            success:
                              type: boolean
                            payment_type_id:
                              type: integer
                            action:
                              type: string
                      summary:
                        type: object
                        properties:
                          total:
                            type: integer
                          successful:
                            type: integer
                          failed:
                            type: integer
                example:
                  success: true
                  message: Updated 2 mapping(s)
                  data:
                    results:
                    - id: 12
                      sales_channel_method: paypal
                      success: true
                      payment_type_id: 4
                      action: mapped
                    - id: null
                      sales_channel_method: gift_card
                      success: true
                      payment_type_id: null
                      action: unmapped
                    summary:
                      total: 2
                      successful: 2
                      failed: 0
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-shopify-integrationinstance-payment-method-mappings-bulk-update
  /api/shopify/{integrationInstance}/payment-method-mappings/{mappingId}:
    delete:
      tags:
      - Shopify
      summary: Delete Payment Method Mapping
      description: 'Removes a payment method mapping by its ID. Payments imported
        afterwards with that gateway fall back to the default payment type behavior.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: mappingId
        in: path
        schema:
          type: integer
        required: true
        example: '11'
        description: The mapping ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                example:
                  success: true
                  message: Payment method mapping for 'shopify_payments' deleted successfully
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                example:
                  success: false
                  message: Mapping not found
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: delete-api-shopify-integrationinstance-payment-method-mappings-mappingid
  /api/shopify/{integrationInstance}/webhooks/configurations:
    get:
      tags:
      - Shopify
      summary: List Webhook Configurations
      description: 'Lists every webhook topic SKU.io can subscribe to on the connected
        shop, with its human-readable label and description, the callback URL SKU.io
        registers, whether the subscription is currently enabled, and the Shopify
        webhook ID when active.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      configurations:
                        type: array
                        items:
                          type: object
                          properties:
                            topic:
                              type: string
                            label:
                              type: string
                            description:
                              type: string
                            callback_url:
                              type: string
                            is_enabled:
                              type: boolean
                            shopify_webhook_id:
                              type: string
                            created_at:
                              type: string
                example:
                  data:
                    configurations:
                    - topic: orders/create
                      label: Orders Create
                      description: Fires when a new order is created in Shopify
                      callback_url: https://acme.sku.io/api/shopify/webhook/orders-create/wt_9f8e7d6c
                      is_enabled: true
                      shopify_webhook_id: '988771122'
                      created_at: '2025-05-01T12:00:00.000000Z'
                    - topic: orders/updated
                      label: Orders Updated
                      description: Fires when an order is updated in Shopify
                      callback_url: https://acme.sku.io/api/shopify/webhook/orders-updated/wt_9f8e7d6c
                      is_enabled: false
                      shopify_webhook_id: null
                      created_at: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shopify-integrationinstance-webhooks-configurations
  /api/shopify/{integrationInstance}/webhooks/configurations/{topic}/enable:
    post:
      tags:
      - Shopify
      summary: Enable Webhook Topic
      description: 'Registers a webhook subscription for the given topic on the connected
        shop (live call to the Shopify Admin API). If the subscription already exists
        the call succeeds without creating a duplicate.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Path parameter: topic uses triple dashes in place of slashes, e.g. orders---create
        for the orders/create topic.'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: topic
        in: path
        schema:
          type: string
        required: true
        description: Webhook topic with / encoded as ---
        example: orders---create
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      success:
                        type: boolean
                      message:
                        type: string
                      webhook:
                        type: object
                        properties:
                          id:
                            type: integer
                          topic:
                            type: string
                          shopify_webhook_id:
                            type: string
                      created:
                        type: boolean
                  message:
                    type: string
                example:
                  data:
                    success: true
                    message: Webhook enabled successfully
                    webhook:
                      id: 15
                      topic: orders/create
                      shopify_webhook_id: '988771122'
                    created: true
                  message: Webhook enabled successfully
        '500':
          description: Internal Server Error
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                example:
                  success: false
                  message: 'Failed to create webhook: Invalid topic'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-shopify-integrationinstance-webhooks-configurations-topic-enable
  /api/shopify/{integrationInstance}/webhooks/configurations/{topic}/disable:
    post:
      tags:
      - Shopify
      summary: Disable Webhook Topic
      description: 'Removes the webhook subscription for the given topic from the
        connected shop (live call to the Shopify Admin API). Succeeds even if the
        subscription was already removed on the Shopify side.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Path parameter: topic uses triple dashes in place of slashes, e.g. orders---create
        for the orders/create topic.'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: topic
        in: path
        schema:
          type: string
        required: true
        description: Webhook topic with / encoded as ---
        example: orders---create
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      success:
                        type: boolean
                      message:
                        type: string
                      deleted:
                        type: boolean
                  message:
                    type: string
                example:
                  data:
                    success: true
                    message: Webhook disabled successfully
                    deleted: true
                  message: Webhook disabled successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-shopify-integrationinstance-webhooks-configurations-topic-disable
  /api/shopify/{integrationInstance}/access-scopes:
    get:
      tags:
      - Shopify
      summary: List Access Scopes
      description: 'List the OAuth access scopes granted to this Shopify app installation,
        sorted alphabetically by handle. Sourced from the Shopify Admin GraphQL `currentAppInstallation.accessScopes`
        field.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Returns 500 when the underlying Shopify GraphQL call returns errors.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Shopify integration instance ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      scopes:
                        type: array
                        items:
                          type: object
                          properties:
                            handle:
                              type: string
                            description:
                              type: string
                      total:
                        type: integer
                example:
                  success: true
                  data:
                    scopes:
                    - handle: read_orders
                      description: Access to view orders
                    - handle: read_products
                      description: Access to view products and variants
                    - handle: read_returns
                      description: Access to view returns
                    total: 3
        '500':
          description: Internal Server Error
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                  errors:
                    type: array
                    items:
                      type: object
                      properties:
                        message:
                          type: string
                example:
                  success: false
                  message: Failed to retrieve access scopes
                  errors:
                  - message: Access denied for currentAppInstallation
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shopify-integrationinstance-access-scopes
  /api/shopify/{integrationInstance}/shop-plan:
    get:
      tags:
      - Shopify
      summary: Get Shop Plan
      description: 'Fetch the shop plan from Shopify and return whether the store
        has Customer PII access via GraphQL. Basic/Starter plans do not have PII access
        — when false, customer email/addresses are excluded from order syncs.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Returns 500 if the Shopify GraphQL call fails.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Shopify integration instance ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      shop_name:
                        type: string
                      plan:
                        type: string
                      is_partner_development:
                        type: boolean
                      is_shopify_plus:
                        type: boolean
                      has_customer_pii_access:
                        type: boolean
                example:
                  success: true
                  data:
                    shop_name: My Store
                    plan: Shopify Plus
                    is_partner_development: false
                    is_shopify_plus: true
                    has_customer_pii_access: true
        '500':
          description: Internal Server Error
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                example:
                  success: false
                  message: 'Failed to retrieve shop plan: GraphQL error'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shopify-integrationinstance-shop-plan
  /api/shopify/{integrationInstance}/returns-access:
    put:
      tags:
      - Shopify
      summary: Set Returns Access
      description: 'Toggle whether the Shopify GraphQL `returns` field should be queried
        when this integration instance syncs orders. Set to `false` when the app installation
        lacks the `read_returns` permission scope — Shopify rejects the field with
        "Access denied for returns field" otherwise. The system also auto-flips this
        to `false` the first time that error is observed.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Request body:

        - has_returns_access (required, boolean): true to include returns in order
        syncs, false to exclude them.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                has_returns_access:
                  type: boolean
              example:
                has_returns_access: false
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Shopify integration instance ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      has_returns_access:
                        type: boolean
                example:
                  success: true
                  data:
                    has_returns_access: false
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      has_returns_access:
                        type: array
                        items:
                          type: string
                example:
                  message: The has returns access field is required.
                  errors:
                    has_returns_access:
                    - The has returns access field is required.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: put-api-shopify-integrationinstance-returns-access
  /api/shopify/{integrationInstance}/customer-pii-access/resume:
    post:
      tags:
      - Shopify
      summary: Resume Customer PII Access
      description: 'Clear the customer PII access blocked state for this Shopify integration
        instance and re-enable automatic order syncing. Call this after the Shopify
        store administrator has granted the app access to protected customer data
        (Shopify Partner Dashboard -> API access -> Protected customer data). The
        blocked state is set automatically when Shopify rejects an orders query with
        "This app is not approved to use the [field] field" (protected customer data),
        which also disables automatic sync - orders without customer PII are unusable
        in SKU.io.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        No request body. Returns the updated flags:

        - customer_pii_access_blocked (boolean): false after resuming

        - is_automatic_sync_enabled (boolean): true after resuming'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Shopify integration instance ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      customer_pii_access_blocked:
                        type: boolean
                      is_automatic_sync_enabled:
                        type: boolean
                example:
                  success: true
                  data:
                    customer_pii_access_blocked: false
                    is_automatic_sync_enabled: true
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-shopify-integrationinstance-customer-pii-access-resume
  /api/shopify/{integrationInstance}/access-token/resume:
    post:
      tags:
      - Shopify
      summary: Resume Invalid Access Token
      description: 'Clear the invalid access token state for this Shopify integration
        instance and re-enable automatic syncing. Call this after the Shopify app
        has been reauthorized and a fresh access token has been issued (e.g. the app
        was reinstalled or the token was rotated). The invalid state is set automatically
        when Shopify rejects an API call with 401 "Invalid API key or access token
        (unrecognized login or wrong password)", which also disables automatic sync
        to stop the failed-job retry storm.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        No request body. Returns the updated flags:

        - access_token_invalid (boolean): false after resuming

        - is_automatic_sync_enabled (boolean): true after resuming'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Shopify integration instance ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      access_token_invalid:
                        type: boolean
                      is_automatic_sync_enabled:
                        type: boolean
                example:
                  success: true
                  data:
                    access_token_invalid: false
                    is_automatic_sync_enabled: true
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-shopify-integrationinstance-access-token-resume
  /api/shopify/{integrationInstance}/payouts:
    get:
      tags:
      - Shopify
      summary: List Payouts
      description: 'Returns a paginated list of Shopify Payments payouts synced for
        the integration instance. Each payout includes the settlement amount, a normalized
        summary split of charges, refunds, and adjustments (gross and fee portions),
        the accounting status, and the number of balance-transaction lines.


        Authentication: Requires Bearer token.


        Filterable columns: status, currency, accounting_status (text), amount (numeric),
        payout_date (date), created_at (datetime). filter[search] matches the payout
        ID and currency.


        Filtering: pass filter[column]=value for an exact match, or filter[column.operator]=value
        with operators such as contains, does_not_contain, is, is_not, is_one_of,
        starts_with, ends_with, is_empty, is_not_empty (text), greater_than, less_than,
        greater_than_or_equal, less_than_or_equal, between (numeric), and is, is_not,
        before, after, on_or_before, on_or_after, between, today, yesterday, past_week,
        past_month, past_year, days_ago, past_days (date/datetime). Complex AND/OR
        trees can be sent as a base64-encoded JSON tree in the filter_groups parameter.


        Allowed sorts: id, legacy_resource_id, payout_date, amount, status, accounting_status
        (prefix with - for descending; default -payout_date). Pagination defaults
        to 10 per page.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Shopify integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        legacy_resource_id:
                          type: string
                        payout_date:
                          type: string
                        status:
                          type: string
                        currency:
                          type: string
                        amount:
                          type: number
                        summary:
                          type: object
                          properties:
                            charges_gross:
                              type: number
                            charges_fee:
                              type: number
                            refunds_gross:
                              type: integer
                            refunds_fee:
                              type: number
                            adjustments_gross:
                              type: number
                            adjustments_fee:
                              type: integer
                        accounting_status:
                          type: string
                        balance_transaction_count:
                          type: integer
                        shopify_created_at:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  next_page_url:
                    type: string
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 12
                    legacy_resource_id: '87642309854'
                    payout_date: '2026-07-10'
                    status: paid
                    currency: USD
                    amount: 1842.55
                    summary:
                      charges_gross: 2010.4
                      charges_fee: 58.3
                      refunds_gross: -95
                      refunds_fee: -2.85
                      adjustments_gross: -11.7
                      adjustments_fee: 0
                    accounting_status: pending
                    balance_transaction_count: 46
                    shopify_created_at: '2026-07-10T04:02:11+00:00'
                    created_at: '2026-07-10T06:15:42+00:00'
                    updated_at: '2026-07-11T06:15:40+00:00'
                  first_page_url: '{{protocol}}://{{domain}}/api/shopify/1/payouts?page=1'
                  from: 1
                  last_page: 3
                  last_page_url: '{{protocol}}://{{domain}}/api/shopify/1/payouts?page=3'
                  next_page_url: '{{protocol}}://{{domain}}/api/shopify/1/payouts?page=2'
                  path: '{{protocol}}://{{domain}}/api/shopify/1/payouts'
                  per_page: 10
                  prev_page_url: null
                  to: 10
                  total: 27
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shopify-integrationinstance-payouts
  /api/shopify/{integrationInstance}/payouts/filter-options:
    get:
      tags:
      - Shopify
      summary: Get Payout Filter Options
      description: 'Returns the available filter values for the payouts list: every
        payout status and accounting status the system recognises, plus the settlement
        currencies present in the synced payouts for the integration instance.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Shopify integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      statuses:
                        type: array
                        items:
                          type: string
                      accounting_statuses:
                        type: array
                        items:
                          type: string
                      currencies:
                        type: array
                        items:
                          type: string
                example:
                  data:
                    statuses:
                    - scheduled
                    - in_transit
                    - paid
                    - failed
                    - canceled
                    accounting_statuses:
                    - pending
                    - ready
                    - posted
                    - held
                    - error
                    currencies:
                    - CAD
                    - USD
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shopify-integrationinstance-payouts-filter-options
  /api/shopify/{integrationInstance}/payouts/sync:
    post:
      tags:
      - Shopify
      summary: Sync Payouts
      description: 'Queues a background sync that imports Shopify Payments payouts
        and their transaction lines from eBay for the integration instance. Returns
        a tracked_job_log_id that can be used to monitor the progress of the sync.


        The request body is optional. With no body, the sync runs the default incremental
        (cursor-based) window. Supply mode to control the range: latest (incremental,
        default), from_start_date (from the instance start date to now), date_range
        (bounded by date_from/date_to), or all (full backfill). date_from and date_to
        are Y-m-d dates and apply when mode is date_range (date_to must be on or after
        date_from).


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                mode:
                  type: string
                date_from:
                  type: string
                date_to:
                  type: string
              example:
                mode: date_range
                date_from: '2026-06-01'
                date_to: '2026-06-30'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Shopify integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 4431
                  message: Payout sync job has been queued
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-shopify-integrationinstance-payouts-sync
  /api/shopify/{integrationInstance}/payouts/{payout}:
    get:
      tags:
      - Shopify
      summary: Get Payout
      description: 'Returns the full detail of a single payout, including the raw
        Shopify summary breakdown, receipt totals, and every balance-transaction line
        with its linked local order and payment transaction where resolved. Returns
        403 if the payout does not belong to the integration instance.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Shopify integration instance ID
        example: '1'
      - name: payout
        in: path
        schema:
          type: integer
        required: true
        description: Payout ID
        example: '12'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      legacy_resource_id:
                        type: string
                      payout_date:
                        type: string
                      status:
                        type: string
                      currency:
                        type: string
                      amount:
                        type: number
                      summary:
                        type: object
                        properties:
                          charges_gross:
                            type: number
                          charges_fee:
                            type: number
                          refunds_gross:
                            type: integer
                          refunds_fee:
                            type: number
                          adjustments_gross:
                            type: number
                          adjustments_fee:
                            type: integer
                      summary_json:
                        type: object
                        properties:
                          charges_gross:
                            type: number
                          charges_fee:
                            type: number
                          refunds_fee_gross:
                            type: integer
                          refunds_fee:
                            type: number
                          adjustments_gross:
                            type: number
                          adjustments_fee:
                            type: integer
                      accounting_status:
                        type: string
                      base_currency_rate:
                        type: string
                        nullable: true
                      receipt_json:
                        type: string
                        nullable: true
                      shopify_created_at:
                        type: string
                      shopify_updated_at:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      balance_transactions:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            legacy_resource_id:
                              type: string
                            shopify_payout_id:
                              type: integer
                            type:
                              type: string
                            financial_code:
                              type: string
                            amount:
                              type: number
                            fee:
                              type: number
                            net:
                              type: number
                            source_type:
                              type: string
                            source_order_id:
                              type: string
                            adjustment_reason:
                              type: string
                              nullable: true
                            shopify_order_transaction_id:
                              type: integer
                            shopify_order_id:
                              type: integer
                            order_transaction:
                              type: object
                              properties:
                                id:
                                  type: integer
                                legacy_resource_id:
                                  type: integer
                                kind:
                                  type: string
                                status:
                                  type: string
                                amount:
                                  type: number
                                gateway:
                                  type: string
                            order:
                              type: object
                              properties:
                                id:
                                  type: integer
                                legacy_resource_id:
                                  type: integer
                                name:
                                  type: string
                                currency:
                                  type: string
                            created_at:
                              type: string
                            updated_at:
                              type: string
                      balance_transaction_count:
                        type: integer
                      integration_instance:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          myshopify_domain:
                            type: string
                example:
                  data:
                    id: 12
                    legacy_resource_id: '87642309854'
                    payout_date: '2026-07-10'
                    status: paid
                    currency: USD
                    amount: 1842.55
                    summary:
                      charges_gross: 2010.4
                      charges_fee: 58.3
                      refunds_gross: -95
                      refunds_fee: -2.85
                      adjustments_gross: -11.7
                      adjustments_fee: 0
                    summary_json:
                      charges_gross: 2010.4
                      charges_fee: 58.3
                      refunds_fee_gross: -95
                      refunds_fee: -2.85
                      adjustments_gross: -11.7
                      adjustments_fee: 0
                    accounting_status: pending
                    base_currency_rate: null
                    receipt_json: null
                    shopify_created_at: '2026-07-10T04:02:11+00:00'
                    shopify_updated_at: '2026-07-10T09:30:00+00:00'
                    created_at: '2026-07-10T06:15:42+00:00'
                    updated_at: '2026-07-11T06:15:40+00:00'
                    balance_transactions:
                    - id: 501
                      legacy_resource_id: '99120833411'
                      shopify_payout_id: 12
                      type: charge
                      financial_code: 'charge: sale'
                      amount: 129.99
                      fee: 4.07
                      net: 125.92
                      source_type: charge
                      source_order_id: '6531194880233'
                      adjustment_reason: null
                      shopify_order_transaction_id: 3120
                      shopify_order_id: 845
                      order_transaction:
                        id: 3120
                        legacy_resource_id: 7714120990001
                        kind: sale
                        status: success
                        amount: 129.99
                        gateway: shopify_payments
                      order:
                        id: 845
                        legacy_resource_id: 6531194880233
                        name: '#1284'
                        currency: USD
                      created_at: '2026-07-10T06:15:43+00:00'
                      updated_at: '2026-07-10T06:15:43+00:00'
                    - id: 502
                      legacy_resource_id: '99120833412'
                      shopify_payout_id: 12
                      type: adjustment
                      financial_code: 'adjustment: chargeback'
                      amount: -95
                      fee: 15
                      net: -110
                      source_type: dispute
                      source_order_id: null
                      adjustment_reason: chargeback
                      shopify_order_transaction_id: null
                      shopify_order_id: null
                      created_at: '2026-07-10T06:15:43+00:00'
                      updated_at: '2026-07-10T06:15:43+00:00'
                    balance_transaction_count: 2
                    integration_instance:
                      id: 1
                      name: My Shopify Store
                      myshopify_domain: my-store.myshopify.com
        '403':
          description: Forbidden
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: Payout does not belong to this integration instance
        '429': *id001
        '401': *id002
        '404': *id004
      operationId: get-api-shopify-integrationinstance-payouts-payout
  /api/shopify/{integrationInstance}/balance-transactions:
    get:
      tags:
      - Shopify
      summary: List Balance Transactions
      description: 'Returns a paginated list of Shopify Payments balance transaction
        lines across every payout synced for the integration instance — the line-level
        detail behind the payout summaries. Each line includes its type, financial
        code, amount, fee, net, source type, source order ID, adjustment reason, and
        cross-link blocks for the parent payout and (when matched) the Shopify order.


        Authentication: Requires Bearer token.


        Filters: filter[search] matches the internal ID, balance transaction ID, source
        order ID, financial code, type, or linked Shopify order (Shopify order ID
        or internal order ID). filter[financial_code], filter[type], filter[shopify_payout_id],
        and filter[id] are exact-match filters.


        Allowed sorts: id, amount, created_at (prefix with - for descending; default
        -id). Pagination defaults to 15 per page.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Shopify integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        legacy_resource_id:
                          type: string
                        shopify_payout_id:
                          type: integer
                        type:
                          type: string
                        financial_code:
                          type: string
                        amount:
                          type: number
                        fee:
                          type: number
                        net:
                          type: number
                        source_type:
                          type: string
                        source_order_id:
                          type: string
                        adjustment_reason:
                          type: string
                          nullable: true
                        shopify_order_transaction_id:
                          type: integer
                        shopify_order_id:
                          type: integer
                        payout:
                          type: object
                          properties:
                            shopify_payout_id:
                              type: integer
                            legacy_resource_id:
                              type: string
                            payout_date:
                              type: string
                            link_reference:
                              type: string
                            link_type_label:
                              type: string
                            link_id:
                              type: integer
                            link_route:
                              type: string
                        order:
                          type: object
                          properties:
                            id:
                              type: integer
                            legacy_resource_id:
                              type: string
                            name:
                              type: string
                            currency:
                              type: string
                            link_reference:
                              type: string
                            link_type_label:
                              type: string
                            link_id:
                              type: integer
                            link_route:
                              type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  next_page_url:
                    type: string
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 4402
                    legacy_resource_id: '774829001'
                    shopify_payout_id: 31
                    type: charge
                    financial_code: 'charge: charge'
                    amount: 128.4
                    fee: 4.02
                    net: 124.38
                    source_type: charge
                    source_order_id: '5231098442'
                    adjustment_reason: null
                    shopify_order_transaction_id: 660123
                    shopify_order_id: 8890
                    payout:
                      shopify_payout_id: 31
                      legacy_resource_id: '88123456'
                      payout_date: '2026-07-12'
                      link_reference: '88123456'
                      link_type_label: Shopify Payout
                      link_id: 31
                      link_route: /integrations/shopify/finance/payout/31
                    order:
                      id: 8890
                      legacy_resource_id: '5231098442'
                      name: '#1042'
                      currency: USD
                      link_reference: '#1042'
                      link_type_label: Shopify Order
                      link_id: 8890
                      link_route: /integrations/shopify/orders/8890
                    created_at: '2026-07-12T05:41:20+00:00'
                    updated_at: '2026-07-12T05:41:20+00:00'
                  first_page_url: '{{protocol}}://{{domain}}/api/shopify/1/balance-transactions?page=1'
                  from: 1
                  last_page: 4
                  last_page_url: '{{protocol}}://{{domain}}/api/shopify/1/balance-transactions?page=4'
                  next_page_url: '{{protocol}}://{{domain}}/api/shopify/1/balance-transactions?page=2'
                  path: '{{protocol}}://{{domain}}/api/shopify/1/balance-transactions'
                  per_page: 15
                  prev_page_url: null
                  to: 15
                  total: 53
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shopify-integrationinstance-balance-transactions
  /api/shopify/{integrationInstance}/balance-transactions/filter-options:
    get:
      tags:
      - Shopify
      summary: Get Balance Transaction Filter Options
      description: 'Returns the distinct filter values present in the synced balance
        transactions for the integration instance: every balance-transaction type
        and every financial code, so a client can populate the balance-transaction
        filters.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Shopify integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      types:
                        type: array
                        items:
                          type: string
                      financial_codes:
                        type: array
                        items:
                          type: string
                example:
                  data:
                    types:
                    - adjustment
                    - charge
                    - dispute
                    - fee
                    - refund
                    financial_codes:
                    - 'adjustment: adjustment'
                    - 'charge: charge'
                    - 'refund: refund'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shopify-integrationinstance-balance-transactions-filter-options
  /api/shopify/payout-mapping-groups:
    get:
      tags:
      - Shopify
      summary: List Global Payout Mapping Groups
      description: 'Returns every global (workspace-wide) payout mapping group, ordered
        by sort order. Global groups apply to all Shopify integration instances unless
        an instance defines its own groups. If no global groups exist yet, the two
        defaults (Shopify Sales as an invoice group and Shopify Fees as a bill group)
        are created and returned.


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: string
                          nullable: true
                        name:
                          type: string
                        document_type:
                          type: string
                        sort_order:
                          type: integer
                        mappings_count:
                          type: integer
                        created_at:
                          type: string
                        updated_at:
                          type: string
                example:
                  data:
                  - id: 1
                    integration_instance_id: null
                    name: Shopify Sales
                    document_type: invoice
                    sort_order: 0
                    mappings_count: 9
                    created_at: '2026-07-17T09:00:00.000000Z'
                    updated_at: '2026-07-17T09:00:00.000000Z'
                  - id: 2
                    integration_instance_id: null
                    name: Shopify Fees
                    document_type: bill
                    sort_order: 1
                    mappings_count: 4
                    created_at: '2026-07-17T09:00:00.000000Z'
                    updated_at: '2026-07-17T09:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-shopify-payout-mapping-groups
    post:
      tags:
      - Shopify
      summary: Create Global Payout Mapping Group
      description: 'Creates a global payout mapping group that applies to every Shopify
        integration instance. Type mappings assigned to the group are combined into
        a single financial document of the group''s document type when a payout is
        posted.


        Authentication: Requires Bearer token.


        Request body:

        - name (required, string, max 255): display name for the group.

        - document_type (required, string): financial document the group posts to;
        one of invoice, bill.

        - sort_order (optional, integer, min 0): position of the group in ordered
        listings.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                document_type:
                  type: string
                sort_order:
                  type: integer
              example:
                name: Marketplace Fees
                document_type: bill
                sort_order: 2
      parameters: []
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: integer
                  integration_instance_id:
                    type: string
                    nullable: true
                  name:
                    type: string
                  document_type:
                    type: string
                  sort_order:
                    type: integer
                  created_at:
                    type: string
                  updated_at:
                    type: string
                example:
                  id: 3
                  integration_instance_id: null
                  name: Marketplace Fees
                  document_type: bill
                  sort_order: 2
                  created_at: '2026-07-17T11:20:00.000000Z'
                  updated_at: '2026-07-17T11:20:00.000000Z'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      name:
                        type: array
                        items:
                          type: string
                      document_type:
                        type: array
                        items:
                          type: string
                example:
                  message: A document type (invoice or bill) is required.
                  errors:
                    name:
                    - The name field is required.
                    document_type:
                    - A document type (invoice or bill) is required.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-shopify-payout-mapping-groups
  /api/shopify/payout-mapping-groups/reorder:
    post:
      tags:
      - Shopify
      summary: Reorder Global Payout Mapping Groups
      description: 'Reorders the global payout mapping groups. Pass the full list
        of global group IDs in the desired order; each group''s sort order is updated
        to match its position in the list.


        Authentication: Requires Bearer token.


        Request body:

        - ids (required, array of integers, min 1): mapping group IDs in the desired
        display order. Each ID must reference an existing payout mapping group.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 2
                - 1
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Groups reordered successfully.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      ids:
                        type: array
                        items:
                          type: string
                example:
                  message: At least one mapping group id is required to reorder.
                  errors:
                    ids:
                    - At least one mapping group id is required to reorder.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-shopify-payout-mapping-groups-reorder
  /api/shopify/payout-mapping-groups/{payoutMappingGroup}:
    put:
      tags:
      - Shopify
      summary: Update Global Payout Mapping Group
      description: 'Updates the name, document type, or sort order of a global payout
        mapping group.


        Authentication: Requires Bearer token.


        Request body:

        - name (required, string, max 255): display name for the group.

        - document_type (required, string): financial document the group posts to;
        one of invoice, bill.

        - sort_order (optional, integer, min 0): position of the group in ordered
        listings.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                document_type:
                  type: string
                sort_order:
                  type: integer
              example:
                name: Shopify Sales - US
                document_type: invoice
                sort_order: 0
      parameters:
      - name: payoutMappingGroup
        in: path
        schema:
          type: integer
        required: true
        description: Payout mapping group ID
        example: '5'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: integer
                  integration_instance_id:
                    type: string
                    nullable: true
                  name:
                    type: string
                  document_type:
                    type: string
                  sort_order:
                    type: integer
                  created_at:
                    type: string
                  updated_at:
                    type: string
                example:
                  id: 1
                  integration_instance_id: null
                  name: Shopify Sales - US
                  document_type: invoice
                  sort_order: 0
                  created_at: '2026-07-17T09:00:00.000000Z'
                  updated_at: '2026-07-17T11:45:00.000000Z'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      name:
                        type: array
                        items:
                          type: string
                      document_type:
                        type: array
                        items:
                          type: string
                example:
                  message: A document type (invoice or bill) is required.
                  errors:
                    name:
                    - The name field is required.
                    document_type:
                    - A document type (invoice or bill) is required.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: put-api-shopify-payout-mapping-groups-payoutmappinggroup
    delete:
      tags:
      - Shopify
      summary: Delete Global Payout Mapping Group
      description: 'Deletes a global payout mapping group. Type mappings that referenced
        the group are kept but left without a group assignment.


        Authentication: Requires Bearer token.'
      parameters:
      - name: payoutMappingGroup
        in: path
        schema:
          type: integer
        required: true
        description: Payout mapping group ID
        example: '5'
      responses:
        '204':
          description: No Content
          content:
            application/json:
              schema:
                type: object
                properties: {}
                example: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-shopify-payout-mapping-groups-payoutmappinggroup
  /api/shopify/{integrationInstance}/payout-mapping-groups:
    get:
      tags:
      - Shopify
      summary: List Payout Mapping Groups
      description: 'Returns the payout mapping groups visible to the integration instance:
        the instance''s own groups first, followed by the global groups. If no global
        groups exist yet, the two defaults (Shopify Sales as an invoice group and
        Shopify Fees as a bill group) are created first.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Shopify integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        name:
                          type: string
                        document_type:
                          type: string
                        sort_order:
                          type: integer
                        mappings_count:
                          type: integer
                        created_at:
                          type: string
                        updated_at:
                          type: string
                example:
                  data:
                  - id: 5
                    integration_instance_id: 1
                    name: US Store Adjustments
                    document_type: bill
                    sort_order: 0
                    mappings_count: 2
                    created_at: '2026-07-17T10:12:00.000000Z'
                    updated_at: '2026-07-17T10:12:00.000000Z'
                  - id: 1
                    integration_instance_id: null
                    name: Shopify Sales
                    document_type: invoice
                    sort_order: 0
                    mappings_count: 9
                    created_at: '2026-07-17T09:00:00.000000Z'
                    updated_at: '2026-07-17T09:00:00.000000Z'
                  - id: 2
                    integration_instance_id: null
                    name: Shopify Fees
                    document_type: bill
                    sort_order: 1
                    mappings_count: 4
                    created_at: '2026-07-17T09:00:00.000000Z'
                    updated_at: '2026-07-17T09:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shopify-integrationinstance-payout-mapping-groups
    post:
      tags:
      - Shopify
      summary: Create Payout Mapping Group
      description: 'Creates a payout mapping group scoped to the integration instance.
        Instance groups are listed ahead of the global defaults and can be used to
        separate the instance''s payout lines into their own financial documents.


        Authentication: Requires Bearer token.


        Request body:

        - name (required, string, max 255): display name for the group.

        - document_type (required, string): financial document the group posts to;
        one of invoice, bill.

        - sort_order (optional, integer, min 0): position of the group in ordered
        listings.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                document_type:
                  type: string
                sort_order:
                  type: integer
              example:
                name: Marketplace Fees
                document_type: bill
                sort_order: 2
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Shopify integration instance ID
        example: '1'
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: integer
                  integration_instance_id:
                    type: integer
                  name:
                    type: string
                  document_type:
                    type: string
                  sort_order:
                    type: integer
                  created_at:
                    type: string
                  updated_at:
                    type: string
                example:
                  id: 6
                  integration_instance_id: 1
                  name: Marketplace Fees
                  document_type: bill
                  sort_order: 2
                  created_at: '2026-07-17T11:20:00.000000Z'
                  updated_at: '2026-07-17T11:20:00.000000Z'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      name:
                        type: array
                        items:
                          type: string
                      document_type:
                        type: array
                        items:
                          type: string
                example:
                  message: A document type (invoice or bill) is required.
                  errors:
                    name:
                    - The name field is required.
                    document_type:
                    - A document type (invoice or bill) is required.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-shopify-integrationinstance-payout-mapping-groups
  /api/shopify/{integrationInstance}/payout-mapping-groups/reorder:
    post:
      tags:
      - Shopify
      summary: Reorder Payout Mapping Groups
      description: 'Reorders the payout mapping groups scoped to the integration instance.
        Pass the full list of the instance''s group IDs in the desired order; each
        group''s sort order is updated to match its position in the list. Global groups
        are not affected.


        Authentication: Requires Bearer token.


        Request body:

        - ids (required, array of integers, min 1): mapping group IDs in the desired
        display order. Each ID must reference an existing payout mapping group.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 6
                - 5
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Shopify integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Groups reordered successfully.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      ids:
                        type: array
                        items:
                          type: string
                example:
                  message: At least one mapping group id is required to reorder.
                  errors:
                    ids:
                    - At least one mapping group id is required to reorder.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-shopify-integrationinstance-payout-mapping-groups-reorder
  /api/shopify/{integrationInstance}/payout-mapping-groups/{payoutMappingGroup}:
    put:
      tags:
      - Shopify
      summary: Update Payout Mapping Group
      description: 'Updates the name, document type, or sort order of a payout mapping
        group scoped to the integration instance.


        Authentication: Requires Bearer token.


        Request body:

        - name (required, string, max 255): display name for the group.

        - document_type (required, string): financial document the group posts to;
        one of invoice, bill.

        - sort_order (optional, integer, min 0): position of the group in ordered
        listings.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                document_type:
                  type: string
                sort_order:
                  type: integer
              example:
                name: Shopify Sales - US
                document_type: invoice
                sort_order: 0
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Shopify integration instance ID
        example: '1'
      - name: payoutMappingGroup
        in: path
        schema:
          type: integer
        required: true
        description: Payout mapping group ID
        example: '5'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: integer
                  integration_instance_id:
                    type: integer
                  name:
                    type: string
                  document_type:
                    type: string
                  sort_order:
                    type: integer
                  created_at:
                    type: string
                  updated_at:
                    type: string
                example:
                  id: 5
                  integration_instance_id: 1
                  name: Shopify Sales - US
                  document_type: invoice
                  sort_order: 0
                  created_at: '2026-07-17T10:12:00.000000Z'
                  updated_at: '2026-07-17T11:45:00.000000Z'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      name:
                        type: array
                        items:
                          type: string
                      document_type:
                        type: array
                        items:
                          type: string
                example:
                  message: A document type (invoice or bill) is required.
                  errors:
                    name:
                    - The name field is required.
                    document_type:
                    - A document type (invoice or bill) is required.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: put-api-shopify-integrationinstance-payout-mapping-groups-payoutmappinggroup
    delete:
      tags:
      - Shopify
      summary: Delete Payout Mapping Group
      description: 'Deletes a payout mapping group scoped to the integration instance.
        Type mappings that referenced the group are kept but left without a group
        assignment.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Shopify integration instance ID
        example: '1'
      - name: payoutMappingGroup
        in: path
        schema:
          type: integer
        required: true
        description: Payout mapping group ID
        example: '5'
      responses:
        '204':
          description: No Content
          content:
            application/json:
              schema:
                type: object
                properties: {}
                example: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-shopify-integrationinstance-payout-mapping-groups-payoutmappinggroup
  /api/shopify/{integrationInstance}/payout-type-mappings:
    get:
      tags:
      - Shopify
      summary: List Payout Type Mappings
      description: 'Returns the resolved payout type mappings for the integration
        instance: per-instance override rows plus the global default rows they have
        not overridden. Each row maps a financial code (a normalized type / source
        / reason combination from Shopify Payments balance transactions) to a general-ledger
        account and an optional mapping group; is_override indicates an instance-specific
        row. Before listing, any financial codes newly seen in the instance''s synced
        balance transactions are registered as unmapped global rows so they can be
        configured.


        Authentication: Requires Bearer token.


        Filterable columns: type, source_type, reason, financial_code, typical_amount_sign,
        mapping_status (mapped/unmapped), group_status (assigned/unassigned) (text),
        created_at, updated_at (datetime). filter[search] matches type, source type,
        reason, and financial code.


        Filtering: pass filter[column]=value for an exact match, or filter[column.operator]=value
        with operators such as contains, does_not_contain, is, is_not, is_one_of,
        starts_with, ends_with, is_empty, is_not_empty (text), greater_than, less_than,
        greater_than_or_equal, less_than_or_equal, between (numeric), and is, is_not,
        before, after, on_or_before, on_or_after, between, today, yesterday, past_week,
        past_month, past_year, days_ago, past_days (date/datetime). Complex AND/OR
        trees can be sent as a base64-encoded JSON tree in the filter_groups parameter.


        Allowed sorts: type, source_type, financial_code, created_at (prefix with
        - for descending; default financial_code). Pagination defaults to 10 per page.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Shopify integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        type:
                          type: string
                        source_type:
                          type: string
                        reason:
                          type: string
                          nullable: true
                        financial_code:
                          type: string
                        typical_amount_sign:
                          type: string
                        shopify_payout_mapping_group_id:
                          type: integer
                        nominalCode:
                          type: object
                          properties:
                            id:
                              type: integer
                            code:
                              type: string
                            name:
                              type: string
                        mappingGroup:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            document_type:
                              type: string
                        is_override:
                          type: boolean
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  next_page_url:
                    type: string
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 7
                    integration_instance_id: 1
                    type: charge
                    source_type: charge
                    reason: null
                    financial_code: 'charge: sale'
                    typical_amount_sign: positive
                    shopify_payout_mapping_group_id: 1
                    nominalCode:
                      id: 210
                      code: '4000'
                      name: Sales Revenue
                    mappingGroup:
                      id: 1
                      name: Shopify Sales
                      document_type: invoice
                    is_override: true
                    created_at: '2026-07-17T09:00:00.000000Z'
                    updated_at: '2026-07-17T09:05:00.000000Z'
                  - id: 3
                    integration_instance_id: null
                    type: fee
                    source_type: shopify_payments
                    reason: null
                    financial_code: 'fee: shopify_payments'
                    typical_amount_sign: negative
                    shopify_payout_mapping_group_id: null
                    nominalCode: null
                    mappingGroup: null
                    is_override: false
                    created_at: '2026-07-17T09:00:00.000000Z'
                    updated_at: '2026-07-17T09:00:00.000000Z'
                  first_page_url: '{{protocol}}://{{domain}}/api/shopify/1/payout-type-mappings?page=1'
                  from: 1
                  last_page: 2
                  last_page_url: '{{protocol}}://{{domain}}/api/shopify/1/payout-type-mappings?page=2'
                  next_page_url: '{{protocol}}://{{domain}}/api/shopify/1/payout-type-mappings?page=2'
                  path: '{{protocol}}://{{domain}}/api/shopify/1/payout-type-mappings'
                  per_page: 10
                  prev_page_url: null
                  to: 10
                  total: 14
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shopify-integrationinstance-payout-type-mappings
    put:
      tags:
      - Shopify
      summary: Update Payout Type Mappings
      description: 'Updates individual payout type mappings, assigning or clearing
        the general-ledger account and mapping group of each. Fields omitted from
        a mapping entry are left unchanged; pass null to clear an assignment.


        Authentication: Requires Bearer token.


        Request body:

        - mappings (required, array, min 1): mapping updates to apply.

        - mappings[].id (required, integer): ID of an existing payout type mapping.

        - mappings[].nominal_code_id (optional, nullable, integer): general-ledger
        account to assign; must reference an existing account. Pass null to clear.

        - mappings[].shopify_payout_mapping_group_id (optional, nullable, integer):
        payout mapping group to assign; must reference an existing group. Pass null
        to clear.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                mappings:
                  type: array
                  items:
                    type: object
                    properties:
                      id:
                        type: integer
                      nominal_code_id:
                        type: integer
                      shopify_payout_mapping_group_id:
                        type: integer
              example:
                mappings:
                - id: 7
                  nominal_code_id: 210
                  shopify_payout_mapping_group_id: 1
                - id: 3
                  nominal_code_id: 305
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Shopify integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Payout type mappings updated successfully.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      mappings:
                        type: array
                        items:
                          type: string
                example:
                  message: At least one type mapping is required.
                  errors:
                    mappings:
                    - At least one type mapping is required.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: put-api-shopify-integrationinstance-payout-type-mappings
  /api/shopify/{integrationInstance}/payout-type-mappings/bulk-assign:
    put:
      tags:
      - Shopify
      summary: Bulk Assign Payout Type Mappings
      description: 'Assigns a general-ledger account and/or a mapping group to several
        payout type mappings at once. At least one of nominal_code_id or shopify_payout_mapping_group_id
        must be provided; pass null to clear that assignment on all selected mappings.
        Only mappings scoped to the integration instance are updated - global rows
        are not modified.


        Authentication: Requires Bearer token.


        Request body:

        - ids (required, array of integers, min 1): payout type mapping IDs to update.
        Each ID must reference an existing payout type mapping.

        - nominal_code_id (optional, nullable, integer): general-ledger account to
        assign to all selected mappings; must reference an existing account.

        - shopify_payout_mapping_group_id (optional, nullable, integer): payout mapping
        group to assign to all selected mappings; must reference an existing group.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
                nominal_code_id:
                  type: integer
                shopify_payout_mapping_group_id:
                  type: integer
              example:
                ids:
                - 3
                - 7
                - 9
                nominal_code_id: 210
                shopify_payout_mapping_group_id: 1
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Shopify integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      updated:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    updated: 3
                  message: 3 type mapping(s) updated successfully.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      nominal_code_id:
                        type: array
                        items:
                          type: string
                example:
                  message: At least one of nominal_code_id or shopify_payout_mapping_group_id
                    must be provided.
                  errors:
                    nominal_code_id:
                    - At least one of nominal_code_id or shopify_payout_mapping_group_id
                      must be provided.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: put-api-shopify-integrationinstance-payout-type-mappings-bulk-assign
  /api/shopify/{integrationInstance}/payout-finance-settings:
    get:
      tags:
      - Shopify
      summary: Get Payout Finance Settings
      description: 'Returns the resolved payout finance settings for the integration
        instance: the fallback revenue and expense accounts used for unmapped payout
        lines, the clearing account payouts settle against, the accounting sync mode
        (per_order or per_payout; default per_order), and the optional payout accounting
        start date before which payouts are not posted. Fallback and clearing accounts
        fall back to the workspace-wide values when the instance has none of its own.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Shopify integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  fallback_revenue_nominal_code_id:
                    type: integer
                  fallback_expense_nominal_code_id:
                    type: integer
                  clearing_nominal_code_id:
                    type: integer
                  accounting_sync_mode:
                    type: string
                  payout_accounting_start_date:
                    type: string
                example:
                  fallback_revenue_nominal_code_id: 220
                  fallback_expense_nominal_code_id: 310
                  clearing_nominal_code_id: 145
                  accounting_sync_mode: per_payout
                  payout_accounting_start_date: '2026-07-01'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shopify-integrationinstance-payout-finance-settings
    put:
      tags:
      - Shopify
      summary: Update Payout Finance Settings
      description: 'Updates the payout finance settings for the integration instance.
        All fields are optional; omitted fields keep their current values, and nullable
        fields can be set to null to clear them. Returns the resolved settings after
        the update.


        Authentication: Requires Bearer token.


        Request body:

        - fallback_revenue_nominal_code_id (optional, nullable, integer): account
        for unmapped revenue lines; must reference an existing general-ledger account.

        - fallback_expense_nominal_code_id (optional, nullable, integer): account
        for unmapped expense lines; must reference an existing general-ledger account.

        - clearing_nominal_code_id (optional, nullable, integer): clearing account
        that payout documents settle against; must reference an existing general-ledger
        account.

        - accounting_sync_mode (optional, string): one of per_order, per_payout.

        - payout_accounting_start_date (optional, nullable, date): payouts dated before
        this are not posted to accounting.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                fallback_revenue_nominal_code_id:
                  type: integer
                fallback_expense_nominal_code_id:
                  type: integer
                clearing_nominal_code_id:
                  type: integer
                accounting_sync_mode:
                  type: string
                payout_accounting_start_date:
                  type: string
              example:
                fallback_revenue_nominal_code_id: 220
                fallback_expense_nominal_code_id: 310
                clearing_nominal_code_id: 145
                accounting_sync_mode: per_payout
                payout_accounting_start_date: '2026-07-01'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Shopify integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  fallback_revenue_nominal_code_id:
                    type: integer
                  fallback_expense_nominal_code_id:
                    type: integer
                  clearing_nominal_code_id:
                    type: integer
                  accounting_sync_mode:
                    type: string
                  payout_accounting_start_date:
                    type: string
                example:
                  fallback_revenue_nominal_code_id: 220
                  fallback_expense_nominal_code_id: 310
                  clearing_nominal_code_id: 145
                  accounting_sync_mode: per_payout
                  payout_accounting_start_date: '2026-07-01'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      accounting_sync_mode:
                        type: array
                        items:
                          type: string
                example:
                  message: The selected accounting sync mode is invalid.
                  errors:
                    accounting_sync_mode:
                    - The selected accounting sync mode is invalid.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: put-api-shopify-integrationinstance-payout-finance-settings
  /api/ebay/integration-instances:
    get:
      tags:
      - eBay
      summary: List Integration Instances
      description: 'List all Ebay integration instances with standard list query parameters.
        Requires Bearer token.


        Supports query params: page, limit, search, sort, archived, included[], excluded[].'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        description: Page number
        example: '1'
      - name: limit
        in: query
        schema:
          type: integer
        description: Items per page
        example: '25'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        integration_id:
                          type: integer
                        is_automatic_sync_enabled:
                          type: boolean
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  total:
                    type: integer
                  per_page:
                    type: integer
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                example:
                  data:
                  - id: 42
                    name: My Ebay Store
                    integration_id: 1
                    is_automatic_sync_enabled: false
                    created_at: '2024-01-15T10:00:00.000Z'
                    updated_at: '2024-01-15T10:00:00.000Z'
                  total: 1
                  per_page: 25
                  current_page: 1
                  last_page: 1
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-ebay-integration-instances
  /api/ebay/{integrationInstance}/legacy-products:
    get:
      tags:
      - eBay
      summary: List Legacy Products (Integration)
      description: 'List all Ebay legacy product listings (the eBay listings grid)
        for a specific integration instance. Uses Spatie QueryBuilder — filters use
        the bracket format (filter[key]=value).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Archived listings are hidden by default; send filter[archived] (or an archived
        condition inside filter_groups) to surface them.


        Authentication: Requires Bearer token.


        Query params: page, per_page (default 10), filter[search], filter[mapping_status]
        (mapped|unmapped), filter[ListingStatus], filter[ListingType], filter[archived],
        filter_groups (base64-encoded advanced filter tree), sort (default -id).


        Response is a standard Laravel paginator (top-level data, current_page, last_page,
        per_page, total, links, etc.).'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        description: Page number
        example: '1'
      - name: per_page
        in: query
        schema:
          type: integer
        description: Items per page (default 10)
        example: '10'
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        ItemID:
                          type: string
                        SKU:
                          type: string
                        Title:
                          type: string
                        ListingType:
                          type: string
                        ListingStatus:
                          type: string
                        QuantityAvailable:
                          type: integer
                        CurrentPriceValue:
                          type: number
                        CurrentPriceCurrency:
                          type: string
                        BidCount:
                          type: string
                        EndingReason:
                          type: string
                          nullable: true
                        WatchCount:
                          type: integer
                        StartTimeUtc:
                          type: string
                        EndTimeUtc:
                          type: string
                        json_object:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                  next_page_url:
                    type: string
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 101
                    integration_instance_id: 42
                    ItemID: '123456789012'
                    SKU: PROD-001
                    Title: Blue Widget - 10 Pack
                    ListingType: FixedPriceItem
                    ListingStatus: Active
                    QuantityAvailable: 50
                    CurrentPriceValue: 24.99
                    CurrentPriceCurrency: USD
                    BidCount: '0'
                    EndingReason: null
                    WatchCount: 3
                    StartTimeUtc: '2024-01-01T00:00:00.000Z'
                    EndTimeUtc: '2024-07-01T00:00:00.000Z'
                    json_object: null
                    created_at: '2024-01-01T00:00:00.000Z'
                    updated_at: '2024-06-15T08:30:00.000Z'
                  first_page_url: https://example.sku.io/api/ebay/42/legacy-products?page=1
                  from: 1
                  last_page: 15
                  last_page_url: https://example.sku.io/api/ebay/42/legacy-products?page=15
                  links: []
                  next_page_url: https://example.sku.io/api/ebay/42/legacy-products?page=2
                  path: https://example.sku.io/api/ebay/42/legacy-products
                  per_page: 10
                  prev_page_url: null
                  to: 10
                  total: 150
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-ebay-integrationinstance-legacy-products
  /api/ebay/{integrationInstance}/legacy-products/{product}:
    get:
      tags:
      - eBay
      summary: Show Legacy Product
      description: 'Retrieve a single Ebay legacy product listing. Requires Bearer
        token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '42'
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: Legacy product ID
        example: '101'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      ItemID:
                        type: string
                      SKU:
                        type: string
                      Title:
                        type: string
                      ListingType:
                        type: string
                      ListingStatus:
                        type: string
                      QuantityAvailable:
                        type: integer
                      CurrentPriceValue:
                        type: number
                      CurrentPriceCurrency:
                        type: string
                      BidCount:
                        type: string
                      EndingReason:
                        type: string
                        nullable: true
                      WatchCount:
                        type: integer
                      StartTimeUtc:
                        type: string
                      EndTimeUtc:
                        type: string
                      json_object:
                        type: object
                        properties:
                          ItemID:
                            type: string
                          SKU:
                            type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 101
                    integration_instance_id: 42
                    ItemID: '123456789012'
                    SKU: PROD-001
                    Title: Blue Widget - 10 Pack
                    ListingType: FixedPriceItem
                    ListingStatus: Active
                    QuantityAvailable: 50
                    CurrentPriceValue: 24.99
                    CurrentPriceCurrency: USD
                    BidCount: '0'
                    EndingReason: null
                    WatchCount: 3
                    StartTimeUtc: '2024-01-01T00:00:00.000Z'
                    EndTimeUtc: '2024-07-01T00:00:00.000Z'
                    json_object:
                      ItemID: '123456789012'
                      SKU: PROD-001
                    created_at: '2024-01-01T00:00:00.000Z'
                    updated_at: '2024-06-15T08:30:00.000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-ebay-integrationinstance-legacy-products-product
    put:
      tags:
      - eBay
      summary: Update Legacy Product
      description: 'Update an existing Ebay legacy product listing. Requires Bearer
        token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                SKU:
                  type: string
              example:
                SKU: PROD-001-UPDATED
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '42'
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: Legacy product ID
        example: '101'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      ItemID:
                        type: string
                      SKU:
                        type: string
                      Title:
                        type: string
                      ListingStatus:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 101
                    integration_instance_id: 42
                    ItemID: '123456789012'
                    SKU: PROD-001-UPDATED
                    Title: Blue Widget - 10 Pack
                    ListingStatus: Active
                    updated_at: '2024-06-20T09:00:00.000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-ebay-integrationinstance-legacy-products-product
    delete:
      tags:
      - eBay
      summary: Delete Legacy Product
      description: 'Delete an Ebay legacy product listing. Requires Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '42'
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: Legacy product ID
        example: '101'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: string
                    nullable: true
                  message:
                    type: string
                example:
                  data: null
                  message: Product deleted
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-ebay-integrationinstance-legacy-products-product
  /api/ebay/{integrationInstance}/legacy-products/create-sku-products:
    post:
      tags:
      - eBay
      summary: Create SKU Products from Listings
      description: 'Create SKU.io products from selected Ebay listings. Returns 400
        if a listing is missing a SKU. Requires Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Bulk selection contract:

        - {"create_all_products": false, "ids": [1, 2]} — create for the given channel
        product IDs

        - {"create_all_products": true} — create for all unmapped products on the
        integration instance

        - {"create_all_products": true, "filters": {...}} — create only for products
        matching the filters. The filters object accepts the same filter keys as the
        corresponding products list endpoint (bare column keys) and/or a "filter_groups"
        tree (base64-encoded JSON). When filters match no products, nothing is created
        and the response message is "No products to create".

        - create_all_products is required; ids is required when create_all_products
        is false and no filters are sent.

        - Legacy {"conjunction", "filterSet"} filter payloads are rejected with 422.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                product_ids:
                  type: array
                  items:
                    type: integer
                overwrite:
                  type: boolean
              example:
                product_ids:
                - 101
                - 102
                - 103
                overwrite: false
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      created:
                        type: integer
                      skipped:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    created: 3
                    skipped: 0
                  message: Products created successfully
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: object
                    properties:
                      apiErrors:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: array
                example:
                  errors:
                    apiErrors:
                    - message: The product with ItemID 123456789012 does not have
                        a SKU.
                      code: Missing SKU
                      data: []
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-ebay-integrationinstance-legacy-products-create-sku-products
  /api/ebay/{integrationInstance}/legacy-products/refresh:
    post:
      tags:
      - eBay
      summary: Refresh Legacy Products
      description: 'Queue a job to refresh all legacy product listings from the Ebay
        API. Returns a tracked job log ID for progress monitoring. Requires Bearer
        token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 789
                  message: Refresh job queued
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-ebay-integrationinstance-legacy-products-refresh
  /api/ebay/{integrationInstance}/legacy-products/map:
    put:
      tags:
      - eBay
      summary: Map Products
      description: 'Map Ebay legacy listings to SKU.io products. Requires Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                mappings:
                  type: array
                  items:
                    type: object
                    properties:
                      sales_channel_product_id:
                        type: integer
                      product_id:
                        type: integer
              example:
                mappings:
                - sales_channel_product_id: 101
                  product_id: 55
                - sales_channel_product_id: 102
                  product_id: 56
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: string
                    nullable: true
                  message:
                    type: string
                example:
                  data: null
                  message: Products mapped successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-ebay-integrationinstance-legacy-products-map
  /api/ebay/{integrationInstance}/products/{product}/smart-match:
    post:
      tags:
      - eBay
      summary: Smart Match Product
      description: 'Find suggested SKU product matches for a single eBay listing.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Matching strategy:

        - exact_match: SKU product whose sku == ebay_product.SKU

        - barcode_match: always null (eBay legacy products do not expose a UPC/barcode
        field)

        - similar_matches: up to 5 fuzzy matches by Title / SKU tokens


        Archived SKU products are excluded. Used by the listing detail page mapping
        modal.


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: eBay integration instance ID
        example: '42'
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: eBay legacy product ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      exact_match:
                        type: object
                        properties:
                          id:
                            type: integer
                          sku:
                            type: string
                          name:
                            type: string
                          barcode:
                            type: string
                          price:
                            type: number
                          type:
                            type: string
                          match_type:
                            type: string
                      barcode_match:
                        type: string
                        nullable: true
                      similar_matches:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            sku:
                              type: string
                            name:
                              type: string
                            barcode:
                              type: string
                            price:
                              type: number
                            type:
                              type: string
                            match_type:
                              type: string
                example:
                  data:
                    exact_match:
                      id: 55
                      sku: EBAY-WIDGET-L
                      name: Widget Large
                      barcode: 012345678905
                      price: 19.99
                      type: simple
                      match_type: sku
                    barcode_match: null
                    similar_matches:
                    - id: 56
                      sku: EBAY-WIDGET-M
                      name: Widget Medium
                      barcode: 012345678912
                      price: 14.99
                      type: simple
                      match_type: fuzzy
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-ebay-integrationinstance-products-product-smart-match
  /api/ebay/{integrationInstance}/products/{product}/raw:
    get:
      tags:
      - eBay
      summary: Get Raw Product from eBay
      description: 'Fetch the raw eBay GetItem response for a single listing, live
        from eBay''s Trading API. Powers the "Load Raw Data from eBay" button on the
        listing detail page.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        The data is not persisted — it reflects the live eBay state.


        Returns 403 if the product doesn''t belong to the given integration instance.
        Returns 500 if eBay''s API call fails (e.g. credentials not configured).


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: eBay integration instance ID
        example: '42'
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: eBay legacy product ID
        example: '10'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      product:
                        type: object
                        properties:
                          ItemID:
                            type: string
                          SKU:
                            type: string
                          Title:
                            type: string
                          ListingType:
                            type: string
                          ListingStatus:
                            type: string
                          QuantityAvailable:
                            type: integer
                          CurrentPriceValue:
                            type: number
                          CurrentPriceCurrency:
                            type: string
                example:
                  data:
                    product:
                      ItemID: '254620010010'
                      SKU: EBY-NOTEBOOK-A5
                      Title: Hardcover Lined Notebook A5 — Set of 2
                      ListingType: FixedPriceItem
                      ListingStatus: Active
                      QuantityAvailable: 20
                      CurrentPriceValue: 11.0
                      CurrentPriceCurrency: USD
        '403':
          description: Forbidden
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: Product does not belong to this integration instance
        '500':
          description: Internal Server Error
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                  message:
                    type: string
                example:
                  error: Failed to fetch raw product data from eBay
                  message: Ebay API credentials not set
        '429': *id001
        '401': *id002
        '404': *id004
      operationId: get-api-ebay-integrationinstance-products-product-raw
  /api/ebay/{integrationInstance}/legacy-products/export:
    get:
      tags:
      - eBay
      summary: Export Legacy Products
      description: 'Export all legacy product listings for an integration instance
        as a file download. Requires Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Response: File download (CSV or Excel format).'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: text/csv
          content:
            text/plain:
              schema:
                type: string
                example: 'id,ItemID,SKU,Title,ListingStatus,CurrentPriceValue

                  101,123456789012,PROD-001,Blue Widget,Active,24.99'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-ebay-integrationinstance-legacy-products-export
  /api/ebay/{integrationInstance}/legacy-products/archive:
    put:
      tags:
      - eBay
      summary: Archive Legacy Products
      description: 'Archive selected Ebay legacy product listings. Requires Bearer
        token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Bulk selection contract:

        - {"ids": [1, 2]} — act on the given channel product IDs

        - {"mode": "all"} — act on all products for the integration instance

        - {"apply_to_all": true, "filters": {...}} — act only on products matching
        the filters. The filters object accepts the same filter keys as the corresponding
        products list endpoint (bare column keys) and/or a "filter_groups" tree (base64-encoded
        JSON). With apply_to_all and no filters, all products for the instance are
        targeted.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 101
                - 102
                - 103
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: string
                    nullable: true
                  message:
                    type: string
                example:
                  data: null
                  message: Products archived
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-ebay-integrationinstance-legacy-products-archive
  /api/ebay/{integrationInstance}/legacy-products/unarchive:
    put:
      tags:
      - eBay
      summary: Unarchive Legacy Products
      description: 'Unarchive selected Ebay legacy product listings. Requires Bearer
        token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Bulk selection contract:

        - {"ids": [1, 2]} — act on the given channel product IDs

        - {"mode": "all"} — act on all products for the integration instance

        - {"apply_to_all": true, "filters": {...}} — act only on products matching
        the filters. The filters object accepts the same filter keys as the corresponding
        products list endpoint (bare column keys) and/or a "filter_groups" tree (base64-encoded
        JSON). With apply_to_all and no filters, all products for the instance are
        targeted.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 101
                - 102
                - 103
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: string
                    nullable: true
                  message:
                    type: string
                example:
                  data: null
                  message: Products unarchived
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-ebay-integrationinstance-legacy-products-unarchive
  /api/ebay/{integrationInstance}/legacy-products/archiveable:
    post:
      tags:
      - eBay
      summary: Check Archiveable Products
      description: 'Check which of the given listings can be archived. Returns lists
        of archiveable and non-archiveable products. Requires Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 101
                - 102
                - 103
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      archiveable:
                        type: array
                        items:
                          type: integer
                      not_archiveable:
                        type: array
                        items:
                          type: integer
                example:
                  data:
                    archiveable:
                    - 101
                    - 102
                    not_archiveable:
                    - 103
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-ebay-integrationinstance-legacy-products-archiveable
  /api/ebay/{integrationInstance}/legacy-products/delete:
    put:
      tags:
      - eBay
      summary: Delete Legacy Products (Bulk)
      description: 'Bulk delete selected Ebay legacy product listings. Requires Bearer
        token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 101
                - 102
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: string
                    nullable: true
                  message:
                    type: string
                example:
                  data: null
                  message: Products deleted
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-ebay-integrationinstance-legacy-products-delete
  /api/ebay/{integrationInstance}/legacy-products/deleteable:
    put:
      tags:
      - eBay
      summary: Check Deleteable Products
      description: 'Check which of the given listings can be deleted (not linked to
        any Ebay orders). Requires Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 101
                - 102
                - 103
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      deleteable:
                        type: array
                        items:
                          type: integer
                      not_deleteable:
                        type: object
                        properties:
                          '103':
                            type: string
                example:
                  data:
                    deleteable:
                    - 101
                    - 102
                    not_deleteable:
                      '103': Currently used by 2 Ebay Order(s)
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-ebay-integrationinstance-legacy-products-deleteable
  /api/ebay/{integrationInstance}/legacy-products/import-mappings:
    post:
      tags:
      - eBay
      summary: Import Mappings
      description: 'Import field mapping configuration for linking Ebay listing fields
        to SKU.io product fields. Requires Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                mappings:
                  type: array
                  items:
                    type: object
                    properties:
                      listing_field:
                        type: string
                      sku_field:
                        type: string
              example:
                mappings:
                - listing_field: SKU
                  sku_field: sku
                - listing_field: Title
                  sku_field: item_name
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: string
                    nullable: true
                  message:
                    type: string
                example:
                  data: null
                  message: Mappings imported successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-ebay-integrationinstance-legacy-products-import-mappings
  /api/ebay/{integrationInstance}/legacy-products/sync-inventory:
    post:
      tags:
      - eBay
      summary: Sync Inventory
      description: 'Push current SKU.io inventory quantities to Ebay listings. Requires
        Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      synced:
                        type: integer
                      failed:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    synced: 45
                    failed: 0
                  message: Inventory synced
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-ebay-integrationinstance-legacy-products-sync-inventory
  /api/ebay/{integrationInstance}/legacy-products/hydrate-product-template:
    post:
      tags:
      - eBay
      summary: Hydrate Product Template
      description: 'Hydrate an Ebay listing template with data from a SKU.io product.
        Requires Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                product_id:
                  type: integer
              example:
                product_id: 55
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      Title:
                        type: string
                      SKU:
                        type: string
                      CurrentPriceValue:
                        type: number
                      CurrentPriceCurrency:
                        type: string
                example:
                  data:
                    Title: Blue Widget - 10 Pack
                    SKU: PROD-001
                    CurrentPriceValue: 24.99
                    CurrentPriceCurrency: USD
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-ebay-integrationinstance-legacy-products-hydrate-product-template
  /api/ebay/{integrationInstance}/legacy-products/get-suggested-categories:
    post:
      tags:
      - eBay
      summary: Get Suggested Categories
      description: 'Get Ebay category suggestions for a product query using the Ebay
        Taxonomy API. Requires Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Request body fields:

        - query (required, string): Search term for category suggestions

        - marketplace_id (required, string): Ebay marketplace ID. Valid values: EBAY_US,
        EBAY_GB, EBAY_AU, EBAY_CA, EBAY_DE, EBAY_FR, EBAY_IT, EBAY_ES'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                query:
                  type: string
                marketplace_id:
                  type: string
              example:
                query: blue widget electronics
                marketplace_id: EBAY_US
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        category:
                          type: object
                          properties:
                            categoryId:
                              type: string
                            categoryName:
                              type: string
                        categoryTreeNodeLevel:
                          type: integer
                        relevancy:
                          type: string
                example:
                  data:
                  - category:
                      categoryId: '58058'
                      categoryName: Consumer Electronics
                    categoryTreeNodeLevel: 1
                    relevancy: HIGH
                  - category:
                      categoryId: '9355'
                      categoryName: Cell Phones & Accessories
                    categoryTreeNodeLevel: 2
                    relevancy: MEDIUM
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      query:
                        type: array
                        items:
                          type: string
                      marketplace_id:
                        type: array
                        items:
                          type: string
                example:
                  message: The given data was invalid.
                  errors:
                    query:
                    - The query field is required.
                    marketplace_id:
                    - The marketplace id field is required.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-ebay-integrationinstance-legacy-products-get-suggested-categories
  /api/ebay/{integrationInstance}/legacy-products/build-payload:
    post:
      tags:
      - eBay
      summary: Build Payload
      description: 'Build the Ebay listing payload for one or more SKU.io products.
        Used to preview the data that will be sent to Ebay before publishing. Requires
        Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                product_ids:
                  type: array
                  items:
                    type: integer
              example:
                product_ids:
                - 55
                - 56
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      '55':
                        type: object
                        properties:
                          Title:
                            type: string
                          SKU:
                            type: string
                          StartPrice:
                            type: string
                          Currency:
                            type: string
                          Quantity:
                            type: integer
                example:
                  data:
                    '55':
                      Title: Blue Widget - 10 Pack
                      SKU: PROD-001
                      StartPrice: '24.99'
                      Currency: USD
                      Quantity: 50
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-ebay-integrationinstance-legacy-products-build-payload
  /api/ebay/{integrationInstance}/legacy-products/publish:
    post:
      tags:
      - eBay
      summary: Publish Listings
      description: 'Publish SKU.io products as new Ebay listings. Returns 400 if Ebay
        returns a bad request error. Requires Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                product_ids:
                  type: array
                  items:
                    type: integer
              example:
                product_ids:
                - 55
                - 56
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      published:
                        type: integer
                      failed:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    published: 2
                    failed: 0
                  message: Listings published successfully
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: object
                    properties:
                      apiErrors:
                        type: string
                  message:
                    type: string
                example:
                  errors:
                    apiErrors: 'Ebay rejected the listing: Invalid category ID'
                  message: Bad Ebay Request
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-ebay-integrationinstance-legacy-products-publish
  /api/ebay/{integrationInstance}/orders:
    get:
      tags:
      - eBay
      summary: List Orders (Integration)
      description: 'List all Ebay orders for a specific integration instance with
        standard list query parameters. Returns paginated results.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Supports query params: page, limit, search, sort, archived, included[], excluded[],
        table_specifications.'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        description: Page number
        example: '1'
      - name: limit
        in: query
        schema:
          type: integer
        description: Items per page
        example: '25'
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        orderId:
                          type: string
                        legacyOrderId:
                          type: string
                        creationDate:
                          type: string
                        creationDateUtc:
                          type: string
                        lastModifiedDate:
                          type: string
                        lastModifiedDateUtc:
                          type: string
                        orderPaymentStatus:
                          type: string
                        orderFulfillmentStatus:
                          type: string
                        totalValue:
                          type: number
                        totalCurrency:
                          type: string
                        salesRecordReference:
                          type: string
                        totalMarketplaceFeeValue:
                          type: number
                        totalMarketplaceFeeCurrency:
                          type: string
                        archived_at:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  total:
                    type: integer
                  per_page:
                    type: integer
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                example:
                  data:
                  - id: 501
                    integration_instance_id: 42
                    orderId: 12-34567-89012
                    legacyOrderId: '987654321'
                    creationDate: '2024-06-01T14:00:00.000Z'
                    creationDateUtc: '2024-06-01T14:00:00.000Z'
                    lastModifiedDate: '2024-06-02T09:00:00.000Z'
                    lastModifiedDateUtc: '2024-06-02T09:00:00.000Z'
                    orderPaymentStatus: PAID
                    orderFulfillmentStatus: NOT_STARTED
                    totalValue: 49.99
                    totalCurrency: USD
                    salesRecordReference: SR-001
                    totalMarketplaceFeeValue: 2.5
                    totalMarketplaceFeeCurrency: USD
                    archived_at: null
                    created_at: '2024-06-01T14:00:00.000Z'
                    updated_at: '2024-06-02T09:00:00.000Z'
                  total: 320
                  per_page: 25
                  current_page: 1
                  last_page: 13
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-ebay-integrationinstance-orders
  /api/ebay/{integrationInstance}/orders/refresh:
    post:
      tags:
      - eBay
      summary: Refresh Orders
      description: 'Queue a job to refresh all orders from the Ebay API. Returns a
        tracked job log ID for progress monitoring. Requires Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 790
                  message: Refresh job queued
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-ebay-integrationinstance-orders-refresh
  /api/ebay/{integrationInstance}/orders/create-sku-orders:
    post:
      tags:
      - eBay
      summary: Create SKU Orders from Ebay
      description: 'Create SKU.io sales orders from selected Ebay orders. Requires
        Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Bulk selection contract:

        - {"ids": [1, 2]} — create for the given channel order IDs

        - {"create_all_orders": true} — create for all eligible orders on the integration
        instance

        - {"create_all_orders": true, "filters": {...}} — create only for orders matching
        the filters. The filters object accepts the same filter keys as the corresponding
        orders list endpoint (bare column keys, e.g. {"order_status": "pending"})
        and/or a "filter_groups" tree (base64-encoded JSON, same format as the list
        endpoint). When filters match no orders, nothing is created and the response
        message is "No orders to create".

        - Legacy {"conjunction", "filterSet"} filter payloads are rejected with 422.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                order_ids:
                  type: array
                  items:
                    type: integer
              example:
                order_ids:
                - 501
                - 502
                - 503
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      created:
                        type: integer
                      skipped:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    created: 3
                    skipped: 0
                  message: SKU orders created successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-ebay-integrationinstance-orders-create-sku-orders
  /api/ebay/{integrationInstance}/orders/export:
    get:
      tags:
      - eBay
      summary: Export Orders
      description: 'Export all Ebay orders for an integration instance as a file download.
        Requires Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Response: File download (CSV or Excel format).'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: text/csv
          content:
            text/plain:
              schema:
                type: string
                example: 'id,orderId,legacyOrderId,orderPaymentStatus,orderFulfillmentStatus,totalValue,totalCurrency

                  501,12-34567-89012,987654321,PAID,NOT_STARTED,49.99,USD'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-ebay-integrationinstance-orders-export
  /api/ebay/{integrationInstance}/orders/archive:
    put:
      tags:
      - eBay
      summary: Bulk Archive eBay Orders
      description: 'Archive multiple eBay orders in one request.


        Authentication: Requires Bearer token.


        Request Body:

        - ids (array of integers, required) — eBay order local DB IDs to archive.
        Orders belonging to other integration instances are ignored.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 101
                - 102
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: eBay integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  archived_count:
                    type: integer
                example:
                  message: 2 orders archived successfully
                  archived_count: 2
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-ebay-integrationinstance-orders-archive
  /api/ebay/{integrationInstance}/orders/unarchive:
    put:
      tags:
      - eBay
      summary: Bulk Unarchive eBay Orders
      description: 'Unarchive multiple eBay orders in one request.


        Authentication: Requires Bearer token.


        Request Body:

        - ids (array of integers, required) — eBay order local DB IDs to unarchive.
        Orders belonging to other integration instances are ignored.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 101
                - 102
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: eBay integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  unarchived_count:
                    type: integer
                example:
                  message: 2 orders unarchived successfully
                  unarchived_count: 2
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-ebay-integrationinstance-orders-unarchive
  /api/ebay/{integrationInstance}/orders/update-sku-orders:
    post:
      tags:
      - eBay
      summary: Update SKU Orders from Channel Orders
      description: 'Update existing SKU orders from eBay channel orders. Accepts {ids}
        or {update_all_orders: true, filters?: &lt;canonical filter object>} - filters
        scope the update to the grid''s matching orders.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
                update_all_orders:
                  type: boolean
                use_jobs:
                  type: boolean
              example:
                ids:
                - 60
                - 61
                update_all_orders: false
                use_jobs: true
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-ebay-integrationinstance-orders-update-sku-orders
  /api/ebay-product-settings:
    get:
      tags:
      - eBay
      summary: List Product Settings
      description: 'Retrieve Ebay product settings for a specific SKU.io product.
        Returns all Ebay-specific settings (e.g., auction-until-sold configuration)
        for the product across all integration instances. Requires Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Query parameters:

        - product_id (required, integer): SKU.io product ID'
      parameters:
      - name: product_id
        in: query
        schema:
          type: integer
        description: Required. The SKU.io product ID to get settings for.
        example: '55'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: array
                items:
                  type: object
                  properties:
                    id:
                      type: integer
                    integration_instance_id:
                      type: integer
                    product_id:
                      type: integer
                    auction_until_sold_enabled:
                      type: boolean
                    auction_until_sold_price_reduction_percentage:
                      type: number
                    auction_until_sold_minimum_price:
                      type: number
                example:
                - id: 10
                  integration_instance_id: 42
                  product_id: 55
                  auction_until_sold_enabled: true
                  auction_until_sold_price_reduction_percentage: 5.0
                  auction_until_sold_minimum_price: 9.99
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      product_id:
                        type: array
                        items:
                          type: string
                example:
                  message: The given data was invalid.
                  errors:
                    product_id:
                    - The product id field is required.
                    - The selected product id is invalid.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-ebay-product-settings
    post:
      tags:
      - eBay
      summary: Save Product Settings
      description: 'Create or update Ebay product settings for a SKU.io product. Upserts
        by product_id and integration_instance_id. Requires Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Request body fields:

        - id (optional, integer): Setting ID for updates

        - integration_instance_id (required, integer): Ebay integration instance ID

        - product_id (required, integer): SKU.io product ID

        - auction_until_sold_enabled (required, boolean): Enable auction-until-sold
        feature

        - auction_until_sold_price_reduction_percentage (required, float): Price reduction
        % for re-listing

        - auction_until_sold_minimum_price (required, float): Minimum price floor
        for auction-until-sold'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                integration_instance_id:
                  type: integer
                product_id:
                  type: integer
                auction_until_sold_enabled:
                  type: boolean
                auction_until_sold_price_reduction_percentage:
                  type: integer
                auction_until_sold_minimum_price:
                  type: number
              example:
                integration_instance_id: 42
                product_id: 55
                auction_until_sold_enabled: true
                auction_until_sold_price_reduction_percentage: 5
                auction_until_sold_minimum_price: 9.99
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            text/plain:
              schema:
                type: string
                example: 'null'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      product_id:
                        type: array
                        items:
                          type: string
                      integration_instance_id:
                        type: array
                        items:
                          type: string
                      auction_until_sold_enabled:
                        type: array
                        items:
                          type: string
                example:
                  message: The given data was invalid.
                  errors:
                    product_id:
                    - The product id field is required.
                    integration_instance_id:
                    - The integration instance id field is required.
                    auction_until_sold_enabled:
                    - The auction until sold enabled field is required.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-ebay-product-settings
  /api/ebay/{integrationInstance}/blemished-auto-list-settings:
    get:
      tags:
      - eBay
      summary: Get Blemished Auto-List Settings
      description: Get the blemished auto-list configuration for an eBay integration
        instance. When a return is dispositioned as a new blemished SKU and its inventory
        lands, an enabled configuration automatically lists that SKU on eBay as an
        auction-until-sold listing using the selected default template. Returns default
        values when no configuration has been saved yet. Requires Bearer token.
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      enabled:
                        type: boolean
                      sales_channel_product_template_id:
                        type: integer
                      sales_channel_product_template_name:
                        type: string
                      ebay_site_id:
                        type: integer
                      starting_price_discount_percentage:
                        type: integer
                      auction_until_sold_enabled:
                        type: boolean
                      auction_until_sold_price_reduction_percentage:
                        type: integer
                      auction_until_sold_minimum_price_percentage:
                        type: integer
                      updated_at:
                        type: string
                example:
                  data:
                    id: 12
                    integration_instance_id: 42
                    enabled: true
                    sales_channel_product_template_id: 3
                    sales_channel_product_template_name: Blemished Auction
                    ebay_site_id: 0
                    starting_price_discount_percentage: 30
                    auction_until_sold_enabled: true
                    auction_until_sold_price_reduction_percentage: 10
                    auction_until_sold_minimum_price_percentage: 50
                    updated_at: '2026-07-11T05:26:53.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-ebay-integrationinstance-blemished-auto-list-settings
    put:
      tags:
      - eBay
      summary: Update Blemished Auto-List Settings
      description: 'Create or update the blemished auto-list configuration for an
        eBay integration instance. Requires Bearer token.


        Body fields:

        - enabled (boolean, required): master switch for automatic listing of new
        blemished SKUs.

        - sales_channel_product_template_id (integer, required when enabled): default
        listing template. Its ListingType must be an auction (Chinese) template.

        - ebay_site_id (integer, required): eBay site. 0 = United States, 100 = eBay
        Motors.

        - starting_price_discount_percentage (number, optional, 0-99): markdown applied
        to the template start price (e.g. 30 lists at 70% of the template price).
        Omit to use the template price as-is.

        - auction_until_sold_enabled (boolean, required): whether auto-listed items
        relist until sold.

        - auction_until_sold_price_reduction_percentage (number, optional, 0-99):
        price reduction applied on each relist.

        - auction_until_sold_minimum_price_percentage (number, optional, 0-100): floor
        as a percentage of the start price.


        Returns 422 if enabling without a template, or if the selected template is
        not an auction template.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                enabled:
                  type: boolean
                sales_channel_product_template_id:
                  type: integer
                ebay_site_id:
                  type: integer
                starting_price_discount_percentage:
                  type: integer
                auction_until_sold_enabled:
                  type: boolean
                auction_until_sold_price_reduction_percentage:
                  type: integer
                auction_until_sold_minimum_price_percentage:
                  type: integer
              example:
                enabled: true
                sales_channel_product_template_id: 3
                ebay_site_id: 0
                starting_price_discount_percentage: 30
                auction_until_sold_enabled: true
                auction_until_sold_price_reduction_percentage: 10
                auction_until_sold_minimum_price_percentage: 50
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      enabled:
                        type: boolean
                      sales_channel_product_template_id:
                        type: integer
                      sales_channel_product_template_name:
                        type: string
                      ebay_site_id:
                        type: integer
                      starting_price_discount_percentage:
                        type: integer
                      auction_until_sold_enabled:
                        type: boolean
                      auction_until_sold_price_reduction_percentage:
                        type: integer
                      auction_until_sold_minimum_price_percentage:
                        type: integer
                      updated_at:
                        type: string
                example:
                  data:
                    id: 12
                    integration_instance_id: 42
                    enabled: true
                    sales_channel_product_template_id: 3
                    sales_channel_product_template_name: Blemished Auction
                    ebay_site_id: 0
                    starting_price_discount_percentage: 30
                    auction_until_sold_enabled: true
                    auction_until_sold_price_reduction_percentage: 10
                    auction_until_sold_minimum_price_percentage: 50
                    updated_at: '2026-07-11T05:26:53.000000Z'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      sales_channel_product_template_id:
                        type: array
                        items:
                          type: string
                example:
                  message: A default auction template is required to enable blemished
                    auto-listing.
                  errors:
                    sales_channel_product_template_id:
                    - A default auction template is required to enable blemished auto-listing.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: put-api-ebay-integrationinstance-blemished-auto-list-settings
  /api/ebay-global-reports/uncovered-blemished-products:
    get:
      tags:
      - eBay
      summary: Uncovered Blemished Products
      description: 'Get a list of blemished/refurbished products that do not have
        an active Ebay listing covering them. Used for identifying inventory gaps
        in Ebay auction-until-sold programs. Requires Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        product_id:
                          type: integer
                        sku:
                          type: string
                        name:
                          type: string
                        quantity_available:
                          type: integer
                        ebay_listings:
                          type: array
                example:
                  data:
                  - product_id: 55
                    sku: PROD-001-B
                    name: Blue Widget (Blemished)
                    quantity_available: 12
                    ebay_listings: []
                  - product_id: 56
                    sku: PROD-002-B
                    name: Red Widget (Blemished)
                    quantity_available: 5
                    ebay_listings: []
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-ebay-global-reports-uncovered-blemished-products
  /api/ebay-global-reports/listed-blemished-products-out-of-stock:
    get:
      tags:
      - eBay
      summary: Listed Blemished Products Out of Stock
      description: 'Get blemished products that currently have active Ebay listings
        but are out of stock. Useful for identifying listings that should be ended
        or revised due to zero inventory. Requires Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        product_id:
                          type: integer
                        sku:
                          type: string
                        name:
                          type: string
                        quantity_available:
                          type: integer
                        ebay_listings:
                          type: array
                          items:
                            type: object
                            properties:
                              ItemID:
                                type: string
                              Title:
                                type: string
                              ListingStatus:
                                type: string
                              QuantityAvailable:
                                type: integer
                example:
                  data:
                  - product_id: 60
                    sku: PROD-005-B
                    name: Green Widget (Blemished)
                    quantity_available: 0
                    ebay_listings:
                    - ItemID: '999888777666'
                      Title: Green Widget Blemished
                      ListingStatus: Active
                      QuantityAvailable: 1
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-ebay-global-reports-listed-blemished-products-out-of-stock
  /api/ebay-global-reports/blemished-auto-list-instances:
    get:
      tags:
      - eBay
      summary: List Blemished Auto-List eBay Instances
      description: Return the eBay integration instances that have blemished auto-listing
        enabled. Use this to determine which instance a blemished product should be
        listed on before calling Auto-List Blemished Products. Requires Bearer token.
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        integration_instance_id:
                          type: integer
                        name:
                          type: string
                example:
                  data:
                  - integration_instance_id: 42
                    name: eBay US
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-ebay-global-reports-blemished-auto-list-instances
  /api/ebay-global-reports/uncovered-blemished-products/list:
    post:
      tags:
      - eBay
      summary: Auto-List Blemished Products on eBay
      description: 'Queue auto-listing of the given blemished products on an eBay
        integration instance that has blemished auto-listing enabled. Each product
        is listed as an auction-until-sold listing; products that are already listed,
        out of stock, or not blemished are skipped. Processing runs in the background
        and the response returns an id for tracking progress. Requires Bearer token.


        Body fields:

        - product_ids (array of integers, required, max 100): blemished product ids
        to list. Larger sets must be listed in batches of 100.

        - integration_instance_id (integer, required): the eBay instance to list on.
        Must have blemished auto-listing enabled.


        Returns 422 if the instance does not have blemished auto-listing enabled.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                product_ids:
                  type: array
                  items:
                    type: integer
                integration_instance_id:
                  type: integer
              example:
                product_ids:
                - 55
                - 56
                integration_instance_id: 42
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                      queued_count:
                        type: integer
                example:
                  data:
                    tracked_job_log_id: 9931
                    queued_count: 2
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Blemished auto-listing is not enabled for this eBay integration.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-ebay-global-reports-uncovered-blemished-products-list
  /api/ebay/{integrationInstance}/payouts:
    get:
      tags:
      - eBay
      summary: List Payouts
      description: 'Returns a paginated list of eBay Managed Payments payouts synced
        for the integration instance. Each payout includes the settlement amount,
        a normalized summary split (sales, refunds, fees, shipping labels, charges,
        disputes, adjustments, and net), the accounting status, and the number of
        transaction lines.


        Authentication: Requires Bearer token.


        Filterable columns: status, currency, accounting_status (text), amount (numeric),
        payout_date (date), created_at (datetime). filter[search] matches the payout
        ID and currency.


        Filtering: pass filter[column]=value for an exact match, or filter[column.operator]=value
        with operators such as contains, does_not_contain, is, is_not, is_one_of,
        starts_with, ends_with, is_empty, is_not_empty (text), greater_than, less_than,
        greater_than_or_equal, less_than_or_equal, between (numeric), and is, is_not,
        before, after, on_or_before, on_or_after, between, today, yesterday, past_week,
        past_month, past_year, days_ago, past_days (date/datetime). Complex AND/OR
        trees can be sent as a base64-encoded JSON tree in the filter_groups parameter.


        Allowed sorts: id, legacy_resource_id, payout_date, amount, status, accounting_status
        (prefix with - for descending; default -payout_date). Pagination defaults
        to 10 per page.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: eBay integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        legacy_resource_id:
                          type: string
                        payout_date:
                          type: string
                        status:
                          type: string
                        currency:
                          type: string
                        amount:
                          type: number
                        summary:
                          type: object
                          properties:
                            sales_gross:
                              type: number
                            refunds_gross:
                              type: integer
                            fees_total:
                              type: number
                            shipping_labels:
                              type: number
                            charges:
                              type: integer
                            disputes:
                              type: integer
                            adjustments:
                              type: integer
                            net:
                              type: number
                        accounting_status:
                          type: string
                        transaction_count:
                          type: integer
                        ebay_created_at:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  next_page_url:
                    type: string
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 12
                    legacy_resource_id: 5f4a8d90-1c7b-4f2e-9b3a-2d8e6f0a1b23
                    payout_date: '2026-07-10'
                    status: succeeded
                    currency: USD
                    amount: 1842.55
                    summary:
                      sales_gross: 2010.4
                      refunds_gross: -95
                      fees_total: -61.15
                      shipping_labels: -11.7
                      charges: 0
                      disputes: 0
                      adjustments: 0
                      net: 1842.55
                    accounting_status: pending
                    transaction_count: 46
                    ebay_created_at: '2026-07-10T04:02:11+00:00'
                    created_at: '2026-07-10T06:15:42+00:00'
                    updated_at: '2026-07-11T06:15:40+00:00'
                  first_page_url: '{{protocol}}://{{domain}}/api/ebay/1/payouts?page=1'
                  from: 1
                  last_page: 3
                  last_page_url: '{{protocol}}://{{domain}}/api/ebay/1/payouts?page=3'
                  next_page_url: '{{protocol}}://{{domain}}/api/ebay/1/payouts?page=2'
                  path: '{{protocol}}://{{domain}}/api/ebay/1/payouts'
                  per_page: 10
                  prev_page_url: null
                  to: 10
                  total: 27
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-ebay-integrationinstance-payouts
  /api/ebay/{integrationInstance}/payouts/filter-options:
    get:
      tags:
      - eBay
      summary: Get Payout Filter Options
      description: 'Returns the available filter values for the payouts list: every
        payout status and accounting status the system recognises, plus the settlement
        currencies present in the synced payouts for the integration instance.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: eBay integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      statuses:
                        type: array
                        items:
                          type: string
                      accounting_statuses:
                        type: array
                        items:
                          type: string
                      currencies:
                        type: array
                        items:
                          type: string
                example:
                  data:
                    statuses:
                    - initiated
                    - retryable_failed
                    - terminal_failed
                    - reversed
                    - succeeded
                    - funds_on_hold
                    - pending
                    accounting_statuses:
                    - pending
                    - ready
                    - posted
                    - held
                    - error
                    currencies:
                    - GBP
                    - USD
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-ebay-integrationinstance-payouts-filter-options
  /api/ebay/{integrationInstance}/payouts/sync:
    post:
      tags:
      - eBay
      summary: Sync Payouts
      description: 'Queues a background sync that imports eBay Managed Payments payouts
        and their transaction lines from eBay for the integration instance. Returns
        a tracked_job_log_id that can be used to monitor the progress of the sync.


        The request body is optional. With no body, the sync runs the default incremental
        (cursor-based) window. Supply mode to control the range: latest (incremental,
        default), from_start_date (from the instance start date to now), date_range
        (bounded by date_from/date_to), or all (full backfill). date_from and date_to
        are Y-m-d dates and apply when mode is date_range (date_to must be on or after
        date_from).


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                mode:
                  type: string
                date_from:
                  type: string
                date_to:
                  type: string
              example:
                mode: date_range
                date_from: '2026-06-01'
                date_to: '2026-06-30'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: eBay integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 4431
                  message: Payout sync job has been queued
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-ebay-integrationinstance-payouts-sync
  /api/ebay/{integrationInstance}/payouts/{payout}:
    get:
      tags:
      - eBay
      summary: Get Payout
      description: 'Returns the full detail of a single payout, including the raw
        summary breakdown, the payout instrument, and every transaction line with
        its per-fee breakdown and linked local order where resolved. Returns 403 if
        the payout does not belong to the integration instance.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: eBay integration instance ID
        example: '1'
      - name: payout
        in: path
        schema:
          type: integer
        required: true
        description: Payout ID
        example: '12'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      legacy_resource_id:
                        type: string
                      payout_date:
                        type: string
                      status:
                        type: string
                      currency:
                        type: string
                      amount:
                        type: number
                      summary:
                        type: object
                        properties:
                          sales_gross:
                            type: number
                          refunds_gross:
                            type: integer
                          fees_total:
                            type: number
                          shipping_labels:
                            type: number
                          charges:
                            type: integer
                          disputes:
                            type: integer
                          adjustments:
                            type: integer
                          net:
                            type: number
                      summary_json:
                        type: object
                        properties:
                          sales_gross:
                            type: number
                          refunds_gross:
                            type: integer
                          fees_total:
                            type: number
                          shipping_labels:
                            type: number
                      accounting_status:
                        type: string
                      base_currency_rate:
                        type: string
                        nullable: true
                      payout_instrument:
                        type: string
                      receipt_json:
                        type: string
                        nullable: true
                      ebay_created_at:
                        type: string
                      ebay_updated_at:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      transactions:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            legacy_transaction_id:
                              type: string
                            ebay_payout_id:
                              type: integer
                            transaction_type:
                              type: string
                            booking_entry:
                              type: string
                            financial_code:
                              type: string
                            amount:
                              type: number
                            total_fee_amount:
                              type: number
                            fees_json:
                              type: array
                              items:
                                type: object
                                properties:
                                  feeType:
                                    type: string
                                  amount:
                                    type: number
                            memo:
                              type: string
                              nullable: true
                            status:
                              type: string
                            ebay_order_id:
                              type: integer
                            order:
                              type: object
                              properties:
                                id:
                                  type: integer
                                order_id:
                                  type: string
                                link_reference:
                                  type: string
                                link_type_label:
                                  type: string
                                link_id:
                                  type: integer
                            created_at:
                              type: string
                            updated_at:
                              type: string
                      transaction_count:
                        type: integer
                      integration_instance:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          country:
                            type: string
                example:
                  data:
                    id: 12
                    legacy_resource_id: 5f4a8d90-1c7b-4f2e-9b3a-2d8e6f0a1b23
                    payout_date: '2026-07-10'
                    status: succeeded
                    currency: USD
                    amount: 1842.55
                    summary:
                      sales_gross: 2010.4
                      refunds_gross: -95
                      fees_total: -61.15
                      shipping_labels: -11.7
                      charges: 0
                      disputes: 0
                      adjustments: 0
                      net: 1842.55
                    summary_json:
                      sales_gross: 2010.4
                      refunds_gross: -95
                      fees_total: -61.15
                      shipping_labels: -11.7
                    accounting_status: pending
                    base_currency_rate: null
                    payout_instrument: Bank account ****6789
                    receipt_json: null
                    ebay_created_at: '2026-07-10T04:02:11+00:00'
                    ebay_updated_at: '2026-07-10T09:30:00+00:00'
                    created_at: '2026-07-10T06:15:42+00:00'
                    updated_at: '2026-07-11T06:15:40+00:00'
                    transactions:
                    - id: 501
                      legacy_transaction_id: 9911-0288-4471
                      ebay_payout_id: 12
                      transaction_type: sale
                      booking_entry: CREDIT
                      financial_code: sale
                      amount: 129.99
                      total_fee_amount: 17.06
                      fees_json:
                      - feeType: final_value_fee
                        amount: 15.79
                      - feeType: international_fee
                        amount: 1.27
                      memo: null
                      status: FUNDS_AVAILABLE_FOR_PAYOUT
                      ebay_order_id: 845
                      order:
                        id: 845
                        order_id: 12-08765-43210
                        link_reference: 12-08765-43210
                        link_type_label: eBay Order
                        link_id: 845
                      created_at: '2026-07-10T06:15:43+00:00'
                      updated_at: '2026-07-10T06:15:43+00:00'
                    - id: 502
                      legacy_transaction_id: 9911-0288-4472
                      ebay_payout_id: 12
                      transaction_type: non_sale_charge
                      booking_entry: DEBIT
                      financial_code: 'non_sale_charge: international-fee'
                      amount: -11.7
                      total_fee_amount: 0
                      fees_json: null
                      memo: International fee
                      status: FUNDS_AVAILABLE_FOR_PAYOUT
                      ebay_order_id: null
                      created_at: '2026-07-10T06:15:43+00:00'
                      updated_at: '2026-07-10T06:15:43+00:00'
                    transaction_count: 2
                    integration_instance:
                      id: 1
                      name: My eBay Store
                      country: US
        '403':
          description: Forbidden
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: Payout does not belong to this integration instance
        '429': *id001
        '401': *id002
        '404': *id004
      operationId: get-api-ebay-integrationinstance-payouts-payout
  /api/ebay/{integrationInstance}/payout-transactions:
    get:
      tags:
      - eBay
      summary: List Payout Transactions
      description: 'Returns a paginated list of eBay Managed Payments payout transaction
        lines across every payout synced for the integration instance — the line-level
        detail behind the payout summaries. Each line includes its transaction type,
        financial code, booking entry (CREDIT/DEBIT), gross amount, total fee amount,
        an itemized fee breakdown (fees_json), status, and cross-link blocks for the
        parent payout and (when matched) the eBay order.


        Authentication: Requires Bearer token.


        Filters: filter[search] matches the internal ID, eBay transaction ID, financial
        code, memo, or linked order (eBay order ID or internal order ID). filter[financial_code],
        filter[transaction_type], filter[booking_entry], filter[ebay_payout_id], and
        filter[id] are exact-match filters.


        Allowed sorts: id, amount, total_fee_amount, created_at (prefix with - for
        descending; default -id). Pagination defaults to 15 per page.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: eBay integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        legacy_transaction_id:
                          type: string
                        ebay_payout_id:
                          type: integer
                        transaction_type:
                          type: string
                        booking_entry:
                          type: string
                        financial_code:
                          type: string
                        amount:
                          type: number
                        total_fee_amount:
                          type: number
                        fees_json:
                          type: array
                          items:
                            type: object
                            properties:
                              feeType:
                                type: string
                              amount:
                                type: number
                        transaction_memo:
                          type: string
                          nullable: true
                        transaction_status:
                          type: string
                        memo:
                          type: string
                          nullable: true
                        status:
                          type: string
                        ebay_order_id:
                          type: integer
                        payout:
                          type: object
                          properties:
                            ebay_payout_id:
                              type: integer
                            legacy_resource_id:
                              type: string
                            payout_date:
                              type: string
                            link_reference:
                              type: string
                            link_type_label:
                              type: string
                            link_id:
                              type: integer
                            link_route:
                              type: string
                        order:
                          type: object
                          properties:
                            id:
                              type: integer
                            order_id:
                              type: string
                            link_reference:
                              type: string
                            link_type_label:
                              type: string
                            link_id:
                              type: integer
                            link_route:
                              type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  next_page_url:
                    type: string
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 8815
                    legacy_transaction_id: 9d2f1c40-5b7a-4e2c-8f3d-1a2b3c4d5e6f
                    ebay_payout_id: 12
                    transaction_type: SALE
                    booking_entry: CREDIT
                    financial_code: sale
                    amount: 84.5
                    total_fee_amount: 11.02
                    fees_json:
                    - feeType: FINAL_VALUE_FEE_FIXED_PER_ORDER
                      amount: 0.4
                    - feeType: FINAL_VALUE_FEE_VARIABLE_PER_ORDER
                      amount: 10.62
                    transaction_memo: null
                    transaction_status: FUNDS_AVAILABLE_FOR_PAYOUT
                    memo: null
                    status: FUNDS_AVAILABLE_FOR_PAYOUT
                    ebay_order_id: 5521
                    payout:
                      ebay_payout_id: 12
                      legacy_resource_id: 5f4a8d90-1c7b-4f2e-9b3a-2d8e6f0a1b23
                      payout_date: '2026-07-10'
                      link_reference: 5f4a8d90-1c7b-4f2e-9b3a-2d8e6f0a1b23
                      link_type_label: eBay Payout
                      link_id: 12
                      link_route: /integrations/ebay/finance/payout/12
                    order:
                      id: 5521
                      order_id: 12-34567-89012
                      link_reference: 12-34567-89012
                      link_type_label: eBay Order
                      link_id: 5521
                      link_route: /integrations/ebay/orders/5521
                    created_at: '2026-07-10T06:15:42+00:00'
                    updated_at: '2026-07-10T06:15:42+00:00'
                  first_page_url: '{{protocol}}://{{domain}}/api/ebay/1/payout-transactions?page=1'
                  from: 1
                  last_page: 5
                  last_page_url: '{{protocol}}://{{domain}}/api/ebay/1/payout-transactions?page=5'
                  next_page_url: '{{protocol}}://{{domain}}/api/ebay/1/payout-transactions?page=2'
                  path: '{{protocol}}://{{domain}}/api/ebay/1/payout-transactions'
                  per_page: 15
                  prev_page_url: null
                  to: 15
                  total: 68
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-ebay-integrationinstance-payout-transactions
  /api/ebay/{integrationInstance}/payout-transactions/filter-options:
    get:
      tags:
      - eBay
      summary: Get Payout Transaction Filter Options
      description: 'Returns the distinct filter values present in the synced payout
        transactions for the integration instance: every transaction type and every
        financial code, so a client can populate the transaction filters.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: eBay integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      transaction_types:
                        type: array
                        items:
                          type: string
                      financial_codes:
                        type: array
                        items:
                          type: string
                example:
                  data:
                    transaction_types:
                    - NON_SALE_CHARGE
                    - REFUND
                    - SALE
                    - SHIPPING_LABEL
                    financial_codes:
                    - refund
                    - sale
                    - shipping_label
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-ebay-integrationinstance-payout-transactions-filter-options
  /api/ebay/payout-mapping-groups:
    get:
      tags:
      - eBay
      summary: List Global Payout Mapping Groups
      description: 'Returns every global (workspace-wide) payout mapping group, ordered
        by sort order. Global groups apply to all eBay integration instances unless
        an instance defines its own groups. If no global groups exist yet, the two
        defaults (eBay Sales as an invoice group and eBay Fees as a bill group) are
        created and returned.


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: string
                          nullable: true
                        name:
                          type: string
                        document_type:
                          type: string
                        sort_order:
                          type: integer
                        mappings_count:
                          type: integer
                        created_at:
                          type: string
                        updated_at:
                          type: string
                example:
                  data:
                  - id: 1
                    integration_instance_id: null
                    name: eBay Sales
                    document_type: invoice
                    sort_order: 0
                    mappings_count: 7
                    created_at: '2026-07-17T09:00:00.000000Z'
                    updated_at: '2026-07-17T09:00:00.000000Z'
                  - id: 2
                    integration_instance_id: null
                    name: eBay Fees
                    document_type: bill
                    sort_order: 1
                    mappings_count: 3
                    created_at: '2026-07-17T09:00:00.000000Z'
                    updated_at: '2026-07-17T09:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-ebay-payout-mapping-groups
    post:
      tags:
      - eBay
      summary: Create Global Payout Mapping Group
      description: 'Creates a global payout mapping group that applies to every eBay
        integration instance. Type mappings assigned to the group are combined into
        a single financial document of the group''s document type when a payout is
        posted.


        Authentication: Requires Bearer token.


        Request body:

        - name (required, string, max 255): display name for the group.

        - document_type (required, string): financial document the group posts to;
        one of invoice, bill.

        - sort_order (optional, integer, min 0): position of the group in ordered
        listings.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                document_type:
                  type: string
                sort_order:
                  type: integer
              example:
                name: Marketplace Charges
                document_type: bill
                sort_order: 2
      parameters: []
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: integer
                  integration_instance_id:
                    type: string
                    nullable: true
                  name:
                    type: string
                  document_type:
                    type: string
                  sort_order:
                    type: integer
                  created_at:
                    type: string
                  updated_at:
                    type: string
                example:
                  id: 3
                  integration_instance_id: null
                  name: Marketplace Charges
                  document_type: bill
                  sort_order: 2
                  created_at: '2026-07-17T11:20:00.000000Z'
                  updated_at: '2026-07-17T11:20:00.000000Z'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      name:
                        type: array
                        items:
                          type: string
                      document_type:
                        type: array
                        items:
                          type: string
                example:
                  message: A document type (invoice or bill) is required.
                  errors:
                    name:
                    - The name field is required.
                    document_type:
                    - A document type (invoice or bill) is required.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-ebay-payout-mapping-groups
  /api/ebay/payout-mapping-groups/reorder:
    post:
      tags:
      - eBay
      summary: Reorder Global Payout Mapping Groups
      description: 'Reorders the global payout mapping groups. Pass the full list
        of global group IDs in the desired order; each group''s sort order is updated
        to match its position in the list.


        Authentication: Requires Bearer token.


        Request body:

        - ids (required, array of integers, min 1): mapping group IDs in the desired
        display order. Each ID must reference an existing payout mapping group.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 2
                - 1
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Groups reordered successfully.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      ids:
                        type: array
                        items:
                          type: string
                example:
                  message: At least one mapping group id is required to reorder.
                  errors:
                    ids:
                    - At least one mapping group id is required to reorder.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-ebay-payout-mapping-groups-reorder
  /api/ebay/payout-mapping-groups/{payoutMappingGroup}:
    put:
      tags:
      - eBay
      summary: Update Global Payout Mapping Group
      description: 'Updates the name, document type, or sort order of a global payout
        mapping group.


        Authentication: Requires Bearer token.


        Request body:

        - name (required, string, max 255): display name for the group.

        - document_type (required, string): financial document the group posts to;
        one of invoice, bill.

        - sort_order (optional, integer, min 0): position of the group in ordered
        listings.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                document_type:
                  type: string
                sort_order:
                  type: integer
              example:
                name: eBay Sales - US
                document_type: invoice
                sort_order: 0
      parameters:
      - name: payoutMappingGroup
        in: path
        schema:
          type: integer
        required: true
        description: Payout mapping group ID
        example: '5'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: integer
                  integration_instance_id:
                    type: string
                    nullable: true
                  name:
                    type: string
                  document_type:
                    type: string
                  sort_order:
                    type: integer
                  created_at:
                    type: string
                  updated_at:
                    type: string
                example:
                  id: 1
                  integration_instance_id: null
                  name: eBay Sales - US
                  document_type: invoice
                  sort_order: 0
                  created_at: '2026-07-17T09:00:00.000000Z'
                  updated_at: '2026-07-17T11:45:00.000000Z'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      name:
                        type: array
                        items:
                          type: string
                      document_type:
                        type: array
                        items:
                          type: string
                example:
                  message: A document type (invoice or bill) is required.
                  errors:
                    name:
                    - The name field is required.
                    document_type:
                    - A document type (invoice or bill) is required.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: put-api-ebay-payout-mapping-groups-payoutmappinggroup
    delete:
      tags:
      - eBay
      summary: Delete Global Payout Mapping Group
      description: 'Deletes a global payout mapping group. Type mappings that referenced
        the group are kept but left without a group assignment.


        Authentication: Requires Bearer token.'
      parameters:
      - name: payoutMappingGroup
        in: path
        schema:
          type: integer
        required: true
        description: Payout mapping group ID
        example: '5'
      responses:
        '204':
          description: No Content
          content:
            application/json:
              schema:
                type: object
                properties: {}
                example: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-ebay-payout-mapping-groups-payoutmappinggroup
  /api/ebay/{integrationInstance}/payout-mapping-groups:
    get:
      tags:
      - eBay
      summary: List Payout Mapping Groups
      description: 'Returns the payout mapping groups visible to the integration instance:
        the instance''s own groups first, followed by the global groups. If no global
        groups exist yet, the two defaults (eBay Sales as an invoice group and eBay
        Fees as a bill group) are created first.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: eBay integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        name:
                          type: string
                        document_type:
                          type: string
                        sort_order:
                          type: integer
                        mappings_count:
                          type: integer
                        created_at:
                          type: string
                        updated_at:
                          type: string
                example:
                  data:
                  - id: 5
                    integration_instance_id: 1
                    name: US Store Charges
                    document_type: bill
                    sort_order: 0
                    mappings_count: 2
                    created_at: '2026-07-17T10:12:00.000000Z'
                    updated_at: '2026-07-17T10:12:00.000000Z'
                  - id: 1
                    integration_instance_id: null
                    name: eBay Sales
                    document_type: invoice
                    sort_order: 0
                    mappings_count: 7
                    created_at: '2026-07-17T09:00:00.000000Z'
                    updated_at: '2026-07-17T09:00:00.000000Z'
                  - id: 2
                    integration_instance_id: null
                    name: eBay Fees
                    document_type: bill
                    sort_order: 1
                    mappings_count: 3
                    created_at: '2026-07-17T09:00:00.000000Z'
                    updated_at: '2026-07-17T09:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-ebay-integrationinstance-payout-mapping-groups
    post:
      tags:
      - eBay
      summary: Create Payout Mapping Group
      description: 'Creates a payout mapping group scoped to the integration instance.
        Instance groups are listed ahead of the global defaults and can be used to
        separate the instance''s payout lines into their own financial documents.


        Authentication: Requires Bearer token.


        Request body:

        - name (required, string, max 255): display name for the group.

        - document_type (required, string): financial document the group posts to;
        one of invoice, bill.

        - sort_order (optional, integer, min 0): position of the group in ordered
        listings.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                document_type:
                  type: string
                sort_order:
                  type: integer
              example:
                name: Marketplace Charges
                document_type: bill
                sort_order: 2
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: eBay integration instance ID
        example: '1'
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: integer
                  integration_instance_id:
                    type: integer
                  name:
                    type: string
                  document_type:
                    type: string
                  sort_order:
                    type: integer
                  created_at:
                    type: string
                  updated_at:
                    type: string
                example:
                  id: 6
                  integration_instance_id: 1
                  name: Marketplace Charges
                  document_type: bill
                  sort_order: 2
                  created_at: '2026-07-17T11:20:00.000000Z'
                  updated_at: '2026-07-17T11:20:00.000000Z'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      name:
                        type: array
                        items:
                          type: string
                      document_type:
                        type: array
                        items:
                          type: string
                example:
                  message: A document type (invoice or bill) is required.
                  errors:
                    name:
                    - The name field is required.
                    document_type:
                    - A document type (invoice or bill) is required.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-ebay-integrationinstance-payout-mapping-groups
  /api/ebay/{integrationInstance}/payout-mapping-groups/reorder:
    post:
      tags:
      - eBay
      summary: Reorder Payout Mapping Groups
      description: 'Reorders the payout mapping groups scoped to the integration instance.
        Pass the full list of the instance''s group IDs in the desired order; each
        group''s sort order is updated to match its position in the list. Global groups
        are not affected.


        Authentication: Requires Bearer token.


        Request body:

        - ids (required, array of integers, min 1): mapping group IDs in the desired
        display order. Each ID must reference an existing payout mapping group.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 6
                - 5
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: eBay integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Groups reordered successfully.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      ids:
                        type: array
                        items:
                          type: string
                example:
                  message: At least one mapping group id is required to reorder.
                  errors:
                    ids:
                    - At least one mapping group id is required to reorder.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-ebay-integrationinstance-payout-mapping-groups-reorder
  /api/ebay/{integrationInstance}/payout-mapping-groups/{payoutMappingGroup}:
    put:
      tags:
      - eBay
      summary: Update Payout Mapping Group
      description: 'Updates the name, document type, or sort order of a payout mapping
        group scoped to the integration instance.


        Authentication: Requires Bearer token.


        Request body:

        - name (required, string, max 255): display name for the group.

        - document_type (required, string): financial document the group posts to;
        one of invoice, bill.

        - sort_order (optional, integer, min 0): position of the group in ordered
        listings.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                document_type:
                  type: string
                sort_order:
                  type: integer
              example:
                name: eBay Sales - US
                document_type: invoice
                sort_order: 0
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: eBay integration instance ID
        example: '1'
      - name: payoutMappingGroup
        in: path
        schema:
          type: integer
        required: true
        description: Payout mapping group ID
        example: '5'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: integer
                  integration_instance_id:
                    type: integer
                  name:
                    type: string
                  document_type:
                    type: string
                  sort_order:
                    type: integer
                  created_at:
                    type: string
                  updated_at:
                    type: string
                example:
                  id: 5
                  integration_instance_id: 1
                  name: eBay Sales - US
                  document_type: invoice
                  sort_order: 0
                  created_at: '2026-07-17T10:12:00.000000Z'
                  updated_at: '2026-07-17T11:45:00.000000Z'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      name:
                        type: array
                        items:
                          type: string
                      document_type:
                        type: array
                        items:
                          type: string
                example:
                  message: A document type (invoice or bill) is required.
                  errors:
                    name:
                    - The name field is required.
                    document_type:
                    - A document type (invoice or bill) is required.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: put-api-ebay-integrationinstance-payout-mapping-groups-payoutmappinggroup
    delete:
      tags:
      - eBay
      summary: Delete Payout Mapping Group
      description: 'Deletes a payout mapping group scoped to the integration instance.
        Type mappings that referenced the group are kept but left without a group
        assignment.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: eBay integration instance ID
        example: '1'
      - name: payoutMappingGroup
        in: path
        schema:
          type: integer
        required: true
        description: Payout mapping group ID
        example: '5'
      responses:
        '204':
          description: No Content
          content:
            application/json:
              schema:
                type: object
                properties: {}
                example: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-ebay-integrationinstance-payout-mapping-groups-payoutmappinggroup
  /api/ebay/{integrationInstance}/payout-type-mappings:
    get:
      tags:
      - eBay
      summary: List Payout Type Mappings
      description: 'Returns the resolved payout type mappings for the integration
        instance: per-instance override rows plus the global default rows they have
        not overridden. Each row maps a financial code (a normalized transaction type,
        expanded with its memo for non-sale charges) to a general-ledger account and
        an optional mapping group; is_override indicates an instance-specific row.
        eBay payout transactions carry no separate source type, so source_type is
        typically empty and the reason is taken from the transaction memo. Before
        listing, any financial codes newly seen in the instance''s synced payout transactions
        are registered as unmapped global rows so they can be configured.


        Authentication: Requires Bearer token.


        Filterable columns: type, source_type, reason, financial_code, typical_amount_sign,
        mapping_status (mapped/unmapped), group_status (assigned/unassigned) (text),
        created_at, updated_at (datetime). filter[search] matches type, source type,
        reason, and financial code.


        Filtering: pass filter[column]=value for an exact match, or filter[column.operator]=value
        with operators such as contains, does_not_contain, is, is_not, is_one_of,
        starts_with, ends_with, is_empty, is_not_empty (text), greater_than, less_than,
        greater_than_or_equal, less_than_or_equal, between (numeric), and is, is_not,
        before, after, on_or_before, on_or_after, between, today, yesterday, past_week,
        past_month, past_year, days_ago, past_days (date/datetime). Complex AND/OR
        trees can be sent as a base64-encoded JSON tree in the filter_groups parameter.


        Allowed sorts: type, source_type, financial_code, created_at (prefix with
        - for descending; default financial_code). Pagination defaults to 10 per page.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: eBay integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        type:
                          type: string
                        source_type:
                          type: string
                          nullable: true
                        reason:
                          type: string
                          nullable: true
                        financial_code:
                          type: string
                        typical_amount_sign:
                          type: string
                        ebay_payout_mapping_group_id:
                          type: integer
                        nominalCode:
                          type: object
                          properties:
                            id:
                              type: integer
                            code:
                              type: string
                            name:
                              type: string
                        mappingGroup:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            document_type:
                              type: string
                        is_override:
                          type: boolean
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  next_page_url:
                    type: string
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 7
                    integration_instance_id: 1
                    type: sale
                    source_type: null
                    reason: null
                    financial_code: sale
                    typical_amount_sign: positive
                    ebay_payout_mapping_group_id: 1
                    nominalCode:
                      id: 210
                      code: '4000'
                      name: Sales Revenue
                    mappingGroup:
                      id: 1
                      name: eBay Sales
                      document_type: invoice
                    is_override: true
                    created_at: '2026-07-17T09:00:00.000000Z'
                    updated_at: '2026-07-17T09:05:00.000000Z'
                  - id: 3
                    integration_instance_id: null
                    type: non_sale_charge
                    source_type: null
                    reason: International fee
                    financial_code: 'non_sale_charge: international-fee'
                    typical_amount_sign: negative
                    ebay_payout_mapping_group_id: null
                    nominalCode: null
                    mappingGroup: null
                    is_override: false
                    created_at: '2026-07-17T09:00:00.000000Z'
                    updated_at: '2026-07-17T09:00:00.000000Z'
                  first_page_url: '{{protocol}}://{{domain}}/api/ebay/1/payout-type-mappings?page=1'
                  from: 1
                  last_page: 2
                  last_page_url: '{{protocol}}://{{domain}}/api/ebay/1/payout-type-mappings?page=2'
                  next_page_url: '{{protocol}}://{{domain}}/api/ebay/1/payout-type-mappings?page=2'
                  path: '{{protocol}}://{{domain}}/api/ebay/1/payout-type-mappings'
                  per_page: 10
                  prev_page_url: null
                  to: 10
                  total: 14
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-ebay-integrationinstance-payout-type-mappings
    put:
      tags:
      - eBay
      summary: Update Payout Type Mappings
      description: 'Updates individual payout type mappings, assigning or clearing
        the general-ledger account and mapping group of each. Fields omitted from
        a mapping entry are left unchanged; pass null to clear an assignment.


        Authentication: Requires Bearer token.


        Request body:

        - mappings (required, array, min 1): mapping updates to apply.

        - mappings[].id (required, integer): ID of an existing payout type mapping
        that is global or belongs to this integration instance.

        - mappings[].nominal_code_id (optional, nullable, integer): general-ledger
        account to assign; must reference an existing account. Pass null to clear.

        - mappings[].ebay_payout_mapping_group_id (optional, nullable, integer): payout
        mapping group to assign; must reference an existing group that is global or
        belongs to this instance. Pass null to clear.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                mappings:
                  type: array
                  items:
                    type: object
                    properties:
                      id:
                        type: integer
                      nominal_code_id:
                        type: integer
                      ebay_payout_mapping_group_id:
                        type: integer
              example:
                mappings:
                - id: 7
                  nominal_code_id: 210
                  ebay_payout_mapping_group_id: 1
                - id: 3
                  nominal_code_id: 305
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: eBay integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Payout type mappings updated successfully.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      mappings:
                        type: array
                        items:
                          type: string
                example:
                  message: At least one type mapping is required.
                  errors:
                    mappings:
                    - At least one type mapping is required.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: put-api-ebay-integrationinstance-payout-type-mappings
  /api/ebay/{integrationInstance}/payout-type-mappings/bulk-assign:
    put:
      tags:
      - eBay
      summary: Bulk Assign Payout Type Mappings
      description: 'Assigns a general-ledger account and/or a mapping group to several
        payout type mappings at once. At least one of nominal_code_id or ebay_payout_mapping_group_id
        must be provided; pass null to clear that assignment on all selected mappings.
        Only mappings scoped to the integration instance are updated - global rows
        are not modified.


        Authentication: Requires Bearer token.


        Request body:

        - ids (required, array of integers, min 1): payout type mapping IDs to update.
        Each ID must reference an existing payout type mapping.

        - nominal_code_id (optional, nullable, integer): general-ledger account to
        assign to all selected mappings; must reference an existing account.

        - ebay_payout_mapping_group_id (optional, nullable, integer): payout mapping
        group to assign to all selected mappings; must reference an existing group
        that is global or belongs to this instance.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
                nominal_code_id:
                  type: integer
                ebay_payout_mapping_group_id:
                  type: integer
              example:
                ids:
                - 3
                - 7
                - 9
                nominal_code_id: 210
                ebay_payout_mapping_group_id: 1
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: eBay integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      updated:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    updated: 3
                  message: 3 type mapping(s) updated successfully.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      nominal_code_id:
                        type: array
                        items:
                          type: string
                example:
                  message: At least one of nominal_code_id or ebay_payout_mapping_group_id
                    must be provided.
                  errors:
                    nominal_code_id:
                    - At least one of nominal_code_id or ebay_payout_mapping_group_id
                      must be provided.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: put-api-ebay-integrationinstance-payout-type-mappings-bulk-assign
  /api/ebay/{integrationInstance}/payout-finance-settings:
    get:
      tags:
      - eBay
      summary: Get Payout Finance Settings
      description: 'Returns the resolved payout finance settings for the integration
        instance: the fallback revenue and expense accounts used for unmapped payout
        lines, the clearing account payouts settle against, the accounting sync mode
        (per_order or per_payout; default per_order), and the optional payout accounting
        start date before which payouts are not posted. Fallback and clearing accounts
        fall back to the workspace-wide values when the instance has none of its own.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: eBay integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  fallback_revenue_nominal_code_id:
                    type: integer
                  fallback_expense_nominal_code_id:
                    type: integer
                  clearing_nominal_code_id:
                    type: integer
                  accounting_sync_mode:
                    type: string
                  payout_accounting_start_date:
                    type: string
                example:
                  fallback_revenue_nominal_code_id: 220
                  fallback_expense_nominal_code_id: 310
                  clearing_nominal_code_id: 145
                  accounting_sync_mode: per_payout
                  payout_accounting_start_date: '2026-07-01'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-ebay-integrationinstance-payout-finance-settings
    put:
      tags:
      - eBay
      summary: Update Payout Finance Settings
      description: 'Updates the payout finance settings for the integration instance.
        All fields are optional; omitted fields keep their current values, and nullable
        fields can be set to null to clear them. Returns the resolved settings after
        the update.


        Authentication: Requires Bearer token.


        Request body:

        - fallback_revenue_nominal_code_id (optional, nullable, integer): account
        for unmapped revenue lines; must reference an existing general-ledger account.

        - fallback_expense_nominal_code_id (optional, nullable, integer): account
        for unmapped expense lines; must reference an existing general-ledger account.

        - clearing_nominal_code_id (optional, nullable, integer): clearing account
        that payout documents settle against; must reference an existing general-ledger
        account.

        - accounting_sync_mode (optional, string): one of per_order, per_payout.

        - payout_accounting_start_date (optional, nullable, date): payouts dated before
        this are not posted to accounting.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                fallback_revenue_nominal_code_id:
                  type: integer
                fallback_expense_nominal_code_id:
                  type: integer
                clearing_nominal_code_id:
                  type: integer
                accounting_sync_mode:
                  type: string
                payout_accounting_start_date:
                  type: string
              example:
                fallback_revenue_nominal_code_id: 220
                fallback_expense_nominal_code_id: 310
                clearing_nominal_code_id: 145
                accounting_sync_mode: per_payout
                payout_accounting_start_date: '2026-07-01'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: eBay integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  fallback_revenue_nominal_code_id:
                    type: integer
                  fallback_expense_nominal_code_id:
                    type: integer
                  clearing_nominal_code_id:
                    type: integer
                  accounting_sync_mode:
                    type: string
                  payout_accounting_start_date:
                    type: string
                example:
                  fallback_revenue_nominal_code_id: 220
                  fallback_expense_nominal_code_id: 310
                  clearing_nominal_code_id: 145
                  accounting_sync_mode: per_payout
                  payout_accounting_start_date: '2026-07-01'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      accounting_sync_mode:
                        type: array
                        items:
                          type: string
                example:
                  message: The selected accounting sync mode is invalid.
                  errors:
                    accounting_sync_mode:
                    - The selected accounting sync mode is invalid.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: put-api-ebay-integrationinstance-payout-finance-settings
  /api/big-commerce:
    get:
      tags:
      - BigCommerce
      summary: List Integration Instances
      description: 'List all BigCommerce integration instances (list view endpoint).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Query parameters:

        - search: string — full-text search

        - sort: string — column name (prefix with - for descending, e.g. -created_at)

        - limit: integer — records per page (default 10)

        - page: integer — page number

        - archived: 0|1 — include archived instances (default 0)

        - included[]: JSON-encoded array of additional columns to include

        - excluded[]: JSON-encoded array of columns to exclude

        - table_specifications: 1 — return only table column specifications'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            text/plain:
              schema:
                type: string
                example: '{"data": [{"id": 1, "integration_id": 5, "name": "My BigCommerce
                  Store", "connection_status": "connected", "is_automatic_sync_enabled":
                  true, "integration_settings": {"store_hash": "abc123xyz", "start_date":
                  "2024-01-01", "store_id": 1, "auto_link_products": true, "auto_create_products":
                  false}, "created_at": "2024-01-15T00:00:00.000000Z", "updated_at":
                  "2024-06-01T00:00:00.000000Z", "integration_name": "BigCommerce",
                  "store": {"id": 1, "name": "Main Store"}}, "total": 1, "per_page":
                  10, "current_page": 1, "last_page": 1]}'
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-big-commerce
    post:
      tags:
      - BigCommerce
      summary: Create Integration Instance
      description: 'Create a new BigCommerce integration instance. After creation,
        automatically dispatches jobs to refresh products and orders from BigCommerce.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Fields:

        - name (required, string, unique): Human-readable name for this integration
        instance

        - integration_id (required, integer): ID of the BigCommerce integration type

        - connection_settings.access_token (required, string): BigCommerce API access
        token

        - integration_settings.store_hash (required, string, not a URL): BigCommerce
        store hash identifier

        - integration_settings.start_date (required, string): Date to start syncing
        orders/products from (YYYY-MM-DD)

        - integration_settings.store_id (required, integer): Internal store ID to
        associate with

        - integration_settings.auto_link_products (required, boolean): Automatically
        link BigCommerce products to SKU products

        - integration_settings.auto_create_products (required, boolean): Automatically
        create SKU products from BigCommerce products

        - integration_settings.sales_nominal_code_id (nullable, integer): Nominal
        code ID for sales accounting

        - integration_settings.cogs_nominal_code_id (nullable, integer): Nominal code
        ID for cost of goods sold

        - integration_settings.shipping_revenue_nominal_code_id (nullable, integer):
        Nominal code ID for shipping revenue

        - integration_settings.shipping_refund_nominal_code_id (nullable, integer):
        Nominal code ID for shipping refunds

        - integration_settings.sales_returns_allowances_nominal_code_id (nullable,
        integer): Nominal code ID for returns

        - integration_settings.sync_sales_order_invoices_to_accounting (boolean, default
        true): Sync invoices to accounting

        - integration_settings.sync_sales_credit_to_accounting (boolean, default true):
        Sync credits to accounting

        - integration_settings.proforma_marketplace_cost_percentage (nullable, float):
        Marketplace cost percentage

        - integration_settings.proforma_payment_cost_percentage (nullable, float):
        Payment cost percentage

        - integration_settings.batch_period_sales_order_fulfillments (nullable, string):
        Batch period override for fulfillments

        - integration_settings.batch_period_customer_returns (nullable, string): Batch
        period override for customer returns

        - is_automatic_sync_enabled (boolean, default false): Enable automatic synchronization'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                integration_id:
                  type: integer
                connection_settings:
                  type: object
                  properties:
                    access_token:
                      type: string
                integration_settings:
                  type: object
                  properties:
                    store_hash:
                      type: string
                    start_date:
                      type: string
                    store_id:
                      type: integer
                    auto_link_products:
                      type: boolean
                    auto_create_products:
                      type: boolean
                    sales_nominal_code_id:
                      type: string
                      nullable: true
                    cogs_nominal_code_id:
                      type: string
                      nullable: true
                    shipping_revenue_nominal_code_id:
                      type: string
                      nullable: true
                    shipping_refund_nominal_code_id:
                      type: string
                      nullable: true
                    sales_returns_allowances_nominal_code_id:
                      type: string
                      nullable: true
                    sync_sales_order_invoices_to_accounting:
                      type: boolean
                    sync_sales_credit_to_accounting:
                      type: boolean
                is_automatic_sync_enabled:
                  type: boolean
              example:
                name: My BigCommerce Store
                integration_id: 5
                connection_settings:
                  access_token: abc123xyz_access_token
                integration_settings:
                  store_hash: abc123xyz
                  start_date: '2024-01-01'
                  store_id: 1
                  auto_link_products: true
                  auto_create_products: false
                  sales_nominal_code_id: null
                  cogs_nominal_code_id: null
                  shipping_revenue_nominal_code_id: null
                  shipping_refund_nominal_code_id: null
                  sales_returns_allowances_nominal_code_id: null
                  sync_sales_order_invoices_to_accounting: true
                  sync_sales_credit_to_accounting: true
                is_automatic_sync_enabled: false
      parameters: []
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_id:
                        type: integer
                      name:
                        type: string
                      connection_status:
                        type: string
                      is_automatic_sync_enabled:
                        type: boolean
                      created_at:
                        type: string
                      updated_at:
                        type: string
                  message:
                    type: string
                    nullable: true
                example:
                  data:
                    id: 1
                    integration_id: 5
                    name: My BigCommerce Store
                    connection_status: connected
                    is_automatic_sync_enabled: false
                    created_at: '2024-01-15T00:00:00.000000Z'
                    updated_at: '2024-01-15T00:00:00.000000Z'
                  message: null
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      name:
                        type: array
                        items:
                          type: string
                      integration_settings.store_hash:
                        type: array
                        items:
                          type: string
                example:
                  message: The name has already been taken.
                  errors:
                    name:
                    - The name has already been taken.
                    integration_settings.store_hash:
                    - The store hash field is required.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-big-commerce
  /api/big-commerce/{integrationInstance}:
    get:
      tags:
      - BigCommerce
      summary: Get Integration Instance
      description: 'Get a single BigCommerce integration instance with salesChannel
        and integration relationships loaded.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_id:
                        type: integer
                      name:
                        type: string
                      connection_status:
                        type: string
                      is_automatic_sync_enabled:
                        type: boolean
                      connection_settings:
                        type: object
                        properties:
                          access_token:
                            type: string
                      integration_settings:
                        type: object
                        properties:
                          store_hash:
                            type: string
                          start_date:
                            type: string
                          store_id:
                            type: integer
                          auto_link_products:
                            type: boolean
                          auto_create_products:
                            type: boolean
                          sync_sales_order_invoices_to_accounting:
                            type: boolean
                          sync_sales_credit_to_accounting:
                            type: boolean
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      integration_name:
                        type: string
                      store:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                example:
                  data:
                    id: 1
                    integration_id: 5
                    name: My BigCommerce Store
                    connection_status: connected
                    is_automatic_sync_enabled: true
                    connection_settings:
                      access_token: '***masked***'
                    integration_settings:
                      store_hash: abc123xyz
                      start_date: '2024-01-01'
                      store_id: 1
                      auto_link_products: true
                      auto_create_products: false
                      sync_sales_order_invoices_to_accounting: true
                      sync_sales_credit_to_accounting: true
                    created_at: '2024-01-15T00:00:00.000000Z'
                    updated_at: '2024-06-01T00:00:00.000000Z'
                    integration_name: BigCommerce
                    store:
                      id: 1
                      name: Main Store
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No query results for model [Modules\BigCommerce\Entities\BigCommerceIntegrationInstance].
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-big-commerce-integrationinstance
    put:
      tags:
      - BigCommerce
      summary: Update Integration Instance
      description: 'Update a BigCommerce integration instance. Supports both PUT (full
        update) and PATCH (partial update — merges connection_settings and integration_settings
        with existing values).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        All fields are optional for PATCH. For PUT, provide all settings fields.


        Side effects:

        - If start_date changes, updates the sales channel date

        - If pricing.masterOfPrice changes, dispatches a job to re-cache product listing
        prices

        - If inventory settings change, invalidates the entire inventory cache

        - If accounting sync settings change, updates related accounting transactions'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                integration_settings:
                  type: object
                  properties:
                    store_hash:
                      type: string
                    start_date:
                      type: string
                    store_id:
                      type: integer
                    auto_link_products:
                      type: boolean
                    auto_create_products:
                      type: boolean
                    sales_nominal_code_id:
                      type: string
                      nullable: true
                    cogs_nominal_code_id:
                      type: string
                      nullable: true
                    shipping_revenue_nominal_code_id:
                      type: string
                      nullable: true
                    shipping_refund_nominal_code_id:
                      type: string
                      nullable: true
                    sales_returns_allowances_nominal_code_id:
                      type: string
                      nullable: true
                    sync_sales_order_invoices_to_accounting:
                      type: boolean
                    sync_sales_credit_to_accounting:
                      type: boolean
                is_automatic_sync_enabled:
                  type: boolean
              example:
                name: My BigCommerce Store Updated
                integration_settings:
                  store_hash: abc123xyz
                  start_date: '2024-01-01'
                  store_id: 1
                  auto_link_products: true
                  auto_create_products: false
                  sales_nominal_code_id: null
                  cogs_nominal_code_id: null
                  shipping_revenue_nominal_code_id: null
                  shipping_refund_nominal_code_id: null
                  sales_returns_allowances_nominal_code_id: null
                  sync_sales_order_invoices_to_accounting: true
                  sync_sales_credit_to_accounting: true
                is_automatic_sync_enabled: true
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      is_automatic_sync_enabled:
                        type: boolean
                      integration_settings:
                        type: object
                        properties:
                          store_hash:
                            type: string
                          start_date:
                            type: string
                          store_id:
                            type: integer
                          auto_link_products:
                            type: boolean
                          auto_create_products:
                            type: boolean
                          sync_sales_order_invoices_to_accounting:
                            type: boolean
                          sync_sales_credit_to_accounting:
                            type: boolean
                      updated_at:
                        type: string
                example:
                  data:
                    id: 1
                    name: My BigCommerce Store Updated
                    is_automatic_sync_enabled: true
                    integration_settings:
                      store_hash: abc123xyz
                      start_date: '2024-01-01'
                      store_id: 1
                      auto_link_products: true
                      auto_create_products: false
                      sync_sales_order_invoices_to_accounting: true
                      sync_sales_credit_to_accounting: true
                    updated_at: '2024-06-10T00:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-big-commerce-integrationinstance
    patch:
      tags:
      - BigCommerce
      summary: Partial Update Integration Instance
      description: 'Partially update a BigCommerce integration instance. Settings
        are deep-merged with existing values — only send the fields you want to change.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                is_automatic_sync_enabled:
                  type: boolean
              example:
                is_automatic_sync_enabled: true
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      is_automatic_sync_enabled:
                        type: boolean
                      updated_at:
                        type: string
                example:
                  data:
                    id: 1
                    name: My BigCommerce Store
                    is_automatic_sync_enabled: true
                    updated_at: '2024-06-10T00:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: patch-api-big-commerce-integrationinstance
    delete:
      tags:
      - BigCommerce
      summary: Delete Integration Instance
      description: 'Delete a BigCommerce integration instance. Dispatches a background
        job to clean up associated data asynchronously.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '1'
      responses:
        '204':
          description: No Content
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            text/plain:
              schema:
                type: string
                example: ''
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-big-commerce-integrationinstance
  /api/big-commerce/{integration_instance}/store-mapped-warehouse-locations:
    put:
      tags:
      - BigCommerce
      summary: Store Mapped Warehouse Locations
      description: 'Map BigCommerce locations to internal warehouses. Updates the
        warehouse_id for each BigCommerce location.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Fields:

        - warehouse_mappings (required, array): Array of location-to-warehouse mappings

        - warehouse_mappings.*.location_id (required, integer): BigCommerce location
        ID (must exist in big_commerce_locations)

        - warehouse_mappings.*.warehouse_id (nullable, integer): Internal warehouse
        ID (must exist in warehouses table, or null to unmap)'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                warehouse_mappings:
                  type: array
                  items:
                    type: object
                    properties:
                      location_id:
                        type: integer
                      warehouse_id:
                        type: integer
              example:
                warehouse_mappings:
                - location_id: 101
                  warehouse_id: 2
                - location_id: 102
                  warehouse_id: null
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: string
                    nullable: true
                  message:
                    type: string
                example:
                  data: null
                  message: Warehouse mappings updated successfully.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      warehouse_mappings.0.location_id:
                        type: array
                        items:
                          type: string
                example:
                  message: The warehouse mappings.0.location id field must exist in
                    big commerce locations.
                  errors:
                    warehouse_mappings.0.location_id:
                    - The warehouse mappings.0.location id field must exist in big
                      commerce locations.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: put-api-big-commerce-integration-instance-store-mapped-warehouse-locations
  /api/big-commerce/{integration_instance}/download-locations:
    get:
      tags:
      - BigCommerce
      summary: Download Locations
      description: 'Sync BigCommerce locations synchronously (runs a background job
        inline) and return the current list of BigCommerce locations along with configured
        inventory locations from the integration settings.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      bigCommerceLocations:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            location_id:
                              type: integer
                            integration_instance_id:
                              type: integer
                            name:
                              type: string
                            code:
                              type: string
                            type:
                              type: string
                            warehouse_id:
                              type: integer
                            created_at:
                              type: string
                      inventoryLocations:
                        type: array
                        items:
                          type: object
                          properties:
                            location_id:
                              type: integer
                            warehouse_id:
                              type: integer
                example:
                  data:
                    bigCommerceLocations:
                    - id: 1
                      location_id: 101
                      integration_instance_id: 1
                      name: Main Warehouse
                      code: MAIN
                      type: PHYSICAL
                      warehouse_id: 2
                      created_at: '2024-01-15T00:00:00.000000Z'
                    inventoryLocations:
                    - location_id: 101
                      warehouse_id: 2
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-big-commerce-integration-instance-download-locations
  /api/big-commerce/{integrationInstance}/get-authorization-url:
    get:
      tags:
      - BigCommerce
      summary: Get Authorization URL
      description: 'Get the BigCommerce OAuth authorization URL for connecting the
        integration. Redirect the user to this URL to begin the OAuth flow.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: string
                example:
                  data: https://login.bigcommerce.com/oauth2/authorize?client_id=abc123&redirect_uri=https%3A%2F%2Fapp.sku.io%2Fbig-commerce%2Fcallback&response_type=code&scope=store_v2_products+store_v2_orders
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-big-commerce-integrationinstance-get-authorization-url
  /api/big-commerce/{integrationInstance}/products:
    get:
      tags:
      - BigCommerce
      summary: List Products
      description: 'List BigCommerce products for a specific integration instance
        (list view endpoint).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        The response uses the list view format with table specifications. Available
        optional columns (via included[]):

        - product: Linked SKU product details (id, name, sku, listing_id)

        - subscription_offering: Linked subscription offering (id, name, sku)

        - mapped_at: Date the product was mapped to a SKU product

        - mapped_sku: SKU of the mapped product

        - json_object: Full raw BigCommerce product JSON data

        - integration_instance_id: Integration instance ID

        - product_listing_id: Product listing ID'
      parameters:
      - name: search
        in: query
        schema:
          type: string
        description: Search term for product name or SKU
      - name: sort
        in: query
        schema:
          type: string
        description: Column to sort by (prefix with - for descending, e.g. -name)
        example: name
      - name: limit
        in: query
        schema:
          type: integer
        description: Records per page
        example: '10'
      - name: page
        in: query
        schema:
          type: integer
        description: Page number
        example: '1'
      - name: archived
        in: query
        schema:
          type: integer
        description: 'Include archived products: 0 = active only, 1 = archived only'
        example: '0'
      - name: included
        in: query
        schema:
          type: string
        description: 'JSON-encoded array of additional columns: ["product", "subscription_offering",
          "mapped_at", "mapped_sku", "json_object"]'
      - name: excluded
        in: query
        schema:
          type: string
        description: JSON-encoded array of columns to exclude
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: BigCommerce integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        big_commerce_id:
                          type: integer
                        sku:
                          type: string
                        name:
                          type: string
                        slug:
                          type: string
                        type:
                          type: string
                        status:
                          type: string
                        featured:
                          type: boolean
                        price:
                          type: number
                        weight:
                          type: number
                        integration_instance_id:
                          type: integer
                        product_listing_id:
                          type: integer
                        product:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            sku:
                              type: string
                            listing_id:
                              type: integer
                        mapped_sku:
                          type: string
                        mapped_at:
                          type: string
                        archived_at:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  total:
                    type: integer
                  per_page:
                    type: integer
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                example:
                  data:
                  - id: 10
                    big_commerce_id: 45678
                    sku: BLUE-WIDGET-M
                    name: Blue Widget Medium
                    slug: blue-widget-medium
                    type: physical
                    status: active
                    featured: false
                    price: 29.99
                    weight: 0.5
                    integration_instance_id: 1
                    product_listing_id: 55
                    product:
                      id: 100
                      name: Blue Widget
                      sku: BW-001
                      listing_id: 55
                    mapped_sku: BW-001
                    mapped_at: '2024-03-01T00:00:00.000000Z'
                    archived_at: null
                    created_at: '2024-01-20T00:00:00.000000Z'
                    updated_at: '2024-05-10T00:00:00.000000Z'
                  total: 1
                  per_page: 10
                  current_page: 1
                  last_page: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-big-commerce-integrationinstance-products
  /api/big-commerce/{integrationInstance}/products/{product}:
    get:
      tags:
      - BigCommerce
      summary: Get Product
      description: 'Get a single BigCommerce product.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: BigCommerce integration instance ID
        example: '1'
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: BigCommerce product ID
        example: '10'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      big_commerce_id:
                        type: integer
                      sku:
                        type: string
                      name:
                        type: string
                      slug:
                        type: string
                      type:
                        type: string
                      status:
                        type: string
                      featured:
                        type: boolean
                      catalog_visibility:
                        type: string
                      price:
                        type: number
                      weight:
                        type: number
                      dimensions_length:
                        type: number
                      dimensions_width:
                        type: number
                      dimensions_height:
                        type: number
                      integration_instance_id:
                        type: integer
                      archived_at:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 10
                    big_commerce_id: 45678
                    sku: BLUE-WIDGET-M
                    name: Blue Widget Medium
                    slug: blue-widget-medium
                    type: physical
                    status: active
                    featured: false
                    catalog_visibility: visible
                    price: 29.99
                    weight: 0.5
                    dimensions_length: 10.0
                    dimensions_width: 5.0
                    dimensions_height: 3.0
                    integration_instance_id: 1
                    archived_at: null
                    created_at: '2024-01-20T00:00:00.000000Z'
                    updated_at: '2024-05-10T00:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-big-commerce-integrationinstance-products-product
  /api/big-commerce/{integrationInstance}/products/create-sku-products:
    post:
      tags:
      - BigCommerce
      summary: Create SKU Products from BigCommerce
      description: 'Create SKU.io products from selected BigCommerce products. Products
        are created asynchronously via queue.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Fields:

        - ids (array, optional): Array of BigCommerce product IDs to create SKU products
        from. Required if create_all_products is false.

        - create_all_products (boolean, default false): Create SKU products for all
        BigCommerce products in this integration.

        - mappings (optional, array): Product mapping overrides to persist.

        - filters (optional, object): list view filters to use instead of explicit
        ids.


        Bulk selection contract:

        - {"create_all_products": false, "ids": [1, 2]} — create for the given channel
        product IDs

        - {"create_all_products": true} — create for all unmapped products on the
        integration instance

        - {"create_all_products": true, "filters": {...}} — create only for products
        matching the filters. The filters object accepts the same filter keys as the
        corresponding products list endpoint (bare column keys) and/or a "filter_groups"
        tree (base64-encoded JSON). When filters match no products, nothing is created
        and the response message is "No products to create".

        - create_all_products is required; ids is required when create_all_products
        is false and no filters are sent.

        - Legacy {"conjunction", "filterSet"} filter payloads are rejected with 422.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
                create_all_products:
                  type: boolean
              example:
                ids:
                - 10
                - 11
                - 12
                create_all_products: false
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: BigCommerce integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: string
                    nullable: true
                  message:
                    type: string
                example:
                  data: null
                  message: Added to queue, products will be created shortly.
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: object
                    properties:
                      apiErrors:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: array
                example:
                  errors:
                    apiErrors:
                    - message: BigCommerce product (ID 1234) has no SKU and cannot
                        be imported.
                      code: Missing SKU
                      data: []
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-big-commerce-integrationinstance-products-create-sku-products
  /api/big-commerce/{integrationInstance}/products/refresh:
    post:
      tags:
      - BigCommerce
      summary: Refresh Products
      description: 'Queue a job to refresh all products from BigCommerce for this
        integration instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: BigCommerce integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: string
                    nullable: true
                  message:
                    type: string
                example:
                  data: null
                  message: Added to queue, products will be refreshed shortly.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-big-commerce-integrationinstance-products-refresh
  /api/big-commerce/{integrationInstance}/products/map:
    put:
      tags:
      - BigCommerce
      summary: Map Products
      description: 'Map BigCommerce products to SKU.io products. Creates product listings
        linking BigCommerce listings to internal products.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                mappings:
                  type: array
                  items:
                    type: object
                    properties:
                      sales_channel_listing_id:
                        type: string
                      product_id:
                        type: integer
              example:
                mappings:
                - sales_channel_listing_id: BLUE-WIDGET-M
                  product_id: 100
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: BigCommerce integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: string
                  message:
                    type: string
                    nullable: true
                example:
                  data: Successfully mapped sales channel products to sku products
                  message: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-big-commerce-integrationinstance-products-map
  /api/big-commerce/{integrationInstance}/products/export:
    get:
      tags:
      - BigCommerce
      summary: Export Products
      description: 'Export BigCommerce products as a CSV or Excel file. Supports the
        same list view filter parameters as the list endpoint.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Response: Binary file download (text/csv or application/vnd.openxmlformats-officedocument.spreadsheetml.sheet).'
      parameters:
      - name: format
        in: query
        schema:
          type: string
        description: 'Export format: csv or xlsx'
        example: csv
      - name: search
        in: query
        schema:
          type: string
        description: Filter exported products by search term
      - name: archived
        in: query
        schema:
          type: integer
        description: 0 = active only, 1 = archived only
        example: '0'
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: BigCommerce integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: text/csv
            Content-Disposition:
              schema:
                type: string
                example: attachment; filename="big-commerce-products.csv"
          content:
            text/plain:
              schema:
                type: string
                example: 'id,sku,name,status,price

                  10,BLUE-WIDGET-M,Blue Widget Medium,active,29.99'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-big-commerce-integrationinstance-products-export
  /api/big-commerce/{integrationInstance}/products/archive:
    put:
      tags:
      - BigCommerce
      summary: Archive Products
      description: 'Archive BigCommerce products (soft-delete). Products are marked
        as archived and hidden from default listings.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Fields:

        - ids (required, array): Array of BigCommerce product IDs to archive. Must
        belong to this integration instance.


        Bulk selection contract:

        - {"ids": [1, 2]} — act on the given channel product IDs

        - {"mode": "all"} — act on all products for the integration instance

        - {"apply_to_all": true, "filters": {...}} — act only on products matching
        the filters. The filters object accepts the same filter keys as the corresponding
        products list endpoint (bare column keys) and/or a "filter_groups" tree (base64-encoded
        JSON). With apply_to_all and no filters, all products for the instance are
        targeted.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 10
                - 11
                - 12
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: BigCommerce integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: string
                    nullable: true
                  message:
                    type: string
                example:
                  data: null
                  message: Products archived successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-big-commerce-integrationinstance-products-archive
  /api/big-commerce/{integrationInstance}/products/unarchive:
    put:
      tags:
      - BigCommerce
      summary: Unarchive Products
      description: 'Unarchive previously archived BigCommerce products.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Fields:

        - ids (required, array): Array of BigCommerce product IDs to unarchive. Must
        belong to this integration instance.


        Bulk selection contract:

        - {"ids": [1, 2]} — act on the given channel product IDs

        - {"mode": "all"} — act on all products for the integration instance

        - {"apply_to_all": true, "filters": {...}} — act only on products matching
        the filters. The filters object accepts the same filter keys as the corresponding
        products list endpoint (bare column keys) and/or a "filter_groups" tree (base64-encoded
        JSON). With apply_to_all and no filters, all products for the instance are
        targeted.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 10
                - 11
                - 12
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: BigCommerce integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: string
                    nullable: true
                  message:
                    type: string
                example:
                  data: null
                  message: Products archived successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-big-commerce-integrationinstance-products-unarchive
  /api/big-commerce/{integrationInstance}/products/archiveable:
    post:
      tags:
      - BigCommerce
      summary: Check Archiveable Products
      description: 'Check which of the given BigCommerce products can be archived.
        Returns a collection indicating whether each product is archiveable.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Fields:

        - ids (required, array): Array of BigCommerce product IDs to check.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 10
                - 11
                - 12
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: BigCommerce integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        archiveable:
                          type: boolean
                example:
                  data:
                  - id: 10
                    archiveable: true
                  - id: 11
                    archiveable: false
                    reason: Product has pending orders
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-big-commerce-integrationinstance-products-archiveable
  /api/big-commerce/{integrationInstance}/products/delete:
    put:
      tags:
      - BigCommerce
      summary: Delete Products
      description: 'Permanently delete BigCommerce products from SKU.io (does not
        delete from BigCommerce). Use archiveable endpoint first to check if deletion
        is safe.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Fields:

        - ids (required, array): Array of BigCommerce product IDs to delete. Must
        belong to this integration instance.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 10
                - 11
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: BigCommerce integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: string
                    nullable: true
                  message:
                    type: string
                example:
                  data: null
                  message: Products deleted successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-big-commerce-integrationinstance-products-delete
  /api/big-commerce/{integrationInstance}/products/import-mappings:
    post:
      tags:
      - BigCommerce
      summary: Import Product Mappings
      description: 'Import product mapping data from a file (CSV/Excel). Queues a
        background job to process the mappings asynchronously.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                file:
                  type: string
                mapping_type:
                  type: string
              example:
                file: base64_encoded_csv_content
                mapping_type: listings
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: BigCommerce integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: string
                    nullable: true
                  message:
                    type: string
                example:
                  data: null
                  message: Added to queue, mappings will be imported shortly.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-big-commerce-integrationinstance-products-import-mappings
  /api/big-commerce/{integrationInstance}/orders:
    get:
      tags:
      - BigCommerce
      summary: List Orders
      description: 'List BigCommerce orders for a specific integration instance (list
        view endpoint).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Available optional columns (via included[]):

        - sku_sales_order: Linked SKU sales order (id, number)

        - json_object: Full raw BigCommerce order JSON data

        - integration_instance_id: Integration instance ID'
      parameters:
      - name: search
        in: query
        schema:
          type: string
        description: Search term for order ID, status, etc.
      - name: sort
        in: query
        schema:
          type: string
        description: Column to sort by (prefix with - for descending)
        example: -date_created
      - name: limit
        in: query
        schema:
          type: integer
        description: Records per page
        example: '10'
      - name: page
        in: query
        schema:
          type: integer
        description: Page number
        example: '1'
      - name: archived
        in: query
        schema:
          type: integer
        description: 'Include archived orders: 0 = active only, 1 = archived only'
        example: '0'
      - name: included
        in: query
        schema:
          type: string
        description: 'JSON-encoded array of columns: ["sku_sales_order", "json_object"]'
      - name: excluded
        in: query
        schema:
          type: string
        description: JSON-encoded array of columns to exclude
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: BigCommerce integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        big_commerce_id:
                          type: string
                        status:
                          type: string
                        currency_code:
                          type: string
                        subtotal_ex_tax:
                          type: string
                        subtotal_inc_tax:
                          type: string
                        total_ex_tax:
                          type: string
                        total_inc_tax:
                          type: string
                        total_tax:
                          type: string
                        base_shipping_cost:
                          type: string
                        items_total:
                          type: integer
                        items_shipped:
                          type: integer
                        payment_method:
                          type: string
                        payment_status:
                          type: string
                        date_created:
                          type: string
                        integration_instance_id:
                          type: integer
                        sku_sales_order:
                          type: object
                          properties:
                            id:
                              type: integer
                            number:
                              type: string
                        archived_at:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  total:
                    type: integer
                  per_page:
                    type: integer
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                example:
                  data:
                  - id: 50
                    big_commerce_id: BC-10001
                    status: shipped
                    currency_code: USD
                    subtotal_ex_tax: '45.00'
                    subtotal_inc_tax: '45.00'
                    total_ex_tax: '52.00'
                    total_inc_tax: '52.00'
                    total_tax: '0.00'
                    base_shipping_cost: '7.00'
                    items_total: 2
                    items_shipped: 2
                    payment_method: Credit Card
                    payment_status: captured
                    date_created: '2024-05-01T00:00:00.000000Z'
                    integration_instance_id: 1
                    sku_sales_order:
                      id: 500
                      number: SO-001234
                    archived_at: null
                    created_at: '2024-05-01T00:00:00.000000Z'
                    updated_at: '2024-05-03T00:00:00.000000Z'
                  total: 1
                  per_page: 10
                  current_page: 1
                  last_page: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-big-commerce-integrationinstance-orders
  /api/big-commerce/{integrationInstance}/orders/create-sku-orders:
    post:
      tags:
      - BigCommerce
      summary: Create SKU Orders from BigCommerce
      description: 'Create SKU.io sales orders from selected BigCommerce orders.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Fields:

        - ids (array, optional): Array of BigCommerce order IDs to create SKU orders
        from.

        - create_all_orders (boolean, default false): Create SKU orders for all BigCommerce
        orders.

        - filters (optional, object): list view filters to use instead of explicit
        ids.


        Bulk selection contract:

        - {"ids": [1, 2]} — create for the given channel order IDs

        - {"create_all_orders": true} — create for all eligible orders on the integration
        instance

        - {"create_all_orders": true, "filters": {...}} — create only for orders matching
        the filters. The filters object accepts the same filter keys as the corresponding
        orders list endpoint (bare column keys, e.g. {"order_status": "pending"})
        and/or a "filter_groups" tree (base64-encoded JSON, same format as the list
        endpoint). When filters match no orders, nothing is created and the response
        message is "No orders to create".

        - Legacy {"conjunction", "filterSet"} filter payloads are rejected with 422.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
                create_all_orders:
                  type: boolean
              example:
                ids:
                - 50
                - 51
                - 52
                create_all_orders: false
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: BigCommerce integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: string
                    nullable: true
                  message:
                    type: string
                example:
                  data: null
                  message: Sku.io sales orders successfully created
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-big-commerce-integrationinstance-orders-create-sku-orders
  /api/big-commerce/{integrationInstance}/orders/refresh:
    post:
      tags:
      - BigCommerce
      summary: Refresh Orders
      description: 'Queue a job to refresh all orders from BigCommerce for this integration
        instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: BigCommerce integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: string
                    nullable: true
                  message:
                    type: string
                example:
                  data: null
                  message: Added to queue, orders will be refreshed shortly.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-big-commerce-integrationinstance-orders-refresh
  /api/big-commerce/{integrationInstance}/orders/refresh-order:
    post:
      tags:
      - BigCommerce
      summary: Refresh Single Order
      description: 'Refresh a single BigCommerce order by its unique identifier (BigCommerce
        order ID). Fetches the latest data from BigCommerce API and returns the updated
        order resource.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Fields:

        - uniqueId (required, string): The BigCommerce order unique ID (e.g., ''BC-10001'')'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                uniqueId:
                  type: string
              example:
                uniqueId: BC-10001
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: BigCommerce integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      big_commerce_id:
                        type: string
                      status:
                        type: string
                      currency_code:
                        type: string
                      total_inc_tax:
                        type: string
                      integration_instance_id:
                        type: integer
                      updated_at:
                        type: string
                example:
                  data:
                    id: 50
                    big_commerce_id: BC-10001
                    status: shipped
                    currency_code: USD
                    total_inc_tax: '52.00'
                    integration_instance_id: 1
                    updated_at: '2024-05-10T00:00:00.000000Z'
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Order not found
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-big-commerce-integrationinstance-orders-refresh-order
  /api/big-commerce/{integrationInstance}/orders/export:
    get:
      tags:
      - BigCommerce
      summary: Export Orders
      description: 'Export BigCommerce orders as a CSV or Excel file.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Response: Binary file download.'
      parameters:
      - name: format
        in: query
        schema:
          type: string
        description: 'Export format: csv or xlsx'
        example: csv
      - name: search
        in: query
        schema:
          type: string
        description: Filter by search term
      - name: archived
        in: query
        schema:
          type: integer
        description: 0 = active only, 1 = archived only
        example: '0'
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: BigCommerce integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: text/csv
            Content-Disposition:
              schema:
                type: string
                example: attachment; filename="big-commerce-orders.csv"
          content:
            text/plain:
              schema:
                type: string
                example: 'id,big_commerce_id,status,total_inc_tax,currency_code

                  50,BC-10001,shipped,52.00,USD'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-big-commerce-integrationinstance-orders-export
  /api/big-commerce/{integrationInstance}/fulfill:
    post:
      tags:
      - BigCommerce
      summary: Fulfill Order
      description: 'Submit a fulfillment to BigCommerce for a given SKU.io sales order
        fulfillment. Sends shipment/tracking information back to BigCommerce.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Fields:

        - sales_order_fulfillment_id (required, integer): ID of the SKU.io sales order
        fulfillment to push to BigCommerce.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                sales_order_fulfillment_id:
                  type: integer
              example:
                sales_order_fulfillment_id: 123
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: BigCommerce integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: string
                    nullable: true
                  message:
                    type: string
                example:
                  data: null
                  message: Successfully submitted to sales channel.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      sales_order_fulfillment_id:
                        type: array
                        items:
                          type: string
                example:
                  message: The sales order fulfillment id field must exist in sales
                    order fulfillments.
                  errors:
                    sales_order_fulfillment_id:
                    - The sales order fulfillment id field must exist in sales order
                      fulfillments.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-big-commerce-integrationinstance-fulfill
  /api/woo-commerce:
    get:
      tags:
      - WooCommerce
      summary: List Integration Instances
      description: 'List all WooCommerce integration instances.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        integration_id:
                          type: integer
                        integration_name:
                          type: string
                        store:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        is_automatic_sync_enabled:
                          type: boolean
                        created_at:
                          type: string
                        updated_at:
                          type: string
                example:
                  data:
                  - id: 1
                    name: My WooCommerce Store
                    integration_id: 7
                    integration_name: WooCommerce
                    store:
                      id: 2
                      name: Main Store
                    is_automatic_sync_enabled: true
                    created_at: '2024-01-15T10:00:00.000000Z'
                    updated_at: '2024-01-15T10:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-woo-commerce
    post:
      tags:
      - WooCommerce
      summary: Create Integration Instance
      description: "Create a new WooCommerce integration instance.\n\n:::info[Authorization]\n\
        Any valid API token can call this endpoint — no specific scope required. [Manage\
        \ tokens](https://app.sku.io/settings/api).\n:::\n\nAfter creation, the response\
        \ includes a redirect_url for OAuth authorization with WooCommerce.\n\nAuthentication:\
        \ Requires Bearer token.\n\nRequest Body:\n- name (string, required) — Unique\
        \ name for the integration instance\n- integration_id (integer, required)\
        \ — ID of the WooCommerce integration record\n- connection_settings (object,\
        \ optional) — WooCommerce API keys\n  - key_id (integer) — WooCommerce key\
        \ ID\n  - user_id (string) — WooCommerce user ID\n  - consumer_key (string)\
        \ — WooCommerce consumer key\n  - consumer_secret (string) — WooCommerce consumer\
        \ secret\n  - key_permissions (string) — Key permissions (e.g. 'read_write')\n\
        - integration_settings (object, required) — Store configuration\n  - url (string,\
        \ required) — Store URL, must start with 'https://' and not end with '/'\n\
        \  - start_date (string, required) — Date to begin syncing orders from\n \
        \ - store_id (integer, required) — SKU.io store ID\n  - auto_link_products\
        \ (boolean, required) — Auto-link WooCommerce products to SKU.io products\n\
        \  - auto_create_products (boolean, required) — Auto-create SKU.io products\
        \ for unlinked WooCommerce products\n  - sales_nominal_code_id (integer, optional)\
        \ — Nominal code for sales revenue\n  - cogs_nominal_code_id (integer, optional)\
        \ — Nominal code for COGS\n  - shipping_revenue_nominal_code_id (integer,\
        \ optional) — Nominal code for shipping revenue\n  - shipping_refund_nominal_code_id\
        \ (integer, optional) — Nominal code for shipping refunds\n  - sales_returns_allowances_nominal_code_id\
        \ (integer, optional) — Nominal code for returns\n  - sync_sales_order_invoices_to_accounting\
        \ (boolean, optional, default: true)\n  - sync_sales_credit_to_accounting\
        \ (boolean, optional, default: true)\n  - batch_period_sales_order_fulfillments\
        \ (string, optional) — Batch period override for fulfillments\n  - batch_period_customer_returns\
        \ (string, optional) — Batch period override for returns\n  - proforma_marketplace_cost_percentage\
        \ (float, optional)\n  - proforma_payment_cost_percentage (float, optional)\n\
        - is_automatic_sync_enabled (boolean, optional, default: false)"
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                integration_id:
                  type: integer
                connection_settings:
                  type: object
                  properties:
                    key_id:
                      type: integer
                    user_id:
                      type: string
                    consumer_key:
                      type: string
                    consumer_secret:
                      type: string
                    key_permissions:
                      type: string
                integration_settings:
                  type: object
                  properties:
                    url:
                      type: string
                    start_date:
                      type: string
                    store_id:
                      type: integer
                    auto_link_products:
                      type: boolean
                    auto_create_products:
                      type: boolean
                    sales_nominal_code_id:
                      type: string
                      nullable: true
                    cogs_nominal_code_id:
                      type: string
                      nullable: true
                    shipping_revenue_nominal_code_id:
                      type: string
                      nullable: true
                    shipping_refund_nominal_code_id:
                      type: string
                      nullable: true
                    sales_returns_allowances_nominal_code_id:
                      type: string
                      nullable: true
                    sync_sales_order_invoices_to_accounting:
                      type: boolean
                    sync_sales_credit_to_accounting:
                      type: boolean
                is_automatic_sync_enabled:
                  type: boolean
              example:
                name: My WooCommerce Store
                integration_id: 7
                connection_settings:
                  key_id: 123
                  user_id: wc_user_abc
                  consumer_key: ck_abc123
                  consumer_secret: cs_abc123
                  key_permissions: read_write
                integration_settings:
                  url: https://mystore.com
                  start_date: '2024-01-01'
                  store_id: 2
                  auto_link_products: true
                  auto_create_products: false
                  sales_nominal_code_id: null
                  cogs_nominal_code_id: null
                  shipping_revenue_nominal_code_id: null
                  shipping_refund_nominal_code_id: null
                  sales_returns_allowances_nominal_code_id: null
                  sync_sales_order_invoices_to_accounting: true
                  sync_sales_credit_to_accounting: true
                is_automatic_sync_enabled: true
      parameters: []
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      integration_id:
                        type: integer
                      integration_name:
                        type: string
                      store:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      is_automatic_sync_enabled:
                        type: boolean
                      created_at:
                        type: string
                      updated_at:
                        type: string
                  redirect_url:
                    type: string
                example:
                  data:
                    id: 1
                    name: My WooCommerce Store
                    integration_id: 7
                    integration_name: WooCommerce
                    store:
                      id: 2
                      name: Main Store
                    is_automatic_sync_enabled: true
                    created_at: '2024-01-15T10:00:00.000000Z'
                    updated_at: '2024-01-15T10:00:00.000000Z'
                  redirect_url: https://mystore.com/wc-auth/v1/authorize?app_name=SKU.io&scope=read_write&user_id=42&return_url=https%3A%2F%2Fapp.sku.io%2F&callback_url=https%3A%2F%2Fapp.sku.io%2Fapi%2Fwoo-commerce%2Fcallback
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-woo-commerce
  /api/woo-commerce/{integration_instance}:
    get:
      tags:
      - WooCommerce
      summary: Show Integration Instance
      description: 'Show a single WooCommerce integration instance with loaded integration
        and store relations.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      integration_id:
                        type: integer
                      integration_name:
                        type: string
                      store:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      connection_settings:
                        type: object
                        properties:
                          key_id:
                            type: integer
                          user_id:
                            type: string
                          consumer_key:
                            type: string
                          consumer_secret:
                            type: string
                          key_permissions:
                            type: string
                      integration_settings:
                        type: object
                        properties:
                          url:
                            type: string
                          start_date:
                            type: string
                          store_id:
                            type: integer
                          auto_link_products:
                            type: boolean
                          auto_create_products:
                            type: boolean
                          sync_sales_order_invoices_to_accounting:
                            type: boolean
                          sync_sales_credit_to_accounting:
                            type: boolean
                      is_automatic_sync_enabled:
                        type: boolean
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 1
                    name: My WooCommerce Store
                    integration_id: 7
                    integration_name: WooCommerce
                    store:
                      id: 2
                      name: Main Store
                    connection_settings:
                      key_id: 123
                      user_id: wc_user_abc
                      consumer_key: ck_***
                      consumer_secret: cs_***
                      key_permissions: read_write
                    integration_settings:
                      url: https://mystore.com
                      start_date: '2024-01-01'
                      store_id: 2
                      auto_link_products: true
                      auto_create_products: false
                      sync_sales_order_invoices_to_accounting: true
                      sync_sales_credit_to_accounting: true
                    is_automatic_sync_enabled: true
                    created_at: '2024-01-15T10:00:00.000000Z'
                    updated_at: '2024-01-15T10:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-woo-commerce-integration-instance
    put:
      tags:
      - WooCommerce
      summary: Update Integration Instance
      description: 'Update a WooCommerce integration instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        PATCH requests perform a deep merge with existing settings. PUT requests replace
        all provided fields.


        Authentication: Requires Bearer token.


        Request Body (all optional):

        - name (string) — New name (must be unique)

        - connection_settings (object) — Updated WooCommerce API credentials

        - integration_settings (object) — Updated integration settings (same fields
        as store)

        - is_automatic_sync_enabled (boolean)'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                integration_settings:
                  type: object
                  properties:
                    url:
                      type: string
                    start_date:
                      type: string
                    store_id:
                      type: integer
                    auto_link_products:
                      type: boolean
                    auto_create_products:
                      type: boolean
                    sync_sales_order_invoices_to_accounting:
                      type: boolean
                    sync_sales_credit_to_accounting:
                      type: boolean
                is_automatic_sync_enabled:
                  type: boolean
              example:
                name: Updated WooCommerce Store
                integration_settings:
                  url: https://mystore.com
                  start_date: '2024-01-01'
                  store_id: 2
                  auto_link_products: true
                  auto_create_products: true
                  sync_sales_order_invoices_to_accounting: true
                  sync_sales_credit_to_accounting: true
                is_automatic_sync_enabled: false
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      integration_id:
                        type: integer
                      integration_name:
                        type: string
                      store:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      is_automatic_sync_enabled:
                        type: boolean
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 1
                    name: Updated WooCommerce Store
                    integration_id: 7
                    integration_name: WooCommerce
                    store:
                      id: 2
                      name: Main Store
                    is_automatic_sync_enabled: false
                    created_at: '2024-01-15T10:00:00.000000Z'
                    updated_at: '2024-01-15T12:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-woo-commerce-integration-instance
    delete:
      tags:
      - WooCommerce
      summary: Delete Integration Instance
      description: 'Delete a WooCommerce integration instance. This dispatches a background
        job to clean up all associated data.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '204':
          description: No Content
          content:
            text/plain:
              schema:
                type: string
                example: ''
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-woo-commerce-integration-instance
    patch:
      tags:
      - WooCommerce
      summary: Update WooCommerce Integration
      description: 'Update the settings of a WooCommerce integration instance. All
        fields are optional - only the fields you send are changed, and `integration_settings`
        is deep-merged with the existing settings on PATCH.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Top-level fields:

        - name (string): Display name for the integration instance.

        - is_automatic_sync_enabled (boolean): Master switch for automatic background
        syncing.

        - connection_settings (object): WooCommerce REST API credentials - user_id,
        consumer_key, consumer_secret, key_permissions.

        - integration_settings (object): Store configuration.


        integration_settings fields:

        - url (string): Store URL. Must start with https:// and must not end with
        a slash.

        - start_date (date): Earliest order date to sync. Must be on or after the
        SKU.io inventory start date.

        - store_id (integer): SKU.io store the sales channel belongs to.

        - auto_link_products (boolean): Automatically link WooCommerce products to
        SKU.io products by SKU.

        - auto_create_products (boolean): Automatically create SKU.io products for
        unmatched listings.

        - sales_nominal_code_id, cogs_nominal_code_id, shipping_revenue_nominal_code_id,
        shipping_refund_nominal_code_id, sales_returns_allowances_nominal_code_id
        (integer|null): Accounting nominal code assignments.

        - pricing (object): Price sync settings.

        - inventory (object): Inventory sync settings (locations, selected warehouses).
        Sent arrays fully replace the stored ones.

        - proforma_marketplace_cost_percentage, proforma_payment_cost_percentage (number|null):
        Estimated cost percentages for proforma profit calculations.

        - sync_sales_order_invoices_to_accounting, sync_sales_credit_to_accounting
        (boolean): Accounting sync toggles.

        - batch_period_sales_order_fulfillments, batch_period_customer_returns (string|null):
        Per-channel accounting batch period overrides.


        Route name: woo-commerce.update'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                is_automatic_sync_enabled:
                  type: boolean
                integration_settings:
                  type: object
                  properties:
                    url:
                      type: string
                    start_date:
                      type: string
                    store_id:
                      type: integer
                    auto_link_products:
                      type: boolean
                    auto_create_products:
                      type: boolean
                    sales_nominal_code_id:
                      type: integer
                    cogs_nominal_code_id:
                      type: integer
                    shipping_revenue_nominal_code_id:
                      type: integer
                    shipping_refund_nominal_code_id:
                      type: integer
                    sales_returns_allowances_nominal_code_id:
                      type: integer
                    sync_sales_order_invoices_to_accounting:
                      type: boolean
                    sync_sales_credit_to_accounting:
                      type: boolean
              example:
                name: My WooCommerce Store
                is_automatic_sync_enabled: true
                integration_settings:
                  url: https://store.example.com
                  start_date: '2026-01-01'
                  store_id: 3
                  auto_link_products: true
                  auto_create_products: false
                  sales_nominal_code_id: 12
                  cogs_nominal_code_id: 18
                  shipping_revenue_nominal_code_id: 21
                  shipping_refund_nominal_code_id: 22
                  sales_returns_allowances_nominal_code_id: 23
                  sync_sales_order_invoices_to_accounting: true
                  sync_sales_credit_to_accounting: true
      parameters:
      - name: integration_instance
        in: path
        required: true
        schema:
          type: string
        description: The integration_instance identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      integration_id:
                        type: integer
                      is_automatic_sync_enabled:
                        type: boolean
                      integration_settings:
                        type: object
                        properties:
                          url:
                            type: string
                          start_date:
                            type: string
                          store_id:
                            type: integer
                          auto_link_products:
                            type: boolean
                          auto_create_products:
                            type: boolean
                          sales_nominal_code_id:
                            type: integer
                          cogs_nominal_code_id:
                            type: integer
                          shipping_revenue_nominal_code_id:
                            type: integer
                          shipping_refund_nominal_code_id:
                            type: integer
                          sales_returns_allowances_nominal_code_id:
                            type: integer
                          sync_sales_order_invoices_to_accounting:
                            type: boolean
                          sync_sales_credit_to_accounting:
                            type: boolean
                      integration_name:
                        type: string
                      sales_channel_id:
                        type: integer
                      store:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                  status:
                    type: string
                example:
                  data:
                    id: 1
                    name: My WooCommerce Store
                    integration_id: 9
                    is_automatic_sync_enabled: true
                    integration_settings:
                      url: https://store.example.com
                      start_date: '2026-01-01'
                      store_id: 3
                      auto_link_products: true
                      auto_create_products: false
                      sales_nominal_code_id: 12
                      cogs_nominal_code_id: 18
                      shipping_revenue_nominal_code_id: 21
                      shipping_refund_nominal_code_id: 22
                      sales_returns_allowances_nominal_code_id: 23
                      sync_sales_order_invoices_to_accounting: true
                      sync_sales_credit_to_accounting: true
                    integration_name: WooCommerce
                    sales_channel_id: 4
                    store:
                      id: 3
                      name: Main Store
                    created_at: '2026-01-05T10:00:00.000000Z'
                    updated_at: '2026-07-01T08:15:22.000000Z'
                  status: Success
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      integration_settings.url:
                        type: array
                        items:
                          type: string
                example:
                  message: 'The integration settings.url field must start with one
                    of the following: https://.'
                  errors:
                    integration_settings.url:
                    - 'The integration settings.url field must start with one of the
                      following: https://.'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: patch-api-woo-commerce-integration-instance
  /api/woo-commerce/{integration_instance}/get-authorization-url:
    get:
      tags:
      - WooCommerce
      summary: Get Authorization URL
      description: 'Get the WooCommerce OAuth authorization URL for a given integration
        instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Use this URL to redirect the user to WooCommerce to authorize the API keys.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: string
                example:
                  data: https://mystore.com/wc-auth/v1/authorize?app_name=SKU.io&scope=read_write&user_id=42&return_url=https%3A%2F%2Fapp.sku.io%2F&callback_url=https%3A%2F%2Fapp.sku.io%2Fapi%2Fwoo-commerce%2Fcallback
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-woo-commerce-integration-instance-get-authorization-url
  /api/woo-commerce/{integration_instance}/products:
    get:
      tags:
      - WooCommerce
      summary: List Products
      description: 'List WooCommerce products (one row per sellable unit — parent
        products and variations unified) for an integration instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Quick Filters:

        - filter[search] (string, optional) — matches sku, unified_title, or id

        - filter[status] (string, optional) — exact status: publish, draft, pending,
        private (''all'' is a no-op)

        - filter[mapping_status] (string, optional) — ''mapped'' or ''unmapped'' (linked
        to a SKU.io product or not)

        - filter[archived] (string, optional) — ''true'' (archived only) or ''false''
        (active only)


        Advanced Filters (filter_groups):

        Base64-encoded JSON tree with and/or conjunctions and nested groups.

        - Text columns: status, product_type, sku, stock_status — operators: is, is_not,
        contains, does_not_contain, starts_with, ends_with, is_one_of, is_not_one_of,
        is_empty, is_not_empty

        - Numeric columns: price — operators: is, is_not, greater_than, less_than,
        greater_than_or_equal, less_than_or_equal, between, is_one_of, is_empty, is_not_empty

        - Boolean columns: mapped — operator: is with value true/false

        Unregistered filter columns return HTTP 400.


        Sorting: sort=field or sort=-field (descending). Allowed sorts: id, woo_commerce_product_id,
        sku, unified_title, woo_commerce_parent_product_id, woo_commerce_variation_id,
        woo_commerce_unique_id, parent_sku, variation_name, price, regular_price,
        sale_price, manage_stock, stock_quantity, weight, product_type, slug, status,
        created_at, updated_at. Default: -id.


        Pagination: page (default 1), per_page (default 10). Standard paginator response
        with data, current_page, last_page, per_page, total, from, to.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        woo_commerce_parent_product_id:
                          type: integer
                        woo_commerce_product_id:
                          type: integer
                        woo_commerce_variation_id:
                          type: integer
                        woo_commerce_unique_id:
                          type: integer
                        parent_product_name:
                          type: string
                        parent_sku:
                          type: string
                        variation_name:
                          type: string
                          nullable: true
                        unified_title:
                          type: string
                        sku:
                          type: string
                        price:
                          type: string
                        regular_price:
                          type: string
                        sale_price:
                          type: string
                          nullable: true
                        manage_stock:
                          type: boolean
                        stock_quantity:
                          type: integer
                        stock_status:
                          type: string
                        weight:
                          type: string
                        image_url:
                          type: string
                        product_type:
                          type: string
                        status:
                          type: string
                        slug:
                          type: string
                        archived_at:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                        updated_at:
                          type: string
                        product_listing_id:
                          type: integer
                        product:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            sku:
                              type: string
                            default_financial_line_type_id:
                              type: integer
                            default_financial_line_type:
                              type: object
                              properties:
                                id:
                                  type: integer
                                name:
                                  type: string
                                classification:
                                  type: string
                            listing_id:
                              type: integer
                        subscription_offering:
                          type: string
                          nullable: true
                        mapped_at:
                          type: string
                        mapped_sku:
                          type: string
                  current_page:
                    type: integer
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  next_page_url:
                    type: string
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 501
                    integration_instance_id: 1
                    woo_commerce_parent_product_id: 33
                    woo_commerce_product_id: 9001
                    woo_commerce_variation_id: 0
                    woo_commerce_unique_id: 9001
                    parent_product_name: Blue Widget
                    parent_sku: BW-001
                    variation_name: null
                    unified_title: Blue Widget
                    sku: BW-001
                    price: '29.99'
                    regular_price: '34.99'
                    sale_price: null
                    manage_stock: true
                    stock_quantity: 42
                    stock_status: instock
                    weight: '0.50'
                    image_url: https://store.example.com/wp-content/uploads/blue-widget.jpg
                    product_type: simple
                    status: publish
                    slug: blue-widget
                    archived_at: null
                    created_at: '2026-01-10T10:00:00.000000Z'
                    updated_at: '2026-06-01T08:30:00.000000Z'
                    product_listing_id: 88
                    product:
                      id: 12
                      name: Blue Widget
                      sku: BW-001
                      default_financial_line_type_id: 3
                      default_financial_line_type:
                        id: 3
                        name: Product Sales
                        classification: revenue
                      listing_id: 88
                    subscription_offering: null
                    mapped_at: '2026-01-10T10:00:00.000000Z'
                    mapped_sku: BW-001
                  current_page: 1
                  first_page_url: https://example.sku.io/api/woo-commerce/1/products?page=1
                  from: 1
                  last_page: 5
                  last_page_url: https://example.sku.io/api/woo-commerce/1/products?page=5
                  next_page_url: https://example.sku.io/api/woo-commerce/1/products?page=2
                  path: https://example.sku.io/api/woo-commerce/1/products
                  per_page: 10
                  prev_page_url: null
                  to: 10
                  total: 45
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-woo-commerce-integration-instance-products
  /api/woo-commerce/{integration_instance}/products/{product}:
    get:
      tags:
      - WooCommerce
      summary: Show Product
      description: 'Get a single WooCommerce product.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: WooCommerce product local DB ID
        example: '501'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      product_listing_id:
                        type: integer
                      product:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          sku:
                            type: string
                          listing_id:
                            type: integer
                      subscription_offering:
                        type: string
                        nullable: true
                      mapped_at:
                        type: string
                      mapped_sku:
                        type: string
                      json_object:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          sku:
                            type: string
                          status:
                            type: string
                          price:
                            type: string
                          description:
                            type: string
                          categories:
                            type: array
                            items:
                              type: object
                              properties:
                                id:
                                  type: integer
                                name:
                                  type: string
                example:
                  data:
                    id: 501
                    integration_instance_id: 1
                    product_listing_id: 88
                    product:
                      id: 12
                      name: Blue Widget
                      sku: BW-001
                      listing_id: 88
                    subscription_offering: null
                    mapped_at: '2024-01-10T10:00:00.000000Z'
                    mapped_sku: BW-001
                    json_object:
                      id: 9001
                      name: Blue Widget
                      sku: BW-001
                      status: publish
                      price: '29.99'
                      description: A high-quality blue widget.
                      categories:
                      - id: 5
                        name: Widgets
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-woo-commerce-integration-instance-products-product
    put:
      tags:
      - WooCommerce
      summary: Update Product
      description: 'Update a WooCommerce product record.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties: {}
              example: {}
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: WooCommerce product local DB ID
        example: '501'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                example:
                  data:
                    id: 501
                    integration_instance_id: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-woo-commerce-integration-instance-products-product
    delete:
      tags:
      - WooCommerce
      summary: Delete Product
      description: 'Delete a single WooCommerce product record from SKU.io.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: WooCommerce product local DB ID
        example: '501'
      responses:
        '204':
          description: No Content
          content:
            text/plain:
              schema:
                type: string
                example: ''
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-woo-commerce-integration-instance-products-product
  /api/woo-commerce/{integration_instance}/products/create-sku-products:
    post:
      tags:
      - WooCommerce
      summary: Create SKU Products from WooCommerce
      description: 'Queue a job to create SKU.io products from the selected WooCommerce
        products.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Request Body:

        - ids (array of integers, optional) — IDs of WooCommerce products to create
        SKU products from. Omit if create_all_products is true or filters are provided.

        - create_all_products (boolean, optional) — If true, create SKU products for
        all unlinked WooCommerce products

        - mappings (array, optional) — Column mapping configuration for the import

        - filters (object, optional) — list view filters to determine which products
        to include


        Bulk selection contract:

        - {"create_all_products": false, "ids": [1, 2]} — create for the given channel
        product IDs

        - {"create_all_products": true} — create for all unmapped products on the
        integration instance

        - {"create_all_products": true, "filters": {...}} — create only for products
        matching the filters. The filters object accepts the same filter keys as the
        corresponding products list endpoint (bare column keys) and/or a "filter_groups"
        tree (base64-encoded JSON). When filters match no products, nothing is created
        and the response message is "No products to create".

        - create_all_products is required; ids is required when create_all_products
        is false and no filters are sent.

        - Legacy {"conjunction", "filterSet"} filter payloads are rejected with 422.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
                create_all_products:
                  type: boolean
                mappings:
                  type: array
                  items:
                    type: object
                    properties:
                      column:
                        type: string
                      mapped_to:
                        type: string
              example:
                ids:
                - 501
                - 502
                - 503
                create_all_products: false
                mappings:
                - column: sku
                  mapped_to: sku
                - column: name
                  mapped_to: name
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Added to queue, products will be created shortly.
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: object
                    properties:
                      apiErrors:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: array
                example:
                  errors:
                    apiErrors:
                    - message: WooCommerce product (ID 1234) has no SKU and cannot
                        be imported.
                      code: Missing SKU
                      data: []
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-woo-commerce-integration-instance-products-create-sku-products
  /api/woo-commerce/{integration_instance}/products/refresh:
    post:
      tags:
      - WooCommerce
      summary: Refresh Products
      description: 'Queue a background job to refresh all WooCommerce products from
        the store API.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Added to queue, products will be refreshed shortly.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-woo-commerce-integration-instance-products-refresh
  /api/woo-commerce/{integration_instance}/products/refresh-tracked:
    post:
      tags:
      - WooCommerce
      summary: Refresh Products (Tracked)
      description: 'Dispatch a tracked background job to re-fetch products from WooCommerce.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Body fields (all optional):

        - mode (string): One of since_latest, full_catalog, date_range. Defaults to
        full_catalog.

        - latestDate (string|null): ISO8601 timestamp used as modified_after when
        mode is since_latest.

        - dateFrom (date|null): YYYY-MM-DD start date for date_range mode.

        - dateTo (date|null): Reserved for future use.

        - dateMethod (string|null): One of created or updated. When date_range is
        selected with dateMethod=created the WC `after` filter is used; with dateMethod=updated
        (default) the WC `modified_after` filter is used.


        Returns a tracked_job_log_id that can be used to monitor job progress via
        the tracked job log endpoints.


        Route name: woo-commerce.products.refresh-tracked'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                mode:
                  type: string
                latestDate:
                  type: string
                dateFrom:
                  type: string
                  nullable: true
                dateTo:
                  type: string
                  nullable: true
                dateMethod:
                  type: string
              example:
                mode: since_latest
                latestDate: '2026-05-01T00:00:00Z'
                dateFrom: null
                dateTo: null
                dateMethod: updated
      parameters:
      - name: integration_instance
        in: path
        required: true
        schema:
          type: string
        description: The integration_instance identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 12345
                  message: Product refresh job has been queued
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-woo-commerce-integration-instance-products-refresh-tracked
  /api/woo-commerce/{integration_instance}/products/map:
    put:
      tags:
      - WooCommerce
      summary: Map Products
      description: "Map WooCommerce products to SKU.io products.\n\n:::info[Authorization]\n\
        Any valid API token can call this endpoint — no specific scope required. [Manage\
        \ tokens](https://app.sku.io/settings/api).\n:::\n\nAuthentication: Requires\
        \ Bearer token.\n\nRequest Body:\n- mappings (array, required) — Collection\
        \ of WooCommerce-to-SKU product mappings\n  - sales_channel_product_id (integer)\
        \ — WooCommerce product local DB ID\n  - sku_product_id (integer) — SKU.io\
        \ product ID to link to"
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                mappings:
                  type: array
                  items:
                    type: object
                    properties:
                      sales_channel_product_id:
                        type: integer
                      sku_product_id:
                        type: integer
              example:
                mappings:
                - sales_channel_product_id: 501
                  sku_product_id: 12
                - sales_channel_product_id: 502
                  sku_product_id: 15
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: string
                example:
                  data: Successfully mapped sales channel products to sku products
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-woo-commerce-integration-instance-products-map
  /api/woo-commerce/{integrationInstance}/products/{product}/smart-match:
    post:
      tags:
      - WooCommerce
      summary: Smart Match Product
      description: 'Find suggested SKU product matches for a single WooCommerce listing.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Matching strategy:

        - exact_match: SKU product whose sku == woo_commerce_product.sku

        - barcode_match: always null (WooCommerce products do not expose a barcode
        field)

        - similar_matches: up to 5 fuzzy matches by unified_title / sku tokens


        Archived SKU products are excluded. Used by the listing detail page mapping
        modal.


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: WooCommerce integration instance ID
        example: '1'
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: WooCommerce product ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      exact_match:
                        type: object
                        properties:
                          id:
                            type: integer
                          sku:
                            type: string
                          name:
                            type: string
                          barcode:
                            type: string
                          price:
                            type: number
                          type:
                            type: string
                          match_type:
                            type: string
                      barcode_match:
                        type: string
                        nullable: true
                      similar_matches:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            sku:
                              type: string
                            name:
                              type: string
                            barcode:
                              type: string
                            price:
                              type: number
                            type:
                              type: string
                            match_type:
                              type: string
                example:
                  data:
                    exact_match:
                      id: 200
                      sku: WOO-WIDGET-L
                      name: Widget Large
                      barcode: 012345678905
                      price: 19.99
                      type: simple
                      match_type: sku
                    barcode_match: null
                    similar_matches:
                    - id: 201
                      sku: WOO-WIDGET-M
                      name: Widget Medium
                      barcode: 012345678912
                      price: 14.99
                      type: simple
                      match_type: fuzzy
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-woo-commerce-integrationinstance-products-product-smart-match
  /api/woo-commerce/{integrationInstance}/products/{product}/raw:
    get:
      tags:
      - WooCommerce
      summary: Get Raw Product from WooCommerce
      description: 'Fetch the raw WooCommerce REST API response for a single product,
        live from /wp-json/wc/v3/products/{id}. Powers the "Load Raw Data from WooCommerce"
        button on the listing detail page.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        The data is not persisted — it reflects the live WooCommerce state. Uses the
        upstream WooCommerce product ID (woo_commerce_product_id) for the API call.


        Returns 403 if the product doesn''t belong to the given integration instance.
        Returns 500 if WooCommerce''s API call fails (e.g. integration not fully configured).


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: WooCommerce integration instance ID
        example: '1'
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: WooCommerce product ID (internal)
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      product:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          slug:
                            type: string
                          permalink:
                            type: string
                          type:
                            type: string
                          status:
                            type: string
                          sku:
                            type: string
                          price:
                            type: string
                          regular_price:
                            type: string
                          stock_status:
                            type: string
                          stock_quantity:
                            type: integer
                example:
                  data:
                    product:
                      id: 906
                      name: Glass Pour-Over Carafe
                      slug: glass-pour-over-carafe
                      permalink: https://shop.example.com/product/glass-pour-over-carafe
                      type: simple
                      status: publish
                      sku: WC-CARAFE-GLASS
                      price: '24.00'
                      regular_price: '24.00'
                      stock_status: instock
                      stock_quantity: 45
        '403':
          description: Forbidden
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: Product does not belong to this integration instance
        '500':
          description: Internal Server Error
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                  message:
                    type: string
                example:
                  error: Failed to fetch raw product data from WooCommerce
                  message: Undefined array key "url"
        '429': *id001
        '401': *id002
        '404': *id004
      operationId: get-api-woo-commerce-integrationinstance-products-product-raw
  /api/woo-commerce/{integrationInstance}/products/{product}/create-sku-product:
    post:
      tags:
      - WooCommerce
      summary: Create SKU Product from WooCommerce Product
      description: 'Create a new SKU product from a WooCommerce listing''s data and
        map it. If a SKU product with the same SKU already exists, the existing one
        is linked instead of creating a duplicate (response includes linked_existing=true).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        This handles product creation, pricing, and listing.


        Returns 422 if the WooCommerce product is already mapped — unmap it first.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties: {}
              example: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: WooCommerce integration instance ID
        example: '1'
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: WooCommerce product ID
        example: '1'
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 201 Created (new SKU product)
                  value:
                    data:
                      id: 1
                      sku: WOO-WIDGET-L
                      unified_title: Widget Large
                      productListing:
                        id: 42
                        product_id: 200
                    linked_existing: false
                    message: SKU product created and mapped successfully.
                example-1:
                  summary: 201 Created (linked to existing SKU)
                  value:
                    data:
                      id: 1
                      sku: WOO-WIDGET-L
                      unified_title: Widget Large
                      productListing:
                        id: 42
                        product_id: 200
                    linked_existing: true
                    message: Product linked to existing SKU product successfully.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: Product is already mapped. Unmap it first.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-woo-commerce-integrationinstance-products-product-create-sku-product
  /api/woo-commerce/{integration_instance}/products/export:
    get:
      tags:
      - WooCommerce
      summary: Export Products
      description: 'Export WooCommerce products as a file download (CSV or Excel).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Response is a binary file download, not JSON.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
            Content-Disposition:
              schema:
                type: string
                example: attachment; filename="woocommerce-products.xlsx"
          content:
            text/plain:
              schema:
                type: string
                example: <binary file content>
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-woo-commerce-integration-instance-products-export
  /api/woo-commerce/{integration_instance}/products/archive:
    put:
      tags:
      - WooCommerce
      summary: Archive Products
      description: 'Archive WooCommerce products (hide from active list without deleting).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Request Body:

        - ids (array, required) — IDs of WooCommerce products to archive (must belong
        to this integration instance)


        Bulk selection contract:

        - {"ids": [1, 2]} — act on the given channel product IDs

        - {"mode": "all"} — act on all products for the integration instance

        - {"apply_to_all": true, "filters": {...}} — act only on products matching
        the filters. The filters object accepts the same filter keys as the corresponding
        products list endpoint (bare column keys) and/or a "filter_groups" tree (base64-encoded
        JSON). With apply_to_all and no filters, all products for the instance are
        targeted.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 501
                - 502
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Products archived successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-woo-commerce-integration-instance-products-archive
  /api/woo-commerce/{integration_instance}/products/unarchive:
    put:
      tags:
      - WooCommerce
      summary: Unarchive Products
      description: 'Unarchive previously archived WooCommerce products.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Request Body:

        - ids (array, required) — IDs of WooCommerce products to unarchive


        Bulk selection contract:

        - {"ids": [1, 2]} — act on the given channel product IDs

        - {"mode": "all"} — act on all products for the integration instance

        - {"apply_to_all": true, "filters": {...}} — act only on products matching
        the filters. The filters object accepts the same filter keys as the corresponding
        products list endpoint (bare column keys) and/or a "filter_groups" tree (base64-encoded
        JSON). With apply_to_all and no filters, all products for the instance are
        targeted.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 501
                - 502
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Products archived successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-woo-commerce-integration-instance-products-unarchive
  /api/woo-commerce/{integration_instance}/products/archiveable:
    post:
      tags:
      - WooCommerce
      summary: Check Archiveable Products
      description: 'Check which products from the provided list can be archived.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Request Body:

        - ids (array, required) — IDs of WooCommerce products to check'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 501
                - 502
                - 503
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: integer
                example:
                  data:
                  - 501
                  - 502
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-woo-commerce-integration-instance-products-archiveable
  /api/woo-commerce/{integration_instance}/products/delete:
    put:
      tags:
      - WooCommerce
      summary: Delete Products
      description: 'Permanently delete WooCommerce products from SKU.io (does not
        delete from WooCommerce).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Request Body:

        - ids (array, required) — IDs of WooCommerce products to delete'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 501
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Products deleted successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-woo-commerce-integration-instance-products-delete
  /api/woo-commerce/{integration_instance}/products/deleteable:
    put:
      tags:
      - WooCommerce
      summary: Check Deleteable Products
      description: 'Check which products from the provided list can be deleted.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Request Body:

        - ids (array, required) — IDs of WooCommerce products to check'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 501
                - 502
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: integer
                example:
                  data:
                  - 501
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-woo-commerce-integration-instance-products-deleteable
  /api/woo-commerce/{integration_instance}/products/import-mappings:
    post:
      tags:
      - WooCommerce
      summary: Import Product Mappings
      description: "Queue a background job to import product field mappings for this\
        \ integration instance.\n\n:::info[Authorization]\nAny valid API token can\
        \ call this endpoint — no specific scope required. [Manage tokens](https://app.sku.io/settings/api).\n\
        :::\n\nAuthentication: Requires Bearer token.\n\nRequest Body:\n- mappings\
        \ (array, required) — Array of column mapping configurations\n  - column (string)\
        \ — Source column from WooCommerce\n  - mapped_to (string) — Target field\
        \ in SKU.io"
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                mappings:
                  type: array
                  items:
                    type: object
                    properties:
                      column:
                        type: string
                      mapped_to:
                        type: string
              example:
                mappings:
                - column: sku
                  mapped_to: sku
                - column: name
                  mapped_to: name
                - column: price
                  mapped_to: price
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Added to queue, mappings will be imported shortly.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-woo-commerce-integration-instance-products-import-mappings
  /api/woo-commerce/{integration_instance}/products/sync-inventory:
    post:
      tags:
      - WooCommerce
      summary: Sync Inventory to WooCommerce
      description: 'Push current SKU.io inventory quantities to WooCommerce for selected
        products.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Request Body:

        - ids (array, optional) — Specific WooCommerce product IDs to sync. If omitted,
        syncs all products.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 501
                - 502
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Successfully submitted to sales channel.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-woo-commerce-integration-instance-products-sync-inventory
  /api/woo-commerce/{integration_instance}/orders:
    get:
      tags:
      - WooCommerce
      summary: List Orders
      description: 'List WooCommerce orders for an integration instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Quick Filters:

        - filter[search] (string, optional) — matches order number or WooCommerce
        order ID

        - filter[order_status] (string, optional) — exact status: pending, processing,
        on-hold, completed, cancelled, refunded, failed (''all'' is a no-op)

        - filter[archived_status] (string, optional) — ''active'' (default) or ''archived''

        - filter[has_sku_order] (string, optional) — ''true'' for orders linked to
        a SKU.io sales order, ''false'' for unlinked


        Advanced Filters (filter_groups):

        Base64-encoded JSON tree with and/or conjunctions and nested groups.

        - Text columns: number — operators: is, is_not, contains, does_not_contain,
        starts_with, ends_with, is_one_of, is_not_one_of, is_empty, is_not_empty

        - Numeric columns: total, total_tax — operators: is, is_not, greater_than,
        less_than, greater_than_or_equal, less_than_or_equal, between, is_one_of,
        is_empty, is_not_empty

        - Date columns: date_created_gmt, created_at, updated_at — operators: is,
        is_not, before, after, on_or_before, on_or_after, between, today, yesterday,
        past_week, past_month, past_year, past_days, days_ago, is_empty, is_not_empty

        Unregistered filter columns return HTTP 400.


        Sorting: sort=field or sort=-field (descending). Allowed sorts: id, woo_commerce_id,
        number, status, currency, date_created_gmt, total, total_tax, created_at,
        updated_at. Default: -id.


        Pagination: page (default 1), per_page (default 10). Standard paginator response
        with data, current_page, last_page, per_page, total, from, to.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        woo_commerce_id:
                          type: string
                        number:
                          type: string
                        status:
                          type: string
                        error_log:
                          type: string
                          nullable: true
                        currency:
                          type: string
                        date_completed_gmt:
                          type: string
                          nullable: true
                        date_modified_gmt:
                          type: string
                        date_created_gmt:
                          type: string
                        total:
                          type: string
                        total_tax:
                          type: string
                        archived_at:
                          type: string
                          nullable: true
                        pre_start_date_import:
                          type: boolean
                        created_at:
                          type: string
                        updated_at:
                          type: string
                        sku_sales_order:
                          type: object
                          properties:
                            id:
                              type: integer
                            number:
                              type: string
                            order_status:
                              type: string
                            fulfillment_status:
                              type: string
                            payment_status:
                              type: string
                        last_synced_at:
                          type: string
                        json_object:
                          type: object
                          properties:
                            id:
                              type: integer
                            number:
                              type: string
                            status:
                              type: string
                            currency:
                              type: string
                            total:
                              type: string
                            total_tax:
                              type: string
                            billing:
                              type: object
                              properties:
                                first_name:
                                  type: string
                                last_name:
                                  type: string
                                email:
                                  type: string
                  current_page:
                    type: integer
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  next_page_url:
                    type: string
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 601
                    integration_instance_id: 1
                    woo_commerce_id: '10001'
                    number: '10001'
                    status: processing
                    error_log: null
                    currency: USD
                    date_completed_gmt: null
                    date_modified_gmt: '2026-06-01T09:15:00.000000Z'
                    date_created_gmt: '2026-06-01T09:00:00.000000Z'
                    total: '49.99'
                    total_tax: '4.10'
                    archived_at: null
                    pre_start_date_import: false
                    created_at: '2026-06-01T09:05:00.000000Z'
                    updated_at: '2026-06-01T09:15:00.000000Z'
                    sku_sales_order:
                      id: 1234
                      number: SO-2026-001
                      order_status: open
                      fulfillment_status: unfulfilled
                      payment_status: paid
                    last_synced_at: '2026-06-01T09:15:00+00:00'
                    json_object:
                      id: 10001
                      number: '10001'
                      status: processing
                      currency: USD
                      total: '49.99'
                      total_tax: '4.10'
                      billing:
                        first_name: Jane
                        last_name: Smith
                        email: jane@example.com
                  current_page: 1
                  first_page_url: https://example.sku.io/api/woo-commerce/1/orders?page=1
                  from: 1
                  last_page: 12
                  last_page_url: https://example.sku.io/api/woo-commerce/1/orders?page=12
                  next_page_url: https://example.sku.io/api/woo-commerce/1/orders?page=2
                  path: https://example.sku.io/api/woo-commerce/1/orders
                  per_page: 10
                  prev_page_url: null
                  to: 10
                  total: 120
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-woo-commerce-integration-instance-orders
  /api/woo-commerce/{integration_instance}/orders/{order}:
    get:
      tags:
      - WooCommerce
      summary: Show Order
      description: 'Get a single WooCommerce order with order items loaded.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: order
        in: path
        schema:
          type: integer
        required: true
        description: WooCommerce order local DB ID
        example: '601'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      sku_sales_order:
                        type: object
                        properties:
                          id:
                            type: integer
                          number:
                            type: string
                      json_object:
                        type: object
                        properties:
                          id:
                            type: integer
                          number:
                            type: string
                          status:
                            type: string
                          total:
                            type: string
                          line_items:
                            type: array
                            items:
                              type: object
                              properties:
                                id:
                                  type: integer
                                name:
                                  type: string
                                quantity:
                                  type: integer
                                price:
                                  type: string
                                sku:
                                  type: string
                example:
                  data:
                    id: 601
                    integration_instance_id: 1
                    sku_sales_order:
                      id: 1234
                      number: SO-2024-001
                    json_object:
                      id: 10001
                      number: '10001'
                      status: processing
                      total: '49.99'
                      line_items:
                      - id: 1
                        name: Blue Widget
                        quantity: 2
                        price: '19.99'
                        sku: BW-001
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-woo-commerce-integration-instance-orders-order
    put:
      tags:
      - WooCommerce
      summary: Update Order
      description: 'Update a WooCommerce order record.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties: {}
              example: {}
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: order
        in: path
        schema:
          type: integer
        required: true
        description: WooCommerce order local DB ID
        example: '601'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                example:
                  data:
                    id: 601
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-woo-commerce-integration-instance-orders-order
    delete:
      tags:
      - WooCommerce
      summary: Delete Order
      description: 'Delete a WooCommerce order record from SKU.io.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: order
        in: path
        schema:
          type: integer
        required: true
        description: WooCommerce order local DB ID
        example: '601'
      responses:
        '204':
          description: No Content
          content:
            text/plain:
              schema:
                type: string
                example: ''
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-woo-commerce-integration-instance-orders-order
  /api/woo-commerce/{integration_instance}/orders/create-sku-orders:
    post:
      tags:
      - WooCommerce
      summary: Create SKU Orders from WooCommerce
      description: 'Create SKU.io sales orders from selected WooCommerce orders.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Request Body:

        - ids (array of integers, optional) — WooCommerce order local DB IDs to convert.
        Omit if create_all_orders is true or filters are provided.

        - create_all_orders (boolean, optional) — If true, creates SKU orders for
        all eligible WooCommerce orders

        - filters (object, optional) — list view filters to determine which orders
        to process


        Bulk selection contract:

        - {"ids": [1, 2]} — create for the given channel order IDs

        - {"create_all_orders": true} — create for all eligible orders on the integration
        instance

        - {"create_all_orders": true, "filters": {...}} — create only for orders matching
        the filters. The filters object accepts the same filter keys as the corresponding
        orders list endpoint (bare column keys, e.g. {"order_status": "pending"})
        and/or a "filter_groups" tree (base64-encoded JSON, same format as the list
        endpoint). When filters match no orders, nothing is created and the response
        message is "No orders to create".

        - Legacy {"conjunction", "filterSet"} filter payloads are rejected with 422.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
                create_all_orders:
                  type: boolean
              example:
                ids:
                - 601
                - 602
                create_all_orders: false
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Sku.io sales orders successfully created
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-woo-commerce-integration-instance-orders-create-sku-orders
  /api/woo-commerce/{integration_instance}/orders/update-sku-orders:
    post:
      tags:
      - WooCommerce
      summary: Update SKU Orders from WooCommerce
      description: 'Update SKU.io sales orders from WooCommerce order data.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Request Body:

        - ids (array of integers, optional) — WooCommerce order IDs whose linked SKU
        orders should be updated

        - update_all_orders (boolean, optional) — If true, update all eligible orders

        - use_jobs (boolean, optional) — If true, process updates asynchronously via
        jobs

        - filters (object, optional) — list view filters to determine scope'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
                update_all_orders:
                  type: boolean
                use_jobs:
                  type: boolean
              example:
                ids:
                - 601
                - 602
                update_all_orders: false
                use_jobs: true
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Sku.io sales orders successfully updated
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-woo-commerce-integration-instance-orders-update-sku-orders
  /api/woo-commerce/{integration_instance}/orders/refresh:
    post:
      tags:
      - WooCommerce
      summary: Refresh Orders
      description: 'Queue a background job to refresh all orders from the WooCommerce
        API.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Added to queue, orders will be refreshed shortly.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-woo-commerce-integration-instance-orders-refresh
  /api/woo-commerce/{integration_instance}/orders/refresh-order:
    post:
      tags:
      - WooCommerce
      summary: Refresh Single Order
      description: 'Refresh a single WooCommerce order by its unique WooCommerce order
        ID.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Request Body:

        - uniqueId (string, required) — The WooCommerce order ID (from json_object.id)'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                uniqueId:
                  type: string
              example:
                uniqueId: '10001'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      sku_sales_order:
                        type: string
                        nullable: true
                      json_object:
                        type: object
                        properties:
                          id:
                            type: integer
                          status:
                            type: string
                          total:
                            type: string
                example:
                  data:
                    id: 601
                    integration_instance_id: 1
                    sku_sales_order: null
                    json_object:
                      id: 10001
                      status: completed
                      total: '49.99'
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Order not found
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-woo-commerce-integration-instance-orders-refresh-order
  /api/woo-commerce/{integration_instance}/orders/export:
    get:
      tags:
      - WooCommerce
      summary: Export Orders
      description: 'Export WooCommerce orders as a file download.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Response is a binary file download, not JSON.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
            Content-Disposition:
              schema:
                type: string
                example: attachment; filename="woocommerce-orders.xlsx"
          content:
            text/plain:
              schema:
                type: string
                example: <binary file content>
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-woo-commerce-integration-instance-orders-export
  /api/woo-commerce/{integration_instance}/fulfill:
    post:
      tags:
      - WooCommerce
      summary: Fulfill Orders
      description: 'Submit fulfillments to WooCommerce for the specified orders.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        This endpoint marks orders as completed in WooCommerce and submits tracking
        information if available.


        Authentication: Requires Bearer token.


        Request Body:

        - order_ids (array of integers, required) — WooCommerce order local DB IDs
        to fulfill'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                order_ids:
                  type: array
                  items:
                    type: integer
              example:
                order_ids:
                - 601
                - 602
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Fulfillments submitted successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-woo-commerce-integration-instance-fulfill
  /api/walmart:
    get:
      tags:
      - Walmart
      summary: List Integration Instances
      description: 'List all Walmart integration instances (list view endpoint).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Query parameters:

        - search: string — full-text search

        - sort: string — column name (prefix with - for descending, e.g. -created_at)

        - limit: integer — records per page (default 10)

        - page: integer — page number

        - archived: 0|1 — include archived instances (default 0)

        - included[]: JSON-encoded array of additional columns to include

        - excluded[]: JSON-encoded array of columns to exclude

        - table_specifications: 1 — return only table column specifications'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_id:
                          type: integer
                        name:
                          type: string
                        connection_status:
                          type: string
                        is_automatic_sync_enabled:
                          type: boolean
                        integration_settings:
                          type: object
                          properties:
                            start_date:
                              type: string
                            store_id:
                              type: integer
                            auto_link_products:
                              type: boolean
                            auto_create_products:
                              type: boolean
                        created_at:
                          type: string
                        updated_at:
                          type: string
                        integration_name:
                          type: string
                        store:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                  total:
                    type: integer
                  per_page:
                    type: integer
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                example:
                  data:
                  - id: 1
                    integration_id: 7
                    name: My Walmart Marketplace
                    connection_status: connected
                    is_automatic_sync_enabled: true
                    integration_settings:
                      start_date: '2024-01-01'
                      store_id: 1
                      auto_link_products: true
                      auto_create_products: false
                    created_at: '2024-01-15T00:00:00.000000Z'
                    updated_at: '2024-06-01T00:00:00.000000Z'
                    integration_name: Walmart
                    store:
                      id: 1
                      name: Main Store
                  total: 1
                  per_page: 10
                  current_page: 1
                  last_page: 1
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-walmart
    post:
      tags:
      - Walmart
      summary: Create Integration Instance
      description: 'Create a new Walmart integration instance. After creation, automatically
        fetches an access token, dispatches jobs to download locations, and refresh
        products and orders.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Fields:

        - name (required, string, unique): Human-readable name for this integration
        instance

        - integration_id (required, integer): ID of the Walmart integration type

        - environment (optional, string): Walmart environment — `sandbox` or `production`.
        Ignored on production servers (always forced to `production`). Defaults to
        `sandbox` on non-production servers. **Immutable after creation** — OAuth
        credentials are bound to the issuing environment. To switch, delete and recreate
        the instance.

        - connection_settings.clientId (optional, string): Walmart API client ID

        - connection_settings.clientSecret (optional, string): Walmart API client
        secret

        - integration_settings.start_date (required, string): Date to start syncing
        orders/products from (YYYY-MM-DD)

        - integration_settings.store_id (required, integer): Internal store ID to
        associate with

        - integration_settings.auto_link_products (required, boolean): Automatically
        link Walmart products to SKU products

        - integration_settings.auto_create_products (required, boolean): Automatically
        create SKU products from Walmart products

        - integration_settings.sales_nominal_code_id (nullable, integer): Nominal
        code ID for sales accounting

        - integration_settings.cogs_nominal_code_id (nullable, integer): Nominal code
        ID for cost of goods sold

        - integration_settings.shipping_revenue_nominal_code_id (nullable, integer):
        Nominal code ID for shipping revenue

        - integration_settings.shipping_refund_nominal_code_id (nullable, integer):
        Nominal code ID for shipping refunds

        - integration_settings.sales_returns_allowances_nominal_code_id (nullable,
        integer): Nominal code ID for returns

        - integration_settings.sync_sales_order_invoices_to_accounting (boolean, default
        true): Sync invoices to accounting

        - integration_settings.sync_sales_credit_to_accounting (boolean, default true):
        Sync credits to accounting

        - integration_settings.proforma_marketplace_cost_percentage (nullable, float):
        Marketplace cost percentage

        - integration_settings.proforma_payment_cost_percentage (nullable, float):
        Payment cost percentage

        - integration_settings.batch_period_sales_order_fulfillments (nullable, string):
        Batch period override for fulfillments

        - integration_settings.batch_period_customer_returns (nullable, string): Batch
        period override for customer returns

        - is_automatic_sync_enabled (boolean, default false): Enable automatic synchronization'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                integration_id:
                  type: integer
                environment:
                  type: string
                connection_settings:
                  type: object
                  properties:
                    clientId:
                      type: string
                    clientSecret:
                      type: string
                integration_settings:
                  type: object
                  properties:
                    start_date:
                      type: string
                    store_id:
                      type: integer
                    auto_link_products:
                      type: boolean
                    auto_create_products:
                      type: boolean
                    sales_nominal_code_id:
                      type: string
                      nullable: true
                    cogs_nominal_code_id:
                      type: string
                      nullable: true
                    shipping_revenue_nominal_code_id:
                      type: string
                      nullable: true
                    shipping_refund_nominal_code_id:
                      type: string
                      nullable: true
                    sales_returns_allowances_nominal_code_id:
                      type: string
                      nullable: true
                    sync_sales_order_invoices_to_accounting:
                      type: boolean
                    sync_sales_credit_to_accounting:
                      type: boolean
                is_automatic_sync_enabled:
                  type: boolean
              example:
                name: My Walmart Marketplace
                integration_id: 7
                environment: sandbox
                connection_settings:
                  clientId: your-walmart-client-id
                  clientSecret: your-walmart-client-secret
                integration_settings:
                  start_date: '2024-01-01'
                  store_id: 1
                  auto_link_products: true
                  auto_create_products: false
                  sales_nominal_code_id: null
                  cogs_nominal_code_id: null
                  shipping_revenue_nominal_code_id: null
                  shipping_refund_nominal_code_id: null
                  sales_returns_allowances_nominal_code_id: null
                  sync_sales_order_invoices_to_accounting: true
                  sync_sales_credit_to_accounting: true
                is_automatic_sync_enabled: false
      parameters: []
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_id:
                        type: integer
                      name:
                        type: string
                      environment:
                        type: string
                      connection_status:
                        type: string
                      is_automatic_sync_enabled:
                        type: boolean
                      created_at:
                        type: string
                      updated_at:
                        type: string
                  message:
                    type: string
                    nullable: true
                example:
                  data:
                    id: 1
                    integration_id: 7
                    name: My Walmart Marketplace
                    environment: sandbox
                    connection_status: connected
                    is_automatic_sync_enabled: false
                    created_at: '2024-01-15T00:00:00.000000Z'
                    updated_at: '2024-01-15T00:00:00.000000Z'
                  message: null
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      name:
                        type: array
                        items:
                          type: string
                      integration_settings.start_date:
                        type: array
                        items:
                          type: string
                example:
                  message: The name has already been taken.
                  errors:
                    name:
                    - The name has already been taken.
                    integration_settings.start_date:
                    - The integration settings.start date field is required.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-walmart
  /api/walmart/{integrationInstance}:
    get:
      tags:
      - Walmart
      summary: Get Integration Instance
      description: 'Get a single Walmart integration instance with salesChannel and
        integration relationships loaded.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_id:
                        type: integer
                      name:
                        type: string
                      connection_status:
                        type: string
                      is_automatic_sync_enabled:
                        type: boolean
                      integration_settings:
                        type: object
                        properties:
                          start_date:
                            type: string
                          store_id:
                            type: integer
                          auto_link_products:
                            type: boolean
                          auto_create_products:
                            type: boolean
                          sync_sales_order_invoices_to_accounting:
                            type: boolean
                          sync_sales_credit_to_accounting:
                            type: boolean
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      integration_name:
                        type: string
                      store:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                example:
                  data:
                    id: 1
                    integration_id: 7
                    name: My Walmart Marketplace
                    connection_status: connected
                    is_automatic_sync_enabled: true
                    integration_settings:
                      start_date: '2024-01-01'
                      store_id: 1
                      auto_link_products: true
                      auto_create_products: false
                      sync_sales_order_invoices_to_accounting: true
                      sync_sales_credit_to_accounting: true
                    created_at: '2024-01-15T00:00:00.000000Z'
                    updated_at: '2024-06-01T00:00:00.000000Z'
                    integration_name: Walmart
                    store:
                      id: 1
                      name: Main Store
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No query results for model [Modules\Walmart\Entities\WalmartIntegrationInstance].
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-walmart-integrationinstance
    put:
      tags:
      - Walmart
      summary: Update Integration Instance
      description: 'Update a Walmart integration instance. Supports both PUT (full
        update) and PATCH (partial update — merges connection_settings and integration_settings
        with existing values).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Side effects:

        - If start_date changes, updates the sales channel date

        - If pricing.masterOfPrice changes, dispatches a job to re-cache product listing
        prices

        - If inventory settings change, invalidates the entire inventory cache

        - If accounting sync settings change, updates related accounting transactions'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                integration_settings:
                  type: object
                  properties:
                    start_date:
                      type: string
                    store_id:
                      type: integer
                    auto_link_products:
                      type: boolean
                    auto_create_products:
                      type: boolean
                    sales_nominal_code_id:
                      type: string
                      nullable: true
                    cogs_nominal_code_id:
                      type: string
                      nullable: true
                    shipping_revenue_nominal_code_id:
                      type: string
                      nullable: true
                    shipping_refund_nominal_code_id:
                      type: string
                      nullable: true
                    sales_returns_allowances_nominal_code_id:
                      type: string
                      nullable: true
                    sync_sales_order_invoices_to_accounting:
                      type: boolean
                    sync_sales_credit_to_accounting:
                      type: boolean
                is_automatic_sync_enabled:
                  type: boolean
              example:
                name: My Walmart Marketplace Updated
                integration_settings:
                  start_date: '2024-01-01'
                  store_id: 1
                  auto_link_products: true
                  auto_create_products: false
                  sales_nominal_code_id: null
                  cogs_nominal_code_id: null
                  shipping_revenue_nominal_code_id: null
                  shipping_refund_nominal_code_id: null
                  sales_returns_allowances_nominal_code_id: null
                  sync_sales_order_invoices_to_accounting: true
                  sync_sales_credit_to_accounting: true
                is_automatic_sync_enabled: true
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      is_automatic_sync_enabled:
                        type: boolean
                      updated_at:
                        type: string
                example:
                  data:
                    id: 1
                    name: My Walmart Marketplace Updated
                    is_automatic_sync_enabled: true
                    updated_at: '2024-06-10T00:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-walmart-integrationinstance
    patch:
      tags:
      - Walmart
      summary: Partial Update Integration Instance
      description: 'Partially update a Walmart integration instance. Settings are
        deep-merged with existing values — only send the fields you want to change.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                is_automatic_sync_enabled:
                  type: boolean
              example:
                is_automatic_sync_enabled: true
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      is_automatic_sync_enabled:
                        type: boolean
                      updated_at:
                        type: string
                example:
                  data:
                    id: 1
                    name: My Walmart Marketplace
                    is_automatic_sync_enabled: true
                    updated_at: '2024-06-10T00:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: patch-api-walmart-integrationinstance
    delete:
      tags:
      - Walmart
      summary: Delete Integration Instance
      description: 'Delete a Walmart integration instance. Dispatches a background
        job to clean up associated data asynchronously.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '1'
      responses:
        '204':
          description: No Content
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            text/plain:
              schema:
                type: string
                example: ''
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-walmart-integrationinstance
  /api/walmart/{integration_instance}/store-mapped-warehouse-locations:
    put:
      tags:
      - Walmart
      summary: Store Mapped Warehouse Locations
      description: 'Map Walmart ship nodes (locations) to internal warehouses. Updates
        the warehouse_id for each Walmart location.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Fields:

        - warehouse_mappings (required, array): Array of ship-node-to-warehouse mappings

        - warehouse_mappings.*.shipNode (required, integer): Walmart ship node ID
        (must exist in walmart_locations)

        - warehouse_mappings.*.warehouse_id (nullable, integer): Internal warehouse
        ID (must exist in warehouses table, or null to unmap)'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                warehouse_mappings:
                  type: array
                  items:
                    type: object
                    properties:
                      shipNode:
                        type: integer
                      warehouse_id:
                        type: integer
              example:
                warehouse_mappings:
                - shipNode: 1001
                  warehouse_id: 2
                - shipNode: 1002
                  warehouse_id: null
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: string
                    nullable: true
                  message:
                    type: string
                example:
                  data: null
                  message: Warehouse mappings updated successfully.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      warehouse_mappings.0.shipNode:
                        type: array
                        items:
                          type: string
                example:
                  message: The warehouse mappings.0.ship node field must exist in
                    walmart locations.
                  errors:
                    warehouse_mappings.0.shipNode:
                    - The warehouse mappings.0.ship node field must exist in walmart
                      locations.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: put-api-walmart-integration-instance-store-mapped-warehouse-locations
  /api/walmart/{integration_instance}/download-locations:
    get:
      tags:
      - Walmart
      summary: Download Locations
      description: 'Sync Walmart ship nodes synchronously (runs a background job inline)
        and return the current list of Walmart locations along with configured inventory
        locations from the integration settings.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Errors:

        - 422: Returned when Walmart credentials are invalid or expired (WalmartReauthorizeException).'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      walmartLocations:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            shipNode:
                              type: integer
                            integration_instance_id:
                              type: integer
                            name:
                              type: string
                            type:
                              type: string
                            warehouse_id:
                              type: integer
                            created_at:
                              type: string
                      inventoryLocations:
                        type: array
                        items:
                          type: object
                          properties:
                            shipNode:
                              type: integer
                            warehouse_id:
                              type: integer
                example:
                  data:
                    walmartLocations:
                    - id: 1
                      shipNode: 1001
                      integration_instance_id: 1
                      name: East Fulfillment Center
                      type: SellerOwned
                      warehouse_id: 2
                      created_at: '2024-01-15T00:00:00.000000Z'
                    inventoryLocations:
                    - shipNode: 1001
                      warehouse_id: 2
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: string
                    nullable: true
                  message:
                    type: string
                example:
                  data: null
                  message: Walmart credentials are invalid or expired. Please re-authorize
                    the integration.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-walmart-integration-instance-download-locations
  /api/walmart/{integrationInstance}/get-authorization-url:
    get:
      tags:
      - Walmart
      summary: Get Authorization URL
      description: 'Get the Walmart OAuth authorization URL for connecting the integration.
        Note: OAuth support is planned but not yet implemented. Walmart currently
        uses client ID + client secret authentication.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: string
                example:
                  data: https://marketplace.walmart.com/oauth/authorize?client_id=your-client-id&redirect_uri=https%3A%2F%2Fapp.sku.io%2Fwalmart%2Fcallback
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-walmart-integrationinstance-get-authorization-url
  /api/walmart/{integrationInstance}/products:
    get:
      tags:
      - Walmart
      summary: List Products
      description: 'List Walmart products for a specific integration instance (list
        view endpoint).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Product fields include: id, integration_instance_id, mart, sku, condition,
        wpid, upc, gtin, productName, shelf, productType, priceCurrency, priceAmount,
        publishedStatus, lifecycleStatus.


        Available optional columns (via included[]):

        - product: Linked SKU product details (id, name, sku, listing_id)

        - subscription_offering: Linked subscription offering (id, name, sku)

        - mapped_at: Date the product was mapped

        - mapped_sku: SKU of the mapped product

        - json_object: Full raw Walmart product JSON data

        - integration_instance_id: Integration instance ID

        - product_listing_id: Product listing ID'
      parameters:
      - name: search
        in: query
        schema:
          type: string
        description: Search term for product name, SKU, WPID, or UPC
      - name: sort
        in: query
        schema:
          type: string
        description: 'Column to sort by (prefix with - for descending, e.g. -productName).
          Available: id, sku, productName, priceAmount, publishedStatus, lifecycleStatus'
        example: productName
      - name: limit
        in: query
        schema:
          type: integer
        description: Records per page
        example: '10'
      - name: page
        in: query
        schema:
          type: integer
        description: Page number
        example: '1'
      - name: archived
        in: query
        schema:
          type: integer
        description: 'Include archived products: 0 = active only, 1 = archived only'
        example: '0'
      - name: included
        in: query
        schema:
          type: string
        description: 'JSON-encoded array of additional columns: ["product", "subscription_offering",
          "mapped_at", "mapped_sku", "json_object", "integration_instance_id", "product_listing_id"]'
      - name: excluded
        in: query
        schema:
          type: string
        description: JSON-encoded array of columns to exclude
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        sku:
                          type: string
                        wpid:
                          type: string
                        upc:
                          type: string
                        gtin:
                          type: string
                        productName:
                          type: string
                        shelf:
                          type: string
                        productType:
                          type: string
                        priceCurrency:
                          type: string
                        priceAmount:
                          type: number
                        publishedStatus:
                          type: string
                        lifecycleStatus:
                          type: string
                        mart:
                          type: string
                        condition:
                          type: string
                        integration_instance_id:
                          type: integer
                        product_listing_id:
                          type: integer
                        product:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            sku:
                              type: string
                            listing_id:
                              type: integer
                        mapped_sku:
                          type: string
                        mapped_at:
                          type: string
                        archived_at:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  total:
                    type: integer
                  per_page:
                    type: integer
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                example:
                  data:
                  - id: 20
                    sku: WMT-WIDGET-L
                    wpid: AB12CD34EF
                    upc: 012345678901
                    gtin: 00012345678901
                    productName: Large Widget
                    shelf: Electronics
                    productType: Electronics
                    priceCurrency: USD
                    priceAmount: 39.99
                    publishedStatus: PUBLISHED
                    lifecycleStatus: ACTIVE
                    mart: WALMART_US
                    condition: New
                    integration_instance_id: 1
                    product_listing_id: 75
                    product:
                      id: 200
                      name: Large Widget
                      sku: LW-002
                      listing_id: 75
                    mapped_sku: LW-002
                    mapped_at: '2024-03-10T00:00:00.000000Z'
                    archived_at: null
                    created_at: '2024-01-25T00:00:00.000000Z'
                    updated_at: '2024-05-15T00:00:00.000000Z'
                  total: 1
                  per_page: 10
                  current_page: 1
                  last_page: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-walmart-integrationinstance-products
  /api/walmart/{integrationInstance}/products/{product}:
    get:
      tags:
      - Walmart
      summary: Get Product
      description: 'Get a single Walmart product.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: Walmart product ID
        example: '20'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      sku:
                        type: string
                      wpid:
                        type: string
                      upc:
                        type: string
                      gtin:
                        type: string
                      productName:
                        type: string
                      shelf:
                        type: string
                      productType:
                        type: string
                      priceCurrency:
                        type: string
                      priceAmount:
                        type: number
                      publishedStatus:
                        type: string
                      lifecycleStatus:
                        type: string
                      mart:
                        type: string
                      condition:
                        type: string
                      integration_instance_id:
                        type: integer
                      archived_at:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 20
                    sku: WMT-WIDGET-L
                    wpid: AB12CD34EF
                    upc: 012345678901
                    gtin: 00012345678901
                    productName: Large Widget
                    shelf: Electronics
                    productType: Electronics
                    priceCurrency: USD
                    priceAmount: 39.99
                    publishedStatus: PUBLISHED
                    lifecycleStatus: ACTIVE
                    mart: WALMART_US
                    condition: New
                    integration_instance_id: 1
                    archived_at: null
                    created_at: '2024-01-25T00:00:00.000000Z'
                    updated_at: '2024-05-15T00:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-walmart-integrationinstance-products-product
  /api/walmart/{integrationInstance}/products/create-sku-products:
    post:
      tags:
      - Walmart
      summary: Create SKU Products from Walmart
      description: 'Create SKU.io products from selected Walmart products. Products
        are created asynchronously via queue.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Fields:

        - ids (array, optional): Array of Walmart product IDs to create SKU products
        from.

        - create_all_products (boolean, default false): Create SKU products for all
        Walmart products.

        - mappings (optional, array): Product mapping overrides to persist.

        - filters (optional, object): list view filters to use instead of explicit
        ids.


        Bulk selection contract:

        - {"create_all_products": false, "ids": [1, 2]} — create for the given channel
        product IDs

        - {"create_all_products": true} — create for all unmapped products on the
        integration instance

        - {"create_all_products": true, "filters": {...}} — create only for products
        matching the filters. The filters object accepts the same filter keys as the
        corresponding products list endpoint (bare column keys) and/or a "filter_groups"
        tree (base64-encoded JSON). When filters match no products, nothing is created
        and the response message is "No products to create".

        - create_all_products is required; ids is required when create_all_products
        is false and no filters are sent.

        - Legacy {"conjunction", "filterSet"} filter payloads are rejected with 422.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
                create_all_products:
                  type: boolean
              example:
                ids:
                - 20
                - 21
                - 22
                create_all_products: false
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: string
                    nullable: true
                  message:
                    type: string
                example:
                  data: null
                  message: Added to queue, products will be created shortly.
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: object
                    properties:
                      apiErrors:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: array
                example:
                  errors:
                    apiErrors:
                    - message: Walmart product (ID 1234) has no SKU and cannot be
                        imported.
                      code: Missing SKU
                      data: []
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-walmart-integrationinstance-products-create-sku-products
  /api/walmart/{integrationInstance}/products/refresh:
    post:
      tags:
      - Walmart
      summary: Refresh Products
      description: 'Queue a job to refresh all products from Walmart for this integration
        instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: string
                    nullable: true
                  message:
                    type: string
                example:
                  data: null
                  message: Added to queue, products will be refreshed shortly.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-walmart-integrationinstance-products-refresh
  /api/walmart/{integrationInstance}/products/map:
    put:
      tags:
      - Walmart
      summary: Map Products
      description: 'Map Walmart products to SKU.io products. Creates product listings
        linking Walmart listings to internal products.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                mappings:
                  type: array
                  items:
                    type: object
                    properties:
                      sales_channel_listing_id:
                        type: string
                      product_id:
                        type: integer
              example:
                mappings:
                - sales_channel_listing_id: WMT-WIDGET-L
                  product_id: 200
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: string
                  message:
                    type: string
                    nullable: true
                example:
                  data: Successfully mapped sales channel products to sku products
                  message: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-walmart-integrationinstance-products-map
  /api/walmart/{integrationInstance}/products/{product}/smart-match:
    post:
      tags:
      - Walmart
      summary: Smart Match Product
      description: 'Find suggested SKU product matches for a single Walmart listing.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Matching strategy:

        - exact_match: SKU product whose sku == walmart_product.sku

        - barcode_match: SKU product whose barcode == walmart_product.upc (falls back
        to gtin)

        - similar_matches: up to 5 fuzzy matches by productName / sku tokens


        Archived SKU products are excluded. Used by the listing detail page mapping
        modal.


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: Walmart product ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      exact_match:
                        type: object
                        properties:
                          id:
                            type: integer
                          sku:
                            type: string
                          name:
                            type: string
                          barcode:
                            type: string
                          price:
                            type: number
                          type:
                            type: string
                          match_type:
                            type: string
                      barcode_match:
                        type: string
                        nullable: true
                      similar_matches:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            sku:
                              type: string
                            name:
                              type: string
                            barcode:
                              type: string
                            price:
                              type: number
                            type:
                              type: string
                            match_type:
                              type: string
                example:
                  data:
                    exact_match:
                      id: 200
                      sku: WMT-WIDGET-L
                      name: Widget Large
                      barcode: 012345678905
                      price: 19.99
                      type: simple
                      match_type: sku
                    barcode_match: null
                    similar_matches:
                    - id: 201
                      sku: WMT-WIDGET-M
                      name: Widget Medium
                      barcode: 012345678912
                      price: 14.99
                      type: simple
                      match_type: fuzzy
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-walmart-integrationinstance-products-product-smart-match
  /api/walmart/{integrationInstance}/products/{product}/map:
    post:
      tags:
      - Walmart
      summary: Map Single Product
      description: 'Map a single Walmart listing to a SKU product (or subscription
        offering). Creates a ProductListing record, or updates the existing one if
        already mapped (remap). After mapping, dispatches a job to map any previously
        unmapped sales order lines for the new listing.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Fields (exactly one of):

        - product_id (integer, required_without:subscription_offering_id): SKU product
        ID to map to. Must exist in products table.

        - subscription_offering_id (integer, required_without:product_id): Subscription
        offering ID to map to. Must exist in subscription_offerings table.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                product_id:
                  type: integer
              example:
                product_id: 200
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: Walmart product ID
        example: '1'
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      sku:
                        type: string
                      productName:
                        type: string
                      productListing:
                        type: object
                        properties:
                          id:
                            type: integer
                          sales_channel_id:
                            type: integer
                          sales_channel_listing_id:
                            type: string
                          product_id:
                            type: integer
                          subscription_offering_id:
                            type: string
                            nullable: true
                  message:
                    type: string
                example:
                  data:
                    id: 1
                    sku: WMT-WIDGET-L
                    productName: Widget Large
                    productListing:
                      id: 42
                      sales_channel_id: 7
                      sales_channel_listing_id: WMT-WIDGET-L
                      product_id: 200
                      subscription_offering_id: null
                  message: Product mapped successfully.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      product_id:
                        type: array
                        items:
                          type: string
                example:
                  message: The product id field is required when subscription offering
                    id is not present.
                  errors:
                    product_id:
                    - The product id field is required when subscription offering
                      id is not present.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-walmart-integrationinstance-products-product-map
    delete:
      tags:
      - Walmart
      summary: Unmap Single Product
      description: 'Remove the mapping between a Walmart listing and its SKU product
        by deleting the ProductListing record. The Walmart product itself is preserved.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Returns 422 if the product is not currently mapped.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: Walmart product ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      sku:
                        type: string
                      productName:
                        type: string
                      productListing:
                        type: string
                        nullable: true
                  message:
                    type: string
                example:
                  data:
                    id: 1
                    sku: WMT-WIDGET-L
                    productName: Widget Large
                    productListing: null
                  message: Product unmapped successfully.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: Product is not mapped.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-walmart-integrationinstance-products-product-map
  /api/walmart/{integrationInstance}/products/{product}/create-sku-product:
    post:
      tags:
      - Walmart
      summary: Create SKU Product from Walmart Product
      description: 'Create a new SKU product from a Walmart listing''s data and map
        it. If a SKU product with the same SKU already exists, the existing one is
        linked instead of creating a duplicate (response includes linked_existing=true).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        This handles product creation, pricing, and listing.


        Returns 422 if the Walmart product is already mapped — unmap it first.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties: {}
              example: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: Walmart product ID
        example: '1'
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 201 Created (new SKU product)
                  value:
                    data:
                      id: 1
                      sku: WMT-WIDGET-L
                      productName: Widget Large
                      productListing:
                        id: 42
                        product_id: 200
                    linked_existing: false
                    message: SKU product created and mapped successfully.
                example-1:
                  summary: 201 Created (linked to existing SKU)
                  value:
                    data:
                      id: 1
                      sku: WMT-WIDGET-L
                      productName: Widget Large
                      productListing:
                        id: 42
                        product_id: 200
                    linked_existing: true
                    message: Product linked to existing SKU product successfully.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: Product is already mapped. Unmap it first.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-walmart-integrationinstance-products-product-create-sku-product
  /api/walmart/{integrationInstance}/products/{product}/raw:
    get:
      tags:
      - Walmart
      summary: Get Raw Product from Walmart
      description: 'Fetch the raw Walmart Marketplace API response for a single item,
        live from /v3/items/{sku}. Powers the "Load Raw Data from Walmart" button
        on the listing detail page.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        The data is not persisted — it reflects the live Walmart state. Uses the product''s
        SKU for the upstream API call.


        Returns 403 if the product doesn''t belong to the given integration instance.
        Returns 500 if Walmart''s API call fails (e.g. credentials missing or SKU
        not found on Walmart).


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: Walmart product ID (internal)
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      product:
                        type: object
                        properties:
                          mart:
                            type: string
                          sku:
                            type: string
                          wpid:
                            type: string
                          upc:
                            type: string
                          gtin:
                            type: string
                          productName:
                            type: string
                          productType:
                            type: string
                          price:
                            type: object
                            properties:
                              currency:
                                type: string
                              amount:
                                type: number
                          publishedStatus:
                            type: string
                          lifecycleStatus:
                            type: string
                example:
                  data:
                    product:
                      mart: WALMART_US
                      sku: '5290084'
                      wpid: 2CB8X1RKNCG4
                      upc: ''
                      gtin: '07323450534660'
                      productName: Fjallraven Men's Ovik Fleece Sweater
                      productType: Sweaters
                      price:
                        currency: USD
                        amount: 119.99
                      publishedStatus: PUBLISHED
                      lifecycleStatus: ACTIVE
        '403':
          description: Forbidden
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: Product does not belong to this integration instance
        '500':
          description: Internal Server Error
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                  message:
                    type: string
                example:
                  error: Failed to fetch raw product data from Walmart
                  message: 'Not Found (404) Response: {"status":404,"error":"Request
                    Not Found","path":"/v3/items/5290084"}'
        '429': *id001
        '401': *id002
        '404': *id004
      operationId: get-api-walmart-integrationinstance-products-product-raw
  /api/walmart/{integrationInstance}/products/export:
    get:
      tags:
      - Walmart
      summary: Export Products
      description: 'Export Walmart products as a CSV or Excel file. Supports the same
        list view filter parameters as the list endpoint.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Response: Binary file download (text/csv or application/vnd.openxmlformats-officedocument.spreadsheetml.sheet).'
      parameters:
      - name: format
        in: query
        schema:
          type: string
        description: 'Export format: csv or xlsx'
        example: csv
      - name: search
        in: query
        schema:
          type: string
        description: Filter exported products by search term
      - name: archived
        in: query
        schema:
          type: integer
        description: 0 = active only, 1 = archived only
        example: '0'
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: text/csv
            Content-Disposition:
              schema:
                type: string
                example: attachment; filename="walmart-products.csv"
          content:
            text/plain:
              schema:
                type: string
                example: 'id,sku,productName,publishedStatus,priceAmount

                  20,WMT-WIDGET-L,Large Widget,PUBLISHED,39.99'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-walmart-integrationinstance-products-export
  /api/walmart/{integrationInstance}/products/sync-inventory:
    post:
      tags:
      - Walmart
      summary: Sync Inventory
      description: 'Push current inventory levels to Walmart for the specified products
        (or all products if ids is omitted). Submits inventory quantities to the Walmart
        Marketplace API.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Fields:

        - ids (optional, array): Array of Walmart product IDs to sync inventory for.
        If omitted, syncs all products.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 20
                - 21
                - 22
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: string
                    nullable: true
                  message:
                    type: string
                example:
                  data: null
                  message: Successfully submitted to sales channel.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-walmart-integrationinstance-products-sync-inventory
  /api/walmart/{integrationInstance}/products/archive:
    put:
      tags:
      - Walmart
      summary: Archive Products
      description: 'Archive Walmart products (soft-delete). Products are marked as
        archived and hidden from default listings.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Fields:

        - ids (required, array): Array of Walmart product IDs to archive. Must belong
        to this integration instance.


        Bulk selection contract:

        - {"ids": [1, 2]} — act on the given channel product IDs

        - {"mode": "all"} — act on all products for the integration instance

        - {"apply_to_all": true, "filters": {...}} — act only on products matching
        the filters. The filters object accepts the same filter keys as the corresponding
        products list endpoint (bare column keys) and/or a "filter_groups" tree (base64-encoded
        JSON). With apply_to_all and no filters, all products for the instance are
        targeted.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 20
                - 21
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: string
                    nullable: true
                  message:
                    type: string
                example:
                  data: null
                  message: Products archived successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-walmart-integrationinstance-products-archive
  /api/walmart/{integrationInstance}/products/unarchive:
    put:
      tags:
      - Walmart
      summary: Unarchive Products
      description: 'Unarchive previously archived Walmart products.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Fields:

        - ids (required, array): Array of Walmart product IDs to unarchive. Must belong
        to this integration instance.


        Bulk selection contract:

        - {"ids": [1, 2]} — act on the given channel product IDs

        - {"mode": "all"} — act on all products for the integration instance

        - {"apply_to_all": true, "filters": {...}} — act only on products matching
        the filters. The filters object accepts the same filter keys as the corresponding
        products list endpoint (bare column keys) and/or a "filter_groups" tree (base64-encoded
        JSON). With apply_to_all and no filters, all products for the instance are
        targeted.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 20
                - 21
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: string
                    nullable: true
                  message:
                    type: string
                example:
                  data: null
                  message: Products archived successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-walmart-integrationinstance-products-unarchive
  /api/walmart/{integrationInstance}/products/archiveable:
    post:
      tags:
      - Walmart
      summary: Check Archiveable Products
      description: 'Check which of the given Walmart products can be archived.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Fields:

        - ids (required, array): Array of Walmart product IDs to check.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 20
                - 21
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        archiveable:
                          type: boolean
                example:
                  data:
                  - id: 20
                    archiveable: true
                  - id: 21
                    archiveable: false
                    reason: Product has pending orders
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-walmart-integrationinstance-products-archiveable
  /api/walmart/{integrationInstance}/products/delete:
    put:
      tags:
      - Walmart
      summary: Delete Products
      description: 'Permanently delete Walmart products from SKU.io (does not delete
        from Walmart). Use archiveable endpoint first to check if deletion is safe.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Fields:

        - ids (required, array): Array of Walmart product IDs to delete. Must belong
        to this integration instance.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 20
                - 21
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: string
                    nullable: true
                  message:
                    type: string
                example:
                  data: null
                  message: Products deleted successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-walmart-integrationinstance-products-delete
  /api/walmart/{integrationInstance}/products/import-mappings:
    post:
      tags:
      - Walmart
      summary: Import Product Mappings
      description: 'Import product mapping data from a file (CSV/Excel). Queues a
        background job to process the mappings asynchronously.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                file:
                  type: string
                mapping_type:
                  type: string
              example:
                file: base64_encoded_csv_content
                mapping_type: listings
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: string
                    nullable: true
                  message:
                    type: string
                example:
                  data: null
                  message: Added to queue, mappings will be imported shortly.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-walmart-integrationinstance-products-import-mappings
  /api/walmart/{integrationInstance}/orders:
    get:
      tags:
      - Walmart
      summary: List Orders
      description: 'List Walmart orders for a specific integration instance (list
        view endpoint).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Order fields include: id, integration_instance_id, customerOrderId, purchaseOrderId,
        customerEmailId, customerName, estimatedDeliveryDate, estimatedShipDate, shipNodeType,
        status, orderDate, currency, total, syncStatus.


        Available optional columns (via included[]):

        - sku_sales_order: Linked SKU sales order (id, number)

        - json_object: Full raw Walmart order JSON data

        - integration_instance_id: Integration instance ID'
      parameters:
      - name: search
        in: query
        schema:
          type: string
        description: Search term for order ID, customer name, or purchase order ID
      - name: sort
        in: query
        schema:
          type: string
        description: 'Column to sort by (prefix with - for descending). Available:
          id, customerOrderId, purchaseOrderId, status, orderDate, total'
        example: -orderDate
      - name: limit
        in: query
        schema:
          type: integer
        description: Records per page
        example: '10'
      - name: page
        in: query
        schema:
          type: integer
        description: Page number
        example: '1'
      - name: archived
        in: query
        schema:
          type: integer
        description: 'Include archived orders: 0 = active only, 1 = archived only'
        example: '0'
      - name: included
        in: query
        schema:
          type: string
        description: 'JSON-encoded array of columns: ["sku_sales_order", "json_object",
          "integration_instance_id"]'
      - name: excluded
        in: query
        schema:
          type: string
        description: JSON-encoded array of columns to exclude
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        customerOrderId:
                          type: string
                        purchaseOrderId:
                          type: string
                        customerEmailId:
                          type: string
                        customerName:
                          type: string
                        estimatedDeliveryDate:
                          type: string
                        estimatedShipDate:
                          type: string
                        shipNodeType:
                          type: string
                        status:
                          type: string
                        orderDate:
                          type: string
                        currency:
                          type: string
                        total:
                          type: string
                        syncStatus:
                          type: string
                        integration_instance_id:
                          type: integer
                        sku_sales_order:
                          type: object
                          properties:
                            id:
                              type: integer
                            number:
                              type: string
                        archived_at:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  total:
                    type: integer
                  per_page:
                    type: integer
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                example:
                  data:
                  - id: 60
                    customerOrderId: '5000000001234'
                    purchaseOrderId: P0000000001234
                    customerEmailId: customer@example.com
                    customerName: John Smith
                    estimatedDeliveryDate: '2024-05-10T00:00:00.000000Z'
                    estimatedShipDate: '2024-05-07T00:00:00.000000Z'
                    shipNodeType: SellerOwned
                    status: Shipped
                    orderDate: '2024-05-05T00:00:00.000000Z'
                    currency: USD
                    total: '49.98'
                    syncStatus: synced
                    integration_instance_id: 1
                    sku_sales_order:
                      id: 600
                      number: SO-005678
                    archived_at: null
                    created_at: '2024-05-05T00:00:00.000000Z'
                    updated_at: '2024-05-07T00:00:00.000000Z'
                  total: 1
                  per_page: 10
                  current_page: 1
                  last_page: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-walmart-integrationinstance-orders
  /api/walmart/{integrationInstance}/orders/{order}:
    get:
      tags:
      - Walmart
      summary: Get Order
      description: 'Get a single Walmart order with order items loaded.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      - name: order
        in: path
        schema:
          type: integer
        required: true
        description: Walmart order ID
        example: '60'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      customerOrderId:
                        type: string
                      purchaseOrderId:
                        type: string
                      customerEmailId:
                        type: string
                      customerName:
                        type: string
                      estimatedDeliveryDate:
                        type: string
                      estimatedShipDate:
                        type: string
                      shipNodeType:
                        type: string
                      status:
                        type: string
                      orderDate:
                        type: string
                      currency:
                        type: string
                      total:
                        type: string
                      syncStatus:
                        type: string
                      integration_instance_id:
                        type: integer
                      archived_at:
                        type: string
                        nullable: true
                      orderItems:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            walmart_order_id:
                              type: integer
                            lineNumber:
                              type: string
                            itemName:
                              type: string
                            itemId:
                              type: string
                            status:
                              type: string
                            quantity:
                              type: integer
                            amount:
                              type: string
                example:
                  data:
                    id: 60
                    customerOrderId: '5000000001234'
                    purchaseOrderId: P0000000001234
                    customerEmailId: customer@example.com
                    customerName: John Smith
                    estimatedDeliveryDate: '2024-05-10T00:00:00.000000Z'
                    estimatedShipDate: '2024-05-07T00:00:00.000000Z'
                    shipNodeType: SellerOwned
                    status: Shipped
                    orderDate: '2024-05-05T00:00:00.000000Z'
                    currency: USD
                    total: '49.98'
                    syncStatus: synced
                    integration_instance_id: 1
                    archived_at: null
                    orderItems:
                    - id: 300
                      walmart_order_id: 60
                      lineNumber: '1'
                      itemName: Large Widget
                      itemId: WMT-WIDGET-L
                      status: Shipped
                      quantity: 2
                      amount: '39.98'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-walmart-integrationinstance-orders-order
  /api/walmart/{integrationInstance}/orders/create-sku-orders:
    post:
      tags:
      - Walmart
      summary: Create SKU Orders from Walmart
      description: 'Create SKU.io sales orders from selected Walmart orders.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Fields:

        - ids (array, optional): Array of Walmart order IDs to create SKU orders from.

        - create_all_orders (boolean, default false): Create SKU orders for all Walmart
        orders.

        - filters (optional, object): list view filters to use instead of explicit
        ids.


        Bulk selection contract:

        - {"ids": [1, 2]} — create for the given channel order IDs

        - {"create_all_orders": true} — create for all eligible orders on the integration
        instance

        - {"create_all_orders": true, "filters": {...}} — create only for orders matching
        the filters. The filters object accepts the same filter keys as the corresponding
        orders list endpoint (bare column keys, e.g. {"order_status": "pending"})
        and/or a "filter_groups" tree (base64-encoded JSON, same format as the list
        endpoint). When filters match no orders, nothing is created and the response
        message is "No orders to create".

        - Legacy {"conjunction", "filterSet"} filter payloads are rejected with 422.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
                create_all_orders:
                  type: boolean
              example:
                ids:
                - 60
                - 61
                - 62
                create_all_orders: false
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: string
                    nullable: true
                  message:
                    type: string
                example:
                  data: null
                  message: Sku.io sales orders successfully created
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-walmart-integrationinstance-orders-create-sku-orders
  /api/walmart/{integrationInstance}/orders/update-sku-orders:
    post:
      tags:
      - Walmart
      summary: Update SKU Orders from Walmart
      description: 'Update existing SKU.io sales orders from the latest Walmart order
        data. Useful for syncing status changes (e.g. cancellations, acknowledgements).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Fields:

        - ids (array, optional): Array of Walmart order IDs to update SKU orders from.

        - update_all_orders (boolean, default false): Update all Walmart orders''
        SKU counterparts.

        - use_jobs (boolean, optional): Process updates via queue jobs instead of
        synchronously.

        - filters (optional, object): list view filters to use instead of explicit
        ids.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
                update_all_orders:
                  type: boolean
                use_jobs:
                  type: boolean
              example:
                ids:
                - 60
                - 61
                update_all_orders: false
                use_jobs: true
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: string
                    nullable: true
                  message:
                    type: string
                example:
                  data: null
                  message: Sku.io sales orders successfully updated
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-walmart-integrationinstance-orders-update-sku-orders
  /api/walmart/{integrationInstance}/orders/refresh:
    post:
      tags:
      - Walmart
      summary: Refresh Orders
      description: 'Queue a job to refresh all orders from Walmart for this integration
        instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: string
                    nullable: true
                  message:
                    type: string
                example:
                  data: null
                  message: Added to queue, orders will be refreshed shortly.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-walmart-integrationinstance-orders-refresh
  /api/walmart/{integrationInstance}/orders/refresh-order:
    post:
      tags:
      - Walmart
      summary: Refresh Single Order
      description: 'Refresh a single Walmart order by its unique identifier (customerOrderId).
        Fetches the latest data from Walmart API and returns the updated order resource.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Fields:

        - uniqueId (required, string): The Walmart customerOrderId (e.g., ''5000000001234'')'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                uniqueId:
                  type: string
              example:
                uniqueId: '5000000001234'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      customerOrderId:
                        type: string
                      purchaseOrderId:
                        type: string
                      status:
                        type: string
                      total:
                        type: string
                      currency:
                        type: string
                      integration_instance_id:
                        type: integer
                      updated_at:
                        type: string
                example:
                  data:
                    id: 60
                    customerOrderId: '5000000001234'
                    purchaseOrderId: P0000000001234
                    status: Shipped
                    total: '49.98'
                    currency: USD
                    integration_instance_id: 1
                    updated_at: '2024-05-10T00:00:00.000000Z'
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Order not found
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-walmart-integrationinstance-orders-refresh-order
  /api/walmart/{integrationInstance}/orders/export:
    get:
      tags:
      - Walmart
      summary: Export Orders
      description: 'Export Walmart orders as a CSV or Excel file.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Response: Binary file download.'
      parameters:
      - name: format
        in: query
        schema:
          type: string
        description: 'Export format: csv or xlsx'
        example: csv
      - name: search
        in: query
        schema:
          type: string
        description: Filter by search term
      - name: archived
        in: query
        schema:
          type: integer
        description: 0 = active only, 1 = archived only
        example: '0'
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: text/csv
            Content-Disposition:
              schema:
                type: string
                example: attachment; filename="walmart-orders.csv"
          content:
            text/plain:
              schema:
                type: string
                example: 'id,customerOrderId,purchaseOrderId,status,total,currency

                  60,5000000001234,P0000000001234,Shipped,49.98,USD'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-walmart-integrationinstance-orders-export
  /api/walmart/{integrationInstance}/orders/{order}/acknowledge:
    post:
      tags:
      - Walmart
      summary: Acknowledge Order
      description: 'Acknowledge a released order to Walmart. Idempotent — orders already
        past the Created status are left unchanged. No request body.


        Authentication: Requires Bearer token.


        Requires the `integrations.sync` permission.'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      - name: order
        in: path
        schema:
          type: integer
        required: true
        description: Walmart order ID
        example: '60'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      customerOrderId:
                        type: string
                      purchaseOrderId:
                        type: string
                      customerEmailId:
                        type: string
                      customerName:
                        type: string
                      estimatedDeliveryDate:
                        type: string
                      estimatedShipDate:
                        type: string
                      shipNodeType:
                        type: string
                      status:
                        type: string
                      orderDate:
                        type: string
                      currency:
                        type: string
                      total:
                        type: string
                      syncStatus:
                        type: string
                      integration_instance_id:
                        type: integer
                      archived_at:
                        type: string
                        nullable: true
                      orderItems:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            walmart_order_id:
                              type: integer
                            lineNumber:
                              type: string
                            itemName:
                              type: string
                            itemId:
                              type: string
                            status:
                              type: string
                            quantity:
                              type: integer
                            amount:
                              type: string
                example:
                  data:
                    id: 60
                    customerOrderId: '5000000001234'
                    purchaseOrderId: P0000000001234
                    customerEmailId: customer@example.com
                    customerName: John Smith
                    estimatedDeliveryDate: '2026-07-20T00:00:00.000000Z'
                    estimatedShipDate: '2026-07-17T00:00:00.000000Z'
                    shipNodeType: SellerOwned
                    status: Acknowledged
                    orderDate: '2026-07-14T00:00:00.000000Z'
                    currency: USD
                    total: '49.98'
                    syncStatus: synced
                    integration_instance_id: 1
                    archived_at: null
                    orderItems:
                    - id: 300
                      walmart_order_id: 60
                      lineNumber: '1'
                      itemName: Large Widget
                      itemId: WMT-WIDGET-L
                      status: Acknowledged
                      quantity: 2
                      amount: '39.98'
        '403':
          description: Forbidden
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 403 Forbidden
                  value:
                    message: This order does not belong to the specified integration
                      instance.
                example-1:
                  summary: 403 Missing Permission
                  value:
                    message: User does not have the right permissions.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Walmart rejected the acknowledgement for this order.
        '429': *id001
        '401': *id002
        '404': *id004
      operationId: post-api-walmart-integrationinstance-orders-order-acknowledge
  /api/walmart/{integrationInstance}/orders/{order}/cancel-lines:
    post:
      tags:
      - Walmart
      summary: Cancel Order Lines
      description: 'Cancel order lines on Walmart (seller-initiated cancellation).


        Authentication: Requires Bearer token.


        Fields:

        - lines (optional, array): Lines to cancel. When omitted, every line still
        in a cancellable status (Created or Acknowledged) is cancelled.

        - lines[].lineNumber (required with lines, string): Walmart order line number.

        - lines[].amount (required with lines, integer): Quantity to cancel on that
        line.


        Requires the `sales_orders.cancel` permission.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                lines:
                  type: array
                  items:
                    type: object
                    properties:
                      lineNumber:
                        type: string
                      amount:
                        type: integer
              example:
                lines:
                - lineNumber: '1'
                  amount: 2
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      - name: order
        in: path
        schema:
          type: integer
        required: true
        description: Walmart order ID
        example: '60'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      customerOrderId:
                        type: string
                      purchaseOrderId:
                        type: string
                      customerEmailId:
                        type: string
                      customerName:
                        type: string
                      estimatedDeliveryDate:
                        type: string
                      estimatedShipDate:
                        type: string
                      shipNodeType:
                        type: string
                      status:
                        type: string
                      orderDate:
                        type: string
                      currency:
                        type: string
                      total:
                        type: string
                      syncStatus:
                        type: string
                      integration_instance_id:
                        type: integer
                      archived_at:
                        type: string
                        nullable: true
                      orderItems:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            walmart_order_id:
                              type: integer
                            lineNumber:
                              type: string
                            itemName:
                              type: string
                            itemId:
                              type: string
                            status:
                              type: string
                            quantity:
                              type: integer
                            amount:
                              type: string
                example:
                  data:
                    id: 60
                    customerOrderId: '5000000001234'
                    purchaseOrderId: P0000000001234
                    customerEmailId: customer@example.com
                    customerName: John Smith
                    estimatedDeliveryDate: '2026-07-20T00:00:00.000000Z'
                    estimatedShipDate: '2026-07-17T00:00:00.000000Z'
                    shipNodeType: SellerOwned
                    status: Cancelled
                    orderDate: '2026-07-14T00:00:00.000000Z'
                    currency: USD
                    total: '49.98'
                    syncStatus: synced
                    integration_instance_id: 1
                    archived_at: null
                    orderItems:
                    - id: 300
                      walmart_order_id: 60
                      lineNumber: '1'
                      itemName: Large Widget
                      itemId: WMT-WIDGET-L
                      status: Cancelled
                      quantity: 2
                      amount: '39.98'
        '403':
          description: Forbidden
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 403 Forbidden
                  value:
                    message: This order does not belong to the specified integration
                      instance.
                example-1:
                  summary: 403 Missing Permission
                  value:
                    message: User does not have the right permissions.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No cancellable lines remain on this order — lines are already
                    shipped or cancelled.
        '429': *id001
        '401': *id002
        '404': *id004
      operationId: post-api-walmart-integrationinstance-orders-order-cancel-lines
  /api/walmart/{integrationInstance}/fulfill:
    post:
      tags:
      - Walmart
      summary: Fulfill Order
      description: 'Submit a fulfillment to Walmart for a given SKU.io sales order
        fulfillment. Sends shipment/tracking information back to the Walmart Marketplace
        API.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Fields:

        - sales_order_fulfillment_id (required, integer): ID of the SKU.io sales order
        fulfillment to push to Walmart.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                sales_order_fulfillment_id:
                  type: integer
              example:
                sales_order_fulfillment_id: 456
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: string
                    nullable: true
                  message:
                    type: string
                example:
                  data: null
                  message: Successfully submitted to sales channel.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      sales_order_fulfillment_id:
                        type: array
                        items:
                          type: string
                example:
                  message: The sales order fulfillment id field must exist in sales
                    order fulfillments.
                  errors:
                    sales_order_fulfillment_id:
                    - The sales order fulfillment id field must exist in sales order
                      fulfillments.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-walmart-integrationinstance-fulfill
  /api/walmart/{integrationInstance}/wfs/inbound-shipments:
    get:
      tags:
      - Walmart
      summary: List Inbound Shipments
      description: 'Paginated list of WFS inbound shipments for an integration instance
        (Spatie QueryBuilder).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Filters (query string, all optional):

        - filter[search]: global fuzzy search over shipment_id, inbound_order_id,
        ship_node.

        - Text filters (contains, does_not_contain, is, is_not, is_one_of, is_not_one_of,
        starts_with, does_not_start_with, ends_with, does_not_end_with, is_empty,
        is_not_empty; bare key = implicit ''is''): shipment_id, inbound_order_id,
        status, ship_node, carrier_name.

        - Numeric filters (is, is_not, is_one_of, is_not_one_of, greater_than, less_than,
        greater_than_or_equal, less_than_or_equal, between, is_empty, is_not_empty):
        id, shipment_units, received_units.

        - Datetime filters (is, is_not, before, after, on_or_before, on_or_after,
        between, is_empty, is_not_empty, today, yesterday, tomorrow, past_week/month/year,
        next_week/month/year, days_ago, days_from_now, past_days, next_days): expected_delivery_date,
        walmart_created_at, created_at.

        Operator syntax: filter[&lt;column>.&lt;operator>]=value (e.g. filter[shipment_id.contains]=9012).


        Sorts (sort=&lt;field>, prefix - for descending): id, shipment_id, inbound_order_id,
        status, ship_node, shipment_units, received_units, line_count, expected_delivery_date,
        updated_expected_delivery_date, walmart_created_at, created_at. Default sort:
        -created_at.


        Pagination: page, per_page (default 10).'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        inbound_order_id:
                          type: string
                        shipment_id:
                          type: string
                        status:
                          type: string
                        can_cancel:
                          type: boolean
                        cancel_blocked_reason:
                          type: string
                          nullable: true
                        ship_node:
                          type: string
                        shipment_units:
                          type: integer
                        received_units:
                          type: integer
                        line_count:
                          type: integer
                        has_shortage:
                          type: boolean
                        expected_delivery_date:
                          type: string
                        updated_expected_delivery_date:
                          type: string
                          nullable: true
                        carrier_name:
                          type: string
                          nullable: true
                        tracking_numbers:
                          type: string
                          nullable: true
                        ship_from_address:
                          type: object
                          properties:
                            name:
                              type: string
                            line1:
                              type: string
                            line2:
                              type: string
                              nullable: true
                            city:
                              type: string
                            state:
                              type: string
                            postal_code:
                              type: string
                            country:
                              type: string
                        ship_to_address:
                          type: object
                          properties:
                            name:
                              type: string
                            line1:
                              type: string
                            line2:
                              type: string
                              nullable: true
                            city:
                              type: string
                            state:
                              type: string
                            postal_code:
                              type: string
                            country:
                              type: string
                        source_warehouse_id:
                          type: integer
                        source_supplier_id:
                          type: string
                          nullable: true
                        source_type:
                          type: string
                        source_name:
                          type: string
                        source_link_status:
                          type: string
                        source_blocks_flows:
                          type: boolean
                        walmart_created_at:
                          type: string
                        created_at:
                          type: string
                        created_by_user_id:
                          type: integer
                        created_by:
                          type: string
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                    items:
                      type: object
                      properties:
                        url:
                          type: string
                          nullable: true
                        label:
                          type: string
                        active:
                          type: boolean
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 42
                    inbound_order_id: 01J8ZT5K9Q7WFS0000000001
                    shipment_id: '9012345678'
                    status: AWAITING_DELIVERY
                    can_cancel: true
                    cancel_blocked_reason: null
                    ship_node: US-WFS-ATL2
                    shipment_units: 120
                    received_units: 0
                    line_count: 3
                    has_shortage: false
                    expected_delivery_date: '2026-07-14T00:00:00.000000Z'
                    updated_expected_delivery_date: null
                    carrier_name: null
                    tracking_numbers: null
                    ship_from_address:
                      name: Main Warehouse
                      line1: 500 Industrial Pkwy
                      line2: null
                      city: Dallas
                      state: TX
                      postal_code: '75201'
                      country: US
                    ship_to_address:
                      name: Atlanta FC
                      line1: 6055 N Bay Dr
                      line2: null
                      city: Atlanta
                      state: GA
                      postal_code: '30336'
                      country: US
                    source_warehouse_id: 7
                    source_supplier_id: null
                    source_type: warehouse
                    source_name: Main Warehouse
                    source_link_status: confirmed
                    source_blocks_flows: false
                    walmart_created_at: '2026-07-03T15:22:41.000000Z'
                    created_at: '2026-07-03T15:22:40.000000Z'
                    created_by_user_id: 5
                    created_by: Jane Operator
                  - id: 41
                    inbound_order_id: 01J8ZT5K9Q7WFS0000000000
                    shipment_id: '9012345600'
                    status: RECEIVED
                    can_cancel: false
                    cancel_blocked_reason: This shipment has already been received
                      by Walmart, so it can no longer be cancelled.
                    ship_node: US-WFS-DFW9
                    shipment_units: 60
                    received_units: 58
                    line_count: 2
                    has_shortage: true
                    expected_delivery_date: '2026-07-14T00:00:00.000000Z'
                    updated_expected_delivery_date: null
                    carrier_name: UPS
                    tracking_numbers:
                    - 1Z999AA10123456784
                    ship_from_address:
                      name: Main Warehouse
                      line1: 500 Industrial Pkwy
                      line2: null
                      city: Dallas
                      state: TX
                      postal_code: '75201'
                      country: US
                    ship_to_address:
                      name: Atlanta FC
                      line1: 6055 N Bay Dr
                      line2: null
                      city: Atlanta
                      state: GA
                      postal_code: '30336'
                      country: US
                    source_warehouse_id: null
                    source_supplier_id: 15
                    source_type: supplier
                    source_name: Acme Supply Co.
                    source_link_status: auto
                    source_blocks_flows: false
                    walmart_created_at: '2026-07-03T15:22:41.000000Z'
                    created_at: '2026-07-03T15:22:40.000000Z'
                    created_by_user_id: 5
                    created_by: Jane Operator
                  first_page_url: '{{protocol}}://{{domain}}/api/walmart/1/wfs/inbound-shipments?page=1'
                  from: 1
                  last_page: 1
                  last_page_url: '{{protocol}}://{{domain}}/api/walmart/1/wfs/inbound-shipments?page=1'
                  links:
                  - url: null
                    label: '&laquo; Previous'
                    active: false
                  - url: '{{protocol}}://{{domain}}/api/walmart/1/wfs/inbound-shipments?page=1'
                    label: '1'
                    active: true
                  - url: null
                    label: Next &raquo;
                    active: false
                  next_page_url: null
                  path: '{{protocol}}://{{domain}}/api/walmart/1/wfs/inbound-shipments'
                  per_page: 10
                  prev_page_url: null
                  to: 2
                  total: 2
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-walmart-integrationinstance-wfs-inbound-shipments
    post:
      tags:
      - Walmart
      summary: Create WFS Inbound Shipment
      description: 'Create a WFS inbound shipment from SKU.io — send the chosen SKUs/quantities
        into Walmart Fulfillment Services from a **warehouse OR a supplier** (exactly
        one). SKU.io enriches each SKU with the GTIN/UPC + description Walmart requires,
        generates a unique inboundOrderId, builds Walmart''s Create-Inbound-Shipment-Order
        payload (returnAddress from the chosen warehouse''s or supplier''s address
        + orderItems), POSTs it to Walmart (POST /v3/fulfillment/inbound-shipments),
        and persists the shipment(s) Walmart returns — Walmart may split one inbound
        order across fulfillment centers, so `data` is an array. Typically driven
        from the inbound builder or the WFS Replenishment grid''s cart ("Send to WFS").


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Request body:

        - source_warehouse_id (integer) — the warehouse the stock ships from. Required
        unless source_supplier_id is given.

        - source_supplier_id (integer) — the supplier the stock ships from (drop-ship
        into WFS). Required unless source_warehouse_id is given. Send exactly one
        of the two.

        - items (required, array, min 1) — each: { sku (required string), quantity
        (required integer >= 1) }.

        - items[].packing_type (optional, ''individual'' | ''case_packed'', default
        ''individual'') — Seller Center''s "Packing setup". Individual: each outer
        box holds one sellable unit. Case-packed: master cases of N units.

        - items[].units_per_case (optional, integer >= 1, default 1) — sellable units
        per master case (Walmart''s innerPackQty). Only meaningful for case_packed;
        quantity MUST divide evenly into cases (422 otherwise). SKU.io maps vendorPackQty
        = quantity / units_per_case (the case count).

        - items[].prep_services (optional, array of ''LABEL'' | ''BAG'') — WFS Prep
        Services Walmart performs on receipt, sent as the order item''s addOnServices.
        LABEL = item labeling ($0.45/unit), BAG = poly bagging ($0.60/unit) — billed
        by Walmart off its fixed rate card (the API carries no price field). Omit
        (or send []) for "Do it myself". Prep and packing are LOCKED once the IO is
        submitted — changing them means cancelling and recreating the inbound.

        - items[].kit_fulfillment_mode (optional): for kit/bundle SKUs — ''kit_stock''
        (ship pre-built) or ''components'' (assemble from components at the source;
        the build is deferred until the 3PL confirms ''Kits Built'').

        - expected_delivery_date (optional, date Y-m-d, must be today or later) —
        when the stock is expected to reach Walmart''s fulfillment center. Walmart
        requires a non-null estimate; when omitted SKU.io defaults it to 7 days out
        and Walmart revises it on receipt.


        Notes on the Walmart payload SKU.io builds: returnAddress.countryCode is sent
        as a 2-letter uppercase code (e.g. US), and per Walmart each item''s itemQty
        must equal vendorPackQty × innerPackQty — individually packed items ship with
        innerPackQty 1, case-packed items with innerPackQty = units_per_case.


        Each SKU must have a GTIN/UPC; a SKU without one is rejected (422) before
        any call to Walmart. Requires a Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                source_warehouse_id:
                  type: integer
                items:
                  type: array
                  items:
                    type: object
                    properties:
                      sku:
                        type: string
                      quantity:
                        type: integer
                      packing_type:
                        type: string
                      units_per_case:
                        type: integer
                      prep_services:
                        type: array
                        items:
                          type: string
                expected_delivery_date:
                  type: string
              example:
                source_warehouse_id: 8
                items:
                - sku: ABC-001
                  quantity: 24
                  packing_type: case_packed
                  units_per_case: 6
                  prep_services:
                  - LABEL
                  - BAG
                - sku: KIT-1
                  quantity: 4
                  kit_fulfillment_mode: components
                expected_delivery_date: 06/30/2026
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        inbound_order_id:
                          type: string
                        shipment_id:
                          type: string
                        status:
                          type: string
                        can_cancel:
                          type: boolean
                        cancel_blocked_reason:
                          type: string
                          nullable: true
                        ship_node:
                          type: string
                        shipment_units:
                          type: integer
                        received_units:
                          type: integer
                        has_shortage:
                          type: boolean
                        expected_delivery_date:
                          type: string
                          nullable: true
                        updated_expected_delivery_date:
                          type: string
                          nullable: true
                        carrier_name:
                          type: string
                        tracking_numbers:
                          type: string
                          nullable: true
                        walmart_created_at:
                          type: string
                        created_at:
                          type: string
                  message:
                    type: string
                example:
                  data:
                  - id: 42
                    inbound_order_id: IO-NEW-1
                    shipment_id: 0066618GDM
                    status: CREATED
                    can_cancel: true
                    cancel_blocked_reason: null
                    ship_node: NJ3
                    shipment_units: 30
                    received_units: 0
                    has_shortage: false
                    expected_delivery_date: null
                    updated_expected_delivery_date: null
                    carrier_name: WFS-FEDEX
                    tracking_numbers: null
                    walmart_created_at: '2026-06-18T19:02:30.000000Z'
                    created_at: '2026-06-18T19:05:00.000000Z'
                  message: WFS inbound shipment created
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 422 Validation Error
                  value:
                    message: Choose where this stock ships from — a warehouse or a
                      supplier.
                    errors:
                      source_warehouse_id:
                      - Choose where this stock ships from — a warehouse or a supplier.
                      items:
                      - Add at least one product to send to WFS.
                example-1:
                  summary: 422 Walmart Rejected
                  value:
                    message: 'Failed to create WFS inbound shipment: SKU ABC-009 is
                      missing a GTIN/UPC, which Walmart requires to create a WFS inbound
                      shipment.'
                example-2:
                  summary: 422 Invalid case pack
                  value:
                    message: Total units (25) must divide evenly into master cases
                      of 6.
                    errors:
                      items.0.units_per_case:
                      - Total units (25) must divide evenly into master cases of 6.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-walmart-integrationinstance-wfs-inbound-shipments
  /api/walmart/{integrationInstance}/wfs/inbound-shipments/{shipment}:
    get:
      tags:
      - Walmart
      summary: Get Inbound Shipment
      description: 'Fetch a single WFS inbound shipment by its SKU.io row id. Eager-loads
        the source warehouse (with address) and source supplier, so ship_from_address
        carries the warehouse name and source_name is populated.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Returns 404 when the shipment does not belong to the given integration instance.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      - name: shipment
        in: path
        schema:
          type: integer
        required: true
        description: WalmartWfsInboundShipment row ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      inbound_order_id:
                        type: string
                      shipment_id:
                        type: string
                      status:
                        type: string
                      can_cancel:
                        type: boolean
                      cancel_blocked_reason:
                        type: string
                        nullable: true
                      ship_node:
                        type: string
                      shipment_units:
                        type: integer
                      received_units:
                        type: integer
                      line_count:
                        type: integer
                      has_shortage:
                        type: boolean
                      expected_delivery_date:
                        type: string
                      updated_expected_delivery_date:
                        type: string
                        nullable: true
                      carrier_name:
                        type: string
                        nullable: true
                      tracking_numbers:
                        type: string
                        nullable: true
                      ship_from_address:
                        type: object
                        properties:
                          name:
                            type: string
                          line1:
                            type: string
                          line2:
                            type: string
                            nullable: true
                          city:
                            type: string
                          state:
                            type: string
                          postal_code:
                            type: string
                          country:
                            type: string
                      ship_to_address:
                        type: object
                        properties:
                          name:
                            type: string
                          line1:
                            type: string
                          line2:
                            type: string
                            nullable: true
                          city:
                            type: string
                          state:
                            type: string
                          postal_code:
                            type: string
                          country:
                            type: string
                      source_warehouse_id:
                        type: integer
                      source_supplier_id:
                        type: string
                        nullable: true
                      source_type:
                        type: string
                      source_name:
                        type: string
                      source_link_status:
                        type: string
                      source_blocks_flows:
                        type: boolean
                      walmart_created_at:
                        type: string
                      created_at:
                        type: string
                      created_by_user_id:
                        type: integer
                      created_by:
                        type: string
                example:
                  data:
                    id: 42
                    inbound_order_id: 01J8ZT5K9Q7WFS0000000001
                    shipment_id: '9012345678'
                    status: AWAITING_DELIVERY
                    can_cancel: true
                    cancel_blocked_reason: null
                    ship_node: US-WFS-ATL2
                    shipment_units: 120
                    received_units: 0
                    line_count: 3
                    has_shortage: false
                    expected_delivery_date: '2026-07-14T00:00:00.000000Z'
                    updated_expected_delivery_date: null
                    carrier_name: null
                    tracking_numbers: null
                    ship_from_address:
                      name: Main Warehouse
                      line1: 500 Industrial Pkwy
                      line2: null
                      city: Dallas
                      state: TX
                      postal_code: '75201'
                      country: US
                    ship_to_address:
                      name: Atlanta FC
                      line1: 6055 N Bay Dr
                      line2: null
                      city: Atlanta
                      state: GA
                      postal_code: '30336'
                      country: US
                    source_warehouse_id: 7
                    source_supplier_id: null
                    source_type: warehouse
                    source_name: Main Warehouse
                    source_link_status: confirmed
                    source_blocks_flows: false
                    walmart_created_at: '2026-07-03T15:22:41.000000Z'
                    created_at: '2026-07-03T15:22:40.000000Z'
                    created_by_user_id: 5
                    created_by: Jane Operator
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-walmart-integrationinstance-wfs-inbound-shipments-shipment
    delete:
      tags:
      - Walmart
      summary: Cancel Inbound Shipment
      description: 'Cancel a WFS inbound shipment. This cancels the WHOLE inbound
        order on Walmart and marks every local shipment sharing that inbound order
        as CANCELLED (Walmart splits one inbound order across FCs, and cancel is order-level).
        Any materialized source document (Warehouse Transfer / Purchase Order) is
        unwound first, and source-stock reservations are released so the stock is
        sellable again. Walmart rejects the cancel once the shipment is receiving,
        closed, or already cancelled.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Returns 200 on success, 404 when the shipment does not belong to the instance,
        and 422 when Walmart rejects the cancel or the shipment has no inbound order
        id on file.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      - name: shipment
        in: path
        schema:
          type: integer
        required: true
        description: WalmartWfsInboundShipment row ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: WFS inbound shipment cancelled
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 'Failed to cancel WFS inbound shipment: A shipment in status
                    RECEIVING can no longer be cancelled.'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-walmart-integrationinstance-wfs-inbound-shipments-shipment
  /api/walmart/{integrationInstance}/wfs/inbound-shipments/preview:
    post:
      tags:
      - Walmart
      summary: Preview WFS Inbound Shipment
      description: 'Preview an inbound order before creating it — returns Walmart''s
        destination fulfillment-center placement plus estimated transfer charges,
        without persisting anything. Takes the SAME request body as Create WFS Inbound
        Shipment.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Request body:

        - source_warehouse_id (integer) — the warehouse the stock ships from. Required
        unless source_supplier_id is given.

        - source_supplier_id (integer) — the supplier the stock ships from. Required
        unless source_warehouse_id is given. Send exactly one of the two.

        - items (required, array, min 1) — each: { sku (required string), quantity
        (required integer >= 1) }.

        - expected_delivery_date (optional, date Y-m-d, today or later).


        Validation errors return 422; a Walmart-side rejection also returns 422 with
        the failure reason. Requires a Bearer token.


        Accepts the same body as Create WFS Inbound Shipment, including the per-item
        packing_type / units_per_case / prep_services fields (see that endpoint for
        field semantics).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                source_warehouse_id:
                  type: integer
                items:
                  type: array
                  items:
                    type: object
                    properties:
                      sku:
                        type: string
                      quantity:
                        type: integer
                      packing_type:
                        type: string
                      units_per_case:
                        type: integer
                      prep_services:
                        type: array
                        items:
                          type: string
                expected_delivery_date:
                  type: string
              example:
                source_warehouse_id: 8
                items:
                - sku: ABC-001
                  quantity: 24
                  packing_type: case_packed
                  units_per_case: 6
                  prep_services:
                  - LABEL
                  - BAG
                - sku: KIT-1
                  quantity: 4
                  kit_fulfillment_mode: components
                expected_delivery_date: 06/30/2026
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      shipments:
                        type: array
                        items:
                          type: object
                          properties:
                            ship_node:
                              type: string
                            items:
                              type: array
                              items:
                                type: object
                                properties:
                                  sku:
                                    type: string
                                  quantity:
                                    type: integer
                      estimated_charges:
                        type: object
                        properties:
                          currency:
                            type: string
                          amount:
                            type: number
                example:
                  data:
                    shipments:
                    - ship_node: NJ3
                      items:
                      - sku: ABC-001
                        quantity: 20
                    estimated_charges:
                      currency: USD
                      amount: 14.5
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      source_warehouse_id:
                        type: array
                        items:
                          type: string
                      items:
                        type: array
                        items:
                          type: string
                example:
                  message: Choose where this stock ships from — a warehouse or a supplier.
                  errors:
                    source_warehouse_id:
                    - Choose where this stock ships from — a warehouse or a supplier.
                    items:
                    - Add at least one product to send to WFS.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-walmart-integrationinstance-wfs-inbound-shipments-preview
  /api/walmart/{integrationInstance}/wfs/inbound-shipments/refresh-tracked:
    post:
      tags:
      - Walmart
      summary: Refresh Shipments (Tracked Job)
      description: 'Queue a tracked background job that pulls WFS inbound shipments
        from Walmart (all pages) and upserts them. Progress is surfaced via the tracked
        job log endpoints; the response returns the tracked job log id to watch. Takes
        no request body.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Job name: ''Refresh WFS Inbound Shipments: {instance name}''. On completion
        the job stores results.shipments_synced (count synced).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties: {}
              example: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 8842
                  message: WFS inbound shipment refresh started
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-walmart-integrationinstance-wfs-inbound-shipments-refresh-tracked
  /api/walmart/{integrationInstance}/wfs/inbound-shipments/{shipment}/source:
    post:
      tags:
      - Walmart
      summary: Set Source
      description: 'Set (or confirm) the definitive source of an inbound shipment
        — a warehouse OR a supplier (exactly one). Used to resolve an imported inbound,
        confirm an auto-matched one, or re-point an existing one. Unwinds any document
        already materialized against the old source (throws/blocks if it has already
        shipped), drops the prior source reservation, marks the link confirmed, and
        re-reserves against the new warehouse (a no-op when supplier-sourced or when
        there are no SKU intent lines).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Fields:

        - source_warehouse_id (integer, required without source_supplier_id, prohibits
        source_supplier_id, exists:warehouses,id): the source warehouse.

        - source_supplier_id (integer, required without source_warehouse_id, exists:suppliers,id):
        the source supplier.

        Provide exactly one — supplying source_warehouse_id together with source_supplier_id
        is rejected.


        Response: the updated shipment (single Walmart WFS inbound shipment object).
        Returns 404 when the shipment does not belong to the instance.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                source_warehouse_id:
                  type: integer
                source_supplier_id:
                  type: string
                  nullable: true
              example:
                source_warehouse_id: 7
                source_supplier_id: null
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      - name: shipment
        in: path
        schema:
          type: integer
        required: true
        description: WalmartWfsInboundShipment row ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      inbound_order_id:
                        type: string
                      shipment_id:
                        type: string
                      status:
                        type: string
                      can_cancel:
                        type: boolean
                      cancel_blocked_reason:
                        type: string
                        nullable: true
                      ship_node:
                        type: string
                      shipment_units:
                        type: integer
                      received_units:
                        type: integer
                      line_count:
                        type: integer
                      has_shortage:
                        type: boolean
                      expected_delivery_date:
                        type: string
                      updated_expected_delivery_date:
                        type: string
                        nullable: true
                      carrier_name:
                        type: string
                        nullable: true
                      tracking_numbers:
                        type: string
                        nullable: true
                      ship_from_address:
                        type: object
                        properties:
                          name:
                            type: string
                          line1:
                            type: string
                          line2:
                            type: string
                            nullable: true
                          city:
                            type: string
                          state:
                            type: string
                          postal_code:
                            type: string
                          country:
                            type: string
                      ship_to_address:
                        type: object
                        properties:
                          name:
                            type: string
                          line1:
                            type: string
                          line2:
                            type: string
                            nullable: true
                          city:
                            type: string
                          state:
                            type: string
                          postal_code:
                            type: string
                          country:
                            type: string
                      source_warehouse_id:
                        type: integer
                      source_supplier_id:
                        type: string
                        nullable: true
                      source_type:
                        type: string
                      source_name:
                        type: string
                      source_link_status:
                        type: string
                      source_blocks_flows:
                        type: boolean
                      walmart_created_at:
                        type: string
                      created_at:
                        type: string
                example:
                  data:
                    id: 42
                    inbound_order_id: 01J8ZT5K9Q7WFS0000000001
                    shipment_id: '9012345678'
                    status: AWAITING_DELIVERY
                    can_cancel: true
                    cancel_blocked_reason: null
                    ship_node: US-WFS-ATL2
                    shipment_units: 120
                    received_units: 0
                    line_count: 3
                    has_shortage: false
                    expected_delivery_date: '2026-07-14T00:00:00.000000Z'
                    updated_expected_delivery_date: null
                    carrier_name: null
                    tracking_numbers: null
                    ship_from_address:
                      name: Main Warehouse
                      line1: 500 Industrial Pkwy
                      line2: null
                      city: Dallas
                      state: TX
                      postal_code: '75201'
                      country: US
                    ship_to_address:
                      name: Atlanta FC
                      line1: 6055 N Bay Dr
                      line2: null
                      city: Atlanta
                      state: GA
                      postal_code: '30336'
                      country: US
                    source_warehouse_id: 7
                    source_supplier_id: null
                    source_type: warehouse
                    source_name: Main Warehouse
                    source_link_status: confirmed
                    source_blocks_flows: false
                    walmart_created_at: '2026-07-03T15:22:41.000000Z'
                    created_at: '2026-07-03T15:22:40.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-walmart-integrationinstance-wfs-inbound-shipments-shipment-source
  /api/walmart/{integrationInstance}/wfs/inbound-shipments/{shipment}/items:
    get:
      tags:
      - Walmart
      summary: Get Shipment Items
      description: 'The per-SKU items Walmart holds for a shipment (sent vs. received),
        pulled live from Walmart and enriched with source-warehouse stock context.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Each row has exactly these keys:

        - sku (string|null): the item SKU / vendor SKU.

        - gtin (string|null): the item GTIN, when Walmart returns one.

        - description (string|null): the item description.

        - shipped_qty (number): units sent on this inbound (Walmart''s itemQty).

        - received_qty (number): units Walmart has received so far.

        - product_id (number|null): local product id when the SKU matches a SKU.io
        product (null when unmatched) — lets the UI link to the product page.

        - available_to_sell (number|null): the product''s sellable stock at the inbound''s
        SOURCE warehouse, already net of what this inbound reserved. Null when the
        SKU is unmatched OR the inbound isn''t warehouse-sourced (supplier/3PL inbounds
        reserve nothing).

        - committed_this_inbound (number|null): units this inbound reserved for that
        product at the source warehouse. Null under the same conditions as available_to_sell.


        Errors: 422 with { message } if the live Walmart fetch fails.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      - name: shipment
        in: path
        schema:
          type: integer
        required: true
        description: WFS inbound shipment ID
        example: '1000012345'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        sku:
                          type: string
                        gtin:
                          type: string
                        description:
                          type: string
                        shipped_qty:
                          type: integer
                        received_qty:
                          type: integer
                        product_id:
                          type: integer
                        available_to_sell:
                          type: integer
                        committed_this_inbound:
                          type: integer
                example:
                  data:
                  - sku: WIDGET-BLU-12OZ
                    gtin: 00810000000012
                    description: Blue Widget 12oz
                    shipped_qty: 50
                    received_qty: 38
                    product_id: 4821
                    available_to_sell: 38
                    committed_this_inbound: 12
                  - sku: UNKNOWN-SKU-99
                    gtin: null
                    description: Unrecognized Item
                    shipped_qty: 10
                    received_qty: 0
                    product_id: null
                    available_to_sell: null
                    committed_this_inbound: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-walmart-integrationinstance-wfs-inbound-shipments-shipment-items
  /api/walmart/{integrationInstance}/wfs/inbound-shipments/{shipment}/allocations:
    get:
      tags:
      - Walmart
      summary: List Source Allocations
      description: 'Paginated source-stock reservations (inventory allocations) for
        this inbound — the source-warehouse reservations created when the inbound
        was made so the earmarked stock can''t be oversold. Scoped to all shipments
        sharing the inbound order (split inbounds), plus any reservations handed off
        to a materialized Warehouse Transfer.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Filters:

        - filter[status]: exact allocation status (e.g. allocated, cancelled, fulfilled).

        - filter[warehouse_id]: exact source warehouse id.

        - filter[search]: allocation id (when numeric) or product SKU / name.


        Sorts (via sort): id, quantity, status, created_at. Prefix with - for descending.
        Default -id.


        Pagination: page, per_page (default 10).'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      - name: shipment
        in: path
        schema:
          type: integer
        required: true
        description: WFS inbound shipment ID
        example: '1000012345'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        product_id:
                          type: integer
                        product:
                          type: object
                          properties:
                            id:
                              type: integer
                            sku:
                              type: string
                            name:
                              type: string
                        warehouse_id:
                          type: integer
                        warehouse:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        link_id:
                          type: integer
                        link_type:
                          type: string
                        link_type_label:
                          type: string
                        link_route:
                          type: string
                          nullable: true
                        link_reference:
                          type: string
                          nullable: true
                        date:
                          type: string
                          nullable: true
                        quantity:
                          type: integer
                        status:
                          type: string
                        status_label:
                          type: string
                        priority:
                          type: integer
                        supplier_id:
                          type: string
                          nullable: true
                        purchase_order_line_id:
                          type: string
                          nullable: true
                        is_tight_coverage:
                          type: boolean
                        release_source_id:
                          type: string
                          nullable: true
                        release_source_type:
                          type: string
                          nullable: true
                        fulfilled_at:
                          type: string
                          nullable: true
                        cancelled_at:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 90211
                    product_id: 4821
                    product:
                      id: 4821
                      sku: WIDGET-BLU-12OZ
                      name: Blue Widget 12oz
                    warehouse_id: 7
                    warehouse:
                      id: 7
                      name: Main Distribution Center
                    link_id: 3312
                    link_type: Modules\Walmart\Entities\WalmartWfsInboundShipment
                    link_type_label: WalmartWfsInboundShipment
                    link_route: null
                    link_reference: null
                    date: null
                    quantity: 12
                    status: allocated
                    status_label: Allocated
                    priority: 0
                    supplier_id: null
                    purchase_order_line_id: null
                    is_tight_coverage: false
                    release_source_id: null
                    release_source_type: null
                    fulfilled_at: null
                    cancelled_at: null
                    created_at: '2026-06-28T14:05:11.000000Z'
                    updated_at: '2026-06-28T14:05:11.000000Z'
                  current_page: 1
                  first_page_url: '{{protocol}}://{{domain}}/api/walmart/1/wfs/inbound-shipments/1000012345/allocations?page=1'
                  from: 1
                  last_page: 1
                  last_page_url: '{{protocol}}://{{domain}}/api/walmart/1/wfs/inbound-shipments/1000012345/allocations?page=1'
                  links: []
                  next_page_url: null
                  path: '{{protocol}}://{{domain}}/api/walmart/1/wfs/inbound-shipments/1000012345/allocations'
                  per_page: 10
                  prev_page_url: null
                  to: 1
                  total: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-walmart-integrationinstance-wfs-inbound-shipments-shipment-allocations
  /api/walmart/{integrationInstance}/wfs/inbound-shipments/{shipment}/reconciliation:
    get:
      tags:
      - Walmart
      summary: Get Reconciliation
      description: 'Sent-vs-received reconciliation for this inbound — per-SKU variance
        + status + the local investigated flag, plus a roll-up summary.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Response: { data: { summary, rows } }.


        summary keys:

        - total_skus (number): distinct SKUs on the shipment.

        - matched (number): SKUs where received === sent (only once receipt is complete).

        - pending_skus (number): SKUs still mid-receipt / not yet fully received.

        - short_skus (number): SKUs received short (receipt complete only).

        - over_skus (number): SKUs received over.

        - short_units (number): total missing units across short SKUs (absolute value).

        - over_units (number): total surplus units across over SKUs.

        - unresolved (number): discrepant (short/over) SKUs not yet marked resolved.

        - receipt_complete (boolean): whether Walmart has finished receiving (status
        Received or Closed).


        row keys: sku, description, product_id (number|null), sent, received, variance
        (received - sent), status (matched | over | short | pending), resolved (boolean
        — local investigated flag).


        Errors: 422 with { message } if reconciliation can''t be loaded.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      - name: shipment
        in: path
        schema:
          type: integer
        required: true
        description: WFS inbound shipment ID
        example: '1000012345'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      summary:
                        type: object
                        properties:
                          total_skus:
                            type: integer
                          matched:
                            type: integer
                          pending_skus:
                            type: integer
                          short_skus:
                            type: integer
                          over_skus:
                            type: integer
                          short_units:
                            type: integer
                          over_units:
                            type: integer
                          unresolved:
                            type: integer
                          receipt_complete:
                            type: boolean
                      rows:
                        type: array
                        items:
                          type: object
                          properties:
                            sku:
                              type: string
                            description:
                              type: string
                            product_id:
                              type: integer
                            sent:
                              type: integer
                            received:
                              type: integer
                            variance:
                              type: integer
                            status:
                              type: string
                            resolved:
                              type: boolean
                example:
                  data:
                    summary:
                      total_skus: 2
                      matched: 1
                      pending_skus: 0
                      short_skus: 1
                      over_skus: 0
                      short_units: 12
                      over_units: 0
                      unresolved: 1
                      receipt_complete: true
                    rows:
                    - sku: WIDGET-BLU-12OZ
                      description: Blue Widget 12oz
                      product_id: 4821
                      sent: 50
                      received: 38
                      variance: -12
                      status: short
                      resolved: false
                    - sku: WIDGET-RED-12OZ
                      description: Red Widget 12oz
                      product_id: 4822
                      sent: 25
                      received: 25
                      variance: 0
                      status: matched
                      resolved: false
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-walmart-integrationinstance-wfs-inbound-shipments-shipment-reconciliation
  /api/walmart/{integrationInstance}/wfs/inbound-shipments/{shipment}/reconciliation/resolve:
    post:
      tags:
      - Walmart
      summary: Resolve Discrepancy
      description: 'Mark a SKU''s receive discrepancy on this shipment as investigated/resolved
        (or reopen it).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Fields:

        - sku (string, required): the SKU whose discrepancy to flag.

        - resolved (boolean, required): true to mark resolved, false to reopen.


        Response: { message } — ''Discrepancy resolved'' when resolved is true, ''Discrepancy
        reopened'' when false.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                sku:
                  type: string
                resolved:
                  type: boolean
              example:
                sku: WIDGET-BLU-12OZ
                resolved: true
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      - name: shipment
        in: path
        schema:
          type: integer
        required: true
        description: WFS inbound shipment ID
        example: '1000012345'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Discrepancy resolved
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-walmart-integrationinstance-wfs-inbound-shipments-shipment-reconciliation-resolve
  /api/walmart/{integrationInstance}/wfs/inbound-shipments/{shipment}/errors:
    get:
      tags:
      - Walmart
      summary: Get WFS Inbound Shipment Errors
      description: 'The errors Walmart recorded against an inbound shipment (why an
        item or order was rejected), pulled live from Walmart. Scoped to the integration
        instance (404 if the shipment belongs to another instance). A Walmart-side
        failure returns a 422. Requires a Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      - name: shipment
        in: path
        schema:
          type: integer
        required: true
        description: Local WFS inbound shipment ID
        example: '7'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        sku:
                          type: string
                        error_code:
                          type: string
                        description:
                          type: string
                example:
                  data:
                  - sku: ABC-009
                    error_code: GTIN_MISSING
                    description: Item is missing a GTIN/UPC required by WFS.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 'Failed to load shipment errors: Walmart returned an error
                    for inbound order WMTIO-99201.'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-walmart-integrationinstance-wfs-inbound-shipments-shipment-errors
  /api/walmart/{integrationInstance}/wfs/inbound-shipments/{shipment}/activity-log:
    get:
      tags:
      - Walmart
      summary: Get Activity Log
      description: 'Paginated activity log for this inbound shipment (newest first).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Filters:

        - filter[event]: activity event — created | updated | deleted | bulk_upsert.

        - filter[source]: properties->source (manual | amazon_sync | inventory_allocation
        | ...).

        - filter[batch_uuid]: filter by batch uuid.

        - filter[search]: matches causer name, properties, or event.


        Pagination: page, per_page (default 15).


        Each row: id, description, event, subject_type (class basename), subject_id,
        properties (object), causer_name (string|null), created_at.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      - name: shipment
        in: path
        schema:
          type: integer
        required: true
        description: WFS inbound shipment ID
        example: '1000012345'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        description:
                          type: string
                        event:
                          type: string
                        subject_type:
                          type: string
                        subject_id:
                          type: integer
                        properties:
                          type: object
                          properties:
                            source:
                              type: string
                            attributes:
                              type: object
                              properties:
                                source_warehouse_id:
                                  type: integer
                        causer_name:
                          type: string
                        created_at:
                          type: string
                  current_page:
                    type: integer
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 55231
                    description: WFS inbound source set to Main Distribution Center
                    event: updated
                    subject_type: WalmartWfsInboundShipment
                    subject_id: 3312
                    properties:
                      source: manual
                      attributes:
                        source_warehouse_id: 7
                    causer_name: Jane Operator
                    created_at: '2026-06-28T14:05:11.000000Z'
                  current_page: 1
                  first_page_url: '{{protocol}}://{{domain}}/api/walmart/1/wfs/inbound-shipments/1000012345/activity-log?page=1'
                  from: 1
                  last_page: 1
                  last_page_url: '{{protocol}}://{{domain}}/api/walmart/1/wfs/inbound-shipments/1000012345/activity-log?page=1'
                  links: []
                  next_page_url: null
                  path: '{{protocol}}://{{domain}}/api/walmart/1/wfs/inbound-shipments/1000012345/activity-log'
                  per_page: 15
                  prev_page_url: null
                  to: 1
                  total: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-walmart-integrationinstance-wfs-inbound-shipments-shipment-activity-log
  /api/walmart/{integrationInstance}/wfs/inbound-shipments/{shipment}/placement-preview:
    get:
      tags:
      - Walmart
      summary: Get Placement Preview
      description: 'Estimate the destination-FC placement + transfer charges for an
        existing shipment by re-running Walmart''s inbound preview from its current
        items + source. This is an estimate — Walmart exposes no billed charges per
        existing order; actual charges live in Walmart Seller Center.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Response: { data: { total_charge (number), currency (string), placements:
        [ ... ] } }.


        Each placement: fc_name (string|null), ship_node (string|null), node_type
        (string|null), charge (number), currency (string), items: [ { sku (string|null),
        quantity (number), charge (number) } ].


        Errors: 422 with { message } — e.g. when Walmart hasn''t reported items for
        the shipment yet, or the preview call fails.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      - name: shipment
        in: path
        schema:
          type: integer
        required: true
        description: WFS inbound shipment ID
        example: '1000012345'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      total_charge:
                        type: number
                      currency:
                        type: string
                      placements:
                        type: array
                        items:
                          type: object
                          properties:
                            fc_name:
                              type: string
                            ship_node:
                              type: string
                            node_type:
                              type: string
                            charge:
                              type: number
                            currency:
                              type: string
                            items:
                              type: array
                              items:
                                type: object
                                properties:
                                  sku:
                                    type: string
                                  quantity:
                                    type: integer
                                  charge:
                                    type: number
                example:
                  data:
                    total_charge: 42.75
                    currency: USD
                    placements:
                    - fc_name: Bethlehem, PA (WFS)
                      ship_node: '10000045'
                      node_type: WFS
                      charge: 42.75
                      currency: USD
                      items:
                      - sku: WIDGET-BLU-12OZ
                        quantity: 50
                        charge: 28.5
                      - sku: WIDGET-RED-12OZ
                        quantity: 25
                        charge: 14.25
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-walmart-integrationinstance-wfs-inbound-shipments-shipment-placement-preview
  /api/walmart/{integrationInstance}/wfs/inbound-shipments/3pl-metrics:
    get:
      tags:
      - Walmart
      summary: Get 3PL Turnaround Metrics
      description: '3PL/supplier turnaround SLA metrics: per-partner turnaround gaps
        between sending a WFS-inbound fulfilment request and each milestone (sent
        → box contents submitted, sent → ready to ship), plus an overall summary.
        Derived from packet timestamps + portal events across all of this integration
        instance''s WFS inbound shipments.


        Authentication: Requires Bearer token.


        Query parameters (both optional):

        - date_from (date, m/d/Y or Y-m-d): only include packets sent on/after this
        day (start of day).

        - date_to (date, m/d/Y or Y-m-d): only include packets sent on/before this
        day (end of day).


        Response: { data: { summary, partners[] } }. summary is the ''All partners''
        aggregate; partners[] is one row per 3PL warehouse / supplier, sorted by shipments_sent
        desc. partner_type is ''all'' (summary), ''3pl'', or ''supplier''. Median/avg
        hour fields are null when no packet has reached that milestone yet.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      summary:
                        type: object
                        properties:
                          partner_name:
                            type: string
                          partner_type:
                            type: string
                          shipments_sent:
                            type: integer
                          ready_count:
                            type: integer
                          overdue_count:
                            type: integer
                          median_hours_to_box_contents:
                            type: number
                          median_hours_to_ready:
                            type: number
                          avg_hours_to_ready:
                            type: number
                      partners:
                        type: array
                        items:
                          type: object
                          properties:
                            partner_name:
                              type: string
                            partner_type:
                              type: string
                            shipments_sent:
                              type: integer
                            ready_count:
                              type: integer
                            overdue_count:
                              type: integer
                            median_hours_to_box_contents:
                              type: integer
                            median_hours_to_ready:
                              type: integer
                            avg_hours_to_ready:
                              type: number
                example:
                  data:
                    summary:
                      partner_name: All partners
                      partner_type: all
                      shipments_sent: 12
                      ready_count: 9
                      overdue_count: 1
                      median_hours_to_box_contents: 6.5
                      median_hours_to_ready: 20.5
                      avg_hours_to_ready: 22.3
                    partners:
                    - partner_name: Acme 3PL Warehouse
                      partner_type: 3pl
                      shipments_sent: 7
                      ready_count: 6
                      overdue_count: 0
                      median_hours_to_box_contents: 5
                      median_hours_to_ready: 18
                      avg_hours_to_ready: 19.2
                    - partner_name: Widget Supply Co
                      partner_type: supplier
                      shipments_sent: 5
                      ready_count: 3
                      overdue_count: 1
                      median_hours_to_box_contents: 8
                      median_hours_to_ready: 26
                      avg_hours_to_ready: 27.5
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-walmart-integrationinstance-wfs-inbound-shipments-3pl-metrics
  /api/walmart/wfs/warehouses/{warehouse}/3pl-metrics:
    get:
      tags:
      - Walmart
      summary: Get Warehouse WFS Turnaround Metrics
      description: '3PL/supplier turnaround SLA metrics scoped to a single source
        warehouse (3PL partner): per-partner turnaround gaps between sending a WFS-inbound
        fulfilment request and each milestone (sent -> box contents submitted, sent
        -> ready to ship), plus an overall summary. Unlike the instance-scoped metrics
        endpoint, this spans every Walmart integration instance -- a warehouse''s
        turnaround is instance-agnostic.


        Authentication: Requires Bearer token.


        Path parameter:

        - warehouse (integer): the source warehouse ID to scope to.


        Query parameters (both optional):

        - date_from (date, m/d/Y or Y-m-d): only include packets sent on/after this
        day (start of day).

        - date_to (date, m/d/Y or Y-m-d): only include packets sent on/before this
        day (end of day).


        Response: { data: { summary, partners[] } }. summary is the ''All partners''
        aggregate; partners[] is one row per 3PL warehouse / supplier, sorted by shipments_sent
        desc. partner_type is ''all'' (summary), ''3pl'', or ''supplier''. Median/avg
        hour fields are null when no packet has reached that milestone yet.'
      parameters:
      - name: warehouse
        in: path
        schema:
          type: integer
        required: true
        description: Source warehouse (3PL) ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      summary:
                        type: object
                        properties:
                          partner_name:
                            type: string
                          partner_type:
                            type: string
                          shipments_sent:
                            type: integer
                          ready_count:
                            type: integer
                          overdue_count:
                            type: integer
                          median_hours_to_box_contents:
                            type: integer
                          median_hours_to_ready:
                            type: integer
                          avg_hours_to_ready:
                            type: number
                      partners:
                        type: array
                        items:
                          type: object
                          properties:
                            partner_name:
                              type: string
                            partner_type:
                              type: string
                            shipments_sent:
                              type: integer
                            ready_count:
                              type: integer
                            overdue_count:
                              type: integer
                            median_hours_to_box_contents:
                              type: integer
                            median_hours_to_ready:
                              type: integer
                            avg_hours_to_ready:
                              type: number
                example:
                  data:
                    summary:
                      partner_name: All partners
                      partner_type: all
                      shipments_sent: 7
                      ready_count: 6
                      overdue_count: 0
                      median_hours_to_box_contents: 5
                      median_hours_to_ready: 18
                      avg_hours_to_ready: 19.2
                    partners:
                    - partner_name: Acme 3PL Warehouse
                      partner_type: 3pl
                      shipments_sent: 7
                      ready_count: 6
                      overdue_count: 0
                      median_hours_to_box_contents: 5
                      median_hours_to_ready: 18
                      avg_hours_to_ready: 19.2
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-walmart-wfs-warehouses-warehouse-3pl-metrics
  /api/walmart/wfs/suppliers/{supplier}/3pl-metrics:
    get:
      tags:
      - Walmart
      summary: Get Supplier WFS Turnaround Metrics
      description: '3PL/supplier turnaround SLA metrics scoped to a single source
        supplier: per-partner turnaround gaps between sending a WFS-inbound fulfilment
        request and each milestone (sent -> box contents submitted, sent -> ready
        to ship), plus an overall summary. Spans every Walmart integration instance
        -- a supplier''s turnaround is instance-agnostic.


        Authentication: Requires Bearer token.


        Path parameter:

        - supplier (integer): the source supplier ID to scope to.


        Query parameters (both optional):

        - date_from (date, m/d/Y or Y-m-d): only include packets sent on/after this
        day (start of day).

        - date_to (date, m/d/Y or Y-m-d): only include packets sent on/before this
        day (end of day).


        Response: { data: { summary, partners[] } }. summary is the ''All partners''
        aggregate; partners[] is one row per 3PL warehouse / supplier, sorted by shipments_sent
        desc. partner_type is ''all'' (summary), ''3pl'', or ''supplier''. Median/avg
        hour fields are null when no packet has reached that milestone yet.'
      parameters:
      - name: supplier
        in: path
        schema:
          type: integer
        required: true
        description: Source supplier ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      summary:
                        type: object
                        properties:
                          partner_name:
                            type: string
                          partner_type:
                            type: string
                          shipments_sent:
                            type: integer
                          ready_count:
                            type: integer
                          overdue_count:
                            type: integer
                          median_hours_to_box_contents:
                            type: integer
                          median_hours_to_ready:
                            type: integer
                          avg_hours_to_ready:
                            type: number
                      partners:
                        type: array
                        items:
                          type: object
                          properties:
                            partner_name:
                              type: string
                            partner_type:
                              type: string
                            shipments_sent:
                              type: integer
                            ready_count:
                              type: integer
                            overdue_count:
                              type: integer
                            median_hours_to_box_contents:
                              type: integer
                            median_hours_to_ready:
                              type: integer
                            avg_hours_to_ready:
                              type: number
                example:
                  data:
                    summary:
                      partner_name: All partners
                      partner_type: all
                      shipments_sent: 5
                      ready_count: 3
                      overdue_count: 1
                      median_hours_to_box_contents: 8
                      median_hours_to_ready: 26
                      avg_hours_to_ready: 27.5
                    partners:
                    - partner_name: Widget Supply Co
                      partner_type: supplier
                      shipments_sent: 5
                      ready_count: 3
                      overdue_count: 1
                      median_hours_to_box_contents: 8
                      median_hours_to_ready: 26
                      avg_hours_to_ready: 27.5
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-walmart-wfs-suppliers-supplier-3pl-metrics
  /api/walmart/{integrationInstance}/wfs/inbound-shipments/{shipment}/suggested-package:
    get:
      tags:
      - Walmart
      summary: Get WFS Inbound Suggested Package
      description: 'Best-guess a single shipping package (weight + dimensions) for
        an inbound shipment, derived from the shipment items'' product records. Used
        to pre-fill the carrier-rate-quote form so the dimensions don''t have to be
        typed by hand.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Weight is summed across all items (converted to LB); the box is approximated
        as a cube of the combined item volume (converted to IN). Items whose product
        has no dimensions are skipped. Values are returned in Walmart units (LB /
        IN).


        Scoped to the integration instance (404 if the shipment belongs to another
        instance). A Walmart-side or estimation failure returns 422. Requires a Bearer
        token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      - name: shipment
        in: path
        schema:
          type: integer
        required: true
        description: Local WFS inbound shipment ID
        example: '7'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      weight:
                        type: integer
                      length:
                        type: number
                      width:
                        type: number
                      height:
                        type: number
                example:
                  data:
                    weight: 28
                    length: 16.49
                    width: 16.49
                    height: 16.49
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 'Failed to estimate package: <reason>'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-walmart-integrationinstance-wfs-inbound-shipments-shipment-suggested-package
  /api/walmart/{integrationInstance}/wfs/inbound-shipments/{shipment}/carrier-rate-quotes:
    post:
      tags:
      - Walmart
      summary: Get Carrier Rate Quotes
      description: 'Request WFS Preferred-Carrier rate quotes for a shipment. Walmart''s
        payload is built from the shipment''s source warehouse (origin/return address)
        + assigned FC (destination) + the supplied package dimensions. The inbound
        must have a resolved SOURCE WAREHOUSE (supplier-sourced or unresolved inbounds
        are rejected). Returns a normalized quote list.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Fields:

        - packages (array, required, min 1): one entry per distinct package.

        - packages[].weight (numeric, required, min 0): package weight in LB.

        - packages[].length (numeric, required, min 0): length in IN.

        - packages[].width (numeric, required, min 0): width in IN.

        - packages[].height (numeric, required, min 0): height in IN.

        - packages[].count (integer, optional, min 1): number of identical packages
        (default 1).

        - pickup_date (date, optional, nullable): requested carrier pickup date.


        Each normalized quote: quote_id, carrier, net_charge, currency, transit_days,
        estimated_delivery, status, mode.


        Response: { "data": [ quotes ] }.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                packages:
                  type: array
                  items:
                    type: object
                    properties:
                      weight:
                        type: number
                      length:
                        type: integer
                      width:
                        type: integer
                      height:
                        type: integer
                      count:
                        type: integer
                pickup_date:
                  type: string
              example:
                packages:
                - weight: 12.5
                  length: 14
                  width: 14
                  height: 14
                  count: 1
                pickup_date: '2026-07-08'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      - name: shipment
        in: path
        schema:
          type: integer
        required: true
        description: WFS inbound shipment ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        quote_id:
                          type: string
                        carrier:
                          type: string
                        net_charge:
                          type: number
                        currency:
                          type: string
                        transit_days:
                          type: integer
                        estimated_delivery:
                          type: string
                        status:
                          type: string
                        mode:
                          type: string
                example:
                  data:
                  - quote_id: QT-8842019
                    carrier: FedEx
                    net_charge: 42.75
                    currency: USD
                    transit_days: 3
                    estimated_delivery: '2026-07-12T00:00:00Z'
                    status: ACTIVE
                    mode: PARCEL
                  - quote_id: QT-8842020
                    carrier: UPS
                    net_charge: 47.1
                    currency: USD
                    transit_days: 2
                    estimated_delivery: '2026-07-11T00:00:00Z'
                    status: ACTIVE
                    mode: PARCEL
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-walmart-integrationinstance-wfs-inbound-shipments-shipment-carrier-rate-quotes
  /api/walmart/{integrationInstance}/wfs/inbound-shipments/{shipment}/carrier-rate-quote/confirm:
    post:
      tags:
      - Walmart
      summary: Confirm WFS Inbound Carrier Rate Quote
      description: 'Confirm (book) the previously requested WFS Preferred-Carrier
        rate quote for an inbound shipment. No request body. Scoped to the integration
        instance (404 if the shipment belongs to another instance). A Walmart-side
        failure returns a 422. Requires a Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      - name: shipment
        in: path
        schema:
          type: integer
        required: true
        description: Local WFS inbound shipment ID
        example: '7'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Carrier rate quote confirmed
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 'Failed to confirm carrier rate quote: No active rate quote
                    to confirm for this shipment.'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-walmart-integrationinstance-wfs-inbound-shipments-shipment-carrier-rate-quote-confirm
  /api/walmart/{integrationInstance}/wfs/inbound-shipments/{shipment}/carrier-rate-quote:
    get:
      tags:
      - Walmart
      summary: Get Existing WFS Inbound Carrier Rate Quote
      description: 'Fetch the carrier rate quote that already exists on Walmart for
        this inbound shipment. The detail page calls this on mount so a previously
        generated quote is shown (with Confirm / Void / Print) instead of a blank
        panel — Walmart''s create endpoint is one-shot per shipment, so re-creating
        would 400. No request body. Scoped to the integration instance (404 if the
        shipment belongs to another instance). When no quote exists yet (the normal
        starting state — Walmart returns 404), this endpoint stays silent and returns
        an empty `data` list with a 200. Requires a Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      - name: shipment
        in: path
        schema:
          type: integer
        required: true
        description: Local WFS inbound shipment ID
        example: '7'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 OK (existing quote)
                  value:
                    data:
                    - quote_id: RQ-88213
                      carrier: WFS-FEDEX
                      net_charge: 42.75
                      currency: USD
                      transit_days: '3'
                      estimated_delivery: '2026-07-01T00:00:00Z'
                      status: ACTIVE
                      mode: PARCEL
                example-1:
                  summary: 200 OK (no quote yet)
                  value:
                    data: []
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-walmart-integrationinstance-wfs-inbound-shipments-shipment-carrier-rate-quote
    delete:
      tags:
      - Walmart
      summary: Void WFS Inbound Carrier Rate Quote
      description: 'Void the carrier rate quote / booking for an inbound shipment.
        No request body. Scoped to the integration instance (404 if the shipment belongs
        to another instance). A Walmart-side failure returns a 422. Requires a Bearer
        token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      - name: shipment
        in: path
        schema:
          type: integer
        required: true
        description: Local WFS inbound shipment ID
        example: '7'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Carrier rate quote voided
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 'Failed to void carrier rate quote: No active rate quote
                    to void for this shipment.'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-walmart-integrationinstance-wfs-inbound-shipments-shipment-carrier-rate-quote
  /api/walmart/{integrationInstance}/wfs/inbound-shipments/{shipment}/carrier-label:
    post:
      tags:
      - Walmart
      summary: Print WFS Inbound Carrier Label
      description: 'Print the carrier label for a booked WFS inbound shipment. The
        response is the raw label document itself — binary PDF bytes streamed as a
        file download (Content-Type: application/pdf, Content-Disposition: attachment),
        NOT a JSON envelope. Scoped to the integration instance (404 if the shipment
        belongs to another instance).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Request body:

        - ship_date (optional, nullable, date) — the ship date to stamp on the label;
        defaults to today (UTC) when omitted.


        Responses:

        - 200: the PDF label bytes (binary download).

        - 404: the shipment does not belong to the given integration instance.

        - 422: ship_date is not a valid date.


        Requires a Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ship_date:
                  type: string
              example:
                ship_date: '2026-06-28'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      - name: shipment
        in: path
        schema:
          type: integer
        required: true
        description: Local WFS inbound shipment ID
        example: '7'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/pdf
            Content-Disposition:
              schema:
                type: string
                example: attachment; filename="wfs-carrier-100000123456789.pdf"
          content:
            text/plain:
              schema:
                type: string
                example: '%PDF-1.4 ...binary label bytes... %%EOF'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      ship_date:
                        type: array
                        items:
                          type: string
                example:
                  message: The ship date field must be a valid date.
                  errors:
                    ship_date:
                    - The ship date field must be a valid date.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-walmart-integrationinstance-wfs-inbound-shipments-shipment-carrier-label
  /api/walmart/{integrationInstance}/wfs/inbound-shipments/{shipment}/tracking:
    post:
      tags:
      - Walmart
      summary: Submit WFS Inbound Shipment Tracking
      description: 'Submit the carrier and tracking numbers for an inbound shipment
        to Walmart and persist them locally. Scoped to the integration instance (404
        if the shipment belongs to another instance).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Request body:

        - carrier_name (required, string, max 255).

        - tracking_numbers (required, array, min 1) — each a required string (max
        255).


        Validation errors return 422; a Walmart-side failure also returns 422 with
        the reason. Requires a Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                carrier_name:
                  type: string
                tracking_numbers:
                  type: array
                  items:
                    type: string
              example:
                carrier_name: FEDEX
                tracking_numbers:
                - '787439195645'
                - '787439195646'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      - name: shipment
        in: path
        schema:
          type: integer
        required: true
        description: Local WFS inbound shipment ID
        example: '7'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Tracking submitted to Walmart
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 'Failed to submit tracking: Walmart rejected the tracking
                    update for this shipment.'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-walmart-integrationinstance-wfs-inbound-shipments-shipment-tracking
  /api/walmart/{integrationInstance}/wfs/inbound-shipments/{shipment}/quantities:
    put:
      tags:
      - Walmart
      summary: Update WFS Inbound Shipment Quantities
      description: 'Update the per-SKU quantities on a not-yet-received inbound shipment.
        Scoped to the integration instance (404 if the shipment belongs to another
        instance).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Request body:

        - items (required, array, min 1) — each: { sku (required string, max 255),
        quantity (required integer >= 0; 0 removes the line) }.


        Validation errors return 422; a Walmart-side failure also returns 422 with
        the reason. Requires a Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                items:
                  type: array
                  items:
                    type: object
                    properties:
                      sku:
                        type: string
                      quantity:
                        type: integer
              example:
                items:
                - sku: ABC-001
                  quantity: 15
                - sku: ABC-002
                  quantity: 0
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      - name: shipment
        in: path
        schema:
          type: integer
        required: true
        description: Local WFS inbound shipment ID
        example: '7'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Shipment quantities updated
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 'Failed to update quantities: This shipment is already
                    receiving and can no longer be edited.'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: put-api-walmart-integrationinstance-wfs-inbound-shipments-shipment-quantities
  /api/walmart/{integrationInstance}/wfs/inbound-shipments/{shipment}/label:
    get:
      tags:
      - Walmart
      summary: Get Inbound Shipment Label
      description: 'Download the Walmart inbound receiving label (PDF) for a shipment.
        The response is streamed as raw PDF bytes (Content-Type: application/pdf,
        Content-Disposition: attachment), NOT JSON.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Response: binary PDF (application/pdf) as a file attachment named wfs-inbound-&lt;shipment_id>.pdf.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      - name: shipment
        in: path
        schema:
          type: integer
        required: true
        description: WFS inbound shipment ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/pdf
            Content-Disposition:
              schema:
                type: string
                example: attachment; filename="wfs-inbound-9821736450.pdf"
          content:
            text/plain:
              schema:
                type: string
                example: '%PDF-1.4 [binary PDF bytes — inbound receiving label; not
                  JSON]'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-walmart-integrationinstance-wfs-inbound-shipments-shipment-label
  /api/walmart/{integrationInstance}/wfs/inbound-products:
    get:
      tags:
      - Walmart
      summary: Search Inbound Products
      description: 'Search seller-fulfilled (non-WFS) Walmart listings eligible to
        send into Walmart Fulfillment Services for the inbound builder''s search/add-items
        step. Only listings with a GTIN/UPC (Walmart rejects items without one) and
        a matching, non-archived SKU.io product are returned; SKUs already in WFS
        are excluded. Results are capped at 50, ordered by product name.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Query params:

        - query (string, optional): search text over Walmart SKU / Walmart product
        name / SKU.io product name.

        - source_warehouse_id (integer, optional): annotate each row with available
        stock at this warehouse (source_quantity). When omitted, source_quantity is
        null.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        product_id:
                          type: integer
                        sku:
                          type: string
                        name:
                          type: string
                        gtin:
                          type: string
                        image:
                          type: string
                        source_quantity:
                          type: integer
                example:
                  data:
                  - product_id: 3391
                    sku: WIDGET-BLUE
                    name: Blue Widget 12oz
                    gtin: 00810000123456
                    image: https://cdn.sku.io/products/widget-blue.jpg
                    source_quantity: 320
                  - product_id: 3392
                    sku: WIDGET-RED
                    name: Red Widget 12oz
                    gtin: 00810000123463
                    image: null
                    source_quantity: 88
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-walmart-integrationinstance-wfs-inbound-products
  /api/walmart/{integrationInstance}/wfs/inbound-products/resolve:
    post:
      tags:
      - Walmart
      summary: Resolve Inbound Identifiers (Bulk)
      description: 'Resolve a list of bulk-import identifiers (SKU / UPC / GTIN) to
        WFS-eligible products for the inbound builder''s Bulk Add modal. Mirrors FBA
        bulk-add resolve: each identifier is classified as matched (exactly one product),
        multiple (several — the user picks), or not_found. Eligibility is identical
        to Search Inbound Products (non-WFS, GTIN/UPC-bearing, matching non-archived
        product, excluding already-WFS SKUs).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Fields:

        - identifiers (string[], required, 1–500 items): raw identifier strings to
        resolve; each max 255 chars.

        - identifier_type (string, optional, one of auto|sku|upc|gtin; default auto):
        how to interpret each identifier. auto matches against SKU, UPC, or GTIN.

        - source_warehouse_id (integer, optional, nullable): when set, resolved products
        carry source_quantity for that warehouse (null otherwise).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                identifiers:
                  type: array
                  items:
                    type: string
                identifier_type:
                  type: string
                source_warehouse_id:
                  type: integer
              example:
                identifiers:
                - WIDGET-BLUE
                - 00810000123463
                - NOPE-999
                identifier_type: auto
                source_warehouse_id: 5
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      matched:
                        type: array
                        items:
                          type: object
                          properties:
                            identifier:
                              type: string
                            product:
                              type: object
                              properties:
                                product_id:
                                  type: integer
                                sku:
                                  type: string
                                name:
                                  type: string
                                gtin:
                                  type: string
                                image:
                                  type: string
                                source_quantity:
                                  type: integer
                      multiple:
                        type: array
                      not_found:
                        type: array
                        items:
                          type: string
                example:
                  data:
                    matched:
                    - identifier: WIDGET-BLUE
                      product:
                        product_id: 3391
                        sku: WIDGET-BLUE
                        name: Blue Widget 12oz
                        gtin: 00810000123456
                        image: https://cdn.sku.io/products/widget-blue.jpg
                        source_quantity: 320
                    - identifier: 00810000123463
                      product:
                        product_id: 3392
                        sku: WIDGET-RED
                        name: Red Widget 12oz
                        gtin: 00810000123463
                        image: null
                        source_quantity: 88
                    multiple: []
                    not_found:
                    - NOPE-999
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-walmart-integrationinstance-wfs-inbound-products-resolve
  /api/walmart/{integrationInstance}/wfs/source-warehouses:
    get:
      tags:
      - Walmart
      summary: List Source Warehouses
      description: 'List the warehouses eligible as a WFS inbound source for the Source
        step of the inbound builder — the seller''s own Direct + 3PL warehouses (non-archived),
        each with its type and a formatted address. Integration-destination warehouses
        (Amazon FBA/AWD, the WFS warehouse itself, virtual) are excluded. Ordered
        by name.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        type:
                          type: string
                        address:
                          type: string
                example:
                  data:
                  - id: 5
                    name: Main Warehouse
                    type: direct
                    address: 123 Commerce Way, Austin, TX
                  - id: 9
                    name: West Coast 3PL
                    type: 3pl
                    address: 88 Logistics Blvd, Ontario, CA
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-walmart-integrationinstance-wfs-source-warehouses
  /api/walmart/{integrationInstance}/wfs/inbound-shipments/{shipment}/fulfillment:
    get:
      tags:
      - Walmart
      summary: Get Fulfillment Packet
      description: 'Get the operator-side view of a shipment''s 3PL/supplier fulfilment
        packet. Returns whether a packet even applies to this shipment''s source (availability),
        the built packet if one exists (else null), the public portal URL, the auto-generated
        default prep instructions (used to pre-fill the editable field), the kitting-instruction
        snippet, and whether the shipment has any component-sourced kits (drives the
        ''Kits will be assembled'' toggle).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Response keys:

        - availability { available, source_type (3pl|supplier|null), reason }: a packet
        only applies to 3PL- or supplier-sourced inbounds; reason explains an unavailable
        case.

        - packet: the WalmartWfsInboundFulfillmentPacket resource (with documents[]),
        or null if not yet built.

        - portal_url: public token-gated portal link (null if no packet).

        - default_instructions: auto-generated prep instructions text.

        - kitting_instruction: the fixed kitting note appended when kits will be assembled.

        - has_component_kits: whether a kitting work order is applicable.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      - name: shipment
        in: path
        schema:
          type: integer
        required: true
        description: WFS inbound shipment ID (local WalmartWfsInboundShipment id)
        example: '843'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      availability:
                        type: object
                        properties:
                          available:
                            type: boolean
                          source_type:
                            type: string
                          reason:
                            type: string
                            nullable: true
                      packet:
                        type: object
                        properties:
                          id:
                            type: integer
                          walmart_wfs_inbound_shipment_id:
                            type: integer
                          source_type:
                            type: string
                          source_type_label:
                            type: string
                          channels:
                            type: array
                            items:
                              type: string
                          status:
                            type: string
                          status_label:
                            type: string
                          build_required:
                            type: boolean
                          instruction_override:
                            type: string
                            nullable: true
                          portal_token:
                            type: string
                          portal_accessible:
                            type: boolean
                          portal_token_expires_at:
                            type: string
                          sent_at:
                            type: string
                            nullable: true
                          acknowledged_at:
                            type: string
                            nullable: true
                          recipient_email:
                            type: string
                          recipient_name:
                            type: string
                          email_from:
                            type: object
                            properties:
                              address:
                                type: string
                              name:
                                type: string
                          email_reply_to:
                            type: object
                            properties:
                              address:
                                type: string
                              name:
                                type: string
                          email_from_default_mode:
                            type: string
                          email_from_options:
                            type: object
                            properties:
                              merchant:
                                type: object
                                properties:
                                  address:
                                    type: string
                                  name:
                                    type: string
                              system:
                                type: object
                                properties:
                                  address:
                                    type: string
                                  name:
                                    type: string
                          email_from_dns_setup:
                            type: object
                            properties:
                              domain:
                                type: string
                              provider:
                                type: string
                              steps:
                                type: array
                                items:
                                  type: object
                                  properties:
                                    title:
                                      type: string
                                    detail:
                                      type: string
                                    record:
                                      type: object
                                      properties:
                                        type:
                                          type: string
                                        host:
                                          type: string
                                        value:
                                          type: string
                          email_template:
                            type: object
                            properties:
                              subject:
                                type: string
                              body:
                                type: string
                              is_custom:
                                type: boolean
                          email_will_attach_prep_sheet:
                            type: boolean
                          email_will_attach_receiving_label:
                            type: boolean
                          email_will_attach_carrier_label:
                            type: boolean
                          documents:
                            type: array
                            items:
                              type: object
                              properties:
                                id:
                                  type: integer
                                type:
                                  type: string
                                type_label:
                                  type: string
                                stage:
                                  type: string
                                stage_label:
                                  type: string
                                status:
                                  type: string
                                status_label:
                                  type: string
                                downloadable:
                                  type: boolean
                          created_at:
                            type: string
                      portal_url:
                        type: string
                      default_instructions:
                        type: string
                      kitting_instruction:
                        type: string
                      has_component_kits:
                        type: boolean
                example:
                  data:
                    availability:
                      available: true
                      source_type: 3pl
                      reason: null
                    packet:
                      id: 12
                      walmart_wfs_inbound_shipment_id: 843
                      source_type: 3pl
                      source_type_label: 3PL Warehouse
                      channels:
                      - email
                      - portal
                      status: draft
                      status_label: Draft
                      build_required: false
                      instruction_override: null
                      portal_token: a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6
                      portal_accessible: true
                      portal_token_expires_at: '2026-08-05T14:30:00.000000Z'
                      sent_at: null
                      acknowledged_at: null
                      recipient_email: receiving@acme3pl.com
                      recipient_name: Acme 3PL Warehouse
                      email_from:
                        address: noreply@sku.io
                        name: Acme Store
                      email_reply_to:
                        address: ops@acme-store.com
                        name: Jane Operator
                      email_from_default_mode: system
                      email_from_options:
                        merchant:
                          address: orders@acme-store.com
                          name: Acme Store
                        system:
                          address: noreply@sku.io
                          name: Acme Store
                      email_from_dns_setup:
                        domain: acme-store.com
                        provider: Postmark
                        steps:
                        - title: Authorize Postmark in acme-store.com's SPF record
                          detail: 'Add include:spf.mtasv.net to the SPF TXT record
                            on acme-store.com. A domain must have exactly one SPF
                            record — merge it into the existing one instead of adding
                            a second. If acme-store.com has no SPF record yet, publish:'
                          record:
                            type: TXT
                            host: acme-store.com
                            value: v=spf1 include:spf.mtasv.net ~all
                        - title: Publish acme-store.com's DKIM records
                          detail: DKIM records are unique per domain and are generated
                            when acme-store.com is added to SKU.io's Postmark sending
                            account. Ask SKU.io support to add acme-store.com — you'll
                            receive three CNAME records (s1._domainkey.acme-store.com,
                            s2._domainkey.acme-store.com and a return-path host) to
                            publish, which also aligns the emails with your DMARC
                            policy.
                        - title: Verify before relying on it
                          detail: Send a test email and check it arrives in the inbox
                            (not spam) with SPF and DKIM shown as PASS in the message
                            headers. Until both pass, recipients with a strict DMARC
                            policy on acme-store.com may reject these emails.
                      email_template:
                        subject: Walmart WFS inbound — prep & receiving label needed
                          for {{reference}}
                        body: <p>Hi,</p><p>We&rsquo;re sending a Walmart Fulfillment
                          Services (WFS) inbound shipment (<strong>{{reference}}</strong>)
                          from your location and need you to prep and pack it per
                          the instructions below, then confirm when it&rsquo;s ready.</p><p><strong>Preferred
                          &mdash; use the secure portal.</strong> It shows the items
                          to prepare, the destination fulfillment center, downloadable
                          paperwork (including the WFS receiving label), and a button
                          to confirm the shipment is ready:</p><p>{{portal_link}}</p><p><strong>Prep
                          instructions:</strong></p><p>{{instructions}}</p><p>Please
                          affix the WFS receiving label to the outside of each carton
                          before the shipment goes out. Once you confirm it&rsquo;s
                          ready in the portal we&rsquo;ll finalize the inbound with
                          Walmart and send the carrier / pickup details.</p><p>Thank
                          you.</p>
                        is_custom: false
                      email_will_attach_prep_sheet: true
                      email_will_attach_receiving_label: true
                      email_will_attach_carrier_label: true
                      documents:
                      - id: 101
                        type: receiving_label
                        type_label: WFS Receiving Label
                        stage: initial
                        stage_label: Initial
                        status: ready
                        status_label: Ready
                        downloadable: true
                      - id: 103
                        type: carrier_label
                        type_label: WFS Carrier Label
                        stage: initial
                        stage_label: Initial
                        status: ready
                        status_label: Ready
                        downloadable: true
                      - id: 102
                        type: instructions
                        type_label: Prep Instructions
                        stage: initial
                        stage_label: Initial
                        status: ready
                        status_label: Ready
                        downloadable: true
                      - id: 104
                        type: asn
                        type_label: Advanced Shipment Notice
                        stage: initial
                        stage_label: Initial
                        status: ready
                        status_label: Ready
                        downloadable: false
                      created_at: '2026-07-06T14:30:00.000000Z'
                    portal_url: '{{protocol}}://{{domain}}/v2/integrations/walmart/wfs/inbound-shipments/fulfillment-portal/a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6?integration=1'
                    default_instructions: "WALMART WFS INBOUND — PREP INSTRUCTIONS\n\
                      Shipment: 970000123456 (Order 100000987654)\nDestination FC:\
                      \ 6099\n\nItems to prepare:\n  • 48 × WIDGET-BLUE — Blue Widget\
                      \ 12oz\n  • 24 × WIDGET-RED — Red Widget 12oz\n\nAffix the WFS\
                      \ Receiving Label (provided) to the outside of each carton."
                    kitting_instruction: 'KITTING: assemble the kit SKUs per the Kitting
                      Work Order, then confirm "Kits Built".'
                    has_component_kits: false
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-walmart-integrationinstance-wfs-inbound-shipments-shipment-fulfillment
    post:
      tags:
      - Walmart
      summary: Build/Update Fulfillment Packet
      description: 'Build (or refresh) the fulfilment packet for a 3PL/supplier-sourced
        inbound — resolves the source type, scaffolds the staged document set, and
        mints a portal token. Re-calling updates the existing packet (channels, build
        flag, instruction override) and re-scaffolds documents. Returns 422 if the
        shipment is direct-warehouse sourced (no packet applies) or its source is
        unresolved.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Fields:

        - channels (string[], optional, each one of email|portal): delivery channels.
        portal is always included even if omitted.

        - build_kits (boolean, optional, default false): when true AND the shipment
        has component-sourced kits, adds a Kitting Work Order and marks build_required.

        - instruction_override (string, optional, nullable, max 5000): replaces the
        auto-generated prep instructions.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                channels:
                  type: array
                  items:
                    type: string
                build_kits:
                  type: boolean
                instruction_override:
                  type: string
                  nullable: true
              example:
                channels:
                - email
                - portal
                build_kits: false
                instruction_override: null
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      - name: shipment
        in: path
        schema:
          type: integer
        required: true
        description: WFS inbound shipment ID (local WalmartWfsInboundShipment id)
        example: '843'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      walmart_wfs_inbound_shipment_id:
                        type: integer
                      source_type:
                        type: string
                      source_type_label:
                        type: string
                      channels:
                        type: array
                        items:
                          type: string
                      status:
                        type: string
                      status_label:
                        type: string
                      build_required:
                        type: boolean
                      instruction_override:
                        type: string
                        nullable: true
                      portal_token:
                        type: string
                      portal_accessible:
                        type: boolean
                      portal_token_expires_at:
                        type: string
                      sent_at:
                        type: string
                        nullable: true
                      acknowledged_at:
                        type: string
                        nullable: true
                      recipient_email:
                        type: string
                      recipient_name:
                        type: string
                      email_template:
                        type: object
                        properties:
                          subject:
                            type: string
                          body:
                            type: string
                      email_will_attach_prep_sheet:
                        type: boolean
                      email_will_attach_receiving_label:
                        type: boolean
                      email_will_attach_carrier_label:
                        type: boolean
                      documents:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            type:
                              type: string
                            type_label:
                              type: string
                            stage:
                              type: string
                            stage_label:
                              type: string
                            status:
                              type: string
                            status_label:
                              type: string
                            downloadable:
                              type: boolean
                      created_at:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 12
                    walmart_wfs_inbound_shipment_id: 843
                    source_type: 3pl
                    source_type_label: 3PL Warehouse
                    channels:
                    - email
                    - portal
                    status: draft
                    status_label: Draft
                    build_required: false
                    instruction_override: null
                    portal_token: a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6
                    portal_accessible: true
                    portal_token_expires_at: '2026-08-05T14:30:00.000000Z'
                    sent_at: null
                    acknowledged_at: null
                    recipient_email: receiving@acme3pl.com
                    recipient_name: Acme 3PL Warehouse
                    email_template:
                      subject: Walmart WFS inbound — prep & receiving label needed
                        for {{reference}}
                      body: <p>Hi,</p><p>We&rsquo;re sending a Walmart Fulfillment
                        Services (WFS) inbound shipment (<strong>{{reference}}</strong>)
                        from your location and need you to prep and pack it per the
                        instructions below, then confirm when it&rsquo;s ready.</p><p><strong>Preferred
                        &mdash; use the secure portal.</strong> It shows the items
                        to prepare, the destination fulfillment center, downloadable
                        paperwork (including the WFS receiving label), and a button
                        to confirm the shipment is ready:</p><p>{{portal_link}}</p><p><strong>Prep
                        instructions:</strong></p><p>{{instructions}}</p><p>Please
                        affix the WFS receiving label to the outside of each carton
                        before the shipment goes out. Once you confirm it&rsquo;s
                        ready in the portal we&rsquo;ll finalize the inbound with
                        Walmart and send the carrier / pickup details.</p><p>Thank
                        you.</p>
                    email_will_attach_prep_sheet: true
                    email_will_attach_receiving_label: true
                    email_will_attach_carrier_label: true
                    documents:
                    - id: 101
                      type: receiving_label
                      type_label: WFS Receiving Label
                      stage: initial
                      stage_label: Initial
                      status: ready
                      status_label: Ready
                      downloadable: true
                    - id: 103
                      type: carrier_label
                      type_label: WFS Carrier Label
                      stage: initial
                      stage_label: Initial
                      status: ready
                      status_label: Ready
                      downloadable: true
                    - id: 102
                      type: instructions
                      type_label: Prep Instructions
                      stage: initial
                      stage_label: Initial
                      status: ready
                      status_label: Ready
                      downloadable: true
                    - id: 104
                      type: asn
                      type_label: Advanced Shipment Notice
                      stage: initial
                      stage_label: Initial
                      status: ready
                      status_label: Ready
                      downloadable: false
                    created_at: '2026-07-06T14:30:00.000000Z'
                  message: Fulfilment packet built
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-walmart-integrationinstance-wfs-inbound-shipments-shipment-fulfillment
  /api/walmart/{integrationInstance}/wfs/inbound-shipments/{shipment}/fulfillment/rotate-token:
    post:
      tags:
      - Walmart
      summary: Rotate Portal Token
      description: 'Revoke the current portal token and issue a fresh one — the old
        public link stops working immediately. Returns 404 if no fulfilment packet
        has been built for this shipment.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Body: none (send an empty JSON object).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties: {}
              example: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      - name: shipment
        in: path
        schema:
          type: integer
        required: true
        description: WFS inbound shipment ID (local WalmartWfsInboundShipment id)
        example: '843'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      walmart_wfs_inbound_shipment_id:
                        type: integer
                      source_type:
                        type: string
                      source_type_label:
                        type: string
                      channels:
                        type: array
                        items:
                          type: string
                      status:
                        type: string
                      status_label:
                        type: string
                      build_required:
                        type: boolean
                      instruction_override:
                        type: string
                        nullable: true
                      portal_token:
                        type: string
                      portal_accessible:
                        type: boolean
                      portal_token_expires_at:
                        type: string
                      sent_at:
                        type: string
                        nullable: true
                      acknowledged_at:
                        type: string
                        nullable: true
                      recipient_email:
                        type: string
                      recipient_name:
                        type: string
                      email_template:
                        type: object
                        properties:
                          subject:
                            type: string
                          body:
                            type: string
                      documents:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            type:
                              type: string
                            type_label:
                              type: string
                            stage:
                              type: string
                            stage_label:
                              type: string
                            status:
                              type: string
                            status_label:
                              type: string
                            downloadable:
                              type: boolean
                      created_at:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 12
                    walmart_wfs_inbound_shipment_id: 843
                    source_type: 3pl
                    source_type_label: 3PL Warehouse
                    channels:
                    - email
                    - portal
                    status: draft
                    status_label: Draft
                    build_required: false
                    instruction_override: null
                    portal_token: f9e8d7c6b5a4f3e2d1c0b9a8f7e6d5c4
                    portal_accessible: true
                    portal_token_expires_at: '2026-08-05T15:10:00.000000Z'
                    sent_at: null
                    acknowledged_at: null
                    recipient_email: receiving@acme3pl.com
                    recipient_name: Acme 3PL Warehouse
                    email_template:
                      subject: Walmart WFS inbound — prep & receiving label needed
                        for {{reference}}
                      body: <p>Hi,</p><p>We&rsquo;re sending a Walmart Fulfillment
                        Services (WFS) inbound shipment (<strong>{{reference}}</strong>)
                        from your location and need you to prep and pack it per the
                        instructions below, then confirm when it&rsquo;s ready.</p><p><strong>Preferred
                        &mdash; use the secure portal.</strong> It shows the items
                        to prepare, the destination fulfillment center, downloadable
                        paperwork (including the WFS receiving label), and a button
                        to confirm the shipment is ready:</p><p>{{portal_link}}</p><p><strong>Prep
                        instructions:</strong></p><p>{{instructions}}</p><p>Please
                        affix the WFS receiving label to the outside of each carton
                        before the shipment goes out. Once you confirm it&rsquo;s
                        ready in the portal we&rsquo;ll finalize the inbound with
                        Walmart and send the carrier / pickup details.</p><p>Thank
                        you.</p>
                    documents:
                    - id: 101
                      type: receiving_label
                      type_label: WFS Receiving Label
                      stage: initial
                      stage_label: Initial
                      status: ready
                      status_label: Ready
                      downloadable: false
                    - id: 102
                      type: instructions
                      type_label: Prep Instructions
                      stage: initial
                      stage_label: Initial
                      status: ready
                      status_label: Ready
                      downloadable: true
                    - id: 104
                      type: asn
                      type_label: Advanced Shipment Notice
                      stage: initial
                      stage_label: Initial
                      status: ready
                      status_label: Ready
                      downloadable: false
                    created_at: '2026-07-06T14:30:00.000000Z'
                  message: Portal link rotated
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-walmart-integrationinstance-wfs-inbound-shipments-shipment-fulfillment-rotate-token
  /api/walmart/{integrationInstance}/wfs/inbound-shipments/{shipment}/fulfillment/email/preview:
    post:
      tags:
      - Walmart
      summary: Preview Fulfillment Email
      description: 'Render the operator''s edited subject/body with the live tokens
        substituted, without sending anything — powers the compose dialog''s preview
        pane. Tokens {{reference}} (the WFS shipment id), {{portal_link}} (a clickable
        anchor to the secure fulfilment portal), and {{instructions}} (the rendered
        prep instructions) are resolved server-side; the subject is treated as plain
        text, the body as HTML. Returns 422 if no fulfilment packet has been built
        for this shipment yet.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Fields:

        - subject (string, required, max 255): the final subject line (tokens substituted
        server-side).

        - body (string, required): the final HTML body (tokens substituted server-side).

        - cc (string[], optional, nullable, each a valid email): additional CC recipients
        (ignored by preview; used on send).

        - from_mode (string, optional, nullable, one of: merchant, system): sender-identity
        override. ''merchant'' sends From the store''s own domain (needs the SPF/DKIM
        setup in email_from_dns_setup); ''system'' sends via SKU.io with the operator
        as Reply-To. Null = the tenant''s default (email_from_default_mode).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                subject:
                  type: string
                body:
                  type: string
                cc:
                  type: array
                  items:
                    type: string
                from_mode:
                  type: string
              example:
                subject: Walmart WFS inbound — prep & receiving label needed for {{reference}}
                body: <p>Hi,</p><p>We&rsquo;re sending a Walmart Fulfillment Services
                  (WFS) inbound shipment (<strong>{{reference}}</strong>) from your
                  location and need you to prep and pack it per the instructions below,
                  then confirm when it&rsquo;s ready.</p><p><strong>Preferred &mdash;
                  use the secure portal.</strong> It shows the items to prepare, the
                  destination fulfillment center, downloadable paperwork (including
                  the WFS receiving label), and a button to confirm the shipment is
                  ready:</p><p>{{portal_link}}</p><p><strong>Prep instructions:</strong></p><p>{{instructions}}</p><p>Please
                  affix the WFS receiving label to the outside of each carton before
                  the shipment goes out. Once you confirm it&rsquo;s ready in the
                  portal we&rsquo;ll finalize the inbound with Walmart and send the
                  carrier / pickup details.</p><p>Thank you.</p>
                cc:
                - warehouse-manager@acme3pl.com
                from_mode: system
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      - name: shipment
        in: path
        schema:
          type: integer
        required: true
        description: WFS inbound shipment ID (local WalmartWfsInboundShipment id)
        example: '843'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      subject:
                        type: string
                      body:
                        type: string
                example:
                  data:
                    subject: Walmart WFS inbound — prep & receiving label needed for
                      970000123456
                    body: '<p>Hi,</p><p>We&rsquo;re sending a Walmart Fulfillment
                      Services (WFS) inbound shipment (<strong>970000123456</strong>)
                      from your location and need you to prep and pack it per the
                      instructions below, then confirm when it&rsquo;s ready.</p><p><strong>Preferred
                      &mdash; use the secure portal.</strong> It shows the items to
                      prepare, the destination fulfillment center, downloadable paperwork
                      (including the WFS receiving label), and a button to confirm
                      the shipment is ready:</p><p><a href="{{protocol}}://{{domain}}/v2/integrations/walmart/wfs/inbound-shipments/fulfillment-portal/a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6?integration=1">{{protocol}}://{{domain}}/v2/integrations/walmart/wfs/inbound-shipments/fulfillment-portal/a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6?integration=1</a></p><p><strong>Prep
                      instructions:</strong></p><p>WALMART WFS INBOUND &mdash; PREP
                      INSTRUCTIONS<br />

                      Shipment: 970000123456 (Order 100000987654)<br />

                      Destination FC: 6099<br />

                      <br />

                      Items to prepare:<br />

                      &nbsp;&nbsp;&bull; 48 &times; WIDGET-BLUE &mdash; Blue Widget
                      12oz<br />

                      &nbsp;&nbsp;&bull; 24 &times; WIDGET-RED &mdash; Red Widget
                      12oz<br />

                      <br />

                      Affix the WFS Receiving Label (provided) to the outside of each
                      carton.</p><p>Please affix the WFS receiving label to the outside
                      of each carton before the shipment goes out. Once you confirm
                      it&rsquo;s ready in the portal we&rsquo;ll finalize the inbound
                      with Walmart and send the carrier / pickup details.</p><p>Thank
                      you.</p>'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-walmart-integrationinstance-wfs-inbound-shipments-shipment-fulfillment-email-preview
  /api/walmart/{integrationInstance}/wfs/inbound-shipments/{shipment}/fulfillment/email:
    post:
      tags:
      - Walmart
      summary: Send Fulfillment Email
      description: 'Send the operator-composed portal invite to the resolved 3PL/supplier
        recipient (a 3PL warehouse''s address email, or the supplier''s PO email),
        substituting the {{reference}}/{{portal_link}}/{{instructions}} tokens server-side,
        then flip the packet status to Sent (sets sent_at). The recipient is resolved
        server-side — it is not accepted from the request. Returns 422 if no packet
        has been built, or if no recipient email is configured for the source (add
        one to the 3PL warehouse address / supplier before emailing).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Fields:

        - subject (string, required, max 255): the final subject line (tokens substituted
        server-side).

        - body (string, required): the final HTML body (tokens substituted server-side).

        - cc (string[], optional, nullable, each a valid email): additional CC recipients.

        - attach_prep_sheet (boolean, optional, default true): attach the prep & pack
        sheet CSV (unit mix, prep requirements, kitting) — included when the shipment
        has lines.

        - attach_receiving_label (boolean, optional, default false; the compose dialog
        pre-checks it whenever a receiving label is available): attach the WFS receiving
        label PDF, fetched live from Walmart at send time. Silently skipped if the
        shipment is a source placeholder or the live fetch fails.

        - attach_carrier_label (boolean, optional, default false; the compose dialog
        pre-checks it whenever a carrier is booked): attach the WFS carrier / pickup
        label PDF, fetched live from Walmart at send time. Silently skipped if no
        carrier is booked or the live fetch fails.

        - from_mode (string, optional, nullable, one of: merchant, system): sender-identity
        override. ''merchant'' sends From the store''s own domain (needs the SPF/DKIM
        setup in email_from_dns_setup); ''system'' sends via SKU.io with the operator
        as Reply-To. Null = the tenant''s default (email_from_default_mode).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                subject:
                  type: string
                body:
                  type: string
                cc:
                  type: array
                  items:
                    type: string
                attach_prep_sheet:
                  type: boolean
                attach_receiving_label:
                  type: boolean
                attach_carrier_label:
                  type: boolean
                from_mode:
                  type: string
              example:
                subject: Walmart WFS inbound — prep & receiving label needed for {{reference}}
                body: <p>Hi,</p><p>We&rsquo;re sending a Walmart Fulfillment Services
                  (WFS) inbound shipment (<strong>{{reference}}</strong>) from your
                  location and need you to prep and pack it per the instructions below,
                  then confirm when it&rsquo;s ready.</p><p><strong>Preferred &mdash;
                  use the secure portal.</strong> It shows the items to prepare, the
                  destination fulfillment center, downloadable paperwork (including
                  the WFS receiving label), and a button to confirm the shipment is
                  ready:</p><p>{{portal_link}}</p><p><strong>Prep instructions:</strong></p><p>{{instructions}}</p><p>Please
                  affix the WFS receiving label to the outside of each carton before
                  the shipment goes out. Once you confirm it&rsquo;s ready in the
                  portal we&rsquo;ll finalize the inbound with Walmart and send the
                  carrier / pickup details.</p><p>Thank you.</p>
                cc:
                - warehouse-manager@acme3pl.com
                attach_prep_sheet: true
                attach_receiving_label: true
                attach_carrier_label: true
                from_mode: system
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      - name: shipment
        in: path
        schema:
          type: integer
        required: true
        description: WFS inbound shipment ID (local WalmartWfsInboundShipment id)
        example: '843'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      walmart_wfs_inbound_shipment_id:
                        type: integer
                      source_type:
                        type: string
                      source_type_label:
                        type: string
                      channels:
                        type: array
                        items:
                          type: string
                      status:
                        type: string
                      status_label:
                        type: string
                      build_required:
                        type: boolean
                      instruction_override:
                        type: string
                        nullable: true
                      portal_token:
                        type: string
                      portal_accessible:
                        type: boolean
                      portal_token_expires_at:
                        type: string
                      sent_at:
                        type: string
                      acknowledged_at:
                        type: string
                        nullable: true
                      recipient_email:
                        type: string
                      recipient_name:
                        type: string
                      email_from:
                        type: object
                        properties:
                          address:
                            type: string
                          name:
                            type: string
                      email_reply_to:
                        type: object
                        properties:
                          address:
                            type: string
                          name:
                            type: string
                      email_from_default_mode:
                        type: string
                      email_from_options:
                        type: object
                        properties:
                          merchant:
                            type: object
                            properties:
                              address:
                                type: string
                              name:
                                type: string
                          system:
                            type: object
                            properties:
                              address:
                                type: string
                              name:
                                type: string
                      email_from_dns_setup:
                        type: object
                        properties:
                          domain:
                            type: string
                          provider:
                            type: string
                          steps:
                            type: array
                            items:
                              type: object
                              properties:
                                title:
                                  type: string
                                detail:
                                  type: string
                                record:
                                  type: object
                                  properties:
                                    type:
                                      type: string
                                    host:
                                      type: string
                                    value:
                                      type: string
                      email_template:
                        type: object
                        properties:
                          subject:
                            type: string
                          body:
                            type: string
                          is_custom:
                            type: boolean
                      email_will_attach_prep_sheet:
                        type: boolean
                      email_will_attach_receiving_label:
                        type: boolean
                      email_will_attach_carrier_label:
                        type: boolean
                      documents:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            type:
                              type: string
                            type_label:
                              type: string
                            stage:
                              type: string
                            stage_label:
                              type: string
                            status:
                              type: string
                            status_label:
                              type: string
                            downloadable:
                              type: boolean
                      created_at:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 12
                    walmart_wfs_inbound_shipment_id: 843
                    source_type: 3pl
                    source_type_label: 3PL Warehouse
                    channels:
                    - email
                    - portal
                    status: sent
                    status_label: Sent
                    build_required: false
                    instruction_override: null
                    portal_token: a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6
                    portal_accessible: true
                    portal_token_expires_at: '2026-08-05T14:30:00.000000Z'
                    sent_at: '2026-07-07T16:05:00.000000Z'
                    acknowledged_at: null
                    recipient_email: receiving@acme3pl.com
                    recipient_name: Acme 3PL Warehouse
                    email_from:
                      address: noreply@sku.io
                      name: Acme Store
                    email_reply_to:
                      address: ops@acme-store.com
                      name: Jane Operator
                    email_from_default_mode: system
                    email_from_options:
                      merchant:
                        address: orders@acme-store.com
                        name: Acme Store
                      system:
                        address: noreply@sku.io
                        name: Acme Store
                    email_from_dns_setup:
                      domain: acme-store.com
                      provider: Postmark
                      steps:
                      - title: Authorize Postmark in acme-store.com's SPF record
                        detail: 'Add include:spf.mtasv.net to the SPF TXT record on
                          acme-store.com. A domain must have exactly one SPF record
                          — merge it into the existing one instead of adding a second.
                          If acme-store.com has no SPF record yet, publish:'
                        record:
                          type: TXT
                          host: acme-store.com
                          value: v=spf1 include:spf.mtasv.net ~all
                      - title: Publish acme-store.com's DKIM records
                        detail: DKIM records are unique per domain and are generated
                          when acme-store.com is added to SKU.io's Postmark sending
                          account. Ask SKU.io support to add acme-store.com — you'll
                          receive three CNAME records (s1._domainkey.acme-store.com,
                          s2._domainkey.acme-store.com and a return-path host) to
                          publish, which also aligns the emails with your DMARC policy.
                      - title: Verify before relying on it
                        detail: Send a test email and check it arrives in the inbox
                          (not spam) with SPF and DKIM shown as PASS in the message
                          headers. Until both pass, recipients with a strict DMARC
                          policy on acme-store.com may reject these emails.
                    email_template:
                      subject: Walmart WFS inbound — prep & receiving label needed
                        for {{reference}}
                      body: <p>Hi,</p><p>We&rsquo;re sending a Walmart Fulfillment
                        Services (WFS) inbound shipment (<strong>{{reference}}</strong>)
                        from your location and need you to prep and pack it per the
                        instructions below, then confirm when it&rsquo;s ready.</p><p><strong>Preferred
                        &mdash; use the secure portal.</strong> It shows the items
                        to prepare, the destination fulfillment center, downloadable
                        paperwork (including the WFS receiving label), and a button
                        to confirm the shipment is ready:</p><p>{{portal_link}}</p><p><strong>Prep
                        instructions:</strong></p><p>{{instructions}}</p><p>Please
                        affix the WFS receiving label to the outside of each carton
                        before the shipment goes out. Once you confirm it&rsquo;s
                        ready in the portal we&rsquo;ll finalize the inbound with
                        Walmart and send the carrier / pickup details.</p><p>Thank
                        you.</p>
                      is_custom: false
                    email_will_attach_prep_sheet: true
                    email_will_attach_receiving_label: true
                    email_will_attach_carrier_label: true
                    documents:
                    - id: 101
                      type: receiving_label
                      type_label: WFS Receiving Label
                      stage: initial
                      stage_label: Initial
                      status: ready
                      status_label: Ready
                      downloadable: true
                    - id: 103
                      type: carrier_label
                      type_label: WFS Carrier Label
                      stage: initial
                      stage_label: Initial
                      status: ready
                      status_label: Ready
                      downloadable: true
                    - id: 102
                      type: instructions
                      type_label: Prep Instructions
                      stage: initial
                      stage_label: Initial
                      status: ready
                      status_label: Ready
                      downloadable: true
                    - id: 104
                      type: asn
                      type_label: Advanced Shipment Notice
                      stage: initial
                      stage_label: Initial
                      status: ready
                      status_label: Ready
                      downloadable: false
                    created_at: '2026-07-06T14:30:00.000000Z'
                  message: Email sent to the 3PL.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-walmart-integrationinstance-wfs-inbound-shipments-shipment-fulfillment-email
  /api/walmart/{integrationInstance}/wfs/inbound-shipments/{shipment}/fulfillment/prep-sheet.csv:
    get:
      tags:
      - Walmart
      summary: Download Prep & Pack Sheet (CSV)
      description: 'Stream the prep-&-pack sheet as a CSV (unit mix, packing, prep,
        and any kitting work order) so an operator can hand it to a 3PL/supplier that
        won''t use the secure portal. The file is named wfs-prep-pack-sheet-&lt;packetId>.csv.
        A fulfilment packet must have been built first — returns 422 JSON { message
        } when none exists yet.


        Authentication: Requires Bearer token.


        Response: a text/csv file download (no JSON body on success).'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      - name: shipment
        in: path
        schema:
          type: integer
        required: true
        description: WFS inbound shipment ID (local WalmartWfsInboundShipment id)
        example: '843'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: text/csv
            Content-Disposition:
              schema:
                type: string
                example: attachment; filename=wfs-prep-pack-sheet-12.csv
          content:
            text/plain:
              schema:
                type: string
                example: "Section,SKU,Description,Quantity,Notes\r\nUnit Mix,WIDGET-BLUE,Blue\
                  \ Widget 12oz,48,\r\nUnit Mix,WIDGET-RED,Red Widget 12oz,24,\r\n\
                  Packing,,,,Affix WFS receiving label to each carton\r\nPrep,,,,Poly-bag\
                  \ units with suffocation warning\r\n"
        '422':
          description: Unprocessable Content
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Build the fulfilment packet before exporting the prep sheet.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-walmart-integrationinstance-wfs-inbound-shipments-shipment-fulfillment-prep-sheet-csv
  /api/walmart/{integrationInstance}/wfs/inbound-shipments/fulfillment-portal/{token}:
    get:
      tags:
      - Walmart
      summary: 'Portal: View Packet'
      description: 'Load the public fulfilment portal for a WFS inbound packet, resolved
        by its portal token. Records a ''viewed'' portal event and returns the full
        order summary the 3PL/supplier needs: reference + destination FC, rendered
        prep instructions, downloadable documents, the kit build manifest (when a
        build is required), the expected line items, and whether it has been acknowledged
        as ready.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Public, token-gated endpoint — no bearer auth. The {token} in the path gates
        packet access; tenant is resolved by host.


        Returns 404 with {"message": "This portal link is no longer valid."} when
        the token is unknown, expired, or revoked.


        Response data fields:

        - reference (string): the WFS shipment_id.

        - inbound_order_id (string|null): Walmart inbound order id.

        - source_name (string|null): the source 3PL/supplier warehouse name.

        - source_type (string): ''3pl'' or ''supplier''.

        - destination_fc (string|null): Walmart ship node / FC.

        - status (string): packet status (draft, sent, in_progress, acknowledged,
        shipped, send_failed, revoked).

        - build_required (bool): whether component-sourced kits must be assembled.

        - kits_pending_build (bool): a build is required and at least one kit is not
        yet confirmed built.

        - kit_build_manifest (array): kits to assemble — { sku, name, quantity, components:[{
        sku, quantity }] }.

        - instructions (string): rendered plain-text prep instructions (or operator
        override).

        - line_items (array): { sku, name, image_url, quantity } for every shipment
        line.

        - documents (array): downloadable documents — { id, type, type_label, stage,
        status }.

        - acknowledged_at (string|null): ISO-8601 timestamp once acknowledged, else
        null.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      - name: token
        in: path
        schema:
          type: string
        required: true
        description: Portal access token that gates this packet (revocable, expiring)
        example: a1b2c3d4e5
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      reference:
                        type: string
                      inbound_order_id:
                        type: string
                      source_name:
                        type: string
                      source_type:
                        type: string
                      destination_fc:
                        type: string
                      destination_address:
                        type: object
                        properties:
                          name:
                            type: string
                          line1:
                            type: string
                          line2:
                            type: string
                            nullable: true
                          city:
                            type: string
                          state:
                            type: string
                          postal_code:
                            type: string
                          country:
                            type: string
                      status:
                        type: string
                      build_required:
                        type: boolean
                      kits_pending_build:
                        type: boolean
                      kit_build_manifest:
                        type: array
                        items:
                          type: object
                          properties:
                            sku:
                              type: string
                            name:
                              type: string
                            quantity:
                              type: integer
                            components:
                              type: array
                              items:
                                type: object
                                properties:
                                  sku:
                                    type: string
                                  quantity:
                                    type: integer
                      instructions:
                        type: string
                      line_items:
                        type: array
                        items:
                          type: object
                          properties:
                            sku:
                              type: string
                            name:
                              type: string
                            image_url:
                              type: string
                            quantity:
                              type: integer
                      documents:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            type:
                              type: string
                            type_label:
                              type: string
                            stage:
                              type: string
                            status:
                              type: string
                      acknowledged_at:
                        type: string
                        nullable: true
                example:
                  data:
                    reference: WFS-8842190
                    inbound_order_id: INB-4471203
                    source_name: Eastgate 3PL Fulfillment
                    source_type: 3pl
                    destination_fc: '6094'
                    destination_address:
                      name: Walmart Fulfillment Center 6094
                      line1: 5300 Centennial Blvd
                      line2: null
                      city: Nashville
                      state: TN
                      postal_code: '37209'
                      country: US
                    status: sent
                    build_required: true
                    kits_pending_build: true
                    kit_build_manifest:
                    - sku: KIT-STARTER-01
                      name: Starter Bundle Kit
                      quantity: 24
                      components:
                      - sku: WIDGET-RED
                        quantity: 2
                      - sku: WIDGET-CABLE
                        quantity: 1
                    instructions: "WALMART WFS INBOUND — PREP INSTRUCTIONS\nShipment:\
                      \ WFS-8842190 (Order INB-4471203)\nDestination FC: 6094\n\n\
                      Items to prepare:\n  • 24 × KIT-STARTER-01 — Starter Bundle\
                      \ Kit\n  • 60 × WIDGET-BLUE-500 — Blue Widget 500ml\n\nAffix\
                      \ the WFS Receiving Label (provided) to the outside of each\
                      \ carton.\n\nKITTING: assemble the kit SKUs per the Kitting\
                      \ Work Order, then confirm \"Kits Built\"."
                    line_items:
                    - sku: KIT-STARTER-01
                      name: Starter Bundle Kit
                      image_url: https://cdn.sku.io/products/kit-starter-01.jpg
                      quantity: 24
                    - sku: WIDGET-BLUE-500
                      name: Blue Widget 500ml
                      image_url: https://cdn.sku.io/products/widget-blue-500.jpg
                      quantity: 60
                    documents:
                    - id: 101
                      type: receiving_label
                      type_label: WFS Receiving Label
                      stage: initial
                      status: ready
                    - id: 102
                      type: instructions
                      type_label: Prep Instructions
                      stage: initial
                      status: ready
                    - id: 104
                      type: work_order
                      type_label: Kitting Work Order
                      stage: initial
                      status: ready
                    - id: 105
                      type: asn
                      type_label: Advanced Shipment Notice
                      stage: initial
                      status: ready
                    acknowledged_at: null
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: This portal link is no longer valid.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-walmart-integrationinstance-wfs-inbound-shipments-fulfillment-portal-token
  /api/walmart/{integrationInstance}/wfs/inbound-shipments/fulfillment-portal/{token}/documents/{document}/download:
    get:
      tags:
      - Walmart
      summary: 'Portal: Download Document'
      description: 'Download one of the packet''s staged documents by id. Records
        a ''downloaded'' portal event, then streams the document as a file attachment
        (not JSON):

        - receiving_label → the live WFS receiving label fetched from Walmart as a
        PDF (Content-Type: application/pdf, Content-Disposition: attachment; filename="wfs-receiving-label-&lt;shipment_id>.pdf").

        - carrier_label → the live WFS carrier / pickup label fetched from Walmart
        as a PDF (Content-Type: application/pdf, Content-Disposition: attachment;
        filename="wfs-carrier-label-&lt;shipment_id>.pdf"). Only present when a preferred
        carrier is booked on the shipment.

        - instructions / work_order → rendered on demand as a plain-text attachment
        (Content-Type: text/plain; charset=UTF-8, filename="&lt;type>-&lt;packet_id>.txt").


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Public, token-gated endpoint — no bearer auth. The {token} in the path gates
        packet access; tenant is resolved by host.


        Errors:

        - 404 (text ''This portal link is no longer valid.'') when the token is invalid/expired/revoked
        or the document does not belong to this packet.

        - 422 (text ''This document is not yet available.'') when the document status
        is not downloadable.

        - 422 (text ''The receiving label could not be retrieved from Walmart right
        now.'') when the live label fetch fails.

        - 422 (text ''The carrier label could not be retrieved from Walmart right
        now.'') when the live carrier-label fetch fails.

        - 422 (text ''This document is prepared elsewhere and will be attached when
        ready.'') for a file-backed type (e.g. po/asn) with no rendered content.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      - name: token
        in: path
        schema:
          type: string
        required: true
        description: Portal access token that gates this packet (revocable, expiring)
        example: a1b2c3d4e5
      - name: document
        in: path
        schema:
          type: integer
        required: true
        description: WFS inbound document ID (must belong to this packet)
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/pdf
            Content-Disposition:
              schema:
                type: string
                example: attachment; filename="wfs-receiving-label-WFS-8842190.pdf"
          content:
            text/plain:
              schema:
                type: string
              examples:
                example-0:
                  summary: 200 OK (Receiving Label PDF)
                  value: '%PDF-1.4

                    <binary PDF stream — the WFS receiving label carton PDF fetched
                    live from Walmart>

                    %%EOF


                    (Sent as an attachment: filename="wfs-receiving-label-WFS-8842190.pdf".
                    Body is binary and not shown here.)'
                example-1:
                  summary: 200 OK (Rendered Text Document)
                  value: 'KITTING WORK ORDER


                    Build 24 × KIT-STARTER-01 — Starter Bundle Kit


                    (text/plain attachment for instructions / work_order document
                    types.)'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: text/plain; charset=UTF-8
          content:
            text/plain:
              schema:
                type: string
                example: This document is not yet available.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-walmart-integrationinstance-wfs-inbound-shipments-fulfillment-portal-token-documents-document-download
  /api/walmart/{integrationInstance}/wfs/inbound-shipments/fulfillment-portal/{token}/kits-built:
    post:
      tags:
      - Walmart
      summary: 'Portal: Confirm Kits Built'
      description: 'Explicitly confirm the component-sourced kits have been assembled.
        Realizes the kit builds (releases the reserved components, assembles the kit,
        and reserves it against the shipment — idempotent and safe when there is nothing
        to build), records a ''kits_built'' portal event, and returns the refreshed
        portal payload with kits_pending_build cleared.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        No request body is required.


        Public, token-gated endpoint — no bearer auth. The {token} in the path gates
        packet access; tenant is resolved by host.


        Errors:

        - 404 {"message": "This portal link is no longer valid."} when the token is
        invalid.

        - 422 {"message": "&lt;reason>"} when the kit build cannot be realized (e.g.
        insufficient components).


        Response: { data: &lt;full portal payload>, message: "Thank you — the kits
        have been marked as built." }.'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      - name: token
        in: path
        schema:
          type: string
        required: true
        description: Portal access token that gates this packet (revocable, expiring)
        example: a1b2c3d4e5
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      reference:
                        type: string
                      inbound_order_id:
                        type: string
                      source_name:
                        type: string
                      source_type:
                        type: string
                      destination_fc:
                        type: string
                      destination_address:
                        type: object
                        properties:
                          name:
                            type: string
                          line1:
                            type: string
                          line2:
                            type: string
                            nullable: true
                          city:
                            type: string
                          state:
                            type: string
                          postal_code:
                            type: string
                          country:
                            type: string
                      status:
                        type: string
                      build_required:
                        type: boolean
                      kits_pending_build:
                        type: boolean
                      kit_build_manifest:
                        type: array
                        items:
                          type: object
                          properties:
                            sku:
                              type: string
                            name:
                              type: string
                            quantity:
                              type: integer
                            components:
                              type: array
                              items:
                                type: object
                                properties:
                                  sku:
                                    type: string
                                  quantity:
                                    type: integer
                      instructions:
                        type: string
                      line_items:
                        type: array
                        items:
                          type: object
                          properties:
                            sku:
                              type: string
                            name:
                              type: string
                            image_url:
                              type: string
                            quantity:
                              type: integer
                      documents:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            type:
                              type: string
                            type_label:
                              type: string
                            stage:
                              type: string
                            status:
                              type: string
                      acknowledged_at:
                        type: string
                        nullable: true
                  message:
                    type: string
                example:
                  data:
                    reference: WFS-8842190
                    inbound_order_id: INB-4471203
                    source_name: Eastgate 3PL Fulfillment
                    source_type: 3pl
                    destination_fc: '6094'
                    destination_address:
                      name: Walmart Fulfillment Center 6094
                      line1: 5300 Centennial Blvd
                      line2: null
                      city: Nashville
                      state: TN
                      postal_code: '37209'
                      country: US
                    status: in_progress
                    build_required: true
                    kits_pending_build: false
                    kit_build_manifest:
                    - sku: KIT-STARTER-01
                      name: Starter Bundle Kit
                      quantity: 24
                      components:
                      - sku: WIDGET-RED
                        quantity: 2
                      - sku: WIDGET-CABLE
                        quantity: 1
                    instructions: "WALMART WFS INBOUND — PREP INSTRUCTIONS\nShipment:\
                      \ WFS-8842190 (Order INB-4471203)\nDestination FC: 6094\n\n\
                      Items to prepare:\n  • 24 × KIT-STARTER-01 — Starter Bundle\
                      \ Kit\n  • 60 × WIDGET-BLUE-500 — Blue Widget 500ml\n\nAffix\
                      \ the WFS Receiving Label (provided) to the outside of each\
                      \ carton.\n\nKITTING: assemble the kit SKUs per the Kitting\
                      \ Work Order, then confirm \"Kits Built\"."
                    line_items:
                    - sku: KIT-STARTER-01
                      name: Starter Bundle Kit
                      image_url: https://cdn.sku.io/products/kit-starter-01.jpg
                      quantity: 24
                    - sku: WIDGET-BLUE-500
                      name: Blue Widget 500ml
                      image_url: https://cdn.sku.io/products/widget-blue-500.jpg
                      quantity: 60
                    documents:
                    - id: 101
                      type: receiving_label
                      type_label: WFS Receiving Label
                      stage: initial
                      status: ready
                    - id: 102
                      type: instructions
                      type_label: Prep Instructions
                      stage: initial
                      status: ready
                    - id: 104
                      type: work_order
                      type_label: Kitting Work Order
                      stage: initial
                      status: ready
                    - id: 105
                      type: asn
                      type_label: Advanced Shipment Notice
                      stage: initial
                      status: ready
                    acknowledged_at: null
                  message: Thank you — the kits have been marked as built.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: There are not enough components in stock to build these
                    kits.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-walmart-integrationinstance-wfs-inbound-shipments-fulfillment-portal-token-kits-built
  /api/walmart/{integrationInstance}/wfs/inbound-shipments/fulfillment-portal/{token}/acknowledge:
    post:
      tags:
      - Walmart
      summary: 'Portal: Acknowledge'
      description: 'Acknowledge the shipment as ready to ship. Requires box contents
        to have been submitted first — otherwise returns 422. On success it backstops
        any unconfirmed component-sourced kit builds (idempotent), marks the packet
        ''acknowledged'' with acknowledged_at set, records an ''acknowledged'' portal
        event, and returns the refreshed portal payload.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        No request body is required.


        Public, token-gated endpoint — no bearer auth. The {token} in the path gates
        packet access; tenant is resolved by host.


        Errors:

        - 404 {"message": "This portal link is no longer valid."} when the token is
        invalid.

        - 422 {"message": "Submit your box contents before confirming the shipment
        is ready."} when box contents have not been submitted yet.


        Response: { data: &lt;full portal payload with status ''acknowledged'' and
        acknowledged_at set>, message: "Thank you — the shipment has been confirmed
        as ready." }.'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      - name: token
        in: path
        schema:
          type: string
        required: true
        description: Portal access token that gates this packet (revocable, expiring)
        example: a1b2c3d4e5
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      reference:
                        type: string
                      inbound_order_id:
                        type: string
                      source_name:
                        type: string
                      source_type:
                        type: string
                      destination_fc:
                        type: string
                      destination_address:
                        type: object
                        properties:
                          name:
                            type: string
                          line1:
                            type: string
                          line2:
                            type: string
                            nullable: true
                          city:
                            type: string
                          state:
                            type: string
                          postal_code:
                            type: string
                          country:
                            type: string
                      status:
                        type: string
                      build_required:
                        type: boolean
                      kits_pending_build:
                        type: boolean
                      kit_build_manifest:
                        type: array
                        items:
                          type: object
                          properties:
                            sku:
                              type: string
                            name:
                              type: string
                            quantity:
                              type: integer
                            components:
                              type: array
                              items:
                                type: object
                                properties:
                                  sku:
                                    type: string
                                  quantity:
                                    type: integer
                      instructions:
                        type: string
                      line_items:
                        type: array
                        items:
                          type: object
                          properties:
                            sku:
                              type: string
                            name:
                              type: string
                            image_url:
                              type: string
                            quantity:
                              type: integer
                      documents:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            type:
                              type: string
                            type_label:
                              type: string
                            stage:
                              type: string
                            status:
                              type: string
                      acknowledged_at:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    reference: WFS-8842190
                    inbound_order_id: INB-4471203
                    source_name: Eastgate 3PL Fulfillment
                    source_type: 3pl
                    destination_fc: '6094'
                    destination_address:
                      name: Walmart Fulfillment Center 6094
                      line1: 5300 Centennial Blvd
                      line2: null
                      city: Nashville
                      state: TN
                      postal_code: '37209'
                      country: US
                    status: acknowledged
                    build_required: true
                    kits_pending_build: false
                    kit_build_manifest:
                    - sku: KIT-STARTER-01
                      name: Starter Bundle Kit
                      quantity: 24
                      components:
                      - sku: WIDGET-RED
                        quantity: 2
                      - sku: WIDGET-CABLE
                        quantity: 1
                    instructions: "WALMART WFS INBOUND — PREP INSTRUCTIONS\nShipment:\
                      \ WFS-8842190 (Order INB-4471203)\nDestination FC: 6094\n\n\
                      Items to prepare:\n  • 24 × KIT-STARTER-01 — Starter Bundle\
                      \ Kit\n  • 60 × WIDGET-BLUE-500 — Blue Widget 500ml\n\nAffix\
                      \ the WFS Receiving Label (provided) to the outside of each\
                      \ carton.\n\nKITTING: assemble the kit SKUs per the Kitting\
                      \ Work Order, then confirm \"Kits Built\"."
                    line_items:
                    - sku: KIT-STARTER-01
                      name: Starter Bundle Kit
                      image_url: https://cdn.sku.io/products/kit-starter-01.jpg
                      quantity: 24
                    - sku: WIDGET-BLUE-500
                      name: Blue Widget 500ml
                      image_url: https://cdn.sku.io/products/widget-blue-500.jpg
                      quantity: 60
                    documents:
                    - id: 101
                      type: receiving_label
                      type_label: WFS Receiving Label
                      stage: initial
                      status: ready
                    - id: 102
                      type: instructions
                      type_label: Prep Instructions
                      stage: initial
                      status: ready
                    - id: 104
                      type: work_order
                      type_label: Kitting Work Order
                      stage: initial
                      status: ready
                    - id: 105
                      type: asn
                      type_label: Advanced Shipment Notice
                      stage: initial
                      status: ready
                    acknowledged_at: '2026-07-06T14:32:05+00:00'
                  message: Thank you — the shipment has been confirmed as ready.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Submit your box contents before confirming the shipment
                    is ready.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-walmart-integrationinstance-wfs-inbound-shipments-fulfillment-portal-token-acknowledge
  /api/walmart/{integrationInstance}/oauth/authorization-url:
    get:
      tags:
      - Walmart
      summary: Get Authorization URL
      description: 'Get the Walmart seller-consent authorization URL for this integration
        instance. Redirect the seller''s browser to the returned URL so they can grant
        delegated access to their Walmart Marketplace account; on approval Walmart
        redirects back with an authorization code that completes the connection.


        Authentication: Requires Bearer token.


        Requires the `integrations.update` permission.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: string
                example:
                  data: https://login.account.wal-mart.com/authorize?responseType=code&clientId=a1b2c3d4-1111-2222-3333-444455556666&redirectUri=https%3A%2F%2Fapp.sku.io%2Fwalmart%2Fcallback&clientType=seller&nonce=8f4e2a&state=eyJpbnN0YW5jZSI6MX0
        '403':
          description: Forbidden
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: User does not have the right permissions.
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Integration instance not found.
        '429': *id001
        '401': *id002
      operationId: get-api-walmart-integrationinstance-oauth-authorization-url
  /api/walmart/{integrationInstance}/oauth/disconnect:
    post:
      tags:
      - Walmart
      summary: Disconnect OAuth Connection
      description: 'Disconnect the delegated Walmart authorization for this integration
        instance. Destroys both the delegated access token and the refresh token and
        deactivates syncing until the seller re-authorizes. No request body.


        Authentication: Requires Bearer token.


        Requires the `integrations.update` permission.'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      disconnected:
                        type: boolean
                example:
                  data:
                    disconnected: true
        '403':
          description: Forbidden
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: User does not have the right permissions.
        '429': *id001
        '401': *id002
        '404': *id004
        '422': *id005
      operationId: post-api-walmart-integrationinstance-oauth-disconnect
  /api/walmart/{integrationInstance}/feeds:
    get:
      tags:
      - Walmart
      summary: List Feeds
      description: 'List bulk feeds submitted to Walmart for this integration instance
        (inventory, price, and promotion feeds) with their processing status, paginated.


        Authentication: Requires Bearer token.


        Feed fields include: id, feed_id (Walmart feed ID), feed_type, status, items_received,
        items_succeeded, items_failed, failed_item_count, payload_summary, failure_reason,
        submitted_at, completed_at, last_polled_at, poll_attempts, created_at.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        feed_id:
                          type: string
                        feed_type:
                          type: string
                        status:
                          type: string
                        items_received:
                          type: integer
                        items_succeeded:
                          type: integer
                        items_failed:
                          type: integer
                        failed_item_count:
                          type: integer
                        payload_summary:
                          type: object
                          properties:
                            listing_count:
                              type: integer
                        failure_reason:
                          type: string
                          nullable: true
                        submitted_at:
                          type: string
                        completed_at:
                          type: string
                        last_polled_at:
                          type: string
                        poll_attempts:
                          type: integer
                        created_at:
                          type: string
                  current_page:
                    type: integer
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                    items:
                      type: object
                      properties:
                        url:
                          type: string
                          nullable: true
                        label:
                          type: string
                        active:
                          type: boolean
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 1042
                    feed_id: 6A76F037DF2A4D148103E18988215469@AVMBCgA
                    feed_type: MP_INVENTORY
                    status: PROCESSED
                    items_received: 25
                    items_succeeded: 24
                    items_failed: 1
                    failed_item_count: 1
                    payload_summary:
                      listing_count: 25
                    failure_reason: null
                    submitted_at: '2026-07-15T10:41:00+00:00'
                    completed_at: '2026-07-15T10:52:00+00:00'
                    last_polled_at: '2026-07-15T10:52:00+00:00'
                    poll_attempts: 3
                    created_at: '2026-07-15T10:41:00+00:00'
                  current_page: 1
                  first_page_url: https://app.sku.io/api/walmart/1/feeds?page=1
                  from: 1
                  last_page: 1
                  last_page_url: https://app.sku.io/api/walmart/1/feeds?page=1
                  links:
                  - url: null
                    label: '&laquo; Previous'
                    active: false
                  - url: https://app.sku.io/api/walmart/1/feeds?page=1
                    label: '1'
                    active: true
                  - url: null
                    label: Next &raquo;
                    active: false
                  next_page_url: null
                  path: https://app.sku.io/api/walmart/1/feeds
                  per_page: 10
                  prev_page_url: null
                  to: 1
                  total: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-walmart-integrationinstance-feeds
  /api/walmart/{integrationInstance}/feeds/{feed}:
    get:
      tags:
      - Walmart
      summary: Get Feed
      description: 'Get a single feed with its per-SKU ingestion errors. Each item
        in the items array is a SKU that Walmart reported on, including any error
        codes and descriptions for failed items.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      - name: feed
        in: path
        schema:
          type: integer
        required: true
        description: Feed ID
        example: '1042'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      feed_id:
                        type: string
                      feed_type:
                        type: string
                      status:
                        type: string
                      items_received:
                        type: integer
                      items_succeeded:
                        type: integer
                      items_failed:
                        type: integer
                      failed_item_count:
                        type: integer
                      payload_summary:
                        type: object
                        properties:
                          listing_count:
                            type: integer
                      failure_reason:
                        type: string
                        nullable: true
                      submitted_at:
                        type: string
                      completed_at:
                        type: string
                      last_polled_at:
                        type: string
                      poll_attempts:
                        type: integer
                      created_at:
                        type: string
                      items:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            sku:
                              type: string
                            status:
                              type: string
                            errors:
                              type: array
                              items:
                                type: object
                                properties:
                                  code:
                                    type: string
                                  field:
                                    type: string
                                  description:
                                    type: string
                            created_at:
                              type: string
                example:
                  data:
                    id: 1042
                    feed_id: 6A76F037DF2A4D148103E18988215469@AVMBCgA
                    feed_type: MP_INVENTORY
                    status: PROCESSED
                    items_received: 25
                    items_succeeded: 24
                    items_failed: 1
                    failed_item_count: 1
                    payload_summary:
                      listing_count: 25
                    failure_reason: null
                    submitted_at: '2026-07-15T10:41:00+00:00'
                    completed_at: '2026-07-15T10:52:00+00:00'
                    last_polled_at: '2026-07-15T10:52:00+00:00'
                    poll_attempts: 3
                    created_at: '2026-07-15T10:41:00+00:00'
                    items:
                    - id: 1
                      sku: SKU-BAD
                      status: ERROR
                      errors:
                      - code: ERR_EXT_ITEM_0001
                        field: description
                        description: Required attribute "Description" is missing.
                      created_at: '2026-07-15T10:52:01+00:00'
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Feed not found for this integration instance.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-walmart-integrationinstance-feeds-feed
  /api/walmart/{integrationInstance}/feeds/{feed}/repoll:
    post:
      tags:
      - Walmart
      summary: Re-poll Feed Status
      description: 'Re-queue status polling for a stalled or lagging feed. Use this
        when a feed has stopped receiving status updates from Walmart. No request
        body.


        Authentication: Requires Bearer token.


        Requires the `integrations.sync` permission.'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      - name: feed
        in: path
        schema:
          type: integer
        required: true
        description: Feed ID
        example: '1042'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      repolling:
                        type: boolean
                example:
                  data:
                    repolling: true
        '403':
          description: Forbidden
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: User does not have the right permissions.
        '429': *id001
        '401': *id002
        '404': *id004
        '422': *id005
      operationId: post-api-walmart-integrationinstance-feeds-feed-repoll
  /api/walmart/{integrationInstance}/prices/push:
    post:
      tags:
      - Walmart
      summary: Push Prices
      description: 'Submit current prices to Walmart as a bulk price feed for listings
        where SKU.io is the master of price.


        Authentication: Requires Bearer token.


        Fields:

        - listing_ids (optional, array of integers): IDs of the listings to push.
        Omit to push all eligible listings.


        Requires the `integrations.sync` permission.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                listing_ids:
                  type: array
                  items:
                    type: integer
              example:
                listing_ids:
                - 101
                - 102
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      feed_id:
                        type: string
                      feed_type:
                        type: string
                      status:
                        type: string
                      items_received:
                        type: integer
                      items_succeeded:
                        type: integer
                      items_failed:
                        type: integer
                      failed_item_count:
                        type: integer
                      payload_summary:
                        type: object
                        properties:
                          listing_count:
                            type: integer
                      failure_reason:
                        type: string
                        nullable: true
                      submitted_at:
                        type: string
                      completed_at:
                        type: string
                        nullable: true
                      last_polled_at:
                        type: string
                        nullable: true
                      poll_attempts:
                        type: integer
                      created_at:
                        type: string
                example:
                  data:
                    id: 1043
                    feed_id: 7B87E148EA3B5E259214F29099326570@AVMBCgA
                    feed_type: price
                    status: RECEIVED
                    items_received: 2
                    items_succeeded: 0
                    items_failed: 0
                    failed_item_count: 0
                    payload_summary:
                      listing_count: 2
                    failure_reason: null
                    submitted_at: '2026-07-15T14:03:00+00:00'
                    completed_at: null
                    last_polled_at: null
                    poll_attempts: 0
                    created_at: '2026-07-15T14:03:00+00:00'
        '403':
          description: Forbidden
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: User does not have the right permissions.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No eligible listings were found to push prices for.
        '429':
          description: Too Many Requests
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                  retry_after:
                    type: integer
                example:
                  error: Feed rate limit reached. Try again later.
                  retry_after: 1800
        '401': *id002
        '404': *id004
      operationId: post-api-walmart-integrationinstance-prices-push
  /api/walmart/{integrationInstance}/listings/{listing}/promotions:
    post:
      tags:
      - Walmart
      summary: Create or Update Promotion
      description: 'Submit a promotional price for a listing to Walmart via the promotion
        feed. Submitting again for the same listing updates the promotion.


        The listing must belong to this integration instance; requests for a listing
        owned by a different instance fail with 403 Forbidden.


        Authentication: Requires Bearer token.


        Fields:

        - amount (required, numeric): Promotional price.

        - effective_date (required, datetime): When the promotion starts.

        - expiration_date (required, datetime): When the promotion ends. Must be after
        effective_date.


        Requires the `integrations.sync` permission.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                amount:
                  type: number
                effective_date:
                  type: string
                expiration_date:
                  type: string
              example:
                amount: 19.99
                effective_date: '2026-08-01T00:00:00Z'
                expiration_date: '2026-08-15T00:00:00Z'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      - name: listing
        in: path
        schema:
          type: integer
        required: true
        description: Walmart listing ID
        example: '101'
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      feed_id:
                        type: string
                      feed_type:
                        type: string
                      status:
                        type: string
                      items_received:
                        type: integer
                      items_succeeded:
                        type: integer
                      items_failed:
                        type: integer
                      failed_item_count:
                        type: integer
                      payload_summary:
                        type: object
                        properties:
                          listing_count:
                            type: integer
                      failure_reason:
                        type: string
                        nullable: true
                      submitted_at:
                        type: string
                      completed_at:
                        type: string
                        nullable: true
                      last_polled_at:
                        type: string
                        nullable: true
                      poll_attempts:
                        type: integer
                      created_at:
                        type: string
                example:
                  data:
                    id: 1044
                    feed_id: 8C98F259FB4C6F36A325039100437681@AVMBCgA
                    feed_type: promo
                    status: RECEIVED
                    items_received: 1
                    items_succeeded: 0
                    items_failed: 0
                    failed_item_count: 0
                    payload_summary:
                      listing_count: 1
                    failure_reason: null
                    submitted_at: '2026-07-15T14:03:00+00:00'
                    completed_at: null
                    last_polled_at: null
                    poll_attempts: 0
                    created_at: '2026-07-15T14:03:00+00:00'
        '403':
          description: Forbidden
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 403 Listing Not Owned By Instance
                  value:
                    error: Listing does not belong to this integration instance
                example-1:
                  summary: 403 Missing Permission
                  value:
                    message: User does not have the right permissions.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      expiration_date:
                        type: array
                        items:
                          type: string
                example:
                  message: The expiration date field must be a date after effective
                    date.
                  errors:
                    expiration_date:
                    - The expiration date field must be a date after effective date.
        '429':
          description: Too Many Requests
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                  retry_after:
                    type: integer
                example:
                  error: Feed rate limit reached. Try again later.
                  retry_after: 1800
        '401': *id002
        '404': *id004
      operationId: post-api-walmart-integrationinstance-listings-listing-promotions
    delete:
      tags:
      - Walmart
      summary: Delete Promotion
      description: 'Remove the promotional price for a listing on Walmart via the
        promotion feed, restoring the regular price. No request body.


        The listing must belong to this integration instance; requests for a listing
        owned by a different instance fail with 403 Forbidden.


        Authentication: Requires Bearer token.


        Requires the `integrations.sync` permission.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      - name: listing
        in: path
        schema:
          type: integer
        required: true
        description: Walmart listing ID
        example: '101'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      feed_id:
                        type: string
                      feed_type:
                        type: string
                      status:
                        type: string
                      items_received:
                        type: integer
                      items_succeeded:
                        type: integer
                      items_failed:
                        type: integer
                      failed_item_count:
                        type: integer
                      payload_summary:
                        type: object
                        properties:
                          listing_count:
                            type: integer
                      failure_reason:
                        type: string
                        nullable: true
                      submitted_at:
                        type: string
                      completed_at:
                        type: string
                        nullable: true
                      last_polled_at:
                        type: string
                        nullable: true
                      poll_attempts:
                        type: integer
                      created_at:
                        type: string
                example:
                  data:
                    id: 1045
                    feed_id: 9DA90360AC5D7047B436140211548792@AVMBCgA
                    feed_type: promo
                    status: RECEIVED
                    items_received: 1
                    items_succeeded: 0
                    items_failed: 0
                    failed_item_count: 0
                    payload_summary:
                      listing_count: 1
                    failure_reason: null
                    submitted_at: '2026-07-15T14:03:00+00:00'
                    completed_at: null
                    last_polled_at: null
                    poll_attempts: 0
                    created_at: '2026-07-15T14:03:00+00:00'
        '403':
          description: Forbidden
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 403 Listing Not Owned By Instance
                  value:
                    error: Listing does not belong to this integration instance
                example-1:
                  summary: 403 Missing Permission
                  value:
                    message: User does not have the right permissions.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No active promotion was found for this listing.
        '429':
          description: Too Many Requests
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                  retry_after:
                    type: integer
                example:
                  error: Feed rate limit reached. Try again later.
                  retry_after: 1800
        '401': *id002
        '404': *id004
      operationId: delete-api-walmart-integrationinstance-listings-listing-promotions
  /api/walmart/{integrationInstance}/reports/recon/dates:
    get:
      tags:
      - Walmart
      summary: List Settlement Report Dates
      description: 'List the available reconciliation (settlement) report cycle dates
        for this integration instance. Use one of the returned dates as the report_date
        parameter when downloading a settlement report.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      availableApReportDates:
                        type: array
                        items:
                          type: string
                example:
                  data:
                    availableApReportDates:
                    - '07152026'
                    - '07012026'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: Failed to retrieve available reconciliation report dates
                    from Walmart.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-walmart-integrationinstance-reports-recon-dates
  /api/walmart/{integrationInstance}/reports/recon/download:
    get:
      tags:
      - Walmart
      summary: Download Settlement Report
      description: 'Download the reconciliation (settlement) report for a given cycle
        date. The response is a ZIP file download (Content-Type: application/octet-stream),
        not JSON. The report_date query parameter is required and must be a cycle
        date in MMDDYYYY format as returned by List Settlement Report Dates.


        Authentication: Requires Bearer token.'
      parameters:
      - name: report_date
        in: query
        schema:
          type: integer
        description: Settlement report cycle date in MMDDYYYY format, as returned
          by List Settlement Report Dates
        example: '07152026'
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/octet-stream
            Content-Disposition:
              schema:
                type: string
                example: attachment; filename="recon-report-07152026.zip"
          content:
            text/plain:
              schema:
                type: string
                example: PK [binary ZIP bytes — reconciliation report for cycle date
                  07152026; not JSON]
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      report_date:
                        type: array
                        items:
                          type: string
                example:
                  message: The report date field is required.
                  errors:
                    report_date:
                    - The report date field is required.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-walmart-integrationinstance-reports-recon-download
  /api/walmart/{integrationInstance}/reports/payment-statement:
    get:
      tags:
      - Walmart
      summary: Get Payment Statement
      description: 'Get the payment statement for the current settlement cycle, including
        the currency, the total payable amount, and the statement line groups.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      currency:
                        type: string
                      totalPayable:
                        type: number
                      statements:
                        type: array
                        items:
                          type: object
                          properties:
                            type:
                              type: string
                            amount:
                              type: number
                example:
                  data:
                    currency: USD
                    totalPayable: 15234.12
                    statements:
                    - type: ORDER_REVENUE
                      amount: 16890.45
                    - type: FEES
                      amount: -1656.33
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-walmart-integrationinstance-reports-payment-statement
  /api/walmart/{integrationInstance}/reports/performance:
    get:
      tags:
      - Walmart
      summary: Get Partner Performance Report
      description: 'Get the partner performance report for this integration instance,
        summarizing marketplace performance metrics as measured by Walmart.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      performance:
                        type: array
                        items:
                          type: object
                          properties:
                            metric:
                              type: string
                            value:
                              type: number
                            target:
                              type: number
                            status:
                              type: string
                example:
                  data:
                    performance:
                    - metric: ORDER_DEFECT_RATE
                      value: 0.008
                      target: 0.02
                      status: GOOD
                    - metric: ON_TIME_SHIPMENT_RATE
                      value: 0.991
                      target: 0.99
                      status: GOOD
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-walmart-integrationinstance-reports-performance
  /api/walmart/{integrationInstance}/reports/requests:
    get:
      tags:
      - Walmart
      summary: List Report Requests
      description: 'List the on-request report requests submitted for this integration
        instance, with their report type and processing status.


        Query parameters:

        - report_type (string, required): report type to list requests for, e.g. ITEM,
        INVENTORY, BUYBOX, CPA, SHIPPING_CONFIGURATION, RETURN_OVERRIDES, PROMO. The
        request fails with 422 when omitted.

        - report_version (string, optional): filter to a specific report version,
        e.g. v1.

        - request_status (string, optional): filter by request processing status,
        e.g. RECEIVED, INPROGRESS, READY, ERROR.


        Authentication: Requires Bearer token.'
      parameters:
      - name: report_type
        in: query
        schema:
          type: string
        description: Report type to list requests for, e.g. ITEM, INVENTORY, BUYBOX,
          CPA, SHIPPING_CONFIGURATION, RETURN_OVERRIDES, PROMO. Required; the request
          fails with 422 when omitted.
        example: ITEM
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      requests:
                        type: array
                        items:
                          type: object
                          properties:
                            requestId:
                              type: string
                            reportType:
                              type: string
                            requestStatus:
                              type: string
                            requestSubmissionDate:
                              type: string
                example:
                  data:
                    requests:
                    - requestId: 8b78e243-4c14-4a4a-8a27-fd3ebeef2f0a
                      reportType: ITEM
                      requestStatus: READY
                      requestSubmissionDate: '2026-07-15T10:00:00Z'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      report_type:
                        type: array
                        items:
                          type: string
                example:
                  message: The report type field is required.
                  errors:
                    report_type:
                    - The report type field is required.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-walmart-integrationinstance-reports-requests
    post:
      tags:
      - Walmart
      summary: Create Report Request
      description: 'Create an on-request report request. Walmart generates the report
        asynchronously; poll its status with Get Report Request Status and fetch the
        file with Get Report Download URL once it is READY.


        Fields:

        - report_type (string, required): the type of report to generate, e.g. ITEM.

        - report_version (string, optional): the report version; defaults to v1.


        Authentication: Requires Bearer token.


        Requires the `integrations.sync` permission.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                report_type:
                  type: string
                report_version:
                  type: string
              example:
                report_type: ITEM
                report_version: v1
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      requestId:
                        type: string
                      requestStatus:
                        type: string
                      reportType:
                        type: string
                example:
                  data:
                    requestId: 8b78e243-4c14-4a4a-8a27-fd3ebeef2f0a
                    requestStatus: RECEIVED
                    reportType: ITEM
        '403':
          description: Forbidden
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: User does not have the right permissions.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      report_type:
                        type: array
                        items:
                          type: string
                example:
                  message: The report type field is required.
                  errors:
                    report_type:
                    - The report type field is required.
        '429': *id001
        '401': *id002
        '404': *id004
      operationId: post-api-walmart-integrationinstance-reports-requests
  /api/walmart/{integrationInstance}/reports/requests/{requestId}:
    get:
      tags:
      - Walmart
      summary: Get Report Request Status
      description: 'Get the current status of an on-request report request.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      - name: requestId
        in: path
        schema:
          type: string
        required: true
        description: Report request ID
        example: 8b78e243-4c14-4a4a-8a27-fd3ebeef2f0a
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      requestId:
                        type: string
                      requestStatus:
                        type: string
                example:
                  data:
                    requestId: 8b78e243-4c14-4a4a-8a27-fd3ebeef2f0a
                    requestStatus: READY
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-walmart-integrationinstance-reports-requests-requestid
  /api/walmart/{integrationInstance}/reports/requests/{requestId}/download:
    get:
      tags:
      - Walmart
      summary: Get Report Download URL
      description: 'Get a time-limited signed download URL for a completed report
        request. Download the report file from the returned URL before it expires.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      - name: requestId
        in: path
        schema:
          type: string
        required: true
        description: Report request ID
        example: 8b78e243-4c14-4a4a-8a27-fd3ebeef2f0a
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      requestId:
                        type: string
                      downloadURL:
                        type: string
                      downloadURLExpirationTime:
                        type: string
                example:
                  data:
                    requestId: 8b78e243-4c14-4a4a-8a27-fd3ebeef2f0a
                    downloadURL: https://marketplace-reports.walmartapis.com/8b78e243-4c14-4a4a-8a27-fd3ebeef2f0a.zip?Signature=abc123
                    downloadURLExpirationTime: '2026-07-15T12:00:00Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-walmart-integrationinstance-reports-requests-requestid-download
  /api/walmart/{integrationInstance}/insights/seller-health:
    get:
      tags:
      - Walmart
      summary: Get Seller Health Summary
      description: 'Get an aggregated seller health summary — valid tracking rate,
        on-time delivery, on-time shipment, cancellation rate, refund rate, and seller
        response rate — over the requested reporting window. Each metric is fetched
        independently; if a single metric cannot be retrieved it is returned with
        an error key while the remaining metrics still succeed.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      vtr:
                        type: object
                        properties:
                          vtrRate:
                            type: number
                      on_time_delivery:
                        type: object
                        properties:
                          otdRate:
                            type: number
                      on_time_shipment:
                        type: object
                        properties:
                          rate:
                            type: number
                      cancellations:
                        type: object
                        properties:
                          rate:
                            type: number
                      refunds:
                        type: object
                        properties:
                          rate:
                            type: number
                      seller_response_rate:
                        type: object
                        properties:
                          error:
                            type: string
                example:
                  data:
                    vtr:
                      vtrRate: 0.98
                    on_time_delivery:
                      otdRate: 0.95
                    on_time_shipment:
                      rate: 0.97
                    cancellations:
                      rate: 0.01
                    refunds:
                      rate: 0.02
                    seller_response_rate:
                      error: Metric unavailable
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-walmart-integrationinstance-insights-seller-health
  /api/walmart/{integrationInstance}/platform-status:
    get:
      tags:
      - Walmart
      summary: Get API Platform Status
      description: 'Get the current status of the Walmart marketplace API platform
        and its components.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      status:
                        type: string
                      components:
                        type: array
                        items:
                          type: object
                          properties:
                            name:
                              type: string
                            status:
                              type: string
                example:
                  data:
                    status: OK
                    components:
                    - name: Orders
                      status: OPERATIONAL
                    - name: Items
                      status: OPERATIONAL
                    - name: Prices
                      status: OPERATIONAL
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-walmart-integrationinstance-platform-status
  /api/walmart/{integrationInstance}/shipping/carriers:
    get:
      tags:
      - Walmart
      summary: List Supported Carriers
      description: 'List the carriers supported by Ship With Walmart for purchasing
        shipping labels.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      carriers:
                        type: array
                        items:
                          type: object
                          properties:
                            carrierShortName:
                              type: string
                            carrierName:
                              type: string
                example:
                  data:
                    carriers:
                    - carrierShortName: UPS
                      carrierName: United Parcel Service
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-walmart-integrationinstance-shipping-carriers
  /api/walmart/{integrationInstance}/shipping/templates:
    get:
      tags:
      - Walmart
      summary: List Shipping Templates
      description: 'List the shipping templates configured on Walmart for this integration
        instance. Templates are read-only here and are managed in Walmart Seller Center.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      shippingTemplates:
                        type: array
                        items:
                          type: object
                          properties:
                            shipmentTemplateId:
                              type: string
                            templateName:
                              type: string
                            status:
                              type: string
                example:
                  data:
                    shippingTemplates:
                    - shipmentTemplateId: 5f2d8a1e-9c47-4b6d-8e15-3a7b2c9d0f41
                      templateName: Standard Shipping
                      status: ACTIVE
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-walmart-integrationinstance-shipping-templates
  /api/walmart/{integrationInstance}/shipping/fulfillment-centers:
    get:
      tags:
      - Walmart
      summary: List Fulfillment Centers
      description: 'List the fulfillment centers (ship nodes) configured on Walmart
        for this integration instance.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      shipNodes:
                        type: array
                        items:
                          type: object
                          properties:
                            shipNode:
                              type: string
                            shipNodeName:
                              type: string
                            status:
                              type: string
                example:
                  data:
                    shipNodes:
                    - shipNode: '10001516180'
                      shipNodeName: Main Warehouse
                      status: ACTIVE
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-walmart-integrationinstance-shipping-fulfillment-centers
  /api/walmart/{integrationInstance}/orders/{order}/shipping/estimates:
    post:
      tags:
      - Walmart
      summary: Get Shipping Estimates
      description: 'Get carrier rate estimates for shipping an order. Send the package
        details (dimensions and weight, passed through to Walmart) and optionally
        a carrier; the order''s purchase order ID is attached automatically.


        Authentication: Requires Bearer token.


        Requires the `sales_orders.fulfill` permission.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                carrierShortName:
                  type: string
                packageDimensions:
                  type: object
                  properties:
                    length:
                      type: integer
                    width:
                      type: integer
                    height:
                      type: integer
                    unitOfMeasurement:
                      type: string
                packageWeight:
                  type: object
                  properties:
                    value:
                      type: number
                    unitOfMeasurement:
                      type: string
              example:
                carrierShortName: UPS
                packageDimensions:
                  length: 10
                  width: 6
                  height: 4
                  unitOfMeasurement: IN
                packageWeight:
                  value: 2.5
                  unitOfMeasurement: LB
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      - name: order
        in: path
        schema:
          type: integer
        required: true
        description: Walmart order ID
        example: '60'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      estimates:
                        type: array
                        items:
                          type: object
                          properties:
                            carrierShortName:
                              type: string
                            serviceType:
                              type: string
                            totalCharges:
                              type: number
                example:
                  data:
                    estimates:
                    - carrierShortName: UPS
                      serviceType: GROUND
                      totalCharges: 8.42
        '403':
          description: Forbidden
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 403 Forbidden
                  value:
                    message: This order does not belong to the specified integration
                      instance.
                example-1:
                  summary: 403 Missing Permission
                  value:
                    message: User does not have the right permissions.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: Failed to retrieve shipping estimates from Walmart.
        '429': *id001
        '401': *id002
        '404': *id004
      operationId: post-api-walmart-integrationinstance-orders-order-shipping-estimates
  /api/walmart/{integrationInstance}/orders/{order}/shipping/labels:
    post:
      tags:
      - Walmart
      summary: Purchase Shipping Label
      description: 'Purchase a Ship With Walmart shipping label for an order shipment.
        Send the package details and the chosen carrier service; the order''s purchase
        order ID is attached automatically.


        Authentication: Requires Bearer token.


        Requires the `sales_orders.fulfill` permission.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                carrierShortName:
                  type: string
                serviceType:
                  type: string
                packageDimensions:
                  type: object
                  properties:
                    length:
                      type: integer
                    width:
                      type: integer
                    height:
                      type: integer
                    unitOfMeasurement:
                      type: string
                packageWeight:
                  type: object
                  properties:
                    value:
                      type: number
                    unitOfMeasurement:
                      type: string
              example:
                carrierShortName: UPS
                serviceType: GROUND
                packageDimensions:
                  length: 10
                  width: 6
                  height: 4
                  unitOfMeasurement: IN
                packageWeight:
                  value: 2.5
                  unitOfMeasurement: LB
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      - name: order
        in: path
        schema:
          type: integer
        required: true
        description: Walmart order ID
        example: '60'
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      trackingNo:
                        type: string
                      labelStatus:
                        type: string
                      labelDownloadURL:
                        type: string
                example:
                  data:
                    trackingNo: 1Z999AA10123456784
                    labelStatus: CREATED
                    labelDownloadURL: https://marketplace.walmartapis.com/v3/shipping/labels/1Z999AA10123456784
        '403':
          description: Forbidden
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 403 Forbidden
                  value:
                    message: This order does not belong to the specified integration
                      instance.
                example-1:
                  summary: 403 Missing Permission
                  value:
                    message: User does not have the right permissions.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: Failed to purchase shipping label from Walmart.
        '429': *id001
        '401': *id002
        '404': *id004
      operationId: post-api-walmart-integrationinstance-orders-order-shipping-labels
    get:
      tags:
      - Walmart
      summary: List Order Shipping Labels
      description: 'List the shipping labels purchased for an order.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      - name: order
        in: path
        schema:
          type: integer
        required: true
        description: Walmart order ID
        example: '60'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      labels:
                        type: array
                        items:
                          type: object
                          properties:
                            trackingNo:
                              type: string
                            carrierShortName:
                              type: string
                            labelStatus:
                              type: string
                example:
                  data:
                    labels:
                    - trackingNo: 1Z999AA10123456784
                      carrierShortName: UPS
                      labelStatus: CREATED
        '403':
          description: Forbidden
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: This order does not belong to the specified integration
                    instance.
        '429': *id001
        '401': *id002
        '404': *id004
      operationId: get-api-walmart-integrationinstance-orders-order-shipping-labels
  /api/walmart/{integrationInstance}/shipping/labels/{carrier}/{trackingNumber}/download:
    get:
      tags:
      - Walmart
      summary: Download Shipping Label
      description: 'Download a purchased shipping label as a PDF file. The response
        is the label document (Content-Type: application/pdf), not JSON.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      - name: carrier
        in: path
        schema:
          type: string
        required: true
        description: Carrier short name the label was purchased with
        example: UPS
      - name: trackingNumber
        in: path
        schema:
          type: string
        required: true
        description: Tracking number of the purchased label
        example: 1Z999AA10123456784
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/pdf
            Content-Disposition:
              schema:
                type: string
                example: attachment; filename="shipping-label-1Z999AA10123456784.pdf"
          content:
            text/plain:
              schema:
                type: string
                example: '%PDF-1.4 [binary PDF bytes — shipping label; not JSON]'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-walmart-integrationinstance-shipping-labels-carrier-trackingnumber-download
  /api/walmart/{integrationInstance}/shipping/labels/{carrier}/{trackingNumber}:
    delete:
      tags:
      - Walmart
      summary: Discard Shipping Label
      description: 'Discard (void) a purchased shipping label so it is no longer used
        or billed. No request body.


        Authentication: Requires Bearer token.


        Requires the `sales_orders.fulfill` permission.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      - name: carrier
        in: path
        schema:
          type: string
        required: true
        description: Carrier short name the label was purchased with
        example: UPS
      - name: trackingNumber
        in: path
        schema:
          type: string
        required: true
        description: Tracking number of the purchased label
        example: 1Z999AA10123456784
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      status:
                        type: string
                example:
                  data:
                    status: DISCARDED
        '403':
          description: Forbidden
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: User does not have the right permissions.
        '429': *id001
        '401': *id002
        '404': *id004
      operationId: delete-api-walmart-integrationinstance-shipping-labels-carrier-trackingnumber
  /api/walmart/{integrationInstance}/webhook-subscriptions:
    get:
      tags:
      - Walmart
      summary: List Webhook Subscriptions
      description: 'List the Walmart event subscriptions for this integration instance.
        Each record is the local mirror of a subscription registered with Walmart,
        including its event type, status, destination URL, and reconciliation state.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        subscription_id:
                          type: string
                        event_type:
                          type: string
                        event_version:
                          type: string
                        resource_name:
                          type: string
                        status:
                          type: string
                        destination_url:
                          type: string
                        last_reconciled_at:
                          type: string
                        last_error:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                example:
                  data:
                  - id: 1
                    subscription_id: 0e5fc5f5-7d19-4bd0-a1f3-59a3c1e7b2c4
                    event_type: PO_CREATED
                    event_version: V1
                    resource_name: ORDER
                    status: ACTIVE
                    destination_url: https://app.sku.io/webhooks/walmart/wh_abc123def456ghi789
                    last_reconciled_at: '2026-07-15T11:40:00+00:00'
                    last_error: null
                    created_at: '2026-07-15T09:00:00+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-walmart-integrationinstance-webhook-subscriptions
    post:
      tags:
      - Walmart
      summary: Create Webhook Subscription
      description: 'Create a webhook subscription so Walmart delivers event notifications
        for this integration instance. The subscription is registered with Walmart
        and mirrored locally.


        Fields:

        - event_type (string, required, max 100 characters): the Walmart event type
        to subscribe to, e.g. PO_CREATED.

        - event_version (string, optional): the event payload version; defaults to
        V1.

        - resource_name (string, optional): the resource the event relates to, e.g.
        ORDER.


        Authentication: Requires Bearer token.


        Requires the `integrations.update` permission.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                event_type:
                  type: string
                event_version:
                  type: string
                resource_name:
                  type: string
              example:
                event_type: PO_CREATED
                event_version: V1
                resource_name: ORDER
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      subscription_id:
                        type: string
                      event_type:
                        type: string
                      event_version:
                        type: string
                      resource_name:
                        type: string
                      status:
                        type: string
                      destination_url:
                        type: string
                      last_reconciled_at:
                        type: string
                        nullable: true
                      last_error:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                example:
                  data:
                    id: 2
                    subscription_id: 7c31a9d2-4e58-4f6b-9a10-2b8f0d3c5e77
                    event_type: PO_CREATED
                    event_version: V1
                    resource_name: ORDER
                    status: ACTIVE
                    destination_url: https://app.sku.io/webhooks/walmart/wh_abc123def456ghi789
                    last_reconciled_at: null
                    last_error: null
                    created_at: '2026-07-15T11:45:00+00:00'
        '403':
          description: Forbidden
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: User does not have the right permissions.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      event_type:
                        type: array
                        items:
                          type: string
                example:
                  message: The event type field is required.
                  errors:
                    event_type:
                    - The event type field is required.
        '429': *id001
        '401': *id002
        '404': *id004
      operationId: post-api-walmart-integrationinstance-webhook-subscriptions
  /api/walmart/{integrationInstance}/webhook-subscriptions/event-types:
    get:
      tags:
      - Walmart
      summary: List Available Event Types
      description: 'List the event types available for webhook subscription, fetched
        directly from Walmart.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      eventTypes:
                        type: array
                        items:
                          type: object
                          properties:
                            eventType:
                              type: string
                            eventVersion:
                              type: string
                            resourceName:
                              type: string
                example:
                  data:
                    eventTypes:
                    - eventType: PO_CREATED
                      eventVersion: V1
                      resourceName: ORDER
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: Failed to retrieve available event types from Walmart.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-walmart-integrationinstance-webhook-subscriptions-event-types
  /api/walmart/{integrationInstance}/webhook-subscriptions/auto-subscribe:
    post:
      tags:
      - Walmart
      summary: Auto-Subscribe Default Events
      description: 'Subscribe this integration instance to every default event type
        Walmart offers. Event types that are already subscribed are skipped. No request
        body.


        The response lists the event types that were subscribed, skipped, and failed,
        plus an errors map of event type to failure reason for each failed subscription.


        Authentication: Requires Bearer token.


        Requires the `integrations.update` permission.'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  subscribed:
                    type: array
                    items:
                      type: string
                  skipped:
                    type: array
                    items:
                      type: string
                  failed:
                    type: array
                    items:
                      type: string
                  errors:
                    type: object
                    properties:
                      PO_LINE_AUTOCANCELLED:
                        type: string
                example:
                  subscribed:
                  - PO_CREATED
                  skipped:
                  - OFFER_UNPUBLISHED
                  failed:
                  - PO_LINE_AUTOCANCELLED
                  errors:
                    PO_LINE_AUTOCANCELLED: Walmart returned HTTP 500 while creating
                      the subscription.
        '403':
          description: Forbidden
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: User does not have the right permissions.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: Failed to retrieve available event types from Walmart.
        '429': *id001
        '401': *id002
        '404': *id004
      operationId: post-api-walmart-integrationinstance-webhook-subscriptions-auto-subscribe
  /api/walmart/{integrationInstance}/webhook-subscriptions/reconcile:
    post:
      tags:
      - Walmart
      summary: Reconcile Webhook Subscriptions
      description: 'Reconcile the local subscription records against Walmart''s subscription
        registry and repair any drift. Subscriptions found on Walmart but missing
        locally are adopted, local records no longer present on Walmart are flagged
        as missing, and matching records are confirmed. No request body.


        Authentication: Requires Bearer token.


        Requires the `integrations.update` permission.'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  adopted:
                    type: integer
                  missing:
                    type: integer
                  confirmed:
                    type: integer
                example:
                  adopted: 0
                  missing: 1
                  confirmed: 4
        '403':
          description: Forbidden
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: User does not have the right permissions.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: Failed to retrieve webhook subscriptions from Walmart.
        '429': *id001
        '401': *id002
        '404': *id004
      operationId: post-api-walmart-integrationinstance-webhook-subscriptions-reconcile
  /api/walmart/{integrationInstance}/webhook-subscriptions/{subscription}:
    delete:
      tags:
      - Walmart
      summary: Delete Webhook Subscription
      description: 'Delete a webhook subscription on Walmart and remove the local
        record.


        Authentication: Requires Bearer token.


        Requires the `integrations.update` permission.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      - name: subscription
        in: path
        schema:
          type: integer
        required: true
        description: Webhook subscription ID
        example: '1'
      responses:
        '204':
          description: No Content
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            text/plain:
              schema:
                type: string
                example: ''
        '403':
          description: Forbidden
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 403 Forbidden
                  value:
                    message: This webhook subscription does not belong to the specified
                      integration instance.
                example-1:
                  summary: 403 Missing Permission
                  value:
                    message: User does not have the right permissions.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: Failed to delete the webhook subscription on Walmart.
        '429': *id001
        '401': *id002
        '404': *id004
      operationId: delete-api-walmart-integrationinstance-webhook-subscriptions-subscription
  /api/walmart/{integrationInstance}/webhook-subscriptions/{subscription}/test:
    post:
      tags:
      - Walmart
      summary: Send Test Notification
      description: 'Ask Walmart to deliver a test event notification for this subscription
        to its destination URL. Use this to verify the subscription is wired up end
        to end. No request body.


        Authentication: Requires Bearer token.


        Requires the `integrations.update` permission.'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      - name: subscription
        in: path
        schema:
          type: integer
        required: true
        description: Webhook subscription ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  eventType:
                    type: string
                  status:
                    type: string
                example:
                  eventType: PO_CREATED
                  status: SUCCESS
        '403':
          description: Forbidden
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 403 Forbidden
                  value:
                    message: This webhook subscription does not belong to the specified
                      integration instance.
                example-1:
                  summary: 403 Missing Permission
                  value:
                    message: User does not have the right permissions.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: Failed to send the test notification.
        '429': *id001
        '401': *id002
        '404': *id004
      operationId: post-api-walmart-integrationinstance-webhook-subscriptions-subscription-test
  /api/magento/{integration_instance}/download-orders:
    put:
      tags:
      - Magento
      summary: Download Orders
      description: 'Download Magento orders by increment_id. Dispatches a synchronous
        job to fetch the specified orders from Magento and create/update them in SKU.


        Authentication: Requires Bearer token with power user access.


        Request Body:

        - increment_ids (required, array): Array of Magento order increment IDs to
        download'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                increment_ids:
                  type: array
                  items:
                    type: string
              example:
                increment_ids:
                - '100000001'
                - '100000002'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Magento integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Successfully downloaded magento orders
        '422':
          description: Unprocessable Entity
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      increment_ids:
                        type: array
                        items:
                          type: string
                example:
                  message: The increment ids field is required.
                  errors:
                    increment_ids:
                    - The increment ids field is required.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: put-api-magento-integration-instance-download-orders
  /api/magento/{integration_instance}/download-products:
    put:
      tags:
      - Magento
      summary: Download Products
      description: 'Download Magento products by ID or SKU. Provide either ''ids''
        (entity_id) or ''skus'', not both.


        Authentication: Requires Bearer token with power user access.


        Request Body (at least one required):

        - ids (array): Array of Magento product entity IDs

        - skus (array): Array of Magento product SKUs'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 123
                - 456
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Magento integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Successfully downloaded magento products
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-magento-integration-instance-download-products
  /api/magento/{integration_instance}/inventory-sources:
    get:
      tags:
      - Magento
      summary: List Inventory Sources
      description: 'Returns the locally stored Magento inventory sources and the integration
        settings inventory sources for the given integration instance.


        Authentication: Requires Bearer token with power user access.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Magento integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      magentoSources:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            integration_instance_id:
                              type: integer
                            source_code:
                              type: string
                            name:
                              type: string
                            enabled:
                              type: boolean
                      inventorySources:
                        type: array
                        items:
                          type: object
                          properties:
                            source_code:
                              type: string
                            name:
                              type: string
                example:
                  data:
                    magentoSources:
                    - id: 1
                      integration_instance_id: 1
                      source_code: default
                      name: Default Source
                      enabled: true
                    inventorySources:
                    - source_code: default
                      name: Default Source
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-magento-integration-instance-inventory-sources
    post:
      tags:
      - Magento
      summary: Download Inventory Sources
      description: 'Downloads inventory sources from Magento API and stores them locally,
        then refreshes the integration instance settings. Returns the updated inventory
        sources list.


        Authentication: Requires Bearer token with power user access.'
      requestBody:
        content: {}
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Magento integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      magentoSources:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            integration_instance_id:
                              type: integer
                            source_code:
                              type: string
                            name:
                              type: string
                            enabled:
                              type: boolean
                      inventorySources:
                        type: array
                        items:
                          type: object
                          properties:
                            source_code:
                              type: string
                            name:
                              type: string
                example:
                  data:
                    magentoSources:
                    - id: 1
                      integration_instance_id: 1
                      source_code: default
                      name: Default Source
                      enabled: true
                    inventorySources:
                    - source_code: default
                      name: Default Source
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-magento-integration-instance-inventory-sources
  /api/magento/{integration_instance}/product-attributes:
    get:
      tags:
      - Magento
      summary: List Product Attributes
      description: 'Returns the Magento product attributes for the given integration
        instance.


        Authentication: Requires Bearer token with power user access.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Magento integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        attribute_code:
                          type: string
                        default_frontend_label:
                          type: string
                        attribute_id:
                          type: integer
                example:
                  data:
                  - attribute_code: color
                    default_frontend_label: Color
                    attribute_id: 93
                  - attribute_code: size
                    default_frontend_label: Size
                    attribute_id: 144
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-magento-integration-instance-product-attributes
  /api/tiktok-shop/config:
    get:
      tags:
      - TikTok Shop
      summary: Get Config
      description: 'Returns the public OAuth config (app_key, redirect_url) for the
        requested environment. the application UI uses this to build the TikTok authorization
        URL.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Query: environment (sandbox|production, default sandbox).


        Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      environment:
                        type: string
                      app_key:
                        type: string
                      redirect_url:
                        type: string
                example:
                  data:
                    environment: production
                    app_key: tt_app_key_xxx
                    redirect_url: https://app.sku.io/tiktok-shop/callback
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-tiktok-shop-config
  /api/tiktok-shop/oauth/init:
    get:
      tags:
      - TikTok Shop
      summary: OAuth Init
      description: 'Generates a state UUID, caches it for 15 minutes, and returns
        the TikTok authorization URL the user should be redirected to. Optionally
        accepts an integration_instance_id to re-link an existing instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      authorization_url:
                        type: string
                      state:
                        type: string
                example:
                  data:
                    authorization_url: https://services.tiktokshop.com/open/authorize?service_id=...&state=8c7...
                    state: 8c7e0d12-b91c-4d2b-a6f4-9c0a2bb1f0aa
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-tiktok-shop-oauth-init
  /api/tiktok-shop/integration-instances:
    get:
      tags:
      - TikTok Shop
      summary: List Integration Instances
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      description: 'List Integration Instances


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      operationId: get-api-tiktok-shop-integration-instances
  /api/tiktok-shop/integration-instances/{integration_instance_id}:
    get:
      tags:
      - TikTok Shop
      summary: Show Integration Instance
      description: 'Returns a single integration instance with integration and salesChannel
        relations.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Requires Bearer token.'
      parameters:
      - name: integration_instance_id
        in: path
        required: true
        schema:
          type: string
        description: The integration_instance_id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      integration_id:
                        type: integer
                      environment:
                        type: string
                      open_id:
                        type: string
                      seller_name:
                        type: string
                      has_access_token:
                        type: boolean
                      access_token_expires_at:
                        type: string
                      refresh_token_expires_at:
                        type: string
                      integration_settings:
                        type: object
                        properties:
                          submit_tracking:
                            type: boolean
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 12
                    name: Acme TikTok Shop
                    integration_id: 17
                    environment: production
                    open_id: '7211223344556677'
                    seller_name: Acme Co.
                    has_access_token: true
                    access_token_expires_at: '2026-05-26T10:00:00+00:00'
                    refresh_token_expires_at: '2027-04-26T10:00:00+00:00'
                    integration_settings:
                      submit_tracking: true
                    created_at: '2026-04-01T10:00:00.000000Z'
                    updated_at: '2026-04-26T10:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-tiktok-shop-integration-instances-integration-instance-id
    patch:
      tags:
      - TikTok Shop
      summary: Update Integration Instance
      description: 'Patch-update name and/or integration_settings. integration_settings
        is deep-merged into the existing JSON.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Fields:

        - name (sometimes, string, max 255)

        - integration_settings (sometimes, array)

        - integration_settings.* (nullable)


        Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                integration_settings:
                  type: object
                  properties:
                    submit_tracking:
                      type: boolean
                    default_warehouse_id:
                      type: integer
              example:
                name: Acme TikTok Shop (US)
                integration_settings:
                  submit_tracking: true
                  default_warehouse_id: 5
      parameters:
      - name: integration_instance_id
        in: path
        required: true
        schema:
          type: string
        description: The integration_instance_id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      integration_id:
                        type: integer
                      environment:
                        type: string
                      open_id:
                        type: string
                      seller_name:
                        type: string
                      has_access_token:
                        type: boolean
                      access_token_expires_at:
                        type: string
                      refresh_token_expires_at:
                        type: string
                      integration_settings:
                        type: object
                        properties:
                          submit_tracking:
                            type: boolean
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 12
                    name: Acme TikTok Shop
                    integration_id: 17
                    environment: production
                    open_id: '7211223344556677'
                    seller_name: Acme Co.
                    has_access_token: true
                    access_token_expires_at: '2026-05-26T10:00:00+00:00'
                    refresh_token_expires_at: '2027-04-26T10:00:00+00:00'
                    integration_settings:
                      submit_tracking: true
                    created_at: '2026-04-01T10:00:00.000000Z'
                    updated_at: '2026-04-26T10:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: patch-api-tiktok-shop-integration-instances-integration-instance-id
    delete:
      tags:
      - TikTok Shop
      summary: Delete Integration Instance
      description: 'Deletes the integration instance. Webhook unsubscribe is best-effort
        — local delete proceeds even on remote failure.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Requires Bearer token.'
      parameters:
      - name: integration_instance_id
        in: path
        required: true
        schema:
          type: string
        description: The integration_instance_id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      deleted:
                        type: boolean
                example:
                  data:
                    deleted: true
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-tiktok-shop-integration-instances-integration-instance-id
  /api/tiktok-shop/dashboard:
    get:
      tags:
      - TikTok Shop
      summary: Get Dashboard Metrics
      description: 'Aggregate dashboard metrics for one or many TikTok Shop connections:
        the connection summaries, synced entity counts (orders, products, returns,
        refunds, transactions, shops), a financial summary (gross/net revenue, refunds,
        units sold) for an optional period, and per-entity sync health.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Query parameters:**

        - `integration_instance_ids` (optional, comma-separated integers) — limit
        to specific connections; omit for all.

        - `period` (optional, one of `today`, `7d`, `30d`) — window for the financial
        summary; omit for all time. Invalid values return 422.


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      integrations:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            shop_url:
                              type: string
                            shop_name:
                              type: string
                            shop_id:
                              type: string
                            shop_cipher:
                              type: string
                            shop_region:
                              type: string
                            seller_id:
                              type: string
                            is_automatic_sync_enabled:
                              type: boolean
                            has_warehouse_mappings:
                              type: boolean
                            integration_settings:
                              type: object
                              properties:
                                orders_start_date:
                                  type: string
                            created_at:
                              type: string
                            updated_at:
                              type: string
                      entity_counts:
                        type: object
                        properties:
                          entities:
                            type: object
                            properties:
                              orders:
                                type: object
                                properties:
                                  display_name:
                                    type: string
                                  total:
                                    type: integer
                              products:
                                type: object
                                properties:
                                  display_name:
                                    type: string
                                  total:
                                    type: integer
                              returns:
                                type: object
                                properties:
                                  display_name:
                                    type: string
                                  total:
                                    type: integer
                              refunds:
                                type: object
                                properties:
                                  display_name:
                                    type: string
                                  total:
                                    type: integer
                              transactions:
                                type: object
                                properties:
                                  display_name:
                                    type: string
                                  total:
                                    type: integer
                              shops:
                                type: object
                                properties:
                                  display_name:
                                    type: string
                                  total:
                                    type: integer
                          totals:
                            type: object
                            properties:
                              total_records:
                                type: integer
                      financial_summary:
                        type: object
                        properties:
                          gross_revenue:
                            type: number
                          total_refunds:
                            type: number
                          net_revenue:
                            type: number
                          units_sold:
                            type: integer
                          units_refunded:
                            type: integer
                          net_units_sold:
                            type: integer
                          error:
                            type: string
                            nullable: true
                      sync_summary:
                        type: object
                        properties:
                          entities:
                            type: object
                            properties:
                              orders:
                                type: object
                                properties:
                                  last_synced_at:
                                    type: string
                                  is_healthy:
                                    type: boolean
                              products:
                                type: object
                                properties:
                                  last_synced_at:
                                    type: string
                                  is_healthy:
                                    type: boolean
                          overall_health:
                            type: object
                            properties:
                              status:
                                type: string
                              healthy_entities:
                                type: integer
                              total_entities:
                                type: integer
                              health_percentage:
                                type: integer
                          auto_sync:
                            type: object
                            properties:
                              is_enabled:
                                type: boolean
                              status_text:
                                type: string
                      generated_at:
                        type: string
                example:
                  success: true
                  data:
                    integrations:
                    - id: 12
                      name: TikTok Shop US
                      shop_url: https://seller-us.tiktok.com
                      shop_name: Acme Official Store
                      shop_id: '7495632100001'
                      shop_cipher: ROW_XXXXXXXXX
                      shop_region: US
                      seller_id: '7493311000002'
                      is_automatic_sync_enabled: true
                      has_warehouse_mappings: true
                      integration_settings:
                        orders_start_date: '2026-01-01'
                      created_at: '2026-03-02T18:20:00+00:00'
                      updated_at: '2026-06-20T08:00:00+00:00'
                    entity_counts:
                      entities:
                        orders:
                          display_name: orders
                          total: 1840
                        products:
                          display_name: products
                          total: 312
                        returns:
                          display_name: returns
                          total: 45
                        refunds:
                          display_name: refunds
                          total: 38
                        transactions:
                          display_name: transactions
                          total: 1720
                        shops:
                          display_name: shops
                          total: 1
                      totals:
                        total_records: 3956
                    financial_summary:
                      gross_revenue: 48210.55
                      total_refunds: 1120.4
                      net_revenue: 47090.15
                      units_sold: 2210
                      units_refunded: 0
                      net_units_sold: 2210
                      error: null
                    sync_summary:
                      entities:
                        orders:
                          last_synced_at: '2026-06-20T08:00:00+00:00'
                          is_healthy: true
                        products:
                          last_synced_at: '2026-06-20T07:45:00+00:00'
                          is_healthy: true
                      overall_health:
                        status: healthy
                        healthy_entities: 2
                        total_entities: 2
                        health_percentage: 100
                      auto_sync:
                        is_enabled: true
                        status_text: Auto sync enabled
                    generated_at: '2026-06-20T08:05:00+00:00'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  error:
                    type: string
                  message:
                    type: string
                example:
                  success: false
                  error: Invalid period
                  message: 'Period must be one of: today, 7d, 30d'
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-tiktok-shop-dashboard
  /api/tiktok-shop/integration-instances/{integration_instance_id}/shop-info:
    get:
      tags:
      - TikTok Shop
      summary: Get Shop Info
      description: 'Get the TikTok Shop metadata for a connection: shop name, id,
        cipher, region, seller id, and the authorizing seller''s account details captured
        during authorization.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance_id
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      shop_name:
                        type: string
                      shop_id:
                        type: string
                      shop_cipher:
                        type: string
                      region:
                        type: string
                      seller_id:
                        type: string
                      main_account_open_id:
                        type: string
                      seller_name:
                        type: string
                example:
                  success: true
                  data:
                    shop_name: Acme Official Store
                    shop_id: '7495632100001'
                    shop_cipher: ROW_XXXXXXXXX
                    region: US
                    seller_id: '7493311000002'
                    main_account_open_id: '7405118000003'
                    seller_name: Acme Inc
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-tiktok-shop-integration-instances-integration-instance-id-shop-info
  /api/tiktok-shop/integration-instances/{integration_instance_id}/access-scopes:
    get:
      tags:
      - TikTok Shop
      summary: List Access Scopes
      description: 'List the TikTok Shop API permission scopes granted to this connection
        during authorization, each with a human-readable description. Use this to
        verify the connection has the permissions a feature needs (orders, products,
        fulfillment, logistics, finance, returns, webhooks).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance_id
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      scopes:
                        type: array
                        items:
                          type: object
                          properties:
                            handle:
                              type: string
                            description:
                              type: string
                      total:
                        type: integer
                example:
                  success: true
                  data:
                    scopes:
                    - handle: order.list
                      description: Read and write order data
                    - handle: product.list
                      description: Read and write product data
                    - handle: seller.fulfillment.basic
                      description: Manage fulfillment and shipping for orders
                    - handle: seller.logistics
                      description: Manage logistics and warehouse data
                    total: 4
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-tiktok-shop-integration-instances-integration-instance-id-access-scopes
  /api/tiktok-shop/orders:
    get:
      tags:
      - TikTok Shop
      summary: List Orders
      description: 'Spatie QueryBuilder paginated list of TikTok Shop orders across
        instances. Allowed filters: integration_instance_ids, status (TikTok Shop
        single-axis enum: UNPAID|ON_HOLD|AWAITING_SHIPMENT|PARTIALLY_SHIPPING|AWAITING_COLLECTION|IN_TRANSIT|DELIVERED|COMPLETED|CANCELLED),
        fulfillment_method, currency, payment_method_name, cancelled, archived, status_state
        (active|archived|all), search (matches tiktok_order_id/buyer_email/recipient_name),
        date_from, date_to. Allowed sorts: id, tiktok_order_id, status, total_amount,
        tiktok_create_time, tiktok_update_time, tiktok_paid_time, last_sync_at, created_at,
        updated_at. Default sort: -tiktok_create_time. per_page defaults to 10.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: filter[integration_instance_ids]
        in: query
        schema:
          type: string
        example: '{{integration_instance_id}}'
        description: Filter by integration instance ids (see the Filtering & Sorting
          guide for operators).
      - name: per_page
        in: query
        schema:
          type: integer
        example: '10'
        description: Results per page (default 10).
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-tiktok-shop-orders
  /api/tiktok-shop/orders/{order_id}:
    get:
      tags:
      - TikTok Shop
      summary: Show Order
      description: 'Returns a single TikTok Shop order with lineItems and packages
        eager-loaded.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Requires Bearer token.'
      parameters:
      - name: order_id
        in: path
        required: true
        schema:
          type: string
        description: The order_id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      tiktok_order_id:
                        type: string
                      status:
                        type: string
                      fulfillment_method:
                        type: string
                      payment_method_name:
                        type: string
                      currency:
                        type: string
                      subtotal_amount:
                        type: number
                      discount_amount:
                        type: number
                      shipping_amount:
                        type: number
                      tax_amount:
                        type: number
                      total_amount:
                        type: number
                      buyer_email:
                        type: string
                      recipient_name:
                        type: string
                      shipping_address:
                        type: object
                        properties:
                          address_line1:
                            type: string
                          city:
                            type: string
                          state:
                            type: string
                          zip:
                            type: string
                          country:
                            type: string
                      raw_payload:
                        type: object
                        properties:
                          id:
                            type: string
                      tiktok_create_time:
                        type: string
                      tiktok_update_time:
                        type: string
                      tiktok_paid_time:
                        type: string
                      tracking_submitted_at:
                        type: string
                        nullable: true
                      archived_at:
                        type: string
                        nullable: true
                      last_sync_at:
                        type: string
                      line_items:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            tiktok_line_item_id:
                              type: string
                            tiktok_product_id:
                              type: string
                            tiktok_sku_id:
                              type: string
                            product_name:
                              type: string
                            sku_name:
                              type: string
                            seller_sku:
                              type: string
                            package_id:
                              type: string
                            quantity:
                              type: integer
                            unit_price:
                              type: number
                            item_status:
                              type: string
                      packages:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            package_id:
                              type: string
                            tracking_number:
                              type: string
                              nullable: true
                            shipping_provider_name:
                              type: string
                              nullable: true
                            package_status:
                              type: string
                            shipped_at:
                              type: string
                              nullable: true
                            delivered_at:
                              type: string
                              nullable: true
                example:
                  data:
                    id: 100
                    integration_instance_id: 12
                    tiktok_order_id: '576461413164253045'
                    status: AWAITING_SHIPMENT
                    fulfillment_method: fulfillment_by_seller
                    payment_method_name: PayPal
                    currency: USD
                    subtotal_amount: 49.99
                    discount_amount: 5.0
                    shipping_amount: 4.99
                    tax_amount: 3.5
                    total_amount: 53.48
                    buyer_email: buyer@example.com
                    recipient_name: Jane Doe
                    shipping_address:
                      address_line1: 123 Main St
                      city: Austin
                      state: TX
                      zip: '78701'
                      country: US
                    raw_payload:
                      id: '576461413164253045'
                    tiktok_create_time: '2026-04-25T08:00:00+00:00'
                    tiktok_update_time: '2026-04-26T09:00:00+00:00'
                    tiktok_paid_time: '2026-04-25T08:01:00+00:00'
                    tracking_submitted_at: null
                    archived_at: null
                    last_sync_at: '2026-04-26T09:05:00+00:00'
                    line_items:
                    - id: 200
                      tiktok_line_item_id: '576461413180000000'
                      tiktok_product_id: '1729384756102938'
                      tiktok_sku_id: '1729384756102939'
                      product_name: Wireless Earbuds
                      sku_name: Black / Standard
                      seller_sku: EAR-BLK-STD
                      package_id: '576461413200000000'
                      quantity: 1
                      unit_price: 49.99
                      item_status: UNSHIPPED
                    packages:
                    - id: 300
                      package_id: '576461413200000000'
                      tracking_number: null
                      shipping_provider_name: null
                      package_status: TO_FULFILL
                      shipped_at: null
                      delivered_at: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-tiktok-shop-orders-order-id
  /api/tiktok-shop/integration-instances/{integration_instance_id}/orders/{order_id}/raw:
    get:
      tags:
      - TikTok Shop
      summary: Get Raw Order from TikTok
      description: 'Fetches the live order JSON directly from the TikTok Shop API
        (`/order/202309/orders?ids=...`) for a single previously-synced order. Mirrors
        the Shopify `getRawOrderFromShopify` pattern — used by the frontend Raw Data
        section as a fetch-on-demand tool to inspect the current upstream payload
        without writing it to the database.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Path params:

        - `tikTokShopIntegrationInstance` (required) — integration instance id.

        - `tikTokShopOrder` (required) — local TikTokShopOrder id.


        Returns: `{ data: <raw TikTok Shop order object> | null }`. `data` is the
        first element from the upstream `orders` array, or `null` if not found.'
      parameters:
      - name: integration_instance_id
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: order_id
        in: path
        schema:
          type: string
        required: true
        description: The order ID.
      responses:
        '200':
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: Success
                  value:
                    data:
                      id: '576461413038489876'
                      buyer_email: buyer@example.com
                      status: AWAITING_SHIPMENT
                      payment:
                        currency: USD
                        total_amount: '42.99'
                        sub_total: '39.99'
                        shipping_fee: '3.00'
                      line_items:
                      - id: 576461413038489876-1
                        product_name: Sample Product
                        sku_name: Default
                        seller_sku: ABC-123
                        quantity: 1
                        sale_price: '39.99'
                      create_time: 1745164200
                      update_time: 1745250720
                example-1:
                  summary: Not Found / Empty
                  value:
                    data: null
          description: Successful response
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-tiktok-shop-integration-instances-integration-instance-id-orders-order-id-raw
  /api/tiktok-shop/integration-instances/{integration_instance_id}/orders/refresh:
    post:
      tags:
      - TikTok Shop
      summary: Refresh Orders from TikTok
      description: 'Dispatches a tracked job to pull recent orders from TikTok Shop.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Accepts (all optional, all dates):

        - `updated_at` — fetch orders updated since this datetime (preferred)

        - `created_at_min` — fetch orders created since this datetime

        - `since` — legacy alias for `updated_at`


        The controller picks the first non-null in the order: `updated_at` → `created_at_min`
        → `since`. If none provided, defaults to last 24 hours.


        Returns `{ data: { tracked_job_log_id }, message }` — track progress via the
        tracked job log endpoints.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                updated_at:
                  type: string
                created_at_min:
                  type: string
                  nullable: true
                since:
                  type: string
                  nullable: true
              example:
                updated_at: '2026-04-01T00:00:00Z'
                created_at_min: null
                since: null
      parameters:
      - name: integration_instance_id
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 4521
                  message: Order refresh queued.
          description: Successful response
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-tiktok-shop-integration-instances-integration-instance-id-orders-refresh
  /api/tiktok-shop/integration-instances/{integration_instance_id}/orders/refresh-one:
    post:
      tags:
      - TikTok Shop
      summary: Refresh Single Order
      description: 'Re-syncs a single order by TikTok order ID.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Body:

        - `uniqueId` (required, string) — the TikTok order ID to refresh.


        Note: TikTok Shop''s API does not currently support fetching a single order
        by ID, so this dispatches a 30-day a background job as a workaround. The targeted
        order will be re-synced as part of that window.


        Returns `{ data: { tracked_job_log_id }, message }`.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                uniqueId:
                  type: string
              example:
                uniqueId: '576461413038489876'
      parameters:
      - name: integration_instance_id
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 4522
                  message: Order refresh queued.
          description: Successful response
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-tiktok-shop-integration-instances-integration-instance-id-orders-refresh-one
  /api/tiktok-shop/integration-instances/{integration_instance_id}/orders/search:
    get:
      tags:
      - TikTok Shop
      summary: Search Orders (Local DB)
      description: 'Searches LOCAL DB for already-synced TikTok Shop orders. Unlike
        Shopify''s equivalent endpoint, this does NOT hit the TikTok Shop API — TikTok''s
        API does not currently support free-text order search. Use this to find orders
        already synced into SKU.io and re-trigger an update via Refresh Single Order.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Query params:

        - `search_by` (required, string) — `order_number`, `tiktok_order_id`, or `email`.
        Defaults to `order_number`.

        - `query` (required, string) — the search term.


        Returns: `{ data: [{ id, legacy_resource_id, name, email, status, tiktok_create_time,
        tiktok_update_time, total_price, currency, exists_in_database, database_id
        }], total }`. `status` is the TikTok Shop single-axis order status enum.'
      parameters:
      - name: search_by
        in: query
        schema:
          type: string
        description: 'One of: order_number, tiktok_order_id, email. Defaults to order_number.'
        example: order_number
      - name: query
        in: query
        schema:
          type: integer
        description: Search term — order ID or buyer email.
        example: '576461413038489876'
      - name: integration_instance_id
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        legacy_resource_id:
                          type: string
                        name:
                          type: string
                        email:
                          type: string
                        status:
                          type: string
                        tiktok_create_time:
                          type: string
                        tiktok_update_time:
                          type: string
                        total_price:
                          type: string
                        currency:
                          type: string
                        exists_in_database:
                          type: boolean
                        database_id:
                          type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 12345
                    legacy_resource_id: '576461413038489876'
                    name: '#576461413038489876'
                    email: buyer@example.com
                    status: AWAITING_SHIPMENT
                    tiktok_create_time: '2026-04-20T15:30:00Z'
                    tiktok_update_time: '2026-04-21T09:12:00Z'
                    total_price: '42.99'
                    currency: USD
                    exists_in_database: true
                    database_id: 12345
                  total: 1
          description: Successful response
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-tiktok-shop-integration-instances-integration-instance-id-orders-search
  /api/tiktok-shop/integration-instances/{integration_instance_id}/orders/{order_id}/submit-tracking:
    post:
      tags:
      - TikTok Shop
      summary: Submit Tracking
      description: 'Dispatches a background job to push tracking numbers up to TikTok
        for the order''s packages. Returns a tracked_job_log_id.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties: {}
              example: {}
      parameters:
      - name: integration_instance_id
        in: path
        required: true
        schema:
          type: string
        description: The integration_instance_id identifier
      - name: order_id
        in: path
        required: true
        schema:
          type: string
        description: The order_id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 9877
                  message: Tracking submission queued.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-tiktok-shop-integration-instances-integration-instance-id-orders-order-id-submit-tracking
  /api/tiktok-shop/integration-instances/{integration_instance_id}/shipping-providers:
    get:
      tags:
      - TikTok Shop
      summary: List Shipping Providers
      description: 'Returns the list of TikTok-recognized shipping providers for the
        instance (used to populate dropdowns in the shipping method mapping UI).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Requires Bearer token.'
      parameters:
      - name: integration_instance_id
        in: path
        required: true
        schema:
          type: string
        description: The integration_instance_id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: string
                        name:
                          type: string
                example:
                  data:
                  - id: '7208012345678'
                    name: USPS
                  - id: '7208087654321'
                    name: FedEx
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-tiktok-shop-integration-instances-integration-instance-id-shipping-providers
  /api/tiktok-shop/integration-instances/{integration_instance_id}/orders/latest-sync-info:
    get:
      tags:
      - TikTok Shop
      summary: Get Latest Sync Info
      description: 'Returns sync metadata: latest_order_name, latest_order_date, sync_cursor_at,
        total_orders, last_sync_at.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integration_instance_id
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-tiktok-shop-integration-instances-integration-instance-id-orders-latest-sync-info
  /api/tiktok-shop/integration-instances/{integration_instance_id}/orders/{order_id}/archive:
    post:
      tags:
      - TikTok Shop
      summary: Archive Order
      description: 'Soft-archives a TikTok Shop order. Sets archived_at timestamp.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters:
      - name: integration_instance_id
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: order_id
        in: path
        schema:
          type: string
        required: true
        description: The order ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-tiktok-shop-integration-instances-integration-instance-id-orders-order-id-archive
  /api/tiktok-shop/integration-instances/{integration_instance_id}/orders/{order_id}/unarchive:
    post:
      tags:
      - TikTok Shop
      summary: Unarchive Order
      description: 'Restores a previously archived TikTok Shop order. Clears archived_at.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters:
      - name: integration_instance_id
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: order_id
        in: path
        schema:
          type: string
        required: true
        description: The order ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-tiktok-shop-integration-instances-integration-instance-id-orders-order-id-unarchive
  /api/tiktok-shop/integration-instances/{integration_instance_id}/orders/bulk-archive:
    post:
      tags:
      - TikTok Shop
      summary: Bulk Archive Orders
      description: 'Bulk-archives orders. Either pass an explicit `ids` array, or
        `apply_to_all: true` with the current `filters` object to archive every matching
        order. Returns archived_count.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1
                - 2
                - 3
      parameters:
      - name: integration_instance_id
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-tiktok-shop-integration-instances-integration-instance-id-orders-bulk-archive
  /api/tiktok-shop/integration-instances/{integration_instance_id}/orders/bulk-unarchive:
    post:
      tags:
      - TikTok Shop
      summary: Bulk Unarchive Orders
      description: 'Bulk-unarchives orders. Either pass an explicit `ids` array, or
        `apply_to_all: true` with the current `filters` object. Returns unarchived_count.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1
                - 2
                - 3
      parameters:
      - name: integration_instance_id
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-tiktok-shop-integration-instances-integration-instance-id-orders-bulk-unarchive
  /api/tiktok-shop/integration-instances/{integration_instance_id}/orders/{order_id}:
    delete:
      tags:
      - TikTok Shop
      summary: Delete Order
      description: 'Permanently deletes a TikTok Shop order from SKU.io (does not
        affect TikTok).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integration_instance_id
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: order_id
        in: path
        schema:
          type: string
        required: true
        description: The order ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-tiktok-shop-integration-instances-integration-instance-id-orders-order-id
  /api/tiktok-shop/integration-instances/{integration_instance_id}/orders/bulk-delete:
    post:
      tags:
      - TikTok Shop
      summary: Bulk Delete Orders
      description: 'Bulk-deletes orders. Either pass an explicit `ids` array, or `apply_to_all:
        true` with the current `filters` object. Returns deleted_count.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1
                - 2
                - 3
      parameters:
      - name: integration_instance_id
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-tiktok-shop-integration-instances-integration-instance-id-orders-bulk-delete
  /api/tiktok-shop/integration-instances/{integration_instance_id}/orders/create-sku-orders:
    post:
      tags:
      - TikTok Shop
      summary: Create SKU Orders from TikTok Shop
      description: 'Create SKU sales orders from TikTok Shop orders. Mirrors the Shopify
        endpoint. Supports three request shapes:


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        1. `create_all_orders: true` — "Create All" header button: creates SKU orders
        for ALL pending TikTok Shop orders (no filters).

        2. `apply_to_all: true, filters: {...}` — bulk toolbar with "All" scope: creates
        SKU orders for filtered pending orders.

        3. `ids: [...]` — bulk toolbar with specific selected orders.


        Only TikTok Shop orders that don''t already have a linked SalesOrder and aren''t
        archived are eligible. Returns the count of orders processed. TODO: For large
        batches a tracked job should be dispatched (currently runs synchronously).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1
                - 2
                - 3
      parameters:
      - name: integration_instance_id
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  total_orders:
                    type: integer
                  tracked_job_log_id:
                    type: string
                    nullable: true
                example:
                  message: 3 SKU orders created successfully
                  total_orders: 3
                  tracked_job_log_id: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-tiktok-shop-integration-instances-integration-instance-id-orders-create-sku-orders
  /api/tiktok-shop/integration-instances/{integration_instance_id}/orders/update-sku-orders:
    post:
      tags:
      - TikTok Shop
      summary: Update SKU Orders from TikTok Shop
      description: 'Update existing SKU sales orders from their linked TikTok Shop
        orders. Re-derives the SalesOrder DTO and persists changes. Only TikTok Shop
        orders that already have a linked SalesOrder are eligible. Pass either `ids:
        [...]` for a specific subset, or `update_all_orders: true` (optionally with
        `filters: {...}`). The `use_jobs` flag is accepted for parity with Shopify
        but is currently ignored — TikTok always runs synchronously.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
                update_all_orders:
                  type: boolean
                use_jobs:
                  type: boolean
              example:
                ids:
                - 1
                - 2
                - 3
                update_all_orders: false
                use_jobs: false
      parameters:
      - name: integration_instance_id
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  total_orders:
                    type: integer
                example:
                  message: 3 SKU orders updated successfully
                  total_orders: 3
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-tiktok-shop-integration-instances-integration-instance-id-orders-update-sku-orders
  /api/tiktok-shop/integration-instances/{integration_instance_id}/orders/{order_id}/sku-order:
    delete:
      tags:
      - TikTok Shop
      summary: Delete Linked SKU Order
      description: 'Delete the SKU sales order linked to a single TikTok Shop order.
        The TikTok Shop order itself is kept intact. Pass `archive_tiktok_shop_order=true`
        to additionally archive the TikTok Shop order so it won''t be re-created on
        the next sync. Returns 404 if no SKU order is linked.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integration_instance_id
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: order_id
        in: path
        schema:
          type: string
        required: true
        description: The order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  archived_tiktok_shop_order:
                    type: boolean
                example:
                  message: SKU order deleted successfully
                  archived_tiktok_shop_order: false
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: No SKU order linked to this TikTok Shop order
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: delete-api-tiktok-shop-integration-instances-integration-instance-id-orders-order-id-sku-order
  /api/tiktok-shop/integration-instances/{integration_instance_id}/orders/bulk-delete-sku-orders:
    post:
      tags:
      - TikTok Shop
      summary: Bulk Delete Linked SKU Orders
      description: 'Bulk-delete the SKU sales orders linked to the given TikTok Shop
        orders. The TikTok Shop orders themselves are kept intact unless `archive_tiktok_shop_orders=true`
        is passed. Pass either an explicit `ids` array, or `apply_to_all: true` with
        the current `filters` object. Returns the deleted count. TODO: For large batches
        a tracked job should be dispatched (currently runs synchronously, mirroring
        Shopify''s a background job).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
                archive_tiktok_shop_orders:
                  type: boolean
              example:
                ids:
                - 1
                - 2
                - 3
                archive_tiktok_shop_orders: false
      parameters:
      - name: integration_instance_id
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  total_orders:
                    type: integer
                  tracked_job_log_id:
                    type: string
                    nullable: true
                example:
                  message: 3 SKU orders deleted successfully
                  total_orders: 3
                  tracked_job_log_id: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-tiktok-shop-integration-instances-integration-instance-id-orders-bulk-delete-sku-orders
  /api/tiktok-shop/integration-instances/{integration_instance_id}/pre-start-date-orders:
    get:
      tags:
      - TikTok Shop
      summary: Query Pre-Start-Date Orders
      description: 'Query TikTok Shop for orders predating the inventory start date
        in a given window.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Query params:

        - `created_at_min` (required, date)

        - `created_at_max` (optional, date, after_or_equal:created_at_min)

        - `status` (optional, one of: any, UNPAID, AWAITING_SHIPMENT, AWAITING_COLLECTION,
        PARTIALLY_SHIPPING, IN_TRANSIT, DELIVERED, COMPLETED, CANCELLED)'
      parameters:
      - name: created_at_min
        in: query
        schema:
          type: string
        example: '2024-01-01'
      - name: integration_instance_id
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-tiktok-shop-integration-instances-integration-instance-id-pre-start-date-orders
  /api/tiktok-shop/integration-instances/{integration_instance_id}/pre-start-date-orders/search:
    get:
      tags:
      - TikTok Shop
      summary: Search Pre-Start-Date Orders
      description: 'Search TikTok Shop for a specific pre-start-date order by ID or
        buyer email.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Query params:

        - `search_by` (required, one of: order_id, email)

        - `search_term` (required, max 255 chars)'
      parameters:
      - name: search_by
        in: query
        schema:
          type: string
        example: order_id
      - name: search_term
        in: query
        schema:
          type: integer
        example: '576461413038489876'
      - name: integration_instance_id
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-tiktok-shop-integration-instances-integration-instance-id-pre-start-date-orders-search
  /api/tiktok-shop/integration-instances/{integration_instance_id}/pre-start-date-orders/import:
    post:
      tags:
      - TikTok Shop
      summary: Import Pre-Start-Date Orders
      description: 'Import selected pre-start-date orders from TikTok Shop by their
        TikTok order ids. Each order is fetched from the TikTok Shop API and stored,
        flagged as a pre-start-date import.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Because each order requires its own throttled TikTok Shop API call, the import
        runs asynchronously as a queued background job. The request returns immediately
        with a tracked job log id that can be polled to follow the import''s progress.


        **Requires `inventory_start_date` to be set** — returns 422 otherwise.


        **Request Body:**

        - `tiktok_order_ids` (required, array of strings, 1-10,000 entries, each a
        TikTok order id string up to 100 chars)


        **Response:**

        - `data.tracked_job_log_id` - id of the tracked job log; poll it to follow
        import progress

        - `message` - human-readable confirmation of how many orders are being imported'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                tiktok_order_ids:
                  type: array
                  items:
                    type: string
              example:
                tiktok_order_ids:
                - '576461413038489876'
                - '576461413038489877'
      parameters:
      - name: integration_instance_id
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 4821
                  message: Importing 2 pre-start-date orders.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-tiktok-shop-integration-instances-integration-instance-id-pre-start-date-orders-import
  /api/tiktok-shop/products:
    get:
      tags:
      - TikTok Shop
      summary: List Products
      parameters:
      - name: filter[integration_instance_ids]
        in: query
        schema:
          type: string
        example: '{{integration_instance_id}}'
        description: Filter by integration instance ids (see the Filtering & Sorting
          guide for operators).
      - name: include
        in: query
        schema:
          type: string
        example: skus
      - name: per_page
        in: query
        schema:
          type: integer
        example: '15'
        description: Results per page (default 10).
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      description: 'List Products


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      operationId: get-api-tiktok-shop-products
  /api/tiktok-shop/products/skus:
    get:
      tags:
      - TikTok Shop
      summary: List Product SKUs (Flattened Mapping List)
      description: 'Flattened one-row-per-SKU product list — the Shopify-parity product-mapping
        table. Unlike **List Products** (one row per TikTok product), each row here
        is a single `TikTokShopProductSku` variant carrying its own mapping block
        (`product`, `sku_product`, `subscription_offering`, `mapped_at`, `mapped_sku`),
        so the shared frontend mapped-product column renders 1:1 exactly as it does
        for Shopify variants.


        Requires a Bearer token.


        **Pagination:** `page` (1-indexed), `per_page` (default 10).

        **Default sort:** `-updated_at`. Allowed sorts: id, seller_sku, tiktok_sku_id,
        name, inventory_quantity, price, inventory_synced_at, archived_at, created_at,
        updated_at (prefix with `-` for descending).


        **Archived behaviour:** archived SKUs are excluded by default. Supply `filter[archived]`
        to change this — `archived`/`true`/`1` returns only archived SKUs, `all` returns
        both.


        **Filters:**

        - `filter[integration_instance_ids]` — comma-separated TikTok integration-instance
        IDs.

        - `filter[seller_sku]` — partial match on the seller SKU.

        - `filter[tiktok_sku_id]` — partial match on the TikTok SKU id.

        - `filter[name]` — partial match on the variant name.

        - `filter[mapped_sku]` — partial match on the mapped SKU.io product SKU.

        - `filter[mapping_status]` — `mapped` or `unmapped`.

        - `filter[mapped]` — boolean; `true` = mapped only, `false` = unmapped only.

        - `filter[archived]` — see Archived behaviour above.

        - `filter[search]` — free-text across id, seller_sku, tiktok_sku_id, name,
        and parent product title.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: filter[integration_instance_ids]
        in: query
        schema:
          type: string
        description: Comma-separated TikTok integration-instance IDs to scope to.
        example: '{{integration_instance_id}}'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        tiktok_shop_product_id:
                          type: integer
                        tiktok_sku_id:
                          type: string
                        seller_sku:
                          type: string
                        name:
                          type: string
                        price:
                          type: number
                        inventory_quantity:
                          type: integer
                        inventory_synced_at:
                          type: string
                        archived_at:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                        updated_at:
                          type: string
                        tiktok_product_id:
                          type: string
                        product_title:
                          type: string
                        product_status:
                          type: string
                        main_image_url:
                          type: string
                        product_listing_id:
                          type: integer
                        product:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            sku:
                              type: string
                            listing_id:
                              type: integer
                            default_financial_line_type_id:
                              type: integer
                            default_financial_line_type:
                              type: object
                              properties:
                                id:
                                  type: integer
                                name:
                                  type: string
                                classification:
                                  type: string
                        subscription_offering:
                          type: string
                          nullable: true
                        mapped_at:
                          type: string
                        mapped_sku:
                          type: string
                        sku_product:
                          type: object
                          properties:
                            id:
                              type: integer
                            sku:
                              type: string
                            name:
                              type: string
                            barcode:
                              type: string
                            price:
                              type: number
                            type:
                              type: string
                            default_financial_line_type_id:
                              type: integer
                            default_financial_line_type:
                              type: object
                              properties:
                                id:
                                  type: integer
                                name:
                                  type: string
                                classification:
                                  type: string
                  current_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  last_page:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                  first_page_url:
                    type: string
                  last_page_url:
                    type: string
                  next_page_url:
                    type: string
                    nullable: true
                  prev_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                example:
                  data:
                  - id: 4412
                    integration_instance_id: 7
                    tiktok_shop_product_id: 883
                    tiktok_sku_id: '1729578451203841001'
                    seller_sku: TEE-RED-L
                    name: Classic Tee / Red / L
                    price: 24.99
                    inventory_quantity: 132
                    inventory_synced_at: '2026-07-02T09:14:22.000000Z'
                    archived_at: null
                    created_at: '2026-05-11T18:02:10.000000Z'
                    updated_at: '2026-07-02T09:14:22.000000Z'
                    tiktok_product_id: '1729511000000112233'
                    product_title: Classic Cotton Tee
                    product_status: ACTIVATE
                    main_image_url: https://p16-oec-va.ibyteimg.com/tos-maliva/classic-tee.jpeg
                    product_listing_id: 55231
                    product:
                      id: 90233
                      name: Classic Tee Red Large
                      sku: SKU-TEE-RED-L
                      listing_id: 55231
                      default_financial_line_type_id: 4
                      default_financial_line_type:
                        id: 4
                        name: Product Sales
                        classification: income
                    subscription_offering: null
                    mapped_at: '2026-06-20T12:41:03.000000Z'
                    mapped_sku: SKU-TEE-RED-L
                    sku_product:
                      id: 90233
                      sku: SKU-TEE-RED-L
                      name: Classic Tee Red Large
                      barcode: '0641243100000'
                      price: 24.99
                      type: standard
                      default_financial_line_type_id: 4
                      default_financial_line_type:
                        id: 4
                        name: Product Sales
                        classification: income
                  - id: 4413
                    integration_instance_id: 7
                    tiktok_shop_product_id: 883
                    tiktok_sku_id: '1729578451203841002'
                    seller_sku: TEE-BLU-M
                    name: Classic Tee / Blue / M
                    price: 24.99
                    inventory_quantity: 0
                    inventory_synced_at: '2026-07-02T09:14:22.000000Z'
                    archived_at: null
                    created_at: '2026-05-11T18:02:10.000000Z'
                    updated_at: '2026-07-02T09:14:22.000000Z'
                    tiktok_product_id: '1729511000000112233'
                    product_title: Classic Cotton Tee
                    product_status: ACTIVATE
                    main_image_url: https://p16-oec-va.ibyteimg.com/tos-maliva/classic-tee.jpeg
                    product_listing_id: null
                    product: null
                    subscription_offering: null
                    mapped_at: null
                    mapped_sku: null
                    sku_product: null
                  current_page: 1
                  per_page: 10
                  total: 2
                  last_page: 1
                  from: 1
                  to: 2
                  first_page_url: '{{protocol}}://{{domain}}/api/tiktok-shop/products/skus?page=1'
                  last_page_url: '{{protocol}}://{{domain}}/api/tiktok-shop/products/skus?page=1'
                  next_page_url: null
                  prev_page_url: null
                  path: '{{protocol}}://{{domain}}/api/tiktok-shop/products/skus'
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-tiktok-shop-products-skus
  /api/tiktok-shop/products/{product_id}:
    get:
      tags:
      - TikTok Shop
      summary: Show Product
      description: 'Returns a single TikTok Shop product with skus and shop eager-loaded.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Requires Bearer token.'
      parameters:
      - name: product_id
        in: path
        required: true
        schema:
          type: string
        description: The product_id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      tiktok_product_id:
                        type: string
                      title:
                        type: string
                      status:
                        type: string
                      skus:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            seller_sku:
                              type: string
                      shop:
                        type: object
                        properties:
                          id:
                            type: integer
                          shop_id:
                            type: string
                          name:
                            type: string
                example:
                  data:
                    id: 500
                    integration_instance_id: 12
                    tiktok_product_id: '1729384756102938'
                    title: Wireless Earbuds
                    status: ACTIVATE
                    skus:
                    - id: 800
                      seller_sku: EAR-BLK-STD
                    shop:
                      id: 5
                      shop_id: '7494838299'
                      name: Acme US
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-tiktok-shop-products-product-id
  /api/tiktok-shop/integration-instances/{integration_instance_id}/products/sync:
    post:
      tags:
      - TikTok Shop
      summary: Sync Products (Tracked)
      description: 'Dispatches a background job to fetch all products for the instance.
        Returns a tracked_job_log_id.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties: {}
              example: {}
      parameters:
      - name: integration_instance_id
        in: path
        required: true
        schema:
          type: string
        description: The integration_instance_id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 9878
                  message: Product sync started.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-tiktok-shop-integration-instances-integration-instance-id-products-sync
  /api/tiktok-shop/integration-instances/{integration_instance_id}/products/skus/{product_sku_id}/smart-match:
    post:
      tags:
      - TikTok Shop
      summary: Smart Match SKU to SKU.io Products
      description: 'Suggest SKU.io Products to map a TikTok Shop SKU (TikTokShopProductSku)
        to, before the user maps it. Mirrors Shopify''s smart-match, but operates
        at TikTok''s per-SKU listing grain (Shopify matches per-variant).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        The endpoint is keyed on the flattened SKU row (`{{product_sku_id}}` — the
        `id` returned by List Product SKUs). No request body: matching is derived
        from the SKU''s `seller_sku`, its variant `name`, and the parent product `title`.


        Match tiers returned in `data`:

        - `exact_match` — a non-archived SKU.io Product whose `sku` exactly equals
        the TikTok `seller_sku` (`match_type` = `sku`). Null when none.

        - `barcode_match` — **always null** for TikTok Shop: TikTok SKUs carry no
        barcode. The key is retained purely so the shared frontend mapping modal renders
        identically to Shopify''s.

        - `similar_matches` — up to 5 non-archived fuzzy matches (LIKE on `name`/`sku`,
        plus the first three >2-char words of the parent title), excluding the exact
        match (`match_type` = `fuzzy`).


        Returns 403 if the SKU does not belong to the given integration instance.


        Authentication: requires a Bearer token (Personal Access Token).'
      requestBody:
        content: {}
      parameters:
      - name: integration_instance_id
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: product_sku_id
        in: path
        schema:
          type: string
        required: true
        description: The product sku ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      exact_match:
                        type: object
                        properties:
                          id:
                            type: integer
                          sku:
                            type: string
                          name:
                            type: string
                          barcode:
                            type: string
                          price:
                            type: string
                          type:
                            type: string
                          match_type:
                            type: string
                      barcode_match:
                        type: string
                        nullable: true
                      similar_matches:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            sku:
                              type: string
                            name:
                              type: string
                            barcode:
                              type: string
                              nullable: true
                            price:
                              type: string
                            type:
                              type: string
                            match_type:
                              type: string
                example:
                  data:
                    exact_match:
                      id: 4821
                      sku: ZKM-001
                      name: Zesty Kumquat Marmalade
                      barcode: '0761234500017'
                      price: '12.99'
                      type: standard
                      match_type: sku
                    barcode_match: null
                    similar_matches:
                    - id: 4822
                      sku: KM-JAR
                      name: Kumquat Marmalade Jar
                      barcode: null
                      price: '9.50'
                      type: standard
                      match_type: fuzzy
                    - id: 4823
                      sku: KM-SPREAD
                      name: Organic Kumquat Spread
                      barcode: null
                      price: '8.25'
                      type: standard
                      match_type: fuzzy
        '403':
          description: Forbidden
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: SKU does not belong to this integration instance
        '429': *id001
        '401': *id002
        '404': *id004
        '422': *id005
      operationId: post-api-tiktok-shop-integration-instances-integration-instance-id-products-skus-product-sku-id-smart-match
  /api/tiktok-shop/integration-instances/{integration_instance_id}/products/skus/{product_sku_id}/create-sku-product:
    post:
      tags:
      - TikTok Shop
      summary: Create SKU.io Product from SKU
      description: 'Create a brand-new SKU.io Product from a TikTok Shop SKU''s own
        data (SKU, name, price) and map the SKU to it in one step. Mirrors Shopify''s
        create-sku-product, but operates at TikTok''s per-SKU listing grain (Shopify
        creates per-variant).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        The endpoint is keyed on the flattened SKU row (`{{product_sku_id}}` — the
        `id` returned by List Product SKUs). No request body: the new product''s `sku`
        is the TikTok `seller_sku` (falling back to `tiktok_sku_id` when the seller
        SKU is blank), its `name` is the SKU variant name (falling back to the parent
        product title), price is copied from the SKU, and barcode is always null (TikTok
        SKUs carry none).


        Create-or-link behaviour (Shopify parity):

        - If **no** SKU.io Product with the resolved SKU exists, a new one is created,
        then the TikTok SKU is mapped to it. `linked_existing` = `false`.

        - If a SKU.io Product with that SKU **already** exists, it is linked to instead
        of duplicated, then the TikTok SKU is mapped to it. `linked_existing` = `true`.


        Mapping creates a ProductListing and re-links any previously-unmapped sales-order
        lines for this listing (dispatched asynchronously). The response `data` is
        the flattened SKU row (same shape as List Product SKUs) reflecting the new
        mapping.


        Returns 422 if the SKU is already mapped (unmap it first), and 403 if the
        SKU does not belong to the given integration instance.


        Authentication: requires a Bearer token (Personal Access Token).'
      requestBody:
        content: {}
      parameters:
      - name: integration_instance_id
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: product_sku_id
        in: path
        schema:
          type: string
        required: true
        description: The product sku ID.
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 201 — Created & mapped (new product)
                  value:
                    data:
                      id: 90321
                      integration_instance_id: 12
                      tiktok_shop_product_id: 4471
                      tiktok_sku_id: '1729382734500123'
                      seller_sku: ZKM-001
                      name: Zesty Kumquat Marmalade / 250g
                      price: '12.99'
                      inventory_quantity: 84
                      inventory_synced_at: '2026-07-02T09:15:00.000000Z'
                      archived_at: null
                      created_at: '2026-06-28T11:02:41.000000Z'
                      updated_at: '2026-07-03T08:40:12.000000Z'
                      tiktok_product_id: '1729382700000456'
                      product_title: Zesty Kumquat Marmalade
                      product_status: ACTIVATE
                      main_image_url: https://p16-oec.tiktokcdn.com/kumquat-main.jpeg
                      product_listing_id: 55231
                      product:
                        id: 4821
                        name: Zesty Kumquat Marmalade / 250g
                        sku: ZKM-001
                        listing_id: 55231
                        default_financial_line_type_id: 3
                        default_financial_line_type:
                          id: 3
                          name: Product Sales
                          classification: revenue
                      subscription_offering: null
                      mapped_at: '2026-07-03T08:40:12.000000Z'
                      mapped_sku: ZKM-001
                      sku_product:
                        id: 4821
                        sku: ZKM-001
                        name: Zesty Kumquat Marmalade / 250g
                        barcode: null
                        price: '12.99'
                        type: standard
                        default_financial_line_type_id: 3
                        default_financial_line_type:
                          id: 3
                          name: Product Sales
                          classification: revenue
                    linked_existing: false
                    message: SKU.io product created and mapped successfully.
                example-1:
                  summary: 201 — Linked to existing product
                  value:
                    data:
                      id: 90322
                      integration_instance_id: 12
                      tiktok_shop_product_id: 4471
                      tiktok_sku_id: '1729382734500124'
                      seller_sku: KM-JAR
                      name: Kumquat Marmalade Jar
                      price: '9.50'
                      inventory_quantity: 20
                      inventory_synced_at: '2026-07-02T09:15:00.000000Z'
                      archived_at: null
                      created_at: '2026-06-28T11:02:41.000000Z'
                      updated_at: '2026-07-03T08:41:03.000000Z'
                      tiktok_product_id: '1729382700000456'
                      product_title: Zesty Kumquat Marmalade
                      product_status: ACTIVATE
                      main_image_url: https://p16-oec.tiktokcdn.com/kumquat-main.jpeg
                      product_listing_id: 55232
                      product:
                        id: 4822
                        name: Kumquat Marmalade Jar
                        sku: KM-JAR
                        listing_id: 55232
                        default_financial_line_type_id: 3
                        default_financial_line_type:
                          id: 3
                          name: Product Sales
                          classification: revenue
                      subscription_offering: null
                      mapped_at: '2026-07-03T08:41:03.000000Z'
                      mapped_sku: KM-JAR
                      sku_product:
                        id: 4822
                        sku: KM-JAR
                        name: Kumquat Marmalade Jar
                        barcode: null
                        price: '9.50'
                        type: standard
                        default_financial_line_type_id: 3
                        default_financial_line_type:
                          id: 3
                          name: Product Sales
                          classification: revenue
                    linked_existing: true
                    message: SKU linked to existing SKU.io product successfully.
        '403':
          description: Forbidden
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: SKU does not belong to this integration instance
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: SKU is already mapped. Unmap it first.
        '429': *id001
        '401': *id002
        '404': *id004
      operationId: post-api-tiktok-shop-integration-instances-integration-instance-id-products-skus-product-sku-id-create-sku-product
  /api/tiktok-shop/integration-instances/{integration_instance_id}/products/{product_id}/map:
    post:
      tags:
      - TikTok Shop
      summary: Map Product SKU
      description: 'Map a TikTok Shop product SKU (TikTokShopProductSku) to a SKU.io
        Product or Subscription Offering. Mirrors Shopify single-map. Body requires
        `sku_id` plus exactly one of `product_id` or `subscription_offering_id`. Response
        includes the reloaded product with skus + product listing.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                sku_id:
                  type: integer
                product_id:
                  type: integer
              example:
                sku_id: 1
                product_id: 123
      parameters:
      - name: integration_instance_id
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: product_id
        in: path
        schema:
          type: string
        required: true
        description: The product ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-tiktok-shop-integration-instances-integration-instance-id-products-product-id-map
    delete:
      tags:
      - TikTok Shop
      summary: Unmap Product SKU
      description: 'Unmap a TikTok Shop product SKU. Deletes the underlying ProductListing.
        Returns 422 if the SKU is not currently mapped.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integration_instance_id
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: product_id
        in: path
        schema:
          type: string
        required: true
        description: The product ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-tiktok-shop-integration-instances-integration-instance-id-products-product-id-map
  /api/tiktok-shop/integration-instances/{integration_instance_id}/products/{product_id}/archive:
    post:
      tags:
      - TikTok Shop
      summary: Archive Product
      description: 'Soft-archive a single TikTok Shop product (sets archived_at).
        Mirrors Shopify single-archive.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters:
      - name: integration_instance_id
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: product_id
        in: path
        schema:
          type: string
        required: true
        description: The product ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-tiktok-shop-integration-instances-integration-instance-id-products-product-id-archive
  /api/tiktok-shop/integration-instances/{integration_instance_id}/products/{product_id}/unarchive:
    post:
      tags:
      - TikTok Shop
      summary: Unarchive Product
      description: 'Restore an archived TikTok Shop product (clears archived_at).
        Mirrors Shopify single-unarchive.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters:
      - name: integration_instance_id
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: product_id
        in: path
        schema:
          type: string
        required: true
        description: The product ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-tiktok-shop-integration-instances-integration-instance-id-products-product-id-unarchive
  /api/tiktok-shop/integration-instances/{integration_instance_id}/products/{product_id}:
    delete:
      tags:
      - TikTok Shop
      summary: Delete Product
      description: 'Hard-delete a single TikTok Shop product and its child SKUs. Mirrors
        Shopify single delete.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integration_instance_id
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: product_id
        in: path
        schema:
          type: string
        required: true
        description: The product ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-tiktok-shop-integration-instances-integration-instance-id-products-product-id
  /api/tiktok-shop/integration-instances/{integration_instance_id}/products/bulk-archive:
    post:
      tags:
      - TikTok Shop
      summary: Bulk Archive Products
      description: 'Bulk-archives TikTok Shop products (sets archived_at). Either
        pass an explicit `ids` array, or `apply_to_all: true` with the current `filters`
        object to archive every product matching the listing filters. Returns archived_count.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Mirrors Shopify bulk-archive. Filters reuse the same Spatie QueryBuilder allowed
        filters as the listing endpoint (`status`, `category_id`, `archived`, `search`,
        `title`, `tiktok_product_id`, `category_name`).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1
                - 2
                - 3
      parameters:
      - name: integration_instance_id
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-tiktok-shop-integration-instances-integration-instance-id-products-bulk-archive
  /api/tiktok-shop/integration-instances/{integration_instance_id}/products/bulk-unarchive:
    post:
      tags:
      - TikTok Shop
      summary: Bulk Unarchive Products
      description: 'Bulk-unarchives TikTok Shop products (clears archived_at). Either
        pass an explicit `ids` array, or `apply_to_all: true` with the current `filters`
        object. Returns unarchived_count.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Mirrors Shopify bulk-unarchive.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1
                - 2
                - 3
      parameters:
      - name: integration_instance_id
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-tiktok-shop-integration-instances-integration-instance-id-products-bulk-unarchive
  /api/tiktok-shop/integration-instances/{integration_instance_id}/products/bulk-delete:
    post:
      tags:
      - TikTok Shop
      summary: Bulk Delete Products
      description: 'Hard-deletes TikTok Shop products (and their child SKUs) in bulk.
        Either pass an explicit `ids` array, or `apply_to_all: true` with the current
        `filters` object. Returns deleted_count.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Mirrors Shopify bulk-delete.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1
                - 2
                - 3
      parameters:
      - name: integration_instance_id
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-tiktok-shop-integration-instances-integration-instance-id-products-bulk-delete
  /api/tiktok-shop/integration-instances/{integration_instance_id}/products/bulk-unmap:
    post:
      tags:
      - TikTok Shop
      summary: Bulk Unmap Product SKUs
      description: 'Bulk-unmaps TikTok Shop product SKUs from their SKU.io ProductListings
        (deletes the ProductListing records). Per-SKU, not per-product, because mapping
        is at the SKU level.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Either pass an explicit `sku_ids` array (TikTok Shop SKU IDs), or `apply_to_all:
        true` with `filters` (product-level filters). When `apply_to_all` is used,
        the backend resolves all mapped SKUs under products matching the filter set.
        Returns unmapped_count.


        Mirrors Shopify''s bulk-unmap pattern adapted for TikTok''s SKU-level mapping
        model.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                sku_ids:
                  type: array
                  items:
                    type: integer
              example:
                sku_ids:
                - 10
                - 11
                - 12
      parameters:
      - name: integration_instance_id
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-tiktok-shop-integration-instances-integration-instance-id-products-bulk-unmap
  /api/tiktok-shop/integration-instances/{integration_instance_id}/products/csv-mappings:
    get:
      tags:
      - TikTok Shop
      summary: Download CSV Mappings
      description: 'Download a CSV of TikTok Shop SKU → SKU.io product mappings, scoped
        by selection, unmapped-only, or all (filtered).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Columns: tiktok_sku_id, tiktok_product_id, seller_sku, product_title, sku_name,
        price, map_to_sku.


        Users edit the `map_to_sku` column then re-upload via the upload endpoint
        to bulk-apply mappings. Mirrors Shopify''s bulk mapping CSV flow but operates
        per-SKU (TikTok lists each SKU as its own variant).


        Returns a binary CSV download (Content-Type: text/csv).'
      parameters:
      - name: scope
        in: query
        schema:
          type: string
        description: 'Required. One of: selected | unmapped | all'
        example: unmapped
      - name: integration_instance_id
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-tiktok-shop-integration-instances-integration-instance-id-products-csv-mappings
    post:
      tags:
      - TikTok Shop
      summary: Upload CSV Mappings
      description: 'Upload an edited CSV (downloaded from the Download CSV Mappings
        endpoint) to bulk-apply TikTok SKU → SKU.io product mappings in one pass.
        Validates and applies row-by-row.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        File must be CSV/TXT, max 10 MB. Required columns: tiktok_sku_id, map_to_sku.
        Empty `map_to_sku` rows are skipped. Rows where the TikTok SKU isn''t found,
        or the SKU.io product code doesn''t match, are returned in `invalid_rows`.


        Response: { mapped_count, skipped_count, failed_count, invalid_rows[] }.'
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                file:
                  type: string
                  description: 'Edited CSV file (max 10 MB). Required columns: tiktok_sku_id,
                    map_to_sku.'
                  format: binary
      parameters:
      - name: integration_instance_id
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      mapped_count:
                        type: integer
                      skipped_count:
                        type: integer
                      failed_count:
                        type: integer
                      invalid_rows:
                        type: array
                        items:
                          type: object
                          properties:
                            row_number:
                              type: integer
                            tiktok_sku_id:
                              type: string
                            map_to_sku:
                              type: string
                            error:
                              type: string
                  message:
                    type: string
                example:
                  data:
                    mapped_count: 12
                    skipped_count: 3
                    failed_count: 1
                    invalid_rows:
                    - row_number: 7
                      tiktok_sku_id: '1729380000000000000'
                      map_to_sku: BAD-SKU-001
                      error: 'No SKU.io product found with code: BAD-SKU-001'
                  message: CSV mapping import complete
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-tiktok-shop-integration-instances-integration-instance-id-products-csv-mappings
  /api/tiktok-shop/integration-instances/{integration_instance_id}/products/csv-mappings/validate:
    post:
      tags:
      - TikTok Shop
      summary: Validate CSV Mappings
      description: 'Parse/preview half of the two-step CSV import — mirrors Shopify''s
        Validate Bulk Mapping CSV, but operates per-SKU (TikTok lists each SKU as
        its own variant, keyed on `tiktok_sku_id`).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Validates the uploaded CSV WITHOUT applying anything, then returns the resolved
        `{tiktok_shop_product_sku_id, tiktok_sku_id, sku_product_id}` pairings the
        frontend previews and posts back to the Apply CSV Mappings endpoint, plus
        counts and any invalid/skipped rows.


        File must be CSV/TXT, max 10 MB. Required columns: tiktok_sku_id, map_to_sku.
        Rows with an empty `map_to_sku` are counted in `skipped_count`. Rows whose
        `tiktok_sku_id` isn''t found for this integration, or whose `map_to_sku` product
        code doesn''t match a SKU.io product, are returned in `invalid_rows` (with
        a per-row `error`).


        Response: { valid_count, skipped_count, invalid_rows[], mappings[] }.'
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                file:
                  type: string
                  description: 'Edited CSV file (max 10 MB). Required columns: tiktok_sku_id,
                    map_to_sku.'
                  format: binary
      parameters:
      - name: integration_instance_id
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      valid_count:
                        type: integer
                      skipped_count:
                        type: integer
                      invalid_rows:
                        type: array
                        items:
                          type: object
                          properties:
                            row_number:
                              type: integer
                            tiktok_sku_id:
                              type: string
                            map_to_sku:
                              type: string
                            error:
                              type: string
                      mappings:
                        type: array
                        items:
                          type: object
                          properties:
                            tiktok_shop_product_sku_id:
                              type: integer
                            tiktok_sku_id:
                              type: string
                            sku_product_id:
                              type: integer
                example:
                  data:
                    valid_count: 2
                    skipped_count: 1
                    invalid_rows:
                    - row_number: 5
                      tiktok_sku_id: '1729380000000000099'
                      map_to_sku: BAD-SKU-001
                      error: 'No SKU.io product found with code: BAD-SKU-001'
                    mappings:
                    - tiktok_shop_product_sku_id: 4821
                      tiktok_sku_id: '1729380000000000001'
                      sku_product_id: 991
                    - tiktok_shop_product_sku_id: 4822
                      tiktok_sku_id: '1729380000000000002'
                      sku_product_id: 992
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: Invalid CSV Format
                  value:
                    error: 'Invalid CSV format. Required columns: tiktok_sku_id, map_to_sku'
                example-1:
                  summary: Validation Error (bad file)
                  value:
                    message: 'The file must be a file of type: csv, txt.'
                    errors:
                      file:
                      - 'The file must be a file of type: csv, txt.'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-tiktok-shop-integration-instances-integration-instance-id-products-csv-mappings-validate
  /api/tiktok-shop/integration-instances/{integration_instance_id}/products/csv-mappings/apply:
    post:
      tags:
      - TikTok Shop
      summary: Apply CSV Mappings
      description: 'Commit half of the two-step CSV import — mirrors Shopify''s Apply
        Bulk Mapping CSV. Applies the `{tiktok_shop_product_sku_id, sku_product_id}`
        pairings returned by the Validate CSV Mappings endpoint. Each pairing maps
        a flattened TikTok SKU to a SKU.io product via the canonical mapping path
        (creates/updates the ProductListing and re-links any unmapped sales-order
        lines).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Body: `mappings` (required, min 1). Each entry needs `tiktok_shop_product_sku_id`
        (integer — the internal TikTokShopProductSku id, NOT the tiktok_sku_id string)
        and `sku_product_id` (integer, must exist in `products`). SKUs that don''t
        belong to this integration instance are counted in `failed_count` rather than
        mapped.


        Response: { mapped_count, failed_count }.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                mappings:
                  type: array
                  items:
                    type: object
                    properties:
                      tiktok_shop_product_sku_id:
                        type: integer
                      sku_product_id:
                        type: integer
              example:
                mappings:
                - tiktok_shop_product_sku_id: 4821
                  sku_product_id: 991
                - tiktok_shop_product_sku_id: 4822
                  sku_product_id: 992
      parameters:
      - name: integration_instance_id
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      mapped_count:
                        type: integer
                      failed_count:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    mapped_count: 2
                    failed_count: 0
                  message: Applied 2 mapping(s).
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      mappings.0.sku_product_id:
                        type: array
                        items:
                          type: string
                example:
                  message: The selected mappings.0.sku_product_id is invalid.
                  errors:
                    mappings.0.sku_product_id:
                    - The selected mappings.0.sku_product_id is invalid.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-tiktok-shop-integration-instances-integration-instance-id-products-csv-mappings-apply
  /api/tiktok-shop/integration-instances/{integration_instance_id}/products/{tiktok_shop_product_id}/raw:
    get:
      tags:
      - TikTok Shop
      summary: Get Raw Product from TikTok
      description: 'Fetches the live raw product JSON directly from the TikTok Shop
        API (`GET /product/202309/products/{tiktok_product_id}`) for the given local
        product. Used by the product detail page''s ''Raw Data from TikTok'' accordion
        when the user clicks ''Load Raw Data from TikTok''.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Returns 403 if the product does not belong to the given integration instance,
        500 on TikTok API failure.


        Requires Bearer token.'
      parameters:
      - name: integration_instance_id
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: tiktok_shop_product_id
        in: path
        schema:
          type: string
        required: true
        description: The tiktok shop product ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      product:
                        type: object
                        properties:
                          id:
                            type: string
                          title:
                            type: string
                          status:
                            type: string
                          create_time:
                            type: integer
                          update_time:
                            type: integer
                          category_chains:
                            type: array
                            items:
                              type: object
                              properties:
                                id:
                                  type: string
                                parent_id:
                                  type: string
                                local_name:
                                  type: string
                                is_leaf:
                                  type: boolean
                          skus:
                            type: array
                            items:
                              type: object
                              properties:
                                id:
                                  type: string
                                seller_sku:
                                  type: string
                                price:
                                  type: object
                                  properties:
                                    sale_price:
                                      type: string
                                    currency:
                                      type: string
                example:
                  data:
                    product:
                      id: '1729382911234567890'
                      title: Demo TikTok Product
                      status: ACTIVATE
                      create_time: 1716595200
                      update_time: 1716681600
                      category_chains:
                      - id: '600001'
                        parent_id: '0'
                        local_name: Apparel & Accessories
                        is_leaf: false
                      skus:
                      - id: '1729382911234567891'
                        seller_sku: DEMO-SKU-1
                        price:
                          sale_price: '12.99'
                          currency: USD
        '403':
          description: Forbidden
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: Product does not belong to this integration instance
        '429': *id001
        '401': *id002
        '404': *id004
      operationId: get-api-tiktok-shop-integration-instances-integration-instance-id-products-tiktok-shop-product-id-raw
  /api/tiktok-shop/integration-instances/{integration_instance_id}/products/{tiktok_shop_product_id}/orders:
    get:
      tags:
      - TikTok Shop
      summary: Get Orders Containing Product
      description: 'Returns a paginated list of TikTok Shop orders that contain this
        product (orders whose line items reference the product''s `tiktok_product_id`).
        Used by the product detail page''s ''Orders Containing This Product'' accordion.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Returns 403 if the product does not belong to the given integration instance.


        Pagination: `page` (default 1), `per_page` (default 10). Sorted by `tiktok_create_time`
        DESC.


        Requires Bearer token.'
      parameters:
      - name: integration_instance_id
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: tiktok_shop_product_id
        in: path
        schema:
          type: string
        required: true
        description: The tiktok shop product ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        tiktok_order_id:
                          type: string
                        status:
                          type: string
                        currency:
                          type: string
                        total_amount:
                          type: string
                        buyer_email:
                          type: string
                        tiktok_create_time:
                          type: string
                        tiktok_update_time:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - id: 12345
                    integration_instance_id: 9
                    tiktok_order_id: '5780000000001234567'
                    status: AWAITING_SHIPMENT
                    currency: USD
                    total_amount: '42.97'
                    buyer_email: buyer@example.com
                    tiktok_create_time: '2026-05-20T15:32:11Z'
                    tiktok_update_time: '2026-05-20T15:35:00Z'
                  current_page: 1
                  last_page: 3
                  per_page: 10
                  total: 27
                  from: 1
                  to: 10
        '403':
          description: Forbidden
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: Product does not belong to this integration instance
        '429': *id001
        '401': *id002
        '404': *id004
      operationId: get-api-tiktok-shop-integration-instances-integration-instance-id-products-tiktok-shop-product-id-orders
  /api/tiktok-shop/integration-instances/{integration_instance_id}/products/bulk:
    post:
      tags:
      - TikTok Shop
      summary: Bulk Map / Unmap / Create / Remap Product SKUs (Sync)
      description: 'Synchronous per-SKU bulk mapping engine backing the frontend BulkMappingModal
        for below-threshold selections. Runs each resolved TikTok Shop SKU through
        the mapping manager and returns Shopify-parity count keys.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Named route: `tiktok-shop.products.bulk`.


        **Body**

        - `action` (required, one of `map` | `unmap` | `create` | `remap`) — the per-SKU
        operation. `map` = smart-match & map unmapped SKUs; `unmap` = delete the SKU''s
        ProductListing; `create` = create-or-link a SKU.io product from the SKU and
        map it; `remap` = repoint an already-mapped SKU to its current best match.
        (archive/unarchive/delete are NOT here — they use the product-id batch endpoints.)

        - `selection` (required, object) — `type` is one of `selected` | `visible`
        | `filtered`. For `selected`, pass `selection.ids` (array of TikTok Shop SKU
        IDs). For `visible`/`filtered`, pass `selection.filters` (same filter keys
        as the flattened SKU list) and the backend resolves the id set.

        - `options` (optional, object) — `match_by` (`sku` | `barcode`; `barcode`
        falls back to exact SKU match since TikTok SKUs carry no barcode), `create_if_no_match`
        (boolean — on `map`, create a SKU.io product when no match is found; counts
        toward `mapped_count`), `field_mappings` (array of `{shopify_field, sku_field}`
        overrides).


        **Response** returns `processed` / `failed` / `skipped` plus one action-specific
        count key (`mapped_count` | `created_count` | `remapped_count` | `unmapped_count`).
        Returns **422** when the selection resolves to no SKUs. Larger selections
        should use `products/bulk-tracked` instead.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                action:
                  type: string
                selection:
                  type: object
                  properties:
                    type:
                      type: string
                    ids:
                      type: array
                      items:
                        type: integer
                options:
                  type: object
                  properties:
                    match_by:
                      type: string
                    create_if_no_match:
                      type: boolean
              example:
                action: map
                selection:
                  type: selected
                  ids:
                  - 10
                  - 11
                  - 12
                options:
                  match_by: sku
                  create_if_no_match: false
      parameters:
      - name: integration_instance_id
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      action:
                        type: string
                      processed:
                        type: integer
                      failed:
                        type: integer
                      skipped:
                        type: integer
                      mapped_count:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    action: map
                    processed: 3
                    failed: 0
                    skipped: 1
                    mapped_count: 2
                  message: 'Bulk map completed. Processed: 3, Failed: 0, Skipped:
                    1'
        '422':
          description: Unprocessable Content
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: Empty Selection (422)
                  value:
                    error: No SKUs found for the given selection.
                example-1:
                  summary: Validation Error (422)
                  value:
                    message: The selected action is invalid.
                    errors:
                      action:
                      - The selected action is invalid.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-tiktok-shop-integration-instances-integration-instance-id-products-bulk
  /api/tiktok-shop/integration-instances/{integration_instance_id}/products/bulk-tracked:
    post:
      tags:
      - TikTok Shop
      summary: Bulk Map Product SKUs (Tracked)
      description: 'Queued counterpart to `products/bulk`, dispatched when the BulkMappingModal
        crosses its tracked-operation threshold. Same body contract as `products/bulk`
        (`action` = `map` | `unmap` | `create` | `remap`, plus `selection` and `options`).
        Dispatches a tracked job and returns its `tracked_job_log_id` for polling
        via `products/bulk-progress/{id}`.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Named route: `tiktok-shop.products.bulk-tracked`.


        The job surfaces via the tracked job log endpoints. Returns **422** when the
        selection resolves to no SKUs.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                action:
                  type: string
                selection:
                  type: object
                  properties:
                    type:
                      type: string
                    filters:
                      type: object
                      properties:
                        mapping_status:
                          type: string
                options:
                  type: object
                  properties:
                    match_by:
                      type: string
                    create_if_no_match:
                      type: boolean
              example:
                action: map
                selection:
                  type: filtered
                  filters:
                    mapping_status: unmapped
                options:
                  match_by: sku
                  create_if_no_match: true
      parameters:
      - name: integration_instance_id
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                  status:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 8842
                  message: Bulk operation job has been queued
                  status: Success
        '422':
          description: Unprocessable Content
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  status:
                    type: string
                example:
                  message: No SKUs found for the given selection.
                  status: Failure
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-tiktok-shop-integration-instances-integration-instance-id-products-bulk-tracked
  /api/tiktok-shop/integration-instances/{integration_instance_id}/products/bulk-progress/{tracked_job_log_id}:
    get:
      tags:
      - TikTok Shop
      summary: Get Bulk Mapping Progress
      description: 'Fetch progress for a tracked bulk mapping operation started by
        `products/bulk-tracked`. Returns the tracked job log object for the given
        `trackedJobLogId` — the same shape the tracked job log endpoints consumes
        (status, processed/total items, progress percentage, messages, results).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Named route: `tiktok-shop.products.bulk-progress`. Returns **404** when the
        log id is unknown.'
      parameters:
      - name: integration_instance_id
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: tracked_job_log_id
        in: path
        schema:
          type: string
        required: true
        description: The tracked job log ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      job_type:
                        type: string
                      queue:
                        type: string
                      job_name:
                        type: string
                      status:
                        type: string
                      related_model:
                        type: object
                        properties:
                          id:
                            type: string
                            nullable: true
                          type:
                            type: string
                            nullable: true
                          reference:
                            type: string
                            nullable: true
                      related_model_reference:
                        type: string
                        nullable: true
                      messages:
                        type: array
                        items:
                          type: string
                      attempted_at:
                        type: string
                      completed_at:
                        type: string
                        nullable: true
                      duration:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      results:
                        type: string
                        nullable: true
                      total_items:
                        type: integer
                      processed_items:
                        type: integer
                      progress_percentage:
                        type: integer
                      progress_mode:
                        type: string
                      stages:
                        type: string
                        nullable: true
                example:
                  data:
                    id: 8842
                    job_type: tiktok-shop-bulk-product-operation
                    queue: default
                    job_name: 'Bulk Map: 42 TikTok Shop products'
                    status: processing
                    related_model:
                      id: null
                      type: null
                      reference: null
                    related_model_reference: null
                    messages:
                    - Processing SKU 18 of 42
                    attempted_at: '2026-07-03T10:14:00+00:00'
                    completed_at: null
                    duration: null
                    created_at: '2026-07-03T10:13:58+00:00'
                    updated_at: '2026-07-03T10:14:12+00:00'
                    results: null
                    total_items: 42
                    processed_items: 18
                    progress_percentage: 43
                    progress_mode: items
                    stages: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-tiktok-shop-integration-instances-integration-instance-id-products-bulk-progress-tracked-job-log-id
  /api/tiktok-shop/integration-instances/{integration_instance_id}/products/map-to-existing-skus:
    post:
      tags:
      - TikTok Shop
      summary: Map to Existing SKUs (Bulk, Queued)
      description: 'Queue a bulk "map to existing SKU.io products only" operation
        (no product creation) over the shared toolbar selection contract. Guarded
        by the instance''s configured field mappings.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Named route: `tiktok-shop.mappings.map-to-existing-skus` (URL is under `products/`).


        **Body** — exactly one selection mode:

        - `ids` (array of TikTok Shop SKU IDs, max 1000), or

        - `process_all` (boolean `true` — all eligible SKUs), or

        - `filters` (object — same filter keys as the flattened SKU list).


        **Responses**: **200** queued-with-summary; **400** when no field mappings
        are configured (`No field mappings found...`), when the selection is invalid
        (none of ids/process_all/filters), or when more than 1000 ids are supplied.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 10
                - 11
                - 12
      parameters:
      - name: integration_instance_id
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      integration_instance_id:
                        type: integer
                      message:
                        type: string
                      status:
                        type: string
                      selection_summary:
                        type: object
                        properties:
                          selection_type:
                            type: string
                          sku_count:
                            type: integer
                          sku_ids:
                            type: array
                            items:
                              type: integer
                example:
                  data:
                    integration_instance_id: 1
                    message: Processing 3 specific SKUs - check queue status for progress
                    status: queued
                    selection_summary:
                      selection_type: specific_skus
                      sku_count: 3
                      sku_ids:
                      - 10
                      - 11
                      - 12
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: No Field Mappings (400)
                  value:
                    error: No field mappings found for this integration instance
                    message: Please configure field mappings before attempting to
                      map products
                example-1:
                  summary: Invalid Selection (400)
                  value:
                    error: Invalid request parameters
                    message: Either "ids", "process_all", or "filters" must be specified
                    examples:
                      specific_skus:
                        ids:
                        - 1
                        - 2
                        - 3
                      all_skus:
                        process_all: true
                      filtered_skus:
                        filters:
                          mapping_status: unmapped
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-tiktok-shop-integration-instances-integration-instance-id-products-map-to-existing-skus
  /api/tiktok-shop/integration-instances/{integration_instance_id}/products/create-products-from-mappings:
    post:
      tags:
      - TikTok Shop
      summary: Create Products from Mappings (Bulk, Queued)
      description: 'Queue a bulk "create new SKU.io products from unmapped SKUs" operation
        over the shared toolbar selection contract. Guarded by the instance''s configured
        field mappings. Same body and response shape as `map-to-existing-skus`, but
        the queued job creates a SKU.io product from each unmapped SKU''s channel
        attributes (linking an existing product when one already has the matching
        SKU) and maps it.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Named route: `tiktok-shop.mappings.create-products-from-mappings` (URL is
        under `products/`).


        **Body** — exactly one of `ids` (max 1000) | `process_all` | `filters`.


        **Responses**: **200** queued-with-summary; **400** when no field mappings
        are configured, when the selection is invalid, or when more than 1000 ids
        are supplied.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                process_all:
                  type: boolean
              example:
                process_all: true
      parameters:
      - name: integration_instance_id
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      integration_instance_id:
                        type: integer
                      message:
                        type: string
                      status:
                        type: string
                      selection_summary:
                        type: object
                        properties:
                          selection_type:
                            type: string
                          filters_applied:
                            type: string
                            nullable: true
                example:
                  data:
                    integration_instance_id: 1
                    message: Processing all eligible SKUs - check queue status for
                      progress
                    status: queued
                    selection_summary:
                      selection_type: all_skus
                      filters_applied: null
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                  message:
                    type: string
                example:
                  error: No field mappings found for this integration instance
                  message: Please configure field mappings before attempting to create
                    products
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-tiktok-shop-integration-instances-integration-instance-id-products-create-products-from-mappings
  /api/tiktok-shop/integration-instances/{integration_instance_id}/products/latest-sync-info:
    get:
      tags:
      - TikTok Shop
      summary: Get Latest Sync Info
      description: 'Summary of the product catalog sync for a connection: the most
        recently updated product (by TikTok''s update time), the total number of synced
        products, and when the last product sync ran.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance_id
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      latest_product_title:
                        type: string
                      latest_product_date:
                        type: string
                      total_products:
                        type: integer
                      last_synced_at:
                        type: string
                example:
                  data:
                    latest_product_title: Ceramic Mug — 12oz
                    latest_product_date: '2026-06-19T22:14:07+00:00'
                    total_products: 312
                    last_synced_at: '2026-06-20T07:45:00+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-tiktok-shop-integration-instances-integration-instance-id-products-latest-sync-info
  /api/tiktok-shop/integration-instances/{integration_instance_id}/locations:
    get:
      tags:
      - TikTok Shop
      summary: List Locations
      description: 'Returns all known TikTok Shop warehouses for the integration instance
        (from the local cache).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Requires Bearer token.'
      parameters:
      - name: integration_instance_id
        in: path
        required: true
        schema:
          type: string
        description: The integration_instance_id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        tiktok_warehouse_id:
                          type: string
                        name:
                          type: string
                        type:
                          type: string
                        is_default:
                          type: boolean
                example:
                  data:
                  - id: 30
                    integration_instance_id: 12
                    tiktok_warehouse_id: '7497123456789'
                    name: Acme US Warehouse
                    type: SALES_WAREHOUSE
                    is_default: true
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-tiktok-shop-integration-instances-integration-instance-id-locations
    post:
      tags:
      - TikTok Shop
      summary: Refresh Locations from TikTok
      description: 'Pull the seller''s warehouses from TikTok Shop into the local
        cache and seed the per-warehouse master-of-stock panel. Returns the number
        of warehouses synced.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters:
      - name: integration_instance_id
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      warehouses_synced:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    warehouses_synced: 3
                  message: Refreshed 3 TikTok Shop warehouse(s).
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-tiktok-shop-integration-instances-integration-instance-id-locations
  /api/tiktok-shop/integration-instances/{integration_instance_id}/inventory:
    get:
      tags:
      - TikTok Shop
      summary: List Inventory Comparison
      description: 'Paginated inventory comparison for this connection — one row per
        SKU × TikTok warehouse. Each row pairs the SKU.io computed available quantity
        (`sku_quantity`) with the last-observed TikTok quantity (`sales_channel_quantity`)
        and derives a `status`:


        - `needs_recalc` — the cache is flagged for recomputation (`is_sku_recalculation_needed`).

        - `synced` — computed quantity equals the channel quantity (null treated as
        0; negatives clamp-aware when negative inventory is disallowed).

        - `variance` — the two differ (see `variance` = `sku_quantity - sales_channel_quantity`).

        - `not_managed` — SKU.io is not the master of stock for this warehouse, so
        its inventory is neither computed nor pushed; the row is excluded from the
        in-sync / variance / needs-recalc counts.


        **Filters:** `filter[search]` (listing SKU / title / product SKU / offering
        name / offering SKU), `filter[status]` (synced|variance|needs_recalc; is /
        is_one_of / is_not), `filter[location_id]` (local warehouse PK; is / is_one_of),
        `filter[sku_quantity]` & `filter[sales_channel_quantity]` (numeric operators),
        `filter[sales_channel_quantity_updated_at]` & `filter[sales_channel_quantity_synced_at]`
        (datetime operators), `filter[listing_sku]`, `filter[title]`.


        **Sorts** (prefix `-` for DESC; default `-id`): id, sku_quantity, sales_channel_quantity,
        created_at, updated_at.


        Pagination: `page`, `per_page` (default 10). Requires a Bearer token.'
      parameters:
      - name: integration_instance_id
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        product_listing_id:
                          type: integer
                        document_id:
                          type: integer
                        listing_sku:
                          type: string
                        title:
                          type: string
                        product:
                          type: object
                          properties:
                            id:
                              type: integer
                            sku:
                              type: string
                            name:
                              type: string
                        subscription_offering:
                          type: string
                          nullable: true
                        location_id:
                          type: integer
                        location_name:
                          type: string
                        location_is_active:
                          type: boolean
                        sku_quantity:
                          type: integer
                        sales_channel_quantity:
                          type: integer
                        variance:
                          type: integer
                        status:
                          type: string
                        is_sku_recalculation_needed:
                          type: boolean
                        sku_quantity_updated_at:
                          type: string
                        sales_channel_quantity_updated_at:
                          type: string
                        sales_channel_quantity_synced_at:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                  first_page_url:
                    type: string
                  last_page_url:
                    type: string
                  next_page_url:
                    type: string
                  prev_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  links:
                    type: array
                example:
                  data:
                  - id: 55210
                    product_listing_id: 3301
                    document_id: 902
                    listing_sku: MUG-12-WHT
                    title: Ceramic Mug — 12oz
                    product:
                      id: 4521
                      sku: MUG-12-WHT
                      name: Ceramic Mug 12oz White
                    subscription_offering: null
                    location_id: 42
                    location_name: Main US Warehouse
                    location_is_active: true
                    sku_quantity: 10
                    sales_channel_quantity: 8
                    variance: 2
                    status: variance
                    is_sku_recalculation_needed: false
                    sku_quantity_updated_at: '2026-06-20T07:45:00+00:00'
                    sales_channel_quantity_updated_at: '2026-06-20T07:50:00+00:00'
                    sales_channel_quantity_synced_at: '2026-06-20T08:10:00+00:00'
                    created_at: '2026-03-02T18:25:00+00:00'
                    updated_at: '2026-06-20T08:10:00+00:00'
                  - id: 55211
                    product_listing_id: 3302
                    document_id: 903
                    listing_sku: MUG-16-BLK
                    title: Ceramic Mug 16oz
                    product:
                      id: 4522
                      sku: MUG-16-BLK
                      name: Ceramic Mug 16oz Black
                    subscription_offering: null
                    location_id: 43
                    location_name: Returns Overflow Warehouse
                    location_is_active: true
                    sku_quantity: 0
                    sales_channel_quantity: null
                    variance: 0
                    status: not_managed
                    is_sku_recalculation_needed: false
                    sku_quantity_updated_at: '2026-06-20T07:45:00+00:00'
                    sales_channel_quantity_updated_at: null
                    sales_channel_quantity_synced_at: null
                    created_at: '2026-03-02T18:25:00+00:00'
                    updated_at: '2026-06-20T08:10:00+00:00'
                  current_page: 1
                  last_page: 9
                  per_page: 10
                  total: 84
                  from: 1
                  to: 10
                  first_page_url: '...'
                  last_page_url: '...'
                  next_page_url: '...'
                  prev_page_url: null
                  path: '...'
                  links: []
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-tiktok-shop-integration-instances-integration-instance-id-inventory
  /api/tiktok-shop/integration-instances/{integration_instance_id}/inventory/summary:
    get:
      tags:
      - TikTok Shop
      summary: Get Inventory Summary
      description: 'KPI counts for the inventory page: total cache rows, in-sync count,
        variance count, and needs-recalculation count, the not-managed count (warehouses
        where SKU.io is not the master of stock — inventory is not synced for them),
        plus the most recent fetch (`last_fetch_at`) and push (`last_sync_at`) timestamps
        across this connection''s rows. Requires a Bearer token.'
      parameters:
      - name: integration_instance_id
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      total_items:
                        type: integer
                      in_sync:
                        type: integer
                      with_variance:
                        type: integer
                      needs_recalculation:
                        type: integer
                      not_managed:
                        type: integer
                      last_fetch_at:
                        type: string
                      last_sync_at:
                        type: string
                example:
                  data:
                    total_items: 84
                    in_sync: 60
                    with_variance: 20
                    needs_recalculation: 4
                    not_managed: 3
                    last_fetch_at: '2026-06-20 07:50:00'
                    last_sync_at: '2026-06-20 08:10:00'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-tiktok-shop-integration-instances-integration-instance-id-inventory-summary
  /api/tiktok-shop/integration-instances/{integration_instance_id}/inventory/recache:
    post:
      tags:
      - TikTok Shop
      summary: Recache Inventory
      description: Recompute the per-warehouse available-quantity cache for every
        mapped listing on this connection, applying the configured master-of-stock,
        buffer-stock, and min/max rules. Runs asynchronously and returns a tracked-job
        id you can poll via Get Recache Progress. Requires a Bearer token.
      requestBody:
        content: {}
      parameters:
      - name: integration_instance_id
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 12345
                  message: Inventory recache job has been queued
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-tiktok-shop-integration-instances-integration-instance-id-inventory-recache
  /api/tiktok-shop/integration-instances/{integration_instance_id}/inventory/recache-progress/{tracked_job_log_id}:
    get:
      tags:
      - TikTok Shop
      summary: Get Recache Progress
      description: Poll the tracked-job log for a recache job (see Recache Inventory).
        Returns the TrackedJobLog resource with status, progress, and completion results.
        Requires a Bearer token.
      parameters:
      - name: integration_instance_id
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: tracked_job_log_id
        in: path
        schema:
          type: string
        required: true
        description: The tracked job log ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      job_type:
                        type: string
                      queue:
                        type: string
                      job_name:
                        type: string
                      status:
                        type: string
                      related_model:
                        type: object
                        properties:
                          id:
                            type: integer
                          type:
                            type: string
                          reference:
                            type: string
                      related_model_reference:
                        type: string
                      messages:
                        type: array
                      attempted_at:
                        type: string
                      completed_at:
                        type: string
                      duration:
                        type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      results:
                        type: object
                        properties:
                          step:
                            type: string
                          step_message:
                            type: string
                          products_processed:
                            type: integer
                          total_products:
                            type: integer
                          completed_at:
                            type: string
                      total_items:
                        type: integer
                      processed_items:
                        type: integer
                      progress_percentage:
                        type: integer
                      progress_mode:
                        type: string
                      stages:
                        type: string
                        nullable: true
                example:
                  data:
                    id: 12345
                    job_type: App\Models\TrackedJobLog
                    queue: default
                    job_name: 'Recache TikTok Shop Inventory: My TikTok Store'
                    status: completed
                    related_model:
                      id: 12
                      type: Modules\TikTokShop\Entities\TikTokShopIntegrationInstance
                      reference: My TikTok Store
                    related_model_reference: My TikTok Store
                    messages: []
                    attempted_at: '2026-06-20T08:09:30.000000Z'
                    completed_at: '2026-06-20T08:10:00.000000Z'
                    duration: 30
                    created_at: '2026-06-20T08:09:29.000000Z'
                    updated_at: '2026-06-20T08:10:00.000000Z'
                    results:
                      step: complete
                      step_message: Recomputed inventory for 45 listings
                      products_processed: 45
                      total_products: 45
                      completed_at: '2026-06-20T08:10:00+00:00'
                    total_items: 45
                    processed_items: 45
                    progress_percentage: 100
                    progress_mode: items
                    stages: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-tiktok-shop-integration-instances-integration-instance-id-inventory-recache-progress-tracked-job-log-id
  /api/tiktok-shop/integration-instances/{integration_instance_id}/inventory/sync:
    post:
      tags:
      - TikTok Shop
      summary: Sync Inventory to TikTok Shop
      description: Push the cached available quantities to TikTok Shop for every listing
        whose SKU.io quantity differs from what TikTok currently holds. Runs asynchronously
        and returns a tracked-job id you can poll via Get Sync Progress. Typically
        run after Recache Inventory. Requires a Bearer token.
      requestBody:
        content: {}
      parameters:
      - name: integration_instance_id
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 12345
                  message: Inventory sync job has been queued
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-tiktok-shop-integration-instances-integration-instance-id-inventory-sync
  /api/tiktok-shop/integration-instances/{integration_instance_id}/inventory/sync-progress/{tracked_job_log_id}:
    get:
      tags:
      - TikTok Shop
      summary: Get Sync Progress
      description: Poll the tracked-job log for a sync job (see Sync Inventory to
        TikTok Shop). Returns the TrackedJobLog resource with status, progress, and
        completion results. Requires a Bearer token.
      parameters:
      - name: integration_instance_id
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: tracked_job_log_id
        in: path
        schema:
          type: string
        required: true
        description: The tracked job log ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      job_type:
                        type: string
                      queue:
                        type: string
                      job_name:
                        type: string
                      status:
                        type: string
                      related_model:
                        type: object
                        properties:
                          id:
                            type: integer
                          type:
                            type: string
                          reference:
                            type: string
                      related_model_reference:
                        type: string
                      messages:
                        type: array
                      attempted_at:
                        type: string
                      completed_at:
                        type: string
                      duration:
                        type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      results:
                        type: object
                        properties:
                          step:
                            type: string
                          step_message:
                            type: string
                          products_processed:
                            type: integer
                          total_products:
                            type: integer
                          completed_at:
                            type: string
                      total_items:
                        type: integer
                      processed_items:
                        type: integer
                      progress_percentage:
                        type: integer
                      progress_mode:
                        type: string
                      stages:
                        type: string
                        nullable: true
                example:
                  data:
                    id: 12345
                    job_type: App\Models\TrackedJobLog
                    queue: default
                    job_name: 'Sync Inventory to TikTok Shop: My TikTok Store'
                    status: completed
                    related_model:
                      id: 12
                      type: Modules\TikTokShop\Entities\TikTokShopIntegrationInstance
                      reference: My TikTok Store
                    related_model_reference: My TikTok Store
                    messages: []
                    attempted_at: '2026-06-20T08:09:30.000000Z'
                    completed_at: '2026-06-20T08:10:00.000000Z'
                    duration: 30
                    created_at: '2026-06-20T08:09:29.000000Z'
                    updated_at: '2026-06-20T08:10:00.000000Z'
                    results:
                      step: complete
                      step_message: Pushed inventory for 20 listings
                      products_processed: 20
                      total_products: 20
                      completed_at: '2026-06-20T08:10:00+00:00'
                    total_items: 20
                    processed_items: 20
                    progress_percentage: 100
                    progress_mode: items
                    stages: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-tiktok-shop-integration-instances-integration-instance-id-inventory-sync-progress-tracked-job-log-id
  /api/tiktok-shop/integration-instances/{integration_instance_id}/inventory/fetch-live:
    post:
      tags:
      - TikTok Shop
      summary: Fetch Live Inventory
      description: Fetch live per-warehouse quantities from TikTok Shop into the sales-channel
        cache. TikTok has no bulk inventory-read endpoint, so this issues per-product
        detail GETs for every product with at least one mapped SKU. This is an inbound
        observation only — it writes `sales_channel_quantity` / `sales_channel_quantity_updated_at`
        and never the push timestamp. Runs asynchronously and returns a tracked-job
        id you can poll via Get Fetch Live Progress. Requires a Bearer token.
      requestBody:
        content: {}
      parameters:
      - name: integration_instance_id
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 12345
                  message: Fetch live inventory job has been queued
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-tiktok-shop-integration-instances-integration-instance-id-inventory-fetch-live
  /api/tiktok-shop/integration-instances/{integration_instance_id}/inventory/fetch-live-progress/{tracked_job_log_id}:
    get:
      tags:
      - TikTok Shop
      summary: Get Fetch Live Progress
      description: Poll the tracked-job log for a fetch-live job (see Fetch Live Inventory).
        Returns the TrackedJobLog resource with status, per-product progress, and
        completion results. Requires a Bearer token.
      parameters:
      - name: integration_instance_id
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: tracked_job_log_id
        in: path
        schema:
          type: string
        required: true
        description: The tracked job log ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      job_type:
                        type: string
                      queue:
                        type: string
                      job_name:
                        type: string
                      status:
                        type: string
                      related_model:
                        type: object
                        properties:
                          id:
                            type: integer
                          type:
                            type: string
                          reference:
                            type: string
                      related_model_reference:
                        type: string
                      messages:
                        type: array
                      attempted_at:
                        type: string
                      completed_at:
                        type: string
                      duration:
                        type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      results:
                        type: object
                        properties:
                          step:
                            type: string
                          step_message:
                            type: string
                          products_processed:
                            type: integer
                          total_products:
                            type: integer
                          cache_entries_updated:
                            type: integer
                          failed_count:
                            type: integer
                          has_failures:
                            type: boolean
                          completed_at:
                            type: string
                      total_items:
                        type: integer
                      processed_items:
                        type: integer
                      progress_percentage:
                        type: integer
                      progress_mode:
                        type: string
                      stages:
                        type: string
                        nullable: true
                example:
                  data:
                    id: 12345
                    job_type: App\Models\TrackedJobLog
                    queue: default
                    job_name: 'Fetch Live TikTok Shop Inventory: My TikTok Store'
                    status: completed
                    related_model:
                      id: 12
                      type: Modules\TikTokShop\Entities\TikTokShopIntegrationInstance
                      reference: My TikTok Store
                    related_model_reference: My TikTok Store
                    messages: []
                    attempted_at: '2026-06-20T08:09:30.000000Z'
                    completed_at: '2026-06-20T08:10:00.000000Z'
                    duration: 30
                    created_at: '2026-06-20T08:09:29.000000Z'
                    updated_at: '2026-06-20T08:10:00.000000Z'
                    results:
                      step: complete
                      step_message: Fetched 120 inventory levels across 45 products
                      products_processed: 45
                      total_products: 45
                      cache_entries_updated: 120
                      failed_count: 0
                      has_failures: false
                      completed_at: '2026-06-20T08:10:00+00:00'
                    total_items: 45
                    processed_items: 45
                    progress_percentage: 100
                    progress_mode: items
                    stages: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-tiktok-shop-integration-instances-integration-instance-id-inventory-fetch-live-progress-tracked-job-log-id
  /api/tiktok-shop/packages:
    get:
      tags:
      - TikTok Shop
      summary: List Packages
      description: 'Paginated list of TikTok Shop packages across one or many integration
        instances. Includes related order summary.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Bearer token required.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        tiktok_shop_order_id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        package_id:
                          type: string
                        tracking_number:
                          type: string
                        shipping_provider_id:
                          type: string
                        shipping_provider_name:
                          type: string
                        package_status:
                          type: string
                        shipped_at:
                          type: string
                        delivered_at:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                        updated_at:
                          type: string
                        order:
                          type: object
                          properties:
                            id:
                              type: integer
                            tiktok_order_id:
                              type: string
                            integration_instance_id:
                              type: integer
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                  first_page_url:
                    type: string
                  last_page_url:
                    type: string
                  next_page_url:
                    type: string
                  prev_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                example:
                  data:
                  - id: 42
                    tiktok_shop_order_id: 1234
                    integration_instance_id: 1
                    package_id: P-9876543210
                    tracking_number: 1ZTEST123456789
                    shipping_provider_id: ups
                    shipping_provider_name: UPS
                    package_status: IN_TRANSIT
                    shipped_at: '2026-04-20T15:32:00Z'
                    delivered_at: null
                    created_at: '2026-04-20T10:00:00Z'
                    updated_at: '2026-04-20T15:32:00Z'
                    order:
                      id: 1234
                      tiktok_order_id: 576XXXXXXXXXXX
                      integration_instance_id: 1
                  current_page: 1
                  last_page: 5
                  per_page: 15
                  total: 73
                  from: 1
                  to: 15
                  first_page_url: https://example.test/api/tiktok-shop/packages?page=1
                  last_page_url: https://example.test/api/tiktok-shop/packages?page=5
                  next_page_url: https://example.test/api/tiktok-shop/packages?page=2
                  prev_page_url: null
                  path: https://example.test/api/tiktok-shop/packages
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-tiktok-shop-packages
  /api/tiktok-shop/integration-instances/{integration_instance_id}/fulfillments/pending:
    get:
      tags:
      - TikTok Shop
      summary: List Pending Fulfillments
      description: 'Paginated list of SalesOrderFulfillment records awaiting TikTok
        tracking submission for the given integration instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Returns LengthAwarePaginator of pending sales order fulfillment object.'
      parameters:
      - name: integration_instance_id
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-tiktok-shop-integration-instances-integration-instance-id-fulfillments-pending
  /api/tiktok-shop/integration-instances/{integration_instance_id}/fulfillments/stats:
    get:
      tags:
      - TikTok Shop
      summary: Fulfillment Sync Stats
      description: "Counts and sync-schedule note for the fulfillments page.\n\n:::info[Authorization]\n\
        Any valid API token can call this endpoint — no specific scope required. [Manage\
        \ tokens](https://app.sku.io/settings/api).\n:::\n\nResponse:\n```json\n{\n\
        \  \"data\": {\n    \"pending_sync_count\": 0,\n    \"mismatch_count\": 0,\n\
        \    \"sync_schedule\": {\n      \"interval\": 0,\n      \"unit\": \"event\"\
        ,\n      \"description\": \"Tracking is automatically submitted to TikTok\
        \ Shop when an order is fulfilled in SKU.io.\"\n    }\n  }\n}\n```"
      parameters:
      - name: integration_instance_id
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-tiktok-shop-integration-instances-integration-instance-id-fulfillments-stats
  /api/tiktok-shop/integration-instances/{integration_instance_id}/fulfillments/{sales_order_fulfillment_id}/submit:
    post:
      tags:
      - TikTok Shop
      summary: Submit Single Fulfillment
      description: 'Submit one SalesOrderFulfillment''s tracking to TikTok Shop.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Body:

        - `force_submit` (optional, bool) — bypass non-production guard.


        Returns 200 with `skipped_non_production: true` when not on production and
        `force_submit` is false. Returns 422 on TikTok submission failure.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                force_submit:
                  type: boolean
              example:
                force_submit: false
      parameters:
      - name: integration_instance_id
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: sales_order_fulfillment_id
        in: path
        schema:
          type: string
        required: true
        description: The sales order fulfillment ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-tiktok-shop-integration-instances-integration-instance-id-fulfillments-sales-order-fulfillment-id-submit
  /api/tiktok-shop/integration-instances/{integration_instance_id}/fulfillments/submit-bulk:
    post:
      tags:
      - TikTok Shop
      summary: Submit Bulk Fulfillments
      description: 'Submit tracking for a list of SalesOrderFulfillment IDs.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Body:

        - `ids` (required, `array<int>`) — must exist in `sales_order_fulfillments`.

        - `force_submit` (optional, bool)


        Response `data`: `{ submitted: int, failed: int }`. `errors` lists failures
        per ID.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
                force_submit:
                  type: boolean
              example:
                ids:
                - 101
                - 102
                - 103
                force_submit: false
      parameters:
      - name: integration_instance_id
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-tiktok-shop-integration-instances-integration-instance-id-fulfillments-submit-bulk
  /api/tiktok-shop/integration-instances/{integration_instance_id}/fulfillments/submit-all:
    post:
      tags:
      - TikTok Shop
      summary: Submit All Pending Fulfillments
      description: 'Submit tracking for every pending fulfillment for this integration
        instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Body:

        - `force_submit` (optional, bool)


        Same response shape as submit-bulk.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                force_submit:
                  type: boolean
              example:
                force_submit: false
      parameters:
      - name: integration_instance_id
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-tiktok-shop-integration-instances-integration-instance-id-fulfillments-submit-all
  /api/tiktok-shop/returns:
    get:
      tags:
      - TikTok Shop
      summary: List Returns
      parameters:
      - name: filter[integration_instance_ids]
        in: query
        schema:
          type: string
        example: '{{integration_instance_id}}'
        description: Filter by integration instance ids (see the Filtering & Sorting
          guide for operators).
      - name: per_page
        in: query
        schema:
          type: integer
        example: '15'
        description: Results per page (default 10).
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      description: 'List Returns


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      operationId: get-api-tiktok-shop-returns
  /api/tiktok-shop/returns/{return_id}:
    get:
      tags:
      - TikTok Shop
      summary: Show Return
      description: 'Returns a single TikTok Shop return with the related order eager-loaded.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Requires Bearer token.'
      parameters:
      - name: return_id
        in: path
        required: true
        schema:
          type: string
        description: The return_id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      tiktok_return_id:
                        type: string
                      return_status:
                        type: string
                      return_reason:
                        type: string
                      order:
                        type: object
                        properties:
                          id:
                            type: integer
                          tiktok_order_id:
                            type: string
                example:
                  data:
                    id: 700
                    tiktok_return_id: '5798833445566'
                    return_status: RETURN_REQUESTED
                    return_reason: Item not as described
                    order:
                      id: 100
                      tiktok_order_id: '576461413164253045'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-tiktok-shop-returns-return-id
  /api/tiktok-shop/integration-instances/{integration_instance_id}/returns/sync:
    post:
      tags:
      - TikTok Shop
      summary: Sync Returns (Tracked)
      description: 'Dispatches a background job for the instance. Returns a tracked_job_log_id.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties: {}
              example: {}
      parameters:
      - name: integration_instance_id
        in: path
        required: true
        schema:
          type: string
        description: The integration_instance_id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 9879
                  message: Returns sync started.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-tiktok-shop-integration-instances-integration-instance-id-returns-sync
  /api/tiktok-shop/refunds:
    get:
      tags:
      - TikTok Shop
      summary: List Refunds
      parameters:
      - name: filter[integration_instance_ids]
        in: query
        schema:
          type: string
        example: '{{integration_instance_id}}'
        description: Filter by integration instance ids (see the Filtering & Sorting
          guide for operators).
      - name: per_page
        in: query
        schema:
          type: integer
        example: '15'
        description: Results per page (default 10).
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      description: 'List Refunds


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      operationId: get-api-tiktok-shop-refunds
  /api/tiktok-shop/refunds/{refund_id}:
    get:
      tags:
      - TikTok Shop
      summary: Show Refund
      description: 'Returns a single TikTok Shop refund with the related order eager-loaded.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Requires Bearer token.'
      parameters:
      - name: refund_id
        in: path
        required: true
        schema:
          type: string
        description: The refund_id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      tiktok_refund_id:
                        type: string
                      refund_status:
                        type: string
                      refund_amount:
                        type: number
                      order:
                        type: object
                        properties:
                          id:
                            type: integer
                          tiktok_order_id:
                            type: string
                example:
                  data:
                    id: 850
                    tiktok_refund_id: '9982334455667'
                    refund_status: SUCCESS
                    refund_amount: 49.99
                    order:
                      id: 100
                      tiktok_order_id: '576461413164253045'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-tiktok-shop-refunds-refund-id
  /api/tiktok-shop/integration-instances/{integration_instance_id}/refunds/sync:
    post:
      tags:
      - TikTok Shop
      summary: Sync Refunds (Tracked)
      description: 'Dispatches a background job for the instance. Returns a tracked_job_log_id.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties: {}
              example: {}
      parameters:
      - name: integration_instance_id
        in: path
        required: true
        schema:
          type: string
        description: The integration_instance_id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 9880
                  message: Refunds sync started.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-tiktok-shop-integration-instances-integration-instance-id-refunds-sync
  /api/tiktok-shop/transactions:
    get:
      tags:
      - TikTok Shop
      summary: List Transactions
      description: 'Paginated list of TikTok Shop transactions (statement transactions)
        across integration instances. Supports Spatie QueryBuilder filters and sorts.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Allowed filters: `integration_instance_ids` (comma-separated), `transaction_type`
        (exact), `currency` (exact), `tiktok_transaction_id` (exact), `adjustment_id`
        (exact), `associated_order_id` (exact), `related_order_id` (exact), `transaction_time_from`/`transaction_time_to`
        (Y-m-d or m/d/Y), `statement_time_from`/`statement_time_to`, `amount_min`/`amount_max`
        (numeric), `search` (matches across tiktok_transaction_id, related_order_id,
        adjustment_id, associated_order_id, transaction_type, settlement_id).


        Allowed sorts: `id`, `tiktok_transaction_time`, `statement_time`, `amount`,
        `net_amount`, `settlement_amount`, `fee_amount`, `created_at`, `updated_at`.
        Prefix with `-` for desc.'
      parameters:
      - name: filter[integration_instance_ids]
        in: query
        schema:
          type: string
        description: Comma-separated integration instance IDs
        example: '{{integration_instance_id}}'
      - name: per_page
        in: query
        schema:
          type: integer
        example: '15'
        description: Results per page (default 10).
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-tiktok-shop-transactions
  /api/tiktok-shop/transactions/{transaction_id}:
    get:
      tags:
      - TikTok Shop
      summary: Get Transaction
      description: 'Returns a single TikTok Shop transaction with its `integration_instance`
        and (when matched by `related_order_id` -> `tiktok_order_id`) `order` relations
        eager-loaded for the detail page. Includes native columns for money breakdown
        (revenue_amount, fee_amount, tax_amount, net_amount, settlement_amount, shipping_cost_amount,
        reserve_amount), identifiers (adjustment_id, associated_order_id), `statement_time`,
        and JSON sub-structures `fee_breakdown_json` / `tax_breakdown_json`.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: transaction_id
        in: path
        schema:
          type: string
        required: true
        description: The transaction ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-tiktok-shop-transactions-transaction-id
  /api/tiktok-shop/integration-instances/{integration_instance_id}/transactions/{transaction_id}/raw:
    get:
      tags:
      - TikTok Shop
      summary: Get Raw Transaction from TikTok
      description: 'Fetches the live transaction JSON directly from the TikTok Shop
        Finance API for a single previously-synced transaction. It reads the parent
        statement''s transactions via `GET /finance/202309/statements/{statement_id}/statement_transactions`
        (paginated via `page_token`, `sort_field=order_create_time`) and returns the
        entry whose id matches the stored `tiktok_transaction_id`. Mirrors the `Get
        Raw Order from TikTok` pattern — used by the frontend Raw Data section as
        a fetch-on-demand tool to inspect the current upstream payload without writing
        it to the database.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Path params:

        - `tikTokShopIntegrationInstance` (required) — integration instance id. Must
        own the transaction, otherwise `403` is returned.

        - `tikTokShopTransaction` (required) — local TikTokShopTransaction id. Must
        have a stored `statement_id`, otherwise `422` is returned.


        Returns: `{ data: <raw TikTok Shop statement transaction object> | null }`
        (`null` when no matching row is found on the statement).'
      parameters:
      - name: integration_instance_id
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: transaction_id
        in: path
        schema:
          type: string
        required: true
        description: The transaction ID.
      responses:
        '403':
          description: Forbidden
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: Transaction does not belong to this integration instance
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                  message:
                    type: string
                example:
                  error: Raw transaction data is unavailable
                  message: This transaction has no associated statement to fetch from
                    TikTok Shop.
        '200':
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: Success
                  value:
                    data:
                      id: '7012345678901234567'
                      type: ORDER
                      order_id: '576461413038489876'
                      adjustment_id: null
                      transaction_time: 1745164200
                      statement_time: 1745250720
                      currency: USD
                      revenue_amount:
                        amount: '42.99'
                        currency: USD
                      fee_amount:
                        amount: '-3.50'
                        currency: USD
                      tax_amount:
                        amount: '-2.10'
                        currency: USD
                      net_amount:
                        amount: '37.39'
                        currency: USD
                      settlement_amount:
                        amount: '37.39'
                        currency: USD
                      shipping_cost_amount:
                        amount: '-3.00'
                        currency: USD
                      reserve_amount:
                        amount: '0.00'
                        currency: USD
                      fee_breakdown:
                      - type: PLATFORM_COMMISSION
                        amount:
                          amount: '-2.50'
                          currency: USD
                      - type: PAYMENT_FEE
                        amount:
                          amount: '-1.00'
                          currency: USD
                      tax_breakdown:
                      - type: SALES_TAX
                        amount:
                          amount: '-2.10'
                          currency: USD
                example-1:
                  summary: Not Found
                  value:
                    data: null
          description: Successful response
        '429': *id001
        '401': *id002
        '404': *id004
      operationId: get-api-tiktok-shop-integration-instances-integration-instance-id-transactions-transaction-id-raw
  /api/tiktok-shop/integration-instances/{integration_instance_id}/transactions/sync:
    post:
      tags:
      - TikTok Shop
      summary: Sync Transactions (Tracked)
      description: 'Dispatches a background job. Returns a tracked_job_log_id.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Fields:

        - since (nullable, date): pull transactions since this time. Defaults to 7
        days ago.


        Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                since:
                  type: string
              example:
                since: '2026-04-19T00:00:00Z'
      parameters:
      - name: integration_instance_id
        in: path
        required: true
        schema:
          type: string
        description: The integration_instance_id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 9881
                  message: Transactions sync started.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-tiktok-shop-integration-instances-integration-instance-id-transactions-sync
  /api/tiktok-shop/integration-instances/{integration_instance_id}/warehouse-mappings:
    get:
      tags:
      - TikTok Shop
      summary: List Warehouse Mappings
      description: 'Returns the existing warehouse mappings, the mappable TikTok Shop
        warehouses for the instance, and all SKU.io warehouses.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Only sales/pickup warehouses are returned in `tiktok_warehouses` — warehouses
        with `type` `RETURN_WAREHOUSE` are excluded here (they still appear on the
        Locations tab). Warehouses with a null `type` are kept so unclassified warehouses
        remain mappable.


        Each SKU.io warehouse includes a `display_name`: supplier warehouses are prefixed
        with the supplier name (e.g. "Acme Supply Co - Main Warehouse") so the mapping
        dropdown isn''t a wall of identical names; non-supplier warehouses fall back
        to the plain name.


        Requires Bearer token.'
      parameters:
      - name: integration_instance_id
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      mappings:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            integration_instance_id:
                              type: integer
                            tiktok_shop_warehouse_id:
                              type: integer
                            sku_io_warehouse_id:
                              type: integer
                      tiktok_warehouses:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            tiktok_warehouse_id:
                              type: string
                            type:
                              type: string
                      sku_warehouses:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            display_name:
                              type: string
                example:
                  data:
                    mappings:
                    - id: 1
                      integration_instance_id: 12
                      tiktok_shop_warehouse_id: 30
                      sku_io_warehouse_id: 5
                    tiktok_warehouses:
                    - id: 30
                      name: Acme US Warehouse
                      tiktok_warehouse_id: '7497123456789'
                      type: SALES_WAREHOUSE
                    sku_warehouses:
                    - id: 5
                      name: Main Warehouse
                      display_name: Acme Supply Co - Main Warehouse
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-tiktok-shop-integration-instances-integration-instance-id-warehouse-mappings
    post:
      tags:
      - TikTok Shop
      summary: Upsert Warehouse Mapping
      description: 'Create or update a warehouse mapping for the instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Fields:

        - tiktok_shop_warehouse_id (required, integer, exists tiktok_shop_warehouses.id)

        - sku_io_warehouse_id (required, integer, exists warehouses.id)


        Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                tiktok_shop_warehouse_id:
                  type: integer
                sku_io_warehouse_id:
                  type: integer
              example:
                tiktok_shop_warehouse_id: 30
                sku_io_warehouse_id: 5
      parameters:
      - name: integration_instance_id
        in: path
        required: true
        schema:
          type: string
        description: The integration_instance_id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      tiktok_shop_warehouse_id:
                        type: integer
                      sku_io_warehouse_id:
                        type: integer
                example:
                  data:
                    id: 1
                    integration_instance_id: 12
                    tiktok_shop_warehouse_id: 30
                    sku_io_warehouse_id: 5
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-tiktok-shop-integration-instances-integration-instance-id-warehouse-mappings
  /api/tiktok-shop/integration-instances/{integration_instance_id}/warehouse-mappings/{tiktokShopWarehouseId}:
    delete:
      tags:
      - TikTok Shop
      summary: Delete Warehouse Mapping
      description: 'Deletes the mapping for the given TikTok Shop warehouse id.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Requires Bearer token.'
      parameters:
      - name: integration_instance_id
        in: path
        required: true
        schema:
          type: string
        description: The integration_instance_id identifier
      - name: tiktokShopWarehouseId
        in: path
        schema:
          type: string
        required: true
        description: The tiktok shop warehouse ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      deleted:
                        type: boolean
                example:
                  data:
                    deleted: true
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-tiktok-shop-integration-instances-integration-instance-id-warehouse-mappings-tiktokshopwarehouseid
  /api/tiktok-shop/integration-instances/{integration_instance_id}/shipping-method-mappings:
    get:
      tags:
      - TikTok Shop
      summary: List Shipping Method Mappings
      description: 'Returns existing mappings, the TikTok shipping provider list (best-effort),
        and all SKU.io shipping methods.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Requires Bearer token.'
      parameters:
      - name: integration_instance_id
        in: path
        required: true
        schema:
          type: string
        description: The integration_instance_id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      mappings:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            integration_instance_id:
                              type: integer
                            sku_io_shipping_method_id:
                              type: integer
                            tiktok_shipping_provider_id:
                              type: string
                            tiktok_shipping_provider_name:
                              type: string
                      tiktok_shipping_providers:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: string
                            name:
                              type: string
                      sku_shipping_methods:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                example:
                  data:
                    mappings:
                    - id: 2
                      integration_instance_id: 12
                      sku_io_shipping_method_id: 7
                      tiktok_shipping_provider_id: '7208012345678'
                      tiktok_shipping_provider_name: USPS
                    tiktok_shipping_providers:
                    - id: '7208012345678'
                      name: USPS
                    - id: '7208087654321'
                      name: FedEx
                    sku_shipping_methods:
                    - id: 7
                      name: USPS Priority
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-tiktok-shop-integration-instances-integration-instance-id-shipping-method-mappings
    post:
      tags:
      - TikTok Shop
      summary: Upsert Shipping Method Mapping
      description: 'Create or update a mapping between a SKU.io shipping method and
        a TikTok shipping provider.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Fields:

        - sku_io_shipping_method_id (required, integer, exists shipping_methods.id)

        - tiktok_shipping_provider_id (required, string, max 100)

        - tiktok_shipping_provider_name (nullable, string, max 255)


        Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                sku_io_shipping_method_id:
                  type: integer
                tiktok_shipping_provider_id:
                  type: string
                tiktok_shipping_provider_name:
                  type: string
              example:
                sku_io_shipping_method_id: 7
                tiktok_shipping_provider_id: '7208012345678'
                tiktok_shipping_provider_name: USPS
      parameters:
      - name: integration_instance_id
        in: path
        required: true
        schema:
          type: string
        description: The integration_instance_id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      sku_io_shipping_method_id:
                        type: integer
                      tiktok_shipping_provider_id:
                        type: string
                      tiktok_shipping_provider_name:
                        type: string
                example:
                  data:
                    id: 2
                    sku_io_shipping_method_id: 7
                    tiktok_shipping_provider_id: '7208012345678'
                    tiktok_shipping_provider_name: USPS
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-tiktok-shop-integration-instances-integration-instance-id-shipping-method-mappings
  /api/tiktok-shop/integration-instances/{integration_instance_id}/shipping-method-mappings/{skuShippingMethodId}:
    delete:
      tags:
      - TikTok Shop
      summary: Delete Shipping Method Mapping
      description: 'Deletes the mapping for the given SKU.io shipping method id.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Requires Bearer token.'
      parameters:
      - name: integration_instance_id
        in: path
        required: true
        schema:
          type: string
        description: The integration_instance_id identifier
      - name: skuShippingMethodId
        in: path
        schema:
          type: string
        required: true
        description: The sku shipping method ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      deleted:
                        type: boolean
                example:
                  data:
                    deleted: true
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-tiktok-shop-integration-instances-integration-instance-id-shipping-method-mappings-skushippingmethodid
  /api/tiktok-shop/integration-instances/{integration_instance_id}/payment-method-mappings:
    get:
      tags:
      - TikTok Shop
      summary: List Payment Method Mappings
      description: 'Returns existing mappings, distinct observed TikTok payment method
        names (from synced orders), and all SKU.io PaymentType records.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Requires Bearer token.'
      parameters:
      - name: integration_instance_id
        in: path
        required: true
        schema:
          type: string
        description: The integration_instance_id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      mappings:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            integration_instance_id:
                              type: integer
                            tiktok_payment_method_name:
                              type: string
                            sku_io_payment_type_id:
                              type: integer
                      tiktok_payment_methods:
                        type: array
                        items:
                          type: string
                      sku_payment_types:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                example:
                  data:
                    mappings:
                    - id: 3
                      integration_instance_id: 12
                      tiktok_payment_method_name: PayPal
                      sku_io_payment_type_id: 4
                    tiktok_payment_methods:
                    - Credit Card
                    - PayPal
                    sku_payment_types:
                    - id: 4
                      name: PayPal
                    - id: 5
                      name: Credit Card
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-tiktok-shop-integration-instances-integration-instance-id-payment-method-mappings
    post:
      tags:
      - TikTok Shop
      summary: Upsert Payment Method Mapping
      description: 'Create or update a mapping between a TikTok payment method name
        and a SKU.io PaymentType.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Fields:

        - tiktok_payment_method_name (required, string, max 150)

        - sku_io_payment_type_id (required, integer, exists payment_types.id)


        Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                tiktok_payment_method_name:
                  type: string
                sku_io_payment_type_id:
                  type: integer
              example:
                tiktok_payment_method_name: PayPal
                sku_io_payment_type_id: 4
      parameters:
      - name: integration_instance_id
        in: path
        required: true
        schema:
          type: string
        description: The integration_instance_id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      tiktok_payment_method_name:
                        type: string
                      sku_io_payment_type_id:
                        type: integer
                example:
                  data:
                    id: 3
                    tiktok_payment_method_name: PayPal
                    sku_io_payment_type_id: 4
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-tiktok-shop-integration-instances-integration-instance-id-payment-method-mappings
    delete:
      tags:
      - TikTok Shop
      summary: Delete Payment Method Mapping
      description: 'Deletes the mapping for a given TikTok payment method name.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Fields:

        - tiktok_payment_method_name (required, string)


        Requires Bearer token.'
      parameters:
      - name: integration_instance_id
        in: path
        required: true
        schema:
          type: string
        description: The integration_instance_id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      deleted:
                        type: boolean
                example:
                  data:
                    deleted: true
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-tiktok-shop-integration-instances-integration-instance-id-payment-method-mappings
  /api/tiktok-shop/mappings/available-fields:
    get:
      tags:
      - TikTok Shop
      summary: Get Available Fields
      description: 'Returns the catalog of available TikTok Shop source fields (grouped
        by Identifiers / Product Info / Variant Details / Pricing / Media / Timestamps)
        and SKU.io target fields (including dynamic ProductPricingTier / SupplierPricingTier
        / Attribute fields). Use this to populate field selectors before configuring
        mappings.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tiktok_fields:
                        type: object
                        properties:
                          tiktok_product_id:
                            type: object
                            properties:
                              name:
                                type: string
                              label:
                                type: string
                              type:
                                type: string
                              description:
                                type: string
                              group:
                                type: string
                          title:
                            type: object
                            properties:
                              name:
                                type: string
                              label:
                                type: string
                              type:
                                type: string
                              group:
                                type: string
                          seller_sku:
                            type: object
                            properties:
                              name:
                                type: string
                              label:
                                type: string
                              type:
                                type: string
                              group:
                                type: string
                          sale_price:
                            type: object
                            properties:
                              name:
                                type: string
                              label:
                                type: string
                              type:
                                type: string
                              group:
                                type: string
                      sku_fields:
                        type: object
                        properties:
                          sku:
                            type: object
                            properties:
                              name:
                                type: string
                              label:
                                type: string
                              type:
                                type: string
                              group:
                                type: string
                          item_name:
                            type: object
                            properties:
                              name:
                                type: string
                              label:
                                type: string
                              type:
                                type: string
                              group:
                                type: string
                          price.1.value:
                            type: object
                            properties:
                              name:
                                type: string
                              label:
                                type: string
                              type:
                                type: string
                              group:
                                type: string
                example:
                  data:
                    tiktok_fields:
                      tiktok_product_id:
                        name: tiktok_product_id
                        label: TikTok Product ID
                        type: string
                        description: Unique TikTok Shop product identifier
                        group: Identifiers
                      title:
                        name: title
                        label: Product Title
                        type: string
                        group: Product Info
                      seller_sku:
                        name: seller_sku
                        label: Seller SKU
                        type: string
                        group: Variant Details
                      sale_price:
                        name: sale_price
                        label: Sale Price
                        type: decimal
                        group: Pricing
                    sku_fields:
                      sku:
                        name: sku
                        label: SKU
                        type: string
                        group: Identifiers
                      item_name:
                        name: item_name
                        label: Item Name
                        type: string
                        group: Product Info
                      price.1.value:
                        name: price.1.value
                        label: Price (Default Tier)
                        type: decimal
                        group: Pricing
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-tiktok-shop-mappings-available-fields
  /api/tiktok-shop/integration-instances/{integration_instance_id}/mappings:
    get:
      tags:
      - TikTok Shop
      summary: Get Field Mappings
      description: 'Returns the full mapping picture for a TikTok Shop integration
        instance: available source/target fields, system defaults, custom (overridden)
        mappings persisted by the merchant, and the effective merged set used during
        product creation. Each mapping entry contains `listing_field` (TikTok side),
        `sku_field` (SKU.io side), and an optional `parsers` array of transforms (rules:
        `fr` find/replace, `tl` trim-left, `tr` trim-right, `append`).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integration_instance_id
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      integration_instance_id:
                        type: integer
                      integration_name:
                        type: string
                      mappings:
                        type: array
                        items:
                          type: object
                          properties:
                            listing_field:
                              type: string
                            sku_field:
                              type: string
                            parsers:
                              type: array
                      available_tiktok_fields:
                        type: object
                        properties:
                          title:
                            type: object
                            properties:
                              name:
                                type: string
                              label:
                                type: string
                              type:
                                type: string
                              group:
                                type: string
                      available_sku_fields:
                        type: object
                        properties:
                          item_name:
                            type: object
                            properties:
                              name:
                                type: string
                              label:
                                type: string
                              type:
                                type: string
                              group:
                                type: string
                      default_mappings:
                        type: array
                        items:
                          type: object
                          properties:
                            listing_field:
                              type: string
                            sku_field:
                              type: string
                            parsers:
                              type: array
                      custom_mappings:
                        type: array
                      effective_mappings:
                        type: array
                        items:
                          type: object
                          properties:
                            listing_field:
                              type: string
                            sku_field:
                              type: string
                            parsers:
                              type: array
                example:
                  data:
                    integration_instance_id: 1
                    integration_name: My TikTok Shop
                    mappings:
                    - listing_field: title
                      sku_field: item_name
                      parsers: []
                    - listing_field: seller_sku
                      sku_field: sku
                      parsers: []
                    - listing_field: sale_price
                      sku_field: price.1.value
                      parsers: []
                    available_tiktok_fields:
                      title:
                        name: title
                        label: Product Title
                        type: string
                        group: Product Info
                    available_sku_fields:
                      item_name:
                        name: item_name
                        label: Item Name
                        type: string
                        group: Product Info
                    default_mappings:
                    - listing_field: title
                      sku_field: item_name
                      parsers: []
                    custom_mappings: []
                    effective_mappings:
                    - listing_field: title
                      sku_field: item_name
                      parsers: []
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-tiktok-shop-integration-instances-integration-instance-id-mappings
    put:
      tags:
      - TikTok Shop
      summary: Update Field Mappings
      description: 'Replace the custom field mappings for this integration instance.
        Body: `mappings` (array, required) — each entry has `listing_field` (string,
        required), `sku_field` (string, required), and `parsers` (array, optional;
        each parser has `rule` one of `fr`/`tl`/`tr`/`append` and `args` shape depending
        on rule). The submitted set fully replaces any existing custom mappings; system
        defaults remain in effect for fields not included. Returns the refreshed effective
        mappings.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                mappings:
                  type: array
                  items:
                    type: object
                    properties:
                      listing_field:
                        type: string
                      sku_field:
                        type: string
                      parsers:
                        type: array
              example:
                mappings:
                - listing_field: title
                  sku_field: item_name
                  parsers: []
                - listing_field: seller_sku
                  sku_field: sku
                  parsers: []
                - listing_field: sale_price
                  sku_field: price.1.value
                  parsers:
                  - rule: fr
                    args:
                      find: USD
                      replace: ''
      parameters:
      - name: integration_instance_id
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      integration_instance_id:
                        type: integer
                      integration_name:
                        type: string
                      mappings:
                        type: array
                        items:
                          type: object
                          properties:
                            listing_field:
                              type: string
                            sku_field:
                              type: string
                            parsers:
                              type: array
                      effective_mappings:
                        type: array
                        items:
                          type: object
                          properties:
                            listing_field:
                              type: string
                            sku_field:
                              type: string
                            parsers:
                              type: array
                  message:
                    type: string
                example:
                  data:
                    integration_instance_id: 1
                    integration_name: My TikTok Shop
                    mappings:
                    - listing_field: title
                      sku_field: item_name
                      parsers: []
                    - listing_field: seller_sku
                      sku_field: sku
                      parsers: []
                    effective_mappings:
                    - listing_field: title
                      sku_field: item_name
                      parsers: []
                    - listing_field: seller_sku
                      sku_field: sku
                      parsers: []
                  message: Field mappings updated successfully
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      mappings:
                        type: array
                        items:
                          type: string
                example:
                  message: The mappings field is required.
                  errors:
                    mappings:
                    - The mappings field is required.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: put-api-tiktok-shop-integration-instances-integration-instance-id-mappings
  /api/tiktok-shop/webhook-events:
    get:
      tags:
      - TikTok Shop
      summary: List Webhook Events
      description: 'Paginated list of TikTok Shop webhook events across one or many
        integration instances.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Bearer token required.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        topic:
                          type: string
                        unique_id:
                          type: string
                        json_data:
                          type: object
                          properties:
                            shop_id:
                              type: string
                            type:
                              type: integer
                            data:
                              type: object
                              properties:
                                order_id:
                                  type: string
                                order_status:
                                  type: string
                        processing_status:
                          type: string
                        processed_at:
                          type: string
                        processing_attempts:
                          type: integer
                        processing_error:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 101
                    integration_instance_id: 1
                    topic: ORDER_STATUS_CHANGE
                    unique_id: 576XXXXXXXXXXX
                    json_data:
                      shop_id: '7400000000000000000'
                      type: 1
                      data:
                        order_id: 576XXXXXXXXXXX
                        order_status: AWAITING_SHIPMENT
                    processing_status: completed
                    processed_at: '2026-04-20T10:00:05Z'
                    processing_attempts: 1
                    processing_error: null
                    created_at: '2026-04-20T10:00:00Z'
                    updated_at: '2026-04-20T10:00:05Z'
                  current_page: 1
                  last_page: 3
                  per_page: 15
                  total: 42
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-tiktok-shop-webhook-events
    delete:
      tags:
      - TikTok Shop
      summary: Delete All Webhook Events
      description: 'Permanently delete ALL webhook events, optionally scoped to one
        or more integration instances. Cannot be undone.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Bearer token required.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  deleted_count:
                    type: integer
                example:
                  message: All events deleted
                  deleted_count: 44
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: delete-api-tiktok-shop-webhook-events
  /api/tiktok-shop/webhook-events/stats:
    get:
      tags:
      - TikTok Shop
      summary: Get Webhook Event Stats
      description: 'Counts of webhook events grouped by processing status (pending,
        processing, completed, failed) plus a total. Used to power the summary cards
        on the Webhooks Events tab.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Bearer token required.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      pending_count:
                        type: integer
                      processing_count:
                        type: integer
                      completed_count:
                        type: integer
                      failed_count:
                        type: integer
                      total_count:
                        type: integer
                example:
                  data:
                    pending_count: 3
                    processing_count: 1
                    completed_count: 38
                    failed_count: 2
                    total_count: 44
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-tiktok-shop-webhook-events-stats
  /api/tiktok-shop/webhook-events/{tikTokShopWebhookEvent}:
    get:
      tags:
      - TikTok Shop
      summary: Show Webhook Event
      description: 'Show a single webhook event including its raw payload.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Bearer token required.'
      parameters:
      - name: tikTokShopWebhookEvent
        in: path
        schema:
          type: string
        required: true
        description: The tik tok shop webhook event ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      topic:
                        type: string
                      unique_id:
                        type: string
                      json_data:
                        type: object
                        properties:
                          shop_id:
                            type: string
                          type:
                            type: integer
                          data:
                            type: object
                            properties:
                              order_id:
                                type: string
                              order_status:
                                type: string
                      processing_status:
                        type: string
                      processed_at:
                        type: string
                      processing_attempts:
                        type: integer
                      processing_error:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 101
                    integration_instance_id: 1
                    topic: ORDER_STATUS_CHANGE
                    unique_id: 576XXXXXXXXXXX
                    json_data:
                      shop_id: '7400000000000000000'
                      type: 1
                      data:
                        order_id: 576XXXXXXXXXXX
                        order_status: AWAITING_SHIPMENT
                    processing_status: completed
                    processed_at: '2026-04-20T10:00:05Z'
                    processing_attempts: 1
                    processing_error: null
                    created_at: '2026-04-20T10:00:00Z'
                    updated_at: '2026-04-20T10:00:05Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-tiktok-shop-webhook-events-tiktokshopwebhookevent
    delete:
      tags:
      - TikTok Shop
      summary: Delete Webhook Event
      description: 'Permanently delete a single webhook event.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Bearer token required.'
      parameters:
      - name: tikTokShopWebhookEvent
        in: path
        schema:
          type: string
        required: true
        description: The tik tok shop webhook event ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Event deleted
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-tiktok-shop-webhook-events-tiktokshopwebhookevent
  /api/tiktok-shop/webhook-events/{tikTokShopWebhookEvent}/process:
    post:
      tags:
      - TikTok Shop
      summary: Process Webhook Event
      description: 'Re-dispatch the processing job for a webhook event without resetting
        its status.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Bearer token required.'
      requestBody:
        content: {}
      parameters:
      - name: tikTokShopWebhookEvent
        in: path
        schema:
          type: string
        required: true
        description: The tik tok shop webhook event ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Event queued for processing
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-tiktok-shop-webhook-events-tiktokshopwebhookevent-process
  /api/tiktok-shop/webhook-events/{tikTokShopWebhookEvent}/reprocess:
    post:
      tags:
      - TikTok Shop
      summary: Reprocess Webhook Event
      description: 'Reset a webhook event back to pending (clears processed_at and
        processing_error) and re-dispatch the processing job. Use this for failed
        events.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Bearer token required.'
      requestBody:
        content: {}
      parameters:
      - name: tikTokShopWebhookEvent
        in: path
        schema:
          type: string
        required: true
        description: The tik tok shop webhook event ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Event reset and queued for reprocessing
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-tiktok-shop-webhook-events-tiktokshopwebhookevent-reprocess
  /api/tiktok-shop/webhook-events/bulk-delete:
    post:
      tags:
      - TikTok Shop
      summary: Bulk Delete Webhook Events
      description: 'Permanently delete multiple webhook events by ID.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Request body fields:

        - ids (required, array of integers): IDs of events to delete


        Authentication: Bearer token required.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 101
                - 102
                - 103
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  deleted_count:
                    type: integer
                example:
                  message: Events deleted
                  deleted_count: 3
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-tiktok-shop-webhook-events-bulk-delete
  /api/tiktok-shop/webhook-events/bulk-process-pending:
    post:
      tags:
      - TikTok Shop
      summary: Bulk Process Pending Webhook Events
      description: 'Loop pending webhook events and dispatch a background job for
        each. Optionally scope to specific integration instances and cap the batch
        with `limit` (max 500, default 100).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Mirrors Shopify''s processPendingEvents bulk handler. Returns `queued_count`
        (number of jobs dispatched).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                integration_instance_ids:
                  type: string
                limit:
                  type: integer
              example:
                integration_instance_ids: 1,2
                limit: 100
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      queued_count:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    queued_count: 17
                  message: Pending webhook events queued for processing
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-tiktok-shop-webhook-events-bulk-process-pending
  /api/tiktok-shop/webhook-events/bulk-retry-failed:
    post:
      tags:
      - TikTok Shop
      summary: Bulk Retry Failed Webhook Events
      description: 'Reset failed webhook events to pending and re-dispatch a background
        job for each. Optionally scope to integration instances and cap with `limit`
        (max 500, default 100).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Mirrors Shopify''s retryFailedEvents bulk handler. Returns `retried_count`.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                integration_instance_ids:
                  type: string
                limit:
                  type: integer
              example:
                integration_instance_ids: '1'
                limit: 100
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      retried_count:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    retried_count: 8
                  message: Failed webhook events reset and queued for retry
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-tiktok-shop-webhook-events-bulk-retry-failed
  /webhooks/tiktok-shop:
    post:
      tags:
      - TikTok Shop
      summary: Receive Webhook (TikTok → SKU.io)
      description: 'Global (per-environment) endpoint that receives signed webhook
        events from TikTok Shop — this is the URL configured on the TikTok Shop app.


        No bearer auth: the request is authenticated by TikTok''s HMAC signature in
        the `Authorization` header (HMAC-SHA256 over `app_secret + raw_body`, keyed
        by the app secret — sandbox or production secret chosen by the resolved instance''s
        environment setting).


        **Tenant routing:** every tenant''s webhooks arrive at this ONE URL. The `InitializeTenantFromWebhookPayload`
        middleware resolves the tenant from the payload `shop_id` (top-level or `data.shop_id`)
        via the central `tenant_integration_routes` registry (external_key = the instance''s
        primary shop id), forwards to the tenant''s home pod if needed, initialises
        tenancy, and exposes the instance to the controller.


        **Flow:** 400 empty body → 404 missing/unknown `shop_id` → 401 invalid signature
        → 422 missing `type` → 200 event persisted + processing job dispatched.


        Topics by `type`: 1 ORDER_STATUS_CHANGE, 2 REVERSE_STATUS_CHANGE, 5 PACKAGE_UPDATE,
        7 PRODUCT_STATUS_CHANGE, 12 AUTHORIZATION_CANCELLATION; unknown types stored
        as TYPE_{n}.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                shop_id:
                  type: string
                type:
                  type: integer
                tts_notification_id:
                  type: string
                timestamp:
                  type: integer
                data:
                  type: object
                  properties:
                    order_id:
                      type: string
                    order_status:
                      type: string
              example:
                shop_id: '7495092941234567890'
                type: 1
                tts_notification_id: 7development123456
                timestamp: 1717000000
                data:
                  order_id: '576461413038785752'
                  order_status: AWAITING_SHIPMENT
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  received:
                    type: boolean
                example:
                  received: true
        '401':
          description: Unauthorized
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: Invalid signature
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: text/html; charset=UTF-8
          content:
            text/plain:
              schema:
                type: string
                example: No tenant registered for this webhook payload key.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: Invalid webhook payload
        '429': *id001
      security: []
      operationId: post-webhooks-tiktok-shop
  /tiktok-shop/callback:
    get:
      tags:
      - TikTok Shop
      summary: OAuth Callback
      description: 'Browser redirect target after the merchant authorizes the app
        on TikTok. Exchanges the auth code for access/refresh tokens, persists a TikTokShopIntegrationInstance,
        syncs authorized shops, subscribes webhooks, dispatches the initial product
        + recent-order backfill on the interactive queue (a background job + a background
        job), and redirects into the SPA. NOT a JSON endpoint.


        The single registered callback URL lives on the central apex (app.sku.io),
        so the callback always lands there with no tenant header. Tenancy is restored
        from the tenant-prefixed state (`<tenantId>_<uuid>`), and the final redirect
        is built with TenantUrl::to so it targets the tenant''s OWN subdomain (e.g.
        https://siber.sku.io/v2/integrations/tiktok-shop/{id}/dashboard) — loading
        the SPA in tenant context instead of forcing the central ''Choose an account''
        picker. On invalid/expired state it redirects to the tenant subdomain''s /v2/integrations/tiktok-shop/new?error=...
        page.


        No auth middleware — the cached state UUID is the security mechanism.'
      parameters:
      - name: code
        in: query
        schema:
          type: string
        description: Authorization code returned by TikTok
        example: AUTH_CODE_FROM_TIKTOK
      - name: state
        in: query
        schema:
          type: string
        description: State UUID issued by /oauth/init
        example: 8c7e0d12-b91c-4d2b-a6f4-9c0a2bb1f0aa
      responses:
        '302':
          description: Found
          headers:
            Location:
              schema:
                type: string
                example: https://siber.sku.io/v2/integrations/tiktok-shop/12/dashboard
          content:
            text/plain:
              schema:
                type: string
                example: ''
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-tiktok-shop-callback
  /api/temu/config:
    get:
      tags:
      - Temu
      summary: Get Config
      description: 'Returns server-side capability flags used by the new-instance
        form on the frontend.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Response fields:**

        - `can_pick_environment` (bool) — `true` on non-production servers, `false`
        on production. The UI uses this to decide whether to render the sandbox/production
        toggle on the new-instance form. On a production server the `HasIntegrationEnvironment`
        trait pins PRODUCTION regardless of the user''s choice, so showing the toggle
        there would just be misleading.


        **Authentication:** Bearer token (Sanctum).'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 Success — Non-production server
                  value:
                    data:
                      can_pick_environment: true
                example-1:
                  summary: 200 Success — Production server
                  value:
                    data:
                      can_pick_environment: false
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-temu-config
  /api/temu/oauth/initialize:
    post:
      tags:
      - Temu
      summary: Initialize OAuth
      description: 'Starts a new Temu OAuth flow.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Generates a tenant-prefixed `state` so the OAuth callback (which lands on
        the central landlord domain with no tenant header) can recover tenancy from
        the state alone. Stores the chosen name + environment + integration_settings
        in a file cache for 1 hour so that `POST /api/temu/oauth/complete` can pick
        them back up after the merchant returns from Temu.


        The returned `authorization_url` is where the frontend redirects/pops up the
        merchant to authorize SKU.io as a Temu app.


        **Request body (TemuInitializeIntegrationData):**

        - `name` (string, required) — Display name for the new integration instance.

        - `environment` (string, optional) — One of `sandbox` or `production`. Honoured
        only on non-production servers; on prod the `HasIntegrationEnvironment` trait
        pins PRODUCTION regardless. Defaults to `sandbox` on non-prod, `production`
        on prod.

        - `integration_settings` (object, optional) — Free-form JSON persisted on
        the instance. Used by the inventory + sync modules.


        **Response data:**

        - `state` (string) — Tenant-prefixed UUID. Round-trips through the OAuth callback
        and must be passed back to `oauth/complete`.

        - `authorization_url` (string) — Full Temu authorization URL with `appKey`,
        `redirect_uri`, and `state` query params.


        **Authentication:** Bearer token (Sanctum).


        **Throws:** `Exception` when Temu app credentials for the selected environment
        are not configured (missing `temu.<env>.app_key` / `app_secret`).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                environment:
                  type: string
                integration_settings:
                  type: object
                  properties:
                    inventory:
                      type: object
                      properties:
                        warehouses:
                          type: array
              example:
                name: Acme US Storefront
                environment: sandbox
                integration_settings:
                  inventory:
                    warehouses: []
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      state:
                        type: string
                      authorization_url:
                        type: string
                example:
                  data:
                    state: 42_4f1a9b2e-37c5-4d8a-9b1f-7c4e9d2a5b18
                    authorization_url: https://agentseller-us.temu.com/sc/seller-open/authorize?appKey=temu_app_key_demo&redirect_uri=https%3A%2F%2Fapp.sku.io%2Fapi%2Ftemu%2Foauth%2Fcallback&state=42_4f1a9b2e-37c5-4d8a-9b1f-7c4e9d2a5b18
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      name:
                        type: array
                        items:
                          type: string
                example:
                  message: The name field is required.
                  errors:
                    name:
                    - The name field is required.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-temu-oauth-initialize
  /api/temu/oauth/complete:
    post:
      tags:
      - Temu
      summary: Complete OAuth
      description: 'Exchanges the OAuth authorization code returned by Temu for an
        access token and creates a new `TemuIntegrationInstance` persisted with that
        token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        The frontend calls this after Temu redirects the merchant back to `/v2/integrations/temu/callback`
        carrying `state`, `code`, and `callback_host`. The callback URL on the central
        landlord is `/api/temu/oauth/callback` (not documented here — it''s a browser-redirected
        endpoint, not a JSON API).


        After the instance is created, initial sync jobs (warehouses, carriers, categories,
        products, orders) are dispatched.


        **Request body (raw JSON, not a FormRequest):**

        - `state` (string, required) — The state returned by `oauth/initialize`. Used
        to look up the stored name + environment + integration_settings from the file
        cache.

        - `code` (string, required) — Authorization code returned by Temu in the redirect
        query string.

        - `callback_host` (string, optional) — API host Temu returned on the redirect
        (e.g. `openapi-b-us.temu.com`). Used as the API base URL for the new instance;
        falls back to `config(''temu.<env>.api_url'')` when not present.


        **Response:** A 201 Created with the newly-persisted `TemuIntegrationInstance`
        resource. The shape is the same as `GET /api/temu/{integrationInstance}` (the
        Temu integration instance object which extends sales channel integration list
        view object).


        **Authentication:** Bearer token (Sanctum).


        **Throws:** `Exception` when `state` or `code` is missing, when the OAuth
        session has expired, has already been completed, or when the token exchange
        with Temu fails.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                state:
                  type: string
                code:
                  type: string
                callback_host:
                  type: string
              example:
                state: 42_4f1a9b2e-37c5-4d8a-9b1f-7c4e9d2a5b18
                code: AUTH_CODE_FROM_TEMU_REDIRECT_abc123
                callback_host: openapi-b-us.temu.com
      parameters: []
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_name:
                        type: string
                      sales_channel_id:
                        type: integer
                      store:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      name:
                        type: string
                      integration_settings:
                        type: object
                        properties:
                          inventory:
                            type: object
                            properties:
                              warehouses:
                                type: array
                      is_automatic_sync_enabled:
                        type: boolean
                      has_warehouse_mappings:
                        type: boolean
                      has_carrier_mappings:
                        type: boolean
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  message: Temu integration created successfully
                  data:
                    id: 17
                    integration_name: Temu
                    sales_channel_id: 42
                    store:
                      id: 3
                      name: Acme US Storefront
                    name: Acme US Storefront
                    integration_settings:
                      inventory:
                        warehouses: []
                    is_automatic_sync_enabled: true
                    has_warehouse_mappings: false
                    has_carrier_mappings: false
                    created_at: '2026-06-19T18:42:11.000000Z'
                    updated_at: '2026-06-19T18:42:11.000000Z'
        '500':
          description: Internal Server Error
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Missing state parameter
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-temu-oauth-complete
  /api/temu/oauth/status:
    get:
      tags:
      - Temu
      summary: Get OAuth Status
      description: 'Polled by the frontend after the OAuth popup/redirect to learn
        the state of the OAuth session.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Used to determine whether Temu has called back yet, and what the next action
        is (e.g. proceed to `/oauth/complete`, or show a reconnection success toast).


        **Query parameters:**

        - `state` (string, required) — The state returned by `oauth/initialize`.


        **Response data (always returned with HTTP 200):**

        - `found` (bool) — `false` when state is missing, expired, or unknown. The
        remaining fields are omitted in that case (only `message` is present).

        - `completed` (bool) — `true` once `/oauth/complete` or a reconnection has
        marked the session as done.

        - `has_code` (bool) — `true` once the OAuth callback endpoint has received
        Temu''s redirect and stored the authorization code in cache. The frontend
        uses this to know it''s safe to call `/oauth/complete`.

        - `name` (string|null) — The display name the user picked at `/oauth/initialize`.

        - `message` (string, only on `found: false`) — Human-readable reason (missing
        parameter or expired session).


        **Authentication:** Bearer token (Sanctum).'
      parameters:
      - name: state
        in: query
        schema:
          type: string
        description: Tenant-prefixed state returned by /oauth/initialize.
        example: 42_4f1a9b2e-37c5-4d8a-9b1f-7c4e9d2a5b18
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 Success — In progress (code received, awaiting complete)
                  value:
                    data:
                      found: true
                      completed: false
                      has_code: true
                      name: Acme US Storefront
                example-1:
                  summary: 200 Success — Completed
                  value:
                    data:
                      found: true
                      completed: true
                      has_code: true
                      name: Acme US Storefront
                example-2:
                  summary: 200 Success — Not found / expired
                  value:
                    data:
                      found: false
                      message: OAuth session not found or expired
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-temu-oauth-status
  /api/temu/sandbox/initialize:
    post:
      tags:
      - Temu
      summary: Sandbox Initialize
      description: 'Creates a Temu sandbox integration instance **without** going
        through the OAuth flow.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Temu''s sandbox has no OAuth — the merchant is issued a static long-lived
        access token through the developer portal. SKU.io reads that token (plus the
        sandbox `app_key` and `app_secret`) from env / Secrets Manager via the `temu.sandbox.*`
        config keys and persists it on the new instance at creation time. The instance
        is created with `environment = sandbox`, its API base URL pinned to `temu.sandbox.api_url`,
        and the access token serialised onto the `authenticator` column.


        After creation, the same initial sync jobs (warehouses, carriers, categories,
        products, orders) are dispatched as for the production OAuth flow.


        **Refuses to run on a production server** — even if the call somehow arrived
        there, the `HasIntegrationEnvironment` trait would coerce the runtime env
        to PRODUCTION and the saved sandbox row would be misleading.


        **Request body (TemuInitializeIntegrationData):**

        - `name` (string, required) — Display name for the sandbox instance. If another
        instance with this exact name already exists, ` (N+1)` is appended.

        - `integration_settings` (object, optional) — Free-form JSON persisted on
        the instance.

        - `environment` (string, optional) — Accepted but ignored — sandbox is forced.


        **Response:** A 201 Created with the newly-persisted `TemuIntegrationInstance`
        resource and a `message`.


        **Authentication:** Bearer token (Sanctum).


        **Throws:** `Exception` when called on a production server, or when `TEMU_SANDBOX_APP_KEY`
        / `TEMU_SANDBOX_APP_SECRET` / `TEMU_SANDBOX_ACCESS_TOKEN` are not configured.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                integration_settings:
                  type: object
                  properties:
                    inventory:
                      type: object
                      properties:
                        warehouses:
                          type: array
              example:
                name: Temu Sandbox
                integration_settings:
                  inventory:
                    warehouses: []
      parameters: []
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_name:
                        type: string
                      sales_channel_id:
                        type: integer
                      store:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      name:
                        type: string
                      integration_settings:
                        type: object
                        properties:
                          inventory:
                            type: object
                            properties:
                              warehouses:
                                type: array
                      is_automatic_sync_enabled:
                        type: boolean
                      has_warehouse_mappings:
                        type: boolean
                      has_carrier_mappings:
                        type: boolean
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  message: Temu sandbox integration created successfully
                  data:
                    id: 18
                    integration_name: Temu
                    sales_channel_id: 43
                    store:
                      id: 4
                      name: Temu Sandbox
                    name: Temu Sandbox
                    integration_settings:
                      inventory:
                        warehouses: []
                    is_automatic_sync_enabled: true
                    has_warehouse_mappings: false
                    has_carrier_mappings: false
                    created_at: '2026-06-19T18:55:02.000000Z'
                    updated_at: '2026-06-19T18:55:02.000000Z'
        '500':
          description: Internal Server Error
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Temu sandbox credentials are not configured. Set TEMU_SANDBOX_APP_KEY,
                    TEMU_SANDBOX_APP_SECRET, and TEMU_SANDBOX_ACCESS_TOKEN in the
                    environment.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-temu-sandbox-initialize
  /api/temu/{integrationInstance}/reconnect:
    post:
      tags:
      - Temu
      summary: Reconnect Integration
      description: 'Re-authorizes an existing `TemuIntegrationInstance` with a fresh
        OAuth access token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Used when the original token has expired or been revoked. The frontend kicks
        off a normal OAuth flow (calls `/oauth/initialize` to get a state + authorization
        URL, sends the merchant to Temu, and the callback stores the authorization
        code under the same state). It then calls this endpoint to exchange that code
        for a new access token bound to the **existing** instance row — the row''s
        environment, name, integration_settings, etc. are preserved.


        In the typical browser-driven path the OAuth callback (`/api/temu/oauth/callback`)
        actually performs the reconnection itself when it detects existing instances
        and redirects with `isReconnect=true`. This endpoint exists for cases where
        the frontend wants to drive the reconnect explicitly.


        **Path parameters:**

        - `integrationInstance` (int, required) — The ID of the TemuIntegrationInstance
        to reconnect.


        **Request body (raw JSON):**

        - `state` (string, required) — The OAuth state from the just-completed reconnect
        authorization flow. Must already have a `code` stored in cache by the OAuth
        callback.


        **Response:** 200 OK with the refreshed `TemuIntegrationInstance` resource
        and a `message`.


        **Authentication:** Bearer token (Sanctum).


        **Throws:** `Exception` when `state` is missing, when the OAuth session has
        expired, has already been completed, or when Temu hasn''t yet posted the authorization
        code for this state.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                state:
                  type: string
              example:
                state: 42_4f1a9b2e-37c5-4d8a-9b1f-7c4e9d2a5b18
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Temu integration instance ID.
        example: '17'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_name:
                        type: string
                      sales_channel_id:
                        type: integer
                      store:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      name:
                        type: string
                      integration_settings:
                        type: object
                        properties:
                          inventory:
                            type: object
                            properties:
                              warehouses:
                                type: array
                      is_automatic_sync_enabled:
                        type: boolean
                      has_warehouse_mappings:
                        type: boolean
                      has_carrier_mappings:
                        type: boolean
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  message: Temu integration reconnected successfully
                  data:
                    id: 17
                    integration_name: Temu
                    sales_channel_id: 42
                    store:
                      id: 3
                      name: Acme US Storefront
                    name: Acme US Storefront
                    integration_settings:
                      inventory:
                        warehouses: []
                    is_automatic_sync_enabled: true
                    has_warehouse_mappings: true
                    has_carrier_mappings: true
                    created_at: '2026-06-10T08:00:00.000000Z'
                    updated_at: '2026-06-19T19:02:48.000000Z'
        '500':
          description: Internal Server Error
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: OAuth session not found or expired. Please restart the
                    authorization process.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-temu-integrationinstance-reconnect
  /api/temu/{integrationInstance}/test-connection:
    get:
      tags:
      - Temu
      summary: Test Connection
      description: 'Verifies that the stored Temu access token for a given integration
        instance is still valid by calling Temu''s `getWarehouses` endpoint (the cheapest
        read with no required parameters).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Used by the Integration Settings page to render a green/red status pill, and
        by the new-instance / reconnect flow to confirm the instance can actually
        talk to Temu before dispatching the initial sync jobs.


        This endpoint **always returns HTTP 200** — connectivity failures are reported
        in the `data.success` flag, not via HTTP status.


        **Path parameters:**

        - `integrationInstance` (int, required) — The ID of the TemuIntegrationInstance
        to test.


        **Response data:**

        - `success` (bool) — `true` when the token is valid and Temu responded; `false`
        otherwise.

        - `message` (string) — Human-readable description of the outcome (e.g. `Connection
        successful`, `Integration instance is not authenticated`, `Connection test
        failed: <upstream-error>`).


        **Authentication:** Bearer token (Sanctum).'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Temu integration instance ID.
        example: '17'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 Success — Connection OK
                  value:
                    data:
                      success: true
                      message: Connection successful
                example-1:
                  summary: 200 Success — Not authenticated
                  value:
                    data:
                      success: false
                      message: Integration instance is not authenticated
                example-2:
                  summary: 200 Success — Upstream failure
                  value:
                    data:
                      success: false
                      message: 'Connection test failed: Temu API returned 401 Unauthorized:
                        invalid access_token'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-temu-integrationinstance-test-connection
  /api/temu/{integrationInstance}/get-authorization-url:
    get:
      tags:
      - Temu
      summary: Get Authorization URL
      description: 'Builds and returns the Temu seller-consent URL for this integration
        instance. Direct the merchant to this URL to authorize (or re-authorize) the
        connection; after they approve access, Temu redirects back to the platform''s
        OAuth callback which completes the token exchange.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        The URL is assembled from the instance''s configured environment (production
        or sandbox), the registered application key, the platform callback address,
        and a state value that identifies this instance. This endpoint is read-only
        — it makes no calls to Temu and changes no data.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '5'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: string
                  status:
                    type: string
                example:
                  data: https://seller.kuajingmaihuo.com/open/auth?appKey=example-app-key&redirect_uri=https%3A%2F%2Fapp.sku.io%2Fapi%2Ftemu%2Foauth%2Fcallback&state=acme_5
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-temu-integrationinstance-get-authorization-url
  /api/temu/{integrationInstance}/orders:
    get:
      tags:
      - Temu
      summary: List Orders
      description: 'Paginated list of Temu orders for an integration instance, powered
        by Spatie QueryBuilder.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Supported filters:

        - `filter[search]` — searches parentOrderSn, Temu id, and linked SKU sales_order_number.

        - `filter[archived]` — ''active'' (default), ''only''/''archived''/''1''/true,
        or ''all''/''2''.

        - `filter[linked]` — true/false; presence of a linked SKU sales order.

        - `filter[parentOrderStatus]` — exact match on the legacy dropdown enum value.

        - AdvancedFilterBuilder operators on: parentOrderSn (text), currency (text),
        parentOrderStatus (text), id (numeric), total (numeric), parentOrderTime (date),
        expectShipLatestTime (date), latestDeliveryTime (date), created_at (date),
        updated_at (date). Operators are appended as `.eq`, `.contains`, `.gte`, `.between`,
        etc.


        Supported sorts: id, parentOrderSn, parentOrderStatus, shippingMethod, expectShipLatestTime,
        latestDeliveryTime, parentOrderTime, total, currency, created_at, updated_at.
        Default sort is `-id`.


        Eager-loads orderItems, integrationInstance, salesOrder.salesOrderFulfillments.


        **Response field:** `unmapped_line_item_count` — number of line items whose
        Temu product exists but has no internal SKU.io Product linked (mapping incomplete).
        Excludes orphan goodsIds with no TemuProduct row. Only present when orderItems
        are loaded.'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        description: 'Page number (default: 1)'
        example: '1'
      - name: per_page
        in: query
        schema:
          type: integer
        description: 'Items per page (default: 15)'
        example: '15'
      - name: sort
        in: query
        schema:
          type: string
        description: 'Sort field. Prefix with `-` for desc. Allowed: id, parentOrderSn,
          parentOrderStatus, shippingMethod, expectShipLatestTime, latestDeliveryTime,
          parentOrderTime, total, currency, created_at, updated_at. Default: -id.'
        example: -id
      - name: filter[search]
        in: query
        schema:
          type: string
        description: Free-text search across parentOrderSn, Temu order id, and linked
          SKU sales_order_number.
        example: PO-1234
      - name: filter[archived]
        in: query
        schema:
          type: string
        description: 'Archived state. Accepts: ''all''|''2'' (both), ''only''|''archived''|''1''|true
          (archived only), '''' / ''active'' / ''0'' (default — active only).'
        example: active
      - name: filter[parentOrderStatus]
        in: query
        schema:
          type: string
        description: Exact match on Temu parent order status enum (e.g. unshipped,
          shipped, delivered, cancelled, partially_shipped, refunding, refunded).
        example: shipped
      - name: filter[linked]
        in: query
        schema:
          type: boolean
        description: true = orders that have a linked SKU sales order, false = orders
          without one.
        example: 'true'
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        parentOrderSn:
                          type: string
                        parentOrderStatus:
                          type: string
                        shippingMethod:
                          type: string
                        customerName:
                          type: string
                        orderPaymentType:
                          type: string
                        expectShipLatestTime:
                          type: string
                        latestDeliveryTime:
                          type: string
                        parentOrderTime:
                          type: string
                        total:
                          type: string
                        currency:
                          type: string
                        status:
                          type: string
                        error_log:
                          type: string
                          nullable: true
                        json_object:
                          type: object
                          properties:
                            parentOrderMap:
                              type: object
                              properties:
                                parentOrderSn:
                                  type: string
                                parentOrderStatus:
                                  type: integer
                        sku_sales_order:
                          type: object
                          properties:
                            id:
                              type: integer
                            order_number:
                              type: string
                            order_status:
                              type: string
                            fulfillment_status:
                              type: string
                            payment_status:
                              type: string
                            total_fulfillments_count:
                              type: integer
                            submitted_fulfillments_count:
                              type: integer
                            available_fulfillments_count:
                              type: integer
                        unmapped_line_item_count:
                          type: integer
                        archived_at:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - id: 1024
                    integration_instance_id: 1
                    parentOrderSn: PO-1024-AB
                    parentOrderStatus: shipped
                    shippingMethod: Standard
                    customerName: Jane Doe
                    orderPaymentType: prepaid
                    expectShipLatestTime: '2025-03-04T23:59:59+00:00'
                    latestDeliveryTime: '2025-03-10T23:59:59+00:00'
                    parentOrderTime: '2025-03-01T12:34:56+00:00'
                    total: '89.97'
                    currency: USD
                    status: shipped
                    error_log: null
                    json_object:
                      parentOrderMap:
                        parentOrderSn: PO-1024-AB
                        parentOrderStatus: 2
                    sku_sales_order:
                      id: 5501
                      order_number: SO-5501
                      order_status: open
                      fulfillment_status: shipped
                      payment_status: paid
                      total_fulfillments_count: 1
                      submitted_fulfillments_count: 1
                      available_fulfillments_count: 0
                    unmapped_line_item_count: 1
                    archived_at: null
                    created_at: '2025-03-01T12:35:10+00:00'
                    updated_at: '2025-03-04T08:00:00+00:00'
                  current_page: 1
                  last_page: 7
                  per_page: 15
                  total: 98
                  from: 1
                  to: 15
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-temu-integrationinstance-orders
  /api/temu/{integrationInstance}/orders/{order}:
    get:
      tags:
      - Temu
      summary: Show Order
      description: 'Fetch a single Temu order with full nested detail. Eager-loads
        orderItems.product.productListing.product, orderItems.product.productListing.subscriptionOffering,
        and salesOrder.salesOrderFulfillments.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Includes a `line_item_products` map keyed by Temu `goodsId` — each value is
        a Temu product object (channel product list view shape) covering the product
        mapping and SKU.io linkage. Use this map to look up which SKU.io product/listing
        each line item resolves to without making a second request.


        **Response field:** `unmapped_line_item_count` — number of line items whose
        Temu product exists but has no internal SKU.io Product linked (mapping incomplete).
        Excludes orphan goodsIds with no TemuProduct row. Only present when orderItems
        are loaded.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: order
        in: path
        schema:
          type: integer
        required: true
        example: '1024'
        description: The order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      parentOrderSn:
                        type: string
                      parentOrderStatus:
                        type: string
                      shippingMethod:
                        type: string
                      customerName:
                        type: string
                      orderPaymentType:
                        type: string
                      expectShipLatestTime:
                        type: string
                      latestDeliveryTime:
                        type: string
                      parentOrderTime:
                        type: string
                      total:
                        type: string
                      currency:
                        type: string
                      status:
                        type: string
                      error_log:
                        type: string
                        nullable: true
                      json_object:
                        type: object
                        properties:
                          parentOrderMap:
                            type: object
                            properties:
                              parentOrderSn:
                                type: string
                              parentOrderStatus:
                                type: integer
                              customerName:
                                type: string
                          orderList:
                            type: array
                            items:
                              type: object
                              properties:
                                goodsId:
                                  type: string
                                quantity:
                                  type: integer
                                goodsName:
                                  type: string
                      sku_sales_order:
                        type: object
                        properties:
                          id:
                            type: integer
                          order_number:
                            type: string
                          order_status:
                            type: string
                          fulfillment_status:
                            type: string
                          payment_status:
                            type: string
                          total_fulfillments_count:
                            type: integer
                          submitted_fulfillments_count:
                            type: integer
                          available_fulfillments_count:
                            type: integer
                      line_item_products:
                        type: object
                        properties:
                          '401234567890':
                            type: object
                            properties:
                              id:
                                type: integer
                              integration_instance_id:
                                type: integer
                              product_listing_id:
                                type: integer
                              product:
                                type: object
                                properties:
                                  id:
                                    type: integer
                                  name:
                                    type: string
                                  sku:
                                    type: string
                                  listing_id:
                                    type: integer
                                  default_financial_line_type_id:
                                    type: integer
                                  default_financial_line_type:
                                    type: object
                                    properties:
                                      id:
                                        type: integer
                                      name:
                                        type: string
                                      classification:
                                        type: string
                              subscription_offering:
                                type: string
                                nullable: true
                              mapped_at:
                                type: string
                              mapped_sku:
                                type: string
                              category_name:
                                type: string
                              json_object:
                                type: object
                                properties:
                                  goodsId:
                                    type: string
                                  productName:
                                    type: string
                                  skcId:
                                    type: string
                              created_at:
                                type: string
                              updated_at:
                                type: string
                          '401234567891':
                            type: object
                            properties:
                              id:
                                type: integer
                              integration_instance_id:
                                type: integer
                              product_listing_id:
                                type: string
                                nullable: true
                              product:
                                type: string
                                nullable: true
                              subscription_offering:
                                type: string
                                nullable: true
                              mapped_at:
                                type: string
                                nullable: true
                              mapped_sku:
                                type: string
                                nullable: true
                              category_name:
                                type: string
                              json_object:
                                type: object
                                properties:
                                  goodsId:
                                    type: string
                                  productName:
                                    type: string
                                  skcId:
                                    type: string
                              created_at:
                                type: string
                              updated_at:
                                type: string
                      unmapped_line_item_count:
                        type: integer
                      archived_at:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 1024
                    integration_instance_id: 1
                    parentOrderSn: PO-1024-AB
                    parentOrderStatus: shipped
                    shippingMethod: Standard
                    customerName: Jane Doe
                    orderPaymentType: prepaid
                    expectShipLatestTime: '2025-03-04T23:59:59+00:00'
                    latestDeliveryTime: '2025-03-10T23:59:59+00:00'
                    parentOrderTime: '2025-03-01T12:34:56+00:00'
                    total: '89.97'
                    currency: USD
                    status: shipped
                    error_log: null
                    json_object:
                      parentOrderMap:
                        parentOrderSn: PO-1024-AB
                        parentOrderStatus: 2
                        customerName: Jane Doe
                      orderList:
                      - goodsId: '401234567890'
                        quantity: 2
                        goodsName: Wireless Earbuds
                      - goodsId: '401234567891'
                        quantity: 1
                        goodsName: Charging Cable
                    sku_sales_order:
                      id: 5501
                      order_number: SO-5501
                      order_status: open
                      fulfillment_status: shipped
                      payment_status: paid
                      total_fulfillments_count: 1
                      submitted_fulfillments_count: 1
                      available_fulfillments_count: 0
                    line_item_products:
                      '401234567890':
                        id: 7012
                        integration_instance_id: 1
                        product_listing_id: 3301
                        product:
                          id: 4501
                          name: Wireless Earbuds
                          sku: WE-001
                          listing_id: 3301
                          default_financial_line_type_id: 12
                          default_financial_line_type:
                            id: 12
                            name: Product Sales
                            classification: income
                        subscription_offering: null
                        mapped_at: '2025-02-20T10:15:00+00:00'
                        mapped_sku: WE-001
                        category_name: Audio
                        json_object:
                          goodsId: '401234567890'
                          productName: Wireless Earbuds
                          skcId: '55512345'
                        created_at: '2025-02-15T09:00:00+00:00'
                        updated_at: '2025-02-20T10:15:00+00:00'
                      '401234567891':
                        id: 7013
                        integration_instance_id: 1
                        product_listing_id: null
                        product: null
                        subscription_offering: null
                        mapped_at: null
                        mapped_sku: null
                        category_name: Accessories
                        json_object:
                          goodsId: '401234567891'
                          productName: Charging Cable
                          skcId: '55512346'
                        created_at: '2025-02-15T09:00:00+00:00'
                        updated_at: '2025-02-15T09:00:00+00:00'
                    unmapped_line_item_count: 1
                    archived_at: null
                    created_at: '2025-03-01T12:35:10+00:00'
                    updated_at: '2025-03-04T08:00:00+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-temu-integrationinstance-orders-order
    delete:
      tags:
      - Temu
      summary: Delete Order
      description: 'Permanently delete a Temu order. Verifies the order belongs to
        the supplied integration instance (returns 403 if not). Does not remove the
        Temu order on Temu''s side — only deletes the local cached record.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: order
        in: path
        schema:
          type: integer
        required: true
        example: '1024'
        description: The order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Order deleted successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-temu-integrationinstance-orders-order
  /api/temu/{integrationInstance}/orders/{order}/sku-order:
    delete:
      tags:
      - Temu
      summary: Delete Linked SKU Order
      description: 'Delete the linked SKU.io sales order while keeping the Temu order.
        Returns 404 if no SKU order is linked.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Optional body field `archive_order` (boolean, default false): when true, also
        archives the Temu order after the SKU order is deleted, preventing the next
        refresh from immediately re-creating it.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: order
        in: path
        schema:
          type: integer
        required: true
        example: '1024'
        description: The order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  archived_order:
                    type: boolean
                example:
                  message: SKU order deleted successfully and Temu order archived
                  archived_order: true
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-temu-integrationinstance-orders-order-sku-order
  /api/temu/{integrationInstance}/orders/latest-sync-info:
    get:
      tags:
      - Temu
      summary: Get Latest Sync Info
      description: 'Returns aggregate stats used by the ''Refresh from Temu'' modal:
        total order count, count with/without a linked SKU sales order, and the latest
        known order (parentOrderSn, parentOrderTime, parentOrderStatus). Used by the
        UI to default the date range and surface sync coverage.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      latest_order_id:
                        type: string
                      latest_order_date:
                        type: string
                      latest_order_status:
                        type: string
                      total_orders:
                        type: integer
                      with_sku_order:
                        type: integer
                      without_sku_order:
                        type: integer
                example:
                  data:
                    latest_order_id: PO-1024-AB
                    latest_order_date: '2025-03-01T12:34:56+00:00'
                    latest_order_status: shipped
                    total_orders: 98
                    with_sku_order: 81
                    without_sku_order: 17
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-temu-integrationinstance-orders-latest-sync-info
  /api/temu/{integrationInstance}/orders/refresh-tracked:
    post:
      tags:
      - Temu
      summary: Refresh Orders (Tracked)
      description: 'Queue a tracked background job that pulls orders from Temu. Returns
        a `tracked_job_log_id` for the tracked job log endpoints to subscribe to.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Body fields (all optional):

        - `mode` — one of `since_latest` (default), `from_start_date`, `date_range`,
        `all`.

        - `dateFrom`, `dateTo` — required when `mode=date_range`; ISO-8601 dates.
        `mode=from_start_date` only needs `dateFrom` (end is now). `mode=all` walks
        from the integration''s `start_date` (or 2022-01-01) to now. `mode=since_latest`
        leaves the range empty so the job auto-resumes from the latest parentOrderTime
        + 1s.

        - `latestDate` — currently accepted for compatibility but not used by the
        controller.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                mode:
                  type: string
                dateFrom:
                  type: string
                dateTo:
                  type: string
              example:
                mode: date_range
                dateFrom: '2025-03-01'
                dateTo: '2025-03-15'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                example:
                  message: Order refresh job has been queued
                  data:
                    tracked_job_log_id: 8821
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-temu-integrationinstance-orders-refresh-tracked
  /api/temu/{integrationInstance}/orders/create-sku-orders:
    post:
      tags:
      - Temu
      summary: Create SKU Orders (Bulk)
      description: 'Dispatch a tracked background job that converts the selected Temu
        orders into SKU.io sales orders. Returns a `tracked_job_log_id` immediately
        so the caller can close the modal and watch progress via the global tray.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Body (CreateSkuOrderFromSalesChannelData):

        - `ids` — array of Temu order ids to convert.

        - `create_all_orders` — boolean; when true, ignore `ids` and create SKU orders
        for every unlinked Temu order in the instance.

        - `filters` — optional filter payload. When present, the controller resolves
        it to a concrete list of ids via `getIdsFromFilters()` before dispatching.


        Bulk selection contract:

        - {"ids": [1, 2]} — create for the given channel order IDs

        - {"create_all_orders": true} — create for all eligible orders on the integration
        instance

        - {"create_all_orders": true, "filters": {...}} — create only for orders matching
        the filters. The filters object accepts the same filter keys as the corresponding
        orders list endpoint (bare column keys, e.g. {"order_status": "pending"})
        and/or a "filter_groups" tree (base64-encoded JSON, same format as the list
        endpoint). When filters match no orders, nothing is created and the response
        message is "No orders to create".

        - Legacy {"conjunction", "filterSet"} filter payloads are rejected with 422.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
                create_all_orders:
                  type: boolean
              example:
                ids:
                - 1024
                - 1025
                - 1026
                create_all_orders: false
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                example:
                  message: Creating SKU orders in the background — track progress
                    in the job tray.
                  data:
                    tracked_job_log_id: 8822
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-temu-integrationinstance-orders-create-sku-orders
  /api/temu/{integration_instance}/orders/create-products-from-items:
    post:
      tags:
      - Temu
      summary: Create Products From Order Items
      description: 'Backfill TemuProduct records for any TemuOrderItem rows that reference
        a `goodsId` not yet present as a product. Useful when the orders endpoint
        ran ahead of the products sync.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        No request body. Looks up orphaned goodsIds, then creates stub product rows.'
      requestBody:
        content: {}
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 OK - Products Created
                  value:
                    message: Created 7 products from order items.
                example-1:
                  summary: 200 OK - Nothing To Do
                  value:
                    message: No order items found without products.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-temu-integration-instance-orders-create-products-from-items
  /api/temu/{integrationInstance}/orders/refresh:
    post:
      tags:
      - Temu
      summary: Refresh Orders
      description: 'Queues a background job that pulls the latest orders from Temu
        and upserts them into the local order list. The job runs on a serialized queue
        so overlapping refreshes for the same instance cannot race. The sync window
        starts just after the most recent stored order (or the instance''s configured
        start date when no orders exist yet).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        After orders are saved, linked sales orders for the fetched page are also
        brought up to date. The response returns immediately; there is no job id to
        poll on this endpoint.


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '5'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  status:
                    type: string
                example:
                  message: Added to queue, orders will be refreshed shortly.
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-temu-integrationinstance-orders-refresh
  /api/temu/{integrationInstance}/orders/refresh-order:
    post:
      tags:
      - Temu
      summary: Refresh Single Order
      description: 'Fetches one order from Temu by its parent order number, saves
        (or updates) it locally, and returns the stored order. Use this to re-sync
        a single order on demand instead of running a full refresh.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Request body:


        - `uniqueId` (string, required) — the Temu parent order number (`parentOrderSn`),
        e.g. `PO-211-01823450917341234`.


        Returns 404 when Temu has no order with that number.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                uniqueId:
                  type: string
              example:
                uniqueId: PO-211-01823450917341234
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '5'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      parentOrderSn:
                        type: string
                      parentOrderStatus:
                        type: integer
                      shippingMethod:
                        type: string
                      customerName:
                        type: string
                      orderPaymentType:
                        type: string
                      expectShipLatestTime:
                        type: string
                      latestDeliveryTime:
                        type: string
                      parentOrderTime:
                        type: string
                      total:
                        type: string
                      currency:
                        type: string
                      status:
                        type: string
                        nullable: true
                      error_log:
                        type: string
                        nullable: true
                      json_object:
                        type: object
                        properties:
                          parentOrderSn:
                            type: string
                          parentOrderStatus:
                            type: integer
                          regionId:
                            type: integer
                      archived_at:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                  status:
                    type: string
                example:
                  data:
                    id: 101
                    integration_instance_id: 5
                    parentOrderSn: PO-211-01823450917341234
                    parentOrderStatus: 2
                    shippingMethod: Standard
                    customerName: John Smith
                    orderPaymentType: PREPAID
                    expectShipLatestTime: '2026-07-08T00:00:00.000000Z'
                    latestDeliveryTime: '2026-07-15T00:00:00.000000Z'
                    parentOrderTime: '2026-07-04T18:22:31.000000Z'
                    total: '38.97'
                    currency: USD
                    status: null
                    error_log: null
                    json_object:
                      parentOrderSn: PO-211-01823450917341234
                      parentOrderStatus: 2
                      regionId: 211
                    archived_at: null
                    created_at: '2026-07-04T18:30:02.000000Z'
                    updated_at: '2026-07-06T09:12:44.000000Z'
                  status: success
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Order not found
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      uniqueId:
                        type: array
                        items:
                          type: string
                example:
                  message: The unique id field is required.
                  errors:
                    uniqueId:
                    - The unique id field is required.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-temu-integrationinstance-orders-refresh-order
  /api/temu/{integrationInstance}/orders/update-sku-orders:
    post:
      tags:
      - Temu
      summary: Bulk Update SKU Orders
      description: 'Re-applies the latest stored Temu order data onto the linked SKU
        sales orders — statuses, cancellations and fulfillment-relevant changes are
        translated into update actions and processed per order. Orders without a linked
        sales order are skipped.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Request body:


        - `update_all_orders` (boolean, required) — when `true`, processes every eligible
        order for the instance.

        - `ids` (array of integers, optional) — specific Temu order ids to process.

        - `filters` (string, optional) — a serialized filter expression; when provided
        it is resolved to a set of order ids before processing.

        - `use_jobs` (boolean, default `true`) — accepted for cross-channel compatibility;
        Temu processes the update synchronously within the request.


        Processing happens in chunks, so very large selections can take a while to
        respond.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                update_all_orders:
                  type: boolean
                ids:
                  type: array
                  items:
                    type: integer
                use_jobs:
                  type: boolean
              example:
                update_all_orders: false
                ids:
                - 101
                - 102
                use_jobs: true
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '5'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  status:
                    type: string
                example:
                  message: Sku.io sales orders successfully updated
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-temu-integrationinstance-orders-update-sku-orders
  /api/temu/{integrationInstance}/orders/{order}/archive:
    post:
      tags:
      - Temu
      summary: Archive Order
      description: 'Archive a single Temu order. Returns 403 if the order does not
        belong to the integration instance. The `archived` flag in the response indicates
        whether the call actually changed state (false means it was already archived).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: order
        in: path
        schema:
          type: integer
        required: true
        example: '1024'
        description: The order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  archived:
                    type: boolean
                example:
                  message: Order archived successfully
                  archived: true
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-temu-integrationinstance-orders-order-archive
  /api/temu/{integrationInstance}/orders/{order}/unarchive:
    post:
      tags:
      - Temu
      summary: Unarchive Order
      description: 'Unarchive a single Temu order. Returns 403 if the order does not
        belong to the integration instance. The `unarchived` flag is false when the
        order was already active.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: order
        in: path
        schema:
          type: integer
        required: true
        example: '1024'
        description: The order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  unarchived:
                    type: boolean
                example:
                  message: Order unarchived successfully
                  unarchived: true
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-temu-integrationinstance-orders-order-unarchive
  /api/temu/{integrationInstance}/orders/bulk-archive:
    post:
      tags:
      - Temu
      summary: Bulk Archive Orders
      description: 'Archive multiple orders in one call. Iterates the matched rows
        in chunks of 100.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Body:

        - `ids` — array of integer order ids (required unless `apply_to_all` is true).

        - `apply_to_all` — boolean; when true, archives every currently non-archived
        order in the instance (ids are ignored).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
                apply_to_all:
                  type: boolean
              example:
                ids:
                - 1024
                - 1025
                - 1026
                apply_to_all: false
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  archived_count:
                    type: integer
                example:
                  message: 3 orders archived successfully
                  archived_count: 3
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-temu-integrationinstance-orders-bulk-archive
  /api/temu/{integrationInstance}/orders/bulk-unarchive:
    post:
      tags:
      - Temu
      summary: Bulk Unarchive Orders
      description: 'Unarchive multiple orders in one call. Iterates the matched rows
        in chunks of 100.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Body:

        - `ids` — array of integer order ids (required unless `apply_to_all` is true).

        - `apply_to_all` — boolean; when true, unarchives every currently archived
        order in the instance (ids are ignored).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
                apply_to_all:
                  type: boolean
              example:
                ids:
                - 1024
                - 1025
                - 1026
                apply_to_all: false
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  unarchived_count:
                    type: integer
                example:
                  message: 3 orders unarchived successfully
                  unarchived_count: 3
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-temu-integrationinstance-orders-bulk-unarchive
  /api/temu/{integrationInstance}/orders/{order}/raw:
    get:
      tags:
      - Temu
      summary: Get Raw Order (from Temu API)
      description: 'Live-fetch the raw Temu order payload by `parentOrderSn` directly
        from Temu''s API (bypasses the local cache). Returns 403 if the order does
        not belong to the integration instance, or 500 with the underlying error message
        if Temu''s API call fails.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: order
        in: path
        schema:
          type: integer
        required: true
        example: '1024'
        description: The order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      parentOrderMap:
                        type: object
                        properties:
                          parentOrderSn:
                            type: string
                          parentOrderStatus:
                            type: integer
                          parentOrderTime:
                            type: integer
                          customerName:
                            type: string
                          shippingMethod:
                            type: string
                          orderAmount:
                            type: integer
                          currency:
                            type: string
                      orderList:
                        type: array
                        items:
                          type: object
                          properties:
                            orderSn:
                              type: string
                            goodsId:
                              type: string
                            skcId:
                              type: string
                            quantity:
                              type: integer
                            goodsName:
                              type: string
                example:
                  data:
                    parentOrderMap:
                      parentOrderSn: PO-1024-AB
                      parentOrderStatus: 2
                      parentOrderTime: 1740830096
                      customerName: Jane Doe
                      shippingMethod: Standard
                      orderAmount: 8997
                      currency: USD
                    orderList:
                    - orderSn: O-1024-1
                      goodsId: '401234567890'
                      skcId: '55512345'
                      quantity: 2
                      goodsName: Wireless Earbuds
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-temu-integrationinstance-orders-order-raw
  /api/temu/{integrationInstance}/orders/{order}/activity-log:
    get:
      tags:
      - Temu
      summary: Order Activity Log
      description: 'Paginated activity log entries for this Temu order, sourced from
        Spatie ActivityLog.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        description: 'Page number (default: 1)'
        example: '1'
      - name: per_page
        in: query
        schema:
          type: integer
        description: 'Items per page (default: 15)'
        example: '15'
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: order
        in: path
        schema:
          type: integer
        required: true
        example: '1024'
        description: The order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        description:
                          type: string
                        event:
                          type: string
                        causer:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        properties:
                          type: object
                          properties:
                            parentOrderSn:
                              type: string
                        created_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - id: 9301
                    description: Order created from Temu
                    event: created
                    causer:
                      id: 12
                      name: Sync Worker
                    properties:
                      parentOrderSn: PO-1024-AB
                    created_at: '2025-03-01T12:35:10+00:00'
                  - id: 9302
                    description: SKU sales order linked
                    event: updated
                    causer:
                      id: 3
                      name: Jane Doe
                    properties:
                      sales_order_id: 5501
                    created_at: '2025-03-01T12:40:22+00:00'
                  current_page: 1
                  last_page: 1
                  per_page: 15
                  total: 2
                  from: 1
                  to: 2
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-temu-integrationinstance-orders-order-activity-log
  /api/temu/{integrationInstance}/products:
    get:
      tags:
      - Temu
      summary: List Products
      description: 'Paginated list of Temu products for an integration instance. Powered
        by Spatie QueryBuilder with grouped advanced filters.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        example: '1'
        description: Page number (default 1).
      - name: per_page
        in: query
        schema:
          type: integer
        example: '15'
        description: Results per page (default 10).
      - name: sort
        in: query
        schema:
          type: string
        description: 'Allowed sorts: id, skuId, goodsId, goodsName, skuStatus, catType,
          created_at, updated_at. Prefix with - for descending.'
        example: -id
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        skuId:
                          type: string
                        goodsId:
                          type: string
                        goodsName:
                          type: string
                        category_name:
                          type: string
                        integration_instance_id:
                          type: integer
                        product_listing_id:
                          type: integer
                        product:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            sku:
                              type: string
                            listing_id:
                              type: integer
                            default_financial_line_type_id:
                              type: integer
                            default_financial_line_type:
                              type: object
                              properties:
                                id:
                                  type: integer
                                name:
                                  type: string
                                classification:
                                  type: string
                        subscription_offering:
                          type: string
                          nullable: true
                        mapped_at:
                          type: string
                        mapped_sku:
                          type: string
                        json_object:
                          type: object
                          properties:
                            goodsId:
                              type: string
                            goodsName:
                              type: string
                            outGoodsSn:
                              type: string
                            price:
                              type: number
                            quantity:
                              type: integer
                            status4VO:
                              type: string
                            retailPrice:
                              type: object
                              properties:
                                amount:
                                  type: number
                                currency:
                                  type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                  first_page_url:
                    type: string
                  last_page_url:
                    type: string
                  next_page_url:
                    type: string
                  prev_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  links:
                    type: array
                example:
                  data:
                  - id: 1024
                    skuId: '172800123456789'
                    goodsId: '60112233445566'
                    goodsName: Wireless Earbuds Pro - Black
                    category_name: Electronics > Audio > Earbuds
                    integration_instance_id: 12
                    product_listing_id: 553
                    product:
                      id: 91
                      name: Earbuds Pro
                      sku: SKU-EARBUDS-PRO
                      listing_id: 553
                      default_financial_line_type_id: 4
                      default_financial_line_type:
                        id: 4
                        name: Product Sales
                        classification: income
                    subscription_offering: null
                    mapped_at: '2026-05-12T14:21:08.000000Z'
                    mapped_sku: SKU-EARBUDS-PRO
                    json_object:
                      goodsId: '60112233445566'
                      goodsName: Wireless Earbuds Pro - Black
                      outGoodsSn: SKU-EARBUDS-PRO
                      price: 39.99
                      quantity: 120
                      status4VO: ON_SALE
                      retailPrice:
                        amount: 39.99
                        currency: USD
                    created_at: '2026-05-10T08:11:45.000000Z'
                    updated_at: '2026-06-18T19:44:02.000000Z'
                  current_page: 1
                  last_page: 7
                  per_page: 15
                  total: 102
                  from: 1
                  to: 15
                  first_page_url: https://app.sku.io/api/temu/12/products?page=1
                  last_page_url: https://app.sku.io/api/temu/12/products?page=7
                  next_page_url: https://app.sku.io/api/temu/12/products?page=2
                  prev_page_url: null
                  path: https://app.sku.io/api/temu/12/products
                  links: []
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-temu-integrationinstance-products
  /api/temu/{integrationInstance}/products/{product}:
    get:
      tags:
      - Temu
      summary: Show Product
      description: 'Fetch a single Temu product with its mapping, integration instance,
        and full json_object.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: product
        in: path
        schema:
          type: string
        required: true
        description: The product ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      skuId:
                        type: string
                      goodsId:
                        type: string
                      goodsName:
                        type: string
                      category_name:
                        type: string
                      integration_instance_id:
                        type: integer
                      product_listing_id:
                        type: integer
                      product:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          sku:
                            type: string
                          listing_id:
                            type: integer
                      subscription_offering:
                        type: string
                        nullable: true
                      mapped_at:
                        type: string
                      mapped_sku:
                        type: string
                      json_object:
                        type: object
                        properties:
                          goodsId:
                            type: string
                          goodsName:
                            type: string
                          outGoodsSn:
                            type: string
                          price:
                            type: number
                          quantity:
                            type: integer
                          status4VO:
                            type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 1024
                    skuId: '172800123456789'
                    goodsId: '60112233445566'
                    goodsName: Wireless Earbuds Pro - Black
                    category_name: Electronics > Audio > Earbuds
                    integration_instance_id: 12
                    product_listing_id: 553
                    product:
                      id: 91
                      name: Earbuds Pro
                      sku: SKU-EARBUDS-PRO
                      listing_id: 553
                    subscription_offering: null
                    mapped_at: '2026-05-12T14:21:08.000000Z'
                    mapped_sku: SKU-EARBUDS-PRO
                    json_object:
                      goodsId: '60112233445566'
                      goodsName: Wireless Earbuds Pro - Black
                      outGoodsSn: SKU-EARBUDS-PRO
                      price: 39.99
                      quantity: 120
                      status4VO: ON_SALE
                    created_at: '2026-05-10T08:11:45.000000Z'
                    updated_at: '2026-06-18T19:44:02.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-temu-integrationinstance-products-product
  /api/temu/{integrationInstance}/products/export:
    get:
      tags:
      - Temu
      summary: Export Products
      description: 'Downloads every imported Temu product listing for the integration
        instance as a spreadsheet file (newest first), including mapping details for
        listings linked to internal products. Nested values such as the raw listing
        payload are serialized to JSON strings within their cells.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        The export always covers all products for the instance — list filters are
        not applied. Requesting an export when the instance has no products returns
        an error.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '5'
        description: The integration instance ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-temu-integrationinstance-products-export
  /api/temu/{integrationInstance}/products/archiveable:
    post:
      tags:
      - Temu
      summary: Check Archiveable Products
      description: 'Pre-validates a set of Temu products for archiving without changing
        anything. For each product the response says whether it can be archived and,
        if not, why. A product cannot be archived while it appears on imported Temu
        orders.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Request body — one of:


        - `ids` (array of integers, required unless `mode` is used) — product ids
        belonging to this integration instance.

        - `mode` (string) — set to `all` to check every product for the instance.


        Response items contain `id`, `archiveable` (boolean) and `reason` (`false`
        when archiveable, otherwise a comma-separated string of reasons).


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 12
                - 13
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '5'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        archiveable:
                          type: boolean
                        reason:
                          type: boolean
                  status:
                    type: string
                example:
                  data:
                  - id: 12
                    archiveable: true
                    reason: false
                  - id: 13
                    archiveable: false
                    reason: Sales Channel Product has Sales Channel Orders
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-temu-integrationinstance-products-archiveable
  /api/temu/{integrationInstance}/products/deleteable:
    put:
      tags:
      - Temu
      summary: Check Deleteable Products
      description: 'Pre-validates a set of Temu products for deletion without changing
        anything. For each product the response says whether it can be deleted; Temu
        products currently have no delete restrictions, so every requested product
        is reported as deleteable.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Request body — one of:


        - `ids` (array of integers, required unless `mode` is used) — product ids
        belonging to this integration instance.

        - `mode` (string) — set to `all` to check every product for the instance.


        Response items contain `id`, `deleteable` (boolean) and `reason` (`false`
        when deleteable).


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 12
                - 13
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '5'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        deleteable:
                          type: boolean
                        reason:
                          type: boolean
                  status:
                    type: string
                example:
                  data:
                  - id: 12
                    deleteable: true
                    reason: false
                  - id: 13
                    deleteable: true
                    reason: false
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-temu-integrationinstance-products-deleteable
  /api/temu/{integrationInstance}/products/archive:
    put:
      tags:
      - Temu
      summary: Bulk Archive Products
      description: 'Archives the selected Temu products, hiding them from the default
        product list. Products that appear on imported Temu orders are silently skipped
        — use the archiveable check endpoint first to see which products qualify.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Request body — one of:


        - `ids` (array of integers, required unless `mode` is used) — product ids
        belonging to this integration instance.

        - `mode` (string) — set to `all` to archive every eligible product for the
        instance.


        Authentication: Requires Bearer token.


        Bulk selection contract:

        - {"ids": [1, 2]} — act on the given channel product IDs

        - {"mode": "all"} — act on all products for the integration instance

        - {"apply_to_all": true, "filters": {...}} — act only on products matching
        the filters. The filters object accepts the same filter keys as the corresponding
        products list endpoint (bare column keys) and/or a "filter_groups" tree (base64-encoded
        JSON). With apply_to_all and no filters, all products for the instance are
        targeted.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 12
                - 14
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '5'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  status:
                    type: string
                example:
                  message: Products archived successfully.
                  status: success
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      ids:
                        type: array
                        items:
                          type: string
                example:
                  message: The selected ids is invalid.
                  errors:
                    ids:
                    - The selected ids is invalid.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: put-api-temu-integrationinstance-products-archive
  /api/temu/{integrationInstance}/products/unarchive:
    put:
      tags:
      - Temu
      summary: Bulk Unarchive Products
      description: 'Restores previously archived Temu products so they appear in the
        default product list again.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Request body — one of:


        - `ids` (array of integers, required unless `mode` is used) — product ids
        belonging to this integration instance.

        - `mode` (string) — set to `all` to unarchive every product for the instance.


        Authentication: Requires Bearer token.


        Bulk selection contract:

        - {"ids": [1, 2]} — act on the given channel product IDs

        - {"mode": "all"} — act on all products for the integration instance

        - {"apply_to_all": true, "filters": {...}} — act only on products matching
        the filters. The filters object accepts the same filter keys as the corresponding
        products list endpoint (bare column keys) and/or a "filter_groups" tree (base64-encoded
        JSON). With apply_to_all and no filters, all products for the instance are
        targeted.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 12
                - 14
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '5'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  status:
                    type: string
                example:
                  message: Products unarchived successfully.
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-temu-integrationinstance-products-unarchive
  /api/temu/{integrationInstance}/products/delete:
    put:
      tags:
      - Temu
      summary: Bulk Delete Products
      description: 'Permanently deletes the selected Temu products from the local
        catalog. Any product-listing mappings tied to those products are removed first,
        so linked internal products lose their Temu listing association. The listings
        on Temu itself are not affected.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Request body — one of:


        - `ids` (array of integers, required unless `mode` is used) — product ids
        belonging to this integration instance.

        - `mode` (string) — set to `all` to delete every product for the instance.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 12
                - 14
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '5'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  status:
                    type: string
                example:
                  message: Products deleted successfully.
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-temu-integrationinstance-products-delete
  /api/temu/{integrationInstance}/products/refresh-tracked:
    post:
      tags:
      - Temu
      summary: Refresh Products (Tracked)
      description: 'Dispatches a tracked background job to pull products from Temu.
        Returns a tracked_job_log_id the UI uses to surface progress via the tracked
        job log endpoints.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Payload fields (all optional):

        - mode: one of since_latest | full_catalog | date_range

        - dateFrom / dateTo: ISO date strings used with date_range

        - latestDate: ISO date used with since_latest'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                mode:
                  type: string
                dateFrom:
                  type: string
                  nullable: true
                dateTo:
                  type: string
                  nullable: true
                latestDate:
                  type: string
                  nullable: true
              example:
                mode: since_latest
                dateFrom: null
                dateTo: null
                latestDate: null
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                example:
                  message: Product refresh job has been queued
                  data:
                    tracked_job_log_id: 4821
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-temu-integrationinstance-products-refresh-tracked
  /api/temu/{integrationInstance}/products/latest-sync-info:
    get:
      tags:
      - Temu
      summary: Latest Sync Info
      description: 'Returns totals + most-recently-updated product info for the Refresh-from-Temu
        modal header. Counts exclude archived rows.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      latest_product_title:
                        type: string
                      latest_product_date:
                        type: string
                      total_products:
                        type: integer
                      mapped_products:
                        type: integer
                      unmapped_products:
                        type: integer
                      last_synced_at:
                        type: string
                example:
                  data:
                    latest_product_title: Wireless Earbuds Pro - Black
                    latest_product_date: '2026-06-18T19:44:02.000000Z'
                    total_products: 102
                    mapped_products: 67
                    unmapped_products: 35
                    last_synced_at: '2026-06-18T19:44:02.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-temu-integrationinstance-products-latest-sync-info
  /api/temu/{integrationInstance}/products/{product}/raw:
    get:
      tags:
      - Temu
      summary: Get Raw Product
      description: 'Calls Temu''s bg.local.goods.detail.query directly and returns
        the raw payload for the on-demand viewer. 403 if the product does not belong
        to the given integration instance; 500 if the upstream call fails.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: product
        in: path
        schema:
          type: string
        required: true
        description: The product ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      product:
                        type: object
                        properties:
                          goodsId:
                            type: string
                          goodsName:
                            type: string
                          outGoodsSn:
                            type: string
                          catId:
                            type: integer
                          catName:
                            type: string
                          status4VO:
                            type: string
                          skuInfoList:
                            type: array
                            items:
                              type: object
                              properties:
                                skuId:
                                  type: string
                                price:
                                  type: number
                                quantity:
                                  type: integer
                example:
                  data:
                    product:
                      goodsId: '60112233445566'
                      goodsName: Wireless Earbuds Pro - Black
                      outGoodsSn: SKU-EARBUDS-PRO
                      catId: 1180
                      catName: Earbuds
                      status4VO: ON_SALE
                      skuInfoList:
                      - skuId: '172800123456789'
                        price: 39.99
                        quantity: 120
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-temu-integrationinstance-products-product-raw
  /api/temu/{integrationInstance}/products/refresh:
    post:
      tags:
      - Temu
      summary: Refresh Products
      description: 'Queues a background job that pulls the product catalog from Temu
        and upserts the listings locally. The job runs on a serialized queue so overlapping
        refreshes for the same instance cannot race. Depending on the instance''s
        auto-link and auto-create settings, newly imported listings may be linked
        to existing internal products by SKU or have internal products created for
        them automatically.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        The response returns immediately; there is no job id to poll on this endpoint.


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '5'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  status:
                    type: string
                example:
                  message: Added to queue, products will be refreshed shortly.
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-temu-integrationinstance-products-refresh
  /api/temu/{integrationInstance}/products/{product}/refresh:
    post:
      tags:
      - Temu
      summary: Refresh Single Product
      description: 'Fetches one product directly from Temu''s API, persists the updated
        data, and returns the refreshed listing — synchronously, without queuing a
        catalog-wide refresh.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Error cases:


        - 403 when the product does not belong to this integration instance.

        - 404 when Temu returns no data for the product.

        - 500 when the Temu API call fails.


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '5'
        description: The integration instance ID.
      - name: product
        in: path
        schema:
          type: integer
        required: true
        example: '12'
        description: The product ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      product_listing_id:
                        type: integer
                      product:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          sku:
                            type: string
                          default_financial_line_type_id:
                            type: integer
                          default_financial_line_type:
                            type: object
                            properties:
                              id:
                                type: integer
                              name:
                                type: string
                              classification:
                                type: string
                          listing_id:
                            type: integer
                      subscription_offering:
                        type: string
                        nullable: true
                      mapped_at:
                        type: string
                      mapped_sku:
                        type: string
                      json_object:
                        type: object
                        properties:
                          goodsId:
                            type: string
                          goodsName:
                            type: string
                          skuId:
                            type: string
                          outGoodsSn:
                            type: string
                          price:
                            type: string
                          quantity:
                            type: integer
                      updated_at:
                        type: string
                      created_at:
                        type: string
                      category_name:
                        type: string
                      skuId:
                        type: string
                      goodsId:
                        type: string
                      goodsName:
                        type: string
                      thumbUrl:
                        type: string
                      skuStatus:
                        type: string
                      catType:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 12
                    integration_instance_id: 5
                    product_listing_id: 88
                    product:
                      id: 341
                      name: Black Cotton T-Shirt
                      sku: TSHIRT-BLK-L
                      default_financial_line_type_id: 2
                      default_financial_line_type:
                        id: 2
                        name: Product Sales
                        classification: revenue
                      listing_id: 88
                    subscription_offering: null
                    mapped_at: '2026-05-14T10:02:31.000000Z'
                    mapped_sku: TSHIRT-BLK-L
                    json_object:
                      goodsId: '601099512340411'
                      goodsName: Black Cotton T-Shirt
                      skuId: '17592186044417'
                      outGoodsSn: TSHIRT-BLK-L
                      price: '12.99'
                      quantity: 240
                    updated_at: '2026-07-06T09:41:12.000000Z'
                    created_at: '2026-04-30T07:18:44.000000Z'
                    category_name: Apparel
                    skuId: '17592186044417'
                    goodsId: '601099512340411'
                    goodsName: Black Cotton T-Shirt
                    thumbUrl: https://img.kwcdn.com/product/thumb/601099512340411.jpg
                    skuStatus: ACTIVE
                    catType: '0'
                  message: Product refreshed from Temu
        '403':
          description: Forbidden
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: Product does not belong to this integration instance
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: Temu returned no data for this product
        '429': *id001
        '401': *id002
        '422': *id005
      operationId: post-api-temu-integrationinstance-products-product-refresh
  /api/temu/{integrationInstance}/products/{product}/smart-match:
    post:
      tags:
      - Temu
      summary: Smart Match
      description: 'Find SKU product matches for a Temu product. Tries exact SKU (outGoodsSn
        first, then skuId) and fuzzy goodsName matches. Empty body.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: product
        in: path
        schema:
          type: string
        required: true
        description: The product ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      exact_match:
                        type: object
                        properties:
                          id:
                            type: integer
                          sku:
                            type: string
                          name:
                            type: string
                          barcode:
                            type: string
                          price:
                            type: number
                          type:
                            type: string
                          match_type:
                            type: string
                      barcode_match:
                        type: string
                        nullable: true
                      similar_matches:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            sku:
                              type: string
                            name:
                              type: string
                            barcode:
                              type: string
                              nullable: true
                            price:
                              type: number
                            type:
                              type: string
                            match_type:
                              type: string
                example:
                  data:
                    exact_match:
                      id: 91
                      sku: SKU-EARBUDS-PRO
                      name: Earbuds Pro
                      barcode: 0123456789012
                      price: 39.99
                      type: simple
                      match_type: sku
                    barcode_match: null
                    similar_matches:
                    - id: 134
                      sku: SKU-EARBUDS-LITE
                      name: Earbuds Lite
                      barcode: null
                      price: 19.99
                      type: simple
                      match_type: fuzzy
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-temu-integrationinstance-products-product-smart-match
  /api/temu/{integrationInstance}/products/{product}/map:
    post:
      tags:
      - Temu
      summary: Map Product to SKU Product
      description: 'Map a single Temu product to either a SKU product (product_id)
        OR a subscription offering (subscription_offering_id). Exactly one of the
        two is required.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Payload:

        - product_id (integer, required_without subscription_offering_id) — must exist
        in products.id

        - subscription_offering_id (integer, required_without product_id) — must exist
        in subscription_offerings.id


        Creates or updates the underlying product_listing and queues a job to re-map
        any open sales order lines.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                product_id:
                  type: integer
              example:
                product_id: 91
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: product
        in: path
        schema:
          type: string
        required: true
        description: The product ID.
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      skuId:
                        type: string
                      goodsId:
                        type: string
                      goodsName:
                        type: string
                      integration_instance_id:
                        type: integer
                      product_listing_id:
                        type: integer
                      product:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          sku:
                            type: string
                          listing_id:
                            type: integer
                      subscription_offering:
                        type: string
                        nullable: true
                      mapped_at:
                        type: string
                      mapped_sku:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 1024
                    skuId: '172800123456789'
                    goodsId: '60112233445566'
                    goodsName: Wireless Earbuds Pro - Black
                    integration_instance_id: 12
                    product_listing_id: 553
                    product:
                      id: 91
                      name: Earbuds Pro
                      sku: SKU-EARBUDS-PRO
                      listing_id: 553
                    subscription_offering: null
                    mapped_at: '2026-06-19T10:15:42.000000Z'
                    mapped_sku: SKU-EARBUDS-PRO
                  message: Product mapped successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-temu-integrationinstance-products-product-map
    delete:
      tags:
      - Temu
      summary: Unmap Product
      description: 'Removes the product_listing linking this Temu product to a SKU
        product/offering. Returns 422 if the product has no current mapping.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: product
        in: path
        schema:
          type: string
        required: true
        description: The product ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      skuId:
                        type: string
                      goodsId:
                        type: string
                      goodsName:
                        type: string
                      integration_instance_id:
                        type: integer
                      product_listing_id:
                        type: string
                        nullable: true
                      product:
                        type: string
                        nullable: true
                      subscription_offering:
                        type: string
                        nullable: true
                      mapped_at:
                        type: string
                        nullable: true
                      mapped_sku:
                        type: string
                        nullable: true
                  message:
                    type: string
                example:
                  data:
                    id: 1024
                    skuId: '172800123456789'
                    goodsId: '60112233445566'
                    goodsName: Wireless Earbuds Pro - Black
                    integration_instance_id: 12
                    product_listing_id: null
                    product: null
                    subscription_offering: null
                    mapped_at: null
                    mapped_sku: null
                  message: Product unmapped successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-temu-integrationinstance-products-product-map
  /api/temu/{integrationInstance}/products/{product}/create-sku-product:
    post:
      tags:
      - Temu
      summary: Create SKU Product
      description: 'Create a new SKU product from a Temu product and immediately link
        it via product_listing.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        If an existing SKU product with a matching sku (outGoodsSn or skuId) is found,
        the response sets `linked_existing: true` and links to that record instead
        of creating a duplicate.


        Returns 422 if the Temu product is already mapped (caller must unmap first).


        Payload (optional, used by the create-from-Temu form):

        - field_mappings (object) — map of SKU product field => Temu source key (persisted
        via DataImportMapping when sent in bulk via createSkuProducts).

        - save_as_default (boolean) — persist the provided field_mappings as the integration
        default.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                field_mappings:
                  type: object
                  properties:
                    sku:
                      type: string
                    name:
                      type: string
                    price:
                      type: string
                    barcode:
                      type: string
                save_as_default:
                  type: boolean
              example:
                field_mappings:
                  sku: outGoodsSn
                  name: goodsName
                  price: price
                  barcode: upc
                save_as_default: true
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: product
        in: path
        schema:
          type: string
        required: true
        description: The product ID.
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      skuId:
                        type: string
                      goodsId:
                        type: string
                      goodsName:
                        type: string
                      integration_instance_id:
                        type: integer
                      product_listing_id:
                        type: integer
                      product:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          sku:
                            type: string
                          listing_id:
                            type: integer
                      subscription_offering:
                        type: string
                        nullable: true
                      mapped_at:
                        type: string
                      mapped_sku:
                        type: string
                  linked_existing:
                    type: boolean
                  message:
                    type: string
                example:
                  data:
                    id: 1024
                    skuId: '172800123456789'
                    goodsId: '60112233445566'
                    goodsName: Wireless Earbuds Pro - Black
                    integration_instance_id: 12
                    product_listing_id: 554
                    product:
                      id: 92
                      name: Wireless Earbuds Pro - Black
                      sku: SKU-EARBUDS-PRO
                      listing_id: 554
                    subscription_offering: null
                    mapped_at: '2026-06-19T10:18:11.000000Z'
                    mapped_sku: SKU-EARBUDS-PRO
                  linked_existing: false
                  message: SKU product created and mapped successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-temu-integrationinstance-products-product-create-sku-product
  /api/temu/{integrationInstance}/products/map:
    put:
      tags:
      - Temu
      summary: Bulk Map Products
      description: "Maps Temu listings to internal products by SKU in bulk. Each mapping\
        \ entry links one Temu listing (identified by its Temu goods id) to the internal\
        \ product whose SKU matches `mapped_sku`. After mapping, any imported order\
        \ lines that were previously unmatched are re-linked to the newly mapped products\
        \ in the background.\n\n:::info[Authorization]\nAny valid API token can call\
        \ this endpoint — no specific scope required. [Manage tokens](https://app.sku.io/settings/api).\n\
        :::\n\nRequest body:\n\n- `mapping` (array, required, min 1) — each entry:\n\
        \  - `sales_channel_listing_id` (string, required) — the Temu goods id of\
        \ the listing.\n  - `mapped_sku` (string or null, required) — SKU of the internal\
        \ product to map to. Passing `null` (or an empty string) together with an\
        \ existing `product_listing_id` removes that mapping.\n  - `product_listing_id`\
        \ (integer or null, optional) — id of an existing listing mapping, used when\
        \ updating or removing a mapping.\n  - `subscription_offering_id` (integer\
        \ or null, optional) — map the listing to a subscription offering instead\
        \ of a product.\n\nAuthentication: Requires Bearer token."
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                mapping:
                  type: array
                  items:
                    type: object
                    properties:
                      sales_channel_listing_id:
                        type: string
                      mapped_sku:
                        type: string
                      product_listing_id:
                        type: string
                        nullable: true
                      subscription_offering_id:
                        type: string
                        nullable: true
              example:
                mapping:
                - sales_channel_listing_id: '601099512340411'
                  mapped_sku: TSHIRT-BLK-L
                  product_listing_id: null
                  subscription_offering_id: null
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '5'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: string
                  status:
                    type: string
                example:
                  data: Successfully mapped sales channel products to sku products
                  status: success
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      mapping:
                        type: array
                        items:
                          type: string
                example:
                  message: The mapping field is required.
                  errors:
                    mapping:
                    - The mapping field is required.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: put-api-temu-integrationinstance-products-map
  /api/temu/{integrationInstance}/products/create-sku-products:
    post:
      tags:
      - Temu
      summary: Bulk Create SKU Products
      description: 'Creates internal SKU products from Temu listings and links them,
        running as a queued background job. If a listing''s candidate SKU already
        exists internally, the listing is linked to the existing product instead of
        creating a duplicate. Field mappings configured for the instance control how
        listing fields populate the new products.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Request body:


        - `create_all_products` (boolean, required) — when `true`, processes every
        listing for the instance.

        - `ids` (array of integers) — specific Temu product ids; required when `create_all_products`
        is `false` and no `filters` are supplied.

        - `filters` (string, optional) — serialized filter expression, resolved to
        a set of ids before the job is dispatched.

        - `mappings` (array, optional) — field mappings to persist before creation;
        each entry has `listing_field` (string), `sku_field` (string) and `parsers`
        (array of `{rule, args}` transforms).

        - `initial_mapping` (boolean, default `false`).


        The response returns immediately with a `tracked_job_log_id` that can be used
        to follow the job''s progress.


        Authentication: Requires Bearer token.


        Bulk selection contract:

        - {"create_all_products": false, "ids": [1, 2]} — create for the given channel
        product IDs

        - {"create_all_products": true} — create for all unmapped products on the
        integration instance

        - {"create_all_products": true, "filters": {...}} — create only for products
        matching the filters. The filters object accepts the same filter keys as the
        corresponding products list endpoint (bare column keys) and/or a "filter_groups"
        tree (base64-encoded JSON). When filters match no products, nothing is created
        and the response message is "No products to create".

        - create_all_products is required; ids is required when create_all_products
        is false and no filters are sent.

        - Legacy {"conjunction", "filterSet"} filter payloads are rejected with 422.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                create_all_products:
                  type: boolean
                ids:
                  type: array
                  items:
                    type: integer
                initial_mapping:
                  type: boolean
                mappings:
                  type: array
                  items:
                    type: object
                    properties:
                      listing_field:
                        type: string
                      sku_field:
                        type: string
                      parsers:
                        type: array
              example:
                create_all_products: false
                ids:
                - 12
                - 13
                initial_mapping: false
                mappings:
                - listing_field: goodsName
                  sku_field: item_name
                  parsers: []
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '5'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  status:
                    type: string
                example:
                  message: Creating SKU products in the background.
                  data:
                    tracked_job_log_id: 4821
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-temu-integrationinstance-products-create-sku-products
  /api/temu/{integrationInstance}/products/import-mappings:
    post:
      tags:
      - Temu
      summary: Import Product Mappings
      description: 'Imports listing-to-product mappings from a previously uploaded
        CSV file, running as a queued background job on a serialized queue. The CSV
        must contain a column with the Temu goods id (the listing''s unique field)
        and a `mapped_sku` column identifying the internal product each listing maps
        to.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Request body:


        - `original_name` (string, required) — the file name as originally uploaded.

        - `stored_name` (string, required) — the server-side stored file name returned
        by the file upload endpoint.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                original_name:
                  type: string
                stored_name:
                  type: string
              example:
                original_name: temu-mappings.csv
                stored_name: 01J8ZK3W9GVXPTF2ab.csv
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '5'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  status:
                    type: string
                example:
                  message: Added to queue, mappings will be imported shortly.
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-temu-integrationinstance-products-import-mappings
  /api/temu/{integrationInstance}/products/{product}/orders:
    get:
      tags:
      - Temu
      summary: Get Orders for Product
      description: 'Paginated list of Temu orders that contain this product (matched
        by goodsId), newest first by parentOrderTime. 403 if the product does not
        belong to the integration instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        example: '1'
        description: Page number (default 1).
      - name: per_page
        in: query
        schema:
          type: integer
        example: '10'
        description: Results per page (default 10).
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: product
        in: path
        schema:
          type: string
        required: true
        description: The product ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        parentOrderSn:
                          type: string
                        parentOrderTime:
                          type: string
                        parentOrderStatus:
                          type: string
                        integration_instance_id:
                          type: integer
                        json_object:
                          type: object
                          properties:
                            parentOrderSn:
                              type: string
                            orderList:
                              type: array
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                  first_page_url:
                    type: string
                  last_page_url:
                    type: string
                  next_page_url:
                    type: string
                    nullable: true
                  prev_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  links:
                    type: array
                example:
                  data:
                  - id: 7781
                    parentOrderSn: PO-2026-0001234
                    parentOrderTime: '2026-06-17T09:42:11.000000Z'
                    parentOrderStatus: SHIPPED
                    integration_instance_id: 12
                    json_object:
                      parentOrderSn: PO-2026-0001234
                      orderList: []
                    created_at: '2026-06-17T09:44:00.000000Z'
                    updated_at: '2026-06-18T12:01:18.000000Z'
                  current_page: 1
                  last_page: 1
                  per_page: 10
                  total: 1
                  from: 1
                  to: 1
                  first_page_url: https://app.sku.io/api/temu/12/products/1024/orders?page=1
                  last_page_url: https://app.sku.io/api/temu/12/products/1024/orders?page=1
                  next_page_url: null
                  prev_page_url: null
                  path: https://app.sku.io/api/temu/12/products/1024/orders
                  links: []
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-temu-integrationinstance-products-product-orders
  /api/temu/{integrationInstance}/fulfillments:
    get:
      tags:
      - Temu
      summary: List Fulfillments
      description: 'Paginated list of SalesOrderFulfillment records for the given
        Temu integration instance. Per-page default is 10. Supports Spatie QueryBuilder
        filters (filter[...]), sorts (sort=...), and grouped advanced filters (filter_groups).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: per_page
        in: query
        schema:
          type: integer
        example: '10'
        description: Results per page (default 10).
      - name: page
        in: query
        schema:
          type: integer
        example: '1'
        description: Page number (default 1).
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        fulfillment_number:
                          type: string
                        sales_order_id:
                          type: integer
                        fulfillment_sequence:
                          type: integer
                        fulfillment_type:
                          type: string
                        status:
                          type: string
                        tracking_number:
                          type: string
                        tracking_link:
                          type: string
                        cost:
                          type: string
                        fulfilled_at:
                          type: string
                        submitted_to_sales_channel_at:
                          type: string
                        warehouse:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            type:
                              type: string
                        requested_shipping_method:
                          type: string
                        fulfilled_shipping_method:
                          type: string
                        fulfilled_quantity:
                          type: integer
                        sales_order:
                          type: object
                          properties:
                            id:
                              type: integer
                            sales_order_number:
                              type: string
                            order_status:
                              type: string
                            temu_order:
                              type: object
                              properties:
                                id:
                                  type: integer
                                parentOrderSn:
                                  type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                    items:
                      type: object
                      properties:
                        url:
                          type: string
                          nullable: true
                        label:
                          type: string
                        active:
                          type: boolean
                  next_page_url:
                    type: string
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 4521
                    fulfillment_number: FUL-4521
                    sales_order_id: 9912
                    fulfillment_sequence: 1
                    fulfillment_type: manual
                    status: fulfilled
                    tracking_number: 1Z999AA10123456784
                    tracking_link: https://www.ups.com/track?tracknum=1Z999AA10123456784
                    cost: '5.99'
                    fulfilled_at: '2026-06-18T14:32:11.000000Z'
                    submitted_to_sales_channel_at: '2026-06-18T14:32:45.000000Z'
                    warehouse:
                      id: 12
                      name: Main Warehouse
                      type: physical
                    requested_shipping_method: UPS Ground
                    fulfilled_shipping_method: UPS Ground
                    fulfilled_quantity: 2
                    sales_order:
                      id: 9912
                      sales_order_number: SO-9912
                      order_status: shipped
                      temu_order:
                        id: 33012
                        parentOrderSn: PO123456789012345
                    created_at: '2026-06-18T14:30:00.000000Z'
                    updated_at: '2026-06-18T14:32:45.000000Z'
                  current_page: 1
                  first_page_url: https://sku-a.test/api/temu/1/fulfillments?page=1
                  from: 1
                  last_page: 3
                  last_page_url: https://sku-a.test/api/temu/1/fulfillments?page=3
                  links:
                  - url: null
                    label: '&laquo; Previous'
                    active: false
                  - url: https://sku-a.test/api/temu/1/fulfillments?page=1
                    label: '1'
                    active: true
                  - url: https://sku-a.test/api/temu/1/fulfillments?page=2
                    label: Next &raquo;
                    active: false
                  next_page_url: https://sku-a.test/api/temu/1/fulfillments?page=2
                  path: https://sku-a.test/api/temu/1/fulfillments
                  per_page: 10
                  prev_page_url: null
                  to: 10
                  total: 27
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-temu-integrationinstance-fulfillments
  /api/temu/{integrationInstance}/fulfillments/{fulfillment}:
    get:
      tags:
      - Temu
      summary: Show Fulfillment
      description: 'Returns a single fulfillment with lines, warehouse/carrier mapping
        flags, API call logs, and the warehouse/carrier display-name maps used by
        the UI. Returns 404 if the fulfillment does not belong to the given Temu integration
        instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: fulfillment
        in: path
        schema:
          type: string
        required: true
        description: The fulfillment ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      fulfillment_number:
                        type: string
                      sales_order_id:
                        type: integer
                      fulfillment_sequence:
                        type: integer
                      fulfillment_type:
                        type: string
                      status:
                        type: string
                      tracking_number:
                        type: string
                      tracking_link:
                        type: string
                      cost:
                        type: string
                      fulfilled_at:
                        type: string
                      submitted_to_sales_channel_at:
                        type: string
                      warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          type:
                            type: string
                      requested_shipping_method:
                        type: string
                      fulfilled_shipping_method:
                        type: string
                      fulfilled_quantity:
                        type: integer
                      sales_order:
                        type: object
                        properties:
                          id:
                            type: integer
                          sales_order_number:
                            type: string
                          order_status:
                            type: string
                          temu_order:
                            type: object
                            properties:
                              id:
                                type: integer
                              parentOrderSn:
                                type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      fulfillment_lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            quantity:
                              type: integer
                            sku:
                              type: string
                            product_name:
                              type: string
                      user:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      warehouse_mapped:
                        type: boolean
                      carrier_mapped:
                        type: boolean
                      api_logs:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            request_url:
                              type: string
                            request_method:
                              type: string
                            request_body:
                              type: string
                            response_status:
                              type: integer
                            response_body:
                              type: string
                            request_timestamp:
                              type: string
                            response_timestamp:
                              type: string
                            duration:
                              type: integer
                            warehouse_name:
                              type: string
                            carrier_name:
                              type: string
                example:
                  data:
                    id: 4521
                    fulfillment_number: FUL-4521
                    sales_order_id: 9912
                    fulfillment_sequence: 1
                    fulfillment_type: manual
                    status: fulfilled
                    tracking_number: 1Z999AA10123456784
                    tracking_link: https://www.ups.com/track?tracknum=1Z999AA10123456784
                    cost: '5.99'
                    fulfilled_at: '2026-06-18T14:32:11.000000Z'
                    submitted_to_sales_channel_at: '2026-06-18T14:32:45.000000Z'
                    warehouse:
                      id: 12
                      name: Main Warehouse
                      type: physical
                    requested_shipping_method: UPS Ground
                    fulfilled_shipping_method: UPS Ground
                    fulfilled_quantity: 2
                    sales_order:
                      id: 9912
                      sales_order_number: SO-9912
                      order_status: shipped
                      temu_order:
                        id: 33012
                        parentOrderSn: PO123456789012345
                    created_at: '2026-06-18T14:30:00.000000Z'
                    updated_at: '2026-06-18T14:32:45.000000Z'
                    fulfillment_lines:
                    - id: 8801
                      quantity: 2
                      sku: SKU-RED-M
                      product_name: Red T-Shirt (Medium)
                    user:
                      id: 7
                      name: Operations Bot
                    warehouse_mapped: true
                    carrier_mapped: true
                    api_logs:
                    - id: 552201
                      request_url: https://openapi.temu.com/openapi/router
                      request_method: POST
                      request_body: '{"request":{"sendRequestList":[{"selfShippingWarehouseId":"WH001","carrierId":1001,"trackingNumber":"1Z999AA10123456784"}]}}'
                      response_status: 200
                      response_body: '{"success":true,"result":{"successList":["PO123456789012345"]}}'
                      request_timestamp: '2026-06-18T14:32:44.500000Z'
                      response_timestamp: '2026-06-18T14:32:45.100000Z'
                      duration: 600
                      warehouse_name: Main Warehouse
                      carrier_name: UPS
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-temu-integrationinstance-fulfillments-fulfillment
  /api/temu/{integrationInstance}/fulfill:
    post:
      tags:
      - Temu
      summary: Submit Fulfillment to Temu
      description: 'Registered by the shared salesChannel route macro (POST /api/temu/{integrationInstance}/fulfill).
        Submits an existing SalesOrderFulfillment to Temu. Temu does NOT auto-generate
        tracking — a carrier tracking number must already be stored on the fulfillment
        OR be supplied here in the request body (it will be persisted).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Validation:

        - sales_order_fulfillment_id (required, integer, must exist in sales_order_fulfillments)

        - tracking_number (nullable, string, max 255)'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                sales_order_fulfillment_id:
                  type: integer
                tracking_number:
                  type: string
              example:
                sales_order_fulfillment_id: 4521
                tracking_number: 1Z999AA10123456784
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                  data:
                    type: string
                    nullable: true
                example:
                  success: true
                  message: Successfully submitted to Temu.
                  data: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-temu-integrationinstance-fulfill
  /api/temu/{integrationInstance}/shipment-status:
    post:
      tags:
      - Temu
      summary: Get Shipment Status
      description: 'Fetches the current shipment/tracking status from Temu for a single
        child order (orderSn) belonging to a parent order (parentOrderSn). Proxies
        bg.logistics.shipment.get on the Temu Open Platform.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Validation:

        - parent_order_sn (required, string)

        - order_sn (required, string)'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                parent_order_sn:
                  type: string
                order_sn:
                  type: string
              example:
                parent_order_sn: PO123456789012345
                order_sn: OO987654321098765
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  errorCode:
                    type: integer
                  errorMsg:
                    type: string
                  result:
                    type: object
                    properties:
                      parentOrderSn:
                        type: string
                      orderSn:
                        type: string
                      shipmentStatus:
                        type: string
                      trackingNumber:
                        type: string
                      carrierId:
                        type: integer
                      carrierName:
                        type: string
                      shippedAt:
                        type: integer
                      deliveredAt:
                        type: integer
                example:
                  success: true
                  errorCode: 1000000
                  errorMsg: Success
                  result:
                    parentOrderSn: PO123456789012345
                    orderSn: OO987654321098765
                    shipmentStatus: DELIVERED
                    trackingNumber: 1Z999AA10123456784
                    carrierId: 1001
                    carrierName: UPS
                    shippedAt: 1750250400
                    deliveredAt: 1750500000
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-temu-integrationinstance-shipment-status
  /api/temu/{integrationInstance}/update-shipping-type:
    post:
      tags:
      - Temu
      summary: Update Shipping Type
      description: 'Updates the carrier and tracking number for a shipment that has
        already been submitted. Used when the original carrier doesn''t pick up the
        package within 48 hours and the seller needs to switch carriers without recreating
        the shipment.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Validation:

        - parent_order_sn (required, string)

        - order_sn (required, string)

        - carrier_id (required, integer — Temu logisticsServiceProviderId)

        - tracking_number (required, string, max 255)'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                parent_order_sn:
                  type: string
                order_sn:
                  type: string
                carrier_id:
                  type: integer
                tracking_number:
                  type: string
              example:
                parent_order_sn: PO123456789012345
                order_sn: OO987654321098765
                carrier_id: 1001
                tracking_number: 1Z999AA10123456784
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  errorCode:
                    type: integer
                  errorMsg:
                    type: string
                  result:
                    type: object
                    properties:
                      parentOrderSn:
                        type: string
                      orderSn:
                        type: string
                      updated:
                        type: boolean
                example:
                  success: true
                  errorCode: 1000000
                  errorMsg: Success
                  result:
                    parentOrderSn: PO123456789012345
                    orderSn: OO987654321098765
                    updated: true
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-temu-integrationinstance-update-shipping-type
  /api/temu/{integrationInstance}/unshipped-packages:
    post:
      tags:
      - Temu
      summary: Get Unshipped Packages
      description: 'Returns the list of child orders (packages) within a parent order
        that have not yet been confirmed as shipped on Temu. Used to drive the partial-shipment
        / multi-package UI.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Validation:

        - parent_order_sn (required, string)'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                parent_order_sn:
                  type: string
              example:
                parent_order_sn: PO123456789012345
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  errorCode:
                    type: integer
                  errorMsg:
                    type: string
                  result:
                    type: object
                    properties:
                      parentOrderSn:
                        type: string
                      unshippedPackageList:
                        type: array
                        items:
                          type: object
                          properties:
                            orderSn:
                              type: string
                            skcId:
                              type: integer
                            productSkuId:
                              type: integer
                            productSkuName:
                              type: string
                            quantity:
                              type: integer
                example:
                  success: true
                  errorCode: 1000000
                  errorMsg: Success
                  result:
                    parentOrderSn: PO123456789012345
                    unshippedPackageList:
                    - orderSn: OO987654321098766
                      skcId: 5500123
                      productSkuId: 7700456
                      productSkuName: Red T-Shirt (Medium)
                      quantity: 2
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-temu-integrationinstance-unshipped-packages
  /api/temu/{integrationInstance}/confirm-shipped-package:
    post:
      tags:
      - Temu
      summary: Confirm Shipped Package
      description: 'Confirms one or more packages within a parent order as shipped
        on Temu, supplying the carrier tracking number for each child order. Required
        because Temu does NOT auto-generate tracking — sellers must supply tracking
        for every package before Temu treats the parent order as shipped.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Validation:

        - parent_order_sn (required, string)

        - package_list (required, array)

        - package_list.*.orderSn (required, string)

        - package_list.*.trackingNumber (required, string)'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                parent_order_sn:
                  type: string
                package_list:
                  type: array
                  items:
                    type: object
                    properties:
                      orderSn:
                        type: string
                      trackingNumber:
                        type: string
              example:
                parent_order_sn: PO123456789012345
                package_list:
                - orderSn: OO987654321098765
                  trackingNumber: 1Z999AA10123456784
                - orderSn: OO987654321098766
                  trackingNumber: 1Z999AA10123456785
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  errorCode:
                    type: integer
                  errorMsg:
                    type: string
                  result:
                    type: object
                    properties:
                      parentOrderSn:
                        type: string
                      confirmedList:
                        type: array
                        items:
                          type: object
                          properties:
                            orderSn:
                              type: string
                            trackingNumber:
                              type: string
                            status:
                              type: string
                      failedList:
                        type: array
                example:
                  success: true
                  errorCode: 1000000
                  errorMsg: Success
                  result:
                    parentOrderSn: PO123456789012345
                    confirmedList:
                    - orderSn: OO987654321098765
                      trackingNumber: 1Z999AA10123456784
                      status: SHIPPED
                    failedList: []
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-temu-integrationinstance-confirm-shipped-package
  /api/temu/{integrationInstance}/fulfillments/stats:
    get:
      tags:
      - Temu
      summary: Get Fulfillment Stats
      description: 'Returns lightweight fulfillment counters for the integration instance:


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        - `pending_submit_count` — fulfillments belonging to this channel''s sales
        orders that have not yet been submitted to Temu.

        - `submit_mode` — always `manual` for Temu: every fulfillment must be submitted
        explicitly with a carrier-issued tracking number; there is no automatic shipment
        sync.

        - `submit_mode_description` — human-readable explanation of the submit mode.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '5'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      pending_submit_count:
                        type: integer
                      submit_mode:
                        type: string
                      submit_mode_description:
                        type: string
                example:
                  data:
                    pending_submit_count: 7
                    submit_mode: manual
                    submit_mode_description: Each fulfillment must be submitted manually
                      with a carrier-issued tracking number — Temu does not auto-sync.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-temu-integrationinstance-fulfillments-stats
  /api/temu/{integrationInstance}/fulfillments/{fulfillment}/preflight:
    get:
      tags:
      - Temu
      summary: Get Fulfillment Preflight Result
      description: 'Validates a stored fulfillment against Temu''s shipment-confirmation
        requirements before submission. Temu requires three values per package — a
        mapped carrier, a mapped warehouse, and a tracking number — all of which must
        be configured on the platform side. This endpoint reports exactly which requirements
        are unmet so submission failures can be prevented up front.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Response fields:


        - `can_submit` (boolean) — `true` when every requirement is satisfied.

        - `blockers` (array) — one entry per unmet requirement: `field` (`carrier`,
        `warehouse` or `tracking_number`), a human-readable `message`, and `fix_path`
        (a relative in-app settings path where the mapping can be corrected, or `null`
        when the fix is on the fulfillment itself).

        - `resolved` (object) — the values that would be sent to Temu: `carrier_id`
        (Temu logistics provider id), `warehouse_id` (Temu warehouse id string), `tracking_number`.
        Unresolvable values are `null`.


        Returns 404 when the fulfillment does not belong to this integration instance.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '5'
        description: The integration instance ID.
      - name: fulfillment
        in: path
        schema:
          type: integer
        required: true
        example: '9214'
        description: The fulfillment ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      can_submit:
                        type: boolean
                      blockers:
                        type: array
                        items:
                          type: object
                          properties:
                            field:
                              type: string
                            message:
                              type: string
                            fix_path:
                              type: string
                              nullable: true
                      resolved:
                        type: object
                        properties:
                          carrier_id:
                            type: integer
                          warehouse_id:
                            type: string
                          tracking_number:
                            type: string
                            nullable: true
                  status:
                    type: string
                example:
                  data:
                    can_submit: false
                    blockers:
                    - field: tracking_number
                      message: A tracking number is required by Temu. Enter the carrier-issued
                        tracking number before submitting.
                      fix_path: null
                    resolved:
                      carrier_id: 331
                      warehouse_id: WH-3341992291
                      tracking_number: null
                  status: success
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Fulfillment not found for this integration instance.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-temu-integrationinstance-fulfillments-fulfillment-preflight
  /api/temu/{integrationInstance}/fulfillments/preflight-preview:
    post:
      tags:
      - Temu
      summary: Preview Fulfillment Preflight
      description: 'Runs the same Temu shipment-confirmation checks as the stored-fulfillment
        preflight, but against raw input values instead of a persisted fulfillment.
        Use this to validate a fulfillment while it is still being composed, before
        anything is saved.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Request body (all fields optional — omitted values are reported as blockers):


        - `warehouse_id` (integer) — local warehouse id; must be mapped to a Temu
        warehouse.

        - `shipping_method_id` (integer) — local shipping method id; must be mapped
        to a Temu carrier.

        - `tracking_number` (string, max 255) — carrier-issued tracking number.


        The response shape matches the stored-fulfillment preflight: `can_submit`,
        `blockers` (each with `field`, `message`, `fix_path`), and `resolved` (`carrier_id`,
        `warehouse_id`, `tracking_number`).


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                warehouse_id:
                  type: integer
                shipping_method_id:
                  type: integer
                tracking_number:
                  type: string
              example:
                warehouse_id: 2
                shipping_method_id: 14
                tracking_number: 1Z999AA10123456784
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '5'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      can_submit:
                        type: boolean
                      blockers:
                        type: array
                      resolved:
                        type: object
                        properties:
                          carrier_id:
                            type: integer
                          warehouse_id:
                            type: string
                          tracking_number:
                            type: string
                  status:
                    type: string
                example:
                  data:
                    can_submit: true
                    blockers: []
                    resolved:
                      carrier_id: 331
                      warehouse_id: WH-3341992291
                      tracking_number: 1Z999AA10123456784
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-temu-integrationinstance-fulfillments-preflight-preview
  /api/temu/{integrationInstance}/warehouses:
    get:
      tags:
      - Temu
      summary: List Warehouses
      description: 'Paginated list of TemuWarehouse records for the given integration
        instance. Includes the mapped local Warehouse (when set) via the `warehouse`
        relation. Per-page default is 15.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: per_page
        in: query
        schema:
          type: integer
        example: '15'
        description: Results per page (default 10).
      - name: page
        in: query
        schema:
          type: integer
        example: '1'
        description: Page number (default 1).
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        local_warehouse_id:
                          type: integer
                        warehouseName:
                          type: string
                        warehouseId:
                          type: string
                        warehouseBrand:
                          type: string
                        regionId1:
                          type: string
                        defaultWarehouse:
                          type: boolean
                        json_object:
                          type: object
                          properties:
                            warehouseAddress:
                              type: object
                              properties:
                                countryCode:
                                  type: string
                                province:
                                  type: string
                                city:
                                  type: string
                                postCode:
                                  type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                        integration_instance:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        warehouse:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            type:
                              type: string
                  current_page:
                    type: integer
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                    items:
                      type: object
                      properties:
                        url:
                          type: string
                          nullable: true
                        label:
                          type: string
                        active:
                          type: boolean
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 17
                    integration_instance_id: 1
                    local_warehouse_id: 12
                    warehouseName: US East Fulfillment Center
                    warehouseId: WH-US-EAST-001
                    warehouseBrand: SKU Operations
                    regionId1: '211'
                    defaultWarehouse: true
                    json_object:
                      warehouseAddress:
                        countryCode: US
                        province: NJ
                        city: Newark
                        postCode: '07102'
                    created_at: '2026-05-12T10:14:22.000000Z'
                    updated_at: '2026-06-18T09:01:45.000000Z'
                    integration_instance:
                      id: 1
                      name: Temu US Production
                    warehouse:
                      id: 12
                      name: Main Warehouse
                      type: physical
                  - id: 18
                    integration_instance_id: 1
                    local_warehouse_id: null
                    warehouseName: US West Fulfillment Center
                    warehouseId: WH-US-WEST-001
                    warehouseBrand: null
                    regionId1: '211'
                    defaultWarehouse: false
                    json_object: {}
                    created_at: '2026-05-12T10:14:23.000000Z'
                    updated_at: '2026-05-12T10:14:23.000000Z'
                    integration_instance:
                      id: 1
                      name: Temu US Production
                    warehouse: null
                  current_page: 1
                  first_page_url: https://sku-a.test/api/temu/1/warehouses?page=1
                  from: 1
                  last_page: 1
                  last_page_url: https://sku-a.test/api/temu/1/warehouses?page=1
                  links:
                  - url: null
                    label: '&laquo; Previous'
                    active: false
                  - url: https://sku-a.test/api/temu/1/warehouses?page=1
                    label: '1'
                    active: true
                  - url: null
                    label: Next &raquo;
                    active: false
                  next_page_url: null
                  path: https://sku-a.test/api/temu/1/warehouses
                  per_page: 15
                  prev_page_url: null
                  to: 2
                  total: 2
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-temu-integrationinstance-warehouses
  /api/temu/{integrationInstance}/download-locations:
    get:
      tags:
      - Temu
      summary: Download Warehouses (Sync from Temu)
      description: 'Synchronously dispatches a background job against the Temu Open
        API to refresh the TemuWarehouse cache for this integration instance. Returns
        the refreshed list of Temu warehouses along with the local inventory warehouses
        configured on the instance for the mapping UI.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      temuLocations:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            integration_instance_id:
                              type: integer
                            local_warehouse_id:
                              type: integer
                            warehouseName:
                              type: string
                            warehouseId:
                              type: string
                            warehouseBrand:
                              type: string
                            regionId1:
                              type: string
                            defaultWarehouse:
                              type: boolean
                            json_object:
                              type: object
                              properties:
                                warehouseAddress:
                                  type: object
                                  properties:
                                    countryCode:
                                      type: string
                                    province:
                                      type: string
                                    city:
                                      type: string
                            created_at:
                              type: string
                            updated_at:
                              type: string
                      inventoryLocations:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                example:
                  data:
                    temuLocations:
                    - id: 17
                      integration_instance_id: 1
                      local_warehouse_id: 12
                      warehouseName: US East Fulfillment Center
                      warehouseId: WH-US-EAST-001
                      warehouseBrand: SKU Operations
                      regionId1: '211'
                      defaultWarehouse: true
                      json_object:
                        warehouseAddress:
                          countryCode: US
                          province: NJ
                          city: Newark
                      created_at: '2026-05-12T10:14:22.000000Z'
                      updated_at: '2026-06-19T08:02:11.000000Z'
                    inventoryLocations:
                    - id: 12
                      name: Main Warehouse
                    - id: 14
                      name: West Coast DC
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-temu-integrationinstance-download-locations
  /api/temu/{integrationInstance}/warehouses/{temu_warehouse}/map:
    put:
      tags:
      - Temu
      summary: Map Warehouse to Local Warehouse
      description: 'Sets `local_warehouse_id` on the TemuWarehouse record so fulfillments
        routed to this Temu warehouse pull stock from the chosen local Warehouse.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Validation:

        - `warehouse_id` — nullable integer, must exist in `warehouses`. Pass `null`
        to clear the mapping.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                warehouse_id:
                  type: integer
              example:
                warehouse_id: 12
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: temu_warehouse
        in: path
        schema:
          type: string
        required: true
        description: The temu warehouse ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      local_warehouse_id:
                        type: integer
                      warehouseName:
                        type: string
                      warehouseId:
                        type: string
                      warehouseBrand:
                        type: string
                      regionId1:
                        type: string
                      defaultWarehouse:
                        type: boolean
                      json_object:
                        type: object
                        properties:
                          warehouseAddress:
                            type: object
                            properties:
                              countryCode:
                                type: string
                              province:
                                type: string
                              city:
                                type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 17
                    integration_instance_id: 1
                    local_warehouse_id: 12
                    warehouseName: US East Fulfillment Center
                    warehouseId: WH-US-EAST-001
                    warehouseBrand: SKU Operations
                    regionId1: '211'
                    defaultWarehouse: true
                    json_object:
                      warehouseAddress:
                        countryCode: US
                        province: NJ
                        city: Newark
                    created_at: '2026-05-12T10:14:22.000000Z'
                    updated_at: '2026-06-19T08:10:01.000000Z'
                  message: Warehouse mapping updated successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-temu-integrationinstance-warehouses-temu-warehouse-map
  /api/temu/{integrationInstance}/warehouses/by-warehouse/{warehouse_id}:
    get:
      tags:
      - Temu
      summary: Check Mapping by Local Warehouse
      description: 'Reverse lookup — given a local Warehouse ID, returns the TemuWarehouse
        it is mapped to (if any). Used by the fulfillment UI to warn users before
        submission when a local warehouse has no Temu mapping.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: warehouse_id
        in: path
        schema:
          type: string
        required: true
        description: The warehouse ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          integration_instance_id:
                            type: integer
                          local_warehouse_id:
                            type: integer
                          warehouseName:
                            type: string
                          warehouseId:
                            type: string
                          warehouseBrand:
                            type: string
                          regionId1:
                            type: string
                          defaultWarehouse:
                            type: boolean
                          json_object:
                            type: object
                            properties: {}
                          created_at:
                            type: string
                          updated_at:
                            type: string
                      is_mapped:
                        type: boolean
                example:
                  data:
                    warehouse:
                      id: 17
                      integration_instance_id: 1
                      local_warehouse_id: 12
                      warehouseName: US East Fulfillment Center
                      warehouseId: WH-US-EAST-001
                      warehouseBrand: SKU Operations
                      regionId1: '211'
                      defaultWarehouse: true
                      json_object: {}
                      created_at: '2026-05-12T10:14:22.000000Z'
                      updated_at: '2026-06-19T08:10:01.000000Z'
                    is_mapped: true
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-temu-integrationinstance-warehouses-by-warehouse-warehouse-id
  /api/temu/{integrationInstance}/carriers:
    get:
      tags:
      - Temu
      summary: List Carriers
      description: 'Paginated list of TemuCarrier records for the given integration
        instance. Includes the mapped local ShippingMethod (when set) via the `shipping_method`
        relation. Per-page default is 15.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: per_page
        in: query
        schema:
          type: integer
        example: '15'
        description: Results per page (default 10).
      - name: page
        in: query
        schema:
          type: integer
        example: '1'
        description: Page number (default 1).
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        logisticsServiceProviderId:
                          type: integer
                        logisticsServiceProviderName:
                          type: string
                        logisticsBrandName:
                          type: string
                        ship_to_country_id:
                          type: integer
                        local_shipping_method_id:
                          type: integer
                        created_at:
                          type: string
                        updated_at:
                          type: string
                        integration_instance:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        shipping_method:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            carrier:
                              type: string
                  current_page:
                    type: integer
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                    items:
                      type: object
                      properties:
                        url:
                          type: string
                          nullable: true
                        label:
                          type: string
                        active:
                          type: boolean
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 31
                    integration_instance_id: 1
                    logisticsServiceProviderId: 1001
                    logisticsServiceProviderName: UPS
                    logisticsBrandName: UPS Ground
                    ship_to_country_id: 211
                    local_shipping_method_id: 7
                    created_at: '2026-05-12T10:18:01.000000Z'
                    updated_at: '2026-06-15T14:32:00.000000Z'
                    integration_instance:
                      id: 1
                      name: Temu US Production
                    shipping_method:
                      id: 7
                      name: UPS Ground
                      carrier: UPS
                  - id: 32
                    integration_instance_id: 1
                    logisticsServiceProviderId: 1002
                    logisticsServiceProviderName: USPS
                    logisticsBrandName: USPS Priority
                    ship_to_country_id: 211
                    local_shipping_method_id: null
                    created_at: '2026-05-12T10:18:02.000000Z'
                    updated_at: '2026-05-12T10:18:02.000000Z'
                    integration_instance:
                      id: 1
                      name: Temu US Production
                    shipping_method: null
                  current_page: 1
                  first_page_url: https://sku-a.test/api/temu/1/carriers?page=1
                  from: 1
                  last_page: 1
                  last_page_url: https://sku-a.test/api/temu/1/carriers?page=1
                  links:
                  - url: null
                    label: '&laquo; Previous'
                    active: false
                  - url: https://sku-a.test/api/temu/1/carriers?page=1
                    label: '1'
                    active: true
                  - url: null
                    label: Next &raquo;
                    active: false
                  next_page_url: null
                  path: https://sku-a.test/api/temu/1/carriers
                  per_page: 15
                  prev_page_url: null
                  to: 2
                  total: 2
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-temu-integrationinstance-carriers
  /api/temu/{integrationInstance}/download-carriers:
    get:
      tags:
      - Temu
      summary: Download Carriers (Sync from Temu)
      description: 'Synchronously dispatches a background job against the Temu Open
        API to refresh the TemuCarrier cache for the requested region (default US=211).
        When `region_id=all`, dispatches once per supported region. Returns the refreshed
        list of TemuCarrier records together with the regions that were downloaded.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      carriers:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            integration_instance_id:
                              type: integer
                            logisticsServiceProviderId:
                              type: integer
                            logisticsServiceProviderName:
                              type: string
                            logisticsBrandName:
                              type: string
                            ship_to_country_id:
                              type: integer
                            local_shipping_method_id:
                              type: integer
                            created_at:
                              type: string
                            updated_at:
                              type: string
                      regions_downloaded:
                        type: array
                        items:
                          type: integer
                example:
                  data:
                    carriers:
                    - id: 31
                      integration_instance_id: 1
                      logisticsServiceProviderId: 1001
                      logisticsServiceProviderName: UPS
                      logisticsBrandName: UPS Ground
                      ship_to_country_id: 211
                      local_shipping_method_id: 7
                      created_at: '2026-05-12T10:18:01.000000Z'
                      updated_at: '2026-06-19T08:14:30.000000Z'
                    - id: 32
                      integration_instance_id: 1
                      logisticsServiceProviderId: 1002
                      logisticsServiceProviderName: USPS
                      logisticsBrandName: USPS Priority
                      ship_to_country_id: 211
                      local_shipping_method_id: null
                      created_at: '2026-05-12T10:18:02.000000Z'
                      updated_at: '2026-06-19T08:14:30.000000Z'
                    regions_downloaded:
                    - 211
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-temu-integrationinstance-download-carriers
  /api/temu/{integrationInstance}/carriers/{temu_carrier_id}/map:
    put:
      tags:
      - Temu
      summary: Map Carrier to Shipping Method
      description: 'Sets `local_shipping_method_id` on the TemuCarrier record so that
        submitting a fulfillment with the chosen shipping method routes to this Temu
        carrier (logisticsServiceProviderId).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Validation:

        - `shipping_method_id` — nullable integer, must exist in `shipping_methods`.
        Pass `null` to clear the mapping.


        Returns 404 if the TemuCarrier does not belong to the supplied integration
        instance.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                shipping_method_id:
                  type: integer
              example:
                shipping_method_id: 7
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: temu_carrier_id
        in: path
        schema:
          type: string
        required: true
        description: The temu carrier ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      logisticsServiceProviderId:
                        type: integer
                      logisticsServiceProviderName:
                        type: string
                      logisticsBrandName:
                        type: string
                      ship_to_country_id:
                        type: integer
                      local_shipping_method_id:
                        type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      shipping_method:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          carrier:
                            type: string
                  message:
                    type: string
                example:
                  data:
                    id: 31
                    integration_instance_id: 1
                    logisticsServiceProviderId: 1001
                    logisticsServiceProviderName: UPS
                    logisticsBrandName: UPS Ground
                    ship_to_country_id: 211
                    local_shipping_method_id: 7
                    created_at: '2026-05-12T10:18:01.000000Z'
                    updated_at: '2026-06-19T08:20:45.000000Z'
                    shipping_method:
                      id: 7
                      name: UPS Ground
                      carrier: UPS
                  message: Carrier mapping updated successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-temu-integrationinstance-carriers-temu-carrier-id-map
  /api/temu/{integrationInstance}/carriers/by-shipping-method/{shipping_method_id}:
    get:
      tags:
      - Temu
      summary: Check Mapping by Shipping Method
      description: 'Reverse lookup — given a local ShippingMethod ID, returns the
        TemuCarrier it is mapped to (if any). Used by the fulfillment UI to warn users
        before submission when a shipping method has no Temu carrier mapping.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: shipping_method_id
        in: path
        schema:
          type: string
        required: true
        description: The shipping method ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      carrier:
                        type: object
                        properties:
                          id:
                            type: integer
                          integration_instance_id:
                            type: integer
                          logisticsServiceProviderId:
                            type: integer
                          logisticsServiceProviderName:
                            type: string
                          logisticsBrandName:
                            type: string
                          ship_to_country_id:
                            type: integer
                          local_shipping_method_id:
                            type: integer
                          created_at:
                            type: string
                          updated_at:
                            type: string
                      is_mapped:
                        type: boolean
                example:
                  data:
                    carrier:
                      id: 31
                      integration_instance_id: 1
                      logisticsServiceProviderId: 1001
                      logisticsServiceProviderName: UPS
                      logisticsBrandName: UPS Ground
                      ship_to_country_id: 211
                      local_shipping_method_id: 7
                      created_at: '2026-05-12T10:18:01.000000Z'
                      updated_at: '2026-06-19T08:20:45.000000Z'
                    is_mapped: true
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-temu-integrationinstance-carriers-by-shipping-method-shipping-method-id
  /api/temu/{integrationInstance}/field-mappings/available-fields:
    get:
      tags:
      - Temu
      summary: Get Available Fields
      description: 'Returns the catalog of available Temu product fields (grouped
        by Basic Info, Pricing & Inventory, Dimensions & Weight) and SKU.io product
        fields available for mapping. Powers the field-mapping configuration UI dropdowns.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      temu_fields:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: string
                            name:
                              type: string
                            group:
                              type: string
                            type:
                              type: string
                      sku_fields:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: string
                            name:
                              type: string
                            description:
                              type: string
                            required:
                              type: boolean
                example:
                  data:
                    temu_fields:
                    - id: skuId
                      name: SKU ID
                      group: Basic Info
                      type: string
                    - id: goodsId
                      name: Goods ID
                      group: Basic Info
                      type: string
                    - id: goodsName
                      name: Goods Name
                      group: Basic Info
                      type: string
                    - id: thumbUrl
                      name: Thumbnail URL
                      group: Basic Info
                      type: string
                    - id: skuStatus
                      name: SKU Status
                      group: Basic Info
                      type: string
                    - id: priceAmount
                      name: Price
                      group: Pricing & Inventory
                      type: decimal
                    - id: priceCurrency
                      name: Currency
                      group: Pricing & Inventory
                      type: string
                    - id: quantity
                      name: Quantity
                      group: Pricing & Inventory
                      type: integer
                    - id: weight
                      name: Weight
                      group: Dimensions & Weight
                      type: decimal
                    - id: length
                      name: Length
                      group: Dimensions & Weight
                      type: decimal
                    - id: width
                      name: Width
                      group: Dimensions & Weight
                      type: decimal
                    - id: height
                      name: Height
                      group: Dimensions & Weight
                      type: decimal
                    sku_fields:
                    - id: sku
                      name: SKU
                      description: Stock keeping unit identifier
                      required: true
                    - id: item_name
                      name: Product Name
                      description: Main product name
                      required: true
                    - id: barcode
                      name: Barcode
                      description: Product barcode (UPC/EAN)
                      required: false
                    - id: mpn
                      name: MPN
                      description: Manufacturer part number
                      required: false
                    - id: brand
                      name: Brand
                      description: Product brand or manufacturer
                      required: false
                    - id: price
                      name: Price
                      description: Selling price
                      required: false
                    - id: weight
                      name: Weight
                      description: Product weight
                      required: false
                    - id: length
                      name: Length
                      description: Product length dimension
                      required: false
                    - id: width
                      name: Width
                      description: Product width dimension
                      required: false
                    - id: height
                      name: Height
                      description: Product height dimension
                      required: false
                    - id: image
                      name: Primary Image
                      description: Primary product image URL
                      required: false
                    - id: other_images
                      name: Additional Images
                      description: Additional product image URLs
                      required: false
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-temu-integrationinstance-field-mappings-available-fields
  /api/temu/{integrationInstance}/field-mappings:
    get:
      tags:
      - Temu
      summary: Get Field Mappings
      description: 'Returns the saved listing field-mapping configuration for this
        Temu integration instance. Each entry pairs a Temu field (`listing_field`)
        with a SKU.io field (`sku_field`) and may include optional parsers that transform
        the value during import.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      mappings:
                        type: array
                        items:
                          type: object
                          properties:
                            listing_field:
                              type: string
                            sku_field:
                              type: string
                            parsers:
                              type: array
                example:
                  data:
                    mappings:
                    - listing_field: skuId
                      sku_field: sku
                      parsers: []
                    - listing_field: goodsName
                      sku_field: item_name
                      parsers: []
                    - listing_field: priceAmount
                      sku_field: price
                      parsers: []
                    - listing_field: thumbUrl
                      sku_field: image
                      parsers: []
                    - listing_field: goodsName
                      sku_field: brand
                      parsers:
                      - rule: fr
                        args:
                          find: 'Brand:'
                          replace: ''
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-temu-integrationinstance-field-mappings
    put:
      tags:
      - Temu
      summary: Update Field Mappings
      description: 'Persist the listing field-mapping configuration for this Temu
        integration instance (model = `listings` in `integration_field_mappings`).
        Replaces the existing mapping for the instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Validation:

        - `mappings` — required array

        - `mappings.*.listing_field` — required string (Temu field id from the available-fields
        catalog)

        - `mappings.*.sku_field` — required string (SKU.io field id from the available-fields
        catalog)

        - `mappings.*.parsers` — optional array of parser rules

        - `mappings.*.parsers.*.rule` — required when `parsers` is supplied; must
        be one of `fr` (find-replace), `tl` (trim-left), `tr` (trim-right), `append`

        - `mappings.*.parsers.*.args` — optional array of parser arguments'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                mappings:
                  type: array
                  items:
                    type: object
                    properties:
                      listing_field:
                        type: string
                      sku_field:
                        type: string
              example:
                mappings:
                - listing_field: skuId
                  sku_field: sku
                - listing_field: goodsName
                  sku_field: item_name
                - listing_field: priceAmount
                  sku_field: price
                - listing_field: thumbUrl
                  sku_field: image
                - listing_field: goodsName
                  sku_field: brand
                  parsers:
                  - rule: fr
                    args:
                      find: 'Brand:'
                      replace: ''
                  - rule: tl
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      mappings:
                        type: array
                        items:
                          type: object
                          properties:
                            listing_field:
                              type: string
                            sku_field:
                              type: string
                  message:
                    type: string
                example:
                  data:
                    mappings:
                    - listing_field: skuId
                      sku_field: sku
                    - listing_field: goodsName
                      sku_field: item_name
                    - listing_field: priceAmount
                      sku_field: price
                    - listing_field: thumbUrl
                      sku_field: image
                    - listing_field: goodsName
                      sku_field: brand
                      parsers:
                      - rule: fr
                        args:
                          find: 'Brand:'
                          replace: ''
                      - rule: tl
                  message: Field mappings saved successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-temu-integrationinstance-field-mappings
  /api/temu/{integrationInstance}/inventory:
    get:
      tags:
      - Temu
      summary: List Inventory (Comparison)
      description: 'Paginated inventory comparison — one row per SKU x Temu warehouse
        from sales_channel_product_inventory_caches. Joins productListing -> salesChannelProduct/product/subscriptionOffering
        and resolves the Temu warehouse name via temu_warehouses.warehouseId. Default
        per_page is 10; default sort is -id. Restricted to warehouses belonging to
        this integration instance. Supports Spatie QueryBuilder filters (filter[...]),
        sorts (sort=...), and grouped advanced filters (filter_groups).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: per_page
        in: query
        schema:
          type: integer
        example: '10'
        description: Results per page (default 10).
      - name: page
        in: query
        schema:
          type: integer
        example: '1'
        description: Page number (default 1).
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        product_listing_id:
                          type: integer
                        document_id:
                          type: integer
                        listing_sku:
                          type: string
                        title:
                          type: string
                        product:
                          type: object
                          properties:
                            id:
                              type: integer
                            sku:
                              type: string
                            name:
                              type: string
                        subscription_offering:
                          type: string
                          nullable: true
                        location_id:
                          type: string
                        location_name:
                          type: string
                        location_is_active:
                          type: boolean
                        sku_quantity:
                          type: integer
                        sales_channel_quantity:
                          type: integer
                        variance:
                          type: integer
                        status:
                          type: string
                        is_sku_recalculation_needed:
                          type: boolean
                        sku_quantity_updated_at:
                          type: string
                        sales_channel_quantity_updated_at:
                          type: string
                        sales_channel_quantity_synced_at:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                    items:
                      type: object
                      properties:
                        url:
                          type: string
                          nullable: true
                        label:
                          type: string
                        active:
                          type: boolean
                  next_page_url:
                    type: string
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 90211
                    product_listing_id: 5521
                    document_id: 8801
                    listing_sku: TEMU-RED-M
                    title: Red T-Shirt (Medium)
                    product:
                      id: 3312
                      sku: SKU-RED-M
                      name: Red T-Shirt (Medium)
                    subscription_offering: null
                    location_id: WH001
                    location_name: Main Warehouse
                    location_is_active: true
                    sku_quantity: 42
                    sales_channel_quantity: 42
                    variance: 0
                    status: synced
                    is_sku_recalculation_needed: false
                    sku_quantity_updated_at: '2026-06-18T14:00:00+00:00'
                    sales_channel_quantity_updated_at: '2026-06-18T13:55:00+00:00'
                    sales_channel_quantity_synced_at: '2026-06-18T14:02:00+00:00'
                    created_at: '2026-05-01T09:00:00+00:00'
                    updated_at: '2026-06-18T14:02:00+00:00'
                  - id: 90212
                    product_listing_id: 5522
                    document_id: 8802
                    listing_sku: TEMU-BLU-L
                    title: Blue T-Shirt (Large)
                    product:
                      id: 3313
                      sku: SKU-BLU-L
                      name: Blue T-Shirt (Large)
                    subscription_offering: null
                    location_id: WH001
                    location_name: Main Warehouse
                    location_is_active: true
                    sku_quantity: 17
                    sales_channel_quantity: 20
                    variance: -3
                    status: variance
                    is_sku_recalculation_needed: false
                    sku_quantity_updated_at: '2026-06-18T14:00:00+00:00'
                    sales_channel_quantity_updated_at: '2026-06-18T13:55:00+00:00'
                    sales_channel_quantity_synced_at: '2026-06-17T10:00:00+00:00'
                    created_at: '2026-05-01T09:00:00+00:00'
                    updated_at: '2026-06-18T14:00:00+00:00'
                  - id: 90213
                    product_listing_id: 5523
                    document_id: 8803
                    listing_sku: TEMU-GRN-S
                    title: Green T-Shirt (Small)
                    product: null
                    subscription_offering:
                      id: 71
                      name: Monthly Tee Club
                      sku: OFFER-TEE-MONTH
                    location_id: WH002
                    location_name: Overflow Warehouse
                    location_is_active: true
                    sku_quantity: 0
                    sales_channel_quantity: null
                    variance: 0
                    status: needs_recalc
                    is_sku_recalculation_needed: true
                    sku_quantity_updated_at: null
                    sales_channel_quantity_updated_at: null
                    sales_channel_quantity_synced_at: null
                    created_at: '2026-06-10T09:00:00+00:00'
                    updated_at: '2026-06-10T09:00:00+00:00'
                  current_page: 1
                  first_page_url: https://sku-a.test/api/temu/1/inventory?page=1
                  from: 1
                  last_page: 5
                  last_page_url: https://sku-a.test/api/temu/1/inventory?page=5
                  links:
                  - url: null
                    label: '&laquo; Previous'
                    active: false
                  - url: https://sku-a.test/api/temu/1/inventory?page=1
                    label: '1'
                    active: true
                  - url: https://sku-a.test/api/temu/1/inventory?page=2
                    label: Next &raquo;
                    active: false
                  next_page_url: https://sku-a.test/api/temu/1/inventory?page=2
                  path: https://sku-a.test/api/temu/1/inventory
                  per_page: 10
                  prev_page_url: null
                  to: 10
                  total: 48
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-temu-integrationinstance-inventory
  /api/temu/{integrationInstance}/inventory/summary:
    get:
      tags:
      - Temu
      summary: Inventory Summary
      description: 'Aggregate inventory statistics for the integration: total rows,
        in-sync count, variance count, needs-recalc count, plus the latest fetch and
        sync timestamps across all cached rows for Temu warehouses owned by this integration.
        Returns zeros and null timestamps when no warehouses are mapped.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      total_items:
                        type: integer
                      in_sync:
                        type: integer
                      with_variance:
                        type: integer
                      needs_recalculation:
                        type: integer
                      last_fetch_at:
                        type: string
                      last_sync_at:
                        type: string
                example:
                  data:
                    total_items: 48
                    in_sync: 39
                    with_variance: 6
                    needs_recalculation: 3
                    last_fetch_at: '2026-06-18T13:55:00.000000Z'
                    last_sync_at: '2026-06-18T14:02:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-temu-integrationinstance-inventory-summary
  /api/temu/{integrationInstance}/inventory/locations:
    get:
      tags:
      - Temu
      summary: List Locations
      description: 'Returns every Temu warehouse for this integration instance — used
        to populate the location filter in the inventory UI. `id` is the external
        Temu warehouseId (also the value used in filter[location_id]), `is_active`
        reflects the warehouse''s defaultWarehouse flag.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: string
                        name:
                          type: string
                        is_active:
                          type: boolean
                example:
                  data:
                  - id: WH001
                    name: Main Warehouse
                    is_active: true
                  - id: WH002
                    name: Overflow Warehouse
                    is_active: false
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-temu-integrationinstance-inventory-locations
  /api/temu/{integrationInstance}/inventory/recache:
    post:
      tags:
      - Temu
      summary: Recache Inventory (Recompute SKU.io Quantities)
      description: 'Queues a background job, which (1) rebuilds `integration_settings.inventory.locations`
        from temu_warehouses (preserving user-edited masterOfStock and inventoryModificationRules)
        and (2) recomputes the `sku_quantity` column on every sales_channel_product_inventory_caches
        row for this integration. Request body is empty. Returns the tracked_job_log_id
        used to poll progress via the recache-progress endpoint or the tracked job
        log endpoints.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties: {}
              example: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                example:
                  message: Inventory recache job has been queued
                  data:
                    tracked_job_log_id: 778812
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-temu-integrationinstance-inventory-recache
  /api/temu/{integrationInstance}/inventory/recache-progress/{trackedJobLogId}:
    get:
      tags:
      - Temu
      summary: Recache Progress
      description: 'Polls the TrackedJobLog row produced by Recache Inventory. Returns
        404 if no log exists for the supplied id. The frontend tracked job log endpoints
        reads `progress_percentage`, `status`, `processed_items` / `total_items` and
        `messages`.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: trackedJobLogId
        in: path
        schema:
          type: string
        required: true
        description: The tracked job log ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      job_type:
                        type: string
                      queue:
                        type: string
                      job_name:
                        type: string
                      status:
                        type: string
                      related_model:
                        type: object
                        properties:
                          id:
                            type: integer
                          type:
                            type: string
                          reference:
                            type: string
                      related_model_reference:
                        type: string
                      messages:
                        type: array
                        items:
                          type: string
                      attempted_at:
                        type: string
                      completed_at:
                        type: string
                        nullable: true
                      duration:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      results:
                        type: string
                        nullable: true
                      total_items:
                        type: integer
                      processed_items:
                        type: integer
                      progress_percentage:
                        type: integer
                      progress_mode:
                        type: string
                      stages:
                        type: string
                        nullable: true
                example:
                  data:
                    id: 778812
                    job_type: Modules\Temu\Jobs\TemuRecacheInventoryTrackedJob
                    queue: default
                    job_name: 'Temu Inventory Recache: Main Temu Store'
                    status: processing
                    related_model:
                      id: 1
                      type: Modules\Temu\Entities\TemuIntegrationInstance
                      reference: Main Temu Store
                    related_model_reference: Main Temu Store
                    messages:
                    - Recomputing sku_quantity for 48 cached rows...
                    attempted_at: '2026-06-19T15:00:00.000000Z'
                    completed_at: null
                    duration: null
                    created_at: '2026-06-19T14:59:59.000000Z'
                    updated_at: '2026-06-19T15:00:05.000000Z'
                    results: null
                    total_items: 48
                    processed_items: 22
                    progress_percentage: 45
                    progress_mode: items
                    stages: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-temu-integrationinstance-inventory-recache-progress-trackedjoblogid
  /api/temu/{integrationInstance}/inventory/sync:
    post:
      tags:
      - Temu
      summary: Sync Inventory to Temu (Push)
      description: 'Queues a background job which pushes the cached SKU.io `sku_quantity`
        values up to Temu via the Temu inventory API. Request body is empty. Returns
        the tracked_job_log_id used to poll progress via the sync-progress endpoint
        or the tracked job log endpoints.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties: {}
              example: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                example:
                  message: Inventory sync job has been queued
                  data:
                    tracked_job_log_id: 778820
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-temu-integrationinstance-inventory-sync
  /api/temu/{integrationInstance}/inventory/sync-progress/{trackedJobLogId}:
    get:
      tags:
      - Temu
      summary: Sync Progress
      description: 'Polls the TrackedJobLog row produced by Sync Inventory to Temu.
        Returns 404 if no log exists for the supplied id. When the job is complete,
        `results` includes per-item push outcomes (successes, failures with messages).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: trackedJobLogId
        in: path
        schema:
          type: string
        required: true
        description: The tracked job log ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      job_type:
                        type: string
                      queue:
                        type: string
                      job_name:
                        type: string
                      status:
                        type: string
                      related_model:
                        type: object
                        properties:
                          id:
                            type: integer
                          type:
                            type: string
                          reference:
                            type: string
                      related_model_reference:
                        type: string
                      messages:
                        type: array
                        items:
                          type: string
                      attempted_at:
                        type: string
                      completed_at:
                        type: string
                      duration:
                        type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      results:
                        type: object
                        properties:
                          total_pushed:
                            type: integer
                          succeeded:
                            type: integer
                          failed_count:
                            type: integer
                          has_failures:
                            type: boolean
                          failures:
                            type: array
                            items:
                              type: object
                              properties:
                                listing_sku:
                                  type: string
                                location_id:
                                  type: string
                                message:
                                  type: string
                      total_items:
                        type: integer
                      processed_items:
                        type: integer
                      progress_percentage:
                        type: integer
                      progress_mode:
                        type: string
                      stages:
                        type: string
                        nullable: true
                example:
                  data:
                    id: 778820
                    job_type: Modules\Temu\Jobs\TemuSyncInventoryTrackedJob
                    queue: default
                    job_name: 'Temu Inventory Sync: Main Temu Store'
                    status: completed
                    related_model:
                      id: 1
                      type: Modules\Temu\Entities\TemuIntegrationInstance
                      reference: Main Temu Store
                    related_model_reference: Main Temu Store
                    messages:
                    - Pushed 48 inventory records to Temu (47 succeeded, 1 failed).
                    attempted_at: '2026-06-19T15:05:00.000000Z'
                    completed_at: '2026-06-19T15:06:12.000000Z'
                    duration: 72
                    created_at: '2026-06-19T15:04:59.000000Z'
                    updated_at: '2026-06-19T15:06:12.000000Z'
                    results:
                      total_pushed: 48
                      succeeded: 47
                      failed_count: 1
                      has_failures: true
                      failures:
                      - listing_sku: TEMU-BLU-L
                        location_id: WH001
                        message: 'Temu API: invalid skuId'
                    total_items: 48
                    processed_items: 48
                    progress_percentage: 100
                    progress_mode: items
                    stages: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-temu-integrationinstance-inventory-sync-progress-trackedjoblogid
  /api/temu/{integrationInstance}/products/sync-inventory:
    post:
      tags:
      - Temu
      summary: Sync Inventory to Temu
      description: 'Computes the current sellable stock for mapped Temu listings and
        pushes the quantities to Temu synchronously. Listings whose cached quantities
        are stale are recalculated first, then the updated numbers are submitted to
        Temu''s inventory API and the local sync cache is refreshed.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Request body:


        - `ids` (array of integers, optional) — product-listing ids to sync. Omit
        to sync every mapped listing for the instance.


        The call is a no-op (still returning the success message) when this platform
        is not configured as the master of stock for the instance, or when no eligible
        listings are found.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 88
                - 89
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '5'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  status:
                    type: string
                example:
                  message: Successfully submitted to sales channel.
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-temu-integrationinstance-products-sync-inventory
  /api/temu/{integrationInstance}/webhooks/configurations:
    get:
      tags:
      - Temu
      summary: List Webhook Configurations
      description: 'Returns every supported event code with its current local subscription
        state (`is_enabled`, `subscribed_at`). Drives the Configuration tab in the
        settings UI.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      configurations:
                        type: array
                        items:
                          type: object
                          properties:
                            event_code:
                              type: string
                            label:
                              type: string
                            description:
                              type: string
                            is_enabled:
                              type: boolean
                            subscribed_at:
                              type: string
                example:
                  data:
                    configurations:
                    - event_code: bg.order.created
                      label: Order Created
                      description: Fires when a new order is placed on Temu.
                      is_enabled: true
                      subscribed_at: '2026-06-15T10:22:11+00:00'
                    - event_code: bg.order.updated
                      label: Order Updated
                      description: Fires when an existing order is updated on Temu.
                      is_enabled: true
                      subscribed_at: '2026-06-15T10:22:11+00:00'
                    - event_code: bg.order.cancelled
                      label: Order Cancelled
                      description: Fires when an order is cancelled on Temu.
                      is_enabled: true
                      subscribed_at: '2026-06-15T10:22:11+00:00'
                    - event_code: bg.order.shipped
                      label: Order Shipped
                      description: Fires when an order has been marked as shipped
                        on Temu.
                      is_enabled: true
                      subscribed_at: '2026-06-15T10:22:11+00:00'
                    - event_code: bg.order.delivered
                      label: Order Delivered
                      description: Fires when an order has been delivered to the customer.
                      is_enabled: false
                      subscribed_at: null
                    - event_code: bg.product.created
                      label: Product Created
                      description: Fires when a new product is created on Temu.
                      is_enabled: true
                      subscribed_at: '2026-06-15T10:22:11+00:00'
                    - event_code: bg.product.updated
                      label: Product Updated
                      description: Fires when a product is updated on Temu.
                      is_enabled: true
                      subscribed_at: '2026-06-15T10:22:11+00:00'
                    - event_code: bg.product.deleted
                      label: Product Deleted
                      description: Fires when a product is removed from Temu.
                      is_enabled: false
                      subscribed_at: null
                    - event_code: bg.inventory.updated
                      label: Inventory Updated
                      description: Fires when Temu updates the available stock for
                        a product.
                      is_enabled: true
                      subscribed_at: '2026-06-15T10:22:11+00:00'
                    - event_code: bg.aftersales.created
                      label: After-Sales Request
                      description: Fires when a buyer initiates a return, refund,
                        or other after-sales action.
                      is_enabled: false
                      subscribed_at: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-temu-integrationinstance-webhooks-configurations
  /api/temu/{integrationInstance}/webhooks/configurations/enable-all:
    post:
      tags:
      - Temu
      summary: Enable All Webhook Subscriptions
      description: 'Dispatches a background job to subscribe the shop to every event
        code in TemuEventCodeEnum. Runs through the Tracked Job pattern — frontend
        should call `notifyJobStarted` and watch the tracked job log endpoints for
        completion. Response includes the `tracked_job_log_id`.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                example:
                  message: Webhook subscription job dispatched
                  data:
                    tracked_job_log_id: 88123
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-temu-integrationinstance-webhooks-configurations-enable-all
  /api/temu/{integrationInstance}/webhooks/configurations/{eventCode}/enable:
    post:
      tags:
      - Temu
      summary: Enable Webhook Subscription
      description: 'Subscribes the shop to a single event code via `bg.tmc.message.update`.
        Idempotent — returns success even if already enabled. Returns 500 if Temu
        rejects the subscription or the event code is invalid.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: eventCode
        in: path
        schema:
          type: string
        required: true
        description: The event code ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      success:
                        type: boolean
                      message:
                        type: string
                      webhook:
                        type: object
                        properties:
                          id:
                            type: integer
                          integration_instance_id:
                            type: integer
                          event_code:
                            type: string
                          subscribed_at:
                            type: string
                          created_at:
                            type: string
                          updated_at:
                            type: string
                      created:
                        type: boolean
                example:
                  message: Webhook enabled successfully
                  data:
                    success: true
                    message: Webhook enabled successfully
                    webhook:
                      id: 412
                      integration_instance_id: 1
                      event_code: bg.order.created
                      subscribed_at: '2026-06-18T16:05:11.000000Z'
                      created_at: '2026-06-18T16:05:11.000000Z'
                      updated_at: '2026-06-18T16:05:11.000000Z'
                    created: true
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-temu-integrationinstance-webhooks-configurations-eventcode-enable
  /api/temu/{integrationInstance}/webhooks/configurations/{eventCode}/disable:
    post:
      tags:
      - Temu
      summary: Disable Webhook Subscription
      description: 'Unsubscribes the shop from a single event code via `bg.tmc.message.update`
        (cancel list), then deletes the local `temu_webhooks` row. Idempotent — succeeds
        even if already disabled. If Temu reports the subscription is already gone
        (error code 110020009 / ''not found'') it is treated as success.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: eventCode
        in: path
        schema:
          type: string
        required: true
        description: The event code ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      success:
                        type: boolean
                      message:
                        type: string
                      deleted:
                        type: boolean
                example:
                  message: Webhook disabled successfully
                  data:
                    success: true
                    message: Webhook disabled successfully
                    deleted: true
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-temu-integrationinstance-webhooks-configurations-eventcode-disable
  /api/temu/{integrationInstance}/webhook-events:
    get:
      tags:
      - Temu
      summary: List Webhook Events
      description: 'Paginated list of webhook events for the given integration instance.
        Uses Spatie QueryBuilder with shared `getWebhookEventAllowedFilters` (text/numeric/datetime
        filters + AdvancedSearch) and supports grouped advanced filters via `filter_groups`.
        Default sort is `-created_at`, default per_page is 10. Returns Temu webhook
        event object payloads (truncates `processing_error` to 200 chars + ellipsis).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: per_page
        in: query
        schema:
          type: integer
        example: '10'
        description: Results per page (default 10).
      - name: page
        in: query
        schema:
          type: integer
        example: '1'
        description: Page number (default 1).
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        event_code:
                          type: string
                        event_label:
                          type: string
                        message_id:
                          type: string
                        unique_id:
                          type: string
                        processing_status:
                          type: string
                        processing_attempts:
                          type: integer
                        last_processing_attempt_at:
                          type: string
                        processing_error:
                          type: string
                          nullable: true
                        payload_date:
                          type: string
                        created_at:
                          type: string
                        processed_at:
                          type: string
                        processing_completed_at:
                          type: string
                        integration_instance:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                  current_page:
                    type: integer
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                    items:
                      type: object
                      properties:
                        url:
                          type: string
                          nullable: true
                        label:
                          type: string
                        active:
                          type: boolean
                  next_page_url:
                    type: string
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 99012
                    event_code: bg.order.created
                    event_label: Order Created
                    message_id: MSG-AB12CD34EF
                    unique_id: PO123456789012345
                    processing_status: processed
                    processing_attempts: 1
                    last_processing_attempt_at: '2026-06-18T16:21:08.000000Z'
                    processing_error: null
                    payload_date: '2026-06-18T16:20:58.000000Z'
                    created_at: '2026-06-18T16:21:02.000000Z'
                    processed_at: '2026-06-18T16:21:09.000000Z'
                    processing_completed_at: '2026-06-18T16:21:09.000000Z'
                    integration_instance:
                      id: 1
                      name: Temu Main Shop
                  - id: 99011
                    event_code: bg.inventory.updated
                    event_label: Inventory Updated
                    message_id: MSG-AB12CD34EE
                    unique_id: '112233445566'
                    processing_status: failed
                    processing_attempts: 2
                    last_processing_attempt_at: '2026-06-18T16:18:45.000000Z'
                    processing_error: '{"error":"SKU not found for productSkcId 112233445566","file":"/var/www/Modules/Temu/Managers/...'
                    payload_date: '2026-06-18T16:18:30.000000Z'
                    created_at: '2026-06-18T16:18:32.000000Z'
                    processed_at: null
                    processing_completed_at: null
                    integration_instance:
                      id: 1
                      name: Temu Main Shop
                  - id: 99010
                    event_code: bg.order.shipped
                    event_label: Order Shipped
                    message_id: MSG-AB12CD34ED
                    unique_id: PO123456789012340
                    processing_status: pending
                    processing_attempts: 0
                    last_processing_attempt_at: null
                    processing_error: null
                    payload_date: '2026-06-18T16:15:11.000000Z'
                    created_at: '2026-06-18T16:15:14.000000Z'
                    processed_at: null
                    processing_completed_at: null
                    integration_instance:
                      id: 1
                      name: Temu Main Shop
                  current_page: 1
                  first_page_url: https://sku-a.test/api/temu/1/webhook-events?page=1
                  from: 1
                  last_page: 12
                  last_page_url: https://sku-a.test/api/temu/1/webhook-events?page=12
                  links:
                  - url: null
                    label: '&laquo; Previous'
                    active: false
                  - url: https://sku-a.test/api/temu/1/webhook-events?page=1
                    label: '1'
                    active: true
                  - url: https://sku-a.test/api/temu/1/webhook-events?page=2
                    label: Next &raquo;
                    active: false
                  next_page_url: https://sku-a.test/api/temu/1/webhook-events?page=2
                  path: https://sku-a.test/api/temu/1/webhook-events
                  per_page: 10
                  prev_page_url: null
                  to: 10
                  total: 117
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-temu-integrationinstance-webhook-events
  /api/temu/{integrationInstance}/webhook-events/stats:
    get:
      tags:
      - Temu
      summary: Get Processing Stats
      description: 'Aggregate counts by processing_status for the given integration
        instance. Drives the summary cards above the events table.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      pending_count:
                        type: integer
                      processing_count:
                        type: integer
                      processed_count:
                        type: integer
                      failed_count:
                        type: integer
                      total_count:
                        type: integer
                  integration_instance:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                example:
                  success: true
                  data:
                    pending_count: 12
                    processing_count: 1
                    processed_count: 98
                    failed_count: 6
                    total_count: 117
                  integration_instance:
                    id: 1
                    name: Temu Main Shop
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-temu-integrationinstance-webhook-events-stats
  /api/temu/{integrationInstance}/webhook-events/process:
    post:
      tags:
      - Temu
      summary: Process Pending Events
      description: 'Processes pending webhook events for the instance. Both body fields
        are optional:

        - `event_code` (string, nullable) — restrict to a single event code. Must
        be one of the TemuEventCodeEnum values (validated server-side).

        - `limit` (int, nullable, 1-100) — cap the number of events processed in this
        call.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                event_code:
                  type: string
                limit:
                  type: integer
              example:
                event_code: bg.order.created
                limit: 25
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      processed_count:
                        type: integer
                      failed_count:
                        type: integer
                      message:
                        type: string
                  message:
                    type: string
                example:
                  success: true
                  data:
                    processed_count: 11
                    failed_count: 1
                    message: Processed 12 webhook event(s)
                  message: Processing completed successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-temu-integrationinstance-webhook-events-process
  /api/temu/{integrationInstance}/webhook-events/retry-failed:
    post:
      tags:
      - Temu
      summary: Retry Failed Events
      description: 'Resets failed events (where `processing_attempts < 3`) back to
        pending then processes them again.

        - `limit` (int, nullable, 1-100) — cap the number of failed events retried
        in this call.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                limit:
                  type: integer
              example:
                limit: 25
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      processed_count:
                        type: integer
                      failed_count:
                        type: integer
                      message:
                        type: string
                  message:
                    type: string
                example:
                  success: true
                  data:
                    processed_count: 5
                    failed_count: 1
                    message: Processed 6 webhook event(s)
                  message: Retry completed successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-temu-integrationinstance-webhook-events-retry-failed
  /api/temu/webhook-events/{eventId}:
    get:
      tags:
      - Temu
      summary: Get Event Details
      description: 'Full event payload including `json_data` (the raw decoded TMC
        message), `processing_error` (full text, not truncated), and timing metadata.
        Backs the event detail drawer.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: eventId
        in: path
        schema:
          type: string
        required: true
        description: The event ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      event_code:
                        type: string
                      event_label:
                        type: string
                      message_id:
                        type: string
                      unique_id:
                        type: string
                      processing_status:
                        type: string
                      processing_attempts:
                        type: integer
                      last_processing_attempt_at:
                        type: string
                      processing_started_at:
                        type: string
                      processing_completed_at:
                        type: string
                      processing_error:
                        type: string
                        nullable: true
                      payload_date:
                        type: string
                      created_at:
                        type: string
                      processed_at:
                        type: string
                      json_data:
                        type: object
                        properties:
                          parentOrderSn:
                            type: string
                          orderStatus:
                            type: integer
                          eventTime:
                            type: integer
                          messageTime:
                            type: integer
                          orderList:
                            type: array
                            items:
                              type: object
                              properties:
                                orderSn:
                                  type: string
                                productSkuId:
                                  type: string
                                quantity:
                                  type: integer
                                price:
                                  type: string
                example:
                  success: true
                  data:
                    id: 99012
                    integration_instance_id: 1
                    event_code: bg.order.created
                    event_label: Order Created
                    message_id: MSG-AB12CD34EF
                    unique_id: PO123456789012345
                    processing_status: processed
                    processing_attempts: 1
                    last_processing_attempt_at: '2026-06-18T16:21:08.000000Z'
                    processing_started_at: '2026-06-18T16:21:08.000000Z'
                    processing_completed_at: '2026-06-18T16:21:09.000000Z'
                    processing_error: null
                    payload_date: '2026-06-18T16:20:58.000000Z'
                    created_at: '2026-06-18T16:21:02.000000Z'
                    processed_at: '2026-06-18T16:21:09.000000Z'
                    json_data:
                      parentOrderSn: PO123456789012345
                      orderStatus: 1
                      eventTime: 1750000858
                      messageTime: 1750000858
                      orderList:
                      - orderSn: ORD123456789012345
                        productSkuId: SKU-RED-M
                        quantity: 2
                        price: '19.99'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-temu-webhook-events-eventid
  /api/temu/webhook-events/{eventId}/process:
    post:
      tags:
      - Temu
      summary: Process Event By Id
      description: 'Processes a single webhook event by id. No-op if the event is
        already in the processed state (returns success with `event already processed`
        message). Does NOT reset state — use `/reprocess` to force a re-run on a processed
        event.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters:
      - name: eventId
        in: path
        schema:
          type: string
        required: true
        description: The event ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      event_id:
                        type: integer
                      success:
                        type: boolean
                      message:
                        type: string
                  message:
                    type: string
                example:
                  success: true
                  data:
                    event_id: 99010
                    success: true
                    message: Event processed successfully
                  message: Event processing completed successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-temu-webhook-events-eventid-process
  /api/temu/webhook-events/{eventId}/reprocess:
    post:
      tags:
      - Temu
      summary: Reprocess Event By Id
      description: 'Forces a re-run of the event even if previously processed — resets
        the row to pending (clearing `processing_error`) and processes it again. Used
        by the ''Reprocess'' action in the per-row menu.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters:
      - name: eventId
        in: path
        schema:
          type: string
        required: true
        description: The event ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      event_id:
                        type: integer
                      success:
                        type: boolean
                      message:
                        type: string
                  message:
                    type: string
                example:
                  success: true
                  data:
                    event_id: 99012
                    success: true
                    message: Event reprocessed successfully
                  message: Event reprocessing completed successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-temu-webhook-events-eventid-reprocess
  /api/temu/webhook-events/bulk-reprocess:
    post:
      tags:
      - Temu
      summary: Bulk Reprocess Events
      description: 'Resets each event in `event_ids` to pending and processes it again.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Validation:

        - `event_ids` (array, required unless `apply_to_all=true`) — each id must
        exist in `temu_webhook_events`.

        - `apply_to_all` (bool, optional) — when true, ignores `event_ids` and resolves
        the id set from `filters` scoped to `integration_instance_id`.

        - `integration_instance_id` (int, required if `apply_to_all=true`) — the instance
        whose events to resolve.

        - `filters` (object, optional) — Spatie filter set forwarded to the repository''s
        `getWebhookEventAllowedFilters()`.


        Returns `processed_count: 0, failed_count: 0` if the resolved id set is empty.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                event_ids:
                  type: array
                  items:
                    type: integer
              example:
                event_ids:
                - 99010
                - 99011
                - 99012
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      processed_count:
                        type: integer
                      failed_count:
                        type: integer
                      message:
                        type: string
                  message:
                    type: string
                example:
                  success: true
                  data:
                    processed_count: 3
                    failed_count: 0
                    message: Processed 3 webhook event(s)
                  message: Bulk reprocessing completed successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-temu-webhook-events-bulk-reprocess
  /api/temu/webhook-events/bulk-delete:
    delete:
      tags:
      - Temu
      summary: Bulk Delete Events
      description: 'Deletes the given webhook events. Requires `confirmation: "YES"`.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Validation:

        - `event_ids` (array, required unless `apply_to_all=true`) — each id must
        exist in `temu_webhook_events`.

        - `apply_to_all` (bool, optional) — when true, resolves the id set from `filters`
        scoped to `integration_instance_id`.

        - `integration_instance_id` (int, required if `apply_to_all=true`).

        - `filters` (object, optional) — Spatie filter set forwarded to the repository.

        - `confirmation` (string, required) — must equal `YES` exactly.


        Returns `deleted_count: 0` if the resolved id set is empty.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      deleted_count:
                        type: integer
                  message:
                    type: string
                example:
                  success: true
                  data:
                    deleted_count: 3
                  message: 3 webhook event(s) deleted successfully
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: delete-api-temu-webhook-events-bulk-delete
  /api/temu/{integrationInstance}/webhook-events/delete-all:
    delete:
      tags:
      - Temu
      summary: Delete All Events (per instance)
      description: 'Hard-deletes every webhook event row for the given integration
        instance. Requires `confirmation: "YES"`. Returns the total `deleted_count`.
        Use with caution — there is no soft-delete on `temu_webhook_events`.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      deleted_count:
                        type: integer
                  message:
                    type: string
                example:
                  success: true
                  data:
                    deleted_count: 117
                  message: 117 webhook event(s) deleted successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-temu-integrationinstance-webhook-events-delete-all
  /api/temu/{integrationInstance}/parent-after-sales:
    get:
      tags:
      - Temu
      summary: List Parent After-Sales
      description: 'Paginated list of TemuParentAfterSale records (returns + refunds)
        for the given Temu integration instance. Per-page default is 15. Uses Spatie
        QueryBuilder with grouped filter support — `filter[...]`, `sort=...`, and
        grouped advanced filters via `filter_groups` are all accepted. Default sort
        is `-updateTime`.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: per_page
        in: query
        schema:
          type: integer
        description: Items per page (default 15)
        example: '15'
      - name: page
        in: query
        schema:
          type: integer
        example: '1'
        description: Page number (default 1).
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        parentAfterSalesId:
                          type: string
                        parentOrderSn:
                          type: string
                        parentAfterSalesStatus:
                          type: integer
                        parentAfterSalesStatusLabel:
                          type: string
                        afterSalesStatusGroups:
                          type: array
                          items:
                            type: object
                            properties:
                              value:
                                type: string
                              label:
                                type: string
                        afterSalesReasonCode:
                          type: integer
                        currency:
                          type: string
                        refundAmount:
                          type: integer
                        refundAmountDecimal:
                          type: number
                        applyTime:
                          type: string
                        updateTime:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                    items:
                      type: object
                      properties:
                        url:
                          type: string
                          nullable: true
                        label:
                          type: string
                        active:
                          type: boolean
                  next_page_url:
                    type: string
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 814
                    integration_instance_id: 1
                    parentAfterSalesId: PAS17234560019887421
                    parentOrderSn: PO123456789012345
                    parentAfterSalesStatus: 4
                    parentAfterSalesStatusLabel: Refund Completed
                    afterSalesStatusGroups:
                    - value: completed
                      label: Completed
                    afterSalesReasonCode: 1002
                    currency: USD
                    refundAmount: 1599
                    refundAmountDecimal: 15.99
                    applyTime: '2026-06-12T17:42:11+00:00'
                    updateTime: '2026-06-15T09:18:03+00:00'
                    created_at: '2026-06-12T17:50:00+00:00'
                    updated_at: '2026-06-15T09:18:30+00:00'
                  - id: 813
                    integration_instance_id: 1
                    parentAfterSalesId: PAS17234551112233440
                    parentOrderSn: PO998877665544332
                    parentAfterSalesStatus: 2
                    parentAfterSalesStatusLabel: Under Review
                    afterSalesStatusGroups:
                    - value: in_progress
                      label: In Progress
                    afterSalesReasonCode: 2003
                    currency: USD
                    refundAmount: 2499
                    refundAmountDecimal: 24.99
                    applyTime: '2026-06-14T03:11:55+00:00'
                    updateTime: '2026-06-14T20:02:17+00:00'
                    created_at: '2026-06-14T03:12:30+00:00'
                    updated_at: '2026-06-14T20:02:30+00:00'
                  current_page: 1
                  first_page_url: https://sku-a.test/api/temu/1/parent-after-sales?page=1
                  from: 1
                  last_page: 4
                  last_page_url: https://sku-a.test/api/temu/1/parent-after-sales?page=4
                  links:
                  - url: null
                    label: '&laquo; Previous'
                    active: false
                  - url: https://sku-a.test/api/temu/1/parent-after-sales?page=1
                    label: '1'
                    active: true
                  - url: https://sku-a.test/api/temu/1/parent-after-sales?page=2
                    label: Next &raquo;
                    active: false
                  next_page_url: https://sku-a.test/api/temu/1/parent-after-sales?page=2
                  path: https://sku-a.test/api/temu/1/parent-after-sales
                  per_page: 15
                  prev_page_url: null
                  to: 15
                  total: 58
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-temu-integrationinstance-parent-after-sales
  /api/temu/{integrationInstance}/parent-after-sales/refresh:
    post:
      tags:
      - Temu
      summary: Refresh Parent After-Sales
      description: 'Dispatches a background job to pull recent after-sales (returns/refunds)
        from the Temu API and upsert them into temu_parent_after_sales. Returns immediately
        with a tracked_job_log_id so the frontend can poll the job-tray composable.
        Body: { days_updated?: int } — defaults to 30 days when omitted.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                days_updated:
                  type: integer
              example:
                days_updated: 30
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      queued:
                        type: boolean
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                  success:
                    type: boolean
                example:
                  data:
                    queued: true
                    tracked_job_log_id: 9421
                  message: Returns refresh queued — track progress in the job tray
                  success: true
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-temu-integrationinstance-parent-after-sales-refresh
  /api/temu/{integrationInstance}/pre-start-date-orders:
    get:
      tags:
      - Temu
      summary: Query Pre-Start-Date Orders
      description: 'Paginates through the Temu API (up to 10 pages of 100) for orders
        updated/created in the requested window, filters down to orders whose parentOrderTime
        is strictly before the configured inventory_start_date, and decorates each
        candidate with eligibility flags (eligible, already_imported, ineligible_reason).
        Returns 422 via the FormRequest if inventory_start_date is not set or if the
        date range is not strictly before it.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: created_at_min
        in: query
        schema:
          type: string
        description: REQUIRED. Lower bound for parent order creation. Must be strictly
          BEFORE the configured inventory_start_date.
        example: '2026-05-01'
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        parentOrderSn:
                          type: string
                        parentOrderTime:
                          type: integer
                        parent_order_created_at:
                          type: string
                        parentOrderStatus:
                          type: integer
                        orderAmount:
                          type: integer
                        currency:
                          type: string
                        itemCount:
                          type: integer
                        eligible:
                          type: boolean
                        already_imported:
                          type: boolean
                        ineligible_reason:
                          type: string
                          nullable: true
                  inventory_start_date:
                    type: string
                  meta:
                    type: object
                    properties:
                      total_queried:
                        type: integer
                      eligible_count:
                        type: integer
                      already_imported_count:
                        type: integer
                example:
                  data:
                  - parentOrderSn: PO111122223333444
                    parentOrderTime: 1746115200000
                    parent_order_created_at: '2026-05-02T00:00:00+00:00'
                    parentOrderStatus: 4
                    orderAmount: 4599
                    currency: USD
                    itemCount: 2
                    eligible: true
                    already_imported: false
                    ineligible_reason: null
                  - parentOrderSn: PO555566667777888
                    parentOrderTime: 1746374400000
                    parent_order_created_at: '2026-05-05T00:00:00+00:00'
                    parentOrderStatus: 4
                    orderAmount: 1899
                    currency: USD
                    itemCount: 1
                    eligible: false
                    already_imported: true
                    ineligible_reason: Order already exists locally
                  inventory_start_date: '2026-06-01'
                  meta:
                    total_queried: 2
                    eligible_count: 1
                    already_imported_count: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-temu-integrationinstance-pre-start-date-orders
  /api/temu/{integrationInstance}/pre-start-date-orders/search:
    get:
      tags:
      - Temu
      summary: Search Pre-Start-Date Order
      description: 'Calls the Temu order detail endpoint for a single parent_order_sn,
        filters out any result whose parentOrderTime is on/after the inventory_start_date,
        and decorates the result with eligibility flags. Empty `data` if the order
        is not found, not pre-start-date, or the upstream call errors. Returns 422
        if inventory_start_date is not configured.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: search_by
        in: query
        schema:
          type: string
        description: REQUIRED. Only 'parent_order_sn' is supported today.
        example: parent_order_sn
      - name: search_term
        in: query
        schema:
          type: string
        description: REQUIRED. The Temu parent order SN to look up. 1-255 chars.
        example: PO111122223333444
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        parentOrderSn:
                          type: string
                        parentOrderTime:
                          type: integer
                        parent_order_created_at:
                          type: string
                        parentOrderStatus:
                          type: integer
                        orderAmount:
                          type: integer
                        currency:
                          type: string
                        itemCount:
                          type: integer
                        eligible:
                          type: boolean
                        already_imported:
                          type: boolean
                        ineligible_reason:
                          type: string
                          nullable: true
                  inventory_start_date:
                    type: string
                  meta:
                    type: object
                    properties:
                      total_queried:
                        type: integer
                      eligible_count:
                        type: integer
                      already_imported_count:
                        type: integer
                example:
                  data:
                  - parentOrderSn: PO111122223333444
                    parentOrderTime: 1746115200000
                    parent_order_created_at: '2026-05-02T00:00:00+00:00'
                    parentOrderStatus: 4
                    orderAmount: 4599
                    currency: USD
                    itemCount: 2
                    eligible: true
                    already_imported: false
                    ineligible_reason: null
                  inventory_start_date: '2026-06-01'
                  meta:
                    total_queried: 1
                    eligible_count: 1
                    already_imported_count: 0
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-temu-integrationinstance-pre-start-date-orders-search
  /api/temu/{integrationInstance}/pre-start-date-orders/import:
    post:
      tags:
      - Temu
      summary: Import Pre-Start-Date Orders
      description: 'Import selected pre-start-date orders from Temu by their parent
        order SNs. Each order is fetched from the Temu API and written so it shows
        up in the local order list, flagged as a pre-start-date import.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Because each order requires its own throttled Temu API call, the import runs
        asynchronously as a queued background job. The request returns immediately
        with a tracked job log id that can be polled to follow the import''s progress.


        **Requires the local inventory_start_date to be set** — returns 422 otherwise.


        **Request Body:**

        - `parent_order_sns` (required, array of strings, 1-10,000 entries) — Temu
        parent order SNs to import.


        **Behavior:**

        - Runs as a background import — the request returns right away with a tracked
        job log id; the orders are fetched and stored asynchronously

        - Orders that already exist locally are flagged as pre-start-date imports
        instead of being re-imported


        **Response:**

        - `data.tracked_job_log_id` - id of the tracked job log; poll it to follow
        import progress

        - `message` - human-readable confirmation of how many orders are being imported'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                parent_order_sns:
                  type: array
                  items:
                    type: string
              example:
                parent_order_sns:
                - PO111122223333444
                - PO555566667777888
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 4821
                  message: Importing 2 pre-start-date orders.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-temu-integrationinstance-pre-start-date-orders-import
  /api/temu:
    get:
      tags:
      - Temu
      summary: List Integration Instances
      description: 'Lists every Temu integration instance on the account. Returns
        all instances in a single response with no pagination, so callers can populate
        pickers or iterate instances without paging.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Each instance includes its display name, the linked sales channel and store,
        the effective integration settings, and two convenience booleans (`has_warehouse_mappings`,
        `has_carrier_mappings`) indicating whether at least one Temu warehouse or
        carrier has been mapped to a local warehouse or shipping method — both mappings
        are prerequisites for submitting fulfillments to Temu.


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_name:
                          type: string
                        sales_channel_id:
                          type: integer
                        store:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        has_warehouse_mappings:
                          type: boolean
                        has_carrier_mappings:
                          type: boolean
                        name:
                          type: string
                        integration_settings:
                          type: object
                          properties:
                            start_date:
                              type: string
                            store_id:
                              type: integer
                            auto_link_products:
                              type: boolean
                            auto_create_products:
                              type: boolean
                        is_automatic_sync_enabled:
                          type: boolean
                        created_at:
                          type: string
                        updated_at:
                          type: string
                example:
                  data:
                  - id: 5
                    integration_name: Temu
                    sales_channel_id: 12
                    store:
                      id: 3
                      name: Main Store
                    has_warehouse_mappings: true
                    has_carrier_mappings: true
                    name: Temu US
                    integration_settings:
                      start_date: '2025-01-01'
                      store_id: 3
                      auto_link_products: true
                      auto_create_products: false
                    is_automatic_sync_enabled: true
                    created_at: '2025-11-02T14:21:05.000000Z'
                    updated_at: '2026-06-30T08:12:44.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-temu
    post:
      tags:
      - Temu
      summary: Create Integration Instance
      description: "Creates a Temu integration instance directly from the supplied\
        \ settings and credentials, and creates the linked sales channel record in\
        \ the same transaction. Most production connections are established through\
        \ the OAuth flow instead (`POST /api/temu/oauth/initialize` followed by `POST\
        \ /api/temu/oauth/complete`), which populates the connection credentials automatically\
        \ — use this endpoint when you already hold valid credentials.\n\n:::info[Authorization]\n\
        Any valid API token can call this endpoint — no specific scope required. [Manage\
        \ tokens](https://app.sku.io/settings/api).\n:::\n\nRequest body fields:\n\
        \n- `name` (string, required) — must be unique across all integration instances.\n\
        - `integration_id` (integer, required) — id of the Temu integration definition.\n\
        - `connection_settings` (object, optional) — `appKey`, `appSecret`, `url`,\
        \ `accessToken`, `expiresAt` (all nullable strings).\n- `integration_settings`\
        \ (object, required):\n  - `start_date` (string, required) — orders before\
        \ this date are not imported.\n  - `store_id` (integer, required) — must reference\
        \ an existing store.\n  - `auto_link_products` (boolean, default `true`),\
        \ `auto_create_products` (boolean, default `false`).\n  - Optional accounting\
        \ fields: `sales_nominal_code_id`, `cogs_nominal_code_id`, `shipping_revenue_nominal_code_id`,\
        \ `shipping_refund_nominal_code_id`, `sales_returns_allowances_nominal_code_id`\
        \ (nullable integers referencing nominal codes), `sync_sales_order_invoices_to_accounting`,\
        \ `sync_sales_credit_to_accounting` (booleans).\n  - Optional `pricing` and\
        \ `inventory` objects, `emailCustomers` (boolean), `proforma_marketplace_cost_percentage`,\
        \ `proforma_payment_cost_percentage` (nullable numbers).\n- `is_automatic_sync_enabled`\
        \ (boolean, default `false`).\n- `environment` (string, optional) — `production`\
        \ or `sandbox`. On production servers the environment is always pinned to\
        \ `production`.\n\nThe response returns the created instance. Note that the\
        \ API normalizes all success status codes to 200.\n\nAuthentication: Requires\
        \ Bearer token."
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                integration_id:
                  type: integer
                connection_settings:
                  type: object
                  properties:
                    appKey:
                      type: string
                    appSecret:
                      type: string
                    url:
                      type: string
                      nullable: true
                    accessToken:
                      type: string
                    expiresAt:
                      type: string
                integration_settings:
                  type: object
                  properties:
                    start_date:
                      type: string
                    store_id:
                      type: integer
                    auto_link_products:
                      type: boolean
                    auto_create_products:
                      type: boolean
                is_automatic_sync_enabled:
                  type: boolean
                environment:
                  type: string
              example:
                name: Temu US
                integration_id: 42
                connection_settings:
                  appKey: example-app-key
                  appSecret: example-app-secret
                  url: null
                  accessToken: example-access-token
                  expiresAt: '2026-12-31T00:00:00Z'
                integration_settings:
                  start_date: '2025-01-01'
                  store_id: 3
                  auto_link_products: true
                  auto_create_products: false
                is_automatic_sync_enabled: false
                environment: production
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      integration_id:
                        type: integer
                      connection_settings:
                        type: object
                        properties:
                          appKey:
                            type: string
                          appSecret:
                            type: string
                          url:
                            type: string
                            nullable: true
                          accessToken:
                            type: string
                          expiresAt:
                            type: string
                      integration_settings:
                        type: object
                        properties:
                          start_date:
                            type: string
                          store_id:
                            type: integer
                          auto_link_products:
                            type: boolean
                          auto_create_products:
                            type: boolean
                      is_automatic_sync_enabled:
                        type: boolean
                      environment:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                  status:
                    type: string
                example:
                  data:
                    id: 5
                    name: Temu US
                    integration_id: 42
                    connection_settings:
                      appKey: example-app-key
                      appSecret: example-app-secret
                      url: null
                      accessToken: example-access-token
                      expiresAt: '2026-12-31T00:00:00Z'
                    integration_settings:
                      start_date: '2025-01-01'
                      store_id: 3
                      auto_link_products: true
                      auto_create_products: false
                    is_automatic_sync_enabled: false
                    environment: production
                    created_at: '2026-07-06T10:15:02.000000Z'
                    updated_at: '2026-07-06T10:15:02.000000Z'
                  status: success
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      name:
                        type: array
                        items:
                          type: string
                example:
                  message: The name has already been taken.
                  errors:
                    name:
                    - The name has already been taken.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-temu
  /api/temu/{integrationInstance}:
    get:
      tags:
      - Temu
      summary: Get Integration Instance
      description: 'Returns a single Temu integration instance with its linked sales
        channel and store, effective settings, and the warehouse/carrier mapping indicators.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '5'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_name:
                        type: string
                      sales_channel_id:
                        type: integer
                      store:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      has_warehouse_mappings:
                        type: boolean
                      has_carrier_mappings:
                        type: boolean
                      name:
                        type: string
                      integration_settings:
                        type: object
                        properties:
                          start_date:
                            type: string
                          store_id:
                            type: integer
                          auto_link_products:
                            type: boolean
                          auto_create_products:
                            type: boolean
                      is_automatic_sync_enabled:
                        type: boolean
                      created_at:
                        type: string
                      updated_at:
                        type: string
                  status:
                    type: string
                example:
                  data:
                    id: 5
                    integration_name: Temu
                    sales_channel_id: 12
                    store:
                      id: 3
                      name: Main Store
                    has_warehouse_mappings: true
                    has_carrier_mappings: true
                    name: Temu US
                    integration_settings:
                      start_date: '2025-01-01'
                      store_id: 3
                      auto_link_products: true
                      auto_create_products: false
                    is_automatic_sync_enabled: true
                    created_at: '2025-11-02T14:21:05.000000Z'
                    updated_at: '2026-06-30T08:12:44.000000Z'
                  status: success
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No query results for model.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-temu-integrationinstance
    put:
      tags:
      - Temu
      summary: Update Integration Instance
      description: 'Updates a Temu integration instance. All body fields are optional
        — only supply the fields you want to change.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        - `name` (string) — new display name.

        - `connection_settings` (object) — `appKey`, `appSecret`, `url`, `accessToken`,
        `expiresAt`.

        - `integration_settings` (object) — same fields as on create (`start_date`,
        `store_id`, `auto_link_products`, `auto_create_products`, nominal code ids,
        `pricing`, `inventory`, `emailCustomers`, proforma cost percentages, accounting
        sync toggles). With PUT the supplied `integration_settings` object is merged
        against the stored settings at the top level; PATCH additionally deep-merges
        nested objects (JSON Merge Patch semantics), except that `inventory` lists
        are always replaced wholesale.

        - `is_automatic_sync_enabled` (boolean).


        Side effects when specific settings change:


        - `start_date` — the instance re-anchors its order sync window.

        - `store_id` — the linked sales channel is repointed to the new store.

        - `pricing.masterOfPrice.name` — a background job recalculates cached listing
        prices.

        - `inventory` — the channel inventory cache is invalidated and rebuilt.

        - Accounting sync toggles — linked accounting transactions are re-evaluated
        for sync eligibility.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                integration_settings:
                  type: object
                  properties:
                    start_date:
                      type: string
                    store_id:
                      type: integer
                    auto_link_products:
                      type: boolean
                    auto_create_products:
                      type: boolean
                is_automatic_sync_enabled:
                  type: boolean
              example:
                name: Temu US (renamed)
                integration_settings:
                  start_date: '2025-03-01'
                  store_id: 3
                  auto_link_products: true
                  auto_create_products: true
                is_automatic_sync_enabled: true
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '5'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_name:
                        type: string
                      sales_channel_id:
                        type: integer
                      store:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      has_warehouse_mappings:
                        type: boolean
                      has_carrier_mappings:
                        type: boolean
                      name:
                        type: string
                      integration_settings:
                        type: object
                        properties:
                          start_date:
                            type: string
                          store_id:
                            type: integer
                          auto_link_products:
                            type: boolean
                          auto_create_products:
                            type: boolean
                      is_automatic_sync_enabled:
                        type: boolean
                      created_at:
                        type: string
                      updated_at:
                        type: string
                  status:
                    type: string
                example:
                  data:
                    id: 5
                    integration_name: Temu
                    sales_channel_id: 12
                    store:
                      id: 3
                      name: Main Store
                    has_warehouse_mappings: true
                    has_carrier_mappings: true
                    name: Temu US (renamed)
                    integration_settings:
                      start_date: '2025-03-01'
                      store_id: 3
                      auto_link_products: true
                      auto_create_products: true
                    is_automatic_sync_enabled: true
                    created_at: '2025-11-02T14:21:05.000000Z'
                    updated_at: '2026-07-06T10:22:41.000000Z'
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-temu-integrationinstance
    delete:
      tags:
      - Temu
      summary: Delete Integration Instance
      description: 'Deletes a Temu integration instance. The deletion runs as a queued
        background job because it cascades widely: the instance''s imported orders
        and products, webhook subscriptions and stored webhook events, API logs, saved
        import mappings, and the linked sales channel are all removed.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        The endpoint responds immediately; the actual removal completes shortly afterwards
        in the background.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '5'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                example:
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-temu-integrationinstance
  /api/temu/{integrationInstance}/activity-log:
    get:
      tags:
      - Temu
      summary: List Activity Log Entries
      description: 'Returns the paginated change history recorded against a Temu integration
        instance, newest first. Each entry describes one recorded event (for example
        a settings update) with its structured `properties` payload and the name of
        the user who caused it (null for system-initiated changes).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Supported filters:


        - `filter[event]` — event type, e.g. `created`, `updated`, `deleted`, `bulk_upsert`.

        - `filter[source]` — originating process recorded on the entry, e.g. `manual`.

        - `filter[batch_uuid]` — return only entries belonging to one bulk-operation
        batch.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '5'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        description:
                          type: string
                        event:
                          type: string
                        properties:
                          type: object
                          properties:
                            attributes:
                              type: object
                              properties:
                                is_automatic_sync_enabled:
                                  type: boolean
                            old:
                              type: object
                              properties:
                                is_automatic_sync_enabled:
                                  type: boolean
                        causer_name:
                          type: string
                        created_at:
                          type: string
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                    items:
                      type: object
                      properties:
                        url:
                          type: string
                          nullable: true
                        label:
                          type: string
                        active:
                          type: boolean
                  next_page_url:
                    type: string
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 90412
                    description: updated
                    event: updated
                    properties:
                      attributes:
                        is_automatic_sync_enabled: true
                      old:
                        is_automatic_sync_enabled: false
                    causer_name: Jane Doe
                    created_at: '2026-06-28T15:42:10.000000Z'
                  first_page_url: https://example.sku.io/api/temu/5/activity-log?page=1
                  from: 1
                  last_page: 4
                  last_page_url: https://example.sku.io/api/temu/5/activity-log?page=4
                  links:
                  - url: null
                    label: '&laquo; Previous'
                    active: false
                  - url: https://example.sku.io/api/temu/5/activity-log?page=1
                    label: '1'
                    active: true
                  - url: https://example.sku.io/api/temu/5/activity-log?page=2
                    label: Next &raquo;
                    active: false
                  next_page_url: https://example.sku.io/api/temu/5/activity-log?page=2
                  path: https://example.sku.io/api/temu/5/activity-log
                  per_page: 15
                  prev_page_url: null
                  to: 15
                  total: 58
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-temu-integrationinstance-activity-log
  /api/square/instances:
    get:
      tags:
      - Square
      summary: List instances
      description: 'List every Square integration instance for the current tenant.


        **Authentication:** Bearer token required.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        environment:
                          type: string
                        is_authorized:
                          type: boolean
                        auth_method:
                          type: string
                        granted_scopes:
                          type: array
                          items:
                            type: string
                        payments_enabled:
                          type: boolean
                        token_expires_at:
                          type: string
                        merchant_id:
                          type: string
                        order_import_start_date:
                          type: string
                        default_return_warehouse_id:
                          type: integer
                        order_sync_watermark_at:
                          type: string
                        locations_count:
                          type: integer
                        catalog_items_count:
                          type: integer
                        orders_count:
                          type: integer
                        created_at:
                          type: string
                        updated_at:
                          type: string
                example:
                  data:
                  - id: 3
                    name: Main Street Coffee Co.
                    environment: sandbox
                    is_authorized: true
                    auth_method: oauth
                    granted_scopes:
                    - MERCHANT_PROFILE_READ
                    - ITEMS_READ
                    - ORDERS_READ
                    - PAYMENTS_READ
                    - CUSTOMERS_READ
                    - INVENTORY_READ
                    - PAYMENTS_WRITE
                    payments_enabled: true
                    token_expires_at: '2026-08-07T18:24:11+00:00'
                    merchant_id: MLKV1XY23ABCD
                    order_import_start_date: '2026-06-01'
                    default_return_warehouse_id: 3
                    order_sync_watermark_at: '2026-07-08T10:15:00+00:00'
                    locations_count: 2
                    catalog_items_count: 312
                    orders_count: 1284
                    created_at: '2026-07-01T13:50:16+00:00'
                    updated_at: '2026-07-08T10:15:00+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-square-instances
    post:
      tags:
      - Square
      summary: Create instance
      description: 'Create a new Square integration instance. For v1, provide a personal
        access token from the Square Developer Console; OAuth is pending business
        verification.


        **Body fields:**

        - `name` (required) — instance display name

        - `environment` (optional) — `sandbox` | `production`, default `sandbox`

        - `access_token` (optional) — personal access token; if omitted, falls back
        to the tenant''s default sandbox token from Secrets Manager

        - `auth_method` (optional) — `manual` | `oauth`

        - `merchant_id` (optional)

        - `order_import_start_date` (optional, YYYY-MM-DD)

        - `default_return_warehouse_id` (optional, integer)'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                environment:
                  type: string
                access_token:
                  type: string
                auth_method:
                  type: string
                merchant_id:
                  type: string
                order_import_start_date:
                  type: string
                default_return_warehouse_id:
                  type: integer
              example:
                name: My Square Sandbox
                environment: sandbox
                access_token: EAAAlxxV7_3x0NGlDRTxU1n2nPuBW9T1fN74XVOfBUJcZ8CMz0LSfj2UdNd-zG0a
                auth_method: manual
                merchant_id: MLXX0EXAMPLE
                order_import_start_date: '2026-06-01'
                default_return_warehouse_id: 5
      parameters: []
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      environment:
                        type: string
                      is_authorized:
                        type: boolean
                      auth_method:
                        type: string
                      granted_scopes:
                        type: array
                      payments_enabled:
                        type: boolean
                      token_expires_at:
                        type: string
                        nullable: true
                      merchant_id:
                        type: string
                      order_import_start_date:
                        type: string
                      default_return_warehouse_id:
                        type: integer
                      order_sync_watermark_at:
                        type: string
                      locations_count:
                        type: integer
                      catalog_items_count:
                        type: integer
                      orders_count:
                        type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 3
                    name: Main Street Coffee Co.
                    environment: sandbox
                    is_authorized: true
                    auth_method: manual
                    granted_scopes: []
                    payments_enabled: false
                    token_expires_at: null
                    merchant_id: MLKV1XY23ABCD
                    order_import_start_date: '2026-06-01'
                    default_return_warehouse_id: 3
                    order_sync_watermark_at: '2026-07-08T10:15:00+00:00'
                    locations_count: 0
                    catalog_items_count: 0
                    orders_count: 0
                    created_at: '2026-07-01T13:50:16+00:00'
                    updated_at: '2026-07-08T10:15:00+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-square-instances
  /api/square/instances/{squareIntegrationInstance}:
    get:
      tags:
      - Square
      summary: Get instance
      description: Fetch a single Square integration instance by ID.
      parameters:
      - name: squareIntegrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The square integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      environment:
                        type: string
                      is_authorized:
                        type: boolean
                      auth_method:
                        type: string
                      granted_scopes:
                        type: array
                        items:
                          type: string
                      payments_enabled:
                        type: boolean
                      token_expires_at:
                        type: string
                      merchant_id:
                        type: string
                      order_import_start_date:
                        type: string
                      default_return_warehouse_id:
                        type: integer
                      order_sync_watermark_at:
                        type: string
                      locations_count:
                        type: integer
                      catalog_items_count:
                        type: integer
                      orders_count:
                        type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 3
                    name: Main Street Coffee Co.
                    environment: sandbox
                    is_authorized: true
                    auth_method: oauth
                    granted_scopes:
                    - MERCHANT_PROFILE_READ
                    - ITEMS_READ
                    - ORDERS_READ
                    - PAYMENTS_READ
                    - CUSTOMERS_READ
                    - INVENTORY_READ
                    - PAYMENTS_WRITE
                    payments_enabled: true
                    token_expires_at: '2026-08-07T18:24:11+00:00'
                    merchant_id: MLKV1XY23ABCD
                    order_import_start_date: '2026-06-01'
                    default_return_warehouse_id: 3
                    order_sync_watermark_at: '2026-07-08T10:15:00+00:00'
                    locations_count: 2
                    catalog_items_count: 312
                    orders_count: 1284
                    created_at: '2026-07-01T13:50:16+00:00'
                    updated_at: '2026-07-08T10:15:00+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-square-instances-squareintegrationinstance
    put:
      tags:
      - Square
      summary: Update instance
      description: 'Update an existing instance. All fields are optional — only fields
        present in the body are changed.


        `payments_enabled` (boolean, optional) — toggles register card processing
        for this account. Auto-set to true when an OAuth grant includes PAYMENTS_WRITE.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                order_import_start_date:
                  type: string
                payments_enabled:
                  type: boolean
              example:
                name: Renamed Square Instance
                order_import_start_date: '2026-07-01'
                payments_enabled: true
      parameters:
      - name: squareIntegrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The square integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      environment:
                        type: string
                      is_authorized:
                        type: boolean
                      auth_method:
                        type: string
                      granted_scopes:
                        type: array
                        items:
                          type: string
                      payments_enabled:
                        type: boolean
                      token_expires_at:
                        type: string
                      merchant_id:
                        type: string
                      order_import_start_date:
                        type: string
                      default_return_warehouse_id:
                        type: integer
                      order_sync_watermark_at:
                        type: string
                      locations_count:
                        type: integer
                      catalog_items_count:
                        type: integer
                      orders_count:
                        type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 3
                    name: Main Street Coffee Co.
                    environment: sandbox
                    is_authorized: true
                    auth_method: oauth
                    granted_scopes:
                    - MERCHANT_PROFILE_READ
                    - ITEMS_READ
                    - ORDERS_READ
                    - PAYMENTS_READ
                    - CUSTOMERS_READ
                    - INVENTORY_READ
                    - PAYMENTS_WRITE
                    payments_enabled: true
                    token_expires_at: '2026-08-07T18:24:11+00:00'
                    merchant_id: MLKV1XY23ABCD
                    order_import_start_date: '2026-06-01'
                    default_return_warehouse_id: 3
                    order_sync_watermark_at: '2026-07-08T10:15:00+00:00'
                    locations_count: 2
                    catalog_items_count: 312
                    orders_count: 1284
                    created_at: '2026-07-01T13:50:16+00:00'
                    updated_at: '2026-07-08T10:15:00+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-square-instances-squareintegrationinstance
    delete:
      tags:
      - Square
      summary: Delete instance
      description: Delete an integration instance. Also removes all synced Square
        orders, catalog items, locations, and webhook events for this instance. Linked
        SKU sales orders themselves are preserved.
      parameters:
      - name: squareIntegrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The square integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Deleted
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-square-instances-squareintegrationinstance
  /api/square/instances/{squareIntegrationInstance}/test-connection:
    post:
      tags:
      - Square
      summary: Test connection
      description: Call `/v2/merchants/me` on Square using the stored access token.
        Latches the returned `merchant_id` onto the instance if it isn't already set.
      requestBody:
        content: {}
      parameters:
      - name: squareIntegrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The square integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  ok:
                    type: boolean
                  message:
                    type: string
                  merchant:
                    type: object
                    properties:
                      id:
                        type: string
                      business_name:
                        type: string
                      country:
                        type: string
                example:
                  ok: true
                  message: Connection to Square verified.
                  merchant:
                    id: MLXX0EXAMPLE
                    business_name: Example Co
                    country: US
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-square-instances-squareintegrationinstance-test-connection
  /api/square/instances/{squareIntegrationInstance}/sync:
    post:
      tags:
      - Square
      summary: Sync (locations + catalog + orders)
      description: 'Dispatches a background sync job for the instance. Returns immediately
        with a tracked_job_log_id.


        **Body:**

        - `scope` (optional) — `all` (default), `locations`, `catalog`, or `orders`

        - `start_at` (optional, ISO 8601) — override the watermark for the orders
        phase'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                scope:
                  type: string
                start_at:
                  type: string
              example:
                scope: all
                start_at: '2026-06-01T00:00:00Z'
      parameters:
      - name: squareIntegrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The square integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 4211
                  message: Square all sync queued.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-square-instances-squareintegrationinstance-sync
  /api/square/instances/{squareIntegrationInstance}/oauth/authorize-url:
    get:
      tags:
      - Square
      summary: Get OAuth authorize URL
      description: 'Builds the Square OAuth authorization URL for this instance. Redirect
        the merchant''s browser to the returned `authorization_url`; after they approve,
        Square redirects back and the connection is stored automatically with the
        granted scopes.


        The requested scope set always includes the standard sales-channel read scopes
        plus any scopes the instance was already granted (Square replaces the grant
        with exactly what is requested, so re-authorizing never narrows an existing
        grant).


        Pass `capabilities=payments` to additionally request `PAYMENTS_READ`/`PAYMENTS_WRITE`
        so the account can process register card payments. Use the same parameter
        to widen an existing channel-only connection (incremental re-consent).


        When payment scopes are granted, `payments_enabled` is set on the instance
        automatically.'
      parameters:
      - name: squareIntegrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The square integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      authorization_url:
                        type: string
                      requested_scopes:
                        type: array
                        items:
                          type: string
                example:
                  data:
                    authorization_url: https://connect.squareupsandbox.com/oauth2/authorize?client_id=sq0idb-XXXX&scope=MERCHANT_PROFILE_READ+ITEMS_READ+ORDERS_READ+PAYMENTS_READ+CUSTOMERS_READ+INVENTORY_READ&session=false&state=tenant_abc123
                    requested_scopes:
                    - MERCHANT_PROFILE_READ
                    - ITEMS_READ
                    - ORDERS_READ
                    - PAYMENTS_READ
                    - CUSTOMERS_READ
                    - INVENTORY_READ
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-square-instances-squareintegrationinstance-oauth-authorize-url
  /api/square/locations:
    get:
      tags:
      - Square
      summary: List locations
      description: 'Paginated list of Square locations across all instances (or filter
        by `filter[integration_instance_id]`).


        **Filters:** `filter[integration_instance_id]`, `filter[status]` (ACTIVE/INACTIVE),
        `filter[search]` (name / square_location_id / city), `filter[mapped]` (true/false).


        **Allowed sorts:** `id`, `name`, `status`, `created_at`, `updated_at`.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        square_location_id:
                          type: string
                        name:
                          type: string
                        status:
                          type: string
                        type:
                          type: string
                        address:
                          type: object
                          properties:
                            address1:
                              type: string
                            city:
                              type: string
                            province:
                              type: string
                            zip:
                              type: string
                            country_code:
                              type: string
                        phone:
                          type: string
                        currency_code:
                          type: string
                        timezone:
                          type: string
                        warehouse_id:
                          type: integer
                        warehouse:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - id: 10
                    integration_instance_id: 1
                    square_location_id: L2XXXXX7A
                    name: Main Street Store
                    status: ACTIVE
                    type: PHYSICAL
                    address:
                      address1: 123 Main St
                      city: Denver
                      province: CO
                      zip: '80202'
                      country_code: US
                    phone: +1-555-123-4567
                    currency_code: USD
                    timezone: America/Denver
                    warehouse_id: 5
                    warehouse:
                      id: 5
                      name: Main Warehouse
                    created_at: '2026-07-01T10:05:00.000000Z'
                    updated_at: '2026-07-01T10:05:00.000000Z'
                  current_page: 1
                  last_page: 1
                  per_page: 25
                  total: 1
                  from: 1
                  to: 1
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-square-locations
  /api/square/locations/{squareLocation}:
    put:
      tags:
      - Square
      summary: Update location mapping
      description: 'Point a Square location at a SKU warehouse. Pass `warehouse_id:
        null` to unmap.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                warehouse_id:
                  type: integer
              example:
                warehouse_id: 5
      parameters:
      - name: squareLocation
        in: path
        schema:
          type: string
        required: true
        description: The square location ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      square_location_id:
                        type: string
                      name:
                        type: string
                      status:
                        type: string
                      type:
                        type: string
                      address:
                        type: object
                        properties:
                          address1:
                            type: string
                          city:
                            type: string
                          province:
                            type: string
                          zip:
                            type: string
                          country_code:
                            type: string
                      phone:
                        type: string
                      currency_code:
                        type: string
                      timezone:
                        type: string
                      warehouse_id:
                        type: integer
                      warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 10
                    integration_instance_id: 1
                    square_location_id: L2XXXXX7A
                    name: Main Street Store
                    status: ACTIVE
                    type: PHYSICAL
                    address:
                      address1: 123 Main St
                      city: Denver
                      province: CO
                      zip: '80202'
                      country_code: US
                    phone: +1-555-123-4567
                    currency_code: USD
                    timezone: America/Denver
                    warehouse_id: 5
                    warehouse:
                      id: 5
                      name: Main Warehouse
                    created_at: '2026-07-01T10:05:00.000000Z'
                    updated_at: '2026-07-01T10:05:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-square-locations-squarelocation
  /api/square/locations/sync:
    post:
      tags:
      - Square
      summary: Sync locations
      description: 'Synchronously call Square''s `/v2/locations` and upsert `square_locations`
        rows.


        `integration_instance_id` (integer, required) — returns 422 when missing.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                integration_instance_id:
                  type: integer
              example:
                integration_instance_id: 1
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  count:
                    type: integer
                example:
                  message: Synced 3 location(s) from Square.
                  count: 3
        '422':
          description: Unprocessable Content
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      integration_instance_id:
                        type: array
                        items:
                          type: string
                example:
                  message: The integration instance id field is required.
                  errors:
                    integration_instance_id:
                    - The integration instance id field is required.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-square-locations-sync
  /api/square/catalog:
    get:
      tags:
      - Square
      summary: List catalog items
      description: 'Paginated list of Square catalog variations across all instances.


        **Filters:** `filter[integration_instance_id]`, `filter[type]`, `filter[is_deleted]`,
        `filter[mapped]` (true/false), `filter[search]` (name / sku / square_catalog_object_id).


        **Allowed sorts:** `id`, `name`, `sku`, `price`, `created_at`, `updated_at`.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        square_catalog_object_id:
                          type: string
                        square_variation_id:
                          type: string
                        square_parent_id:
                          type: string
                        type:
                          type: string
                        sku:
                          type: string
                        name:
                          type: string
                        description:
                          type: string
                        category:
                          type: string
                        price:
                          type: number
                        currency_code:
                          type: string
                        is_deleted:
                          type: boolean
                        square_updated_at:
                          type: string
                        product_id:
                          type: integer
                        product:
                          type: object
                          properties:
                            id:
                              type: integer
                            sku:
                              type: string
                            name:
                              type: string
                            reference:
                              type: string
                            link_route:
                              type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - id: 42
                    integration_instance_id: 1
                    square_catalog_object_id: AAAA00000000000BBBBBBBB
                    square_variation_id: AAAA00000000000BBBBBBBB
                    square_parent_id: PPPP00000000000CCCCCCCC
                    type: ITEM_VARIATION
                    sku: TEE-BLK-M
                    name: Cotton T-Shirt - Medium Black
                    description: 100% cotton, unisex fit
                    category: Apparel
                    price: 24.99
                    currency_code: USD
                    is_deleted: false
                    square_updated_at: '2026-06-28T14:12:33+00:00'
                    product_id: 987
                    product:
                      id: 987
                      sku: TEE-BLK-M
                      name: Cotton T-Shirt - M/Black
                      reference: TEE-BLK-M
                      link_route: /products/987
                    created_at: '2026-07-01T10:10:00.000000Z'
                    updated_at: '2026-07-01T10:10:00.000000Z'
                  current_page: 1
                  last_page: 1
                  per_page: 25
                  total: 1
                  from: 1
                  to: 1
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-square-catalog
  /api/square/catalog/latest-sync-info:
    get:
      tags:
      - Square
      summary: Get latest catalog sync info
      description: 'Latest-sync summary for an instance''s catalog: the most recently
        updated item plus total / mapped / unmapped product counts. Useful before
        queuing a refresh to decide whether a `since_latest` sync is sufficient.


        Route name: square.catalog.latest-sync-info'
      parameters:
      - name: integration_instance_id
        in: query
        schema:
          type: integer
        description: The Square integration instance to inspect (required).
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      latest_product_title:
                        type: string
                      latest_product_date:
                        type: string
                      total_products:
                        type: integer
                      mapped_products:
                        type: integer
                      unmapped_products:
                        type: integer
                example:
                  data:
                    latest_product_title: Blue Ceramic Mug - Large
                    latest_product_date: '2026-07-06T18:24:11+00:00'
                    total_products: 312
                    mapped_products: 268
                    unmapped_products: 44
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-square-catalog-latest-sync-info
  /api/square/catalog/{squareCatalogItem}:
    put:
      tags:
      - Square
      summary: Update catalog mapping
      description: 'Point a Square catalog variation at a SKU Product. Pass `product_id:
        null` to unmap.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                product_id:
                  type: integer
              example:
                product_id: 987
      parameters:
      - name: squareCatalogItem
        in: path
        schema:
          type: string
        required: true
        description: The square catalog item ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      square_catalog_object_id:
                        type: string
                      square_variation_id:
                        type: string
                      square_parent_id:
                        type: string
                      type:
                        type: string
                      sku:
                        type: string
                      name:
                        type: string
                      description:
                        type: string
                      category:
                        type: string
                      price:
                        type: number
                      currency_code:
                        type: string
                      is_deleted:
                        type: boolean
                      square_updated_at:
                        type: string
                      product_id:
                        type: integer
                      product:
                        type: object
                        properties:
                          id:
                            type: integer
                          sku:
                            type: string
                          name:
                            type: string
                          reference:
                            type: string
                          link_route:
                            type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 42
                    integration_instance_id: 1
                    square_catalog_object_id: AAAA00000000000BBBBBBBB
                    square_variation_id: AAAA00000000000BBBBBBBB
                    square_parent_id: PPPP00000000000CCCCCCCC
                    type: ITEM_VARIATION
                    sku: TEE-BLK-M
                    name: Cotton T-Shirt - Medium Black
                    description: 100% cotton, unisex fit
                    category: Apparel
                    price: 24.99
                    currency_code: USD
                    is_deleted: false
                    square_updated_at: '2026-06-28T14:12:33+00:00'
                    product_id: 987
                    product:
                      id: 987
                      sku: TEE-BLK-M
                      name: Cotton T-Shirt - M/Black
                      reference: TEE-BLK-M
                      link_route: /products/987
                    created_at: '2026-07-01T10:10:00.000000Z'
                    updated_at: '2026-07-01T10:10:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-square-catalog-squarecatalogitem
  /api/square/catalog/sync:
    post:
      tags:
      - Square
      summary: Sync catalog
      description: 'Synchronously call Square''s `/v2/catalog/list` (cursor-paginated)
        and upsert `square_catalog_items` rows.


        `integration_instance_id` (integer, required) — returns 422 when missing.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                integration_instance_id:
                  type: integer
              example:
                integration_instance_id: 1
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  count:
                    type: integer
                example:
                  message: Synced 214 catalog variation(s) from Square.
                  count: 214
        '422':
          description: Unprocessable Content
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      integration_instance_id:
                        type: array
                        items:
                          type: string
                example:
                  message: The integration instance id field is required.
                  errors:
                    integration_instance_id:
                    - The integration instance id field is required.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-square-catalog-sync
  /api/square/orders:
    get:
      tags:
      - Square
      summary: List orders
      description: 'Paginated list of Square orders across all instances.


        **Filters:** `filter[integration_instance_id]`, `filter[state]` (OPEN/COMPLETED/CANCELED),
        `filter[channel_source]` (pos/online/marketplace/unknown), `filter[is_pos]`
        (true/false), `filter[sync_status]` (pending/synced/failed), `filter[search]`
        (square_order_id / customer_email / customer_name), `filter[date_from]` /
        `filter[date_to]` (ISO 8601).


        **Allowed sorts:** `id`, `square_created_at`, `square_updated_at`, `total`,
        `state`, `sync_status`.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        square_order_id:
                          type: string
                        square_location_id:
                          type: string
                        state:
                          type: string
                        source_name:
                          type: string
                        channel_source:
                          type: string
                        is_pos:
                          type: boolean
                        customer_id:
                          type: string
                          nullable: true
                        customer_email:
                          type: string
                        customer_name:
                          type: string
                          nullable: true
                        subtotal:
                          type: number
                        tax_total:
                          type: integer
                        discount_total:
                          type: integer
                        service_charge_total:
                          type: integer
                        tip_total:
                          type: integer
                        total:
                          type: number
                        currency_code:
                          type: string
                        square_created_at:
                          type: string
                        square_updated_at:
                          type: string
                        closed_at:
                          type: string
                        fulfillment_state:
                          type: string
                        sync_status:
                          type: string
                        sync_error:
                          type: string
                          nullable: true
                        last_synced_at:
                          type: string
                        sales_order_id:
                          type: integer
                        sales_order:
                          type: object
                          properties:
                            id:
                              type: integer
                            sales_order_number:
                              type: string
                            link_route:
                              type: string
                        line_items:
                          type: array
                          items:
                            type: object
                            properties:
                              id:
                                type: integer
                              uid:
                                type: string
                              sku:
                                type: string
                              name:
                                type: string
                              variation_name:
                                type: string
                              quantity:
                                type: integer
                              base_price:
                                type: number
                              gross_sales:
                                type: number
                              total_tax:
                                type: integer
                              total_discount:
                                type: integer
                              total:
                                type: number
                              currency_code:
                                type: string
                              square_catalog_object_id:
                                type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - id: 128
                    integration_instance_id: 1
                    square_order_id: ORDER123XYZ
                    square_location_id: L2XXXXX7A
                    state: COMPLETED
                    source_name: Point of Sale
                    channel_source: pos
                    is_pos: true
                    customer_id: null
                    customer_email: walk.in@example.com
                    customer_name: null
                    subtotal: 49.98
                    tax_total: 4
                    discount_total: 0
                    service_charge_total: 0
                    tip_total: 5
                    total: 58.98
                    currency_code: USD
                    square_created_at: '2026-07-01T15:23:00+00:00'
                    square_updated_at: '2026-07-01T15:24:12+00:00'
                    closed_at: '2026-07-01T15:24:12+00:00'
                    fulfillment_state: COMPLETED
                    sync_status: synced
                    sync_error: null
                    last_synced_at: '2026-07-01T15:25:00+00:00'
                    sales_order_id: 5501
                    sales_order:
                      id: 5501
                      sales_order_number: ORDER123XYZ
                      link_route: /orders/5501
                    line_items:
                    - id: 501
                      uid: uid-line-1
                      sku: TEE-BLK-M
                      name: Cotton T-Shirt
                      variation_name: Medium / Black
                      quantity: 2
                      base_price: 24.99
                      gross_sales: 49.98
                      total_tax: 4
                      total_discount: 0
                      total: 58.98
                      currency_code: USD
                      square_catalog_object_id: AAAA00000000000BBBBBBBB
                    created_at: '2026-07-01T15:23:05.000000Z'
                    updated_at: '2026-07-01T15:25:00.000000Z'
                  current_page: 1
                  last_page: 1
                  per_page: 25
                  total: 1
                  from: 1
                  to: 1
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-square-orders
  /api/square/orders/latest-sync-info:
    get:
      tags:
      - Square
      summary: Get latest order sync info
      description: 'Latest-sync summary for an instance''s orders: the most recently
        updated synced order and the total number of orders stored. Useful before
        queuing a refresh to decide whether a `since_latest` sync is sufficient.


        Route name: square.orders.latest-sync-info'
      parameters:
      - name: integration_instance_id
        in: query
        schema:
          type: integer
        description: The Square integration instance to inspect (required).
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      latest_order_id:
                        type: string
                      latest_order_date:
                        type: string
                      total_orders:
                        type: integer
                example:
                  data:
                    latest_order_id: CAISENgvlJ6jLWAzERDzjyHVybY
                    latest_order_date: '2026-07-06T18:24:11+00:00'
                    total_orders: 1284
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-square-orders-latest-sync-info
  /api/square/orders/{squareOrder}:
    get:
      tags:
      - Square
      summary: Get order
      description: 'Fetch one Square order with its line items and linked SKU sales
        order.


        When the order has been promoted, `sales_order` includes the SKU sales order''s
        order/fulfillment/payment statuses, a `link_route` to its detail page, and
        its `fulfillments` (tracking number, warehouse, shipping method, and fulfilled
        line items). `raw_data` (the full Square API payload) is only included on
        this single-order endpoint, not on the list.'
      parameters:
      - name: squareOrder
        in: path
        schema:
          type: string
        required: true
        description: The square order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      square_order_id:
                        type: string
                      square_location_id:
                        type: string
                      state:
                        type: string
                      source_name:
                        type: string
                      channel_source:
                        type: string
                      is_pos:
                        type: boolean
                      customer_id:
                        type: string
                      customer_email:
                        type: string
                      customer_name:
                        type: string
                      subtotal:
                        type: integer
                      tax_total:
                        type: number
                      discount_total:
                        type: integer
                      service_charge_total:
                        type: integer
                      tip_total:
                        type: integer
                      total:
                        type: number
                      currency_code:
                        type: string
                      square_created_at:
                        type: string
                      square_updated_at:
                        type: string
                      closed_at:
                        type: string
                      fulfillment_state:
                        type: string
                      sync_status:
                        type: string
                      sync_error:
                        type: string
                        nullable: true
                      last_synced_at:
                        type: string
                      sales_order_id:
                        type: integer
                      sales_order:
                        type: object
                        properties:
                          id:
                            type: integer
                          sales_order_number:
                            type: string
                          order_status:
                            type: string
                          fulfillment_status:
                            type: string
                          payment_status:
                            type: string
                          link_route:
                            type: string
                          fulfillments:
                            type: array
                            items:
                              type: object
                              properties:
                                id:
                                  type: integer
                                status:
                                  type: string
                                fulfillment_type:
                                  type: string
                                tracking_number:
                                  type: string
                                cost:
                                  type: number
                                fulfilled_at:
                                  type: string
                                submitted_to_sales_channel_at:
                                  type: string
                                  nullable: true
                                warehouse:
                                  type: object
                                  properties:
                                    id:
                                      type: integer
                                    name:
                                      type: string
                                shipping_method:
                                  type: object
                                  properties:
                                    id:
                                      type: integer
                                    name:
                                      type: string
                                line_items:
                                  type: array
                                  items:
                                    type: object
                                    properties:
                                      id:
                                        type: integer
                                      quantity:
                                        type: integer
                                      product_name:
                                        type: string
                                      sku:
                                        type: string
                      line_items:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            uid:
                              type: string
                            sku:
                              type: string
                            name:
                              type: string
                            variation_name:
                              type: string
                            quantity:
                              type: integer
                            base_price:
                              type: number
                            gross_sales:
                              type: integer
                            total_tax:
                              type: number
                            total_discount:
                              type: integer
                            total:
                              type: number
                            currency_code:
                              type: string
                            square_catalog_object_id:
                              type: string
                      raw_data:
                        type: object
                        properties:
                          id:
                            type: string
                          location_id:
                            type: string
                          state:
                            type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 128
                    integration_instance_id: 1
                    square_order_id: CAISENgvlJ6jLWAzERDzjyHVybY
                    square_location_id: L2XXXXX7A
                    state: COMPLETED
                    source_name: Point of Sale
                    channel_source: pos
                    is_pos: true
                    customer_id: 8FMBVGB0Q3GVWMYE86HB4X8H70
                    customer_email: jane@example.com
                    customer_name: Jane Doe
                    subtotal: 45
                    tax_total: 3.94
                    discount_total: 0
                    service_charge_total: 0
                    tip_total: 5
                    total: 53.94
                    currency_code: USD
                    square_created_at: '2026-07-05T14:03:22+00:00'
                    square_updated_at: '2026-07-05T14:05:10+00:00'
                    closed_at: '2026-07-05T14:05:10+00:00'
                    fulfillment_state: COMPLETED
                    sync_status: synced
                    sync_error: null
                    last_synced_at: '2026-07-06T18:24:11+00:00'
                    sales_order_id: 918
                    sales_order:
                      id: 918
                      sales_order_number: SO-000918
                      order_status: completed
                      fulfillment_status: fulfilled
                      payment_status: paid
                      link_route: /orders/sales-orders/918
                      fulfillments:
                      - id: 501
                        status: fulfilled
                        fulfillment_type: shipping
                        tracking_number: 1Z999AA10123456784
                        cost: 7.25
                        fulfilled_at: '2026-07-05T16:10:00.000000Z'
                        submitted_to_sales_channel_at: null
                        warehouse:
                          id: 3
                          name: Main Warehouse
                        shipping_method:
                          id: 2
                          name: UPS Ground
                        line_items:
                        - id: 1203
                          quantity: 2
                          product_name: Blue Ceramic Mug - Large
                          sku: MUG-BLU-L
                    line_items:
                    - id: 77
                      uid: 8CBRDDGRrM6cSf3HpiUmwB
                      sku: MUG-BLU-L
                      name: Blue Ceramic Mug
                      variation_name: Large
                      quantity: 2
                      base_price: 22.5
                      gross_sales: 45
                      total_tax: 3.94
                      total_discount: 0
                      total: 48.94
                      currency_code: USD
                      square_catalog_object_id: W62UWFY35CWMYGVWK6TWJDNI
                    raw_data:
                      id: CAISENgvlJ6jLWAzERDzjyHVybY
                      location_id: L2XXXXX7A
                      state: COMPLETED
                    created_at: '2026-07-05T14:06:00+00:00'
                    updated_at: '2026-07-06T18:24:11+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-square-orders-squareorder
  /api/square/orders/sync:
    post:
      tags:
      - Square
      summary: Sync orders
      description: 'Queues a background sync of Square orders for the instance, then
        promotes new orders to SKU sales orders. Returns a tracked job log id that
        can be used to follow progress.


        `mode` is optional: `since_latest` (default) resumes from the persisted sync
        watermark; `all` re-syncs from the instance''s order import start date. `date_from`
        (optional, date) overrides the window start.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                integration_instance_id:
                  type: integer
                mode:
                  type: string
                date_from:
                  type: string
              example:
                integration_instance_id: 1
                mode: since_latest
                date_from: '2026-07-01'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 3151
                  message: Square orders sync started.
        '422':
          description: Unprocessable Content
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      integration_instance_id:
                        type: array
                        items:
                          type: string
                example:
                  message: The integration instance id field is required.
                  errors:
                    integration_instance_id:
                    - The integration instance id field is required.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-square-orders-sync
  /api/square/orders/submit-fulfillments:
    post:
      tags:
      - Square
      summary: Submit fulfillments
      description: 'Push pending fulfillment tracking back to Square for online orders
        shipped in SKU. Each eligible fulfillment updates the Square order''s shipment
        fulfillment to COMPLETED with carrier, tracking number, tracking URL, and
        shipped-at time.


        `integration_instance_id` (integer, required) — the Square connection to submit
        for.

        `fulfillment_ids` (array of integers, optional) — submit only these fulfillments;
        omit to sweep every eligible pending fulfillment on the connection.


        Only fulfillments that are fulfilled, carry a tracking number, are not pickups,
        and have not already been submitted are pushed. Point-of-sale orders are never
        pushed — they are handed over at the register.


        Pending fulfillments are also submitted automatically every 10 minutes. Requires
        the ORDERS_WRITE OAuth scope.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                integration_instance_id:
                  type: integer
                fulfillment_ids:
                  type: array
                  items:
                    type: integer
              example:
                integration_instance_id: 1
                fulfillment_ids:
                - 12
                - 13
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  submitted:
                    type: integer
                  skipped:
                    type: integer
                  failed:
                    type: integer
                  errors:
                    type: array
                example:
                  message: 2 fulfillment(s) submitted to Square.
                  submitted: 2
                  skipped: 0
                  failed: 0
                  errors: []
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-square-orders-submit-fulfillments
  /api/webhooks/square:
    post:
      tags:
      - Square
      summary: Receive webhook
      description: '**Public endpoint** — no bearer required. Square posts here for
        every subscribed event.


        **Required header:** `X-Square-HmacSha256-Signature` (Square signs `notification_url
        + raw_body` with the subscription''s signature key; verified per-instance).


        **Handled event families:** `order.*` (refetches the order and promotes),
        `refund.*` (recorded in v1; sales-credit reconciliation lands in a follow-up),
        `inventory.*` / `catalog.*` (marked ignored — served by the scheduled sync
        commands).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                merchant_id:
                  type: string
                type:
                  type: string
                event_id:
                  type: string
                created_at:
                  type: string
                data:
                  type: object
                  properties:
                    type:
                      type: string
                    id:
                      type: string
                    object:
                      type: object
                      properties:
                        order_updated:
                          type: object
                          properties:
                            order_id:
                              type: string
                            state:
                              type: string
              example:
                merchant_id: MLXX0EXAMPLE
                type: order.updated
                event_id: 5e77f748-3aaf-4d05-8b16-1a3c9d3b3b41
                created_at: '2026-07-01T15:24:12Z'
                data:
                  type: order
                  id: ORDER123XYZ
                  object:
                    order_updated:
                      order_id: ORDER123XYZ
                      state: COMPLETED
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  event_id:
                    type: integer
                example:
                  message: accepted
                  event_id: 942
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-webhooks-square
  /api/square/payouts:
    get:
      tags:
      - Square
      summary: List payouts
      description: 'List Square payouts (deposit/settlement batches) — the money Square
        transferred to the seller''s bank account. Each payout aggregates the charges,
        refunds, and fees settled in that deposit; use it to reconcile channel revenue
        against bank deposits.


        Amounts are integer minor units (cents).


        Requires the PAYOUTS_READ OAuth scope on the connected Square account.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        square_payout_id:
                          type: string
                        square_location_id:
                          type: string
                        status:
                          type: string
                        type:
                          type: string
                        amount:
                          type: integer
                        currency_code:
                          type: string
                        arrival_date:
                          type: string
                        end_to_end_id:
                          type: string
                        square_created_at:
                          type: string
                        square_updated_at:
                          type: string
                        entries_synced_at:
                          type: string
                        entries_count:
                          type: integer
                        created_at:
                          type: string
                        updated_at:
                          type: string
                        integration_instance:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                  current_page:
                    type: integer
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 14
                    integration_instance_id: 3
                    square_payout_id: po_a1b2c3d4-5678-90ab-cdef-111213141516
                    square_location_id: L3PKY0ZZZ8Q1D
                    status: PAID
                    type: BATCH
                    amount: 45000
                    currency_code: USD
                    arrival_date: '2026-07-09'
                    end_to_end_id: T2X9AB34CD
                    square_created_at: '2026-07-08T04:10:00+00:00'
                    square_updated_at: '2026-07-08T09:30:00+00:00'
                    entries_synced_at: '2026-07-08T10:00:12+00:00'
                    entries_count: 38
                    created_at: '2026-07-08T10:00:11+00:00'
                    updated_at: '2026-07-08T10:00:12+00:00'
                    integration_instance:
                      id: 3
                      name: Main Street Coffee Co.
                  current_page: 1
                  first_page_url: https://sku1.test/api/square/payouts?page=1
                  from: 1
                  last_page: 1
                  last_page_url: https://sku1.test/api/square/payouts?page=1
                  links: []
                  next_page_url: null
                  path: https://sku1.test/api/square/payouts
                  per_page: 25
                  prev_page_url: null
                  to: 1
                  total: 1
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-square-payouts
  /api/square/payouts/{squarePayout}:
    get:
      tags:
      - Square
      summary: Get payout
      description: 'Get a single Square payout, including its entry count and the
        connected Square account.


        Amounts are integer minor units (cents).'
      parameters:
      - name: squarePayout
        in: path
        schema:
          type: string
        required: true
        description: The square payout ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      square_payout_id:
                        type: string
                      square_location_id:
                        type: string
                      status:
                        type: string
                      type:
                        type: string
                      amount:
                        type: integer
                      currency_code:
                        type: string
                      arrival_date:
                        type: string
                      end_to_end_id:
                        type: string
                      square_created_at:
                        type: string
                      square_updated_at:
                        type: string
                      entries_synced_at:
                        type: string
                      entries_count:
                        type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      integration_instance:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                example:
                  data:
                    id: 14
                    integration_instance_id: 3
                    square_payout_id: po_a1b2c3d4-5678-90ab-cdef-111213141516
                    square_location_id: L3PKY0ZZZ8Q1D
                    status: PAID
                    type: BATCH
                    amount: 45000
                    currency_code: USD
                    arrival_date: '2026-07-09'
                    end_to_end_id: T2X9AB34CD
                    square_created_at: '2026-07-08T04:10:00+00:00'
                    square_updated_at: '2026-07-08T09:30:00+00:00'
                    entries_synced_at: '2026-07-08T10:00:12+00:00'
                    entries_count: 38
                    created_at: '2026-07-08T10:00:11+00:00'
                    updated_at: '2026-07-08T10:00:12+00:00'
                    integration_instance:
                      id: 3
                      name: Main Street Coffee Co.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-square-payouts-squarepayout
  /api/square/payouts/{squarePayout}/entries:
    get:
      tags:
      - Square
      summary: List payout entries
      description: 'List the individual entries of one payout — each charge, refund,
        fee, or adjustment that was settled in the deposit, with gross/fee/net amounts
        and the Square payment it relates to.


        Amounts are integer minor units (cents).'
      parameters:
      - name: squarePayout
        in: path
        schema:
          type: string
        required: true
        description: The square payout ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        square_payout_id:
                          type: integer
                        square_payout_entry_id:
                          type: string
                        type:
                          type: string
                        effective_at:
                          type: string
                        gross_amount:
                          type: integer
                        fee_amount:
                          type: integer
                        net_amount:
                          type: integer
                        currency_code:
                          type: string
                        square_payment_id:
                          type: string
                        square_refund_id:
                          type: string
                          nullable: true
                  current_page:
                    type: integer
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 301
                    square_payout_id: 14
                    square_payout_entry_id: poe_9f8e7d6c-5432-10fe-dcba-212223242526
                    type: CHARGE
                    effective_at: '2026-07-08T03:22:41+00:00'
                    gross_amount: 2500
                    fee_amount: 73
                    net_amount: 2427
                    currency_code: USD
                    square_payment_id: pmt_1A2B3C4D5E6F
                    square_refund_id: null
                  current_page: 1
                  first_page_url: https://sku1.test/api/square/payouts?page=1
                  from: 1
                  last_page: 1
                  last_page_url: https://sku1.test/api/square/payouts?page=1
                  links: []
                  next_page_url: null
                  path: https://sku1.test/api/square/payouts
                  per_page: 25
                  prev_page_url: null
                  to: 1
                  total: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-square-payouts-squarepayout-entries
  /api/square/instances/{squareIntegrationInstance}/payouts/sync:
    post:
      tags:
      - Square
      summary: Sync payouts
      description: 'Start a background sync of payouts (and their entries) from Square
        for this connection. Payouts download per location from the last sync watermark;
        entries are refetched only when a payout changed. Returns a tracked job id
        for monitoring progress.


        Payouts also refresh automatically every hour.'
      requestBody:
        content: {}
      parameters:
      - name: squareIntegrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The square integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 981
                  message: Square payouts sync started.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-square-instances-squareintegrationinstance-payouts-sync
  /api/magento1/instances:
    get:
      tags:
      - Magento 1
      summary: List Integration Instances
      description: 'Lists every Magento 1 integration instance on the account. Returns
        all instances in a single response with no pagination, so callers can populate
        pickers or iterate instances without paging.


        Each instance includes its display name, connection status, the store base
        URL and API user. The SOAP API key is never returned — the `api_key_set` boolean
        indicates only whether one is stored. Each instance also reports the import
        start date, the inventory push rules, mirrored order and product counts, and
        the timestamps of the most recent order and product syncs (derived from the
        newest mirrored record, since Magento 1 has no sync cursor).


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        is_configured:
                          type: boolean
                        connection_status:
                          type: string
                        is_automatic_sync_enabled:
                          type: boolean
                        store_base_url:
                          type: string
                        api_user:
                          type: string
                        api_key_set:
                          type: boolean
                        start_date:
                          type: string
                        inventory:
                          type: object
                          properties:
                            masterOfStock:
                              type: string
                            inventoryModificationRules:
                              type: object
                              properties:
                                maxRuleType:
                                  type: string
                                minRuleType:
                                  type: string
                            selectedWarehouses:
                              type: array
                              items:
                                type: integer
                        last_orders_sync:
                          type: string
                        last_products_sync:
                          type: string
                        orders_count:
                          type: integer
                        products_count:
                          type: integer
                        created_at:
                          type: string
                        updated_at:
                          type: string
                        refunds:
                          type: object
                          properties:
                            allow_refunds_from_sku:
                              type: boolean
                example:
                  data:
                  - id: 3
                    name: Acme Storefront
                    is_configured: true
                    connection_status: Ready
                    is_automatic_sync_enabled: true
                    store_base_url: https://store.example.com
                    api_user: sku_integration
                    api_key_set: true
                    start_date: '2026-01-01'
                    inventory:
                      masterOfStock: sku.io
                      inventoryModificationRules:
                        maxRuleType: None
                        minRuleType: None
                      selectedWarehouses:
                      - 1
                      - 4
                    last_orders_sync: '2026-07-07T18:42:10+00:00'
                    last_products_sync: '2026-07-07T18:40:03+00:00'
                    orders_count: 128
                    products_count: 342
                    created_at: '2026-06-15T09:12:00+00:00'
                    updated_at: '2026-07-07T18:42:10+00:00'
                    refunds:
                      allow_refunds_from_sku: false
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-magento1-instances
    post:
      tags:
      - Magento 1
      summary: Create Integration Instance
      description: "Creates a Magento 1 integration instance from the supplied SOAP\
        \ credentials and settings, and creates the linked sales channel record in\
        \ the same request.\n\nRequest body fields:\n\n- `name` (string, required)\
        \ — display name for the connection.\n- `connection_settings` (object, required):\n\
        \  - `store_base_url` (string, required) — the store's base URL (any trailing\
        \ slash is stripped).\n  - `api_user` (string, required) — the SOAP API user\
        \ name.\n  - `api_key` (string, required) — the SOAP API key. Stored server-side\
        \ and never returned.\n- `start_date` (string, optional) — date (`YYYY-MM-DD`);\
        \ orders placed before it are not imported.\n- `inventory` (object, optional):\n\
        \  - `masterOfStock` (string) — `sku.io` or `Neither`.\n  - `inventoryModificationRules`\
        \ (object) — `maxRuleType`, `minRuleType` (strings) with optional `maxRuleTypeValue`,\
        \ `minRuleTypeValue`, `subtractBufferStock` (numbers).\n  - `selectedWarehouses`\
        \ (array of integers) — ids of warehouses whose stock feeds the store.\n\n\
        The response returns the created instance. Note that the API normalizes success\
        \ status codes to 200.\n\nAuthentication: Requires Bearer token."
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                connection_settings:
                  type: object
                  properties:
                    store_base_url:
                      type: string
                    api_user:
                      type: string
                    api_key:
                      type: string
                start_date:
                  type: string
                inventory:
                  type: object
                  properties:
                    masterOfStock:
                      type: string
                    inventoryModificationRules:
                      type: object
                      properties:
                        maxRuleType:
                          type: string
                        minRuleType:
                          type: string
                    selectedWarehouses:
                      type: array
                      items:
                        type: integer
              example:
                name: Acme Storefront
                connection_settings:
                  store_base_url: https://store.example.com
                  api_user: sku_integration
                  api_key: your-soap-api-key
                start_date: '2026-01-01'
                inventory:
                  masterOfStock: sku.io
                  inventoryModificationRules:
                    maxRuleType: None
                    minRuleType: None
                  selectedWarehouses:
                  - 1
                  - 4
      parameters: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      is_configured:
                        type: boolean
                      connection_status:
                        type: string
                      is_automatic_sync_enabled:
                        type: boolean
                      store_base_url:
                        type: string
                      api_user:
                        type: string
                      api_key_set:
                        type: boolean
                      start_date:
                        type: string
                      inventory:
                        type: object
                        properties:
                          masterOfStock:
                            type: string
                          inventoryModificationRules:
                            type: object
                            properties:
                              maxRuleType:
                                type: string
                              minRuleType:
                                type: string
                          selectedWarehouses:
                            type: array
                            items:
                              type: integer
                      last_orders_sync:
                        type: string
                      last_products_sync:
                        type: string
                      orders_count:
                        type: integer
                      products_count:
                        type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      refunds:
                        type: object
                        properties:
                          allow_refunds_from_sku:
                            type: boolean
                example:
                  data:
                    id: 3
                    name: Acme Storefront
                    is_configured: true
                    connection_status: Ready
                    is_automatic_sync_enabled: true
                    store_base_url: https://store.example.com
                    api_user: sku_integration
                    api_key_set: true
                    start_date: '2026-01-01'
                    inventory:
                      masterOfStock: sku.io
                      inventoryModificationRules:
                        maxRuleType: None
                        minRuleType: None
                      selectedWarehouses:
                      - 1
                      - 4
                    last_orders_sync: '2026-07-07T18:42:10+00:00'
                    last_products_sync: '2026-07-07T18:40:03+00:00'
                    orders_count: 128
                    products_count: 342
                    created_at: '2026-06-15T09:12:00+00:00'
                    updated_at: '2026-07-07T18:42:10+00:00'
                    refunds:
                      allow_refunds_from_sku: false
        '422':
          description: Unprocessable Entity
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      connection_settings.store_base_url:
                        type: array
                        items:
                          type: string
                      connection_settings.api_key:
                        type: array
                        items:
                          type: string
                example:
                  message: The connection settings.store base url field is required.
                  errors:
                    connection_settings.store_base_url:
                    - The connection settings.store base url field is required.
                    connection_settings.api_key:
                    - The connection settings.api key field is required.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-magento1-instances
  /api/magento1/instances/{integrationInstance}:
    get:
      tags:
      - Magento 1
      summary: Get Integration Instance
      description: 'Returns a single Magento 1 integration instance by id, including
        its connection status, settings, mirrored order and product counts, and last-sync
        timestamps. The SOAP API key is never returned — only `api_key_set` indicates
        whether one is stored.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      is_configured:
                        type: boolean
                      connection_status:
                        type: string
                      is_automatic_sync_enabled:
                        type: boolean
                      store_base_url:
                        type: string
                      api_user:
                        type: string
                      api_key_set:
                        type: boolean
                      start_date:
                        type: string
                      inventory:
                        type: object
                        properties:
                          masterOfStock:
                            type: string
                          inventoryModificationRules:
                            type: object
                            properties:
                              maxRuleType:
                                type: string
                              minRuleType:
                                type: string
                          selectedWarehouses:
                            type: array
                            items:
                              type: integer
                      last_orders_sync:
                        type: string
                      last_products_sync:
                        type: string
                      orders_count:
                        type: integer
                      products_count:
                        type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      refunds:
                        type: object
                        properties:
                          allow_refunds_from_sku:
                            type: boolean
                example:
                  data:
                    id: 3
                    name: Acme Storefront
                    is_configured: true
                    connection_status: Ready
                    is_automatic_sync_enabled: true
                    store_base_url: https://store.example.com
                    api_user: sku_integration
                    api_key_set: true
                    start_date: '2026-01-01'
                    inventory:
                      masterOfStock: sku.io
                      inventoryModificationRules:
                        maxRuleType: None
                        minRuleType: None
                      selectedWarehouses:
                      - 1
                      - 4
                    last_orders_sync: '2026-07-07T18:42:10+00:00'
                    last_products_sync: '2026-07-07T18:40:03+00:00'
                    orders_count: 128
                    products_count: 342
                    created_at: '2026-06-15T09:12:00+00:00'
                    updated_at: '2026-07-07T18:42:10+00:00'
                    refunds:
                      allow_refunds_from_sku: false
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-magento1-instances-integrationinstance
    put:
      tags:
      - Magento 1
      summary: Update Integration Instance
      description: 'Updates a Magento 1 integration instance. All fields are optional
        — only the keys you send are changed. Credentials are merged, so omitting
        `connection_settings.api_key` keeps the stored key intact rather than clearing
        it.


        Request body fields (all optional):


        - `name` (string), `is_automatic_sync_enabled` (boolean).

        - `connection_settings` (object) — any of `store_base_url`, `api_user`, `api_key`.

        - `start_date` (string, `YYYY-MM-DD`, nullable).

        - `inventory` (object) — same shape as on create.

        - `refunds` (object) — outbound refund settings: `allow_refunds_from_sku`
        (boolean, default `false`) enables issuing refunds to Magento 1 from SKU.
        Refunds are recorded as **offline credit memos** on the Magento order — no
        money moves on the channel; the customer must be refunded through the payment
        processor separately.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                is_automatic_sync_enabled:
                  type: boolean
                connection_settings:
                  type: object
                  properties:
                    store_base_url:
                      type: string
                    api_user:
                      type: string
                start_date:
                  type: string
                inventory:
                  type: object
                  properties:
                    masterOfStock:
                      type: string
                    inventoryModificationRules:
                      type: object
                      properties:
                        maxRuleType:
                          type: string
                        minRuleType:
                          type: string
                    selectedWarehouses:
                      type: array
                      items:
                        type: integer
                refunds:
                  type: object
                  properties:
                    allow_refunds_from_sku:
                      type: boolean
              example:
                name: Acme Storefront (US)
                is_automatic_sync_enabled: true
                connection_settings:
                  store_base_url: https://store.example.com
                  api_user: sku_integration
                start_date: '2026-01-01'
                inventory:
                  masterOfStock: sku.io
                  inventoryModificationRules:
                    maxRuleType: None
                    minRuleType: None
                  selectedWarehouses:
                  - 1
                  - 4
                refunds:
                  allow_refunds_from_sku: false
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      is_configured:
                        type: boolean
                      connection_status:
                        type: string
                      is_automatic_sync_enabled:
                        type: boolean
                      store_base_url:
                        type: string
                      api_user:
                        type: string
                      api_key_set:
                        type: boolean
                      start_date:
                        type: string
                      inventory:
                        type: object
                        properties:
                          masterOfStock:
                            type: string
                          inventoryModificationRules:
                            type: object
                            properties:
                              maxRuleType:
                                type: string
                              minRuleType:
                                type: string
                          selectedWarehouses:
                            type: array
                            items:
                              type: integer
                      last_orders_sync:
                        type: string
                      last_products_sync:
                        type: string
                      orders_count:
                        type: integer
                      products_count:
                        type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      refunds:
                        type: object
                        properties:
                          allow_refunds_from_sku:
                            type: boolean
                example:
                  data:
                    id: 3
                    name: Acme Storefront (US)
                    is_configured: true
                    connection_status: Ready
                    is_automatic_sync_enabled: true
                    store_base_url: https://store.example.com
                    api_user: sku_integration
                    api_key_set: true
                    start_date: '2026-01-01'
                    inventory:
                      masterOfStock: sku.io
                      inventoryModificationRules:
                        maxRuleType: None
                        minRuleType: None
                      selectedWarehouses:
                      - 1
                      - 4
                    last_orders_sync: '2026-07-07T18:42:10+00:00'
                    last_products_sync: '2026-07-07T18:40:03+00:00'
                    orders_count: 128
                    products_count: 342
                    created_at: '2026-06-15T09:12:00+00:00'
                    updated_at: '2026-07-07T18:42:10+00:00'
                    refunds:
                      allow_refunds_from_sku: false
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-magento1-instances-integrationinstance
    delete:
      tags:
      - Magento 1
      summary: Delete Integration Instance
      description: 'Deletes a Magento 1 integration instance and cleans up its linked
        sales channel, mirrored orders and products, and mapping records.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Integration deleted successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-magento1-instances-integrationinstance
  /api/magento1/instances/{integrationInstance}/activity-log:
    get:
      tags:
      - Magento 1
      summary: Get Activity Log
      description: Paginated change history for orders belonging to this integration
        instance. Each entry records a change event (created, updated, etc.), who
        made it, and a JSON `properties` payload holding the before/after attributes
        and the source of the change. Since Magento 1 is polled rather than pushing
        webhooks, this is the closest thing to a per-store event feed. Authenticate
        with a Personal Access Token (PAT) Bearer token.
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Magento 1 integration instance id
        example: '3'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        description:
                          type: string
                        event:
                          type: string
                        subject_type:
                          type: string
                        subject_id:
                          type: integer
                        properties:
                          type: object
                          properties:
                            source:
                              type: string
                            attributes:
                              type: object
                              properties:
                                status:
                                  type: string
                                state:
                                  type: string
                            old:
                              type: object
                              properties:
                                status:
                                  type: string
                                state:
                                  type: string
                        batch_uuid:
                          type: string
                        causer_name:
                          type: string
                        created_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - id: 884213
                    description: updated
                    event: updated
                    subject_type: Magento1Order
                    subject_id: 5120
                    properties:
                      source: sync
                      attributes:
                        status: complete
                        state: complete
                      old:
                        status: processing
                        state: processing
                    batch_uuid: 9b2d1f4a-3c7e-4a2b-8f6d-1e2a3b4c5d6e
                    causer_name: Sync Service
                    created_at: '2026-07-08T09:14:22.000000Z'
                  - id: 884198
                    description: created
                    event: created
                    subject_type: Magento1Order
                    subject_id: 5120
                    properties:
                      source: sync
                      attributes:
                        magento_increment_id: '100004521'
                        status: processing
                    batch_uuid: null
                    causer_name: null
                    created_at: '2026-07-08T08:51:03.000000Z'
                  current_page: 1
                  last_page: 12
                  per_page: 15
                  total: 174
                  from: 1
                  to: 15
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-magento1-instances-integrationinstance-activity-log
  /api/magento1/instances/{integrationInstance}/sync-orders:
    post:
      tags:
      - Magento 1
      summary: Sync Orders
      description: 'Starts a background pull of orders from the Magento 1 store into
        SKU.io. Returns a `tracked_job_log_id` you can poll for progress. Only one
        order sync runs per instance at a time — a second request while one is running
        is ignored.


        Body (all optional): `mode` — one of `since_latest` (resume from the last
        synced order; default), `from_start_date` (re-sweep from `dateFrom` up to
        now), or `date_range` (only orders within `[dateFrom, dateTo]`). `dateFrom`/`dateTo`
        — ISO-8601 dates, required for `from_start_date` (from) and `date_range` (both).
        `dateMethod` — `created` or `updated`, which order timestamp a `date_range`
        sweep filters on (default `updated`).


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                mode:
                  type: string
                dateFrom:
                  type: string
                dateTo:
                  type: string
                dateMethod:
                  type: string
              example:
                mode: date_range
                dateFrom: '2026-01-01'
                dateTo: '2026-02-01'
                dateMethod: updated
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 91427
                  message: Order sync started
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-magento1-instances-integrationinstance-sync-orders
  /api/magento1/instances/{integrationInstance}/sync-products:
    post:
      tags:
      - Magento 1
      summary: Sync Products
      description: 'Starts a background pull of products from the Magento 1 store
        into SKU.io. Returns a `tracked_job_log_id` you can poll for progress. Only
        one product sync runs per instance at a time.


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 91427
                  message: Product sync started
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-magento1-instances-integrationinstance-sync-products
  /api/magento1/instances/{integrationInstance}/sync-inventory:
    post:
      tags:
      - Magento 1
      summary: Sync Inventory
      description: 'Starts an inventory push from SKU.io to the Magento 1 store. The
        push fans out into batched jobs, so no `tracked_job_log_id` is returned —
        the response only confirms the push was queued. Inventory is pushed only from
        production environments and only for instances with inventory sync enabled;
        elsewhere the push is skipped.


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Inventory sync started
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-magento1-instances-integrationinstance-sync-inventory
  /api/magento1/orders:
    get:
      tags:
      - Magento 1
      summary: List Orders
      description: 'Lists Magento 1 orders for one integration instance (the local
        mirror of orders pulled from the store). Scope with the `instance_id` query
        param — without it an empty page is returned so another store''s orders never
        leak. Paginated (default 15/page).


        Allowed sorts: id, magento_created_at, magento_updated_at, grand_total, subtotal,
        status. Prefix with - for descending. Default: -magento_created_at.


        Advanced filters (Spatie QueryBuilder): filter[search] (matches id, increment_id,
        external_order_id, customer email/first/last name); filter[increment_id],
        filter[external_order_id], filter[status], filter[state], filter[order_currency_code],
        filter[shipping_method] (text: supports .is / .contains / .starts_with / .ends_with
        tree operators); filter[grand_total], filter[subtotal], filter[tax_amount],
        filter[shipping_amount], filter[discount_amount] (numeric comparisons); filter[magento_created_at],
        filter[magento_updated_at], filter[created_at], filter[updated_at] (datetime
        ranges); filter[has_sku_order]=true|false (whether a SKU sales order is linked);
        filter[has_unmapped_items]=true|false (whether any line''s Magento product
        is not linked to a SKU.io product); filter[archived]=only|all (default omitted
        = Active/non-archived only).


        Each line item includes the linked SKU.io product (via the Magento product
        → product listing mapping) when one exists.


        Authentication: Requires Bearer token.'
      parameters:
      - name: instance_id
        in: query
        schema:
          type: integer
        description: Integration instance id to scope orders to (required — without
          it an empty page is returned)
        example: '3'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        increment_id:
                          type: string
                        external_order_id:
                          type: string
                        status:
                          type: string
                        state:
                          type: string
                        customer_email:
                          type: string
                        customer_firstname:
                          type: string
                        customer_lastname:
                          type: string
                        order_currency_code:
                          type: string
                        grand_total:
                          type: string
                        subtotal:
                          type: string
                        tax_amount:
                          type: string
                        shipping_amount:
                          type: string
                        discount_amount:
                          type: string
                        shipping_method:
                          type: string
                        shipping_description:
                          type: string
                        magento_created_at:
                          type: string
                        magento_updated_at:
                          type: string
                        order_items:
                          type: array
                          items:
                            type: object
                            properties:
                              id:
                                type: integer
                              item_id:
                                type: integer
                              product_id:
                                type: integer
                              product_type:
                                type: string
                              sku:
                                type: string
                              name:
                                type: string
                              magento_product_id:
                                type: integer
                              magento_product_route:
                                type: string
                              qty_ordered:
                                type: integer
                              qty_shipped:
                                type: integer
                              qty_canceled:
                                type: integer
                              qty_refunded:
                                type: integer
                              qty_invoiced:
                                type: integer
                              price:
                                type: string
                              row_total:
                                type: string
                              tax_amount:
                                type: string
                              discount_amount:
                                type: string
                              sku_product_id:
                                type: integer
                              sku_product_route:
                                type: string
                              sku_product:
                                type: object
                                properties:
                                  id:
                                    type: integer
                                  sku:
                                    type: string
                                  name:
                                    type: string
                                  type:
                                    type: string
                        sales_order:
                          type: object
                          properties:
                            id:
                              type: integer
                            sales_order_number:
                              type: string
                            order_status:
                              type: string
                            fulfillment_status:
                              type: string
                            payment_status:
                              type: string
                        created_at:
                          type: string
                        archived_at:
                          type: string
                          nullable: true
                        is_archived:
                          type: boolean
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                  first_page_url:
                    type: string
                  last_page_url:
                    type: string
                  next_page_url:
                    type: string
                  prev_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  links:
                    type: array
                example:
                  data:
                  - id: 3391
                    integration_instance_id: 3
                    increment_id: '100004821'
                    external_order_id: '4821'
                    status: processing
                    state: processing
                    customer_email: jane.doe@example.com
                    customer_firstname: Jane
                    customer_lastname: Doe
                    order_currency_code: USD
                    grand_total: '54.1000'
                    subtotal: '49.9800'
                    tax_amount: '4.1200'
                    shipping_amount: '5.0000'
                    discount_amount: '0.0000'
                    shipping_method: flatrate_flatrate
                    shipping_description: Flat Rate - Fixed
                    magento_created_at: '2026-07-01T14:22:05+00:00'
                    magento_updated_at: '2026-07-02T09:10:44+00:00'
                    order_items:
                    - id: 55012
                      item_id: 88231
                      product_id: 4471
                      product_type: simple
                      sku: WIDGET-BLUE-M
                      name: Blue Widget - Medium
                      magento_product_id: 14471
                      magento_product_route: /integrations/magento1/products/14471
                      qty_ordered: 2
                      qty_shipped: 2
                      qty_canceled: 0
                      qty_refunded: 0
                      qty_invoiced: 2
                      price: '24.9900'
                      row_total: '49.9800'
                      tax_amount: '4.1200'
                      discount_amount: '0.0000'
                      sku_product_id: 8817
                      sku_product_route: /products/8817
                      sku_product:
                        id: 8817
                        sku: SKU-WIDGET-BLUE-M
                        name: Blue Widget (Medium)
                        type: standard
                    sales_order:
                      id: 120544
                      sales_order_number: SO-120544
                      order_status: processing
                      fulfillment_status: unfulfilled
                      payment_status: paid
                    created_at: '2026-07-01T14:25:11+00:00'
                    archived_at: null
                    is_archived: false
                  current_page: 1
                  last_page: 12
                  per_page: 15
                  total: 174
                  from: 1
                  to: 15
                  first_page_url: '{{protocol}}{{domain}}/api/magento1/orders?page=1'
                  last_page_url: '{{protocol}}{{domain}}/api/magento1/orders?page=12'
                  next_page_url: '{{protocol}}{{domain}}/api/magento1/orders?page=2'
                  prev_page_url: null
                  path: '{{protocol}}{{domain}}/api/magento1/orders'
                  links: []
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-magento1-orders
  /api/magento1/orders/filter-options:
    get:
      tags:
      - Magento 1
      summary: Get Order Filter Options
      description: 'Returns the distinct status, state, currency, and shipping-method
        values that actually appear in the orders for the given integration instance,
        so the list filters only offer options that return rows. Returns empty arrays
        when the instance cannot be resolved.


        Authentication: Requires Bearer token.'
      parameters:
      - name: instance_id
        in: query
        schema:
          type: integer
        description: Integration instance id to scope options to
        example: '3'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      statuses:
                        type: array
                        items:
                          type: string
                      states:
                        type: array
                        items:
                          type: string
                      currencies:
                        type: array
                        items:
                          type: string
                      shipping_methods:
                        type: array
                        items:
                          type: string
                example:
                  data:
                    statuses:
                    - canceled
                    - closed
                    - complete
                    - processing
                    states:
                    - canceled
                    - complete
                    - new
                    - processing
                    currencies:
                    - USD
                    shipping_methods:
                    - flatrate_flatrate
                    - freeshipping_freeshipping
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-magento1-orders-filter-options
  /api/magento1/orders/{order}:
    get:
      tags:
      - Magento 1
      summary: Get Order
      description: 'Returns a single Magento 1 order with its line items (each resolving
        the linked SKU.io product when mapped) and a summary of the linked SKU sales
        order.


        Authentication: Requires Bearer token.'
      parameters:
      - name: order
        in: path
        schema:
          type: string
        required: true
        description: The order ID.
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      increment_id:
                        type: string
                      external_order_id:
                        type: string
                      status:
                        type: string
                      state:
                        type: string
                      customer_email:
                        type: string
                      customer_firstname:
                        type: string
                      customer_lastname:
                        type: string
                      order_currency_code:
                        type: string
                      grand_total:
                        type: string
                      subtotal:
                        type: string
                      tax_amount:
                        type: string
                      shipping_amount:
                        type: string
                      discount_amount:
                        type: string
                      shipping_method:
                        type: string
                      shipping_description:
                        type: string
                      magento_created_at:
                        type: string
                      magento_updated_at:
                        type: string
                      order_items:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            item_id:
                              type: integer
                            product_id:
                              type: integer
                            product_type:
                              type: string
                            sku:
                              type: string
                            name:
                              type: string
                            magento_product_id:
                              type: integer
                            magento_product_route:
                              type: string
                            qty_ordered:
                              type: integer
                            qty_shipped:
                              type: integer
                            qty_canceled:
                              type: integer
                            qty_refunded:
                              type: integer
                            qty_invoiced:
                              type: integer
                            price:
                              type: string
                            row_total:
                              type: string
                            tax_amount:
                              type: string
                            discount_amount:
                              type: string
                            sku_product_id:
                              type: integer
                            sku_product_route:
                              type: string
                            sku_product:
                              type: object
                              properties:
                                id:
                                  type: integer
                                sku:
                                  type: string
                                name:
                                  type: string
                                type:
                                  type: string
                      sales_order:
                        type: object
                        properties:
                          id:
                            type: integer
                          sales_order_number:
                            type: string
                          order_status:
                            type: string
                          fulfillment_status:
                            type: string
                          payment_status:
                            type: string
                      created_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                      is_archived:
                        type: boolean
                example:
                  data:
                    id: 3391
                    integration_instance_id: 3
                    increment_id: '100004821'
                    external_order_id: '4821'
                    status: processing
                    state: processing
                    customer_email: jane.doe@example.com
                    customer_firstname: Jane
                    customer_lastname: Doe
                    order_currency_code: USD
                    grand_total: '54.1000'
                    subtotal: '49.9800'
                    tax_amount: '4.1200'
                    shipping_amount: '5.0000'
                    discount_amount: '0.0000'
                    shipping_method: flatrate_flatrate
                    shipping_description: Flat Rate - Fixed
                    magento_created_at: '2026-07-01T14:22:05+00:00'
                    magento_updated_at: '2026-07-02T09:10:44+00:00'
                    order_items:
                    - id: 55012
                      item_id: 88231
                      product_id: 4471
                      product_type: simple
                      sku: WIDGET-BLUE-M
                      name: Blue Widget - Medium
                      magento_product_id: 14471
                      magento_product_route: /integrations/magento1/products/14471
                      qty_ordered: 2
                      qty_shipped: 2
                      qty_canceled: 0
                      qty_refunded: 0
                      qty_invoiced: 2
                      price: '24.9900'
                      row_total: '49.9800'
                      tax_amount: '4.1200'
                      discount_amount: '0.0000'
                      sku_product_id: 8817
                      sku_product_route: /products/8817
                      sku_product:
                        id: 8817
                        sku: SKU-WIDGET-BLUE-M
                        name: Blue Widget (Medium)
                        type: standard
                    sales_order:
                      id: 120544
                      sales_order_number: SO-120544
                      order_status: processing
                      fulfillment_status: unfulfilled
                      payment_status: paid
                    created_at: '2026-07-01T14:25:11+00:00'
                    archived_at: null
                    is_archived: false
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-magento1-orders-order
  /api/magento1/orders/{order}/raw:
    get:
      tags:
      - Magento 1
      summary: Get Raw Order Data
      description: 'Fetches the full order payload live from the Magento 1 store (the
        deep `salesOrderInfo` SOAP response) for the ''View Raw Data'' panel. Magento
        1 order mirrors carry no stored raw blob, so this reads on demand from the
        store. Returns 422 if the store call fails.


        Authentication: Requires Bearer token.'
      parameters:
      - name: order
        in: path
        schema:
          type: string
        required: true
        description: The order ID.
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      increment_id:
                        type: string
                      order_id:
                        type: string
                      status:
                        type: string
                      state:
                        type: string
                      customer_email:
                        type: string
                      grand_total:
                        type: string
                      items:
                        type: array
                        items:
                          type: object
                          properties:
                            item_id:
                              type: string
                            sku:
                              type: string
                            name:
                              type: string
                            qty_ordered:
                              type: string
                            price:
                              type: string
                      shipping_address:
                        type: object
                        properties:
                          firstname:
                            type: string
                          lastname:
                            type: string
                          city:
                            type: string
                          region:
                            type: string
                          postcode:
                            type: string
                          country_id:
                            type: string
                      billing_address:
                        type: object
                        properties:
                          firstname:
                            type: string
                          lastname:
                            type: string
                          city:
                            type: string
                          region:
                            type: string
                          postcode:
                            type: string
                          country_id:
                            type: string
                example:
                  data:
                    increment_id: '100004821'
                    order_id: '4821'
                    status: processing
                    state: processing
                    customer_email: jane.doe@example.com
                    grand_total: '54.1000'
                    items:
                    - item_id: '88231'
                      sku: WIDGET-BLUE-M
                      name: Blue Widget - Medium
                      qty_ordered: '2.0000'
                      price: '24.9900'
                    shipping_address:
                      firstname: Jane
                      lastname: Doe
                      city: Austin
                      region: Texas
                      postcode: '78701'
                      country_id: US
                    billing_address:
                      firstname: Jane
                      lastname: Doe
                      city: Austin
                      region: Texas
                      postcode: '78701'
                      country_id: US
        '422':
          description: Unprocessable Entity
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 'Failed to fetch raw order data from Magento 1: SOAP fault:
                    Requested order not found.'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-magento1-orders-order-raw
  /api/magento1/orders/{order}/refetch:
    post:
      tags:
      - Magento 1
      summary: Refetch Order
      description: 'Re-pulls a single order from the Magento 1 store, re-persists
        the local mirror, and returns the refreshed order. Returns 422 if the store
        call fails.


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: order
        in: path
        schema:
          type: string
        required: true
        description: The order ID.
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      increment_id:
                        type: string
                      external_order_id:
                        type: string
                      status:
                        type: string
                      state:
                        type: string
                      customer_email:
                        type: string
                      customer_firstname:
                        type: string
                      customer_lastname:
                        type: string
                      order_currency_code:
                        type: string
                      grand_total:
                        type: string
                      subtotal:
                        type: string
                      tax_amount:
                        type: string
                      shipping_amount:
                        type: string
                      discount_amount:
                        type: string
                      shipping_method:
                        type: string
                      shipping_description:
                        type: string
                      magento_created_at:
                        type: string
                      magento_updated_at:
                        type: string
                      order_items:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            item_id:
                              type: integer
                            product_id:
                              type: integer
                            product_type:
                              type: string
                            sku:
                              type: string
                            name:
                              type: string
                            magento_product_id:
                              type: integer
                            magento_product_route:
                              type: string
                            qty_ordered:
                              type: integer
                            qty_shipped:
                              type: integer
                            qty_canceled:
                              type: integer
                            qty_refunded:
                              type: integer
                            qty_invoiced:
                              type: integer
                            price:
                              type: string
                            row_total:
                              type: string
                            tax_amount:
                              type: string
                            discount_amount:
                              type: string
                            sku_product_id:
                              type: integer
                            sku_product_route:
                              type: string
                            sku_product:
                              type: object
                              properties:
                                id:
                                  type: integer
                                sku:
                                  type: string
                                name:
                                  type: string
                                type:
                                  type: string
                      sales_order:
                        type: object
                        properties:
                          id:
                            type: integer
                          sales_order_number:
                            type: string
                          order_status:
                            type: string
                          fulfillment_status:
                            type: string
                          payment_status:
                            type: string
                      created_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                      is_archived:
                        type: boolean
                example:
                  message: Order refreshed from Magento 1
                  data:
                    id: 3391
                    integration_instance_id: 3
                    increment_id: '100004821'
                    external_order_id: '4821'
                    status: processing
                    state: processing
                    customer_email: jane.doe@example.com
                    customer_firstname: Jane
                    customer_lastname: Doe
                    order_currency_code: USD
                    grand_total: '54.1000'
                    subtotal: '49.9800'
                    tax_amount: '4.1200'
                    shipping_amount: '5.0000'
                    discount_amount: '0.0000'
                    shipping_method: flatrate_flatrate
                    shipping_description: Flat Rate - Fixed
                    magento_created_at: '2026-07-01T14:22:05+00:00'
                    magento_updated_at: '2026-07-02T09:10:44+00:00'
                    order_items:
                    - id: 55012
                      item_id: 88231
                      product_id: 4471
                      product_type: simple
                      sku: WIDGET-BLUE-M
                      name: Blue Widget - Medium
                      magento_product_id: 14471
                      magento_product_route: /integrations/magento1/products/14471
                      qty_ordered: 2
                      qty_shipped: 2
                      qty_canceled: 0
                      qty_refunded: 0
                      qty_invoiced: 2
                      price: '24.9900'
                      row_total: '49.9800'
                      tax_amount: '4.1200'
                      discount_amount: '0.0000'
                      sku_product_id: 8817
                      sku_product_route: /products/8817
                      sku_product:
                        id: 8817
                        sku: SKU-WIDGET-BLUE-M
                        name: Blue Widget (Medium)
                        type: standard
                    sales_order:
                      id: 120544
                      sales_order_number: SO-120544
                      order_status: processing
                      fulfillment_status: unfulfilled
                      payment_status: paid
                    created_at: '2026-07-01T14:25:11+00:00'
                    archived_at: null
                    is_archived: false
        '422':
          description: Unprocessable Entity
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Failed to fetch order from Magento 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-magento1-orders-order-refetch
  /api/magento1/orders/{order}/archive:
    post:
      tags:
      - Magento 1
      summary: Archive Order
      description: 'Archives a single Magento 1 order so it is excluded from the active
        list and never auto-creates a SKU sales order. Idempotent — returns `archived:
        false` if it was already archived.


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: order
        in: path
        schema:
          type: string
        required: true
        description: The order ID.
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  archived:
                    type: boolean
                example:
                  message: Order archived successfully
                  archived: true
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-magento1-orders-order-archive
  /api/magento1/orders/{order}/unarchive:
    post:
      tags:
      - Magento 1
      summary: Unarchive Order
      description: 'Restores a previously archived Magento 1 order to the active list.
        Idempotent — returns `unarchived: false` if it was already active.


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: order
        in: path
        schema:
          type: string
        required: true
        description: The order ID.
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  unarchived:
                    type: boolean
                example:
                  message: Order unarchived successfully
                  unarchived: true
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-magento1-orders-order-unarchive
  /api/magento1/instances/{integrationInstance}/orders/bulk-archive:
    post:
      tags:
      - Magento 1
      summary: Bulk Archive Orders
      description: 'Archives multiple Magento 1 orders on the instance. Already-archived
        orders are skipped and not counted.


        Body fields:

        - ids (array of integers, required): Magento 1 order ids to archive.


        Set `apply_to_all: true` (instead of `ids`) to archive EVERY non-archived
        order for the instance — the "All Filtered" bulk scope.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
                apply_to_all:
                  type: boolean
              example:
                ids:
                - 3391
                - 3392
                - 3393
                apply_to_all: false
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  archived_count:
                    type: integer
                example:
                  message: 3 orders archived successfully
                  archived_count: 3
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-magento1-instances-integrationinstance-orders-bulk-archive
  /api/magento1/instances/{integrationInstance}/orders/bulk-unarchive:
    post:
      tags:
      - Magento 1
      summary: Bulk Unarchive Orders
      description: 'Restores multiple archived Magento 1 orders on the instance to
        active. Already-active orders are skipped and not counted.


        Body fields:

        - ids (array of integers, required): Magento 1 order ids to unarchive.


        Set `apply_to_all: true` (instead of `ids`) to unarchive EVERY archived order
        for the instance — the "All Filtered" bulk scope.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
                apply_to_all:
                  type: boolean
              example:
                ids:
                - 3391
                - 3392
                - 3393
                apply_to_all: false
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  unarchived_count:
                    type: integer
                example:
                  message: 3 orders unarchived successfully
                  unarchived_count: 3
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-magento1-instances-integrationinstance-orders-bulk-unarchive
  /api/magento1/instances/{integrationInstance}/orders/latest-sync-info:
    get:
      tags:
      - Magento 1
      summary: Get Latest Sync Info
      description: 'Aggregated metrics for the orders refresh modal: the latest imported
        order, total order count, the created / pending / archived split, and the
        last-synced timestamp (derived from the freshest mirror write — Magento 1
        has no sync cursor).


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      latest_order_display_id:
                        type: string
                      latest_order_date:
                        type: string
                      total_orders:
                        type: integer
                      created_count:
                        type: integer
                      pending_count:
                        type: integer
                      archived_count:
                        type: integer
                      last_synced_at:
                        type: string
                example:
                  data:
                    latest_order_display_id: '100004821'
                    latest_order_date: '2026-07-01T14:22:05+00:00'
                    total_orders: 174
                    created_count: 150
                    pending_count: 20
                    archived_count: 4
                    last_synced_at: '2026-07-02T09:12:00+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-magento1-instances-integrationinstance-orders-latest-sync-info
  /api/magento1/instances/{integrationInstance}/orders/create-sku-orders:
    post:
      tags:
      - Magento 1
      summary: Create SKU Orders
      description: 'Creates SKU.io sales orders from selected Magento 1 orders, or
        from every unlinked, non-archived order on the instance when `create_all_orders`
        is true. Runs as a background job — returns a `tracked_job_log_id` to poll.
        Already-linked and archived orders are skipped.


        Body fields:

        - ids (array of integers, required unless create_all_orders is true): Magento
        1 order ids to create SKU orders for.

        - create_all_orders (boolean, optional, default false): when true, ignores
        ids and creates SKU orders for all unlinked, non-archived orders.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
                create_all_orders:
                  type: boolean
              example:
                ids:
                - 3391
                - 3392
                - 3393
                create_all_orders: false
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 OK
                  value:
                    message: SKU order creation started for 3 orders
                    tracked_job_log_id: 91555
                    total_orders: 3
                example-1:
                  summary: 200 No Orders
                  value:
                    message: No orders to create
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-magento1-instances-integrationinstance-orders-create-sku-orders
  /api/magento1/instances/{integrationInstance}/orders/{order}/update-sku-order:
    post:
      tags:
      - Magento 1
      summary: Update SKU Order
      description: 'Refetches a single Magento 1 order and re-syncs the status fields
        on its linked SKU.io sales order. Returns 403 if the order does not belong
        to the instance, 404 if no SKU order is linked, 422 if the update failed.


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: order
        in: path
        schema:
          type: string
        required: true
        description: The order ID.
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  refetched:
                    type: boolean
                example:
                  message: SKU order updated successfully
                  refetched: true
        '403':
          description: Forbidden
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: Order does not belong to this integration instance
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: No SKU order linked to this Magento 1 order
        '422':
          description: Unprocessable Entity
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: Failed to update SKU order
        '429': *id001
        '401': *id002
      operationId: post-api-magento1-instances-integrationinstance-orders-order-update-sku-order
  /api/magento1/instances/{integrationInstance}/orders/bulk-update-sku-orders:
    post:
      tags:
      - Magento 1
      summary: Bulk Update SKU Orders
      description: 'Refetches the given Magento 1 orders and re-syncs the status fields
        (order/fulfillment/payment status) on their linked SKU.io sales orders. A
        single order is processed synchronously; multiple orders run as a background
        job with a `tracked_job_log_id`.


        Body fields:

        - ids (array of integers, required): Magento 1 order ids whose linked SKU
        orders to update.


        Set `apply_to_all: true` (instead of `ids`) to update EVERY order that has
        a linked SKU sales order — the "All Filtered" bulk scope.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
                apply_to_all:
                  type: boolean
              example:
                ids:
                - 3391
                - 3392
                - 3393
                apply_to_all: false
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 Job Started
                  value:
                    message: Bulk update job started
                    tracked_job_log_id: 91561
                    total_orders: 3
                example-1:
                  summary: 200 Single Updated
                  value:
                    message: 1 SKU order updated successfully
                    tracked_job_log_id: null
                example-2:
                  summary: 200 None Found
                  value:
                    message: No orders found with linked SKU orders to update
                    tracked_job_log_id: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-magento1-instances-integrationinstance-orders-bulk-update-sku-orders
  /api/magento1/instances/{integrationInstance}/orders/bulk-delete:
    post:
      tags:
      - Magento 1
      summary: Delete Orders
      description: 'Permanently delete Magento 1 orders from SKU.io (the mirror records),
        cascading to any linked SKU sales order + order items. This does NOT delete
        anything in the Magento 1 store. Distinct from Delete SKU Orders, which only
        unlinks.


        Body: `ids` (integer array) OR `apply_to_all: true` to delete EVERY order
        for the instance (the "All Filtered" scope). Deletes >1 order via a tracked
        background job (returns `tracked_job_log_id`); a single order deletes synchronously.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
                apply_to_all:
                  type: boolean
              example:
                ids:
                - 3391
                - 3392
                - 3393
                apply_to_all: false
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Magento 1 integration instance id
        example: '3'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  tracked_job_log_id:
                    type: integer
                  total_orders:
                    type: integer
                example:
                  message: Bulk delete job started
                  tracked_job_log_id: 7
                  total_orders: 3
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-magento1-instances-integrationinstance-orders-bulk-delete
  /api/magento1/instances/{integrationInstance}/orders/{order}/sku-order:
    delete:
      tags:
      - Magento 1
      summary: Delete SKU Order
      description: 'Deletes the SKU.io sales order linked to a single Magento 1 order
        (the Magento 1 order is kept). Optionally archives the Magento 1 order afterwards
        via the `archive_magento1_order` query flag. Returns 403 if the order does
        not belong to the instance, 404 if no SKU order is linked.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: order
        in: path
        schema:
          type: string
        required: true
        description: The order ID.
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  archived_magento1_order:
                    type: boolean
                example:
                  message: SKU order deleted successfully
                  archived_magento1_order: false
        '403':
          description: Forbidden
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: Order does not belong to this integration instance
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: No SKU order linked to this Magento 1 order
        '429': *id001
        '401': *id002
      operationId: delete-api-magento1-instances-integrationinstance-orders-order-sku-order
  /api/magento1/instances/{integrationInstance}/orders/bulk-delete-sku-orders:
    post:
      tags:
      - Magento 1
      summary: Bulk Delete SKU Orders
      description: 'Deletes the SKU.io sales orders linked to the given Magento 1
        orders (the Magento 1 orders themselves are kept). A single order is deleted
        synchronously; multiple orders run as a background job with a `tracked_job_log_id`.
        Optionally archives the Magento 1 orders afterwards so they are not re-created
        on the next sync.


        Body fields:

        - ids (array of integers, required): Magento 1 order ids whose linked SKU
        orders to delete.

        - archive_magento1_orders (boolean, optional, default false): archive the
        Magento 1 orders after deleting.


        Set `apply_to_all: true` (instead of `ids`) to delete the linked SKU sales
        order for EVERY order that has one — the "All Filtered" bulk scope.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
                apply_to_all:
                  type: boolean
                archive_magento1_orders:
                  type: boolean
              example:
                ids:
                - 3391
                - 3392
                - 3393
                apply_to_all: false
                archive_magento1_orders: false
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 Job Started
                  value:
                    message: Bulk delete job started
                    tracked_job_log_id: 91560
                    total_orders: 3
                example-1:
                  summary: 200 Single Deleted
                  value:
                    message: 1 SKU order deleted successfully
                    tracked_job_log_id: null
                example-2:
                  summary: 200 None Found
                  value:
                    message: No orders found to delete
                    tracked_job_log_id: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-magento1-instances-integrationinstance-orders-bulk-delete-sku-orders
  /api/magento1/orders/{order}/submit-tracking:
    post:
      tags:
      - Magento 1
      summary: Submit Tracking
      description: 'Queues a shipment (with tracking) back to the Magento 1 store
        for this order, using the most recent fulfilled shipment that carries a tracking
        number on the linked SKU sales order. Magento 1 is merchant-fulfilled, so
        tracking always applies. Returns 422 if no SKU order is linked or no fulfilled
        shipment with a tracking number exists.


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: order
        in: path
        schema:
          type: string
        required: true
        description: The order ID.
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Magento 1 tracking submission queued.
        '422':
          description: Unprocessable Entity
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 422 No Linked Order
                  value:
                    message: No SKU sales order linked to this Magento 1 order.
                example-1:
                  summary: 422 No Shipment
                  value:
                    message: No fulfilled shipment with a tracking number was found
                      for this order.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-magento1-orders-order-submit-tracking
  /api/magento1/instances/{integrationInstance}/orders/search:
    post:
      tags:
      - Magento 1
      summary: Search Orders
      description: 'Live-search the connected Magento 1 store for orders by increment
        id or customer email. Returns shallow matches, each flagged with whether it
        already exists in SKU.io.


        Body: `search_by` — `increment_id` or `email`. `query` — the search term (string,
        max 255).


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                search_by:
                  type: string
                query:
                  type: string
              example:
                search_by: increment_id
                query: '100000017'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Magento 1 integration instance id
        example: '3'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        increment_id:
                          type: string
                        status:
                          type: string
                        customer_email:
                          type: string
                        customer_firstname:
                          type: string
                        customer_lastname:
                          type: string
                        created_at:
                          type: string
                        grand_total:
                          type: string
                        order_currency_code:
                          type: string
                        exists_in_database:
                          type: boolean
                        database_id:
                          type: integer
                example:
                  data:
                  - increment_id: '100000017'
                    status: complete
                    customer_email: jane@example.com
                    customer_firstname: Jane
                    customer_lastname: Doe
                    created_at: '2026-07-07 13:55:58'
                    grand_total: '129.9900'
                    order_currency_code: USD
                    exists_in_database: true
                    database_id: 42
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-magento1-instances-integrationinstance-orders-search
  /api/magento1/instances/{integrationInstance}/orders/fetch-single:
    post:
      tags:
      - Magento 1
      summary: Download Single Order
      description: 'Fetch a single order from the Magento 1 store by its increment
        id and persist it into SKU.io. Use this to import a specific order surfaced
        by Search Orders.


        Body: `increment_id` — the Magento order increment id (string, required).


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                increment_id:
                  type: string
              example:
                increment_id: '100000017'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Magento 1 integration instance id
        example: '3'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      increment_id:
                        type: string
                      status:
                        type: string
                      state:
                        type: string
                      customer_email:
                        type: string
                      customer_firstname:
                        type: string
                      customer_lastname:
                        type: string
                      grand_total:
                        type: string
                      order_currency_code:
                        type: string
                      magento_created_at:
                        type: string
                      magento_updated_at:
                        type: string
                      sales_order:
                        type: object
                        properties:
                          id:
                            type: integer
                          sales_order_number:
                            type: string
                      order_items:
                        type: array
                        items:
                          type: object
                          properties:
                            sku:
                              type: string
                            name:
                              type: string
                            qty_ordered:
                              type: string
                            price:
                              type: string
                example:
                  message: Order fetched from Magento 1
                  data:
                    id: 42
                    integration_instance_id: 3
                    increment_id: '100000017'
                    status: complete
                    state: complete
                    customer_email: jane@example.com
                    customer_firstname: Jane
                    customer_lastname: Doe
                    grand_total: '129.9900'
                    order_currency_code: USD
                    magento_created_at: '2026-07-07T13:55:58+00:00'
                    magento_updated_at: '2026-07-07T13:55:58+00:00'
                    sales_order:
                      id: 8891
                      sales_order_number: SO-100482
                    order_items:
                    - sku: ACME-HOODIE-M-BLU
                      name: Acme Hoodie - Medium - Blue
                      qty_ordered: '1.0000'
                      price: '129.9900'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-magento1-instances-integrationinstance-orders-fetch-single
  /api/magento1/products:
    get:
      tags:
      - Magento 1
      summary: List Products (Cross-Instance)
      description: 'Lists Magento 1 catalog products (the local mirror pulled from
        the store) for ONE integration instance. Scope with the `instance_id` query
        param — it is REQUIRED here; without it an empty page is returned so another
        store''s catalog never leaks (the controller refuses to fall back to `::first()`).
        Paginated (default 10/page on this cross-instance route).


        Allowed sorts: id, product_id, sku, name, price, qty, status, magento_created_at,
        magento_updated_at. Prefix with - for descending. Default: -magento_updated_at.


        Search (filter[search]) matches id, product_id, sku, name. Advanced filters
        (Spatie QueryBuilder): filter[sku], filter[name], filter[type_id], filter[status],
        filter[visibility] (text, tree operators); filter[product_id], filter[price],
        filter[weight], filter[qty] (numeric); filter[is_in_stock], filter[has_mapping]
        (boolean, .is); filter[magento_created_at], filter[magento_updated_at], filter[created_at],
        filter[updated_at] (datetime ranges); filter[archived]=only|all.


        Authentication: Requires Bearer token.'
      parameters:
      - name: instance_id
        in: query
        schema:
          type: integer
        description: Integration instance id to scope products to. On the cross-instance
          index this is REQUIRED — without it an empty page is returned so another
          store's catalog never leaks (no ::first() fallback).
        example: '3'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        product_id:
                          type: integer
                        sku:
                          type: string
                        name:
                          type: string
                        type_id:
                          type: string
                        status:
                          type: string
                        visibility:
                          type: string
                        price:
                          type: string
                        weight:
                          type: string
                        short_description:
                          type: string
                        description:
                          type: string
                        qty:
                          type: string
                        is_in_stock:
                          type: boolean
                        image_url:
                          type: string
                        store_id:
                          type: integer
                        magento_created_at:
                          type: string
                        magento_updated_at:
                          type: string
                        is_mapped:
                          type: boolean
                        product_listing:
                          type: object
                          properties:
                            id:
                              type: integer
                            listing_sku:
                              type: string
                            product:
                              type: object
                              properties:
                                id:
                                  type: integer
                                sku:
                                  type: string
                                name:
                                  type: string
                                type:
                                  type: string
                        created_at:
                          type: string
                        archived_at:
                          type: string
                          nullable: true
                        is_archived:
                          type: boolean
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                  first_page_url:
                    type: string
                  last_page_url:
                    type: string
                  next_page_url:
                    type: string
                  prev_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  links:
                    type: array
                example:
                  data:
                  - id: 512
                    integration_instance_id: 3
                    product_id: 8842
                    sku: ACME-HOODIE-M-BLU
                    name: Acme Hoodie - Medium - Blue
                    type_id: simple
                    status: '1'
                    visibility: '4'
                    price: '49.9900'
                    weight: '0.8000'
                    short_description: Soft cotton hoodie
                    description: A soft, midweight cotton hoodie.
                    qty: '124.0000'
                    is_in_stock: true
                    image_url: https://store.example.com/media/catalog/product/a/c/acme-hoodie.jpg
                    store_id: 1
                    magento_created_at: '2026-01-04T09:12:00+00:00'
                    magento_updated_at: '2026-07-02T14:33:00+00:00'
                    is_mapped: true
                    product_listing:
                      id: 9001
                      listing_sku: ACME-HOODIE-M-BLU
                      product:
                        id: 30412
                        sku: ACME-HOODIE-M-BLU
                        name: Acme Hoodie (Medium, Blue)
                        type: simple
                    created_at: '2026-01-04T09:15:00+00:00'
                    archived_at: null
                    is_archived: false
                  current_page: 1
                  last_page: 9
                  per_page: 15
                  total: 128
                  from: 1
                  to: 15
                  first_page_url: '...'
                  last_page_url: '...'
                  next_page_url: '...'
                  prev_page_url: null
                  path: '...'
                  links: []
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-magento1-products
  /api/magento1/instances/{integrationInstance}/products:
    get:
      tags:
      - Magento 1
      summary: List Products by Instance
      description: 'Lists Magento 1 catalog products for the instance given in the
        path (the instance-scoped variant of the cross-instance index — same pagination,
        sorting, search, and filters, but the instance comes from the URL rather than
        `instance_id`).


        Allowed sorts: id, product_id, sku, name, price, qty, status, magento_created_at,
        magento_updated_at (default -magento_updated_at). Same advanced filters as
        the cross-instance index. Paginated (default 15/page).


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Magento 1 integration instance id
        example: '3'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        product_id:
                          type: integer
                        sku:
                          type: string
                        name:
                          type: string
                        type_id:
                          type: string
                        status:
                          type: string
                        visibility:
                          type: string
                        price:
                          type: string
                        weight:
                          type: string
                        short_description:
                          type: string
                        description:
                          type: string
                        qty:
                          type: string
                        is_in_stock:
                          type: boolean
                        image_url:
                          type: string
                        store_id:
                          type: integer
                        magento_created_at:
                          type: string
                        magento_updated_at:
                          type: string
                        is_mapped:
                          type: boolean
                        product_listing:
                          type: object
                          properties:
                            id:
                              type: integer
                            listing_sku:
                              type: string
                            product:
                              type: object
                              properties:
                                id:
                                  type: integer
                                sku:
                                  type: string
                                name:
                                  type: string
                                type:
                                  type: string
                        created_at:
                          type: string
                        archived_at:
                          type: string
                          nullable: true
                        is_archived:
                          type: boolean
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                  first_page_url:
                    type: string
                  last_page_url:
                    type: string
                  next_page_url:
                    type: string
                  prev_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  links:
                    type: array
                example:
                  data:
                  - id: 512
                    integration_instance_id: 3
                    product_id: 8842
                    sku: ACME-HOODIE-M-BLU
                    name: Acme Hoodie - Medium - Blue
                    type_id: simple
                    status: '1'
                    visibility: '4'
                    price: '49.9900'
                    weight: '0.8000'
                    short_description: Soft cotton hoodie
                    description: A soft, midweight cotton hoodie.
                    qty: '124.0000'
                    is_in_stock: true
                    image_url: https://store.example.com/media/catalog/product/a/c/acme-hoodie.jpg
                    store_id: 1
                    magento_created_at: '2026-01-04T09:12:00+00:00'
                    magento_updated_at: '2026-07-02T14:33:00+00:00'
                    is_mapped: true
                    product_listing:
                      id: 9001
                      listing_sku: ACME-HOODIE-M-BLU
                      product:
                        id: 30412
                        sku: ACME-HOODIE-M-BLU
                        name: Acme Hoodie (Medium, Blue)
                        type: simple
                    created_at: '2026-01-04T09:15:00+00:00'
                    archived_at: null
                    is_archived: false
                  current_page: 1
                  last_page: 9
                  per_page: 15
                  total: 128
                  from: 1
                  to: 15
                  first_page_url: '...'
                  last_page_url: '...'
                  next_page_url: '...'
                  prev_page_url: null
                  path: '...'
                  links: []
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-magento1-instances-integrationinstance-products
  /api/magento1/instances/{integrationInstance}/products/filter-options:
    get:
      tags:
      - Magento 1
      summary: Get Product Filter Options
      description: 'Distinct filter option values for the products listing filter
        chips — the set of product types, statuses, and visibilities present in this
        instance''s mirrored catalog.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Magento 1 integration instance id
        example: '3'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      types:
                        type: array
                        items:
                          type: string
                      statuses:
                        type: array
                        items:
                          type: string
                      visibilities:
                        type: array
                        items:
                          type: string
                example:
                  data:
                    types:
                    - simple
                    - configurable
                    - bundle
                    statuses:
                    - '1'
                    - '2'
                    visibilities:
                    - '1'
                    - '2'
                    - '3'
                    - '4'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-magento1-instances-integrationinstance-products-filter-options
  /api/magento1/instances/{integrationInstance}/products/latest-sync-info:
    get:
      tags:
      - Magento 1
      summary: Get Latest Product Sync Info
      description: 'Product sync summary powering the "Latest Synced Product" header
        card on the Refresh-from-Magento-1 modal: total/mapped/unmapped/archived counts
        plus the last-synced timestamp.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Magento 1 integration instance id
        example: '3'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      total:
                        type: integer
                      mapped:
                        type: integer
                      unmapped:
                        type: integer
                      archived:
                        type: integer
                      last_synced_at:
                        type: string
                example:
                  data:
                    total: 128
                    mapped: 91
                    unmapped: 37
                    archived: 4
                    last_synced_at: '2026-07-08T06:20:00+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-magento1-instances-integrationinstance-products-latest-sync-info
  /api/magento1/instances/{integrationInstance}/products/refresh-tracked:
    post:
      tags:
      - Magento 1
      summary: Refresh Products (Tracked)
      description: 'Starts a background product refresh from the Magento 1 store into
        SKU.io. Returns a `tracked_job_log_id` you can poll for progress.


        Body (optional): `mode` — either `since_latest` (resume from the last synced
        product; default) or `full_catalog` (re-import the entire catalog). Magento
        1''s catalog API has no date query, so date-range refresh is not supported
        for products.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                mode:
                  type: string
              example:
                mode: since_latest
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Magento 1 integration instance id
        example: '3'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 48213
                  message: Product refresh job has been queued
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-magento1-instances-integrationinstance-products-refresh-tracked
  /api/magento1/instances/{integrationInstance}/products/bulk:
    post:
      tags:
      - Magento 1
      summary: Bulk Product Operation (Sync)
      description: "Runs a bulk operation on catalog products synchronously — best\
        \ for small \"Selected Only\" requests. For large \"All Filtered\" sets that\
        \ may exceed the HTTP timeout, use Bulk Product Operation (Tracked) instead.\n\
        \nBody fields:\n- action (string, required): one of archive, unarchive, delete,\
        \ map, unmap, create, remap. `map`/`remap` link by the product's own SKU;\
        \ `archive` skips products that already carry channel orders.\n- selection\
        \ (object, required):\n  - selection.type (required): selected | visible |\
        \ filtered.\n  - selection.ids (`array<int>`, required when type=selected):\
        \ magento1_products.id PKs.\n  - selection.filters (object, optional): the\
        \ same filter[...] tree as the listing, used when type=filtered/visible to\
        \ resolve the id set server-side.\n- options (object, optional): action-specific\
        \ options.\n\nReturns per-action counts. 422 if the selection resolves to\
        \ zero products.\n\nAuthentication: Requires Bearer token."
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                action:
                  type: string
                selection:
                  type: object
                  properties:
                    type:
                      type: string
                    ids:
                      type: array
                      items:
                        type: integer
                options:
                  type: object
                  properties: {}
              example:
                action: map
                selection:
                  type: selected
                  ids:
                  - 512
                  - 513
                  - 514
                options: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Magento 1 integration instance id
        example: '3'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      processed:
                        type: integer
                      failed:
                        type: integer
                      skipped:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    processed: 3
                    failed: 0
                    skipped: 0
                  message: 'Bulk map completed. Processed: 3, Failed: 0, Skipped:
                    0'
        '422':
          description: Unprocessable Entity
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: No products found for the given selection.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-magento1-instances-integrationinstance-products-bulk
  /api/magento1/instances/{integrationInstance}/products/bulk-tracked:
    post:
      tags:
      - Magento 1
      summary: Bulk Product Operation (Tracked)
      description: 'Starts a tracked bulk operation on catalog products — best for
        "All Filtered" requests that may exceed the HTTP timeout. Returns a `tracked_job_log_id`
        to poll for progress. Same body contract as the synchronous Bulk endpoint.


        Body fields:

        - action (string, required): archive | unarchive | delete | map | unmap |
        create | remap.

        - selection (object, required): { type: selected|visible|filtered, ids: [int]
        (required when selected), filters: {…} }.

        - options (object, optional).


        422 if the selection resolves to zero products.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                action:
                  type: string
                selection:
                  type: object
                  properties:
                    type:
                      type: string
                    filters:
                      type: object
                      properties:
                        filter:
                          type: object
                          properties:
                            has_mapping:
                              type: string
                options:
                  type: object
                  properties: {}
              example:
                action: archive
                selection:
                  type: filtered
                  filters:
                    filter:
                      has_mapping: 'false'
                options: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Magento 1 integration instance id
        example: '3'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 48219
                  message: Bulk operation job has been queued
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-magento1-instances-integrationinstance-products-bulk-tracked
  /api/magento1/instances/{integrationInstance}/products/bulk-progress/{trackedJobLogId}:
    get:
      tags:
      - Magento 1
      summary: Get Bulk Operation Progress
      description: 'Progress for a tracked bulk product operation job — the tracked
        job log (status, processed/total, errors).


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Magento 1 integration instance id
        example: '3'
      - name: trackedJobLogId
        in: path
        schema:
          type: integer
        required: true
        description: Tracked job log id returned by Bulk Product Operation (Tracked)
        example: '48219'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      status:
                        type: string
                      total:
                        type: integer
                      processed:
                        type: integer
                      failed:
                        type: integer
                      created_at:
                        type: string
                example:
                  data:
                    id: 48219
                    name: Bulk Magento 1 Product Operation
                    status: COMPLETED
                    total: 37
                    processed: 37
                    failed: 0
                    created_at: '2026-07-08T06:40:00+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-magento1-instances-integrationinstance-products-bulk-progress-trackedjoblogid
  /api/magento1/instances/{integrationInstance}/products/{product}/smart-match:
    post:
      tags:
      - Magento 1
      summary: Smart-Match Product
      description: 'Returns smart-match candidates for a catalog product: the best
        exact-SKU match plus fuzzy name/SKU candidates. Powers the per-row mapping
        modal.


        Body: none.


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Magento 1 integration instance id
        example: '3'
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: Magento 1 product mirror id (magento1_products.id PK)
        example: '512'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      exact_match:
                        type: object
                        properties:
                          id:
                            type: integer
                          sku:
                            type: string
                          name:
                            type: string
                          barcode:
                            type: string
                          type:
                            type: string
                          price:
                            type: string
                          match_type:
                            type: string
                      similar_matches:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            sku:
                              type: string
                            name:
                              type: string
                            barcode:
                              type: string
                            type:
                              type: string
                            price:
                              type: string
                            match_type:
                              type: string
                example:
                  data:
                    exact_match:
                      id: 30412
                      sku: ACME-HOODIE-M-BLU
                      name: Acme Hoodie (Medium, Blue)
                      barcode: 0819431027
                      type: simple
                      price: '49.99'
                      match_type: sku
                    similar_matches:
                    - id: 30418
                      sku: ACME-HOODIE-L-BLU
                      name: Acme Hoodie (Large, Blue)
                      barcode: 0819431034
                      type: simple
                      price: '49.99'
                      match_type: fuzzy
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-magento1-instances-integrationinstance-products-product-smart-match
  /api/magento1/instances/{integrationInstance}/products/{product}/create-sku-product:
    post:
      tags:
      - Magento 1
      summary: Create SKU Product from Magento Product
      description: 'Creates a new SKU.io product from the catalog product''s data
        and links it. If a SKU.io product with the matching SKU already exists, the
        manager links to it instead of creating a duplicate. Returns 422 if the catalog
        product is already mapped (unmap it first).


        Body: none.


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Magento 1 integration instance id
        example: '3'
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: Magento 1 product mirror id (magento1_products.id PK)
        example: '512'
      responses:
        '201':
          description: Created
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      product_id:
                        type: integer
                      sku:
                        type: string
                      name:
                        type: string
                      type_id:
                        type: string
                      status:
                        type: string
                      visibility:
                        type: string
                      price:
                        type: string
                      weight:
                        type: string
                      short_description:
                        type: string
                      description:
                        type: string
                      qty:
                        type: string
                      is_in_stock:
                        type: boolean
                      image_url:
                        type: string
                      store_id:
                        type: integer
                      magento_created_at:
                        type: string
                      magento_updated_at:
                        type: string
                      is_mapped:
                        type: boolean
                      product_listing:
                        type: object
                        properties:
                          id:
                            type: integer
                          listing_sku:
                            type: string
                          product:
                            type: object
                            properties:
                              id:
                                type: integer
                              sku:
                                type: string
                              name:
                                type: string
                              type:
                                type: string
                      created_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                      is_archived:
                        type: boolean
                  message:
                    type: string
                example:
                  data:
                    id: 512
                    integration_instance_id: 3
                    product_id: 8842
                    sku: ACME-HOODIE-M-BLU
                    name: Acme Hoodie - Medium - Blue
                    type_id: simple
                    status: '1'
                    visibility: '4'
                    price: '49.9900'
                    weight: '0.8000'
                    short_description: Soft cotton hoodie
                    description: A soft, midweight cotton hoodie.
                    qty: '124.0000'
                    is_in_stock: true
                    image_url: https://store.example.com/media/catalog/product/a/c/acme-hoodie.jpg
                    store_id: 1
                    magento_created_at: '2026-01-04T09:12:00+00:00'
                    magento_updated_at: '2026-07-02T14:33:00+00:00'
                    is_mapped: true
                    product_listing:
                      id: 9001
                      listing_sku: ACME-HOODIE-M-BLU
                      product:
                        id: 30412
                        sku: ACME-HOODIE-M-BLU
                        name: Acme Hoodie (Medium, Blue)
                        type: simple
                    created_at: '2026-01-04T09:15:00+00:00'
                    archived_at: null
                    is_archived: false
                  message: SKU.io product created and mapped.
        '422':
          description: Unprocessable Entity
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: Product is already mapped. Unmap it first.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-magento1-instances-integrationinstance-products-product-create-sku-product
  /api/magento1/instances/{integrationInstance}/products/{product}/map:
    post:
      tags:
      - Magento 1
      summary: Map Product
      description: 'Maps a single catalog product to a specific SKU.io product chosen
        in the smart-match modal. Replaces any existing mapping in place. Returns
        the refreshed Magento 1 product resource (with its `product_listing`).


        Body fields:

        - product_id (integer, required): the SKU.io product id to link (must exist
        in `products`).


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                product_id:
                  type: integer
              example:
                product_id: 30412
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Magento 1 integration instance id
        example: '3'
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: Magento 1 product mirror id (magento1_products.id PK)
        example: '512'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      product_id:
                        type: integer
                      sku:
                        type: string
                      name:
                        type: string
                      type_id:
                        type: string
                      status:
                        type: string
                      visibility:
                        type: string
                      price:
                        type: string
                      weight:
                        type: string
                      short_description:
                        type: string
                      description:
                        type: string
                      qty:
                        type: string
                      is_in_stock:
                        type: boolean
                      image_url:
                        type: string
                      store_id:
                        type: integer
                      magento_created_at:
                        type: string
                      magento_updated_at:
                        type: string
                      is_mapped:
                        type: boolean
                      product_listing:
                        type: object
                        properties:
                          id:
                            type: integer
                          listing_sku:
                            type: string
                          product:
                            type: object
                            properties:
                              id:
                                type: integer
                              sku:
                                type: string
                              name:
                                type: string
                              type:
                                type: string
                      created_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                      is_archived:
                        type: boolean
                example:
                  data:
                    id: 512
                    integration_instance_id: 3
                    product_id: 8842
                    sku: ACME-HOODIE-M-BLU
                    name: Acme Hoodie - Medium - Blue
                    type_id: simple
                    status: '1'
                    visibility: '4'
                    price: '49.9900'
                    weight: '0.8000'
                    short_description: Soft cotton hoodie
                    description: A soft, midweight cotton hoodie.
                    qty: '124.0000'
                    is_in_stock: true
                    image_url: https://store.example.com/media/catalog/product/a/c/acme-hoodie.jpg
                    store_id: 1
                    magento_created_at: '2026-01-04T09:12:00+00:00'
                    magento_updated_at: '2026-07-02T14:33:00+00:00'
                    is_mapped: true
                    product_listing:
                      id: 9001
                      listing_sku: ACME-HOODIE-M-BLU
                      product:
                        id: 30412
                        sku: ACME-HOODIE-M-BLU
                        name: Acme Hoodie (Medium, Blue)
                        type: simple
                    created_at: '2026-01-04T09:15:00+00:00'
                    archived_at: null
                    is_archived: false
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-magento1-instances-integrationinstance-products-product-map
    delete:
      tags:
      - Magento 1
      summary: Unmap Product
      description: 'Removes the SKU.io product link for a single catalog product.


        Body: none.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Magento 1 integration instance id
        example: '3'
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: Magento 1 product mirror id (magento1_products.id PK)
        example: '512'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      unmapped:
                        type: boolean
                  message:
                    type: string
                example:
                  data:
                    unmapped: true
                  message: Product unmapped
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-magento1-instances-integrationinstance-products-product-map
  /api/magento1/instances/{integrationInstance}/products/{product}/raw:
    get:
      tags:
      - Magento 1
      summary: Get Raw Product Data (Live)
      description: 'Fetches the raw catalog payload for a product LIVE from the Magento
        1 store via the SOAP Core API (mirrors Shopify''s "Load Raw Data" panel).
        Magento 1 mirror tables carry no `raw_data` column, so there is no cached
        fallback — a store/SOAP error surfaces as 422.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Magento 1 integration instance id
        example: '3'
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: Magento 1 product mirror id (magento1_products.id PK)
        example: '512'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      product_id:
                        type: string
                      sku:
                        type: string
                      name:
                        type: string
                      status:
                        type: string
                      visibility:
                        type: string
                      type:
                        type: string
                      price:
                        type: string
                      weight:
                        type: string
                  source:
                    type: string
                example:
                  data:
                    product_id: '8842'
                    sku: ACME-HOODIE-M-BLU
                    name: Acme Hoodie - Medium - Blue
                    status: '1'
                    visibility: '4'
                    type: simple
                    price: '49.9900'
                    weight: '0.8000'
                  source: live
        '422':
          description: Unprocessable Entity
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 'Failed to fetch raw product data from Magento 1: SOAP
                    fault: Requested product not found.'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-magento1-instances-integrationinstance-products-product-raw
  /api/magento1/instances/{integrationInstance}/products/{product}:
    get:
      tags:
      - Magento 1
      summary: Get Product
      description: 'Shows a single Magento 1 catalog product with its linked SKU.io
        product listing (when mapped). 404 if the product does not belong to the given
        instance.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Magento 1 integration instance id
        example: '3'
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: Magento 1 product mirror id (magento1_products.id PK)
        example: '512'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      product_id:
                        type: integer
                      sku:
                        type: string
                      name:
                        type: string
                      type_id:
                        type: string
                      status:
                        type: string
                      visibility:
                        type: string
                      price:
                        type: string
                      weight:
                        type: string
                      short_description:
                        type: string
                      description:
                        type: string
                      qty:
                        type: string
                      is_in_stock:
                        type: boolean
                      image_url:
                        type: string
                      store_id:
                        type: integer
                      magento_created_at:
                        type: string
                      magento_updated_at:
                        type: string
                      is_mapped:
                        type: boolean
                      product_listing:
                        type: object
                        properties:
                          id:
                            type: integer
                          listing_sku:
                            type: string
                          product:
                            type: object
                            properties:
                              id:
                                type: integer
                              sku:
                                type: string
                              name:
                                type: string
                              type:
                                type: string
                      created_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                      is_archived:
                        type: boolean
                example:
                  data:
                    id: 512
                    integration_instance_id: 3
                    product_id: 8842
                    sku: ACME-HOODIE-M-BLU
                    name: Acme Hoodie - Medium - Blue
                    type_id: simple
                    status: '1'
                    visibility: '4'
                    price: '49.9900'
                    weight: '0.8000'
                    short_description: Soft cotton hoodie
                    description: A soft, midweight cotton hoodie.
                    qty: '124.0000'
                    is_in_stock: true
                    image_url: https://store.example.com/media/catalog/product/a/c/acme-hoodie.jpg
                    store_id: 1
                    magento_created_at: '2026-01-04T09:12:00+00:00'
                    magento_updated_at: '2026-07-02T14:33:00+00:00'
                    is_mapped: true
                    product_listing:
                      id: 9001
                      listing_sku: ACME-HOODIE-M-BLU
                      product:
                        id: 30412
                        sku: ACME-HOODIE-M-BLU
                        name: Acme Hoodie (Medium, Blue)
                        type: simple
                    created_at: '2026-01-04T09:15:00+00:00'
                    archived_at: null
                    is_archived: false
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-magento1-instances-integrationinstance-products-product
  /api/magento1/instances/{integrationInstance}/products/search:
    post:
      tags:
      - Magento 1
      summary: Search Products
      description: 'Live-search the connected Magento 1 catalog by SKU or name. Returns
        shallow matches, each flagged with whether it already exists in SKU.io.


        Body: `search_by` — `sku` or `name`. `query` — the search term (string, max
        255).


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                search_by:
                  type: string
                query:
                  type: string
              example:
                search_by: sku
                query: ACME-HOODIE
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Magento 1 integration instance id
        example: '3'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        product_id:
                          type: string
                        sku:
                          type: string
                        name:
                          type: string
                        type:
                          type: string
                        exists_in_database:
                          type: boolean
                        database_id:
                          type: string
                          nullable: true
                example:
                  data:
                  - product_id: '8842'
                    sku: ACME-HOODIE-M-BLU
                    name: Acme Hoodie - Medium - Blue
                    type: simple
                    exists_in_database: false
                    database_id: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-magento1-instances-integrationinstance-products-search
  /api/magento1/instances/{integrationInstance}/products/fetch-single:
    post:
      tags:
      - Magento 1
      summary: Download Single Product
      description: 'Fetch a single catalog product from the Magento 1 store by its
        product id (deep data + live stock) and persist it into SKU.io. Use this to
        import a specific product surfaced by Search Products.


        Body: `product_id` — the Magento catalog product id (string, required).


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                product_id:
                  type: string
              example:
                product_id: '8842'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Magento 1 integration instance id
        example: '3'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      product_id:
                        type: integer
                      sku:
                        type: string
                      name:
                        type: string
                      type_id:
                        type: string
                      status:
                        type: string
                      visibility:
                        type: string
                      price:
                        type: string
                      weight:
                        type: string
                      qty:
                        type: string
                      is_in_stock:
                        type: boolean
                      magento_created_at:
                        type: string
                      magento_updated_at:
                        type: string
                      is_mapped:
                        type: boolean
                      product_listing:
                        type: object
                        properties:
                          id:
                            type: integer
                          listing_sku:
                            type: string
                          product:
                            type: object
                            properties:
                              id:
                                type: integer
                              sku:
                                type: string
                              name:
                                type: string
                              type:
                                type: string
                example:
                  message: Product fetched from Magento 1
                  data:
                    id: 512
                    integration_instance_id: 3
                    product_id: 8842
                    sku: ACME-HOODIE-M-BLU
                    name: Acme Hoodie - Medium - Blue
                    type_id: simple
                    status: '1'
                    visibility: '4'
                    price: '49.9900'
                    weight: '0.8000'
                    qty: '124.0000'
                    is_in_stock: true
                    magento_created_at: '2026-01-04T09:12:00+00:00'
                    magento_updated_at: '2026-07-02T14:33:00+00:00'
                    is_mapped: true
                    product_listing:
                      id: 9001
                      listing_sku: ACME-HOODIE-M-BLU
                      product:
                        id: 30412
                        sku: ACME-HOODIE-M-BLU
                        name: Acme Hoodie (Medium, Blue)
                        type: simple
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-magento1-instances-integrationinstance-products-fetch-single
  /api/magento1/instances/{integrationInstance}/mappings:
    get:
      tags:
      - Magento 1
      summary: Get Field Mappings
      description: 'Current Magento 1 → SKU.io field-mapping config for the instance
        — what the Map dialog''s "Field Mapping" section edits. Returns the available
        source (Magento) fields, the constrained set of target (SKU) fields, the default
        mappings, the instance''s custom overrides, and the effective (merged) mappings.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Magento 1 integration instance id
        example: '3'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      integration_instance_id:
                        type: integer
                      integration_name:
                        type: string
                      mappings:
                        type: array
                        items:
                          type: object
                          properties:
                            listing_field:
                              type: string
                            sku_field:
                              type: string
                            parsers:
                              type: array
                      available_magento_fields:
                        type: array
                        items:
                          type: string
                      available_sku_fields:
                        type: array
                        items:
                          type: string
                      default_mappings:
                        type: array
                        items:
                          type: object
                          properties:
                            listing_field:
                              type: string
                            sku_field:
                              type: string
                      custom_mappings:
                        type: array
                      effective_mappings:
                        type: array
                        items:
                          type: object
                          properties:
                            listing_field:
                              type: string
                            sku_field:
                              type: string
                example:
                  data:
                    integration_instance_id: 3
                    integration_name: Acme Magento Store
                    mappings:
                    - listing_field: sku
                      sku_field: sku
                      parsers: []
                    - listing_field: name
                      sku_field: item_name
                      parsers: []
                    - listing_field: price
                      sku_field: price
                      parsers: []
                    - listing_field: weight
                      sku_field: weight
                      parsers: []
                    available_magento_fields:
                    - name
                    - sku
                    - price
                    - weight
                    - short_description
                    - description
                    available_sku_fields:
                    - sku
                    - item_name
                    - price
                    - weight
                    - length
                    - width
                    - height
                    default_mappings:
                    - listing_field: sku
                      sku_field: sku
                    - listing_field: name
                      sku_field: item_name
                    - listing_field: price
                      sku_field: price
                    - listing_field: weight
                      sku_field: weight
                    custom_mappings: []
                    effective_mappings:
                    - listing_field: sku
                      sku_field: sku
                    - listing_field: name
                      sku_field: item_name
                    - listing_field: price
                      sku_field: price
                    - listing_field: weight
                      sku_field: weight
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-magento1-instances-integrationinstance-mappings
    put:
      tags:
      - Magento 1
      summary: Update Field Mappings
      description: "Upserts the per-instance field-mapping config. Target (`sku_field`)\
        \ values are constrained to the exact keys `Magento1Product::applyDataMapping()`\
        \ resolves (sku, item_name, price, weight, length, width, height), so a saved\
        \ mapping never silently no-ops at product-creation time.\n\nBody fields:\n\
        - mappings (array, required): the full mapping set to persist.\n  - mappings.*.listing_field\
        \ (string, required): a Magento source field (name, sku, price, weight, short_description,\
        \ description).\n  - mappings.*.sku_field (string, required): the SKU.io target\
        \ field.\n  - mappings.*.parsers (array, optional/nullable): ordered value\
        \ transformers applied on import.\n\nReturns the persisted mappings + the\
        \ recomputed effective mappings.\n\nAuthentication: Requires Bearer token."
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                mappings:
                  type: array
                  items:
                    type: object
                    properties:
                      listing_field:
                        type: string
                      sku_field:
                        type: string
                      parsers:
                        type: array
              example:
                mappings:
                - listing_field: sku
                  sku_field: sku
                  parsers: []
                - listing_field: name
                  sku_field: item_name
                  parsers: []
                - listing_field: price
                  sku_field: price
                  parsers: []
                - listing_field: weight
                  sku_field: weight
                  parsers: []
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Magento 1 integration instance id
        example: '3'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      integration_instance_id:
                        type: integer
                      integration_name:
                        type: string
                      mappings:
                        type: array
                        items:
                          type: object
                          properties:
                            listing_field:
                              type: string
                            sku_field:
                              type: string
                            parsers:
                              type: array
                      effective_mappings:
                        type: array
                        items:
                          type: object
                          properties:
                            listing_field:
                              type: string
                            sku_field:
                              type: string
                  message:
                    type: string
                example:
                  data:
                    integration_instance_id: 3
                    integration_name: Acme Magento Store
                    mappings:
                    - listing_field: sku
                      sku_field: sku
                      parsers: []
                    - listing_field: name
                      sku_field: item_name
                      parsers: []
                    - listing_field: price
                      sku_field: price
                      parsers: []
                    - listing_field: weight
                      sku_field: weight
                      parsers: []
                    effective_mappings:
                    - listing_field: sku
                      sku_field: sku
                    - listing_field: name
                      sku_field: item_name
                    - listing_field: price
                      sku_field: price
                    - listing_field: weight
                      sku_field: weight
                  message: Field mappings updated successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-magento1-instances-integrationinstance-mappings
  /api/magento1/instances/{integrationInstance}/inventory:
    get:
      tags:
      - Magento 1
      summary: List Inventory Comparison
      description: 'Lists the inventory-comparison rows for a Magento 1 instance —
        one row per mapped product listing — comparing the SKU.io on-hand quantity
        against the last-known Magento 1 store quantity, with the variance and a per-row
        sync status (synced / variance / needs_recalc).


        Allowed sorts: id, sku_quantity, sales_channel_quantity, sales_channel_quantity_updated_at,
        sales_channel_quantity_synced_at, created_at, updated_at (default -id). Advanced
        search + status/quantity/datetime filters as listed. Paginated (default 10/page).


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        product_listing_id:
                          type: integer
                        document_id:
                          type: integer
                        sku:
                          type: string
                        title:
                          type: string
                        product_sku:
                          type: string
                        sku_quantity:
                          type: integer
                        sales_channel_quantity:
                          type: integer
                        variance:
                          type: integer
                        change_needed:
                          type: integer
                        status:
                          type: string
                        is_sku_recalculation_needed:
                          type: boolean
                        sales_channel_quantity_updated_at:
                          type: string
                        sales_channel_quantity_synced_at:
                          type: string
                        sku_quantity_updated_at:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                        magento_product_id:
                          type: integer
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                  first_page_url:
                    type: string
                  last_page_url:
                    type: string
                  next_page_url:
                    type: string
                  prev_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  links:
                    type: array
                example:
                  data:
                  - id: 7712
                    product_listing_id: 9001
                    document_id: 512
                    sku: ACME-HOODIE-M-BLU
                    title: Acme Hoodie - Medium - Blue
                    product_sku: ACME-HOODIE-M-BLU
                    sku_quantity: 124
                    sales_channel_quantity: 118
                    variance: 6
                    change_needed: 6
                    status: variance
                    is_sku_recalculation_needed: false
                    sales_channel_quantity_updated_at: '2026-07-07T14:33:00+00:00'
                    sales_channel_quantity_synced_at: '2026-07-06T09:10:00+00:00'
                    sku_quantity_updated_at: '2026-07-07T15:00:00+00:00'
                    created_at: '2026-01-04T09:15:00+00:00'
                    updated_at: '2026-07-07T15:00:00+00:00'
                    magento_product_id: 8842
                  current_page: 1
                  last_page: 5
                  per_page: 10
                  total: 48
                  from: 1
                  to: 10
                  first_page_url: '...'
                  last_page_url: '...'
                  next_page_url: '...'
                  prev_page_url: null
                  path: '...'
                  links: []
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-magento1-instances-integrationinstance-inventory
  /api/magento1/instances/{integrationInstance}/inventory/summary:
    get:
      tags:
      - Magento 1
      summary: Get Inventory Summary
      description: 'Returns aggregate inventory statistics for a Magento 1 instance:
        total mapped items, in-sync count, variance count, needs-recalculation count,
        in-stock / out-of-stock counts, the last fetch and last push timestamps, and
        the (never-fetched) count. Powers the summary cards above the inventory comparison
        list.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      total_items:
                        type: integer
                      in_sync:
                        type: integer
                      with_variance:
                        type: integer
                      needs_recalculation:
                        type: integer
                      in_stock:
                        type: integer
                      out_of_stock:
                        type: integer
                      last_fetch_at:
                        type: string
                      last_sync_at:
                        type: string
                      needs_update:
                        type: integer
                      never_fetched:
                        type: integer
                example:
                  data:
                    total_items: 48
                    in_sync: 39
                    with_variance: 6
                    needs_recalculation: 3
                    in_stock: 44
                    out_of_stock: 4
                    last_fetch_at: '2026-07-07T14:33:00+00:00'
                    last_sync_at: '2026-07-06T09:10:00+00:00'
                    needs_update: 6
                    never_fetched: 2
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-magento1-instances-integrationinstance-inventory-summary
  /api/magento1/instances/{integrationInstance}/inventory/fetch:
    post:
      tags:
      - Magento 1
      summary: Fetch Inventory Levels (Tracked)
      description: 'Starts a tracked job that reads the current stock level from Magento
        1 for every mapped product and writes it into the comparison cache (the store-side
        column). Use this to refresh the Magento 1 quantities shown in the comparison
        before deciding what to push. Returns a `tracked_job_log_id` you can poll
        for progress.


        Body: none.


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 48233
                  message: Inventory refresh started
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-magento1-instances-integrationinstance-inventory-fetch
  /api/magento1/instances/{integrationInstance}/inventory/recache:
    post:
      tags:
      - Magento 1
      summary: Recache Inventory (Tracked)
      description: 'Starts a tracked job that recomputes SKU.io on-hand quantities
        for every mapped product listing on the instance and refreshes the comparison
        cache. Use this when the SKU.io side is stale (status = needs_recalc). Returns
        a `tracked_job_log_id` you can poll for progress.


        Body: none.


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 48231
                  message: Inventory recache started
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-magento1-instances-integrationinstance-inventory-recache
  /api/magento1/instances/{integrationInstance}/inventory/push:
    post:
      tags:
      - Magento 1
      summary: Push Inventory (Tracked)
      description: 'Starts a tracked job that pushes SKU.io on-hand quantities to
        Magento 1 for the mapped products with a variance. The outbound inventory
        sync gate (per-instance sync settings) is enforced inside the job — when outbound
        inventory sync is disabled the job still completes successfully, pushing nothing.
        Returns a `tracked_job_log_id` you can poll for progress.


        Body: none.


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 48232
                  message: Inventory push started
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-magento1-instances-integrationinstance-inventory-push
  /api/magento2/test-connection:
    post:
      tags:
      - Connection
      summary: Test Connection
      description: 'Validates the supplied Magento 2 credentials by calling the REST
        API. Returns the store views and MSI (Multi-Source Inventory) sources the
        merchant has access to — used by the UI to preview before persisting.


        Nothing is persisted by this endpoint.


        **Body parameters:**

        - `base_url` (required, URL): The storefront base URL — e.g. `https://shop.example.com`.
        Trailing slash is trimmed server-side.

        - `access_token` (required, string, min 8 chars, max 255): The integration
        access token from Magento Admin → System → Integrations.


        **Error responses:**

        - `422` — validation failure OR Magento rejected the credentials (`success:
        false` with a human-readable `message`).

        - `401` — caller is not authenticated to SKU.io.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                base_url:
                  type: string
                access_token:
                  type: string
              example:
                base_url: https://shop.example.com
                access_token: magento_integration_access_token_xxxxxxxx
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      store_views:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            code:
                              type: string
                            name:
                              type: string
                            website_id:
                              type: integer
                            store_group_id:
                              type: integer
                      inventory_sources:
                        type: array
                        items:
                          type: object
                          properties:
                            source_code:
                              type: string
                            name:
                              type: string
                            enabled:
                              type: boolean
                            country_id:
                              type: string
                example:
                  success: true
                  data:
                    store_views:
                    - id: 0
                      code: admin
                      name: Admin
                      website_id: 0
                      store_group_id: 0
                    - id: 1
                      code: default
                      name: Default Store View
                      website_id: 1
                      store_group_id: 1
                    - id: 2
                      code: en_us
                      name: United States
                      website_id: 1
                      store_group_id: 1
                    inventory_sources:
                    - source_code: default
                      name: Default Source
                      enabled: true
                      country_id: US
                    - source_code: us_warehouse
                      name: US Warehouse
                      enabled: true
                      country_id: US
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 422 — Credentials rejected
                  value:
                    success: false
                    message: 'Magento 2 rejected the credentials: the access token
                      is invalid or expired.'
                example-1:
                  summary: 422 — Validation error (missing field)
                  value:
                    message: The access token field is required.
                    errors:
                      access_token:
                      - The access token field is required.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-magento2-test-connection
  /api/magento2/install:
    post:
      tags:
      - Connection
      summary: Install
      description: 'Provisions a new Magento 2 IntegrationInstance after re-validating
        the supplied credentials server-side. The probe runs again here — clients
        cannot skip validation by calling `/install` directly.


        The returned instance includes the access token in masked form only (last
        4 chars). The full token is encrypted at rest and never echoed back.


        **Body parameters:**

        - `name` (required, string, max 255): Human-readable instance name. Must be
        unique within your tenant.

        - `base_url` (required, URL): Magento storefront base URL.

        - `access_token` (required, string, min 8 chars): The integration access token
        from Magento Admin.

        - `country` (optional, nullable, ISO 3166-1 alpha-2): Two-letter country code,
        e.g. `US`.


        **Behavior:**

        - Server probes Magento for store views + MSI sources and persists the discovery
        into `integration_settings.discovery` so downstream phases can read them without
        re-fetching.

        - Default `integration_settings` are seeded: orders auto-download disabled,
        email_customers enabled.


        **Error responses:**

        - `422` — name already taken OR Magento rejected the credentials.

        - `401` — caller is not authenticated to SKU.io.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                base_url:
                  type: string
                access_token:
                  type: string
                country:
                  type: string
              example:
                name: Acme — US Storefront
                base_url: https://shop.example.com
                access_token: magento_integration_access_token_xxxxxxxx
                country: US
      parameters: []
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_id:
                        type: integer
                      name:
                        type: string
                      country:
                        type: string
                      sync_status:
                        type: string
                        nullable: true
                      connection_status:
                        type: string
                        nullable: true
                      is_automatic_sync_enabled:
                        type: boolean
                      connection_settings:
                        type: object
                        properties:
                          base_url:
                            type: string
                          access_token_masked:
                            type: string
                      integration_settings:
                        type: object
                        properties:
                          orders:
                            type: object
                            properties:
                              download:
                                type: object
                                properties:
                                  last_updated_after:
                                    type: string
                                    nullable: true
                                  status:
                                    type: array
                                  auto_download:
                                    type: object
                                    properties:
                                      enabled:
                                        type: boolean
                                      frequency_mins:
                                        type: integer
                          inventory:
                            type: object
                            properties:
                              master_of_stock:
                                type: string
                                nullable: true
                          communications:
                            type: object
                            properties:
                              email_customers:
                                type: boolean
                          discovery:
                            type: object
                            properties:
                              store_views:
                                type: array
                                items:
                                  type: object
                                  properties:
                                    id:
                                      type: integer
                                    code:
                                      type: string
                                    name:
                                      type: string
                              inventory_sources:
                                type: array
                                items:
                                  type: object
                                  properties:
                                    source_code:
                                      type: string
                                    name:
                                      type: string
                                    enabled:
                                      type: boolean
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  success: true
                  data:
                    id: 42
                    integration_id: 17
                    name: Acme — US Storefront
                    country: US
                    sync_status: null
                    connection_status: null
                    is_automatic_sync_enabled: false
                    connection_settings:
                      base_url: https://shop.example.com
                      access_token_masked: ••••••••••••••••••••xxxx
                    integration_settings:
                      orders:
                        download:
                          last_updated_after: null
                          status: []
                          auto_download:
                            enabled: false
                            frequency_mins: 15
                      inventory:
                        master_of_stock: null
                      communications:
                        email_customers: true
                      discovery:
                        store_views:
                        - id: 1
                          code: default
                          name: Default Store View
                        inventory_sources:
                        - source_code: default
                          name: Default Source
                          enabled: true
                    created_at: '2026-06-10T12:34:56+00:00'
                    updated_at: '2026-06-10T12:34:56+00:00'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                example:
                  success: false
                  message: An integration instance named 'Acme — US Storefront' already
                    exists.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-magento2-install
  /api/shipfusion/integration-instances:
    post:
      tags:
      - Shipfusion
      summary: Create Integration Instance
      description: "Create a new Shipfusion integration instance.\n\n:::info[Authorization]\n\
        Any valid API token can call this endpoint — no specific scope required. [Manage\
        \ tokens](https://app.sku.io/settings/api).\n:::\n\nAuthentication: Requires\
        \ Bearer token.\n\nRequest Body:\n- name (string, required) — Unique name\
        \ for the integration instance\n- integration_id (integer, required) — ID\
        \ of the integration record (must exist in integrations table)\n- connection_settings\
        \ (object, optional) — Shipfusion API credentials\n  - username (string) —\
        \ Shipfusion API username\n  - password (string) — Shipfusion API password\n\
        - integration_settings (object, optional) — Integration behavior settings\n\
        \  - enable_fulfillment (boolean) — Enable automated fulfillment via Shipfusion\n\
        \  - pass_tags (boolean) — Pass order tags to Shipfusion\n- is_automatic_sync_enabled\
        \ (boolean, optional, default: false) — Enable automatic order/inventory syncing"
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                integration_id:
                  type: integer
                connection_settings:
                  type: object
                  properties:
                    username:
                      type: string
                    password:
                      type: string
                integration_settings:
                  type: object
                  properties:
                    enable_fulfillment:
                      type: boolean
                    pass_tags:
                      type: boolean
                is_automatic_sync_enabled:
                  type: boolean
              example:
                name: My Shipfusion Account
                integration_id: 5
                connection_settings:
                  username: sfuser@example.com
                  password: sf_api_password
                integration_settings:
                  enable_fulfillment: true
                  pass_tags: false
                is_automatic_sync_enabled: true
      parameters: []
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      integration_id:
                        type: integer
                      connection_settings:
                        type: object
                        properties:
                          username:
                            type: string
                          password:
                            type: string
                      integration_settings:
                        type: object
                        properties:
                          connection_name:
                            type: string
                            nullable: true
                          linked_warehouse:
                            type: string
                            nullable: true
                          enable_fulfillment:
                            type: boolean
                          pass_tags:
                            type: boolean
                      is_automatic_sync_enabled:
                        type: boolean
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 1
                    name: My Shipfusion Account
                    integration_id: 5
                    connection_settings:
                      username: sfuser@example.com
                      password: '***'
                    integration_settings:
                      connection_name: null
                      linked_warehouse: null
                      enable_fulfillment: true
                      pass_tags: false
                    is_automatic_sync_enabled: true
                    created_at: '2024-01-15T10:00:00.000000Z'
                    updated_at: '2024-01-15T10:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-shipfusion-integration-instances
  /api/shipfusion/integration-instances/{integration_instance}:
    get:
      tags:
      - Shipfusion
      summary: Show Integration Instance
      description: 'Retrieve a single Shipfusion integration instance by ID.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      integration_id:
                        type: integer
                      connection_settings:
                        type: object
                        properties:
                          username:
                            type: string
                          password:
                            type: string
                      integration_settings:
                        type: object
                        properties:
                          connection_name:
                            type: string
                            nullable: true
                          linked_warehouse:
                            type: string
                            nullable: true
                          enable_fulfillment:
                            type: boolean
                          pass_tags:
                            type: boolean
                      is_automatic_sync_enabled:
                        type: boolean
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 1
                    name: My Shipfusion Account
                    integration_id: 5
                    connection_settings:
                      username: sfuser@example.com
                      password: '***'
                    integration_settings:
                      connection_name: null
                      linked_warehouse: null
                      enable_fulfillment: true
                      pass_tags: false
                    is_automatic_sync_enabled: true
                    created_at: '2024-01-15T10:00:00.000000Z'
                    updated_at: '2024-01-15T10:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shipfusion-integration-instances-integration-instance
    put:
      tags:
      - Shipfusion
      summary: Update Integration Instance
      description: 'Update a Shipfusion integration instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        All fields are optional — only include the ones you want to update.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                integration_settings:
                  type: object
                  properties:
                    enable_fulfillment:
                      type: boolean
                    pass_tags:
                      type: boolean
                is_automatic_sync_enabled:
                  type: boolean
              example:
                name: Updated Shipfusion Account
                integration_settings:
                  enable_fulfillment: false
                  pass_tags: true
                is_automatic_sync_enabled: false
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      integration_id:
                        type: integer
                      connection_settings:
                        type: object
                        properties:
                          username:
                            type: string
                          password:
                            type: string
                      integration_settings:
                        type: object
                        properties:
                          connection_name:
                            type: string
                            nullable: true
                          linked_warehouse:
                            type: string
                            nullable: true
                          enable_fulfillment:
                            type: boolean
                          pass_tags:
                            type: boolean
                      is_automatic_sync_enabled:
                        type: boolean
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 1
                    name: Updated Shipfusion Account
                    integration_id: 5
                    connection_settings:
                      username: sfuser@example.com
                      password: '***'
                    integration_settings:
                      connection_name: null
                      linked_warehouse: null
                      enable_fulfillment: false
                      pass_tags: true
                    is_automatic_sync_enabled: false
                    created_at: '2024-01-15T10:00:00.000000Z'
                    updated_at: '2024-01-15T12:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-shipfusion-integration-instances-integration-instance
    delete:
      tags:
      - Shipfusion
      summary: Delete Integration Instance
      description: 'Delete a Shipfusion integration instance and all associated data.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Integration instance deleted successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-shipfusion-integration-instances-integration-instance
  /api/shipfusion/integration-instances/{integration_instance}/dashboard:
    get:
      tags:
      - Shipfusion
      summary: Get Dashboard Metrics
      description: 'Get dashboard metrics for a Shipfusion integration instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Returns order counts by status, warehouse shipment counts by status, last
        sync timestamps, and sync frequency configuration.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      orders_by_status:
                        type: object
                        properties:
                          pending:
                            type: integer
                          shipped:
                            type: integer
                          cancelled:
                            type: integer
                      warehouse_shipments_by_status:
                        type: object
                        properties:
                          open:
                            type: integer
                          closed:
                            type: integer
                      orders_last_synced_at:
                        type: string
                      warehouse_shipments_last_synced_at:
                        type: string
                      tracking_info_last_updated_at:
                        type: string
                      sync_frequency:
                        type: string
                      tracking_update_frequency:
                        type: string
                example:
                  data:
                    orders_by_status:
                      pending: 12
                      shipped: 87
                      cancelled: 3
                    warehouse_shipments_by_status:
                      open: 5
                      closed: 22
                    orders_last_synced_at: '2024-01-15T09:30:00.000000Z'
                    warehouse_shipments_last_synced_at: '2024-01-15T09:30:00.000000Z'
                    tracking_info_last_updated_at: '2024-01-15T08:00:00.000000Z'
                    sync_frequency: Every 30 minutes
                    tracking_update_frequency: Every hour
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shipfusion-integration-instances-integration-instance-dashboard
  /api/shipfusion/integration-instances/{integration_instance}/warehouse-mappings:
    get:
      tags:
      - Shipfusion
      summary: List Warehouse Mappings
      description: 'List all warehouse mappings for a Shipfusion integration instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Each mapping links a Shipfusion warehouse code (e.g. ''IL'', ''CA'') to a
        SKU.io warehouse.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        shipfusion_warehouse_code:
                          type: string
                        shipfusion_warehouse_label:
                          type: string
                        warehouse_id:
                          type: integer
                        warehouse_name:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                example:
                  data:
                  - id: 1
                    integration_instance_id: 1
                    shipfusion_warehouse_code: IL
                    shipfusion_warehouse_label: Illinois
                    warehouse_id: 3
                    warehouse_name: Main Warehouse
                    created_at: '2024-01-15T10:00:00.000000Z'
                    updated_at: '2024-01-15T10:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shipfusion-integration-instances-integration-instance-warehouse-mappings
    post:
      tags:
      - Shipfusion
      summary: Create Warehouse Mapping
      description: 'Create a new warehouse mapping linking a Shipfusion warehouse
        code to a SKU.io warehouse.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                shipfusion_warehouse_code:
                  type: string
                warehouse_id:
                  type: integer
              example:
                shipfusion_warehouse_code: IL
                warehouse_id: 3
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      shipfusion_warehouse_code:
                        type: string
                      shipfusion_warehouse_label:
                        type: string
                      warehouse_id:
                        type: integer
                      warehouse_name:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 1
                    integration_instance_id: 1
                    shipfusion_warehouse_code: IL
                    shipfusion_warehouse_label: Illinois
                    warehouse_id: 3
                    warehouse_name: Main Warehouse
                    created_at: '2024-01-15T10:00:00.000000Z'
                    updated_at: '2024-01-15T10:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-shipfusion-integration-instances-integration-instance-warehouse-mappings
  /api/shipfusion/integration-instances/{integration_instance}/warehouse-mappings/{warehouse_code}:
    put:
      tags:
      - Shipfusion
      summary: Update Warehouse Mapping
      description: 'Update the SKU.io warehouse linked to a Shipfusion warehouse code.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                warehouse_id:
                  type: integer
              example:
                warehouse_id: 5
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: warehouse_code
        in: path
        schema:
          type: string
        required: true
        description: Shipfusion warehouse code
        example: IL
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      shipfusion_warehouse_code:
                        type: string
                      shipfusion_warehouse_label:
                        type: string
                      warehouse_id:
                        type: integer
                      warehouse_name:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 1
                    integration_instance_id: 1
                    shipfusion_warehouse_code: IL
                    shipfusion_warehouse_label: Illinois
                    warehouse_id: 5
                    warehouse_name: East Coast Warehouse
                    created_at: '2024-01-15T10:00:00.000000Z'
                    updated_at: '2024-01-15T12:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-shipfusion-integration-instances-integration-instance-warehouse-mappings-warehouse-code
    delete:
      tags:
      - Shipfusion
      summary: Delete Warehouse Mapping
      description: 'Delete a warehouse mapping by Shipfusion warehouse code.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: warehouse_code
        in: path
        schema:
          type: string
        required: true
        description: Shipfusion warehouse code
        example: IL
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Warehouse mapping deleted successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-shipfusion-integration-instances-integration-instance-warehouse-mappings-warehouse-code
  /api/shipfusion/integration-instances/{integration_instance}/orders:
    get:
      tags:
      - Shipfusion
      summary: List Orders
      description: 'List Shipfusion orders for the integration instance (paginated).
        Each order carries its resolved SKU fulfillment link (`sku_fulfillment`) for
        the "SKU Order" card — resolved FulfillmentOrder-first so a deferred-FO order
        still links — plus the scalar tracking fields (`tracking_number`, `carrier`,
        `shipped_at`) derived from the order''s stored payload (per-box detail lives
        on the separate Packages endpoint). Supports Spatie QueryBuilder filters,
        advanced filter operators, grouped filter trees, and sorting. Authenticate
        with a Personal Access Token (PAT) Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        shipfusion_id:
                          type: string
                        order_number:
                          type: string
                        shipment_status:
                          type: string
                        warehouse:
                          type: string
                        order_date:
                          type: string
                        sku_fulfillment_id:
                          type: integer
                        sku_fulfillment_order_id:
                          type: integer
                        sku_fulfillment:
                          type: object
                          properties:
                            id:
                              type: integer
                            link_reference:
                              type: integer
                            link_type_label:
                              type: string
                            link_id:
                              type: integer
                            link_route:
                              type: string
                            status:
                              type: string
                            tracking_number:
                              type: string
                            tracking_url:
                              type: string
                            fulfilled_at:
                              type: string
                            created_at:
                              type: string
                            sales_order_id:
                              type: integer
                            sales_order_number:
                              type: string
                            fulfillment_order_id:
                              type: integer
                            warehouse:
                              type: object
                              properties:
                                id:
                                  type: integer
                                name:
                                  type: string
                        tracking_number:
                          type: string
                        carrier:
                          type: string
                        shipped_at:
                          type: string
                        has_detailed_data:
                          type: boolean
                        details_last_updated:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  next_page_url:
                    type: string
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 12345
                    integration_instance_id: 4
                    shipfusion_id: SF-12345
                    order_number: BG125116.1
                    shipment_status: shipped
                    warehouse: IL
                    order_date: '2026-05-25'
                    sku_fulfillment_id: 256917
                    sku_fulfillment_order_id: 4412
                    sku_fulfillment:
                      id: 256917
                      link_reference: 256917
                      link_type_label: Sales Order Fulfillment
                      link_id: 256917
                      link_route: /orders/sales-orders/fulfillments/256917
                      status: shipped
                      tracking_number: 1Z999AA10123456784
                      tracking_url: https://www.ups.com/track?tracknum=1Z999AA10123456784
                      fulfilled_at: '2026-05-25T16:32:00+00:00'
                      created_at: '2026-05-25T15:10:00+00:00'
                      sales_order_id: 88123
                      sales_order_number: SO-88123
                      fulfillment_order_id: 4412
                      warehouse:
                        id: 7
                        name: Illinois DC
                    tracking_number: 1Z999AA10123456784
                    carrier: UPS Ground
                    shipped_at: '2026-05-25T16:32:00.000000Z'
                    has_detailed_data: true
                    details_last_updated: '2026-05-25T16:35:00.000000Z'
                    created_at: '2026-05-20T09:00:00.000000Z'
                    updated_at: '2026-05-25T16:35:00.000000Z'
                  current_page: 1
                  first_page_url: '{{protocol}}://{{domain}}/api/shipfusion/integration-instances/{{integration_instance}}/orders?page=1'
                  from: 1
                  last_page: 17
                  last_page_url: '{{protocol}}://{{domain}}/api/shipfusion/integration-instances/{{integration_instance}}/orders?page=17'
                  next_page_url: '{{protocol}}://{{domain}}/api/shipfusion/integration-instances/{{integration_instance}}/orders?page=2'
                  path: '{{protocol}}://{{domain}}/api/shipfusion/integration-instances/{{integration_instance}}/orders'
                  per_page: 10
                  prev_page_url: null
                  to: 10
                  total: 167
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shipfusion-integration-instances-integration-instance-orders
  /api/shipfusion/integration-instances/{integration_instance}/orders/{order}:
    get:
      tags:
      - Shipfusion
      summary: Get Order
      description: 'Get a specific Shipfusion order by its Shipfusion ID.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: order
        in: path
        schema:
          type: string
        required: true
        description: Shipfusion order number
        example: SF-12345
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shipfusion-integration-instances-integration-instance-orders-order
    delete:
      tags:
      - Shipfusion
      summary: Delete Order
      description: 'Cancel/delete a Shipfusion order.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: order
        in: path
        schema:
          type: string
        required: true
        description: Shipfusion order number
        example: SF-12345
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-shipfusion-integration-instances-integration-instance-orders-order
  /api/shipfusion/integration-instances/{integration_instance}/orders/{order}/detail:
    get:
      tags:
      - Shipfusion
      summary: Get Order Detail (JSON)
      description: 'Get full detail for a single Shipfusion order. Returns the resource
        fields the standalone order detail page renders (id, integration_instance_id,
        shipfusion_id, order_number, shipment_status, warehouse, order_date, tracking_number,
        carrier, shipped_at, has_detailed_data, details_last_updated, timestamps),
        the linked `sku_fulfillment` card (resolved FulfillmentOrder-first so a deferred-FO
        order still links — a Sales Order Fulfillment, or the Fulfillment Order itself
        when the SOF has not been minted yet), AND the raw Shipfusion `json_object`
        (recipient address, shipmentItems, tracking packages) used by the detail page''s
        expandable sections.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        The `:order` path variable is the SKU primary key (route-model binding), matching
        the Fulfillment Order → provider-order cross-link route. Returns 404 if the
        order does not belong to the given integration instance.


        Authentication: Requires Bearer token.


        The response also includes a normalized `shipment_items` array (derived from
        `json_object.shipmentItems`) that the Items table renders. Each entry: `sku`
        (string|null), `product_id` (the EXTERNAL Shipfusion product id — not a SKU.io
        id, kept for reference only), `sku_product_id` (the resolved local SKU.io
        product id, used to link the SKU to its product detail page `/products/{sku_product_id}`;
        null when the SKU has no matching product), `quantity` (number|null), `status`
        (string|null), and `lot_number` (first lot number, string|null).'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: order
        in: path
        schema:
          type: integer
        required: true
        example: '101'
        description: The order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      shipfusion_id:
                        type: string
                      order_number:
                        type: string
                      shipment_status:
                        type: string
                      warehouse:
                        type: string
                      order_date:
                        type: string
                      sku_fulfillment_id:
                        type: integer
                      sku_fulfillment_order_id:
                        type: integer
                      sku_fulfillment:
                        type: object
                        properties:
                          id:
                            type: integer
                          link_reference:
                            type: integer
                          link_type_label:
                            type: string
                          link_id:
                            type: integer
                          link_route:
                            type: string
                          status:
                            type: string
                          tracking_number:
                            type: string
                          tracking_url:
                            type: string
                          fulfilled_at:
                            type: string
                          created_at:
                            type: string
                          sales_order_id:
                            type: integer
                          sales_order_number:
                            type: string
                          fulfillment_order_id:
                            type: integer
                          warehouse:
                            type: object
                            properties:
                              id:
                                type: integer
                              name:
                                type: string
                      tracking_number:
                        type: string
                      carrier:
                        type: string
                      shipped_at:
                        type: string
                      has_detailed_data:
                        type: boolean
                      details_last_updated:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      json_object:
                        type: object
                        properties:
                          id:
                            type: integer
                          shipmentId:
                            type: integer
                          orderNumber:
                            type: string
                          orderReferenceNumber:
                            type: string
                          shipmentStatus:
                            type: string
                          warehouse:
                            type: string
                          orderDate:
                            type: string
                          shipDate:
                            type: string
                          salesChannelTitle:
                            type: string
                          shipmentInstructions:
                            type: string
                          address:
                            type: object
                            properties:
                              firstName:
                                type: string
                              lastName:
                                type: string
                              address1:
                                type: string
                              address2:
                                type: string
                              city:
                                type: string
                              state:
                                type: string
                              zip:
                                type: string
                              country:
                                type: string
                              phoneNumber:
                                type: string
                              emailAddress:
                                type: string
                          shipmentItems:
                            type: array
                            items:
                              type: object
                              properties:
                                shipmentItemId:
                                  type: integer
                                SKU:
                                  type: string
                                qty:
                                  type: integer
                                itemStatus:
                                  type: string
                                lotInformation:
                                  type: array
                                  items:
                                    type: object
                                    properties:
                                      lotNumber:
                                        type: string
                          tracking:
                            type: object
                            properties:
                              totalPackages:
                                type: integer
                              packages:
                                type: array
                                items:
                                  type: object
                                  properties:
                                    trackingStatus:
                                      type: string
                                    shippingCarrier:
                                      type: string
                                    shippingService:
                                      type: string
                                    trackingNumber:
                                      type: string
                                    trackingUrl:
                                      type: string
                                    shipDate:
                                      type: string
                                    dimensions:
                                      type: object
                                      properties:
                                        lengthIn:
                                          type: integer
                                        widthIn:
                                          type: integer
                                        heightIn:
                                          type: integer
                                        weightLb:
                                          type: integer
                                        weightOz:
                                          type: integer
                      shipment_items:
                        type: array
                        items:
                          type: object
                          properties:
                            sku:
                              type: string
                            product_id:
                              type: integer
                            sku_product_id:
                              type: integer
                            quantity:
                              type: integer
                            status:
                              type: string
                            lot_number:
                              type: string
                example:
                  status: success
                  data:
                    id: 101
                    integration_instance_id: 7
                    shipfusion_id: SF-12345
                    order_number: ORD-100245
                    shipment_status: shipped
                    warehouse: PA
                    order_date: '2026-06-20'
                    sku_fulfillment_id: 5582
                    sku_fulfillment_order_id: 12460
                    sku_fulfillment:
                      id: 5582
                      link_reference: 5582
                      link_type_label: Sales Order Fulfillment
                      link_id: 5582
                      link_route: /orders/sales-orders/fulfillments/5582
                      status: shipped
                      tracking_number: 1Z999AA10123456784
                      tracking_url: https://www.ups.com/track?tracknum=1Z999AA10123456784
                      fulfilled_at: '2026-06-21T14:32:00+00:00'
                      created_at: '2026-06-20T09:15:00+00:00'
                      sales_order_id: 32861
                      sales_order_number: SO-32861
                      fulfillment_order_id: 12460
                      warehouse:
                        id: 3
                        name: Main Warehouse
                    tracking_number: 1Z999AA10123456784
                    carrier: UPS Ground
                    shipped_at: '2026-06-21T14:32:00.000000Z'
                    has_detailed_data: true
                    details_last_updated: '2026-06-21T15:00:00.000000Z'
                    created_at: '2026-06-20T09:15:00.000000Z'
                    updated_at: '2026-06-21T15:00:00.000000Z'
                    json_object:
                      id: 987654
                      shipmentId: 987654
                      orderNumber: ORD-100245
                      orderReferenceNumber: REF-100245
                      shipmentStatus: shipped
                      warehouse: PA
                      orderDate: '20260620'
                      shipDate: '20260621'
                      salesChannelTitle: Shopify
                      shipmentInstructions: Leave at front door
                      address:
                        firstName: Jane
                        lastName: Doe
                        address1: 123 Market St
                        address2: Suite 400
                        city: Philadelphia
                        state: PA
                        zip: '19103'
                        country: US
                        phoneNumber: +1 215-555-0142
                        emailAddress: jane.doe@example.com
                      shipmentItems:
                      - shipmentItemId: 5511
                        SKU: WIDGET-BLK-01
                        qty: 2
                        itemStatus: shipped
                        lotInformation:
                        - lotNumber: LOT-2026-0420
                      tracking:
                        totalPackages: 1
                        packages:
                        - trackingStatus: Delivered
                          shippingCarrier: UPS
                          shippingService: Ground
                          trackingNumber: 1Z999AA10123456784
                          trackingUrl: https://www.ups.com/track?tracknum=1Z999AA10123456784
                          shipDate: '20260621'
                          dimensions:
                            lengthIn: 12
                            widthIn: 9
                            heightIn: 4
                            weightLb: 2
                            weightOz: 6
                    shipment_items:
                    - sku: WIDGET-BLK-01
                      product_id: 1999637981
                      sku_product_id: 482
                      quantity: 2
                      status: shipped
                      lot_number: LOT-2026-0420
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shipfusion-integration-instances-integration-instance-orders-order-detail
  /api/shipfusion/integration-instances/{integration_instance}/orders/{order}/raw:
    get:
      tags:
      - Shipfusion
      summary: Get Raw Order Data
      description: 'Fetch the raw, un-persisted Shipfusion shipment JSON for a single
        order, live from the Shipfusion API. Mirrors the Shopify order detail "Load
        Raw Data" panel — it powers the ShipFusion order detail page''s expandable
        "Raw Data" JSON tree viewer. Unlike `sync-detail`, this NEVER writes to the
        local row; it is a read-only transparency/debugging fetch.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        ShipFusion exposes a single REST API (no GraphQL), so there is one source
        — no REST/GraphQL tabs.


        The `:order` path variable is the SKU primary key (route-model binding). No
        request body, no query params.


        Responses:

        • 200 `{ data: <raw shipment JSON object> }` — the complete shipment payload
        straight from Shipfusion.

        • 200 `{ data: null, unavailable_reason: string }` — Shipfusion answered HTTP
        200 but with `responseStatus: "error"` or a non-empty `errors` array (e.g.
        the order was just submitted and the warehouse has not populated shipment
        detail yet). The frontend shows the `unavailable_reason` message with a Retry
        button.

        • 404 `{ error }` — the order does not belong to the given integration instance.

        • 500 `{ error, message }` — the live fetch to Shipfusion failed (network/timeout/upstream
        error).


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: order
        in: path
        schema:
          type: integer
        required: true
        example: '101'
        description: The order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 Success (raw shipment JSON)
                  value:
                    data:
                      responseStatus: success
                      id: 987654
                      shipmentId: 987654
                      orderNumber: ORD-100245
                      orderReferenceNumber: REF-100245
                      shipmentStatus: shipped
                      warehouse: PA
                      orderDate: '20260620'
                      shipDate: '20260621'
                      salesChannelTitle: Shopify
                      shipmentInstructions: Leave at front door
                      address:
                        firstName: Jane
                        lastName: Doe
                        address1: 123 Market St
                        address2: Suite 400
                        city: Philadelphia
                        state: PA
                        zip: '19103'
                        country: US
                        phoneNumber: +1 215-555-0142
                        emailAddress: jane.doe@example.com
                      shipmentItems:
                      - shipmentItemId: 5511
                        SKU: WIDGET-BLK-01
                        qty: 2
                        itemStatus: shipped
                        lotInformation:
                        - lotNumber: LOT-2026-0420
                      tracking:
                        totalPackages: 1
                        packages:
                        - trackingStatus: Delivered
                          shippingCarrier: UPS
                          shippingService: Ground
                          trackingNumber: 1Z999AA10123456784
                          trackingUrl: https://www.ups.com/track?tracknum=1Z999AA10123456784
                          shipDate: '20260621'
                          dimensions:
                            lengthIn: 12
                            widthIn: 9
                            heightIn: 4
                            weightLb: 2
                            weightOz: 6
                example-1:
                  summary: 200 Unavailable (not synced yet)
                  value:
                    data: null
                    unavailable_reason: Shipfusion has not returned shipment detail
                      for this order yet. This usually means the order was just submitted
                      and the warehouse has not populated it. Try again shortly, or
                      use "Fetch Details from Shipfusion" once it becomes available.
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: Order does not belong to this integration instance
        '500':
          description: Internal Server Error
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                  message:
                    type: string
                example:
                  error: Failed to fetch raw order data from Shipfusion
                  message: 'cURL error 28: Operation timed out after 30000 milliseconds'
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-shipfusion-integration-instances-integration-instance-orders-order-raw
  /api/shipfusion/integration-instances/{integration_instance}/orders/{order}/sync-detail:
    post:
      tags:
      - Shipfusion
      summary: Sync Order Detail
      description: 'Fetch and store the latest detailed order data from the Shipfusion
        API for a specific order.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: order
        in: path
        schema:
          type: integer
        required: true
        example: '101'
        description: The order ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-shipfusion-integration-instances-integration-instance-orders-order-sync-detail
  /api/shipfusion/integration-instances/{integration_instance}/orders/oldest-incomplete:
    get:
      tags:
      - Shipfusion
      summary: Get Oldest Incomplete Order
      description: 'Get the oldest incomplete order for use in the sync modal UI.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shipfusion-integration-instances-integration-instance-orders-oldest-incomplete
  /api/shipfusion/integration-instances/{integration_instance}/orders/sync:
    post:
      tags:
      - Shipfusion
      summary: Sync Orders (Queue Job)
      description: 'Queue a background job to sync all orders from Shipfusion for
        a given date range and optional status.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-shipfusion-integration-instances-integration-instance-orders-sync
  /api/shipfusion/integration-instances/{integration_instance}/orders/sync-progress/{trackedJobLogId}:
    get:
      tags:
      - Shipfusion
      summary: Get Order Sync Progress
      description: 'Get progress of a queued order sync job.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: trackedJobLogId
        in: path
        schema:
          type: integer
        required: true
        example: '42'
        description: The tracked job log ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shipfusion-integration-instances-integration-instance-orders-sync-progress-trackedjoblogid
  /api/shipfusion/integration-instances/{integration_instance}/orders/update-tracking:
    post:
      tags:
      - Shipfusion
      summary: Update Tracking Info
      description: 'Trigger an update of tracking information for all shipped orders
        from this integration instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-shipfusion-integration-instances-integration-instance-orders-update-tracking
  /api/shipfusion/integration-instances/{integration_instance}/packages:
    get:
      tags:
      - Shipfusion
      summary: List Packages
      description: 'Paginated list of packages across all orders for this Shipfusion
        integration instance. Each package is promoted out of its parent order''s
        `json_object.tracking.packages[]` array into its own row so packages are searchable
        by their per-package `tracking_number` (multi-package orders carry distinct
        tracking numbers that the order-level tracking_number drops) — mirroring the
        StarShipIt Order → Package model.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Supports Spatie QueryBuilder filtering, sorting, and pagination.


        Filters:

        - `filter[search]` — partial match across tracking_number, shipfusion_shipment_id,
        carrier_service_name, name, and the parent order''s order_number

        - `filter[delivery_status]` — exact match on delivery status (e.g. Pending,
        InTransit, Delivered)

        - `filter[shipfusion_order_id]` — exact match on the local parent order id
        (shipfusion_orders.id)

        - Advanced per-column operators are available for: id (numeric), tracking_number,
        shipfusion_shipment_id, name, carrier, carrier_service_name, carrier_service_code,
        delivery_status, packaging_type, shipment_type (text), weight (numeric), shipped_at,
        label_created_date, created_at, updated_at (datetime)


        Allowed sorts: id, tracking_number, name, weight, delivery_status, carrier,
        carrier_service_name, packaging_type, shipment_type, shipped_at, label_created_date,
        created_at, updated_at, order (sorts by the related order number) (prefix
        with `-` for DESC; default `-id`).


        Pagination: `page` (default 1), `per_page` (default 10).


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        shipfusion_order_id:
                          type: integer
                        package_index:
                          type: integer
                        shipfusion_shipment_id:
                          type: string
                        name:
                          type: string
                        weight:
                          type: number
                        height:
                          type: integer
                        width:
                          type: integer
                        length:
                          type: integer
                        packaging_type:
                          type: string
                        carrier:
                          type: string
                        carrier_service_code:
                          type: string
                        carrier_service_name:
                          type: string
                        shipping_carrier_code:
                          type: string
                        shipping_method:
                          type: string
                        tracking_number:
                          type: string
                        tracking_url:
                          type: string
                        delivery_status:
                          type: string
                        shipment_type:
                          type: string
                          nullable: true
                        shipped_at:
                          type: string
                        label_created_date:
                          type: string
                          nullable: true
                        order:
                          type: object
                          properties:
                            id:
                              type: integer
                            order_number:
                              type: string
                            shipfusion_id:
                              type: string
                            link_reference:
                              type: string
                            link_type_label:
                              type: string
                            link_id:
                              type: integer
                            link_route:
                              type: string
                        sku_sales_order_fulfillment_id:
                          type: integer
                        sku_fulfillment_id:
                          type: string
                          nullable: true
                        sku_fulfillment_status:
                          type: string
                        sales_order_id:
                          type: integer
                        sales_order_number:
                          type: string
                        sales_order_legacy_url:
                          type: string
                        warehouse:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  next_page_url:
                    type: string
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 91234
                    integration_instance_id: 4
                    shipfusion_order_id: 60012
                    package_index: 0
                    shipfusion_shipment_id: SF-SHIP-88231
                    name: Box 1
                    weight: 0.81
                    height: 3
                    width: 6
                    length: 9
                    packaging_type: box
                    carrier: DHL Global Mail
                    carrier_service_code: ParcelsExpeditedDomestic
                    carrier_service_name: Parcel Expedited Domestic
                    shipping_carrier_code: DHLGlobalMail
                    shipping_method: DHL Global Mail - Parcel Expedited Domestic
                    tracking_number: 1Z999AA10123456784
                    tracking_url: https://webtrack.dhlglobalmail.com/?trackingnumber=1Z999AA10123456784
                    delivery_status: InTransit
                    shipment_type: null
                    shipped_at: '2025-01-28T00:00:00+00:00'
                    label_created_date: null
                    order:
                      id: 60012
                      order_number: LS-100245
                      shipfusion_id: '884412'
                      link_reference: LS-100245
                      link_type_label: Shipfusion Order
                      link_id: 60012
                      link_route: /integrations/shipfusion/4/orders/60012
                    sku_sales_order_fulfillment_id: 33421
                    sku_fulfillment_id: null
                    sku_fulfillment_status: fulfilled
                    sales_order_id: 77810
                    sales_order_number: SO-55231
                    sales_order_legacy_url: /sales-orders/77810
                    warehouse:
                      id: 12
                      name: ShipFusion - Cincinnati
                    created_at: '2025-01-28T14:21:09+00:00'
                    updated_at: '2025-01-28T14:21:09+00:00'
                  current_page: 1
                  first_page_url: '{{protocol}}://{{domain}}/api/shipfusion/integration-instances/{{integration_instance}}/packages?page=1'
                  from: 1
                  last_page: 12
                  last_page_url: '{{protocol}}://{{domain}}/api/shipfusion/integration-instances/{{integration_instance}}/packages?page=12'
                  next_page_url: '{{protocol}}://{{domain}}/api/shipfusion/integration-instances/{{integration_instance}}/packages?page=2'
                  path: '{{protocol}}://{{domain}}/api/shipfusion/integration-instances/{{integration_instance}}/packages'
                  per_page: 10
                  prev_page_url: null
                  to: 10
                  total: 116
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shipfusion-integration-instances-integration-instance-packages
  /api/shipfusion/integration-instances/{integration_instance}/packages/{package}:
    get:
      tags:
      - Shipfusion
      summary: Get Package
      description: 'Fetch a single Shipfusion package by its local id, scoped to the
        integration instance (returns 404 if the package belongs to a different instance).
        The full provider `json_object` for the package is always included on this
        detail endpoint (the endpoint forces `include_json=1`).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Also includes `shipment_items` — the normalized line items for this package''s
        shipment. ShipFusion tracks items at the shipment (order) level rather than
        per physical package, so each item is resolved from the parent order''s `json_object.shipmentItems`
        first, falling back to the package''s own embedded items. Each item carries
        `sku`, `product_id`, `quantity`, `status`, and `lot_number`. `shipment_items`
        is only present when `include_json` is set; the index (List Packages) endpoint
        does not return it.


        Includes SKU.io linkage — the package''s own SalesOrderFulfillment plus the
        parent order''s legacy order→SOF link as a transition fallback — and a cross-link
        payload pointing back at the parent Shipfusion order.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: package
        in: path
        schema:
          type: integer
        required: true
        description: Local shipfusion_packages.id
        example: '91234'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      shipfusion_order_id:
                        type: integer
                      package_index:
                        type: integer
                      shipfusion_shipment_id:
                        type: string
                      name:
                        type: string
                      weight:
                        type: number
                      height:
                        type: integer
                      width:
                        type: integer
                      length:
                        type: integer
                      packaging_type:
                        type: string
                      carrier:
                        type: string
                      carrier_service_code:
                        type: string
                      carrier_service_name:
                        type: string
                      shipping_carrier_code:
                        type: string
                      shipping_method:
                        type: string
                      tracking_number:
                        type: string
                      tracking_url:
                        type: string
                      delivery_status:
                        type: string
                      shipment_type:
                        type: string
                        nullable: true
                      shipped_at:
                        type: string
                      label_created_date:
                        type: string
                        nullable: true
                      order:
                        type: object
                        properties:
                          id:
                            type: integer
                          order_number:
                            type: string
                          shipfusion_id:
                            type: string
                          link_reference:
                            type: string
                          link_type_label:
                            type: string
                          link_id:
                            type: integer
                          link_route:
                            type: string
                      sku_sales_order_fulfillment_id:
                        type: integer
                      sku_fulfillment_id:
                        type: string
                        nullable: true
                      sku_fulfillment_status:
                        type: string
                      sales_order_id:
                        type: integer
                      sales_order_number:
                        type: string
                      sales_order_legacy_url:
                        type: string
                      warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      shipment_items:
                        type: array
                        items:
                          type: object
                          properties:
                            sku:
                              type: string
                            product_id:
                              type: integer
                            quantity:
                              type: integer
                            status:
                              type: string
                            lot_number:
                              type: string
                      json_object:
                        type: object
                        properties:
                          shipmentItems:
                            type: array
                            items:
                              type: object
                              properties:
                                SKU:
                                  type: string
                                productId:
                                  type: integer
                                qty:
                                  type: integer
                                itemStatus:
                                  type: string
                                lotInformation:
                                  type: array
                                  items:
                                    type: object
                                    properties:
                                      lotNumber:
                                        type: string
                          shippingCarrier:
                            type: string
                          shippingService:
                            type: string
                          shippingCarrierCode:
                            type: string
                          shippingServiceCode:
                            type: string
                          shipDate:
                            type: string
                          shipTimestamp:
                            type: integer
                          trackingNumber:
                            type: string
                          trackingUrl:
                            type: string
                          trackingStatus:
                            type: string
                          dimensions:
                            type: object
                            properties:
                              lengthIn:
                                type: integer
                              widthIn:
                                type: integer
                              heightIn:
                                type: integer
                              type:
                                type: string
                              weightOz:
                                type: integer
                              weightLb:
                                type: number
                example:
                  data:
                    id: 91234
                    integration_instance_id: 4
                    shipfusion_order_id: 60012
                    package_index: 0
                    shipfusion_shipment_id: SF-SHIP-88231
                    name: Box 1
                    weight: 0.81
                    height: 3
                    width: 6
                    length: 9
                    packaging_type: box
                    carrier: DHL Global Mail
                    carrier_service_code: ParcelsExpeditedDomestic
                    carrier_service_name: Parcel Expedited Domestic
                    shipping_carrier_code: DHLGlobalMail
                    shipping_method: DHL Global Mail - Parcel Expedited Domestic
                    tracking_number: 1Z999AA10123456784
                    tracking_url: https://webtrack.dhlglobalmail.com/?trackingnumber=1Z999AA10123456784
                    delivery_status: InTransit
                    shipment_type: null
                    shipped_at: '2025-01-28T00:00:00+00:00'
                    label_created_date: null
                    order:
                      id: 60012
                      order_number: LS-100245
                      shipfusion_id: '884412'
                      link_reference: LS-100245
                      link_type_label: Shipfusion Order
                      link_id: 60012
                      link_route: /integrations/shipfusion/4/orders/60012
                    sku_sales_order_fulfillment_id: 33421
                    sku_fulfillment_id: null
                    sku_fulfillment_status: fulfilled
                    sales_order_id: 77810
                    sales_order_number: SO-55231
                    sales_order_legacy_url: /sales-orders/77810
                    warehouse:
                      id: 12
                      name: ShipFusion - Cincinnati
                    created_at: '2025-01-28T14:21:09+00:00'
                    updated_at: '2025-01-28T14:21:09+00:00'
                    shipment_items:
                    - sku: '100233'
                      product_id: 1999637981
                      quantity: 1
                      status: shipped
                      lot_number: '25320'
                    - sku: '100663'
                      product_id: 1999637421
                      quantity: 2
                      status: shipped
                      lot_number: null
                    json_object:
                      shipmentItems:
                      - SKU: '100233'
                        productId: 1999637981
                        qty: 1
                        itemStatus: shipped
                        lotInformation:
                        - lotNumber: '25320'
                      - SKU: '100663'
                        productId: 1999637421
                        qty: 2
                        itemStatus: shipped
                        lotInformation: []
                      shippingCarrier: DHL Global Mail
                      shippingService: Parcel Expedited Domestic
                      shippingCarrierCode: DHLGlobalMail
                      shippingServiceCode: ParcelsExpeditedDomestic
                      shipDate: '20250128'
                      shipTimestamp: 1762273047
                      trackingNumber: 1Z999AA10123456784
                      trackingUrl: https://webtrack.dhlglobalmail.com/?trackingnumber=1Z999AA10123456784
                      trackingStatus: InTransit
                      dimensions:
                        lengthIn: 9
                        widthIn: 6
                        heightIn: 3
                        type: box
                        weightOz: 13
                        weightLb: 0.81
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Package not found for this instance
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-shipfusion-integration-instances-integration-instance-packages-package
  /api/shipfusion/integration-instances/{integration_instance}/warehouse-shipments:
    get:
      tags:
      - Shipfusion
      summary: List Warehouse Shipments
      description: 'List all warehouse shipments (inbound) for a Shipfusion integration
        instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shipfusion-integration-instances-integration-instance-warehouse-shipments
  /api/shipfusion/integration-instances/{integration_instance}/warehouse-shipments/{warehouse_shipment}:
    get:
      tags:
      - Shipfusion
      summary: Get Warehouse Shipment
      description: 'Get a specific warehouse shipment by its Shipfusion ID.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: warehouse_shipment
        in: path
        schema:
          type: string
        required: true
        description: Shipfusion warehouse shipment number
        example: WS-5001
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shipfusion-integration-instances-integration-instance-warehouse-shipments-warehouse-shipment
  /api/shipfusion/integration-instances/{integration_instance}/warehouse-shipments/{warehouse_shipment}/detail:
    get:
      tags:
      - Shipfusion
      summary: Get Warehouse Shipment Detail (JSON)
      description: 'Get the full raw JSON detail for a warehouse shipment as returned
        by the Shipfusion API.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: warehouse_shipment
        in: path
        schema:
          type: integer
        required: true
        example: '201'
        description: The warehouse shipment ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shipfusion-integration-instances-integration-instance-warehouse-shipments-warehouse-shipment-detail
  /api/shipfusion/integration-instances/{integration_instance}/warehouse-shipments/{warehouse_shipment}/sync-detail:
    post:
      tags:
      - Shipfusion
      summary: Sync Warehouse Shipment Detail
      description: 'Fetch and store the latest detailed data for a warehouse shipment
        from the Shipfusion API.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: warehouse_shipment
        in: path
        schema:
          type: integer
        required: true
        example: '201'
        description: The warehouse shipment ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-shipfusion-integration-instances-integration-instance-warehouse-shipments-warehouse-shipment-sync-detail
  /api/shipfusion/integration-instances/{integration_instance}/warehouse-shipments/sync:
    post:
      tags:
      - Shipfusion
      summary: Sync Warehouse Shipments (Queue Job)
      description: 'Queue a background job to sync all warehouse shipments from Shipfusion
        for a given date range.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-shipfusion-integration-instances-integration-instance-warehouse-shipments-sync
  /api/shipfusion/integration-instances/{integration_instance}/warehouse-shipments/sync-progress/{trackedJobLogId}:
    get:
      tags:
      - Shipfusion
      summary: Get Warehouse Shipment Sync Progress
      description: 'Get progress of a queued warehouse shipment sync job.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: trackedJobLogId
        in: path
        schema:
          type: integer
        required: true
        example: '43'
        description: The tracked job log ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shipfusion-integration-instances-integration-instance-warehouse-shipments-sync-progress-trackedjoblogid
  /api/shipfusion/integration-instances/{integration_instance}/webhook-events:
    get:
      tags:
      - Shipfusion
      summary: List Webhook Events
      description: 'List all Shipfusion webhook events for an integration instance,
        with pagination.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shipfusion-integration-instances-integration-instance-webhook-events
  /api/shipfusion/integration-instances/{integration_instance}/webhook-events/{webhook_event}:
    get:
      tags:
      - Shipfusion
      summary: Show Webhook Event
      description: 'Get a single Shipfusion webhook event by ID.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: webhook_event
        in: path
        schema:
          type: integer
        required: true
        example: '301'
        description: The webhook event ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shipfusion-integration-instances-integration-instance-webhook-events-webhook-event
  /api/shipfusion/integration-instances/{integration_instance}/webhook-events/{webhook_event}/retry:
    post:
      tags:
      - Shipfusion
      summary: Retry Webhook Event
      description: 'Retry processing an unprocessed Shipfusion webhook event.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: webhook_event
        in: path
        schema:
          type: integer
        required: true
        example: '301'
        description: The webhook event ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-shipfusion-integration-instances-integration-instance-webhook-events-webhook-event-retry
  /api/shipfusion/integration-instances/{integration_instance}/inventory/refresh:
    post:
      tags:
      - Shipfusion
      summary: Refresh Inventory
      description: 'Refresh inventory data from the Shipfusion API for a specific
        warehouse.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                warehouse:
                  type: string
              example:
                warehouse: IL
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-shipfusion-integration-instances-integration-instance-inventory-refresh
  /api/shipfusion/integration-instances/{integration_instance}/inventory/discrepancies:
    get:
      tags:
      - Shipfusion
      summary: Get Inventory Discrepancies
      description: 'Get inventory discrepancies between SKU.io quantities and Shipfusion
        quantities.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shipfusion-integration-instances-integration-instance-inventory-discrepancies
  /api/shipfusion/integration-instances/{integration_instance}/inventory/without-sku-products:
    get:
      tags:
      - Shipfusion
      summary: Get Items Without SKU Products
      description: 'Get Shipfusion inventory items that do not have a corresponding
        SKU.io product.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shipfusion-integration-instances-integration-instance-inventory-without-sku-products
  /api/shipfusion/integration-instances/{integration_instance}/inventory/without-shipfusion-inventory:
    get:
      tags:
      - Shipfusion
      summary: Get Products Without Shipfusion Inventory
      description: 'Get SKU.io products that do not have a corresponding Shipfusion
        inventory record.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shipfusion-integration-instances-integration-instance-inventory-without-shipfusion-inventory
  /api/shipfusion/integration-instances/{integration_instance}/inventory/create-stock-take:
    post:
      tags:
      - Shipfusion
      summary: Create Stock Take from Discrepancies
      description: 'Create a SKU.io stock take from selected Shipfusion inventory
        discrepancies.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                product_ids:
                  type: array
                  items:
                    type: integer
                notes:
                  type: string
                date:
                  type: string
                status:
                  type: string
              example:
                product_ids:
                - 12
                - 15
                - 22
                notes: Stock take created from Shipfusion discrepancy report
                date: '2024-01-15'
                status: draft
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-shipfusion-integration-instances-integration-instance-inventory-create-stock-take
  /api/shipfusion/integration-instances/{integration_instance}/inventory/product-movements:
    get:
      tags:
      - Shipfusion
      summary: Get Product Inventory Movements
      description: 'Get recent inventory movements for a specific product across warehouses
        mapped to this Shipfusion integration.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: product_id
        in: query
        schema:
          type: integer
        example: '12'
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shipfusion-integration-instances-integration-instance-inventory-product-movements
  /api/shipfusion/integration-instances/{integration_instance}/inventory/last-synced-at:
    get:
      tags:
      - Shipfusion
      summary: Get Last Synced At
      description: 'Get the timestamp of the last successful inventory sync from Shipfusion.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shipfusion-integration-instances-integration-instance-inventory-last-synced-at
  /api/shiphero/integration-instances:
    post:
      tags:
      - ShipHero
      summary: Create Integration Instance
      description: 'Create a new ShipHero integration instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                integration_id:
                  type: integer
                connection_settings:
                  type: object
                  properties: {}
                integration_settings:
                  type: object
                  properties:
                    connection_name:
                      type: string
                    enable_fulfillment:
                      type: boolean
                is_automatic_sync_enabled:
                  type: boolean
              example:
                name: ShipHero Production
                integration_id: 8
                connection_settings: {}
                integration_settings:
                  connection_name: main
                  enable_fulfillment: true
                is_automatic_sync_enabled: false
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-shiphero-integration-instances
  /api/shiphero/integration-instances/{integration_instance}:
    get:
      tags:
      - ShipHero
      summary: Show Integration Instance
      description: 'Retrieve a ShipHero integration instance by ID.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        example: '8'
        description: The integration instance ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shiphero-integration-instances-integration-instance
    put:
      tags:
      - ShipHero
      summary: Update Integration Instance
      description: 'Update a ShipHero integration instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                integration_id:
                  type: integer
                connection_settings:
                  type: object
                  properties: {}
                integration_settings:
                  type: object
                  properties:
                    connection_name:
                      type: string
                    enable_fulfillment:
                      type: boolean
                is_automatic_sync_enabled:
                  type: boolean
              example:
                name: ShipHero Production
                integration_id: 8
                connection_settings: {}
                integration_settings:
                  connection_name: main
                  enable_fulfillment: true
                is_automatic_sync_enabled: true
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        example: '8'
        description: The integration instance ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-shiphero-integration-instances-integration-instance
    delete:
      tags:
      - ShipHero
      summary: Delete Integration Instance
      description: 'Delete a ShipHero integration instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        example: '8'
        description: The integration instance ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-shiphero-integration-instances-integration-instance
  /api/shiphero/integration-instances/{integration_instance}/dashboard:
    get:
      tags:
      - ShipHero
      summary: Show Dashboard Metrics
      description: 'Aggregated dashboard metrics for the ShipHero integration instance:
        order counts grouped by fulfillment status, total orders, mapped warehouse
        count, last sync timestamps, sync cadence, and webhook health.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        example: '8'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      orders_by_status:
                        type: object
                        properties:
                          pending:
                            type: integer
                          fulfilled:
                            type: integer
                          canceled:
                            type: integer
                      total_orders:
                        type: integer
                      warehouse_count:
                        type: integer
                      orders_last_synced_at:
                        type: string
                      tracking_info_last_updated_at:
                        type: string
                      sync_frequency:
                        type: string
                      tracking_update_frequency:
                        type: string
                      webhook_health:
                        type: object
                        properties:
                          registered:
                            type: boolean
                          last_received_at:
                            type: string
                example:
                  data:
                    orders_by_status:
                      pending: 12
                      fulfilled: 340
                      canceled: 5
                    total_orders: 357
                    warehouse_count: 3
                    orders_last_synced_at: '2026-06-15T08:02:11.000000Z'
                    tracking_info_last_updated_at: '2026-06-15T08:10:00.000000Z'
                    sync_frequency: On demand
                    tracking_update_frequency: Every 10 minutes
                    webhook_health:
                      registered: true
                      last_received_at: '2026-06-14T22:45:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shiphero-integration-instances-integration-instance-dashboard
  /api/shiphero/integration-instances/{integration_instance}/warehouses:
    get:
      tags:
      - ShipHero
      summary: List Warehouses
      description: 'List all ShipHero warehouses alongside local SKU.io warehouses.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        example: '8'
        description: The integration instance ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shiphero-integration-instances-integration-instance-warehouses
  /api/shiphero/integration-instances/{integration_instance}/warehouses/download:
    get:
      tags:
      - ShipHero
      summary: Download Warehouses from ShipHero
      description: 'Fetch and cache warehouses from the ShipHero API.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        example: '8'
        description: The integration instance ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shiphero-integration-instances-integration-instance-warehouses-download
  /api/shiphero/integration-instances/{integration_instance}/warehouses/map:
    put:
      tags:
      - ShipHero
      summary: Map Warehouses
      description: 'Map ShipHero warehouses to SKU.io local warehouses.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                payload:
                  type: array
                  items:
                    type: object
                    properties:
                      id:
                        type: integer
                      warehouse_id:
                        type: integer
              example:
                payload:
                - id: 1
                  warehouse_id: 1
                - id: 2
                  warehouse_id: 2
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        example: '8'
        description: The integration instance ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-shiphero-integration-instances-integration-instance-warehouses-map
  /api/shiphero/integration-instances/{integration_instance}/inventory/refresh:
    post:
      tags:
      - ShipHero
      summary: Refresh Inventory
      description: 'Trigger a full inventory sync from ShipHero API.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                warehouse_id:
                  type: integer
              example:
                warehouse_id: 1
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        example: '8'
        description: The integration instance ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-shiphero-integration-instances-integration-instance-inventory-refresh
  /api/shiphero/integration-instances/{integration_instance}/inventory/discrepancies:
    get:
      tags:
      - ShipHero
      summary: Get Inventory Discrepancies
      description: 'Get inventory discrepancies between SKU.io and ShipHero.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: warehouse_id
        in: query
        schema:
          type: integer
        example: '1'
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        example: '8'
        description: The integration instance ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shiphero-integration-instances-integration-instance-inventory-discrepancies
  /api/shiphero/integration-instances/{integration_instance}/inventory/without-sku-products:
    get:
      tags:
      - ShipHero
      summary: Get Items Without SKU Products
      description: 'List ShipHero inventory items that do not have a matching SKU.io
        product.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: warehouse_id
        in: query
        schema:
          type: integer
        example: '1'
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        example: '8'
        description: The integration instance ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shiphero-integration-instances-integration-instance-inventory-without-sku-products
  /api/shiphero/integration-instances/{integration_instance}/inventory/without-shiphero-inventory:
    get:
      tags:
      - ShipHero
      summary: Get SKU Products Without ShipHero Inventory
      description: 'List SKU.io products that do not have corresponding inventory
        records in ShipHero.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: warehouse_id
        in: query
        schema:
          type: integer
        example: '1'
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        example: '8'
        description: The integration instance ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shiphero-integration-instances-integration-instance-inventory-without-shiphero-inventory
  /api/shiphero/integration-instances/{integration_instance}/inventory/last-synced-at:
    get:
      tags:
      - ShipHero
      summary: Get Last Synced At
      description: 'Get the timestamp of the most recent successful inventory sync
        from ShipHero.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        example: '8'
        description: The integration instance ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shiphero-integration-instances-integration-instance-inventory-last-synced-at
  /api/shiphero/integration-instances/{integration_instance}/inventory/create-stock-take:
    post:
      tags:
      - ShipHero
      summary: Create Stock Take From Discrepancies
      description: 'Create a SKU.io stock take from the selected ShipHero inventory
        discrepancies. The stock take counts each product at its ShipHero on-hand
        quantity.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Request Body:**


        | Field | Type | Required | Description |

        | --- | --- | --- | --- |

        | product_ids | array of integers | optional | Product IDs to include. Each
        must exist in `products`. **Empty array (or omitted) = "stock take all"**:
        every visible discrepancy is included (kits excluded by default — see `include_kits`).
        |

        | warehouse_id | integer | optional | Warehouse to scope discrepancies to.
        Must exist in `warehouses`. Defaults to the first mapped warehouse. |

        | notes | string | optional | Custom notes (max 500 chars). Defaults to an
        auto-generated note referencing the warehouse. |

        | date | string | optional | Stock take date in `Y-m-d` format. Defaults to
        today. |

        | status | string | optional | One of `draft`, `open`, `closed`. Defaults
        to `draft`. `open` initiates the count; `closed` initiates and finalizes it.
        |

        | include_kits | boolean | optional | Default `false`. Only meaningful for
        a "stock take all" (empty `product_ids`). ShipHero reports 0 on hand for kit
        SKUs (inventory lives on the components), so kits are excluded by default
        to avoid zeroing out their SKU.io on-hand inventory. Set `true` to include
        them anyway; `excluded_kit_count` in the response will then be 0. |


        **Response (`data`):**


        | Field | Type | Description |

        | --- | --- | --- |

        | stock_take | object | The created stock take record. |

        | stock_take_url | string | Tenant URL to the stock take detail page (`/v2/inventory/stock-takes/{id}`).
        |

        | selected_count | integer | Number of discrepancies included in the stock
        take. |

        | total_value_adjustment | string | Sum of discrepancy values, formatted to
        2 decimal places. |

        | excluded_kit_count | integer | Number of kit SKUs excluded from a "stock
        take all" (0 when `include_kits` is true or when specific `product_ids` were
        given). |


        **Errors:** Returns `422` with a `message` when no warehouse mapping exists,
        no discrepancies match the criteria, or the specified warehouse is not mapped.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                product_ids:
                  type: array
                  items:
                    type: integer
                warehouse_id:
                  type: integer
                notes:
                  type: string
                date:
                  type: string
                status:
                  type: string
                include_kits:
                  type: boolean
              example:
                product_ids:
                - 42
                - 57
                - 88
                warehouse_id: 1
                notes: Stock take from ShipHero discrepancies May 2024
                date: '2024-05-01'
                status: draft
                include_kits: false
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        example: '8'
        description: The integration instance ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-shiphero-integration-instances-integration-instance-inventory-create-stock-take
  /api/shiphero/integration-instances/{integration_instance}/inventory/product-movements:
    get:
      tags:
      - ShipHero
      summary: Get Product Inventory Movements
      description: 'Get recent inventory movements for a specific product in ShipHero-mapped
        warehouses.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: product_id
        in: query
        schema:
          type: integer
        example: '42'
      - name: limit
        in: query
        schema:
          type: integer
        example: '10'
        description: Maximum number of results to return.
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        example: '8'
        description: The integration instance ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shiphero-integration-instances-integration-instance-inventory-product-movements
  /api/shiphero/integration-instances/{integration_instance}/orders:
    get:
      tags:
      - ShipHero
      summary: List Orders
      description: 'List ShipHero orders for the integration instance, newest first.
        Canonical list view endpoint (Spatie QueryBuilder); returns a paginated list
        of lightweight order rows.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Quick search (filter[search]): matches ID (exact), order number (partial),
        and ShipHero ID (partial). Restrict which columns are searched with search_columns
        (allowed: id, order_number, shiphero_id); force exact matching on a column
        with search_strict_columns.


        Filters (all optional):

        - filter[fulfillment_status]: exact ShipHero fulfillment_status (pending,
        fulfilled, canceled).

        - filter[has_fulfillment]: true/1 = linked to a SKU.io fulfillment; false/0
        = unlinked; omit for all.

        - filter[sku_fulfillment_id]: exact linked SalesOrderFulfillment id.

        - Per-column advanced filters with operators: filter[id], filter[order_number],
        filter[shiphero_id], filter[fulfillment_status], filter[created_at], filter[updated_at].


        Sort (sort): id, order_number, fulfillment_status, created_at, updated_at.
        Prefix with - for descending. Default: -id.

        Pagination: page, per_page (default 10).


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        example: '8'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        shiphero_id:
                          type: string
                        order_number:
                          type: string
                        fulfillment_status:
                          type: string
                        fulfillment_status_label:
                          type: string
                        fulfillment_status_color:
                          type: string
                        order_date:
                          type: string
                        tracking_number:
                          type: string
                        tracking_url:
                          type: string
                        carrier:
                          type: string
                        shipped_at:
                          type: string
                        sku_fulfillment:
                          type: object
                          properties:
                            id:
                              type: integer
                            link_reference:
                              type: string
                            link_type_label:
                              type: string
                            link_id:
                              type: integer
                            link_route:
                              type: string
                            status:
                              type: string
                            sales_order_id:
                              type: integer
                            sales_order_number:
                              type: string
                            fulfillment_order_id:
                              type: integer
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  per_page:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                  last_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 1024
                    integration_instance_id: 8
                    shiphero_id: T3JkZXI6MTIzNDU2
                    order_number: SO-100245
                    fulfillment_status: fulfilled
                    fulfillment_status_label: Fulfilled
                    fulfillment_status_color: success
                    order_date: '2026-06-10'
                    tracking_number: 1Z999AA10123456784
                    tracking_url: https://www.ups.com/track?tracknum=1Z999AA10123456784
                    carrier: UPS
                    shipped_at: '2026-06-11T14:32:00.000000Z'
                    sku_fulfillment:
                      id: 55231
                      link_reference: FUL-100245
                      link_type_label: Sales Order Fulfillment
                      link_id: 55231
                      link_route: /orders/sales-orders/fulfillments/55231
                      status: shipped
                      sales_order_id: 4021
                      sales_order_number: SO-100245
                      fulfillment_order_id: 9876
                    created_at: '2026-06-10T09:15:00.000000Z'
                    updated_at: '2026-06-11T14:32:05.000000Z'
                  - id: 1025
                    integration_instance_id: 8
                    shiphero_id: T3JkZXI6MTIzNDU3
                    order_number: SO-100246
                    fulfillment_status: pending
                    fulfillment_status_label: Pending
                    fulfillment_status_color: warning
                    order_date: '2026-06-12'
                    tracking_number: null
                    tracking_url: null
                    carrier: null
                    shipped_at: null
                    sku_fulfillment: null
                    created_at: '2026-06-12T10:00:00.000000Z'
                    updated_at: '2026-06-12T10:00:00.000000Z'
                  current_page: 1
                  per_page: 10
                  from: 1
                  to: 2
                  last_page: 1
                  total: 2
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shiphero-integration-instances-integration-instance-orders
  /api/shiphero/integration-instances/{integration_instance}/orders/{order}:
    get:
      tags:
      - ShipHero
      summary: Show Order
      description: 'Get a single ShipHero order by its ShipHero id (the `shiphero_id`,
        not the local row id).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        example: '8'
        description: The integration instance ID.
      - name: order
        in: path
        schema:
          type: string
        required: true
        example: T3JkZXI6MTIzNDU2
        description: The order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      shiphero_id:
                        type: string
                      order_number:
                        type: string
                      fulfillment_status:
                        type: string
                      sku_fulfillment_id:
                        type: integer
                      has_fulfillment:
                        type: boolean
                      order_date:
                        type: string
                      tracking_number:
                        type: string
                      carrier:
                        type: string
                      shipped_at:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 1024
                    integration_instance_id: 8
                    shiphero_id: T3JkZXI6MTIzNDU2
                    order_number: SO-100245
                    fulfillment_status: fulfilled
                    sku_fulfillment_id: 55231
                    has_fulfillment: true
                    order_date: '2026-06-10'
                    tracking_number: 1Z999AA10123456784
                    carrier: UPS
                    shipped_at: '2026-06-11T14:32:00.000000Z'
                    created_at: '2026-06-10T09:15:00.000000Z'
                    updated_at: '2026-06-11T14:32:05.000000Z'
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: array
                    items:
                      type: object
                      properties:
                        message:
                          type: string
                        code:
                          type: string
                        key:
                          type: string
                example:
                  errors:
                  - message: Order not found
                    code: OrderNotFound
                    key: order
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-shiphero-integration-instances-integration-instance-orders-order
  /api/shiphero/integration-instances/{integration_instance}/orders/{order}/detail:
    get:
      tags:
      - ShipHero
      summary: Get Order Detail
      description: 'Get the full decoded ShipHero JSON object for an order (by local
        row id via route-model binding). `has_detailed_data` is false when no raw
        payload has been cached yet.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        example: '8'
        description: The integration instance ID.
      - name: order
        in: path
        schema:
          type: integer
        required: true
        example: '1024'
        description: The order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      json_object:
                        type: object
                        properties:
                          order_number:
                            type: string
                          fulfillment_status:
                            type: string
                          order_date:
                            type: string
                          shipping_labels:
                            type: array
                            items:
                              type: object
                              properties:
                                tracking_number:
                                  type: string
                                carrier:
                                  type: string
                                created_date:
                                  type: string
                      has_detailed_data:
                        type: boolean
                example:
                  data:
                    json_object:
                      order_number: SO-100245
                      fulfillment_status: fulfilled
                      order_date: '2026-06-10T09:15:00+00:00'
                      shipping_labels:
                      - tracking_number: 1Z999AA10123456784
                        carrier: UPS
                        created_date: '2026-06-11T14:32:00+00:00'
                    has_detailed_data: true
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: array
                    items:
                      type: object
                      properties:
                        message:
                          type: string
                        code:
                          type: string
                        key:
                          type: string
                example:
                  errors:
                  - message: Order not found
                    code: OrderNotFound
                    key: order
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-shiphero-integration-instances-integration-instance-orders-order-detail
  /api/shiphero/integration-instances/{integration_instance}/orders/sync:
    post:
      tags:
      - ShipHero
      summary: Sync Orders
      description: 'Queue a tracked background job that re-syncs every open order
        for the integration instance and applies any new tracking. Returns the tracked
        job log id so the frontend can poll progress.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        If a sync is already pending/processing for this instance, responds 409 SyncInProgress.


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        example: '8'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 9912
                  message: Order sync job has been queued
        '409':
          description: Conflict
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: array
                    items:
                      type: object
                      properties:
                        message:
                          type: string
                        code:
                          type: string
                        key:
                          type: string
                example:
                  errors:
                  - message: An order sync is already in progress for this integration
                    code: SyncInProgress
                    key: sync
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-shiphero-integration-instances-integration-instance-orders-sync
  /api/shiphero/integration-instances/{integration_instance}/orders/sync-progress/{trackedJobLogId}:
    get:
      tags:
      - ShipHero
      summary: Get Order Sync Progress
      description: 'Fetch the progress of a queued order sync job by its tracked job
        log id.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        example: '8'
        description: The integration instance ID.
      - name: trackedJobLogId
        in: path
        schema:
          type: integer
        required: true
        example: '9912'
        description: The tracked job log ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      job_type:
                        type: string
                      queue:
                        type: string
                      job_name:
                        type: string
                      status:
                        type: string
                      related_model:
                        type: object
                        properties:
                          id:
                            type: integer
                          type:
                            type: string
                          reference:
                            type: string
                      related_model_reference:
                        type: string
                      messages:
                        type: array
                      attempted_at:
                        type: string
                      completed_at:
                        type: string
                        nullable: true
                      duration:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      results:
                        type: string
                        nullable: true
                      total_items:
                        type: integer
                      processed_items:
                        type: integer
                      progress_percentage:
                        type: number
                      progress_mode:
                        type: string
                      stages:
                        type: string
                        nullable: true
                example:
                  data:
                    id: 9912
                    job_type: tenant_aware
                    queue: default
                    job_name: 'Sync Shiphero Orders: ShipHero Main'
                    status: processing
                    related_model:
                      id: 8
                      type: Modules\Shiphero\Entities\ShipheroIntegrationInstance
                      reference: ShipHero Main
                    related_model_reference: ShipHero Main
                    messages: []
                    attempted_at: '2026-06-15T08:02:00.000000Z'
                    completed_at: null
                    duration: null
                    created_at: '2026-06-15T08:01:59.000000Z'
                    updated_at: '2026-06-15T08:02:30.000000Z'
                    results: null
                    total_items: 357
                    processed_items: 120
                    progress_percentage: 33.61
                    progress_mode: count
                    stages: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shiphero-integration-instances-integration-instance-orders-sync-progress-trackedjoblogid
  /api/shiphero/integration-instances/{integration_instance}/orders/import:
    post:
      tags:
      - ShipHero
      summary: Import Orders
      description: 'Queue a tracked background job that **imports** orders from ShipHero
        within a date window — treating ShipHero as an order *source*, not just a
        fulfillment target. Each imported order is FK-linked to its matching SKU entity
        by `order_number` (writing the real `sku_fulfillment_order_id` / `sku_fulfillment_id`);
        true orphans are imported unlinked.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Returns the tracked job log id so the frontend can poll progress (via Get
        Order Sync Progress).


        If an import is already pending/processing for this instance, responds 409
        ImportInProgress.


        **Request body (all optional):**

        - `mode` — fetch mode: `since_latest` | `from_start_date` | `date_range` |
        `all`. Defaults to `all` (unbounded full re-sync of the entire order history).

        - `date_from` — ISO date; the window start for `from_start_date` and `date_range`.

        - `date_to` — ISO date; the window end for `date_range`.

        - `date_method` — `created` | `updated`. For `date_range`, selects which ShipHero
        timestamp the window filters on (default `created`).

        - `latest_date` — ISO date anchor for `since_latest` (falls back to the stored
        last-sync cursor).


        **Mode → window mapping:** `since_latest` → `updated_from` = latest_date/cursor;
        `from_start_date` → `order_date_from` = date_from; `date_range` (created)
        → `order_date_from`/`order_date_to`; `date_range` (updated) → `updated_from`/`updated_to`;
        `all` → unbounded.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                mode:
                  type: string
                date_from:
                  type: string
                date_to:
                  type: string
                date_method:
                  type: string
                latest_date:
                  type: string
              example:
                mode: date_range
                date_from: '2026-06-01'
                date_to: '2026-06-30'
                date_method: created
                latest_date: '2026-06-15T08:00:00Z'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        example: '8'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 9913
                  message: Order import job has been queued
        '409':
          description: Conflict
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: array
                    items:
                      type: object
                      properties:
                        message:
                          type: string
                        code:
                          type: string
                        key:
                          type: string
                example:
                  errors:
                  - message: An order import is already in progress for this integration
                    code: ImportInProgress
                    key: import
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      mode:
                        type: array
                        items:
                          type: string
                example:
                  message: The selected mode is invalid.
                  errors:
                    mode:
                    - The selected mode is invalid.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-shiphero-integration-instances-integration-instance-orders-import
  /api/shiphero/integration-instances/{integration_instance}/orders/import-info:
    get:
      tags:
      - ShipHero
      summary: Get Order Import Info
      description: 'Import UI metadata for the shared Refresh Orders modal:

        - `last_synced_at` — the "since latest" anchor. Prefers the persisted import
        cursor, falling back to the most recently imported order''s `updated_at` when
        no cursor has been recorded yet.

        - `latest_identifier` — the most recently imported order''s `order_number`
        (null when no orders exist).

        - `total_orders` — total imported order count for the instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        example: '8'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      last_synced_at:
                        type: string
                      latest_identifier:
                        type: string
                      total_orders:
                        type: integer
                example:
                  data:
                    last_synced_at: '2026-06-29T22:14:05.000000Z'
                    latest_identifier: SO-1042.1
                    total_orders: 1284
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shiphero-integration-instances-integration-instance-orders-import-info
  /api/shiphero/integration-instances/{integration_instance}/orders/search:
    post:
      tags:
      - ShipHero
      summary: Search Orders by Number
      description: Search ShipHero live for an order by its order number and return
        whether it already exists locally. Use this to pull a specific order the incremental
        import misses — e.g. a manual or backdated order created earlier than the
        last synced order (which "fetch new since latest" can never reach). Requires
        a Bearer token.
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                query:
                  type: string
              example:
                query: '129120541727222.1'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        example: '38'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: string
                        name:
                          type: string
                        email:
                          type: string
                          nullable: true
                        createdAt:
                          type: string
                          nullable: true
                        financialStatus:
                          type: string
                          nullable: true
                        fulfillmentStatus:
                          type: string
                        totalPrice:
                          type: string
                          nullable: true
                        currency:
                          type: string
                          nullable: true
                        existsInDatabase:
                          type: boolean
                example:
                  data:
                  - id: T3JkZXI6OTk5
                    name: '129120541727222.1'
                    email: null
                    createdAt: null
                    financialStatus: null
                    fulfillmentStatus: fulfilled
                    totalPrice: null
                    currency: null
                    existsInDatabase: false
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-shiphero-integration-instances-integration-instance-orders-search
  /api/shiphero/integration-instances/{integration_instance}/orders/refresh-order:
    post:
      tags:
      - ShipHero
      summary: Import Single Order
      description: Import (or update) a single ShipHero order by its ShipHero id —
        the `id` returned by Search Orders by Number. Fetches the order live and persists
        it locally, linking it to a matching sales-order fulfillment when the order
        number lines up. Requires a Bearer token.
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                uniqueId:
                  type: string
              example:
                uniqueId: T3JkZXI6OTk5
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        example: '38'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      order_number:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 41
                    order_number: '129120541727222.1'
                  message: Order imported from ShipHero
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-shiphero-integration-instances-integration-instance-orders-refresh-order
  /api/shiphero/integration-instances/{integration_instance}/orders/{order}/sync-detail:
    post:
      tags:
      - ShipHero
      summary: Sync Single Order Detail
      description: 'Re-fetch a single order from ShipHero and apply any new tracking.
        Orders linked to a SalesOrderFulfillment refresh their tracking; FO-first
        orders (the deferred-shipment path — linked only to a FulfillmentOrder, not
        yet to a fulfillment) get their thin order_create stub enriched with the full
        order GET. Returns 422 OrderNotLinked only when the order is linked to neither
        a fulfillment nor a fulfillment order.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        example: '8'
        description: The integration instance ID.
      - name: order
        in: path
        schema:
          type: integer
        required: true
        example: '1024'
        description: The order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      shiphero_id:
                        type: string
                      order_number:
                        type: string
                      fulfillment_status:
                        type: string
                      sku_fulfillment_id:
                        type: integer
                      has_fulfillment:
                        type: boolean
                      order_date:
                        type: string
                      tracking_number:
                        type: string
                      carrier:
                        type: string
                      shipped_at:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 1024
                    integration_instance_id: 8
                    shiphero_id: T3JkZXI6MTIzNDU2
                    order_number: SO-100245
                    fulfillment_status: fulfilled
                    sku_fulfillment_id: 55231
                    has_fulfillment: true
                    order_date: '2026-06-10'
                    tracking_number: 1Z999AA10123456784
                    carrier: UPS
                    shipped_at: '2026-06-11T14:32:00.000000Z'
                    created_at: '2026-06-10T09:15:00.000000Z'
                    updated_at: '2026-06-11T14:32:05.000000Z'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: array
                    items:
                      type: object
                      properties:
                        message:
                          type: string
                        code:
                          type: string
                        key:
                          type: string
                example:
                  errors:
                  - message: Order is not linked to a fulfillment
                    code: OrderNotLinked
                    key: order
        '500':
          description: Internal Server Error
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: array
                    items:
                      type: object
                      properties:
                        message:
                          type: string
                        code:
                          type: string
                        key:
                          type: string
                example:
                  errors:
                  - message: ShipHero API request failed
                    code: SyncDetailFailed
                    key: order
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-shiphero-integration-instances-integration-instance-orders-order-sync-detail
  /api/shiphero/update-order/{sales_order_fulfillment}:
    put:
      tags:
      - ShipHero
      summary: Update Order From Fulfillment (Power User)
      description: 'Re-push a sales order fulfillment to ShipHero. Requires Power
        User role.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token + is_power_user middleware.'
      requestBody:
        content: {}
      parameters:
      - name: sales_order_fulfillment
        in: path
        schema:
          type: integer
        required: true
        example: '202'
        description: The sales order fulfillment ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-shiphero-update-order-sales-order-fulfillment
  /api/shiphero/integration-instances/{integration_instance}/orders/{order}/activity-log:
    get:
      tags:
      - ShipHero
      summary: Get Order Activity Log
      description: 'Paginated Spatie activity-log entries for a single ShipHero order
        (by local row id) — the order detail page''s Activity Log section. Each entry:
        id, description, event (created/updated/deleted), subject_type, subject_id,
        properties (changed attributes), causer_name, created_at. Ordered newest first.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Pagination: page (default 1), per_page (default 15).


        Authentication: Requires Bearer token.


        Filters: filter[event] (exact event), filter[source] (matches properties->source),
        filter[batch_uuid] (exact batch uuid), filter[search] (LIKE over causer name
        / properties / event).'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        example: '8'
        description: The integration instance ID.
      - name: order
        in: path
        schema:
          type: integer
        required: true
        example: '1024'
        description: The order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        description:
                          type: string
                        event:
                          type: string
                        subject_type:
                          type: string
                        subject_id:
                          type: integer
                        properties:
                          type: object
                          properties:
                            attributes:
                              type: object
                              properties:
                                fulfillment_status:
                                  type: string
                            old:
                              type: object
                              properties:
                                fulfillment_status:
                                  type: string
                        causer_name:
                          type: string
                        created_at:
                          type: string
                  current_page:
                    type: integer
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 90412
                    description: updated
                    event: updated
                    subject_type: ShipheroOrder
                    subject_id: 1024
                    properties:
                      attributes:
                        fulfillment_status: fulfilled
                      old:
                        fulfillment_status: pending
                    causer_name: Sync Job
                    created_at: '2026-06-11T14:33:00.000000Z'
                  - id: 90380
                    description: created
                    event: created
                    subject_type: ShipheroOrder
                    subject_id: 1024
                    properties:
                      attributes:
                        order_number: SO-100245
                    causer_name: null
                    created_at: '2026-06-10T09:15:00.000000Z'
                  current_page: 1
                  first_page_url: '{{protocol}}://{{domain}}/api/shiphero/...?page=1'
                  from: 1
                  last_page: 1
                  per_page: 15
                  to: 2
                  total: 2
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: array
                    items:
                      type: object
                      properties:
                        message:
                          type: string
                        code:
                          type: string
                        key:
                          type: string
                example:
                  errors:
                  - message: Order not found
                    code: OrderNotFound
                    key: order
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-shiphero-integration-instances-integration-instance-orders-order-activity-log
  /api/shiphero/integration-instances/{integration_instance}/shipments:
    get:
      tags:
      - ShipHero
      summary: List Shipments
      description: 'Server-side paginated + filterable ShipHero shipments. Filters:
        carrier (exact), shipping_method (exact), has_order_link (true/false), search
        (tracking_number / order_number / shiphero_shipment_id / carrier). Sortable:
        id, order_number, tracking_number, carrier, shipping_method, cost, created_date,
        created_at, updated_at (default -created_date).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        example: '38'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        shiphero_shipment_id:
                          type: string
                        shiphero_legacy_id:
                          type: string
                        order_id:
                          type: integer
                        shiphero_order_id:
                          type: string
                        order_number:
                          type: string
                        tracking_number:
                          type: string
                        tracking_url:
                          type: string
                        carrier:
                          type: string
                        shipping_name:
                          type: string
                        shipping_method:
                          type: string
                        cost:
                          type: number
                        insurance_amount:
                          type: integer
                        warehouse_id:
                          type: integer
                        warehouse:
                          type: string
                        carrier_account_id:
                          type: string
                        source:
                          type: string
                        shipped_off_shiphero:
                          type: boolean
                        dropshipment:
                          type: boolean
                        created_date:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                        order:
                          type: object
                          properties:
                            id:
                              type: integer
                            order_number:
                              type: string
                            shiphero_id:
                              type: string
                            link_reference:
                              type: string
                            link_type_label:
                              type: string
                            link_id:
                              type: integer
                            link_route:
                              type: string
                        sku_sales_order_fulfillment_id:
                          type: integer
                        sku_fulfillment_id:
                          type: integer
                        sku_fulfillment_status:
                          type: string
                        sales_order_id:
                          type: integer
                        sales_order_number:
                          type: string
                        sku_fulfillment_route:
                          type: string
                        warehouse_link:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                  current_page:
                    type: integer
                  per_page:
                    type: integer
                  last_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - id: 15
                    integration_instance_id: 1
                    shiphero_shipment_id: U2hpcG1lbnQ6OTg3NjU0
                    shiphero_legacy_id: '1122334455'
                    order_id: 1
                    shiphero_order_id: T3JkZXI6MTIzNDU2Nzg5
                    order_number: SO-100245
                    tracking_number: 1Z999AA10123456784
                    tracking_url: https://www.ups.com/track?loc=en_US&tracknum=1Z999AA10123456784
                    carrier: UPS
                    shipping_name: UPS Ground
                    shipping_method: ground
                    cost: 8.45
                    insurance_amount: 0
                    warehouse_id: 3
                    warehouse: Primary DC
                    carrier_account_id: ca_8842
                    source: shiphero
                    shipped_off_shiphero: false
                    dropshipment: false
                    created_date: '2024-06-03T08:14:00.000Z'
                    created_at: '2024-06-03T08:14:02.000000Z'
                    updated_at: '2024-06-03T08:14:05.000000Z'
                    order:
                      id: 1
                      order_number: SO-100245
                      shiphero_id: T3JkZXI6MTIzNDU2Nzg5
                      link_reference: SO-100245
                      link_type_label: ShipHero Order
                      link_id: 1
                      link_route: /integrations/shiphero/1/orders/1
                    sku_sales_order_fulfillment_id: 88
                    sku_fulfillment_id: 88
                    sku_fulfillment_status: shipped
                    sales_order_id: 55
                    sales_order_number: SO-2024-0055
                    sku_fulfillment_route: /orders/sales-orders/fulfillments/88
                    warehouse_link:
                      id: 3
                      name: Primary DC
                  current_page: 1
                  per_page: 10
                  last_page: 3
                  total: 27
                  from: 1
                  to: 10
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shiphero-integration-instances-integration-instance-shipments
  /api/shiphero/integration-instances/{integration_instance}/shipments/{shipment}:
    get:
      tags:
      - ShipHero
      summary: Get Shipment
      description: 'Single ShipHero shipment by local row id. Append include_json=1
        for the raw payload.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        example: '38'
        description: The integration instance ID.
      - name: shipment
        in: path
        schema:
          type: integer
        required: true
        example: '12'
        description: The shipment ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      shiphero_shipment_id:
                        type: string
                      shiphero_legacy_id:
                        type: string
                      order_id:
                        type: integer
                      shiphero_order_id:
                        type: string
                      order_number:
                        type: string
                      tracking_number:
                        type: string
                      tracking_url:
                        type: string
                      carrier:
                        type: string
                      shipping_name:
                        type: string
                      shipping_method:
                        type: string
                      cost:
                        type: number
                      insurance_amount:
                        type: integer
                      warehouse_id:
                        type: integer
                      warehouse:
                        type: string
                      carrier_account_id:
                        type: string
                      source:
                        type: string
                      shipped_off_shiphero:
                        type: boolean
                      dropshipment:
                        type: boolean
                      created_date:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      order:
                        type: object
                        properties:
                          id:
                            type: integer
                          order_number:
                            type: string
                          shiphero_id:
                            type: string
                          link_reference:
                            type: string
                          link_type_label:
                            type: string
                          link_id:
                            type: integer
                          link_route:
                            type: string
                      sku_sales_order_fulfillment_id:
                        type: integer
                      sku_fulfillment_id:
                        type: integer
                      sku_fulfillment_status:
                        type: string
                      sales_order_id:
                        type: integer
                      sales_order_number:
                        type: string
                      sku_fulfillment_route:
                        type: string
                      warehouse_link:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                example:
                  data:
                    id: 15
                    integration_instance_id: 1
                    shiphero_shipment_id: U2hpcG1lbnQ6OTg3NjU0
                    shiphero_legacy_id: '1122334455'
                    order_id: 1
                    shiphero_order_id: T3JkZXI6MTIzNDU2Nzg5
                    order_number: SO-100245
                    tracking_number: 1Z999AA10123456784
                    tracking_url: https://www.ups.com/track?loc=en_US&tracknum=1Z999AA10123456784
                    carrier: UPS
                    shipping_name: UPS Ground
                    shipping_method: ground
                    cost: 8.45
                    insurance_amount: 0
                    warehouse_id: 3
                    warehouse: Primary DC
                    carrier_account_id: ca_8842
                    source: shiphero
                    shipped_off_shiphero: false
                    dropshipment: false
                    created_date: '2024-06-03T08:14:00.000Z'
                    created_at: '2024-06-03T08:14:02.000000Z'
                    updated_at: '2024-06-03T08:14:05.000000Z'
                    order:
                      id: 1
                      order_number: SO-100245
                      shiphero_id: T3JkZXI6MTIzNDU2Nzg5
                      link_reference: SO-100245
                      link_type_label: ShipHero Order
                      link_id: 1
                      link_route: /integrations/shiphero/1/orders/1
                    sku_sales_order_fulfillment_id: 88
                    sku_fulfillment_id: 88
                    sku_fulfillment_status: shipped
                    sales_order_id: 55
                    sales_order_number: SO-2024-0055
                    sku_fulfillment_route: /orders/sales-orders/fulfillments/88
                    warehouse_link:
                      id: 3
                      name: Primary DC
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: array
                    items:
                      type: object
                      properties:
                        message:
                          type: string
                        code:
                          type: string
                        key:
                          type: string
                example:
                  errors:
                  - message: Not Found
                    code: NotFound
                    key: shipment
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-shiphero-integration-instances-integration-instance-shipments-shipment
  /api/shiphero/integration-instances/{integration_instance}/shipments/sync:
    post:
      tags:
      - ShipHero
      summary: Sync Shipments
      description: "Queue a tracked job that syncs shipments from ShipHero's GraphQL\
        \ `shipments` query (cursor-paginated). Job name: `Sync Shiphero Shipments:\
        \ {instance}`.\n\n:::info[Authorization]\nAny valid API token can call this\
        \ endpoint — no specific scope required. [Manage tokens](https://app.sku.io/settings/api).\n\
        :::\n\nRequest body (all optional):\n- `mode` (string) — sync mode. One of:\
        \ `since_latest`, `date_range`, `all`.\n    - `since_latest` — pass `date_from`\
        \ set to the latest synced shipment's created date (bounded window through\
        \ now).\n    - `date_range` — pass an explicit `date_from` / `date_to` window.\n\
        \    - `all` — FULL re-sync: leaves the window unbounded so ShipHero returns\
        \ the entire shipment history. `date_from` / `date_to` are ignored.\n- `date_from`\
        \ (ISO 8601 datetime) — lower bound. Ignored when `mode=all`.\n- `date_to`\
        \ (ISO 8601 datetime) — upper bound. Ignored when `mode=all`.\n\nWhen `mode`\
        \ is omitted, a missing date window defaults to the last 30 days.\n\nReturns\
        \ 409 if a shipments sync is already in progress for this integration.\n\n\
        Authentication: Requires Bearer token."
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                mode:
                  type: string
                date_from:
                  type: string
                date_to:
                  type: string
              example:
                mode: date_range
                date_from: '2026-05-25T00:00:00Z'
                date_to: '2026-06-25T00:00:00Z'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        example: '38'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 90871
                  message: Shipments sync job has been queued
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-shiphero-integration-instances-integration-instance-shipments-sync
  /api/shiphero/integration-instances/{integration_instance}/shipments/sync-info:
    get:
      tags:
      - ShipHero
      summary: Get Shipments Sync Info
      description: 'Latest synced shipment + total count, for the sync UI.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        example: '38'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      latest_shipment_identifier:
                        type: string
                      latest_shipment_date:
                        type: string
                      total_shipments:
                        type: integer
                example:
                  data:
                    latest_shipment_identifier: '9405550105799029788980'
                    latest_shipment_date: '2026-06-24T13:29:00.000000Z'
                    total_shipments: 190
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shiphero-integration-instances-integration-instance-shipments-sync-info
  /api/shiphero/integration-instances/{integration_instance}/products:
    get:
      tags:
      - ShipHero
      summary: List Products
      description: 'Paginated list of ShipHero products — one row per SKU with on-hand/available/allocated/backorder
        summed across warehouses, plus the number of stocking warehouses and the mapped
        local product, plus the ShipHero product id (shiphero_product_legacy_id).
        Filters: kit (true/false), mapped (mapped/unmapped), search. Sortable: sku,
        name, on_hand, available, allocated, backorder, warehouse_count, value, last_synced_at.
        Requires a Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        example: '38'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        sku:
                          type: string
                        name:
                          type: string
                        barcode:
                          type: string
                        shiphero_product_id:
                          type: string
                        on_hand:
                          type: integer
                        available:
                          type: integer
                        allocated:
                          type: integer
                        backorder:
                          type: integer
                        reserve:
                          type: integer
                        non_sellable:
                          type: integer
                        warehouse_count:
                          type: integer
                        value:
                          type: number
                        price:
                          type: number
                        kit:
                          type: boolean
                        last_synced_at:
                          type: string
                        mapped_product:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        shiphero_product_legacy_id:
                          type: integer
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - sku: CABLE-USB-C
                    name: USB-C Cable
                    barcode: '693400391793911'
                    shiphero_product_id: UHJvZHVjdEluZm86MTIz
                    on_hand: 412
                    available: 388
                    allocated: 24
                    backorder: 0
                    reserve: 0
                    non_sellable: 0
                    warehouse_count: 2
                    value: 5.5
                    price: 9.99
                    kit: false
                    last_synced_at: '2026-07-20T17:52:26.000000Z'
                    mapped_product:
                      id: 459
                      name: USB-C Cable
                    shiphero_product_legacy_id: 333360642
                  current_page: 1
                  last_page: 78
                  per_page: 10
                  total: 778
                  from: 1
                  to: 10
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shiphero-integration-instances-integration-instance-products
  /api/shiphero/integration-instances/{integration_instance}/products/{sku}:
    get:
      tags:
      - ShipHero
      summary: Get Product
      description: 'Full detail for one ShipHero product: per-warehouse inventory
        breakdown, summed totals, richer product fields (barcode, dimensions, value,
        country, tariff, tags, images, kit) and the mapped local SKU product. The
        sku path segment is URL-encoded. Requires a Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        example: '38'
        description: The integration instance ID.
      - name: sku
        in: path
        schema:
          type: string
        required: true
        example: CABLE-USB-C
        description: The sku ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      sku:
                        type: string
                      name:
                        type: string
                      barcode:
                        type: string
                      shiphero_product_id:
                        type: string
                      ship_hero_product_id:
                        type: integer
                      needs_review:
                        type: boolean
                      value:
                        type: string
                      price:
                        type: string
                      kit:
                        type: boolean
                      country_of_manufacture:
                        type: string
                      tariff_code:
                        type: string
                      dimensions:
                        type: object
                        properties:
                          height:
                            type: string
                          width:
                            type: string
                          length:
                            type: string
                          weight:
                            type: string
                      images:
                        type: array
                      tags:
                        type: array
                      shiphero_updated_at:
                        type: string
                      totals:
                        type: object
                        properties:
                          on_hand:
                            type: integer
                          available:
                            type: integer
                          allocated:
                            type: integer
                          backorder:
                            type: integer
                          reserve:
                            type: integer
                          non_sellable:
                            type: integer
                      warehouse_count:
                        type: integer
                      last_synced_at:
                        type: string
                      warehouses:
                        type: array
                        items:
                          type: object
                          properties:
                            warehouse_id:
                              type: integer
                            warehouse_name:
                              type: string
                            shiphero_warehouse_id:
                              type: string
                            on_hand:
                              type: integer
                            available:
                              type: integer
                            allocated:
                              type: integer
                            backorder:
                              type: integer
                            reserve:
                              type: integer
                            non_sellable:
                              type: integer
                      mapped_product:
                        type: object
                        properties:
                          id:
                            type: integer
                          sku:
                            type: string
                          name:
                            type: string
                example:
                  data:
                    sku: CABLE-USB-C
                    name: USB-C Cable
                    barcode: '693400391793911'
                    shiphero_product_id: UHJvZHVjdEluZm86MTIz
                    ship_hero_product_id: 1024
                    needs_review: false
                    value: '5.5000'
                    price: '9.9900'
                    kit: false
                    country_of_manufacture: US
                    tariff_code: ''
                    dimensions:
                      height: 1.0000 inch
                      width: 0.50 inch
                      length: 4.00 inch
                      weight: 0.0600 lb
                    images: []
                    tags: []
                    shiphero_updated_at: '2026-07-01T23:32:03'
                    totals:
                      on_hand: 412
                      available: 388
                      allocated: 24
                      backorder: 0
                      reserve: 0
                      non_sellable: 0
                    warehouse_count: 2
                    last_synced_at: '2026-07-20T17:52:26.000000Z'
                    warehouses:
                    - warehouse_id: 4
                      warehouse_name: Main Warehouse
                      shiphero_warehouse_id: V2FyZWhvdXNlOjExNTQxNQ==
                      on_hand: 300
                      available: 288
                      allocated: 12
                      backorder: 0
                      reserve: 0
                      non_sellable: 0
                    mapped_product:
                      id: 459
                      sku: ABC-123
                      name: USB-C Cable
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shiphero-integration-instances-integration-instance-products-sku
  /api/shiphero/integration-instances/{integration_instance}/products/{shipHeroProduct}/mapping:
    put:
      tags:
      - ShipHero
      summary: Set Product SKU Mapping
      description: 'Sets or clears the SKU.io product mapping for a ShipHero product.
        Pass `sku_product_id` to map this ShipHero SKU to a SKU.io product, or `null`
        to unmap. Use this when a fulfillment provider holds stock under a SKU that
        differs from your own (a SKU they will not rename): once mapped, the ShipHero
        SKU resolves to the mapped product across the products list, inventory reconciliation,
        and fulfillment submission. Requires a Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                sku_product_id:
                  type: integer
              example:
                sku_product_id: 459
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        example: '38'
        description: The integration instance ID.
      - name: shipHeroProduct
        in: path
        schema:
          type: integer
        required: true
        description: ShipHero product id (the mapping mirror row, from the products
          list / detail).
        example: '1024'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 Mapped
                  value:
                    data:
                      ship_hero_product_id: 1024
                      sku: amzn.gr.2968014-FBA-AaEE6yfT22OThjupL-LN
                      sku_product_id: 459
                      needs_review: false
                      mapped_product:
                        id: 459
                        sku: ABC-123
                        name: USB-C Cable
                    message: Product mapped.
                example-1:
                  summary: 200 Unmapped
                  value:
                    data:
                      ship_hero_product_id: 1024
                      sku: amzn.gr.2968014-FBA-AaEE6yfT22OThjupL-LN
                      sku_product_id: null
                      needs_review: false
                      mapped_product: null
                    message: Product unmapped.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      sku_product_id:
                        type: array
                        items:
                          type: string
                example:
                  message: The selected sku product id is invalid.
                  errors:
                    sku_product_id:
                    - The selected sku product id is invalid.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: put-api-shiphero-integration-instances-integration-instance-products-shipheroproduct-mapping
  /api/shiphero/integration-instances/{integration_instance}/inventory-audit:
    get:
      tags:
      - ShipHero
      summary: List Inventory Changes
      description: 'Server-side paginated, filterable audit trail of ShipHero inventory
        movements. Each row is one inventory change with the signed delta, human-readable
        reason, category, and who/where/when. Filters: category (comma-separated),
        warehouse_id, shiphero_warehouse_id, cycle_counted (true/false), search. Also
        searchable/sortable by id and shiphero_change_id. Sortable: id, changed_at,
        sku, change_in_on_hand, new_on_hand, previous_on_hand, category, created_at.
        Requires a Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        example: '38'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        shiphero_change_id:
                          type: integer
                        sku:
                          type: string
                        product:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        category:
                          type: string
                        category_label:
                          type: string
                        previous_on_hand:
                          type: integer
                        change_in_on_hand:
                          type: integer
                        new_on_hand:
                          type: integer
                        cycle_counted:
                          type: boolean
                        reason_text:
                          type: string
                        reference_type:
                          type: string
                        reference_number:
                          type: string
                        shiphero_reference_url:
                          type: string
                        warehouse:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        shiphero_warehouse_id:
                          type: integer
                        location_name:
                          type: string
                        location_zone:
                          type: string
                        shiphero_user_id:
                          type: integer
                        changed_at:
                          type: string
                        created_at:
                          type: string
                        shiphero_order:
                          type: object
                          properties:
                            id:
                              type: integer
                            order_number:
                              type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - id: 4412
                    shiphero_change_id: 1409175962
                    sku: SU400-939-3057
                    product:
                      id: 459
                      name: Premium Widget
                    category: pick
                    category_label: Pick
                    previous_on_hand: 298
                    change_in_on_hand: -1
                    new_on_hand: 297
                    cycle_counted: false
                    reason_text: 'Order #FP2075.1 picked into tote Tote-325. Pick
                      type: mib'
                    reference_type: order
                    reference_number: '#FP2075.1'
                    shiphero_reference_url: https://app.shiphero.com/dashboard/orders/details/804491805
                    warehouse:
                      id: 4
                      name: Main Warehouse
                    shiphero_warehouse_id: 115415
                    location_name: E-05-06-A-03
                    location_zone: A
                    shiphero_user_id: 716769
                    changed_at: '2026-04-27T16:19:50.000000Z'
                    created_at: '2026-07-20T20:25:47.000000Z'
                    shiphero_order:
                      id: 1995
                      order_number: SXC14895.1
                  current_page: 1
                  last_page: 18
                  per_page: 10
                  total: 179
                  from: 1
                  to: 10
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shiphero-integration-instances-integration-instance-inventory-audit
  /api/shiphero/integration-instances/{integration_instance}/inventory-audit/kpi-stats:
    get:
      tags:
      - ShipHero
      summary: Get Inventory Audit KPI Stats
      description: Summary KPIs for the inventory audit trail — total changes, net
        change, increases, decreases, adjustments, cycle counts, and a per-category
        breakdown. Honors the same filters as the list endpoint (pass the same filter[...]
        query params). Requires a Bearer token.
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        example: '38'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      total_changes:
                        type: integer
                      net_change:
                        type: integer
                      increases:
                        type: integer
                      decreases:
                        type: integer
                      adjustments:
                        type: integer
                      cycle_counts:
                        type: integer
                      by_category:
                        type: object
                        properties:
                          pick:
                            type: integer
                          transfer:
                            type: integer
                          receive:
                            type: integer
                          return:
                            type: integer
                          ship:
                            type: integer
                          adjustment:
                            type: integer
                          location_add:
                            type: integer
                      range:
                        type: object
                        properties:
                          from:
                            type: string
                          to:
                            type: string
                example:
                  data:
                    total_changes: 179
                    net_change: 125
                    increases: 81
                    decreases: 95
                    adjustments: 2
                    cycle_counts: 0
                    by_category:
                      pick: 57
                      transfer: 72
                      receive: 27
                      return: 12
                      ship: 6
                      adjustment: 2
                      location_add: 3
                    range:
                      from: '2026-07-14 17:51:22'
                      to: '2026-07-20 20:25:46'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shiphero-integration-instances-integration-instance-inventory-audit-kpi-stats
  /api/shiphero/integration-instances/{integration_instance}/inventory-audit/sync-info:
    get:
      tags:
      - ShipHero
      summary: Get Inventory Audit Sync Info
      description: Metadata for the inventory audit sync UI — the most recent recorded
        movement time and the total number of changes stored. Requires a Bearer token.
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        example: '38'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      latest_changed_at:
                        type: string
                      total_changes:
                        type: integer
                example:
                  data:
                    latest_changed_at: '2026-07-20T20:25:46.000000Z'
                    total_changes: 179
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shiphero-integration-instances-integration-instance-inventory-audit-sync-info
  /api/shiphero/integration-instances/{integration_instance}/inventory-audit/export:
    get:
      tags:
      - ShipHero
      summary: Export Inventory Audit
      description: Download the inventory audit trail as an Excel (.xlsx) or CSV file.
        The export honors the active filters (scope=filtered) or can export all, the
        current page, or a selected set of ids. Returns a binary file download, not
        JSON. Requires a Bearer token.
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        example: '38'
        description: The integration instance ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shiphero-integration-instances-integration-instance-inventory-audit-export
  /api/shiphero/integration-instances/{integration_instance}/inventory-audit/sync:
    post:
      tags:
      - ShipHero
      summary: Sync Inventory Audit
      description: 'Queue a background job that pulls ShipHero inventory changes into
        the audit ledger. mode: since_latest (incremental from the latest recorded
        change, pass date_from), date_range (pass date_from + date_to), or all (full
        history). Returns the tracked job id. Returns 409 if a sync is already running
        for this integration. Requires a Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                mode:
                  type: string
                date_from:
                  type: string
                date_to:
                  type: string
              example:
                mode: since_latest
                date_from: '2026-07-14'
                date_to: '2026-07-20'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        example: '38'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 90210
                  message: Inventory audit sync job has been queued
        '409':
          description: Conflict
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: object
                    properties:
                      sync:
                        type: array
                        items:
                          type: object
                          properties:
                            code:
                              type: string
                            detail:
                              type: string
                example:
                  errors:
                    sync:
                    - code: SyncInProgress
                      detail: An inventory audit sync is already in progress for this
                        integration
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-shiphero-integration-instances-integration-instance-inventory-audit-sync
  /api/shiphero/integration-instances/{integration_instance}/inventory-audit/{inventoryChange}:
    get:
      tags:
      - ShipHero
      summary: Get Inventory Change
      description: Get a single inventory change by its local id, with the resolved
        product and warehouse. Requires a Bearer token.
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        example: '38'
        description: The integration instance ID.
      - name: inventoryChange
        in: path
        schema:
          type: integer
        required: true
        example: '4412'
        description: The inventory change ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      shiphero_change_id:
                        type: integer
                      sku:
                        type: string
                      product:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      category:
                        type: string
                      category_label:
                        type: string
                      previous_on_hand:
                        type: integer
                      change_in_on_hand:
                        type: integer
                      new_on_hand:
                        type: integer
                      cycle_counted:
                        type: boolean
                      reason_text:
                        type: string
                      reference_type:
                        type: string
                      reference_number:
                        type: string
                      shiphero_reference_url:
                        type: string
                      warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      shiphero_warehouse_id:
                        type: integer
                      location_name:
                        type: string
                      location_zone:
                        type: string
                      shiphero_user_id:
                        type: integer
                      changed_at:
                        type: string
                      created_at:
                        type: string
                      shiphero_order:
                        type: object
                        properties:
                          id:
                            type: integer
                          order_number:
                            type: string
                example:
                  data:
                    id: 4412
                    shiphero_change_id: 1409175962
                    sku: SU400-939-3057
                    product:
                      id: 459
                      name: Premium Widget
                    category: pick
                    category_label: Pick
                    previous_on_hand: 298
                    change_in_on_hand: -1
                    new_on_hand: 297
                    cycle_counted: false
                    reason_text: 'Order #FP2075.1 picked into tote Tote-325. Pick
                      type: mib'
                    reference_type: order
                    reference_number: '#FP2075.1'
                    shiphero_reference_url: https://app.shiphero.com/dashboard/orders/details/804491805
                    warehouse:
                      id: 4
                      name: Main Warehouse
                    shiphero_warehouse_id: 115415
                    location_name: E-05-06-A-03
                    location_zone: A
                    shiphero_user_id: 716769
                    changed_at: '2026-04-27T16:19:50.000000Z'
                    created_at: '2026-07-20T20:25:47.000000Z'
                    shiphero_order:
                      id: 1995
                      order_number: SXC14895.1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shiphero-integration-instances-integration-instance-inventory-audit-inventorychange
  /api/shipstation/integration-instances:
    post:
      tags:
      - ShipStation
      summary: Create Integration Instance
      description: "Creates a new ShipStation integration instance.\n\n:::info[Authorization]\n\
        Any valid API token can call this endpoint — no specific scope required. [Manage\
        \ tokens](https://app.sku.io/settings/api).\n:::\n\nOn success the manager\
        \ immediately dispatches the initial background sync jobs for the new instance:\
        \ auto-subscribe webhooks, sync warehouses, sync shipping methods, sync orders,\
        \ and sync shipments (tracking info). Each sync surfaces via the tracked job\
        \ log endpoints.\n\nBody fields:\n- name (string, required): display name\
        \ for the instance. Must be unique across all integration instances (validated\
        \ by a unique rule and re-checked in the manager, which returns 422 with `Provider\
        \ name (X) already exists` on conflict).\n- connection_settings (object, required):\
        \ ShipStation V1 API credentials.\n  - connection_settings.apiKey (string,\
        \ required in practice): ShipStation API Key.\n  - connection_settings.apiSecret\
        \ (string, required in practice): ShipStation API Secret.\n  - connection_settings.timezone\
        \ (string, optional): IANA timezone used to interpret ShipStation's local\
        \ timestamps. Defaults to America/Los_Angeles (ShipStation V1 returns PST/PDT\
        \ timestamps).\n- integration_settings (object, optional): initial integration\
        \ settings (see Update for the full key list). Defaults to `{}`.\n  - integration_settings.sync_enabled\
        \ (boolean): whether automatic order syncing is on.\n  - integration_settings.order_start_date\
        \ (date string or null): earliest order date to sync. When not set, syncs\
        \ fall back to the Inventory Start Date, then a fixed 30-day window.\n  -\
        \ integration_settings.auto_submit_fulfillments (boolean): submit fulfillments\
        \ automatically without manual review.\n- is_automatic_sync_enabled (boolean,\
        \ optional): toggle the hourly scheduled syncs for this instance.\n\nResponse:\
        \ `data.id` and `data.name` of the created instance.\n\nAuthentication: Requires\
        \ Bearer token."
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                connection_settings:
                  type: object
                  properties:
                    apiKey:
                      type: string
                    apiSecret:
                      type: string
                    timezone:
                      type: string
                integration_settings:
                  type: object
                  properties:
                    sync_enabled:
                      type: boolean
                    order_start_date:
                      type: string
                    auto_submit_fulfillments:
                      type: boolean
                is_automatic_sync_enabled:
                  type: boolean
              example:
                name: ShipStation US
                connection_settings:
                  apiKey: ss_live_a1b2c3d4e5f6
                  apiSecret: ss_secret_f6e5d4c3b2a1
                  timezone: America/Los_Angeles
                integration_settings:
                  sync_enabled: true
                  order_start_date: '2026-05-11'
                  auto_submit_fulfillments: true
                is_automatic_sync_enabled: true
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                example:
                  data:
                    id: 12
                    name: ShipStation US
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 422 Duplicate Name (manager check)
                  value:
                    message: Provider name (ShipStation US) already exists
                example-1:
                  summary: 422 Validation Error
                  value:
                    message: The name has already been taken.
                    errors:
                      name:
                      - The name has already been taken.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-shipstation-integration-instances
  /api/shipstation/integration-instances/{integration_instance}:
    get:
      tags:
      - ShipStation
      summary: Get Integration Instance
      description: 'Returns a single ShipStation integration instance with its connection
        settings and integration settings.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Response fields:

        - id (int), name (string), integration_id (int)

        - connection_settings (object): apiKey, apiSecret, timezone

        - integration_settings (object): connection_name, enable_fulfillment, order_start_date,
        auto_submit_fulfillments, settings (legacy ShipStation options such as productFieldToPass,
        gift_card_note_sales_order_custom_field_id, saturday_delivery_sales_order_custom_field_id,
        send_sales_order_tags_as_notes), fulfillment_cost_financial_line_type_id,
        and fulfillment (per-warehouse routing: enabledWarehousesIds / automatedWarehousesIds)

        - is_automatic_sync_enabled (boolean)

        - created_at / updated_at (ISO 8601)


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      integration_id:
                        type: integer
                      connection_settings:
                        type: object
                        properties:
                          apiKey:
                            type: string
                          apiSecret:
                            type: string
                          timezone:
                            type: string
                      integration_settings:
                        type: object
                        properties:
                          connection_name:
                            type: string
                          enable_fulfillment:
                            type: boolean
                          order_start_date:
                            type: string
                          auto_submit_fulfillments:
                            type: boolean
                          settings:
                            type: object
                            properties:
                              productFieldToPass:
                                type: string
                              send_sales_order_tags_as_notes:
                                type: boolean
                          fulfillment_cost_financial_line_type_id:
                            type: integer
                          fulfillment:
                            type: object
                            properties:
                              enabledWarehousesIds:
                                type: array
                                items:
                                  type: integer
                              automatedWarehousesIds:
                                type: array
                                items:
                                  type: integer
                      is_automatic_sync_enabled:
                        type: boolean
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 12
                    name: ShipStation US
                    integration_id: 27
                    connection_settings:
                      apiKey: ss_live_a1b2c3d4e5f6
                      apiSecret: ss_secret_f6e5d4c3b2a1
                      timezone: America/Los_Angeles
                    integration_settings:
                      connection_name: ShipStation US
                      enable_fulfillment: true
                      order_start_date: '2026-01-01'
                      auto_submit_fulfillments: true
                      settings:
                        productFieldToPass: sku
                        send_sales_order_tags_as_notes: false
                      fulfillment_cost_financial_line_type_id: 4
                      fulfillment:
                        enabledWarehousesIds:
                        - 1
                        - 2
                        automatedWarehousesIds:
                        - 1
                    is_automatic_sync_enabled: true
                    created_at: '2026-05-01T10:15:00+00:00'
                    updated_at: '2026-06-09T18:42:11+00:00'
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No query results for model [Modules\Shipstation\Entities\ShipstationIntegrationInstance]
                    999
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-shipstation-integration-instances-integration-instance
    put:
      tags:
      - ShipStation
      summary: Update Integration Instance
      description: "Update an existing ShipStation integration instance. All fields\
        \ are optional. Requires Bearer token.\n\n:::info[Authorization]\nAny valid\
        \ API token can call this endpoint — no specific scope required. [Manage tokens](https://app.sku.io/settings/api).\n\
        :::\n\nRequest body fields:\n- name (optional, string)\n- connection_settings\
        \ (optional, object): API credentials\n- integration_settings (optional, object).\
        \ Includes:\n  - fulfillment_cost_financial_line_type_id (optional, int|null):\
        \ COST financial line type used for ShipStation shipping cost lines. null\
        \ = auto (default \"Shipping Cost\"). Must be a cost type or returns 422.\n\
        - is_automatic_sync_enabled (optional, boolean)\n\nWhen the effective cost-line\
        \ type changes, a reconcile tracked job is dispatched and the response includes\
        \ reconcile_tracked_job_log_id."
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                integration_settings:
                  type: object
                  properties:
                    fulfillment_cost_financial_line_type_id:
                      type: integer
                is_automatic_sync_enabled:
                  type: boolean
              example:
                name: US ShipStation
                integration_settings:
                  fulfillment_cost_financial_line_type_id: 29
                is_automatic_sync_enabled: true
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      integration_id:
                        type: integer
                      connection_settings:
                        type: object
                        properties:
                          apiKey:
                            type: string
                          apiSecret:
                            type: string
                          timezone:
                            type: string
                      integration_settings:
                        type: object
                        properties:
                          connection_name:
                            type: string
                          enable_fulfillment:
                            type: boolean
                          order_start_date:
                            type: string
                          auto_submit_fulfillments:
                            type: boolean
                          settings:
                            type: object
                            properties:
                              productFieldToPass:
                                type: string
                              send_sales_order_tags_as_notes:
                                type: boolean
                          fulfillment_cost_financial_line_type_id:
                            type: integer
                          fulfillment:
                            type: object
                            properties:
                              enabledWarehousesIds:
                                type: array
                                items:
                                  type: integer
                              automatedWarehousesIds:
                                type: array
                                items:
                                  type: integer
                      is_automatic_sync_enabled:
                        type: boolean
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 12
                    name: ShipStation US
                    integration_id: 27
                    connection_settings:
                      apiKey: ss_live_a1b2c3d4e5f6
                      apiSecret: ss_secret_f6e5d4c3b2a1
                      timezone: America/Los_Angeles
                    integration_settings:
                      connection_name: ShipStation US
                      enable_fulfillment: true
                      order_start_date: '2026-01-01'
                      auto_submit_fulfillments: true
                      settings:
                        productFieldToPass: sku
                        send_sales_order_tags_as_notes: false
                      fulfillment_cost_financial_line_type_id: 4
                      fulfillment:
                        enabledWarehousesIds:
                        - 1
                        - 2
                        automatedWarehousesIds:
                        - 1
                    is_automatic_sync_enabled: true
                    created_at: '2026-05-01T10:15:00+00:00'
                    updated_at: '2026-06-09T18:42:11+00:00'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      name:
                        type: array
                        items:
                          type: string
                example:
                  message: The name has already been taken.
                  errors:
                    name:
                    - The name has already been taken.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: put-api-shipstation-integration-instances-integration-instance
    delete:
      tags:
      - ShipStation
      summary: Delete Integration Instance
      description: 'Deletes a ShipStation integration instance. The deletion runs
        asynchronously — a background job removes the instance and its related data
        (orders, warehouses, shipping method mappings, webhook events/subscriptions).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Integration instance deleted successfully
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No query results for model [Modules\Shipstation\Entities\ShipstationIntegrationInstance]
                    999
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: delete-api-shipstation-integration-instances-integration-instance
  /api/shipstation/integration-instances/{integration_instance}/dashboard:
    get:
      tags:
      - ShipStation
      summary: Get Dashboard Metrics
      description: 'Returns dashboard metrics for a ShipStation integration instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Response fields (camelCase, serialized from ShipstationDashboardMetricsData):

        - totalOrders (int): total synced ShipStation orders for the instance

        - ordersByStatus (array): one row per ShipStation order status (awaiting_payment,
        awaiting_shipment, pending_fulfillment, shipped, on_hold, cancelled, rejected_fulfillment,
        unknown) with status, status_label and count (zero-filled for statuses with
        no orders)

        - ordersByCarrier (array): up to 20 carriers ordered by count desc, each {carrier,
        count}

        - totalWarehouses (int): synced ShipStation warehouses

        - unprocessedWebhookEvents (int) / failedWebhookEvents (int): webhook event
        queue health

        - activeWebhookSubscriptions (int)

        - ordersLastSyncedAt / trackingInfoLastUpdatedAt / warehousesLastSyncedAt
        (ISO 8601 or null): last sync timestamps

        - unlinkedOrders (int): ShipStation orders not linked to a SKU fulfillment

        - schedules (object): sync schedule metadata keyed by orders, tracking_info,
        warehouses — each {frequency: ''Hourly'' | ''Manual only'', seconds_until_next:
        int | null} powering the dashboard countdown

        - ordersChart (array): one {date, orders_count} row per day for the last 30
        days (oldest first, zero-filled)


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      totalOrders:
                        type: integer
                      ordersByStatus:
                        type: array
                        items:
                          type: object
                          properties:
                            status:
                              type: string
                            status_label:
                              type: string
                            count:
                              type: integer
                      ordersByCarrier:
                        type: array
                        items:
                          type: object
                          properties:
                            carrier:
                              type: string
                            count:
                              type: integer
                      totalWarehouses:
                        type: integer
                      unprocessedWebhookEvents:
                        type: integer
                      failedWebhookEvents:
                        type: integer
                      activeWebhookSubscriptions:
                        type: integer
                      ordersLastSyncedAt:
                        type: string
                      trackingInfoLastUpdatedAt:
                        type: string
                      warehousesLastSyncedAt:
                        type: string
                      unlinkedOrders:
                        type: integer
                      schedules:
                        type: object
                        properties:
                          orders:
                            type: object
                            properties:
                              frequency:
                                type: string
                              seconds_until_next:
                                type: integer
                          tracking_info:
                            type: object
                            properties:
                              frequency:
                                type: string
                              seconds_until_next:
                                type: integer
                          warehouses:
                            type: object
                            properties:
                              frequency:
                                type: string
                              seconds_until_next:
                                type: string
                                nullable: true
                      ordersChart:
                        type: array
                        items:
                          type: object
                          properties:
                            date:
                              type: string
                            orders_count:
                              type: integer
                example:
                  data:
                    totalOrders: 1245
                    ordersByStatus:
                    - status: awaiting_payment
                      status_label: Awaiting Payment
                      count: 12
                    - status: awaiting_shipment
                      status_label: Awaiting Shipment
                      count: 86
                    - status: pending_fulfillment
                      status_label: Pending Fulfillment
                      count: 9
                    - status: shipped
                      status_label: Shipped
                      count: 1098
                    - status: on_hold
                      status_label: On Hold
                      count: 5
                    - status: cancelled
                      status_label: Cancelled
                      count: 30
                    - status: rejected_fulfillment
                      status_label: Rejected Fulfillment
                      count: 2
                    - status: unknown
                      status_label: Unknown
                      count: 3
                    ordersByCarrier:
                    - carrier: stamps_com
                      count: 640
                    - carrier: ups
                      count: 310
                    - carrier: fedex
                      count: 148
                    totalWarehouses: 3
                    unprocessedWebhookEvents: 4
                    failedWebhookEvents: 1
                    activeWebhookSubscriptions: 2
                    ordersLastSyncedAt: '2026-06-10T08:00:12+00:00'
                    trackingInfoLastUpdatedAt: '2026-06-10T08:05:43+00:00'
                    warehousesLastSyncedAt: '2026-06-09T15:21:07+00:00'
                    unlinkedOrders: 17
                    schedules:
                      orders:
                        frequency: Hourly
                        seconds_until_next: 1820
                      tracking_info:
                        frequency: Hourly
                        seconds_until_next: 1820
                      warehouses:
                        frequency: Manual only
                        seconds_until_next: null
                    ordersChart:
                    - date: '2026-05-12'
                      orders_count: 38
                    - date: '2026-05-13'
                      orders_count: 42
                    - date: '2026-05-14'
                      orders_count: 0
                    - date: '2026-05-15'
                      orders_count: 51
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shipstation-integration-instances-integration-instance-dashboard
  /api/shipstation/integration-instances/{integration_instance}/orders-chart:
    get:
      tags:
      - ShipStation
      summary: Get Orders Chart (Date Range)
      description: 'Returns a daily order-count time series for a ShipStation integration
        instance over the given date range, powering the dashboard orders trend chart''s
        custom range selection.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        The response contains one bucket per day in [start_date, end_date] (oldest
        first), counting orders by their order_date and filling zero-counts for days
        with no orders so the chart x-axis is continuous.


        Query parameters:

        - start_date (required, date e.g. YYYY-MM-DD): start of the range

        - end_date (required, date e.g. YYYY-MM-DD): end of the range; must be on
        or after start_date


        Authentication: Requires Bearer token.'
      parameters:
      - name: start_date
        in: query
        schema:
          type: string
        description: Start date of the range (YYYY-MM-DD). Required.
        example: '2026-05-11'
      - name: end_date
        in: query
        schema:
          type: string
        description: End date of the range (YYYY-MM-DD). Must be on or after start_date.
          Required.
        example: '2026-06-10'
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        date:
                          type: string
                        orders_count:
                          type: integer
                example:
                  data:
                  - date: '2026-05-11'
                    orders_count: 0
                  - date: '2026-05-12'
                    orders_count: 38
                  - date: '2026-05-13'
                    orders_count: 42
                  - date: '2026-05-14'
                    orders_count: 7
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      end_date:
                        type: array
                        items:
                          type: string
                example:
                  message: The end date field must be a date after or equal to start
                    date.
                  errors:
                    end_date:
                    - The end date field must be a date after or equal to start date.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shipstation-integration-instances-integration-instance-orders-chart
  /api/shipstation/integration-instances/{integration_instance}/test-connection:
    post:
      tags:
      - ShipStation
      summary: Test Connection
      description: 'Tests the ShipStation API connection for an integration instance
        by calling the ShipStation V1 List Warehouses endpoint with the instance''s
        stored apiKey/apiSecret.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        No request body. Returns 200 with `Connection successful` when ShipStation
        responds successfully, or 400 when the request fails (invalid credentials,
        network error, etc.).


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Connection successful
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Connection test failed. Please verify your API Key and
                    API Secret.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-shipstation-integration-instances-integration-instance-test-connection
  /api/shipstation/integration-instances/{integrationInstance}/cost-line-type/preview:
    post:
      tags:
      - ShipStation
      summary: Preview Cost Line Type Impact
      description: 'Preview how many ShipStation cost financial lines and sales orders
        would be touched if the fulfillment-cost financial line type changed to new_type_id.
        Read-only. Requires Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Request body:

        - new_type_id (optional, int|null): Proposed cost financial line type id.
        null = auto default. Must exist.


        Drives the confirmation modal before saving the setting.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                new_type_id:
                  type: integer
              example:
                new_type_id: 29
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: ShipStation integration instance ID
        example: '6'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      rewire_lines:
                        type: integer
                      backfill_lines:
                        type: integer
                      sales_orders_impacted:
                        type: integer
                      is_noop:
                        type: boolean
                example:
                  data:
                    rewire_lines: 12
                    backfill_lines: 340
                    sales_orders_impacted: 351
                    is_noop: false
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-shipstation-integration-instances-integrationinstance-cost-line-type-preview
  /api/shipstation/integration-instances/{integration_instance}/fulfillment-routing:
    put:
      tags:
      - ShipStation
      summary: Update Fulfillment Routing
      description: 'Saves per-warehouse fulfillment routing for a ShipStation integration
        instance — which SKU warehouses participate in ShipStation fulfillment and
        which of those are pushed automatically (no manual review). Stored under integration_settings.fulfillment.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Body fields (both must be present, arrays of warehouse ids):

        - enabledWarehousesIds (`array<int>`, required/present): warehouses that participate
        in ShipStation fulfillment

        - automatedWarehousesIds (`array<int>`, required/present): subset of enabled
        warehouses whose fulfillments are pushed automatically. Ids not also present
        in enabledWarehousesIds are silently dropped. Returns 422 if any warehouse
        is already automated by another integration instance.


        Response: the saved `fulfillment` object plus a confirmation message.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                enabledWarehousesIds:
                  type: array
                  items:
                    type: integer
                automatedWarehousesIds:
                  type: array
                  items:
                    type: integer
              example:
                enabledWarehousesIds:
                - 1
                - 2
                - 3
                automatedWarehousesIds:
                - 1
                - 2
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      fulfillment:
                        type: object
                        properties:
                          enabledWarehousesIds:
                            type: array
                            items:
                              type: integer
                          automatedWarehousesIds:
                            type: array
                            items:
                              type: integer
                  message:
                    type: string
                example:
                  data:
                    fulfillment:
                      enabledWarehousesIds:
                      - 1
                      - 2
                      - 3
                      automatedWarehousesIds:
                      - 1
                      - 2
                  message: Fulfillment routing saved
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 422 Warehouse Conflict
                  value:
                    message: 'Warehouses already automated by another integration:
                      4, 7'
                example-1:
                  summary: 422 Validation Error
                  value:
                    message: The enabledWarehousesIds field must be present.
                    errors:
                      enabledWarehousesIds:
                      - The enabledWarehousesIds field must be present.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: put-api-shipstation-integration-instances-integration-instance-fulfillment-routing
  /api/shipstation/integration-instances/{integration_instance}/orders:
    get:
      tags:
      - ShipStation
      summary: List Orders
      description: 'Paginated list of locally cached ShipStation orders for an integration
        instance (default sort `-id`, default 10 per page). Eager loads the linked
        SKU fulfillment (+ sales order number and warehouse).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Free-text search** — `filter[search]` searches `order_number`, `tracking_number`,
        `shipstation_order_id`, `customer_name`. Prefers the Scout/Typesense index
        (fast substring search); falls back to column-aware DB LIKE. `search_columns`
        restricts which columns are searched; `search_strict_columns` switches listed
        columns to exact `=` match. A fully-strict search always runs on the DB.


        **Simple filters** — `filter[order_status]`, `filter[carrier_code]`, `filter[sku_fulfillment_id]`
        (exact); `filter[has_fulfillment]`, `filter[has_tracking]` (true/false); `filter[date_from]`,
        `filter[date_to]` (order_date bounds).


        **Advanced operator filters** — `filter[<column>.<operator>]=value` (bare
        `filter[<column>]=value` acts as implicit `is`):

        - Text columns (`order_number`, `shipstation_order_id`, `order_key`, `tracking_number`,
        `customer_name`, `order_status`, `carrier_code`, `service_code`): contains,
        does_not_contain, is, is_not, is_one_of, starts_with, does_not_start_with,
        ends_with, does_not_end_with, is_empty, is_not_empty

        - Numeric column (`id`): is, is_not, is_one_of, greater_than, less_than, greater_than_or_equal,
        less_than_or_equal, between, is_empty, is_not_empty

        - Date column (`order_date`) and datetime columns (`ship_date`, `created_at`,
        `updated_at` — timezone-aware): is, is_not, before, after, on_or_before, on_or_after,
        between, is_empty, is_not_empty, today, yesterday, tomorrow, past_week, past_month,
        past_year, next_week, next_month, next_year, days_ago, days_from_now, past_days,
        next_days


        **Grouped filters** — `filter_groups` (base64 JSON on GET; plain JSON in a
        POST body) applies a nested AND/OR condition tree against the same registered
        columns, taking precedence over flat filters.


        **Sorting** — `sort` accepts: id, order_number, customer_name, order_date,
        order_status, created_at, updated_at, ship_date, carrier_code, tracking_number
        (prefix `-` for descending; default `-id`).


        **Response fields of note** — `tracking_url` is resolved server-side from
        carrier_code + tracking_number (null when the carrier is unknown); `customer_name`
        is searchable/filterable; `sku_fulfillment` is a cross-link object (route,
        sales order number, warehouse) or null; `json_object` is only included when
        `include_json=1`.


        Authentication: Requires Bearer token.


        Each order includes a `shipments` array of linked ShipStation shipment rows
        (tracking number/URL, carrier + service, cost, voided / return-label flags,
        ship date, and a `link_route` to the shipment detail page), sorted by ship
        date descending.'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        description: Page number (default 1).
        example: '1'
      - name: per_page
        in: query
        schema:
          type: integer
        description: Items per page (default 10).
        example: '10'
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        shipstation_order_id:
                          type: integer
                        order_key:
                          type: string
                        order_number:
                          type: string
                        order_status:
                          type: string
                        order_status_label:
                          type: string
                        order_status_color:
                          type: string
                        customer_email:
                          type: string
                        order_date:
                          type: string
                        ship_date:
                          type: string
                        ship_by_date:
                          type: string
                        carrier_code:
                          type: string
                        service_code:
                          type: string
                        tracking_number:
                          type: string
                        tracking_url:
                          type: string
                        shipments:
                          type: array
                          items:
                            type: object
                            properties:
                              id:
                                type: integer
                              shipstation_shipment_id:
                                type: integer
                              tracking_number:
                                type: string
                              tracking_url:
                                type: string
                              carrier_code:
                                type: string
                              service_code:
                                type: string
                              package_code:
                                type: string
                              confirmation:
                                type: string
                              shipment_cost:
                                type: number
                              voided:
                                type: boolean
                              is_return_label:
                                type: boolean
                              ship_date:
                                type: string
                              create_date:
                                type: string
                              link_route:
                                type: string
                        sku_fulfillment:
                          type: object
                          properties:
                            id:
                              type: integer
                            link_reference:
                              type: integer
                            link_type_label:
                              type: string
                            link_id:
                              type: integer
                            link_route:
                              type: string
                            status:
                              type: string
                            tracking_number:
                              type: string
                            tracking_url:
                              type: string
                            fulfilled_at:
                              type: string
                            created_at:
                              type: string
                            sales_order_number:
                              type: string
                            warehouse:
                              type: object
                              properties:
                                id:
                                  type: integer
                                name:
                                  type: string
                        has_detailed_data:
                          type: boolean
                        details_last_updated:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                  next_page_url:
                    type: string
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 412
                    integration_instance_id: 7
                    shipstation_order_id: 987654321
                    order_key: a1b2c3d4e5f6
                    order_number: C604018.1
                    order_status: shipped
                    order_status_label: Shipped
                    order_status_color: success
                    customer_email: jane@example.com
                    order_date: '2026-06-01T14:22:10+00:00'
                    ship_date: '2026-06-02T18:05:00+00:00'
                    ship_by_date: '2026-06-04T07:00:00+00:00'
                    carrier_code: fedex
                    service_code: fedex_ground
                    tracking_number: '781234567890'
                    tracking_url: https://www.fedex.com/fedextrack/?trknbr=781234567890
                    shipments:
                    - id: 101
                      shipstation_shipment_id: 987654321
                      tracking_number: '9400111899560000000001'
                      tracking_url: https://tools.usps.com/go/TrackConfirmAction?tLabels=9400111899560000000001
                      carrier_code: stamps_com
                      service_code: usps_priority_mail
                      package_code: package
                      confirmation: delivery
                      shipment_cost: 7.42
                      voided: false
                      is_return_label: false
                      ship_date: '2026-06-08T00:00:00+00:00'
                      create_date: '2026-06-08T14:22:10+00:00'
                      link_route: /integrations/shipstation/4/shipments/101
                    sku_fulfillment:
                      id: 650
                      link_reference: 650
                      link_type_label: Sales Order Fulfillment
                      link_id: 650
                      link_route: /orders/sales-orders/fulfillments/650
                      status: fulfilled
                      tracking_number: '781234567890'
                      tracking_url: https://www.fedex.com/fedextrack/?trknbr=781234567890
                      fulfilled_at: '2026-06-02T18:06:11+00:00'
                      created_at: '2026-06-01T14:30:00+00:00'
                      sales_order_number: C604018
                      warehouse:
                        id: 3
                        name: Main Warehouse
                    has_detailed_data: true
                    details_last_updated: '2026-06-02T18:10:00+00:00'
                    created_at: '2026-06-01T14:25:00+00:00'
                    updated_at: '2026-06-02T18:10:00+00:00'
                  - id: 411
                    integration_instance_id: 7
                    shipstation_order_id: 987654300
                    order_key: f6e5d4c3b2a1
                    order_number: C604011.1
                    order_status: awaiting_shipment
                    order_status_label: Awaiting Shipment
                    order_status_color: warning
                    customer_email: bob@example.com
                    order_date: '2026-06-01T09:11:42+00:00'
                    ship_date: null
                    ship_by_date: '2026-06-03T07:00:00+00:00'
                    carrier_code: null
                    service_code: null
                    tracking_number: null
                    tracking_url: null
                    shipments:
                    - id: 101
                      shipstation_shipment_id: 987654321
                      tracking_number: '9400111899560000000001'
                      tracking_url: https://tools.usps.com/go/TrackConfirmAction?tLabels=9400111899560000000001
                      carrier_code: stamps_com
                      service_code: usps_priority_mail
                      package_code: package
                      confirmation: delivery
                      shipment_cost: 7.42
                      voided: false
                      is_return_label: false
                      ship_date: '2026-06-08T00:00:00+00:00'
                      create_date: '2026-06-08T14:22:10+00:00'
                      link_route: /integrations/shipstation/4/shipments/101
                    sku_fulfillment: null
                    has_detailed_data: false
                    details_last_updated: null
                    created_at: '2026-06-01T09:15:00+00:00'
                    updated_at: '2026-06-01T09:15:00+00:00'
                  first_page_url: '{{protocol}}://{{domain}}/api/shipstation/integration-instances/7/orders?page=1'
                  from: 1
                  last_page: 21
                  last_page_url: '{{protocol}}://{{domain}}/api/shipstation/integration-instances/7/orders?page=21'
                  links: []
                  next_page_url: '{{protocol}}://{{domain}}/api/shipstation/integration-instances/7/orders?page=2'
                  path: '{{protocol}}://{{domain}}/api/shipstation/integration-instances/7/orders'
                  per_page: 10
                  prev_page_url: null
                  to: 10
                  total: 204
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shipstation-integration-instances-integration-instance-orders
  /api/shipstation/integration-instances/{integration_instance}/orders/search:
    post:
      tags:
      - ShipStation
      summary: Search Orders (Live)
      description: 'Search ShipStation **live** for orders matching a phrase, for
        the refresh modal''s "Search Specific Order" tab. ShipStation''s V1 `orderNumber`
        filter is a **starts-with** match, so the query should be an order number
        or its prefix (up to 50 results are fetched). Each result is flagged with
        whether it already exists in this instance''s local cache so the UI can offer
        Download (new) vs Update (existing).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Body parameters:**

        - `query` — **required** string (max 255). The order number (or prefix) to
        search for.


        **Errors:**

        - 422 if `query` is missing or exceeds 255 chars

        - 502 if the upstream ShipStation call fails (message: `Search failed: ...`)


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                query:
                  type: string
              example:
                query: C604018
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        shipstation_order_id:
                          type: integer
                        order_number:
                          type: string
                        status:
                          type: string
                        order_date:
                          type: string
                        email:
                          type: string
                        exists_in_database:
                          type: boolean
                        database_id:
                          type: integer
                  status:
                    type: string
                example:
                  data:
                  - shipstation_order_id: 987654321
                    order_number: C604018.1
                    status: shipped
                    order_date: '2026-06-01T07:22:10.0000000'
                    email: jane@example.com
                    exists_in_database: true
                    database_id: 412
                  - shipstation_order_id: 987654399
                    order_number: C604018.2
                    status: awaiting_shipment
                    order_date: '2026-06-01T07:25:44.0000000'
                    email: jane@example.com
                    exists_in_database: false
                    database_id: null
                  status: Success
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      query:
                        type: array
                        items:
                          type: string
                example:
                  message: The query field is required.
                  errors:
                    query:
                    - The query field is required.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-shipstation-integration-instances-integration-instance-orders-search
  /api/shipstation/integration-instances/{integration_instance}/orders/sync:
    post:
      tags:
      - ShipStation
      summary: Sync Orders
      description: 'Queue a background orders sync from ShipStation into the local
        cache. Dispatches a tracked job (a background job, job name `Sync ShipStation
        Orders: {instance name}`) and returns its `tracked_job_log_id` for polling
        via the tracked job log endpoints or the `sync-progress` endpoint.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Body parameters (all optional):**

        - `mode` — string. One of `since_latest` | `date_range` | `all`. With `all`
        the job ignores any start date and pulls full history; with `date_range` use
        `date_from`/`date_to`; with `since_latest` the job resumes from the most recently
        synced order.

        - `date_from` — date/datetime string (Carbon-parseable). Start bound for the
        fetch. (`since_date` is accepted as a deprecated alias for backward compatibility
        with the previous one-click refresh payload.)

        - `date_to` — date/datetime string (Carbon-parseable). Optional end bound
        (date_range mode).


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                mode:
                  type: string
                date_from:
                  type: string
                date_to:
                  type: string
              example:
                mode: date_range
                date_from: '2026-05-01'
                date_to: '2026-05-31'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                  status:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 5821
                  message: Order sync queued
                  status: Success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-shipstation-integration-instances-integration-instance-orders-sync
  /api/shipstation/integration-instances/{integration_instance}/orders/sync-info:
    get:
      tags:
      - ShipStation
      summary: Sync Info
      description: 'Header data for the orders refresh modal: the most recently dated
        order (number + ISO-8601 order date), the total cached order count, and the
        effective **order start date** the "Fetch from Start Date" sync option will
        use.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        `order_start_date_source` explains where the start date came from, falling
        back in order:

        1. `ShipStation Order Start Date` — set on the integration instance

        2. `Inventory Start Date` — the general inventory settings start date

        3. `Default sync window (last 30 days)` — a fixed 30-day window used when
        neither start date is configured


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      latest_order_number:
                        type: string
                      latest_order_date:
                        type: string
                      total_orders:
                        type: integer
                      order_start_date:
                        type: string
                      order_start_date_source:
                        type: string
                  status:
                    type: string
                example:
                  data:
                    latest_order_number: C604018.1
                    latest_order_date: '2026-06-01T14:22:10+00:00'
                    total_orders: 204
                    order_start_date: '2025-01-01'
                    order_start_date_source: ShipStation Order Start Date
                  status: Success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shipstation-integration-instances-integration-instance-orders-sync-info
  /api/shipstation/integration-instances/{integration_instance}/orders/sync-progress/{trackedJobLogId}:
    get:
      tags:
      - ShipStation
      summary: Sync Progress
      description: 'Poll the progress of a queued orders sync by its tracked job log
        id (returned by POST `/orders/sync`).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        The job must be a ShipStation sync (`job_name` starting with `Sync ShipStation`)
        belonging to this integration instance — matched either by the job name suffix
        (`: {instance name}`) or by the log''s related model (`ShipstationIntegrationInstance`
        + instance id). Anything else returns **404 Job not found** (also returned
        when the id does not exist).


        `status` is the TrackedJobLog status enum value (e.g. `pending`, `processing`,
        `completed`, `failed`, `cancelled`).


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: trackedJobLogId
        in: path
        schema:
          type: integer
        required: true
        description: The tracked_job_log_id returned by POST /orders/sync.
        example: '5821'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      status:
                        type: string
                      job_name:
                        type: string
                      total_items:
                        type: integer
                      processed_items:
                        type: integer
                      progress_percentage:
                        type: integer
                      messages:
                        type: array
                        items:
                          type: string
                      results:
                        type: string
                        nullable: true
                      completed_at:
                        type: string
                        nullable: true
                  status:
                    type: string
                example:
                  data:
                    id: 5821
                    status: processing
                    job_name: 'Sync ShipStation Orders: My ShipStation'
                    total_items: 500
                    processed_items: 240
                    progress_percentage: 48
                    messages:
                    - Fetched page 3 of 5
                    results: null
                    completed_at: null
                  status: Success
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  status:
                    type: string
                example:
                  message: Job not found
                  status: Error
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-shipstation-integration-instances-integration-instance-orders-sync-progress-trackedjoblogid
  /api/shipstation/integration-instances/{integration_instance}/orders/refresh-order:
    post:
      tags:
      - ShipStation
      summary: Refresh Single Order
      description: 'Download (or update) a single order **live** from ShipStation
        by its ShipStation order id and upsert it into the local cache with detailed
        data (`has_detailed_data: true`, `details_last_updated` stamped). Backs the
        search tab''s per-result Download/Update buttons. Newly downloaded orders
        are auto-linked to a matching SKU fulfillment when an unambiguous match exists.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Body parameters:**

        - `uniqueId` — **required** string. The ShipStation order id (`shipstation_order_id`
        / `orderId`, as returned by the live search endpoint).


        Returns the persisted order serialized with `json_object` included.


        **Errors:**

        - 422 if `uniqueId` is missing

        - 502 if the upstream ShipStation fetch or persistence fails (message: `Failed
        to refresh order: ...`)


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                uniqueId:
                  type: string
              example:
                uniqueId: '987654321'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      shipstation_order_id:
                        type: integer
                      order_key:
                        type: string
                      order_number:
                        type: string
                      order_status:
                        type: string
                      order_status_label:
                        type: string
                      order_status_color:
                        type: string
                      customer_email:
                        type: string
                      order_date:
                        type: string
                      ship_date:
                        type: string
                      ship_by_date:
                        type: string
                      carrier_code:
                        type: string
                      service_code:
                        type: string
                      tracking_number:
                        type: string
                      tracking_url:
                        type: string
                      sku_fulfillment:
                        type: string
                        nullable: true
                      has_detailed_data:
                        type: boolean
                      details_last_updated:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      json_object:
                        type: object
                        properties:
                          orderId:
                            type: integer
                          orderNumber:
                            type: string
                          orderStatus:
                            type: string
                          items:
                            type: array
                            items:
                              type: object
                              properties:
                                sku:
                                  type: string
                                quantity:
                                  type: integer
                  message:
                    type: string
                  status:
                    type: string
                example:
                  data:
                    id: 412
                    integration_instance_id: 7
                    shipstation_order_id: 987654321
                    order_key: a1b2c3d4e5f6
                    order_number: C604018.1
                    order_status: shipped
                    order_status_label: Shipped
                    order_status_color: success
                    customer_email: jane@example.com
                    order_date: '2026-06-01T14:22:10+00:00'
                    ship_date: '2026-06-02T18:05:00+00:00'
                    ship_by_date: '2026-06-04T07:00:00+00:00'
                    carrier_code: fedex
                    service_code: fedex_ground
                    tracking_number: '781234567890'
                    tracking_url: https://www.fedex.com/fedextrack/?trknbr=781234567890
                    sku_fulfillment: null
                    has_detailed_data: true
                    details_last_updated: '2026-06-10T11:02:33+00:00'
                    created_at: '2026-06-01T14:25:00+00:00'
                    updated_at: '2026-06-10T11:02:33+00:00'
                    json_object:
                      orderId: 987654321
                      orderNumber: C604018.1
                      orderStatus: shipped
                      items:
                      - sku: WIDGET-1
                        quantity: 2
                  message: Order refreshed from ShipStation
                  status: Success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-shipstation-integration-instances-integration-instance-orders-refresh-order
  /api/shipstation/integration-instances/{integration_instance}/orders/submit-fulfillment:
    post:
      tags:
      - ShipStation
      summary: Submit Fulfillment
      description: 'Manually re-dispatch a SKU.io SalesOrderFulfillment''s sales order
        to ShipStation via the canonical operator-initiated FulfillmentDispatcher.
        On the `defer_dispatch_sof` canary this submits the FulfillmentOrder with
        NO SalesOrderFulfillment at submit (the shipment SOF is minted at ship); it
        is idempotent — already-submitted FulfillmentOrders are skipped.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Body parameters:**

        - `sku_fulfillment_id` — **required** integer. A SalesOrderFulfillment id;
        its sales order is dispatched.


        **Errors:**

        - 400 if `sku_fulfillment_id` is missing (message: `sku_fulfillment_id required`)

        - 404 if the fulfillment (`Fulfillment not found`) or its sales order (`Sales
        order not found`) does not exist

        - 502 if the dispatch fails (message: `Failed to submit fulfillment: ...`)


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                sku_fulfillment_id:
                  type: integer
              example:
                sku_fulfillment_id: 650
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      sales_order_id:
                        type: integer
                  message:
                    type: string
                  status:
                    type: string
                example:
                  data:
                    sales_order_id: 12345
                  message: Order dispatched to ShipStation
                  status: Success
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  status:
                    type: string
                example:
                  message: Fulfillment not found
                  status: Error
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-shipstation-integration-instances-integration-instance-orders-submit-fulfillment
  /api/shipstation/integration-instances/{integration_instance}/orders/{order}:
    get:
      tags:
      - ShipStation
      summary: Get Order
      description: 'Returns a single ShipStation order from the local cache, serialized
        via ShipStation order object. Includes the order status (value + label + color),
        carrier/service codes, a resolved `tracking_url` (derived from `carrier_code`
        + `tracking_number` via `ShipstationTrackingUrl::resolve`), and the linked
        SKU.io sales order fulfillment (`sku_fulfillment`, null when not linked).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        When `include_json=1` (or `true`) is supplied, the raw ShipStation JSON payload
        is included as `json_object`.


        Returns 404 when the order does not belong to the given integration instance.


        Authentication: Requires Bearer token.


        Each order includes a `shipments` array of linked ShipStation shipment rows
        (tracking number/URL, carrier + service, cost, voided / return-label flags,
        ship date, and a `link_route` to the shipment detail page), sorted by ship
        date descending.


        **product_links** — when `include_json=1`, the response also includes `product_links`:
        a map of lowercased item SKU → `{ id, name, link_route }` resolving the raw
        payload''s item SKUs (shipmentItems for shipments, items for orders) to local
        SKU.io products at `/products/{id}`. SKUs with no matching local product are
        absent from the map.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: order
        in: path
        schema:
          type: integer
        required: true
        description: Internal ShipstationOrder ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      shipstation_order_id:
                        type: string
                      order_key:
                        type: string
                      order_number:
                        type: string
                      order_status:
                        type: string
                      order_status_label:
                        type: string
                      order_status_color:
                        type: string
                      customer_email:
                        type: string
                      order_date:
                        type: string
                      ship_date:
                        type: string
                      ship_by_date:
                        type: string
                        nullable: true
                      carrier_code:
                        type: string
                      service_code:
                        type: string
                      tracking_number:
                        type: string
                      tracking_url:
                        type: string
                      shipments:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            shipstation_shipment_id:
                              type: integer
                            tracking_number:
                              type: string
                            tracking_url:
                              type: string
                            carrier_code:
                              type: string
                            service_code:
                              type: string
                            package_code:
                              type: string
                            confirmation:
                              type: string
                            shipment_cost:
                              type: number
                            voided:
                              type: boolean
                            is_return_label:
                              type: boolean
                            ship_date:
                              type: string
                            create_date:
                              type: string
                            link_route:
                              type: string
                      sku_fulfillment:
                        type: object
                        properties:
                          id:
                            type: integer
                          link_reference:
                            type: integer
                          link_type_label:
                            type: string
                          link_id:
                            type: integer
                          link_route:
                            type: string
                          status:
                            type: string
                          tracking_number:
                            type: string
                          tracking_url:
                            type: string
                          fulfilled_at:
                            type: string
                          created_at:
                            type: string
                          sales_order_number:
                            type: string
                          warehouse:
                            type: object
                            properties:
                              id:
                                type: integer
                              name:
                                type: string
                      has_detailed_data:
                        type: boolean
                      details_last_updated:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 42
                    integration_instance_id: 3
                    shipstation_order_id: '987654321'
                    order_key: manual-7f3b2c9d
                    order_number: SO-10245
                    order_status: shipped
                    order_status_label: Shipped
                    order_status_color: success
                    customer_email: jane.doe@example.com
                    order_date: '2026-05-28T14:32:00+00:00'
                    ship_date: '2026-05-29T09:15:00+00:00'
                    ship_by_date: null
                    carrier_code: ups
                    service_code: ups_ground
                    tracking_number: 1Z999AA10123456784
                    tracking_url: https://www.ups.com/track?loc=en_US&tracknum=1Z999AA10123456784
                    shipments:
                    - id: 101
                      shipstation_shipment_id: 987654321
                      tracking_number: '9400111899560000000001'
                      tracking_url: https://tools.usps.com/go/TrackConfirmAction?tLabels=9400111899560000000001
                      carrier_code: stamps_com
                      service_code: usps_priority_mail
                      package_code: package
                      confirmation: delivery
                      shipment_cost: 7.42
                      voided: false
                      is_return_label: false
                      ship_date: '2026-06-08T00:00:00+00:00'
                      create_date: '2026-06-08T14:22:10+00:00'
                      link_route: /integrations/shipstation/4/shipments/101
                    sku_fulfillment:
                      id: 815
                      link_reference: 815
                      link_type_label: Sales Order Fulfillment
                      link_id: 815
                      link_route: /orders/sales-orders/fulfillments/815
                      status: shipped
                      tracking_number: 1Z999AA10123456784
                      tracking_url: https://www.ups.com/track?loc=en_US&tracknum=1Z999AA10123456784
                      fulfilled_at: '2026-05-29T09:20:00+00:00'
                      created_at: '2026-05-28T15:00:00+00:00'
                      sales_order_number: SO-10245
                      warehouse:
                        id: 2
                        name: Main Warehouse
                    has_detailed_data: true
                    details_last_updated: '2026-05-30T08:00:00+00:00'
                    created_at: '2026-05-28T15:00:00+00:00'
                    updated_at: '2026-05-30T08:00:00+00:00'
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Order not found for this instance
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-shipstation-integration-instances-integration-instance-orders-order
  /api/shipstation/integration-instances/{integration_instance}/orders/{order}/detail:
    get:
      tags:
      - ShipStation
      summary: Get Order Detail (raw JSON)
      description: 'Returns the full cached detail for a ShipStation order: the complete
        raw `json_object` payload (including `items`, addresses, weight, advanced
        options, etc. when full detail has been fetched), plus `has_detailed_data`
        indicating whether the per-order detail endpoint has been synced (via `POST
        .../sync-detail`) and `details_last_updated` for when that happened.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        List-sync only populates summary fields; `has_detailed_data=false` means the
        `json_object` may only contain the list-level payload.


        Returns 404 when the order does not belong to the given integration instance.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: order
        in: path
        schema:
          type: integer
        required: true
        description: Internal ShipstationOrder ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      shipstation_order_id:
                        type: string
                      order_number:
                        type: string
                      json_object:
                        type: object
                        properties:
                          orderId:
                            type: integer
                          orderKey:
                            type: string
                          orderNumber:
                            type: string
                          orderDate:
                            type: string
                          orderStatus:
                            type: string
                          customerEmail:
                            type: string
                          customerUsername:
                            type: string
                          billTo:
                            type: object
                            properties:
                              name:
                                type: string
                          shipTo:
                            type: object
                            properties:
                              name:
                                type: string
                              street1:
                                type: string
                              city:
                                type: string
                              state:
                                type: string
                              postalCode:
                                type: string
                              country:
                                type: string
                          items:
                            type: array
                            items:
                              type: object
                              properties:
                                orderItemId:
                                  type: integer
                                sku:
                                  type: string
                                name:
                                  type: string
                                quantity:
                                  type: integer
                                unitPrice:
                                  type: number
                          carrierCode:
                            type: string
                          serviceCode:
                            type: string
                          orderTotal:
                            type: integer
                          amountPaid:
                            type: integer
                          weight:
                            type: object
                            properties:
                              value:
                                type: integer
                              units:
                                type: string
                      has_detailed_data:
                        type: boolean
                      details_last_updated:
                        type: string
                example:
                  data:
                    id: 42
                    shipstation_order_id: '987654321'
                    order_number: SO-10245
                    json_object:
                      orderId: 987654321
                      orderKey: manual-7f3b2c9d
                      orderNumber: SO-10245
                      orderDate: '2026-05-28T07:32:00.0000000'
                      orderStatus: shipped
                      customerEmail: jane.doe@example.com
                      customerUsername: jane.doe@example.com
                      billTo:
                        name: Jane Doe
                      shipTo:
                        name: Jane Doe
                        street1: 123 Main St
                        city: Austin
                        state: TX
                        postalCode: '78701'
                        country: US
                      items:
                      - orderItemId: 555001
                        sku: WIDGET-L
                        name: Large Widget
                        quantity: 2
                        unitPrice: 19.99
                      carrierCode: ups
                      serviceCode: ups_ground
                      orderTotal: 52
                      amountPaid: 52
                      weight:
                        value: 24
                        units: ounces
                    has_detailed_data: true
                    details_last_updated: '2026-05-30T08:00:00+00:00'
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Order not found for this instance
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-shipstation-integration-instances-integration-instance-orders-order-detail
  /api/shipstation/integration-instances/{integration_instance}/orders/{order}/webhook-events:
    get:
      tags:
      - ShipStation
      summary: Get Order Webhook Events
      description: 'Recent webhook events scoped to this single ShipStation order,
        matched on the order''s `order_number`, `tracking_number` or `shipstation_order_id`.
        Used by the order detail page to render a per-order webhook audit trail.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Each event is serialized via ShipStation webhook event object and includes
        the event type (value + label + color), the ShipStation `resource_url`/`resource_type`,
        whether the resource was fetched, signature validation status, the raw `payload`,
        processing state (`processed`, `processed_at`, `error_message`) and the `dedup_key`.


        Returns 404 when the order does not belong to the given integration instance.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: order
        in: path
        schema:
          type: integer
        required: true
        description: Internal ShipstationOrder ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        event_type:
                          type: string
                        event_type_label:
                          type: string
                        event_type_color:
                          type: string
                        resource_url:
                          type: string
                        resource_type:
                          type: string
                        resource_fetched:
                          type: boolean
                        order_number:
                          type: string
                        shipstation_order_id:
                          type: integer
                        tracking_number:
                          type: string
                        signature_valid:
                          type: boolean
                        payload:
                          type: object
                          properties:
                            resource_url:
                              type: string
                            resource_type:
                              type: string
                        processed:
                          type: boolean
                        processed_at:
                          type: string
                        error_message:
                          type: string
                          nullable: true
                        dedup_key:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                example:
                  data:
                  - id: 311
                    integration_instance_id: 3
                    event_type: SHIP_NOTIFY
                    event_type_label: Ship Notify
                    event_type_color: success
                    resource_url: https://ssapi.shipstation.com/orders?importBatch=1abc2def-3ghi-4jkl-5mno-6pqr7stu8vwx
                    resource_type: SHIP_NOTIFY
                    resource_fetched: true
                    order_number: SO-10245
                    shipstation_order_id: 987654321
                    tracking_number: 1Z999AA10123456784
                    signature_valid: true
                    payload:
                      resource_url: https://ssapi.shipstation.com/orders?importBatch=1abc2def-3ghi-4jkl-5mno-6pqr7stu8vwx
                      resource_type: SHIP_NOTIFY
                    processed: true
                    processed_at: '2026-05-29T09:21:30+00:00'
                    error_message: null
                    dedup_key: ship_notify-987654321-1Z999AA10123456784
                    created_at: '2026-05-29T09:21:28+00:00'
                    updated_at: '2026-05-29T09:21:30+00:00'
                  - id: 298
                    integration_instance_id: 3
                    event_type: ORDER_NOTIFY
                    event_type_label: Order Notify
                    event_type_color: info
                    resource_url: https://ssapi.shipstation.com/orders?importBatch=9zyx8wvu-7tsr-6qpo-5nml-4kji3hgf2edc
                    resource_type: ORDER_NOTIFY
                    resource_fetched: true
                    order_number: SO-10245
                    shipstation_order_id: 987654321
                    tracking_number: null
                    signature_valid: true
                    payload:
                      resource_url: https://ssapi.shipstation.com/orders?importBatch=9zyx8wvu-7tsr-6qpo-5nml-4kji3hgf2edc
                      resource_type: ORDER_NOTIFY
                    processed: true
                    processed_at: '2026-05-28T15:01:02+00:00'
                    error_message: null
                    dedup_key: order_notify-987654321
                    created_at: '2026-05-28T15:01:00+00:00'
                    updated_at: '2026-05-28T15:01:02+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shipstation-integration-instances-integration-instance-orders-order-webhook-events
  /api/shipstation/integration-instances/{integration_instance}/orders/{order}/tracking:
    post:
      tags:
      - ShipStation
      summary: Refresh Order Tracking
      description: 'Refreshes tracking for a single order live from ShipStation''s
        V1 `/shipments` endpoint (looked up by the order''s ShipStation order ID),
        persists the tracking number / carrier / ship date to the local order cache,
        and applies the tracking to the linked SKU.io SalesOrderFulfillment (if any).
        Mirrors the Starshipit "Refresh Order Tracking" endpoint.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        No request body. Returns the refreshed order (with `json_object` included)
        and the message "Tracking refreshed from ShipStation".


        Errors: 404 when the order does not belong to the instance; 400 when the order
        has no `shipstation_order_id`; 502 when the live ShipStation call fails.


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: order
        in: path
        schema:
          type: integer
        required: true
        description: Internal ShipstationOrder ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      shipstation_order_id:
                        type: string
                      order_key:
                        type: string
                      order_number:
                        type: string
                      order_status:
                        type: string
                      order_status_label:
                        type: string
                      order_status_color:
                        type: string
                      customer_email:
                        type: string
                      order_date:
                        type: string
                      ship_date:
                        type: string
                      ship_by_date:
                        type: string
                        nullable: true
                      carrier_code:
                        type: string
                      service_code:
                        type: string
                      tracking_number:
                        type: string
                      tracking_url:
                        type: string
                      sku_fulfillment:
                        type: object
                        properties:
                          id:
                            type: integer
                          link_reference:
                            type: integer
                          link_type_label:
                            type: string
                          link_id:
                            type: integer
                          link_route:
                            type: string
                          status:
                            type: string
                          tracking_number:
                            type: string
                          tracking_url:
                            type: string
                          fulfilled_at:
                            type: string
                          created_at:
                            type: string
                          sales_order_number:
                            type: string
                          warehouse:
                            type: object
                            properties:
                              id:
                                type: integer
                              name:
                                type: string
                      has_detailed_data:
                        type: boolean
                      details_last_updated:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      json_object:
                        type: object
                        properties:
                          orderId:
                            type: integer
                          orderNumber:
                            type: string
                          orderStatus:
                            type: string
                  message:
                    type: string
                example:
                  data:
                    id: 42
                    integration_instance_id: 3
                    shipstation_order_id: '987654321'
                    order_key: manual-7f3b2c9d
                    order_number: SO-10245
                    order_status: shipped
                    order_status_label: Shipped
                    order_status_color: success
                    customer_email: jane.doe@example.com
                    order_date: '2026-05-28T14:32:00+00:00'
                    ship_date: '2026-05-29T09:15:00+00:00'
                    ship_by_date: null
                    carrier_code: ups
                    service_code: ups_ground
                    tracking_number: 1Z999AA10123456784
                    tracking_url: https://www.ups.com/track?loc=en_US&tracknum=1Z999AA10123456784
                    sku_fulfillment:
                      id: 815
                      link_reference: 815
                      link_type_label: Sales Order Fulfillment
                      link_id: 815
                      link_route: /orders/sales-orders/fulfillments/815
                      status: shipped
                      tracking_number: 1Z999AA10123456784
                      tracking_url: https://www.ups.com/track?loc=en_US&tracknum=1Z999AA10123456784
                      fulfilled_at: '2026-05-29T09:20:00+00:00'
                      created_at: '2026-05-28T15:00:00+00:00'
                      sales_order_number: SO-10245
                      warehouse:
                        id: 2
                        name: Main Warehouse
                    has_detailed_data: true
                    details_last_updated: '2026-05-30T08:00:00+00:00'
                    created_at: '2026-05-28T15:00:00+00:00'
                    updated_at: '2026-06-10T10:05:00+00:00'
                    json_object:
                      orderId: 987654321
                      orderNumber: SO-10245
                      orderStatus: shipped
                  message: Tracking refreshed from ShipStation
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Order is missing a ShipStation order ID, which is required
                    to look up shipments.
        '502':
          description: Bad Gateway
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 'Failed to refresh tracking: HTTP request returned status
                    code 429'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-shipstation-integration-instances-integration-instance-orders-order-tracking
  /api/shipstation/integration-instances/{integration_instance}/orders/{order}/sync-detail:
    post:
      tags:
      - ShipStation
      summary: Sync Order Detail
      description: 'Fetches the full order detail for a single order live from the
        ShipStation API, replacing the cached `json_object` with the complete per-order
        payload (items, addresses, weight, advanced options) and setting `has_detailed_data=true`
        + `details_last_updated`.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        No request body. Returns the refreshed order serialized via ShipStation order
        object with `json_object` included so the detail page can re-render items
        / packages / raw data immediately.


        Errors: 404 when the order does not belong to the instance; 502 when the live
        ShipStation call fails.


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: order
        in: path
        schema:
          type: integer
        required: true
        description: Internal ShipstationOrder ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      shipstation_order_id:
                        type: string
                      order_key:
                        type: string
                      order_number:
                        type: string
                      order_status:
                        type: string
                      order_status_label:
                        type: string
                      order_status_color:
                        type: string
                      customer_email:
                        type: string
                      order_date:
                        type: string
                      ship_date:
                        type: string
                      ship_by_date:
                        type: string
                        nullable: true
                      carrier_code:
                        type: string
                      service_code:
                        type: string
                      tracking_number:
                        type: string
                      tracking_url:
                        type: string
                      sku_fulfillment:
                        type: string
                        nullable: true
                      has_detailed_data:
                        type: boolean
                      details_last_updated:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      json_object:
                        type: object
                        properties:
                          orderId:
                            type: integer
                          orderNumber:
                            type: string
                          orderStatus:
                            type: string
                          items:
                            type: array
                            items:
                              type: object
                              properties:
                                orderItemId:
                                  type: integer
                                sku:
                                  type: string
                                name:
                                  type: string
                                quantity:
                                  type: integer
                                unitPrice:
                                  type: number
                          shipTo:
                            type: object
                            properties:
                              name:
                                type: string
                              city:
                                type: string
                              state:
                                type: string
                              country:
                                type: string
                          weight:
                            type: object
                            properties:
                              value:
                                type: integer
                              units:
                                type: string
                example:
                  data:
                    id: 42
                    integration_instance_id: 3
                    shipstation_order_id: '987654321'
                    order_key: manual-7f3b2c9d
                    order_number: SO-10245
                    order_status: shipped
                    order_status_label: Shipped
                    order_status_color: success
                    customer_email: jane.doe@example.com
                    order_date: '2026-05-28T14:32:00+00:00'
                    ship_date: '2026-05-29T09:15:00+00:00'
                    ship_by_date: null
                    carrier_code: ups
                    service_code: ups_ground
                    tracking_number: 1Z999AA10123456784
                    tracking_url: https://www.ups.com/track?loc=en_US&tracknum=1Z999AA10123456784
                    sku_fulfillment: null
                    has_detailed_data: true
                    details_last_updated: '2026-06-10T10:12:00+00:00'
                    created_at: '2026-05-28T15:00:00+00:00'
                    updated_at: '2026-06-10T10:12:00+00:00'
                    json_object:
                      orderId: 987654321
                      orderNumber: SO-10245
                      orderStatus: shipped
                      items:
                      - orderItemId: 555001
                        sku: WIDGET-L
                        name: Large Widget
                        quantity: 2
                        unitPrice: 19.99
                      shipTo:
                        name: Jane Doe
                        city: Austin
                        state: TX
                        country: US
                      weight:
                        value: 24
                        units: ounces
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Order not found for this instance
        '502':
          description: Bad Gateway
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 'Failed to fetch order detail: Order 987654321 not found
                    in ShipStation'
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-shipstation-integration-instances-integration-instance-orders-order-sync-detail
  /api/shipstation/integration-instances/{integration_instance}/orders/{order}/link-fulfillment:
    post:
      tags:
      - ShipStation
      summary: Link Order to Fulfillment
      description: 'Manually links a cached ShipStation order to a SKU.io SalesOrderFulfillment
        by setting `sku_fulfillment_id` on the order (matched by its ShipStation order
        ID).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Body fields:

        - `sku_fulfillment_id` (integer, required) — the SalesOrderFulfillment ID
        to link.


        Returns the updated order (with `json_object` included and the populated `sku_fulfillment`
        object).


        Errors: 400 when `sku_fulfillment_id` is missing/zero; 404 when the order
        does not belong to the instance, or when no cached order with that ShipStation
        order ID exists.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                sku_fulfillment_id:
                  type: integer
              example:
                sku_fulfillment_id: 815
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: order
        in: path
        schema:
          type: integer
        required: true
        description: Internal ShipstationOrder ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      shipstation_order_id:
                        type: string
                      order_key:
                        type: string
                      order_number:
                        type: string
                      order_status:
                        type: string
                      order_status_label:
                        type: string
                      order_status_color:
                        type: string
                      customer_email:
                        type: string
                      order_date:
                        type: string
                      ship_date:
                        type: string
                      ship_by_date:
                        type: string
                        nullable: true
                      carrier_code:
                        type: string
                      service_code:
                        type: string
                      tracking_number:
                        type: string
                      tracking_url:
                        type: string
                      sku_fulfillment:
                        type: object
                        properties:
                          id:
                            type: integer
                          link_reference:
                            type: integer
                          link_type_label:
                            type: string
                          link_id:
                            type: integer
                          link_route:
                            type: string
                          status:
                            type: string
                          tracking_number:
                            type: string
                          tracking_url:
                            type: string
                          fulfilled_at:
                            type: string
                          created_at:
                            type: string
                          sales_order_number:
                            type: string
                          warehouse:
                            type: object
                            properties:
                              id:
                                type: integer
                              name:
                                type: string
                      has_detailed_data:
                        type: boolean
                      details_last_updated:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      json_object:
                        type: object
                        properties:
                          orderId:
                            type: integer
                          orderNumber:
                            type: string
                          orderStatus:
                            type: string
                example:
                  data:
                    id: 42
                    integration_instance_id: 3
                    shipstation_order_id: '987654321'
                    order_key: manual-7f3b2c9d
                    order_number: SO-10245
                    order_status: shipped
                    order_status_label: Shipped
                    order_status_color: success
                    customer_email: jane.doe@example.com
                    order_date: '2026-05-28T14:32:00+00:00'
                    ship_date: '2026-05-29T09:15:00+00:00'
                    ship_by_date: null
                    carrier_code: ups
                    service_code: ups_ground
                    tracking_number: 1Z999AA10123456784
                    tracking_url: https://www.ups.com/track?loc=en_US&tracknum=1Z999AA10123456784
                    sku_fulfillment:
                      id: 815
                      link_reference: 815
                      link_type_label: Sales Order Fulfillment
                      link_id: 815
                      link_route: /orders/sales-orders/fulfillments/815
                      status: shipped
                      tracking_number: 1Z999AA10123456784
                      tracking_url: https://www.ups.com/track?loc=en_US&tracknum=1Z999AA10123456784
                      fulfilled_at: '2026-05-29T09:20:00+00:00'
                      created_at: '2026-05-28T15:00:00+00:00'
                      sales_order_number: SO-10245
                      warehouse:
                        id: 2
                        name: Main Warehouse
                    has_detailed_data: true
                    details_last_updated: '2026-05-30T08:00:00+00:00'
                    created_at: '2026-05-28T15:00:00+00:00'
                    updated_at: '2026-06-10T10:20:00+00:00'
                    json_object:
                      orderId: 987654321
                      orderNumber: SO-10245
                      orderStatus: shipped
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: sku_fulfillment_id required
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Order not found
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-shipstation-integration-instances-integration-instance-orders-order-link-fulfillment
  /api/shipstation/integration-instances/{integration_instance}/orders/{order}/unlink-fulfillment:
    post:
      tags:
      - ShipStation
      summary: Unlink Order from Fulfillment
      description: 'Removes the manual link between a cached ShipStation order and
        its SKU.io SalesOrderFulfillment by clearing `sku_fulfillment_id` on the order.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        No request body. Returns the updated order (with `json_object` included) —
        `sku_fulfillment` is null after unlinking.


        Returns 404 when the order does not belong to the given integration instance.


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: order
        in: path
        schema:
          type: integer
        required: true
        description: Internal ShipstationOrder ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      shipstation_order_id:
                        type: string
                      order_key:
                        type: string
                      order_number:
                        type: string
                      order_status:
                        type: string
                      order_status_label:
                        type: string
                      order_status_color:
                        type: string
                      customer_email:
                        type: string
                      order_date:
                        type: string
                      ship_date:
                        type: string
                      ship_by_date:
                        type: string
                        nullable: true
                      carrier_code:
                        type: string
                      service_code:
                        type: string
                      tracking_number:
                        type: string
                      tracking_url:
                        type: string
                      sku_fulfillment:
                        type: string
                        nullable: true
                      has_detailed_data:
                        type: boolean
                      details_last_updated:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      json_object:
                        type: object
                        properties:
                          orderId:
                            type: integer
                          orderNumber:
                            type: string
                          orderStatus:
                            type: string
                example:
                  data:
                    id: 42
                    integration_instance_id: 3
                    shipstation_order_id: '987654321'
                    order_key: manual-7f3b2c9d
                    order_number: SO-10245
                    order_status: shipped
                    order_status_label: Shipped
                    order_status_color: success
                    customer_email: jane.doe@example.com
                    order_date: '2026-05-28T14:32:00+00:00'
                    ship_date: '2026-05-29T09:15:00+00:00'
                    ship_by_date: null
                    carrier_code: ups
                    service_code: ups_ground
                    tracking_number: 1Z999AA10123456784
                    tracking_url: https://www.ups.com/track?loc=en_US&tracknum=1Z999AA10123456784
                    sku_fulfillment: null
                    has_detailed_data: true
                    details_last_updated: '2026-05-30T08:00:00+00:00'
                    created_at: '2026-05-28T15:00:00+00:00'
                    updated_at: '2026-06-10T10:25:00+00:00'
                    json_object:
                      orderId: 987654321
                      orderNumber: SO-10245
                      orderStatus: shipped
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Order not found for this instance
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-shipstation-integration-instances-integration-instance-orders-order-unlink-fulfillment
  /api/shipstation/{integration_instance}/download-shipping-services:
    post:
      tags:
      - ShipStation
      summary: Download Shipping Services
      description: 'Download available shipping services from ShipStation and seed
        them into the shipping method mapping table.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token + Power User access.'
      requestBody:
        content: {}
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        example: '5'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        shipping_provider_id:
                          type: integer
                        shipping_provider_carrier:
                          type: string
                        shipping_provider_method:
                          type: string
                        shipping_method_id:
                          type: integer
                        shipping_method_name:
                          type: string
                  status:
                    type: string
                example:
                  data:
                  - id: 1
                    shipping_provider_id: 5
                    shipping_provider_carrier: stamps_com
                    shipping_provider_method: usps_first_class_mail
                    shipping_method_id: 12
                    shipping_method_name: USPS First Class
                  status: success
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: object
                    properties:
                      id:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: array
                example:
                  errors:
                    id:
                    - message: Unable to retrieve shipping services from ShipStation.
                      code: IntegrationApiError
                      data: []
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-session-only: true
      operationId: post-api-shipstation-integration-instance-download-shipping-services
  /api/shipstation/integration-instances/{integration_instance}/orders/{order}/activity-log:
    get:
      tags:
      - ShipStation
      summary: Get Order Activity Log
      description: 'Paginated Spatie activity-log entries for a single Shipstation
        order (by local row id) — the order detail page''s Activity Log tab. Each
        entry: id, description, event (created/updated/deleted), subject_type, subject_id,
        properties (changed attributes), causer_name, created_at. Ordered newest first.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Pagination: page (default 1), per_page (default 15).


        Authentication: Requires Bearer token.


        Filters: filter[event] (exact event), filter[source] (matches properties->source),
        filter[batch_uuid] (exact batch uuid), filter[search] (LIKE over causer name
        / properties / event).'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: order
        in: path
        schema:
          type: integer
        required: true
        description: Internal ShipstationOrder ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        description:
                          type: string
                        event:
                          type: string
                        subject_type:
                          type: string
                        subject_id:
                          type: integer
                        properties:
                          type: object
                          properties:
                            attributes:
                              type: object
                              properties:
                                tracking_number:
                                  type: string
                            old:
                              type: object
                              properties:
                                tracking_number:
                                  type: string
                                  nullable: true
                        causer_name:
                          type: string
                        created_at:
                          type: string
                  current_page:
                    type: integer
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 90412
                    description: updated
                    event: updated
                    subject_type: ShipstationOrder
                    subject_id: 42
                    properties:
                      attributes:
                        tracking_number: 1Z999AA10123456784
                      old:
                        tracking_number: null
                    causer_name: Sync Job
                    created_at: '2026-06-11T14:33:00.000000Z'
                  - id: 90380
                    description: created
                    event: created
                    subject_type: ShipstationOrder
                    subject_id: 42
                    properties:
                      attributes:
                        order_number: SO-100245
                    causer_name: null
                    created_at: '2026-06-10T09:15:00.000000Z'
                  current_page: 1
                  first_page_url: '{{protocol}}://{{domain}}/api/shipstation/...?page=1'
                  from: 1
                  last_page: 1
                  per_page: 15
                  to: 2
                  total: 2
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Order not found for this instance
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-shipstation-integration-instances-integration-instance-orders-order-activity-log
  /api/shipstation/integration-instances/{integrationInstance}/shipments:
    get:
      tags:
      - ShipStation
      summary: List Shipments
      description: 'List label shipments for a ShipStation integration instance (paginated).
        Backed by the dedicated shipstation_shipments table populated from ShipStation''s
        GET /shipments endpoint.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Free-text search (filter[search]) matches tracking_number, shipstation_shipment_id,
        order_number, carrier_code, service_code (Typesense-backed when available,
        with DB LIKE fallback).


        Allowed sorts: id, shipstation_shipment_id, order_number, tracking_number,
        carrier_code, service_code, package_code, shipment_cost, weight_value, voided,
        ship_date, create_date, created_at, updated_at. Prefix with - for DESC. Default
        sort: -ship_date.


        Advanced filter operators are supported per column via the AdvancedFiltersModal
        (text operators on order_number/tracking_number/carrier_code/service_code/package_code/confirmation/warehouse_id,
        numeric on id/shipstation_shipment_id/weight_value/shipment_cost, datetime
        on ship_date/create_date/created_at/updated_at).


        Pass include_json=1 to include the raw ShipStation payload (json_object) on
        each row.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        shipstation_shipment_id:
                          type: integer
                        order_id:
                          type: integer
                        shipstation_order_id:
                          type: integer
                        order_number:
                          type: string
                        tracking_number:
                          type: string
                        tracking_url:
                          type: string
                        carrier_code:
                          type: string
                        service_code:
                          type: string
                        package_code:
                          type: string
                        confirmation:
                          type: string
                        warehouse_id:
                          type: string
                        weight_value:
                          type: number
                        weight_units:
                          type: string
                        length:
                          type: integer
                        width:
                          type: integer
                        height:
                          type: integer
                        dimension_units:
                          type: string
                        shipment_cost:
                          type: number
                        insurance_cost:
                          type: integer
                        voided:
                          type: boolean
                        void_date:
                          type: string
                          nullable: true
                        is_return_label:
                          type: boolean
                        batch_number:
                          type: string
                        ship_date:
                          type: string
                        create_date:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                        order:
                          type: object
                          properties:
                            id:
                              type: integer
                            order_number:
                              type: string
                            shipstation_order_id:
                              type: integer
                            link_reference:
                              type: string
                            link_type_label:
                              type: string
                            link_id:
                              type: integer
                            link_route:
                              type: string
                        sku_fulfillment_id:
                          type: integer
                        sku_fulfillment_status:
                          type: string
                        sales_order_id:
                          type: integer
                        sales_order_number:
                          type: string
                        sales_order_legacy_url:
                          type: string
                        warehouse:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                  first_page_url:
                    type: string
                  last_page_url:
                    type: string
                  next_page_url:
                    type: string
                  prev_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  links:
                    type: array
                example:
                  data:
                  - id: 101
                    integration_instance_id: 4
                    shipstation_shipment_id: 987654321
                    order_id: 2456
                    shipstation_order_id: 123456789
                    order_number: SS-10342
                    tracking_number: '9400111899560000000001'
                    tracking_url: https://tools.usps.com/go/TrackConfirmAction?tLabels=9400111899560000000001
                    carrier_code: stamps_com
                    service_code: usps_priority_mail
                    package_code: package
                    confirmation: delivery
                    warehouse_id: '12345'
                    weight_value: 14.5
                    weight_units: ounces
                    length: 10
                    width: 8
                    height: 4
                    dimension_units: inches
                    shipment_cost: 7.42
                    insurance_cost: 0
                    voided: false
                    void_date: null
                    is_return_label: false
                    batch_number: '100301'
                    ship_date: '2026-06-08T00:00:00+00:00'
                    create_date: '2026-06-08T14:22:10+00:00'
                    created_at: '2026-06-08T14:25:00+00:00'
                    updated_at: '2026-06-08T14:25:00+00:00'
                    order:
                      id: 2456
                      order_number: SS-10342
                      shipstation_order_id: 123456789
                      link_reference: SS-10342
                      link_type_label: ShipStation Order
                      link_id: 2456
                      link_route: /integrations/shipstation/4/orders/2456
                    sku_fulfillment_id: 778
                    sku_fulfillment_status: shipped
                    sales_order_id: 3301
                    sales_order_number: SO-3301
                    sales_order_legacy_url: /sales-orders/3301
                    warehouse:
                      id: 2
                      name: Main Warehouse
                  current_page: 1
                  last_page: 12
                  per_page: 10
                  total: 118
                  from: 1
                  to: 10
                  first_page_url: '...'
                  last_page_url: '...'
                  next_page_url: '...'
                  prev_page_url: null
                  path: '...'
                  links: []
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shipstation-integration-instances-integrationinstance-shipments
  /api/shipstation/integration-instances/{integrationInstance}/shipments/{shipment}:
    get:
      tags:
      - ShipStation
      summary: Get Shipment
      description: 'Get a single ShipStation shipment by local row id. Returns 404
        when the shipment does not belong to the instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        **product_links** — when `include_json=1`, the response also includes `product_links`:
        a map of lowercased item SKU → `{ id, name, link_route }` resolving the raw
        payload''s item SKUs (shipmentItems for shipments, items for orders) to local
        SKU.io products at `/products/{id}`. SKUs with no matching local product are
        absent from the map.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: shipment
        in: path
        schema:
          type: integer
        required: true
        example: '101'
        description: The shipment ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      shipstation_shipment_id:
                        type: integer
                      order_id:
                        type: integer
                      shipstation_order_id:
                        type: integer
                      order_number:
                        type: string
                      tracking_number:
                        type: string
                      tracking_url:
                        type: string
                      carrier_code:
                        type: string
                      service_code:
                        type: string
                      package_code:
                        type: string
                      confirmation:
                        type: string
                      warehouse_id:
                        type: string
                      weight_value:
                        type: number
                      weight_units:
                        type: string
                      length:
                        type: integer
                      width:
                        type: integer
                      height:
                        type: integer
                      dimension_units:
                        type: string
                      shipment_cost:
                        type: number
                      insurance_cost:
                        type: integer
                      voided:
                        type: boolean
                      void_date:
                        type: string
                        nullable: true
                      is_return_label:
                        type: boolean
                      batch_number:
                        type: string
                      ship_date:
                        type: string
                      create_date:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      order:
                        type: object
                        properties:
                          id:
                            type: integer
                          order_number:
                            type: string
                          shipstation_order_id:
                            type: integer
                          link_reference:
                            type: string
                          link_type_label:
                            type: string
                          link_id:
                            type: integer
                          link_route:
                            type: string
                      sku_fulfillment_id:
                        type: integer
                      sku_fulfillment_status:
                        type: string
                      sales_order_id:
                        type: integer
                      sales_order_number:
                        type: string
                      sales_order_legacy_url:
                        type: string
                      warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                  message:
                    type: string
                    nullable: true
                example:
                  data:
                    id: 101
                    integration_instance_id: 4
                    shipstation_shipment_id: 987654321
                    order_id: 2456
                    shipstation_order_id: 123456789
                    order_number: SS-10342
                    tracking_number: '9400111899560000000001'
                    tracking_url: https://tools.usps.com/go/TrackConfirmAction?tLabels=9400111899560000000001
                    carrier_code: stamps_com
                    service_code: usps_priority_mail
                    package_code: package
                    confirmation: delivery
                    warehouse_id: '12345'
                    weight_value: 14.5
                    weight_units: ounces
                    length: 10
                    width: 8
                    height: 4
                    dimension_units: inches
                    shipment_cost: 7.42
                    insurance_cost: 0
                    voided: false
                    void_date: null
                    is_return_label: false
                    batch_number: '100301'
                    ship_date: '2026-06-08T00:00:00+00:00'
                    create_date: '2026-06-08T14:22:10+00:00'
                    created_at: '2026-06-08T14:25:00+00:00'
                    updated_at: '2026-06-08T14:25:00+00:00'
                    order:
                      id: 2456
                      order_number: SS-10342
                      shipstation_order_id: 123456789
                      link_reference: SS-10342
                      link_type_label: ShipStation Order
                      link_id: 2456
                      link_route: /integrations/shipstation/4/orders/2456
                    sku_fulfillment_id: 778
                    sku_fulfillment_status: shipped
                    sales_order_id: 3301
                    sales_order_number: SO-3301
                    sales_order_legacy_url: /sales-orders/3301
                    warehouse:
                      id: 2
                      name: Main Warehouse
                  message: null
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: ''
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-shipstation-integration-instances-integrationinstance-shipments-shipment
  /api/shipstation/integration-instances/{integrationInstance}/shipments/{shipment}/refresh:
    post:
      tags:
      - ShipStation
      summary: Refresh Shipment From ShipStation
      description: 'Fetch fresh shipment data live from the ShipStation API and upsert
        it into the local row, then return the refreshed resource (including the raw
        json_object payload).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        ShipStation V1 has no GET /shipments/{id} endpoint, so the lookup calls List
        Shipments filtered by the shipment''s orderId (falling back to its trackingNumber)
        and matches the shipmentId in the results.


        Returns 404 when the local shipment does not belong to the instance, or when
        ShipStation no longer returns the shipment (e.g. it was removed). Returns
        502 when the ShipStation API call fails.


        Authentication: Requires Bearer token.


        **product_links** — when `include_json=1`, the response also includes `product_links`:
        a map of lowercased item SKU → `{ id, name, link_route }` resolving the raw
        payload''s item SKUs (shipmentItems for shipments, items for orders) to local
        SKU.io products at `/products/{id}`. SKUs with no matching local product are
        absent from the map.'
      requestBody:
        content: {}
      parameters:
      - name: include_json
        in: query
        schema:
          type: integer
        description: Include raw ShipStation payload (json_object) in the response.
          The endpoint forces this on internally, so the refreshed payload is always
          returned.
        example: '1'
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '4'
        description: The integration instance ID.
      - name: shipment
        in: path
        schema:
          type: integer
        required: true
        example: '101'
        description: The shipment ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      shipstation_shipment_id:
                        type: integer
                      order_id:
                        type: integer
                      shipstation_order_id:
                        type: integer
                      order_number:
                        type: string
                      tracking_number:
                        type: string
                      tracking_url:
                        type: string
                      carrier_code:
                        type: string
                      service_code:
                        type: string
                      package_code:
                        type: string
                      confirmation:
                        type: string
                      warehouse_id:
                        type: string
                      weight_value:
                        type: number
                      weight_units:
                        type: string
                      length:
                        type: integer
                      width:
                        type: integer
                      height:
                        type: integer
                      dimension_units:
                        type: string
                      shipment_cost:
                        type: number
                      insurance_cost:
                        type: integer
                      voided:
                        type: boolean
                      void_date:
                        type: string
                        nullable: true
                      is_return_label:
                        type: boolean
                      batch_number:
                        type: string
                      ship_date:
                        type: string
                      create_date:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      json_object:
                        type: object
                        properties:
                          shipmentId:
                            type: integer
                          orderId:
                            type: integer
                          orderNumber:
                            type: string
                          trackingNumber:
                            type: string
                          carrierCode:
                            type: string
                          serviceCode:
                            type: string
                          shipmentCost:
                            type: number
                          voided:
                            type: boolean
                          shipDate:
                            type: string
                          shipmentItems:
                            type: array
                            items:
                              type: object
                              properties:
                                orderItemId:
                                  type: integer
                                sku:
                                  type: string
                                name:
                                  type: string
                                quantity:
                                  type: integer
                      order:
                        type: object
                        properties:
                          id:
                            type: integer
                          order_number:
                            type: string
                          shipstation_order_id:
                            type: integer
                          link_reference:
                            type: string
                          link_type_label:
                            type: string
                          link_id:
                            type: integer
                          link_route:
                            type: string
                      sku_fulfillment_id:
                        type: integer
                      sku_fulfillment_status:
                        type: string
                      sales_order_id:
                        type: integer
                      sales_order_number:
                        type: string
                      sales_order_legacy_url:
                        type: string
                      warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      product_links:
                        type: object
                        properties:
                          l0524v-303-3230-u-1:
                            type: object
                            properties:
                              id:
                                type: integer
                              name:
                                type: string
                              link_route:
                                type: string
                  message:
                    type: string
                example:
                  data:
                    id: 101
                    integration_instance_id: 4
                    shipstation_shipment_id: 987654321
                    order_id: 2456
                    shipstation_order_id: 123456789
                    order_number: SS-10342
                    tracking_number: '9400111899560000000001'
                    tracking_url: https://tools.usps.com/go/TrackConfirmAction?tLabels=9400111899560000000001
                    carrier_code: stamps_com
                    service_code: usps_priority_mail
                    package_code: package
                    confirmation: delivery
                    warehouse_id: '12345'
                    weight_value: 14.5
                    weight_units: ounces
                    length: 10
                    width: 8
                    height: 4
                    dimension_units: inches
                    shipment_cost: 7.42
                    insurance_cost: 0
                    voided: false
                    void_date: null
                    is_return_label: false
                    batch_number: '100301'
                    ship_date: '2026-06-08T00:00:00+00:00'
                    create_date: '2026-06-08T14:22:10+00:00'
                    created_at: '2026-06-08T14:25:00+00:00'
                    updated_at: '2026-06-10T09:12:44+00:00'
                    json_object:
                      shipmentId: 987654321
                      orderId: 123456789
                      orderNumber: SS-10342
                      trackingNumber: '9400111899560000000001'
                      carrierCode: stamps_com
                      serviceCode: usps_priority_mail
                      shipmentCost: 7.42
                      voided: false
                      shipDate: '2026-06-08'
                      shipmentItems:
                      - orderItemId: 555111
                        sku: WIDGET-1
                        name: Widget
                        quantity: 2
                    order:
                      id: 2456
                      order_number: SS-10342
                      shipstation_order_id: 123456789
                      link_reference: SS-10342
                      link_type_label: ShipStation Order
                      link_id: 2456
                      link_route: /integrations/shipstation/4/orders/2456
                    sku_fulfillment_id: 778
                    sku_fulfillment_status: shipped
                    sales_order_id: 3301
                    sales_order_number: SO-3301
                    sales_order_legacy_url: /sales-orders/3301
                    warehouse:
                      id: 2
                      name: Main Warehouse
                    product_links:
                      l0524v-303-3230-u-1:
                        id: 4821
                        name: 24V COB LED Strip Spotless 32.8ft UL Listed IP20 Indoor
                          - Warm White 3000k
                        link_route: /products/4821
                  message: Shipment refreshed from ShipStation
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: ShipStation no longer returns this shipment — it may have
                    been removed.
        '502':
          description: Bad Gateway
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 'Failed to fetch shipment from ShipStation: cURL error
                    28: Operation timed out'
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-shipstation-integration-instances-integrationinstance-shipments-shipment-refresh
  /api/shipstation/integration-instances/{integrationInstance}/shipments/sync:
    post:
      tags:
      - ShipStation
      summary: Sync Shipments
      description: 'Queue a tracked background sync that pages ShipStation''s GET
        /shipments endpoint into the shipstation_shipments table (and applies tracking
        to linked orders/fulfillments, including a second pass over GET /fulfillments
        for externally fulfilled orders).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Body fields (all optional):

        - mode: ''all'' (full history), ''date_range'' (bounded by date_from/date_to),
        ''since_latest'' (bounded by date_from). Default: falls back to date_from,
        else the configured order start date.

        - date_from / since_date: ISO datetime lower bound

        - date_to: ISO datetime upper bound


        Track progress via the tracked job log endpoints (job name: ''Sync ShipStation
        Shipments: {instance name}'').


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                mode:
                  type: string
                date_from:
                  type: string
                date_to:
                  type: string
              example:
                mode: since_latest
                date_from: '2026-05-01T00:00:00Z'
                date_to: '2026-06-01T00:00:00Z'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 991
                  message: Shipments sync queued
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-shipstation-integration-instances-integrationinstance-shipments-sync
  /api/shipstation/integration-instances/{integrationInstance}/shipments/sync-info:
    get:
      tags:
      - ShipStation
      summary: Shipments Sync Info
      description: 'Header data for the shipments refresh modal: the most recently
        created shipment (by ShipStation createDate), the total shipment count, and
        the effective sync start date for this instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        `shipment_start_date` is the date the "Fetch from Start Date" sync option
        will use, and `shipment_start_date_source` is a human-readable label for where
        it came from. The date resolves in priority order: the instance''s ShipStation
        Order Start Date (source: "ShipStation Order Start Date"), then the general
        Inventory Start Date (source: "Inventory Start Date"), then a 30-day fallback
        window (source: "Default sync window (last 30 days)").


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      latest_shipment_identifier:
                        type: string
                      latest_shipment_date:
                        type: string
                      total_shipments:
                        type: integer
                      shipment_start_date:
                        type: string
                      shipment_start_date_source:
                        type: string
                  message:
                    type: string
                    nullable: true
                example:
                  data:
                    latest_shipment_identifier: '9400111899560000000001'
                    latest_shipment_date: '2026-06-08T14:22:10+00:00'
                    total_shipments: 118
                    shipment_start_date: '2025-01-01'
                    shipment_start_date_source: Inventory Start Date
                  message: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shipstation-integration-instances-integrationinstance-shipments-sync-info
  /api/shipstation/integration-instances/{integrationInstance}/shipments/search:
    post:
      tags:
      - ShipStation
      summary: Search Shipments
      description: 'Search ShipStation live for label shipments matching an order
        number or tracking number. Backs the "Search Specific Shipment" tab of the
        shipments refresh modal.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Request body:**

        - `search_by` (string, optional) — `order_number` (default) or `tracking_number`.
        `order_number` is a starts-with match in ShipStation V1; `tracking_number`
        is an exact match.

        - `query` (string, required, max 255) — the order number or tracking number
        to search for.


        Returns up to 50 live results from ShipStation. Each result includes `exists_in_database`
        / `database_id` so the UI can offer "Download" (new) vs "Update" (already
        cached). Use the returned `shipstation_shipment_id`, `shipstation_order_id`,
        and `tracking_number` to call the Refresh Single Shipment endpoint.


        Returns 502 if the ShipStation API call fails.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                search_by:
                  type: string
                query:
                  type: string
              example:
                search_by: order_number
                query: SS-10342
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        shipstation_shipment_id:
                          type: integer
                        shipstation_order_id:
                          type: integer
                        order_number:
                          type: string
                        tracking_number:
                          type: string
                        carrier_code:
                          type: string
                        service_code:
                          type: string
                        shipment_cost:
                          type: number
                        voided:
                          type: boolean
                        create_date:
                          type: string
                        ship_date:
                          type: string
                        exists_in_database:
                          type: boolean
                        database_id:
                          type: integer
                  message:
                    type: string
                    nullable: true
                example:
                  data:
                  - shipstation_shipment_id: 987654321
                    shipstation_order_id: 123456789
                    order_number: SS-10342
                    tracking_number: '9400111899560000000001'
                    carrier_code: stamps_com
                    service_code: usps_priority_mail
                    shipment_cost: 7.42
                    voided: false
                    create_date: '2026-06-08T14:22:10+00:00'
                    ship_date: '2026-06-08T00:00:00+00:00'
                    exists_in_database: true
                    database_id: 101
                  - shipstation_shipment_id: 987654400
                    shipstation_order_id: 123456790
                    order_number: SS-10343
                    tracking_number: '9400111899560000000045'
                    carrier_code: stamps_com
                    service_code: usps_first_class_mail
                    shipment_cost: 4.15
                    voided: false
                    create_date: '2026-06-09T09:10:05+00:00'
                    ship_date: '2026-06-09T00:00:00+00:00'
                    exists_in_database: false
                    database_id: null
                  message: null
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      query:
                        type: array
                        items:
                          type: string
                example:
                  message: The query field is required.
                  errors:
                    query:
                    - The query field is required.
        '502':
          description: Bad Gateway
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: string
                    nullable: true
                  message:
                    type: string
                example:
                  data: null
                  message: 'Search failed: ShipStation API request failed with status
                    500'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-shipstation-integration-instances-integrationinstance-shipments-search
  /api/shipstation/integration-instances/{integrationInstance}/shipments/refresh-shipment:
    post:
      tags:
      - ShipStation
      summary: Refresh Single Shipment
      description: 'Download (or update) a single label shipment live from ShipStation
        and persist it to the local cache. Backs the per-result Download/Update buttons
        on the shipments refresh modal''s search tab.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        ShipStation V1 has no GET /shipments/{id} endpoint, so the lookup needs the
        shipment''s order id or tracking number alongside its id — the shipment is
        found by listing shipments filtered by `orderId` (preferred) or exact `trackingNumber`
        and matching on the shipment id.


        **Request body:**

        - `uniqueId` (string, required) — the ShipStation shipment id (`shipstation_shipment_id`
        from a search result).

        - `order_id` (integer, optional, nullable) — the ShipStation order id (`shipstation_order_id`
        from a search result). Preferred lookup key.

        - `tracking_number` (string, optional, nullable, max 255) — fallback lookup
        key when the shipment has no order id.


        At least one of `order_id` or `tracking_number` is required (400 otherwise).
        Returns 404 if ShipStation no longer returns the shipment, 502 if the ShipStation
        API call fails.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                uniqueId:
                  type: string
                order_id:
                  type: integer
                tracking_number:
                  type: string
                  nullable: true
              example:
                uniqueId: '987654321'
                order_id: 123456789
                tracking_number: null
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      shipstation_shipment_id:
                        type: integer
                      order_id:
                        type: integer
                      shipstation_order_id:
                        type: integer
                      order_number:
                        type: string
                      tracking_number:
                        type: string
                      tracking_url:
                        type: string
                      carrier_code:
                        type: string
                      service_code:
                        type: string
                      package_code:
                        type: string
                      confirmation:
                        type: string
                      warehouse_id:
                        type: string
                      weight_value:
                        type: number
                      weight_units:
                        type: string
                      length:
                        type: integer
                      width:
                        type: integer
                      height:
                        type: integer
                      dimension_units:
                        type: string
                      shipment_cost:
                        type: number
                      insurance_cost:
                        type: integer
                      voided:
                        type: boolean
                      void_date:
                        type: string
                        nullable: true
                      is_return_label:
                        type: boolean
                      batch_number:
                        type: string
                      ship_date:
                        type: string
                      create_date:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      order:
                        type: object
                        properties:
                          id:
                            type: integer
                          order_number:
                            type: string
                          shipstation_order_id:
                            type: integer
                          link_reference:
                            type: string
                          link_type_label:
                            type: string
                          link_id:
                            type: integer
                          link_route:
                            type: string
                      sku_fulfillment_id:
                        type: integer
                      sku_fulfillment_status:
                        type: string
                      sales_order_id:
                        type: integer
                      sales_order_number:
                        type: string
                      sales_order_legacy_url:
                        type: string
                      warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                  message:
                    type: string
                example:
                  data:
                    id: 101
                    integration_instance_id: 4
                    shipstation_shipment_id: 987654321
                    order_id: 2456
                    shipstation_order_id: 123456789
                    order_number: SS-10342
                    tracking_number: '9400111899560000000001'
                    tracking_url: https://tools.usps.com/go/TrackConfirmAction?tLabels=9400111899560000000001
                    carrier_code: stamps_com
                    service_code: usps_priority_mail
                    package_code: package
                    confirmation: delivery
                    warehouse_id: '12345'
                    weight_value: 14.5
                    weight_units: ounces
                    length: 10
                    width: 8
                    height: 4
                    dimension_units: inches
                    shipment_cost: 7.42
                    insurance_cost: 0
                    voided: false
                    void_date: null
                    is_return_label: false
                    batch_number: '100301'
                    ship_date: '2026-06-08T00:00:00+00:00'
                    create_date: '2026-06-08T14:22:10+00:00'
                    created_at: '2026-06-08T14:25:00+00:00'
                    updated_at: '2026-06-08T14:25:00+00:00'
                    order:
                      id: 2456
                      order_number: SS-10342
                      shipstation_order_id: 123456789
                      link_reference: SS-10342
                      link_type_label: ShipStation Order
                      link_id: 2456
                      link_route: /integrations/shipstation/4/orders/2456
                    sku_fulfillment_id: 778
                    sku_fulfillment_status: shipped
                    sales_order_id: 3301
                    sales_order_number: SO-3301
                    sales_order_legacy_url: /sales-orders/3301
                    warehouse:
                      id: 2
                      name: Main Warehouse
                  message: Shipment refreshed from ShipStation
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: string
                    nullable: true
                  message:
                    type: string
                example:
                  data: null
                  message: order_id or tracking_number is required to look up a shipment
                    — ShipStation has no shipment-by-id endpoint.
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: string
                    nullable: true
                  message:
                    type: string
                example:
                  data: null
                  message: ShipStation no longer returns this shipment — it may have
                    been removed.
        '502':
          description: Bad Gateway
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: string
                    nullable: true
                  message:
                    type: string
                example:
                  data: null
                  message: 'Failed to refresh shipment: ShipStation API request failed
                    with status 500'
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-shipstation-integration-instances-integrationinstance-shipments-refresh-shipment
  /api/shipstation/integration-instances/{integration_instance}/warehouses:
    get:
      tags:
      - ShipStation
      summary: List Warehouses
      description: 'All cached ShipStation warehouses for this instance, ordered by
        name (no pagination or filters). Each entry includes the optional SKU.io warehouse
        link (`warehouse_id` + `warehouse_name`) and origin-address fields.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        shipstation_id:
                          type: integer
                        name:
                          type: string
                        is_default:
                          type: boolean
                        warehouse_id:
                          type: integer
                        warehouse_name:
                          type: string
                        address_line_1:
                          type: string
                        city:
                          type: string
                        state:
                          type: string
                        postal_code:
                          type: string
                        country:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                example:
                  success: true
                  data:
                  - id: 5
                    shipstation_id: 98765
                    name: Main Fulfillment Center
                    is_default: true
                    warehouse_id: 3
                    warehouse_name: Main Warehouse
                    address_line_1: 123 Commerce St
                    city: Austin
                    state: TX
                    postal_code: '78701'
                    country: US
                    created_at: '2026-04-10T08:00:00+00:00'
                    updated_at: '2026-06-01T12:00:00+00:00'
                  - id: 6
                    shipstation_id: 98766
                    name: West Coast Annex
                    is_default: false
                    warehouse_id: null
                    warehouse_name: null
                    address_line_1: 55 Harbor Blvd
                    city: Long Beach
                    state: CA
                    postal_code: '90802'
                    country: US
                    created_at: '2026-04-10T08:00:00+00:00'
                    updated_at: '2026-06-01T12:00:00+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shipstation-integration-instances-integration-instance-warehouses
  /api/shipstation/integration-instances/{integration_instance}/warehouses/sync:
    post:
      tags:
      - ShipStation
      summary: Sync Warehouses
      description: 'Queues a background job as a tracked job that pulls the warehouse
        list from the ShipStation API and upserts the local cache. No request body.
        Returns `data.tracked_job_log_id` for the tracked job log endpoints.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                example:
                  success: true
                  message: Warehouse sync queued
                  data:
                    tracked_job_log_id: 9140
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-shipstation-integration-instances-integration-instance-warehouses-sync
  /api/shipstation/integration-instances/{integration_instance}/warehouses/{shipstationId}/link:
    post:
      tags:
      - ShipStation
      summary: Link Warehouse
      description: 'Links (or unlinks) a ShipStation warehouse to a SKU.io warehouse.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Path params:

        - `shipstationId` — the ShipStation warehouse id (shipstation_id), not the
        local row id


        Body fields:

        - `warehouse_id` — SKU.io warehouse id to link; pass null (or omit) to unlink


        Returns the updated warehouse resource.


        Errors:

        - 404 — no cached ShipStation warehouse with that shipstation_id for this
        instance (''Warehouse not found'')


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                warehouse_id:
                  type: integer
              example:
                warehouse_id: 3
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: shipstationId
        in: path
        schema:
          type: string
        required: true
        description: The shipstation ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      shipstation_id:
                        type: integer
                      name:
                        type: string
                      is_default:
                        type: boolean
                      warehouse_id:
                        type: integer
                      warehouse_name:
                        type: string
                      address_line_1:
                        type: string
                      city:
                        type: string
                      state:
                        type: string
                      postal_code:
                        type: string
                      country:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  success: true
                  data:
                    id: 5
                    shipstation_id: 98765
                    name: Main Fulfillment Center
                    is_default: true
                    warehouse_id: 3
                    warehouse_name: Main Warehouse
                    address_line_1: 123 Commerce St
                    city: Austin
                    state: TX
                    postal_code: '78701'
                    country: US
                    created_at: '2026-04-10T08:00:00+00:00'
                    updated_at: '2026-06-10T09:30:00+00:00'
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                example:
                  success: false
                  message: Warehouse not found
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-shipstation-integration-instances-integration-instance-warehouses-shipstationid-link
  /api/shipstation/warehouses:
    get:
      tags:
      - ShipStation
      summary: Get ShipStation Warehouses
      description: 'List all ShipStation warehouses that have been downloaded from
        ShipStation.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token + Power User access.'
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: get-api-shipstation-warehouses
  /api/shipstation/warehouses/mappings:
    get:
      tags:
      - ShipStation
      summary: Get Warehouse Mappings
      description: 'Retrieve all mappings between SKU warehouses and ShipStation warehouses.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token + Power User access.'
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: get-api-shipstation-warehouses-mappings
  /api/shipstation/warehouses/download:
    post:
      tags:
      - ShipStation
      summary: Download ShipStation Warehouses
      description: 'Download warehouses from ShipStation and store them locally.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token + Power User access.'
      requestBody:
        content: {}
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-session-only: true
      operationId: post-api-shipstation-warehouses-download
  /api/shipstation/warehouses/map:
    post:
      tags:
      - ShipStation
      summary: Map Warehouses
      description: 'Create mappings between SKU warehouses and ShipStation warehouses.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token + Power User access.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                mapping:
                  type: array
                  items:
                    type: object
                    properties:
                      warehouse_id:
                        type: integer
                      shipstation_warehouse_id:
                        type: integer
              example:
                mapping:
                - warehouse_id: 1
                  shipstation_warehouse_id: 1
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-session-only: true
      operationId: post-api-shipstation-warehouses-map
  /api/shipstation/warehouses/unmap:
    post:
      tags:
      - ShipStation
      summary: Unmap Warehouses
      description: 'Remove warehouse mappings between SKU and ShipStation.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token + Power User access.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1
                - 2
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-session-only: true
      operationId: post-api-shipstation-warehouses-unmap
  /api/shipstation/integration-instances/{integration_instance}/shipping-methods:
    get:
      tags:
      - ShipStation
      summary: List Shipping Methods
      description: 'Returns every ShipStation carrier/service combination for the
        instance (flattened to `carrier_code|service_code` codes, cached 10 minutes
        from the ShipStation /carriers + /services endpoints, sorted by carrier then
        service name) with its current SKU.io mapping (or null), plus the list of
        available SKU.io shipping methods for the mapping dropdown.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      services:
                        type: array
                        items:
                          type: object
                          properties:
                            code:
                              type: string
                            carrier_code:
                              type: string
                            carrier_name:
                              type: string
                            service_code:
                              type: string
                            service_name:
                              type: string
                            is_domestic:
                              type: boolean
                            mapping:
                              type: object
                              properties:
                                id:
                                  type: integer
                                shipping_method_id:
                                  type: integer
                                shipping_method_name:
                                  type: string
                                shipping_method_type:
                                  type: string
                      sku_shipping_methods:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            full_name:
                              type: string
                            type:
                              type: string
                example:
                  success: true
                  data:
                    services:
                    - code: ups|ups_ground
                      carrier_code: ups
                      carrier_name: UPS
                      service_code: ups_ground
                      service_name: UPS Ground
                      is_domestic: true
                      mapping:
                        id: 12
                        shipping_method_id: 4
                        shipping_method_name: Ground Shipping
                        shipping_method_type: standard
                    - code: fedex|fedex_2day
                      carrier_code: fedex
                      carrier_name: FedEx
                      service_code: fedex_2day
                      service_name: FedEx 2Day
                      is_domestic: true
                      mapping: null
                    sku_shipping_methods:
                    - id: 4
                      name: Ground Shipping
                      full_name: Ground Shipping (3-5 days)
                      type: standard
                    - id: 5
                      name: Expedited
                      full_name: Expedited (2 days)
                      type: expedited
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shipstation-integration-instances-integration-instance-shipping-methods
  /api/shipstation/integration-instances/{integration_instance}/shipping-methods/sync:
    post:
      tags:
      - ShipStation
      summary: Sync Shipping Methods
      description: 'Queues a background job as a tracked job that force-refreshes
        the carrier/service cache from ShipStation. No request body. Returns `data.tracked_job_log_id`
        for the tracked job log endpoints.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                example:
                  success: true
                  message: Shipping methods sync queued
                  data:
                    tracked_job_log_id: 9142
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-shipstation-integration-instances-integration-instance-shipping-methods-sync
  /api/shipstation/integration-instances/{integration_instance}/shipping-methods/export:
    get:
      tags:
      - ShipStation
      summary: Export Shipping Method Mappings (CSV)
      description: 'Downloads the persisted mappings as CSV (Content-Type: text/csv,
        Content-Disposition attachment named `shipstation-shipping-methods-{instance}-{date}.csv`).
        Only stored mappings are exported — no live ShipStation API calls.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Columns: code, carrier_code, carrier_name, service_code, service_name, is_domestic
        (yes/no), shipping_method_id, shipping_method_name.


        The file is round-trippable with the import endpoint: blanking both shipping_method_id
        and shipping_method_name on a row deletes that mapping on re-import.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: text/csv
            Content-Disposition:
              schema:
                type: string
                example: attachment; filename="shipstation-shipping-methods-1-2026-06-10.csv"
          content:
            text/plain:
              schema:
                type: string
                example: 'code,carrier_code,carrier_name,service_code,service_name,is_domestic,shipping_method_id,shipping_method_name

                  ups|ups_ground,ups,UPS,ups_ground,UPS Ground,yes,4,Ground Shipping
                  (3-5 days)

                  fedex|fedex_2day,fedex,FedEx,fedex_2day,FedEx 2Day,yes,5,Expedited
                  (2 days)

                  '
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shipstation-integration-instances-integration-instance-shipping-methods-export
  /api/shipstation/integration-instances/{integration_instance}/shipping-methods/import:
    post:
      tags:
      - ShipStation
      summary: Import Shipping Method Mappings (CSV)
      description: 'Uploads a CSV of mappings (multipart/form-data).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Body fields:

        - `file` — required, mimes: csv or txt, max 2048 KB. First row must be a header.


        Row semantics (per line):

        - `code` identifies the service (`carrier_code|service_code`); if blank, it
        is rebuilt from carrier_code + service_code columns

        - `shipping_method_id` (authoritative) or `shipping_method_name` (fallback,
        matched case-insensitively against name or full_name) resolves the SKU.io
        shipping method

        - Both blank → the mapping for that code is deleted

        - Unresolvable rows are collected into `errors` with their line numbers


        Response data: `{created, updated, deleted, errors[]}` summary.


        Errors:

        - 422 — missing/invalid file (wrong mime type or > 2 MB)


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                file:
                  type: string
                  format: binary
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      created:
                        type: integer
                      updated:
                        type: integer
                      deleted:
                        type: integer
                      errors:
                        type: array
                        items:
                          type: string
                example:
                  success: true
                  message: Import processed
                  data:
                    created: 3
                    updated: 1
                    deleted: 1
                    errors:
                    - 'Line 6: shipping method name ''Overnight Gold'' not found'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      file:
                        type: array
                        items:
                          type: string
                example:
                  message: The file field is required.
                  errors:
                    file:
                    - The file field is required.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-shipstation-integration-instances-integration-instance-shipping-methods-import
  /api/shipstation/integration-instances/{integration_instance}/shipping-methods/map:
    put:
      tags:
      - ShipStation
      summary: Map Shipping Method
      description: 'Creates or updates a single mapping from a ShipStation `carrier_code|service_code`
        code to a SKU.io shipping method. Carrier/service metadata is captured from
        the cached service list when the code is recognized.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Body fields:

        - `code` — required, string, max 255 (format: carrier_code|service_code)

        - `shipping_method_id` — required, integer, must exist in shipping_methods


        Errors:

        - 422 — validation failure (missing code, unknown shipping_method_id)


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                code:
                  type: string
                shipping_method_id:
                  type: integer
              example:
                code: ups|ups_ground
                shipping_method_id: 4
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      code:
                        type: string
                      shipping_method_id:
                        type: integer
                example:
                  success: true
                  message: Mapping saved
                  data:
                    id: 12
                    code: ups|ups_ground
                    shipping_method_id: 4
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      shipping_method_id:
                        type: array
                        items:
                          type: string
                example:
                  message: The selected shipping method id is invalid.
                  errors:
                    shipping_method_id:
                    - The selected shipping method id is invalid.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: put-api-shipstation-integration-instances-integration-instance-shipping-methods-map
  /api/shipstation/integration-instances/{integration_instance}/shipping-methods/bulk-map:
    put:
      tags:
      - ShipStation
      summary: Bulk Map Shipping Methods
      description: 'Maps many ShipStation service codes to a single SKU.io shipping
        method in one call. Duplicate codes are de-duplicated; carrier/service metadata
        is derived from the `carrier_code|service_code` split (no live ShipStation
        lookup).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Body fields:

        - `codes` — required, array, min 1; each entry required string max 255

        - `shipping_method_id` — required, integer, must exist in shipping_methods


        Response data: `updated_count` — number of mappings written.


        Errors:

        - 422 — validation failure (empty codes array, unknown shipping_method_id)


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                codes:
                  type: array
                  items:
                    type: string
                shipping_method_id:
                  type: integer
              example:
                codes:
                - ups|ups_ground
                - fedex|fedex_2day
                - usps|usps_priority_mail
                shipping_method_id: 4
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      updated_count:
                        type: integer
                example:
                  success: true
                  message: 3 mapping(s) saved
                  data:
                    updated_count: 3
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-shipstation-integration-instances-integration-instance-shipping-methods-bulk-map
  /api/shipstation/integration-instances/{integration_instance}/shipping-methods/map/ups|ups_ground:
    delete:
      tags:
      - ShipStation
      summary: Unmap Shipping Method
      description: 'Deletes the mapping for a ShipStation service code.


        Path params:

        - `code` — the mapped `carrier_code|service_code` code. The route allows any
        characters including slashes (`->where(''code'', ''.*'')`), so codes containing
        `/` work; URL-encode the pipe (`%7C`) when needed.


        Errors:

        - 404 — no mapping exists for that code (''Mapping not found'')


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                example:
                  success: true
                  message: Mapping removed
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                example:
                  success: false
                  message: Mapping not found
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: delete-api-shipstation-integration-instances-integration-instance-shipping-methods-map-ups-ups-ground
  /api/odoo-3pl/{integration_instance}/shipping-methods:
    get:
      tags:
      - Odoo 3PL
      summary: List Shipping Methods
      description: List the available Odoo 3PL carriers for this integration instance
        together with the SKU.io shipping methods available to map onto. Each carrier
        row includes its current SKU shipping-method mapping (if any). Requires a
        Bearer token.
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '3'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      services:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            odoo_3pl_carrier_id:
                              type: integer
                            name:
                              type: string
                            delivery_type:
                              type: string
                            shipping_method_id:
                              type: string
                              nullable: true
                            sku_shipping_method_name:
                              type: string
                              nullable: true
                      sku_shipping_methods:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            full_name:
                              type: string
                            type:
                              type: string
                      last_synced_at:
                        type: string
                example:
                  data:
                    services:
                    - id: 1
                      odoo_3pl_carrier_id: 5
                      name: Fedex Canada Ground
                      delivery_type: fedex_rest
                      shipping_method_id: null
                      sku_shipping_method_name: null
                    - id: 3
                      odoo_3pl_carrier_id: 10
                      name: ups ground
                      delivery_type: ups_rest
                      shipping_method_id: 5
                      sku_shipping_method_name: UPS Ground
                    sku_shipping_methods:
                    - id: 5
                      name: Ground
                      full_name: UPS Ground
                      type: domestic
                    - id: 16
                      name: 1 Day Freight
                      full_name: FedEx 1 Day Freight
                      type: domestic
                    last_synced_at: '2026-07-15T14:05:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-odoo-3pl-integration-instance-shipping-methods
  /api/odoo-3pl/{integration_instance}/shipping-methods/sync:
    post:
      tags:
      - Odoo 3PL
      summary: Sync Shipping Methods
      description: Refresh the carrier catalog from Odoo 3PL, then auto-link any unmapped
        carriers to SKU.io shipping methods whose name matches. Returns how many carriers
        were fetched and how many were auto-matched. Requires a Bearer token.
      requestBody:
        content: {}
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '3'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      carriers_fetched:
                        type: integer
                      auto_matched:
                        type: integer
                example:
                  message: Synced 3 shipping method(s); 1 auto-matched.
                  data:
                    carriers_fetched: 3
                    auto_matched: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-odoo-3pl-integration-instance-shipping-methods-sync
  /api/odoo-3pl/{integration_instance}/shipping-methods/export:
    get:
      tags:
      - Odoo 3PL
      summary: Export Shipping Method Mappings
      description: Download the current carrier-to-SKU shipping-method mappings as
        a re-importable CSV. A row with a blank shipping_method_id and shipping_method_name
        clears that mapping on import. Requires a Bearer token.
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '3'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: text/csv
          content:
            text/plain:
              schema:
                type: string
                example: "odoo_3pl_carrier_id,name,delivery_type,shipping_method_id,shipping_method_name\r\
                  \n5,Fedex Canada Ground,fedex_rest,,\r\n10,ups ground,ups_rest,5,UPS\
                  \ Ground\r\n"
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-odoo-3pl-integration-instance-shipping-methods-export
  /api/odoo-3pl/{integration_instance}/shipping-methods/import:
    post:
      tags:
      - Odoo 3PL
      summary: Import Shipping Method Mappings
      description: Upload a CSV of carrier-to-SKU shipping-method mappings. Each row
        is keyed by odoo_3pl_carrier_id and resolves the SKU.io method by shipping_method_id
        (authoritative) or shipping_method_name (fallback). Both blank clears that
        mapping. Content-Type is multipart/form-data; the file must be a CSV (max
        2 MB). Requires a Bearer token.
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                file:
                  type: string
                  description: 'CSV file with columns: odoo_3pl_carrier_id, name,
                    delivery_type, shipping_method_id, shipping_method_name'
                  format: binary
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '3'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      created:
                        type: integer
                      updated:
                        type: integer
                      deleted:
                        type: integer
                      errors:
                        type: array
                example:
                  message: Import processed
                  data:
                    created: 1
                    updated: 1
                    deleted: 0
                    errors: []
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-odoo-3pl-integration-instance-shipping-methods-import
  /api/odoo-3pl/{integration_instance}/shipping-methods/auto-match:
    post:
      tags:
      - Odoo 3PL
      summary: Auto-Match Shipping Methods
      description: Auto-link unmapped Odoo 3PL carriers to SKU.io shipping methods
        whose name matches (case, spacing and punctuation insensitive). Never overwrites
        an existing mapping. Returns how many carriers were newly linked. Requires
        a Bearer token.
      requestBody:
        content: {}
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '3'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      matched_count:
                        type: integer
                example:
                  message: 1 shipping method(s) auto-matched
                  data:
                    matched_count: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-odoo-3pl-integration-instance-shipping-methods-auto-match
  /api/odoo-3pl/{integration_instance}/shipping-methods/bulk-map:
    put:
      tags:
      - Odoo 3PL
      summary: Bulk Map Shipping Methods
      description: Map many Odoo 3PL carriers to a single SKU.io shipping method at
        once, or clear them by sending a null shipping_method_id. Requires a Bearer
        token.
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
                shipping_method_id:
                  type: integer
              example:
                ids:
                - 1
                - 3
                shipping_method_id: 5
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '3'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      updated_count:
                        type: integer
                example:
                  message: 2 mapping(s) saved
                  data:
                    updated_count: 2
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      ids:
                        type: array
                        items:
                          type: string
                example:
                  message: The ids field is required.
                  errors:
                    ids:
                    - The ids field is required.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: put-api-odoo-3pl-integration-instance-shipping-methods-bulk-map
  /api/odoo-3pl/{integration_instance}/shipping-methods/{shippingMethodId}/mapping:
    put:
      tags:
      - Odoo 3PL
      summary: Update Shipping Method Mapping
      description: Set or clear the SKU.io shipping-method mapping for a single Odoo
        3PL carrier. Send a null shipping_method_id to unmap. Once mapped, orders
        using that SKU shipping method submit to Odoo 3PL with the carrier's name
        as the requested shipping method. Requires a Bearer token.
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                shipping_method_id:
                  type: integer
              example:
                shipping_method_id: 5
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '3'
      - name: shippingMethodId
        in: path
        schema:
          type: integer
        required: true
        description: Odoo 3PL shipping-method (carrier) row ID
        example: '3'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      odoo_3pl_carrier_id:
                        type: integer
                      name:
                        type: string
                      delivery_type:
                        type: string
                      shipping_method_id:
                        type: integer
                      is_mapped:
                        type: boolean
                      sku_shipping_method:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          full_name:
                            type: string
                          carrier_name:
                            type: string
                      last_synced_at:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  message: Shipping method mapped.
                  data:
                    id: 3
                    integration_instance_id: 3
                    odoo_3pl_carrier_id: 10
                    name: ups ground
                    delivery_type: ups_rest
                    shipping_method_id: 5
                    is_mapped: true
                    sku_shipping_method:
                      id: 5
                      name: Ground
                      full_name: UPS Ground
                      carrier_name: UPS
                    last_synced_at: '2026-07-15T14:05:00.000000Z'
                    created_at: '2026-07-15T14:05:00.000000Z'
                    updated_at: '2026-07-15T14:06:00.000000Z'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      shipping_method_id:
                        type: array
                        items:
                          type: string
                example:
                  message: The selected shipping method id is invalid.
                  errors:
                    shipping_method_id:
                    - The selected shipping method id is invalid.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: put-api-odoo-3pl-integration-instance-shipping-methods-shippingmethodid-mapping
  /api/shipstation/integration-instances/{integration_instance}/webhook-events:
    get:
      tags:
      - ShipStation
      summary: List Webhook Events
      description: 'Paginated list of inbound webhook events recorded for this ShipStation
        integration instance, newest first (default sort -id).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Filtering** (Spatie QueryBuilder + GroupedFilterSupport):

        - `filter[search]` — multi-column AdvancedSearchFilter across `id`, `order_number`,
        `tracking_number`, `event_type`; tune with top-level `search_columns` / `search_strict_columns`

        - Numeric: `id`, `shipstation_order_id`

        - Text: `event_type`, `resource_type`, `processed`, `signature_valid`, `order_number`,
        `tracking_number`

        - Datetime: `processed_at`, `created_at`, `updated_at`

        - `filter[has_error]=true` — legacy flag for events with an error_message

        - `filter_groups` — base64-encoded JSON tree for grouped AND/OR filtering
        using the same column.operator names


        **Sorting**: `id`, `created_at`, `updated_at`, `event_type`, `processed_at`
        (default `-id`).


        **Pagination**: standard Laravel paginator, `per_page` default 15.


        Authentication: Requires Bearer token.'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        description: Page number
        example: '1'
      - name: per_page
        in: query
        schema:
          type: integer
        description: Items per page (default 15)
        example: '15'
      - name: sort
        in: query
        schema:
          type: string
        description: 'Sort column. Allowed: id, created_at, updated_at, event_type,
          processed_at. Prefix with - for descending. Default: -id'
        example: -id
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        event_type:
                          type: string
                        event_type_label:
                          type: string
                        event_type_color:
                          type: string
                        resource_url:
                          type: string
                        resource_type:
                          type: string
                        resource_fetched:
                          type: boolean
                        order_number:
                          type: string
                        shipstation_order_id:
                          type: integer
                        tracking_number:
                          type: string
                        signature_valid:
                          type: boolean
                        payload:
                          type: object
                          properties:
                            resource_url:
                              type: string
                            resource_type:
                              type: string
                        processed:
                          type: boolean
                        processed_at:
                          type: string
                        error_message:
                          type: string
                          nullable: true
                        dedup_key:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                  next_page_url:
                    type: string
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 1201
                    integration_instance_id: 5
                    event_type: SHIP_NOTIFY
                    event_type_label: Shipment Notification
                    event_type_color: success
                    resource_url: https://ssapi.shipstation.com/shipments?storeId=12345&batchId=98765&includeShipmentItems=false
                    resource_type: SHIP_NOTIFY
                    resource_fetched: true
                    order_number: SO-1234
                    shipstation_order_id: 123456789
                    tracking_number: '9405511899560001234567'
                    signature_valid: true
                    payload:
                      resource_url: https://ssapi.shipstation.com/shipments?storeId=12345&batchId=98765&includeShipmentItems=false
                      resource_type: SHIP_NOTIFY
                    processed: true
                    processed_at: '2026-06-09T14:32:11+00:00'
                    error_message: null
                    dedup_key: a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6
                    created_at: '2026-06-09T14:32:08+00:00'
                    updated_at: '2026-06-09T14:32:11+00:00'
                  - id: 1200
                    integration_instance_id: 5
                    event_type: ORDER_NOTIFY
                    event_type_label: Order Notification
                    event_type_color: info
                    resource_url: https://ssapi.shipstation.com/orders?storeId=12345&importBatch=11223
                    resource_type: ORDER_NOTIFY
                    resource_fetched: false
                    order_number: null
                    shipstation_order_id: null
                    tracking_number: null
                    signature_valid: true
                    payload:
                      resource_url: https://ssapi.shipstation.com/orders?storeId=12345&importBatch=11223
                      resource_type: ORDER_NOTIFY
                    processed: false
                    processed_at: null
                    error_message: ShipStation API returned 429 Too Many Requests
                      while fetching resource
                    dedup_key: f6e5d4c3b2a1f0e9d8c7b6a5f4e3d2c1
                    created_at: '2026-06-09T14:30:55+00:00'
                    updated_at: '2026-06-09T14:31:02+00:00'
                  first_page_url: '{{protocol}}://{{domain}}/api/shipstation/integration-instances/5/webhook-events?page=1'
                  from: 1
                  last_page: 7
                  last_page_url: '{{protocol}}://{{domain}}/api/shipstation/integration-instances/5/webhook-events?page=7'
                  links: []
                  next_page_url: '{{protocol}}://{{domain}}/api/shipstation/integration-instances/5/webhook-events?page=2'
                  path: '{{protocol}}://{{domain}}/api/shipstation/integration-instances/5/webhook-events'
                  per_page: 15
                  prev_page_url: null
                  to: 15
                  total: 98
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shipstation-integration-instances-integration-instance-webhook-events
  /api/shipstation/integration-instances/{integration_instance}/webhook-events/{webhook_event}:
    get:
      tags:
      - ShipStation
      summary: Get Webhook Event
      description: 'Returns the full detail for a single webhook event, including
        the raw inbound `payload`, processing status, error message (if processing
        failed), dedup key and signature validity.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Returns **404** if the event does not belong to the given integration instance.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: webhook_event
        in: path
        schema:
          type: integer
        required: true
        description: ShipstationWebhookEvent ID
        example: '1201'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      event_type:
                        type: string
                      event_type_label:
                        type: string
                      event_type_color:
                        type: string
                      resource_url:
                        type: string
                      resource_type:
                        type: string
                      resource_fetched:
                        type: boolean
                      order_number:
                        type: string
                      shipstation_order_id:
                        type: integer
                      tracking_number:
                        type: string
                      signature_valid:
                        type: boolean
                      payload:
                        type: object
                        properties:
                          resource_url:
                            type: string
                          resource_type:
                            type: string
                      processed:
                        type: boolean
                      processed_at:
                        type: string
                      error_message:
                        type: string
                        nullable: true
                      dedup_key:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 1201
                    integration_instance_id: 5
                    event_type: SHIP_NOTIFY
                    event_type_label: Shipment Notification
                    event_type_color: success
                    resource_url: https://ssapi.shipstation.com/shipments?storeId=12345&batchId=98765&includeShipmentItems=false
                    resource_type: SHIP_NOTIFY
                    resource_fetched: true
                    order_number: SO-1234
                    shipstation_order_id: 123456789
                    tracking_number: '9405511899560001234567'
                    signature_valid: true
                    payload:
                      resource_url: https://ssapi.shipstation.com/shipments?storeId=12345&batchId=98765&includeShipmentItems=false
                      resource_type: SHIP_NOTIFY
                    processed: true
                    processed_at: '2026-06-09T14:32:11+00:00'
                    error_message: null
                    dedup_key: a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6
                    created_at: '2026-06-09T14:32:08+00:00'
                    updated_at: '2026-06-09T14:32:11+00:00'
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Not Found
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-shipstation-integration-instances-integration-instance-webhook-events-webhook-event
  /api/shipstation/integration-instances/{integration_instance}/webhook-events/{webhook_event}/retry:
    post:
      tags:
      - ShipStation
      summary: Retry Webhook Event
      description: 'Queues the webhook event for reprocessing by dispatching a background
        job. Typically used on events whose `processed` flag is false and `error_message`
        is set (e.g. a transient ShipStation API failure during the resource fetch).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        The job re-runs the standard processing path: fetch the resource from ShipStation,
        apply the fetched payload (order/shipment linkage), then mark the event processed
        or record a new error.


        Returns **404** if the event does not belong to the given integration instance.


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: webhook_event
        in: path
        schema:
          type: integer
        required: true
        description: ShipstationWebhookEvent ID to re-process
        example: '1200'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  status:
                    type: string
                example:
                  message: Webhook event queued for retry
                  status: Success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-shipstation-integration-instances-integration-instance-webhook-events-webhook-event-retry
  /api/shipstation/integration-instances/{integration_instance}/webhook-subscriptions:
    get:
      tags:
      - ShipStation
      summary: List Webhook Configurations
      description: 'Returns the webhook configuration matrix for the instance:


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        - `configurations` — one row per ShipStation event type (`SHIP_NOTIFY`, `ITEM_SHIP_NOTIFY`,
        `ORDER_NOTIFY`, `ITEM_ORDER_NOTIFY`, `FULFILLMENT_SHIPPED`, `FULFILLMENT_REJECTED`)
        with label, color, description, and the linked local subscription (`subscription_id`,
        `shipstation_webhook_id`, `friendly_name`, `is_enabled`)

        - `target_url` — the public ingress URL ShipStation should POST notifications
        to (encodes the integration instance id so tenancy can be initialised)

        - `event_type_count` — total number of supported event types (6)


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      configurations:
                        type: array
                        items:
                          type: object
                          properties:
                            event_type:
                              type: string
                            event_type_label:
                              type: string
                            event_type_color:
                              type: string
                            event_type_description:
                              type: string
                            subscription_id:
                              type: integer
                            shipstation_webhook_id:
                              type: string
                            callback_url:
                              type: string
                            friendly_name:
                              type: string
                            is_enabled:
                              type: boolean
                      target_url:
                        type: string
                      event_type_count:
                        type: integer
                example:
                  data:
                    configurations:
                    - event_type: SHIP_NOTIFY
                      event_type_label: Shipment Notification
                      event_type_color: success
                      event_type_description: Sent when one or more shipments are
                        created in ShipStation.
                      subscription_id: 12
                      shipstation_webhook_id: '784512'
                      callback_url: https://acme.sku.io/api/shipstation/webhooks/5/notify
                      friendly_name: SKU.io Shipment Notification
                      is_enabled: true
                    - event_type: ITEM_SHIP_NOTIFY
                      event_type_label: Item Shipment Notification
                      event_type_color: success
                      event_type_description: Sent when shipments are created — payload
                        includes per-item shipment detail.
                      subscription_id: null
                      shipstation_webhook_id: null
                      callback_url: https://acme.sku.io/api/shipstation/webhooks/5/notify
                      friendly_name: null
                      is_enabled: false
                    - event_type: ORDER_NOTIFY
                      event_type_label: Order Notification
                      event_type_color: info
                      event_type_description: Sent when one or more new orders are
                        imported into ShipStation.
                      subscription_id: 13
                      shipstation_webhook_id: '784513'
                      callback_url: https://acme.sku.io/api/shipstation/webhooks/5/notify
                      friendly_name: SKU.io Order Notification
                      is_enabled: true
                    - event_type: ITEM_ORDER_NOTIFY
                      event_type_label: Item Order Notification
                      event_type_color: info
                      event_type_description: Sent when orders are imported — payload
                        includes per-item order detail.
                      subscription_id: null
                      shipstation_webhook_id: null
                      callback_url: https://acme.sku.io/api/shipstation/webhooks/5/notify
                      friendly_name: null
                      is_enabled: false
                    - event_type: FULFILLMENT_SHIPPED
                      event_type_label: Fulfillment Shipped
                      event_type_color: success
                      event_type_description: Sent when a fulfillment marked-as-shipped
                        is recorded in ShipStation.
                      subscription_id: null
                      shipstation_webhook_id: null
                      callback_url: https://acme.sku.io/api/shipstation/webhooks/5/notify
                      friendly_name: null
                      is_enabled: false
                    - event_type: FULFILLMENT_REJECTED
                      event_type_label: Fulfillment Rejected
                      event_type_color: error
                      event_type_description: Sent when ShipStation rejects an inbound
                        fulfillment.
                      subscription_id: null
                      shipstation_webhook_id: null
                      callback_url: https://acme.sku.io/api/shipstation/webhooks/5/notify
                      friendly_name: null
                      is_enabled: false
                    target_url: https://acme.sku.io/api/shipstation/webhooks/5/notify
                    event_type_count: 6
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shipstation-integration-instances-integration-instance-webhook-subscriptions
    post:
      tags:
      - ShipStation
      summary: Subscribe to Webhook Event
      description: 'Creates a webhook subscription on the ShipStation account (POST
        /webhooks/subscribe via the ShipStation V1 API) pointing at this instance''s
        ingress URL, then records it locally.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Body fields:**

        - `event_type` (required, string) — one of: `SHIP_NOTIFY`, `ITEM_SHIP_NOTIFY`,
        `ORDER_NOTIFY`, `ITEM_ORDER_NOTIFY`, `FULFILLMENT_SHIPPED`, `FULFILLMENT_REJECTED`

        - `friendly_name` (optional, string, max 255) — display name for the webhook
        in ShipStation; defaults to the event type label when omitted


        Returns **422** when `event_type` is missing or not one of the allowed values.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                event_type:
                  type: string
                friendly_name:
                  type: string
              example:
                event_type: SHIP_NOTIFY
                friendly_name: SKU.io Shipment Notification
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      event_type:
                        type: string
                      event_type_label:
                        type: string
                      event_type_color:
                        type: string
                      shipstation_webhook_id:
                        type: string
                      target_url:
                        type: string
                      friendly_name:
                        type: string
                      active:
                        type: boolean
                      created_at:
                        type: string
                      updated_at:
                        type: string
                  message:
                    type: string
                  status:
                    type: string
                example:
                  data:
                    id: 12
                    event_type: SHIP_NOTIFY
                    event_type_label: Shipment Notification
                    event_type_color: success
                    shipstation_webhook_id: '784512'
                    target_url: https://acme.sku.io/api/shipstation/webhooks/5/notify
                    friendly_name: SKU.io Shipment Notification
                    active: true
                    created_at: '2026-06-10T09:15:00+00:00'
                    updated_at: '2026-06-10T09:15:00+00:00'
                  message: Webhook subscribed
                  status: Success
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      event_type:
                        type: array
                        items:
                          type: string
                example:
                  message: The selected event type is invalid.
                  errors:
                    event_type:
                    - The selected event type is invalid.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-shipstation-integration-instances-integration-instance-webhook-subscriptions
  /api/shipstation/integration-instances/{integration_instance}/webhook-subscriptions/sync:
    post:
      tags:
      - ShipStation
      summary: Sync Subscriptions from ShipStation
      description: 'Reconciles the local subscription table with the live webhook
        list on the ShipStation account (GET /webhooks):


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        - Remote webhooks with a recognised event type that are missing locally are
        **added**

        - Local subscriptions whose ShipStation webhook no longer exists remotely
        are **removed**


        Returns counts of added/removed plus the resulting total.


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      added:
                        type: integer
                      removed:
                        type: integer
                      total:
                        type: integer
                  message:
                    type: string
                  status:
                    type: string
                example:
                  data:
                    added: 1
                    removed: 0
                    total: 3
                  message: Sync complete — 1 added, 0 removed
                  status: Success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-shipstation-integration-instances-integration-instance-webhook-subscriptions-sync
  /api/shipstation/integration-instances/{integration_instance}/webhook-subscriptions/{subscription}:
    delete:
      tags:
      - ShipStation
      summary: Unsubscribe Webhook
      description: 'Removes the webhook subscription from the ShipStation account
        (DELETE /webhooks/{id}) and deletes the local record.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Returns **404** if the subscription does not belong to the given integration
        instance.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: subscription
        in: path
        schema:
          type: integer
        required: true
        description: ShipstationWebhookSubscription ID
        example: '12'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  status:
                    type: string
                example:
                  message: Webhook unsubscribed
                  status: Success
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Not Found
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: delete-api-shipstation-integration-instances-integration-instance-webhook-subscriptions-subscription
  /api/veracore/integration-instances:
    post:
      tags:
      - Veracore
      summary: Create Integration Instance
      description: 'Create a new Veracore integration instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                integration_id:
                  type: integer
                connection_settings:
                  type: object
                  properties: {}
                integration_settings:
                  type: object
                  properties:
                    connection_name:
                      type: string
                    linked_warehouse_id:
                      type: integer
                    enable_fulfillment:
                      type: boolean
                is_automatic_sync_enabled:
                  type: boolean
                is_deliver_by_date_required:
                  type: boolean
                gift_card_note_sales_order_custom_field_id:
                  type: string
                  nullable: true
                third_party_enabled_shipping_method_ids:
                  type: array
              example:
                name: Veracore Production
                integration_id: 12
                connection_settings: {}
                integration_settings:
                  connection_name: main
                  linked_warehouse_id: 1
                  enable_fulfillment: true
                is_automatic_sync_enabled: false
                is_deliver_by_date_required: false
                gift_card_note_sales_order_custom_field_id: null
                third_party_enabled_shipping_method_ids: []
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-veracore-integration-instances
  /api/veracore/integration-instances/{integration_instance}:
    get:
      tags:
      - Veracore
      summary: Show Integration Instance
      description: 'Retrieve a Veracore integration instance by ID.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        example: '5'
        description: The integration instance ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-veracore-integration-instances-integration-instance
    put:
      tags:
      - Veracore
      summary: Update Integration Instance
      description: 'Update a Veracore integration instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                integration_id:
                  type: integer
                connection_settings:
                  type: object
                  properties: {}
                integration_settings:
                  type: object
                  properties:
                    connection_name:
                      type: string
                    linked_warehouse_id:
                      type: integer
                    enable_fulfillment:
                      type: boolean
                is_automatic_sync_enabled:
                  type: boolean
                is_deliver_by_date_required:
                  type: boolean
                gift_card_note_sales_order_custom_field_id:
                  type: string
                  nullable: true
                third_party_enabled_shipping_method_ids:
                  type: array
                  items:
                    type: integer
              example:
                name: Veracore Production Updated
                integration_id: 12
                connection_settings: {}
                integration_settings:
                  connection_name: main
                  linked_warehouse_id: 1
                  enable_fulfillment: true
                is_automatic_sync_enabled: true
                is_deliver_by_date_required: true
                gift_card_note_sales_order_custom_field_id: null
                third_party_enabled_shipping_method_ids:
                - 3
                - 7
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        example: '5'
        description: The integration instance ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-veracore-integration-instances-integration-instance
    delete:
      tags:
      - Veracore
      summary: Delete Integration Instance
      description: 'Delete a Veracore integration instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        example: '5'
        description: The integration instance ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-veracore-integration-instances-integration-instance
  /api/veracore/integration-instances/test-connection:
    post:
      tags:
      - Veracore
      summary: Test Connection with Credentials
      description: 'Test a set of Veracore credentials before saving an integration
        instance. The endpoint attempts to request an access token from the Veracore
        API using the supplied credentials and reports whether authentication succeeded.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        No integration instance is created or modified — the credentials are used
        only for the live authentication attempt.


        Use this during initial setup. To test the credentials already saved on an
        existing instance, use the instance-scoped test-connection endpoint instead.


        **Errors**

        - `422` when a required field is missing.

        - `422` with `data.success = false` and `data.error` when Veracore rejects
        the credentials or the server cannot be reached.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                username:
                  type: string
                password:
                  type: string
                systemId:
                  type: string
                server_name:
                  type: string
              example:
                username: api-user@example.com
                password: secret-password
                systemId: ACME01
                server_name: rhu338
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      success:
                        type: boolean
                      has_token:
                        type: boolean
                  message:
                    type: string
                  status:
                    type: string
                example:
                  data:
                    success: true
                    has_token: true
                  message: Veracore connection successful.
                  status: success
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      success:
                        type: boolean
                      error:
                        type: string
                  message:
                    type: string
                  status:
                    type: string
                example:
                  data:
                    success: false
                    error: 'Unauthorized: invalid username or password'
                  message: Veracore connection failed.
                  status: failure
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-veracore-integration-instances-test-connection
  /api/veracore/integration-instances/{integration_instance}/test-connection:
    post:
      tags:
      - Veracore
      summary: Test Connection for Instance
      description: 'Test the Veracore connection for an existing integration instance
        using its saved credentials. The endpoint attempts to request an access token
        from the Veracore API and reports whether authentication succeeded.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        No request body is required — the credentials stored on the instance are used.


        **Errors**

        - `404` when the integration instance does not exist.

        - `422` with `data.success = false` and `data.error` when Veracore rejects
        the saved credentials or the server cannot be reached.


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      success:
                        type: boolean
                      has_token:
                        type: boolean
                  message:
                    type: string
                  status:
                    type: string
                example:
                  data:
                    success: true
                    has_token: true
                  message: Veracore connection successful.
                  status: success
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      success:
                        type: boolean
                      error:
                        type: string
                  message:
                    type: string
                  status:
                    type: string
                example:
                  data:
                    success: false
                    error: 'Unauthorized: invalid username or password'
                  message: Veracore connection failed.
                  status: failure
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-veracore-integration-instances-integration-instance-test-connection
  /api/veracore/integration-instances/{integration_instance}/financial/preview-impact:
    get:
      tags:
      - Veracore
      summary: Preview Financial Line Type Impact
      description: 'Preview how many financial lines and sales orders would be affected
        if the fulfillment-cost financial line type configured on this Veracore integration
        instance were changed to `new_type_id`. This is a read-only computation —
        no data is modified.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        The preview compares the currently configured type against the proposed one
        for fulfillments in the warehouse linked to this instance:

        - `rewire_lines` — existing fulfillment-cost financial lines that would be
        moved from the old type to the new type.

        - `backfill_lines` — fulfillments with a cost that have no financial line
        of the new type yet and would get one created.

        - `sales_orders_impacted` — distinct sales orders touched by either change.

        - `is_noop` — `true` when the change would have no effect (same type, no linked
        warehouse, or the proposed type is not a cost type).


        Omit `new_type_id` (or send it empty) to preview clearing the setting.


        **Errors**

        - `404` when the integration instance does not exist.

        - `422` when `new_type_id` is not an existing financial line type id.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 OK
                  value:
                    data:
                      rewire_lines: 128
                      backfill_lines: 46
                      sales_orders_impacted: 152
                      is_noop: false
                    status: success
                example-1:
                  summary: 200 OK — no effect
                  value:
                    data:
                      rewire_lines: 0
                      backfill_lines: 0
                      sales_orders_impacted: 0
                      is_noop: true
                    status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-veracore-integration-instances-integration-instance-financial-preview-impact
  /api/veracore/update-order/{sales_order_fulfillment}:
    put:
      tags:
      - Veracore
      summary: Update Order From Fulfillment (Power User)
      description: 'Re-dispatch a sales order fulfillment to Veracore. Requires Power
        User role.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token + is_power_user middleware.'
      requestBody:
        content: {}
      parameters:
      - name: sales_order_fulfillment
        in: path
        schema:
          type: integer
        required: true
        example: '101'
        description: The sales order fulfillment ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-veracore-update-order-sales-order-fulfillment
  /api/veracore/integration-instances/{integration_instance}/orders:
    get:
      tags:
      - Veracore
      summary: List Orders
      description: 'List locally cached Veracore orders for an integration instance
        (paginated), serialized via Veracore order object. Each order exposes the
        SKU.io fulfillment link fields: `sku_fulfillment_id` (legacy order→SalesOrderFulfillment
        id, kept as a fallback), `sku_fulfillment_order_id` (order→FulfillmentOrder
        id), and `sku_fulfillment` (a resolved link object, or null when the order
        is not yet linked). Supply `include_json=1` to include the raw Veracore `json_data`
        payload.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        example: '5'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        veracore_id:
                          type: integer
                        ReferenceNumber:
                          type: string
                        CurrentOrderStatus:
                          type: string
                        status_label:
                          type: string
                        status_color:
                          type: string
                        sku_fulfillment_id:
                          type: integer
                        sku_fulfillment_order_id:
                          type: integer
                        customer_name:
                          type: string
                        customer_email:
                          type: string
                        ship_date:
                          type: string
                        tracking_number:
                          type: string
                        carrier:
                          type: string
                        carrier_description:
                          type: string
                        requested_shipping:
                          type: string
                        ship_to:
                          type: object
                          properties:
                            name:
                              type: string
                            company:
                              type: string
                              nullable: true
                            address1:
                              type: string
                            address2:
                              type: string
                              nullable: true
                            city:
                              type: string
                            state:
                              type: string
                            postal_code:
                              type: string
                            country:
                              type: string
                            phone:
                              type: string
                            email:
                              type: string
                        items:
                          type: array
                          items:
                            type: object
                            properties:
                              sku:
                                type: string
                              description:
                                type: string
                              quantity:
                                type: integer
                              unit_price:
                                type: number
                        sku_fulfillment:
                          type: object
                          properties:
                            id:
                              type: integer
                            link_reference:
                              type: integer
                            link_type_label:
                              type: string
                            link_id:
                              type: integer
                            link_route:
                              type: string
                            status:
                              type: string
                            tracking_number:
                              type: string
                            tracking_url:
                              type: string
                            fulfilled_at:
                              type: string
                            created_at:
                              type: string
                            sales_order_id:
                              type: integer
                            sales_order_number:
                              type: string
                            fulfillment_order_id:
                              type: integer
                            warehouse:
                              type: object
                              properties:
                                id:
                                  type: integer
                                name:
                                  type: string
                        has_detailed_data:
                          type: boolean
                        details_last_updated:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - id: 5012
                    integration_instance_id: 5
                    veracore_id: 880123
                    ReferenceNumber: SO-2024-0091
                    CurrentOrderStatus: Shipped
                    status_label: Shipped
                    status_color: warning
                    sku_fulfillment_id: 731
                    sku_fulfillment_order_id: 642
                    customer_name: Jane Doe
                    customer_email: jane.doe@example.com
                    ship_date: '2024-06-03T14:00:00Z'
                    tracking_number: 1Z999AA10123456784
                    carrier: UPS
                    carrier_description: UPS Ground
                    requested_shipping: Ground
                    ship_to:
                      name: Jane Doe
                      company: null
                      address1: 123 Market St
                      address2: null
                      city: San Francisco
                      state: CA
                      postal_code: '94103'
                      country: US
                      phone: +1-415-555-0100
                      email: jane.doe@example.com
                    items:
                    - sku: WIDGET-BLUE-L
                      description: Blue Widget (Large)
                      quantity: 2
                      unit_price: 19.99
                    sku_fulfillment:
                      id: 731
                      link_reference: 731
                      link_type_label: Sales Order Fulfillment
                      link_id: 731
                      link_route: /orders/sales-orders/fulfillments/731
                      status: shipped
                      tracking_number: 1Z999AA10123456784
                      tracking_url: https://www.ups.com/track?loc=en_US&tracknum=1Z999AA10123456784
                      fulfilled_at: '2024-06-03T14:00:00+00:00'
                      created_at: '2024-06-01T12:00:00+00:00'
                      sales_order_id: 91
                      sales_order_number: SO-2024-0091
                      fulfillment_order_id: 642
                      warehouse:
                        id: 3
                        name: Main Warehouse
                    has_detailed_data: true
                    details_last_updated: '2024-06-03T15:00:00+00:00'
                    created_at: '2024-06-01T12:00:00+00:00'
                    updated_at: '2024-06-03T14:05:00+00:00'
                  - id: 5011
                    integration_instance_id: 5
                    veracore_id: 880119
                    ReferenceNumber: SO-2024-0090
                    CurrentOrderStatus: Processed
                    status_label: Processed
                    status_color: primary
                    sku_fulfillment_id: null
                    sku_fulfillment_order_id: null
                    customer_name: John Smith
                    customer_email: john.smith@example.com
                    ship_date: null
                    tracking_number: null
                    carrier: null
                    carrier_description: null
                    requested_shipping: Ground
                    ship_to:
                      name: John Smith
                      company: null
                      address1: 500 Oak Ave
                      address2: null
                      city: Austin
                      state: TX
                      postal_code: '78701'
                      country: US
                      phone: null
                      email: john.smith@example.com
                    items:
                    - sku: WIDGET-RED-S
                      description: Red Widget (Small)
                      quantity: 1
                      unit_price: 9.99
                    sku_fulfillment: null
                    has_detailed_data: false
                    details_last_updated: null
                    created_at: '2024-06-01T09:00:00+00:00'
                    updated_at: '2024-06-01T09:00:00+00:00'
                  current_page: 1
                  last_page: 9
                  per_page: 15
                  total: 128
                  from: 1
                  to: 2
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-veracore-integration-instances-integration-instance-orders
  /api/veracore/integration-instances/{integration_instance}/orders/{order}:
    get:
      tags:
      - Veracore
      summary: Show Order
      description: 'Show a single locally cached Veracore order by its database id,
        serialized via Veracore order object. Exposes the SKU.io fulfillment link
        fields `sku_fulfillment_id`, `sku_fulfillment_order_id`, and the resolved
        `sku_fulfillment` link object (null when not linked). Supply `include_json=1`
        to include the raw Veracore `json_data` payload. Returns 404 when the order
        does not belong to the given integration instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        example: '5'
        description: The integration instance ID.
      - name: order
        in: path
        schema:
          type: integer
        required: true
        example: '5012'
        description: The order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      veracore_id:
                        type: integer
                      ReferenceNumber:
                        type: string
                      CurrentOrderStatus:
                        type: string
                      status_label:
                        type: string
                      status_color:
                        type: string
                      sku_fulfillment_id:
                        type: integer
                      sku_fulfillment_order_id:
                        type: integer
                      customer_name:
                        type: string
                      customer_email:
                        type: string
                      ship_date:
                        type: string
                      tracking_number:
                        type: string
                      carrier:
                        type: string
                      carrier_description:
                        type: string
                      requested_shipping:
                        type: string
                      ship_to:
                        type: object
                        properties:
                          name:
                            type: string
                          company:
                            type: string
                            nullable: true
                          address1:
                            type: string
                          address2:
                            type: string
                            nullable: true
                          city:
                            type: string
                          state:
                            type: string
                          postal_code:
                            type: string
                          country:
                            type: string
                          phone:
                            type: string
                          email:
                            type: string
                      items:
                        type: array
                        items:
                          type: object
                          properties:
                            sku:
                              type: string
                            description:
                              type: string
                            quantity:
                              type: integer
                            unit_price:
                              type: number
                      sku_fulfillment:
                        type: object
                        properties:
                          id:
                            type: integer
                          link_reference:
                            type: integer
                          link_type_label:
                            type: string
                          link_id:
                            type: integer
                          link_route:
                            type: string
                          status:
                            type: string
                          tracking_number:
                            type: string
                          tracking_url:
                            type: string
                          fulfilled_at:
                            type: string
                          created_at:
                            type: string
                          sales_order_id:
                            type: integer
                          sales_order_number:
                            type: string
                          fulfillment_order_id:
                            type: integer
                          warehouse:
                            type: object
                            properties:
                              id:
                                type: integer
                              name:
                                type: string
                      has_detailed_data:
                        type: boolean
                      details_last_updated:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 5012
                    integration_instance_id: 5
                    veracore_id: 880123
                    ReferenceNumber: SO-2024-0091
                    CurrentOrderStatus: Shipped
                    status_label: Shipped
                    status_color: warning
                    sku_fulfillment_id: 731
                    sku_fulfillment_order_id: 642
                    customer_name: Jane Doe
                    customer_email: jane.doe@example.com
                    ship_date: '2024-06-03T14:00:00Z'
                    tracking_number: 1Z999AA10123456784
                    carrier: UPS
                    carrier_description: UPS Ground
                    requested_shipping: Ground
                    ship_to:
                      name: Jane Doe
                      company: null
                      address1: 123 Market St
                      address2: null
                      city: San Francisco
                      state: CA
                      postal_code: '94103'
                      country: US
                      phone: +1-415-555-0100
                      email: jane.doe@example.com
                    items:
                    - sku: WIDGET-BLUE-L
                      description: Blue Widget (Large)
                      quantity: 2
                      unit_price: 19.99
                    sku_fulfillment:
                      id: 731
                      link_reference: 731
                      link_type_label: Sales Order Fulfillment
                      link_id: 731
                      link_route: /orders/sales-orders/fulfillments/731
                      status: shipped
                      tracking_number: 1Z999AA10123456784
                      tracking_url: https://www.ups.com/track?loc=en_US&tracknum=1Z999AA10123456784
                      fulfilled_at: '2024-06-03T14:00:00+00:00'
                      created_at: '2024-06-01T12:00:00+00:00'
                      sales_order_id: 91
                      sales_order_number: SO-2024-0091
                      fulfillment_order_id: 642
                      warehouse:
                        id: 3
                        name: Main Warehouse
                    has_detailed_data: true
                    details_last_updated: '2024-06-03T15:00:00+00:00'
                    created_at: '2024-06-01T12:00:00+00:00'
                    updated_at: '2024-06-03T14:05:00+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-veracore-integration-instances-integration-instance-orders-order
  /api/veracore/integration-instances/{integration_instance}/orders/sync:
    post:
      tags:
      - Veracore
      summary: Sync Orders
      description: 'Queue a background job that syncs orders from Veracore for this
        integration instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        The job fetches the order list from the Veracore API for the instance''s configured
        look-back window, upserts each order locally, then queues follow-up fetches
        that pull full detail (status, shipping, line items) for every order that
        has never been enriched or is still in an open status. The instance''s last-synced
        timestamp is updated when the job finishes.


        The response is immediate and contains a `tracked_job_log_id`. Poll the sync-progress
        endpoint with that id to follow the job:

        `GET /api/veracore/integration-instances/:integration_instance/orders/sync-progress/{tracked_job_log_id}`


        **Errors**

        - `404` when the integration instance does not exist or is not a Veracore
        instance.


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                  status:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 3311
                  message: Order sync queued
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-veracore-integration-instances-integration-instance-orders-sync
  /api/veracore/integration-instances/{integration_instance}/orders/sync-progress/{tracked_job_log_id}:
    get:
      tags:
      - Veracore
      summary: Get Order Sync Progress
      description: 'Get the progress of a queued Veracore order sync. Pass the `tracked_job_log_id`
        returned by the sync endpoint.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        `status` moves through `pending` → `processing` → `completed` (or `failed`).
        While processing, `total_items` / `processed_items` / `progress_percentage`
        report how many orders still need a detail fetch. `results` includes counters
        recorded by the job such as `orders_fetched`, `orders_needing_detail`, and
        the synced date range.


        **Errors**

        - `404` when no job log exists with that id, or the id belongs to a job other
        than a Veracore order sync.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: tracked_job_log_id
        in: path
        schema:
          type: integer
        required: true
        example: '3311'
        description: The tracked job log ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      status:
                        type: string
                      job_name:
                        type: string
                      total_items:
                        type: integer
                      processed_items:
                        type: integer
                      progress_percentage:
                        type: number
                      messages:
                        type: array
                      results:
                        type: object
                        properties:
                          orders_fetched:
                            type: integer
                          orders_needing_detail:
                            type: integer
                          date_from:
                            type: string
                          date_to:
                            type: string
                      attempted_at:
                        type: string
                      completed_at:
                        type: string
                        nullable: true
                  status:
                    type: string
                example:
                  data:
                    id: 3311
                    status: processing
                    job_name: 'Sync Veracore Orders: Veracore 3PL'
                    total_items: 148
                    processed_items: 96
                    progress_percentage: 64.86
                    messages: []
                    results:
                      orders_fetched: 148
                      orders_needing_detail: 148
                      date_from: '2026-06-22T00:00:00+00:00'
                      date_to: '2026-07-06T02:00:04+00:00'
                    attempted_at: '2026-07-06T02:00:05.000000Z'
                    completed_at: null
                  status: success
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  status:
                    type: string
                example:
                  message: Job not found
                  status: failure
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-veracore-integration-instances-integration-instance-orders-sync-progress-tracked-job-log-id
  /api/veracore/integration-instances/{integration_instance}/orders/{order}/sync-detail:
    post:
      tags:
      - Veracore
      summary: Sync Order Detail
      description: 'Refresh a single Veracore order''s stored data by fetching full
        order detail from the Veracore API. The fetched detail (status flags, shipping,
        line items, addresses) is merged into the locally stored order and the detail-refresh
        timestamp is updated.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Veracore reports status as a block of flags where several can be true at once;
        the most advanced flag becomes the order''s current status (`Canceled` and
        `Complete` take precedence, then `Shipped`, and so on).


        The call is synchronous — the Veracore API is contacted during the request
        and the refreshed order is returned.


        **Errors**

        - `404` when the order does not exist or belongs to a different integration
        instance.

        - `422` when the stored record has no Veracore order id to fetch by; run a
        full order sync first.

        - `502` when the Veracore API call fails.


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: order
        in: path
        schema:
          type: integer
        required: true
        example: '42'
        description: The order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      veracore_id:
                        type: integer
                      ReferenceNumber:
                        type: string
                      CurrentOrderStatus:
                        type: string
                      status_label:
                        type: string
                      status_color:
                        type: string
                      sku_fulfillment_id:
                        type: integer
                      sku_fulfillment_order_id:
                        type: string
                        nullable: true
                      customer_name:
                        type: string
                      customer_email:
                        type: string
                      ship_date:
                        type: string
                      tracking_number:
                        type: string
                      parcels:
                        type: array
                      carrier:
                        type: string
                      carrier_description:
                        type: string
                      requested_shipping:
                        type: string
                      ship_to:
                        type: object
                        properties:
                          name:
                            type: string
                          company:
                            type: string
                            nullable: true
                          address1:
                            type: string
                          address2:
                            type: string
                            nullable: true
                          city:
                            type: string
                          state:
                            type: string
                          postal_code:
                            type: string
                          country:
                            type: string
                          phone:
                            type: string
                          email:
                            type: string
                      items:
                        type: array
                        items:
                          type: object
                          properties:
                            sku:
                              type: string
                            description:
                              type: string
                            quantity:
                              type: integer
                            unit_price:
                              type: number
                      sku_fulfillment:
                        type: object
                        properties:
                          id:
                            type: integer
                          link_reference:
                            type: integer
                          link_type_label:
                            type: string
                          link_id:
                            type: integer
                          link_route:
                            type: string
                          status:
                            type: string
                          tracking_number:
                            type: string
                          tracking_url:
                            type: string
                          fulfilled_at:
                            type: string
                          created_at:
                            type: string
                          sales_order_id:
                            type: integer
                          sales_order_number:
                            type: string
                          fulfillment_order_id:
                            type: string
                            nullable: true
                          warehouse:
                            type: object
                            properties:
                              id:
                                type: integer
                              name:
                                type: string
                      has_detailed_data:
                        type: boolean
                      details_last_updated:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                  message:
                    type: string
                  status:
                    type: string
                example:
                  data:
                    id: 42
                    integration_instance_id: 1
                    veracore_id: 8675309
                    ReferenceNumber: C604018.1
                    CurrentOrderStatus: Shipped
                    status_label: Shipped
                    status_color: warning
                    sku_fulfillment_id: 5150
                    sku_fulfillment_order_id: null
                    customer_name: Jane Smith
                    customer_email: jane.smith@example.com
                    ship_date: '2026-07-01T18:22:04Z'
                    tracking_number: 1Z999AA10123456784
                    parcels: []
                    carrier: UPS
                    carrier_description: UPS Ground
                    requested_shipping: Ground
                    ship_to:
                      name: Jane Smith
                      company: null
                      address1: 123 Main St
                      address2: null
                      city: Austin
                      state: TX
                      postal_code: '78701'
                      country: US
                      phone: 512-555-0134
                      email: jane.smith@example.com
                    items:
                    - sku: WIDGET-BLUE
                      description: Blue Widget
                      quantity: 2
                      unit_price: 14.99
                    sku_fulfillment:
                      id: 5150
                      link_reference: 5150
                      link_type_label: Sales Order Fulfillment
                      link_id: 5150
                      link_route: /orders/sales-orders/fulfillments/5150
                      status: fulfilled
                      tracking_number: 1Z999AA10123456784
                      tracking_url: https://www.ups.com/track?tracknum=1Z999AA10123456784
                      fulfilled_at: '2026-07-01T18:22:04+00:00'
                      created_at: '2026-07-01T10:13:58+00:00'
                      sales_order_id: 900
                      sales_order_number: C604018
                      fulfillment_order_id: null
                      warehouse:
                        id: 4
                        name: Veracore 3PL
                    has_detailed_data: true
                    details_last_updated: '2026-07-06T09:15:00+00:00'
                    created_at: '2026-07-01T02:00:18+00:00'
                    updated_at: '2026-07-06T09:15:00+00:00'
                  message: Order details refreshed
                  status: success
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  status:
                    type: string
                example:
                  message: Cannot sync details — this record has no Veracore OrderId
                    in its stored data. Run a full order list sync from the Veracore
                    integration page to repopulate it.
                  status: failure
        '502':
          description: Bad Gateway
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  status:
                    type: string
                example:
                  message: 'Failed to fetch order detail: cURL error 28: Operation
                    timed out'
                  status: failure
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-veracore-integration-instances-integration-instance-orders-order-sync-detail
  /api/veracore/integration-instances/{integration_instance}/dashboard:
    get:
      tags:
      - Veracore
      summary: Get Dashboard Metrics
      description: 'Get aggregate metrics for a Veracore integration instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Returns:

        - `totalOrders` — total Veracore orders stored for this instance.

        - `ordersByStatus` — one entry per Veracore order status (all 13 statuses
        are always present, with `count: 0` when empty): `Unapproved`, `Unprocessed`,
        `Accepted`, `Hold`, `DeniedCredit`, `Pending`, `Processed`, `Picked`, `Backordered`,
        `PartiallyShipped`, `Shipped`, `Complete`, `Canceled`.

        - `ordersLastSyncedAt` / `trackingLastSyncedAt` — timestamps of the most recent
        order and tracking syncs.

        - `pendingReportTasks` — report tasks still in `created`, `polling`, or `done`
        (awaiting processing) status.

        - `failedReportTasks` — report tasks in `failed` status.

        - `unlinkedOrders` — Veracore orders not yet linked to a SKU.io fulfillment.


        All values are computed from locally stored data; no call is made to the Veracore
        API.


        **Errors**

        - `404` when the integration instance does not exist.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      totalOrders:
                        type: integer
                      ordersByStatus:
                        type: array
                        items:
                          type: object
                          properties:
                            status:
                              type: string
                            status_label:
                              type: string
                            count:
                              type: integer
                      ordersLastSyncedAt:
                        type: string
                      trackingLastSyncedAt:
                        type: string
                      pendingReportTasks:
                        type: integer
                      failedReportTasks:
                        type: integer
                      unlinkedOrders:
                        type: integer
                  status:
                    type: string
                example:
                  data:
                    totalOrders: 1284
                    ordersByStatus:
                    - status: Unapproved
                      status_label: Unapproved
                      count: 0
                    - status: Unprocessed
                      status_label: Unprocessed
                      count: 3
                    - status: Accepted
                      status_label: Accepted
                      count: 12
                    - status: Hold
                      status_label: Hold
                      count: 1
                    - status: DeniedCredit
                      status_label: Denied Credit
                      count: 0
                    - status: Pending
                      status_label: Pending
                      count: 8
                    - status: Processed
                      status_label: Processed
                      count: 25
                    - status: Picked
                      status_label: Picked
                      count: 14
                    - status: Backordered
                      status_label: Backordered
                      count: 2
                    - status: PartiallyShipped
                      status_label: Partially Shipped
                      count: 4
                    - status: Shipped
                      status_label: Shipped
                      count: 310
                    - status: Complete
                      status_label: Complete
                      count: 896
                    - status: Canceled
                      status_label: Canceled
                      count: 9
                    ordersLastSyncedAt: '2026-07-06T02:00:11+00:00'
                    trackingLastSyncedAt: '2026-07-06T02:30:44+00:00'
                    pendingReportTasks: 2
                    failedReportTasks: 1
                    unlinkedOrders: 7
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-veracore-integration-instances-integration-instance-dashboard
  /api/veracore/integration-instances/{integration_instance}/activity-log:
    get:
      tags:
      - Veracore
      summary: List Activity Log Entries
      description: 'List activity log entries recorded against a Veracore integration
        instance, including changes to the instance itself and to its Veracore orders.
        Entries are returned newest first.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Each entry includes the event name, the type and id of the changed record,
        the change payload (`properties`), and the name of the user who caused the
        change (`causer_name`, `null` for system-initiated changes).


        **Filters**

        - `filter[search]` — matches the causer name, event, record type, or anywhere
        in the change payload.

        - `filter[event]` — exact event, e.g. `created`, `updated`, `deleted`, `bulk_upsert`.

        - `filter[source]` — the source recorded on the change, e.g. `manual` or a
        sync process name.

        - `filter[batch_uuid]` — all entries written by one bulk operation.


        **Errors**

        - `404` when the integration instance does not exist.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        description:
                          type: string
                        event:
                          type: string
                        subject_type:
                          type: string
                        subject_id:
                          type: integer
                        properties:
                          type: object
                          properties:
                            attributes:
                              type: object
                              properties:
                                integration_settings:
                                  type: object
                                  properties:
                                    sync_days_back:
                                      type: integer
                            old:
                              type: object
                              properties:
                                integration_settings:
                                  type: object
                                  properties:
                                    sync_days_back:
                                      type: integer
                        causer_name:
                          type: string
                        created_at:
                          type: string
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                    items:
                      type: object
                      properties:
                        url:
                          type: string
                          nullable: true
                        label:
                          type: string
                        active:
                          type: boolean
                  next_page_url:
                    type: string
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 90211
                    description: updated
                    event: updated
                    subject_type: IntegrationInstance
                    subject_id: 1
                    properties:
                      attributes:
                        integration_settings:
                          sync_days_back: 14
                      old:
                        integration_settings:
                          sync_days_back: 7
                    causer_name: Jane Admin
                    created_at: '2026-07-05T14:22:31.000000Z'
                  - id: 90187
                    description: created
                    event: created
                    subject_type: VeracoreOrder
                    subject_id: 42
                    properties:
                      source: veracore_sync
                    causer_name: null
                    created_at: '2026-07-05T02:00:18.000000Z'
                  first_page_url: https://app.example.com/api/veracore/integration-instances/1/activity-log?page=1
                  from: 1
                  last_page: 6
                  last_page_url: https://app.example.com/api/veracore/integration-instances/1/activity-log?page=6
                  links:
                  - url: null
                    label: '&laquo; Previous'
                    active: false
                  - url: https://app.example.com/api/veracore/integration-instances/1/activity-log?page=1
                    label: '1'
                    active: true
                  - url: https://app.example.com/api/veracore/integration-instances/1/activity-log?page=2
                    label: Next &raquo;
                    active: false
                  next_page_url: https://app.example.com/api/veracore/integration-instances/1/activity-log?page=2
                  path: https://app.example.com/api/veracore/integration-instances/1/activity-log
                  per_page: 15
                  prev_page_url: null
                  to: 15
                  total: 84
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-veracore-integration-instances-integration-instance-activity-log
  /api/veracore/integration-instances/{integration_instance}/fulfillments:
    get:
      tags:
      - Veracore
      summary: List Fulfillments
      description: 'List SKU.io sales order fulfillments dispatched to this Veracore
        integration instance. Only fulfillments of the Veracore fulfillment type are
        returned, scoped to the warehouse linked to the instance when one is configured.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Use this to find the fulfillment a Veracore order shipped against, then link
        it with the link-fulfillment endpoint. Each row is a full fulfillment record
        plus a `customer_name` convenience field.


        **Filters**

        - `filter[search]` — matches fulfillment number, tracking number, sales order
        number, or customer name.

        - `filter[status]` — exact fulfillment status.

        - `filter[requested_shipping_method_id]` — exact shipping method id.


        **Sorting**

        `sort` accepts `id`, `fulfillment_number`, `status`, `fulfilled_at`, `created_at`,
        `updated_at` (prefix with `-` for descending). Default sort is `-id`.


        **Errors**

        - `404` when the integration instance does not exist or is not a Veracore
        instance.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        fulfillment_number:
                          type: string
                        sales_order_id:
                          type: integer
                        fulfillment_order_id:
                          type: integer
                        fulfillment_type:
                          type: string
                        fulfillment_status:
                          type: string
                        shipping_method_id:
                          type: integer
                        shipping_method:
                          type: string
                        requested_shipping_method:
                          type: string
                          nullable: true
                        requested_shipping_method_id:
                          type: integer
                        requested_shipping_method_name:
                          type: string
                        fulfilled_shipping_method:
                          type: string
                          nullable: true
                        fulfilled_shipping_method_id:
                          type: integer
                        fulfilled_shipping_method_name:
                          type: string
                        fulfilled_date:
                          type: string
                        tracking_number:
                          type: string
                        tracking_url:
                          type: string
                        tracking_link:
                          type: string
                        warehouse:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            type:
                              type: string
                            supplier_id:
                              type: string
                              nullable: true
                            is_dropship:
                              type: boolean
                        warehouse_id:
                          type: integer
                        fulfilled_by:
                          type: string
                          nullable: true
                        fulfilled_quantity:
                          type: integer
                        fulfillment_lines:
                          type: array
                          items:
                            type: object
                            properties:
                              id:
                                type: integer
                              sales_order_line_id:
                                type: integer
                              quantity:
                                type: integer
                        cost:
                          type: number
                        status:
                          type: string
                        voided_at:
                          type: string
                          nullable: true
                        void_reason:
                          type: string
                          nullable: true
                        voided_by:
                          type: string
                          nullable: true
                        fulfilled_at:
                          type: string
                        marked_for_pickup_at:
                          type: string
                          nullable: true
                        expected_pickup_at:
                          type: string
                          nullable: true
                        packing_slip_printed_at:
                          type: string
                          nullable: true
                        submitted_to_sales_channel_at:
                          type: string
                        last_synced_to_provider_at:
                          type: string
                        last_synced_from_provider_at:
                          type: string
                        metadata:
                          type: string
                          nullable: true
                        fulfillment_sequence:
                          type: integer
                        is_parent:
                          type: boolean
                        parent_id:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                        provider_order_id:
                          type: integer
                        sales_channel_fulfillment_link:
                          type: string
                          nullable: true
                        customer_name:
                          type: string
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                    items:
                      type: object
                      properties:
                        url:
                          type: string
                          nullable: true
                        label:
                          type: string
                        active:
                          type: boolean
                  next_page_url:
                    type: string
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 5150
                    fulfillment_number: F-5150
                    sales_order_id: 900
                    fulfillment_order_id: 611
                    fulfillment_type: veracore
                    fulfillment_status: fulfilled
                    shipping_method_id: 3
                    shipping_method: UPS Ground
                    requested_shipping_method: null
                    requested_shipping_method_id: 3
                    requested_shipping_method_name: UPS Ground
                    fulfilled_shipping_method: null
                    fulfilled_shipping_method_id: 3
                    fulfilled_shipping_method_name: UPS Ground
                    fulfilled_date: '2026-07-01T18:22:04.000000Z'
                    tracking_number: 1Z999AA10123456784
                    tracking_url: https://www.ups.com/track?tracknum=1Z999AA10123456784
                    tracking_link: https://www.ups.com/track?tracknum=1Z999AA10123456784
                    warehouse:
                      id: 4
                      name: Veracore 3PL
                      type: third_party
                      supplier_id: null
                      is_dropship: false
                    warehouse_id: 4
                    fulfilled_by: null
                    fulfilled_quantity: 2
                    fulfillment_lines:
                    - id: 8123
                      sales_order_line_id: 4410
                      quantity: 2
                    cost: 8.42
                    status: fulfilled
                    voided_at: null
                    void_reason: null
                    voided_by: null
                    fulfilled_at: '2026-07-01T18:22:04.000000Z'
                    marked_for_pickup_at: null
                    expected_pickup_at: null
                    packing_slip_printed_at: null
                    submitted_to_sales_channel_at: '2026-07-01T19:05:12.000000Z'
                    last_synced_to_provider_at: '2026-07-01T10:14:00.000000Z'
                    last_synced_from_provider_at: '2026-07-01T18:30:00.000000Z'
                    metadata: null
                    fulfillment_sequence: 1
                    is_parent: false
                    parent_id: null
                    created_at: '2026-07-01T10:13:58.000000Z'
                    provider_order_id: 8675309
                    sales_channel_fulfillment_link: null
                    customer_name: Jane Smith
                  first_page_url: https://app.example.com/api/veracore/integration-instances/1/fulfillments?page=1
                  from: 1
                  last_page: 12
                  last_page_url: https://app.example.com/api/veracore/integration-instances/1/fulfillments?page=12
                  links:
                  - url: null
                    label: '&laquo; Previous'
                    active: false
                  - url: https://app.example.com/api/veracore/integration-instances/1/fulfillments?page=1
                    label: '1'
                    active: true
                  - url: https://app.example.com/api/veracore/integration-instances/1/fulfillments?page=2
                    label: Next &raquo;
                    active: false
                  next_page_url: https://app.example.com/api/veracore/integration-instances/1/fulfillments?page=2
                  path: https://app.example.com/api/veracore/integration-instances/1/fulfillments
                  per_page: 15
                  prev_page_url: null
                  to: 15
                  total: 178
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-veracore-integration-instances-integration-instance-fulfillments
  /api/veracore/integration-instances/{integration_instance}/orders/{order}/link-fulfillment:
    post:
      tags:
      - Veracore
      summary: Link Order to Fulfillment
      description: 'Link a Veracore order to a SKU.io sales order fulfillment. Pass
        the fulfillment id as `sku_fulfillment_id` in the body — use the fulfillments
        list endpoint to find candidates.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        This is a local bookkeeping change only: the link is stored on the Veracore
        order record in SKU.io so tracking, costs, and reconciliation can flow between
        the two. Nothing is sent to Veracore.


        Returns the updated Veracore order with its `sku_fulfillment` details populated.


        **Errors**

        - `400` when `sku_fulfillment_id` is missing or zero.

        - `404` when the order does not exist or belongs to a different integration
        instance.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                sku_fulfillment_id:
                  type: integer
              example:
                sku_fulfillment_id: 5150
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: order
        in: path
        schema:
          type: integer
        required: true
        example: '42'
        description: The order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      veracore_id:
                        type: integer
                      ReferenceNumber:
                        type: string
                      CurrentOrderStatus:
                        type: string
                      status_label:
                        type: string
                      status_color:
                        type: string
                      sku_fulfillment_id:
                        type: integer
                      sku_fulfillment_order_id:
                        type: string
                        nullable: true
                      customer_name:
                        type: string
                      customer_email:
                        type: string
                      ship_date:
                        type: string
                      tracking_number:
                        type: string
                      parcels:
                        type: array
                      carrier:
                        type: string
                      carrier_description:
                        type: string
                      requested_shipping:
                        type: string
                      ship_to:
                        type: object
                        properties:
                          name:
                            type: string
                          company:
                            type: string
                            nullable: true
                          address1:
                            type: string
                          address2:
                            type: string
                            nullable: true
                          city:
                            type: string
                          state:
                            type: string
                          postal_code:
                            type: string
                          country:
                            type: string
                          phone:
                            type: string
                          email:
                            type: string
                      items:
                        type: array
                        items:
                          type: object
                          properties:
                            sku:
                              type: string
                            description:
                              type: string
                            quantity:
                              type: integer
                            unit_price:
                              type: number
                      sku_fulfillment:
                        type: object
                        properties:
                          id:
                            type: integer
                          link_reference:
                            type: integer
                          link_type_label:
                            type: string
                          link_id:
                            type: integer
                          link_route:
                            type: string
                          status:
                            type: string
                          tracking_number:
                            type: string
                          tracking_url:
                            type: string
                          fulfilled_at:
                            type: string
                          created_at:
                            type: string
                          sales_order_id:
                            type: integer
                          sales_order_number:
                            type: string
                          fulfillment_order_id:
                            type: string
                            nullable: true
                          warehouse:
                            type: object
                            properties:
                              id:
                                type: integer
                              name:
                                type: string
                      has_detailed_data:
                        type: boolean
                      details_last_updated:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                  status:
                    type: string
                example:
                  data:
                    id: 42
                    integration_instance_id: 1
                    veracore_id: 8675309
                    ReferenceNumber: C604018.1
                    CurrentOrderStatus: Shipped
                    status_label: Shipped
                    status_color: warning
                    sku_fulfillment_id: 5150
                    sku_fulfillment_order_id: null
                    customer_name: Jane Smith
                    customer_email: jane.smith@example.com
                    ship_date: '2026-07-01T18:22:04Z'
                    tracking_number: 1Z999AA10123456784
                    parcels: []
                    carrier: UPS
                    carrier_description: UPS Ground
                    requested_shipping: Ground
                    ship_to:
                      name: Jane Smith
                      company: null
                      address1: 123 Main St
                      address2: null
                      city: Austin
                      state: TX
                      postal_code: '78701'
                      country: US
                      phone: 512-555-0134
                      email: jane.smith@example.com
                    items:
                    - sku: WIDGET-BLUE
                      description: Blue Widget
                      quantity: 2
                      unit_price: 14.99
                    sku_fulfillment:
                      id: 5150
                      link_reference: 5150
                      link_type_label: Sales Order Fulfillment
                      link_id: 5150
                      link_route: /orders/sales-orders/fulfillments/5150
                      status: fulfilled
                      tracking_number: 1Z999AA10123456784
                      tracking_url: https://www.ups.com/track?tracknum=1Z999AA10123456784
                      fulfilled_at: '2026-07-01T18:22:04+00:00'
                      created_at: '2026-07-01T10:13:58+00:00'
                      sales_order_id: 900
                      sales_order_number: C604018
                      fulfillment_order_id: null
                      warehouse:
                        id: 4
                        name: Veracore 3PL
                    has_detailed_data: true
                    details_last_updated: '2026-07-02T09:15:00+00:00'
                    created_at: '2026-07-01T02:00:18+00:00'
                    updated_at: '2026-07-06T10:01:12+00:00'
                  status: success
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  status:
                    type: string
                example:
                  message: sku_fulfillment_id required
                  status: failure
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  status:
                    type: string
                example:
                  message: Order not found
                  status: failure
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-veracore-integration-instances-integration-instance-orders-order-link-fulfillment
  /api/veracore/integration-instances/{integration_instance}/orders/{order}/unlink-fulfillment:
    post:
      tags:
      - Veracore
      summary: Unlink Order from Fulfillment
      description: 'Remove the link between a Veracore order and its SKU.io sales
        order fulfillment. No request body is required.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        This is a local bookkeeping change only: the stored link on the Veracore order
        record is cleared. Nothing is sent to Veracore, and the fulfillment itself
        is not modified.


        Returns the updated Veracore order with `sku_fulfillment_id` cleared.


        **Errors**

        - `404` when the order does not exist or belongs to a different integration
        instance.


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: order
        in: path
        schema:
          type: integer
        required: true
        example: '42'
        description: The order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      veracore_id:
                        type: integer
                      ReferenceNumber:
                        type: string
                      CurrentOrderStatus:
                        type: string
                      status_label:
                        type: string
                      status_color:
                        type: string
                      sku_fulfillment_id:
                        type: string
                        nullable: true
                      sku_fulfillment_order_id:
                        type: string
                        nullable: true
                      customer_name:
                        type: string
                      customer_email:
                        type: string
                      ship_date:
                        type: string
                      tracking_number:
                        type: string
                      parcels:
                        type: array
                      carrier:
                        type: string
                      carrier_description:
                        type: string
                      requested_shipping:
                        type: string
                      ship_to:
                        type: object
                        properties:
                          name:
                            type: string
                          company:
                            type: string
                            nullable: true
                          address1:
                            type: string
                          address2:
                            type: string
                            nullable: true
                          city:
                            type: string
                          state:
                            type: string
                          postal_code:
                            type: string
                          country:
                            type: string
                          phone:
                            type: string
                          email:
                            type: string
                      items:
                        type: array
                        items:
                          type: object
                          properties:
                            sku:
                              type: string
                            description:
                              type: string
                            quantity:
                              type: integer
                            unit_price:
                              type: number
                      sku_fulfillment:
                        type: string
                        nullable: true
                      has_detailed_data:
                        type: boolean
                      details_last_updated:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                  status:
                    type: string
                example:
                  data:
                    id: 42
                    integration_instance_id: 1
                    veracore_id: 8675309
                    ReferenceNumber: C604018.1
                    CurrentOrderStatus: Shipped
                    status_label: Shipped
                    status_color: warning
                    sku_fulfillment_id: null
                    sku_fulfillment_order_id: null
                    customer_name: Jane Smith
                    customer_email: jane.smith@example.com
                    ship_date: '2026-07-01T18:22:04Z'
                    tracking_number: 1Z999AA10123456784
                    parcels: []
                    carrier: UPS
                    carrier_description: UPS Ground
                    requested_shipping: Ground
                    ship_to:
                      name: Jane Smith
                      company: null
                      address1: 123 Main St
                      address2: null
                      city: Austin
                      state: TX
                      postal_code: '78701'
                      country: US
                      phone: 512-555-0134
                      email: jane.smith@example.com
                    items:
                    - sku: WIDGET-BLUE
                      description: Blue Widget
                      quantity: 2
                      unit_price: 14.99
                    sku_fulfillment: null
                    has_detailed_data: true
                    details_last_updated: '2026-07-02T09:15:00+00:00'
                    created_at: '2026-07-01T02:00:18+00:00'
                    updated_at: '2026-07-06T10:05:40+00:00'
                  status: success
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  status:
                    type: string
                example:
                  message: Order not found for this instance
                  status: failure
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-veracore-integration-instances-integration-instance-orders-order-unlink-fulfillment
  /api/veracore/integration-instances/{integration_instance}/report-tasks:
    get:
      tags:
      - Veracore
      summary: List Report Tasks
      description: 'List Veracore report tasks for an integration instance. A report
        task represents one Veracore report run used to import shipment and tracking
        data for a date range. Tasks are returned newest first.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Statuses**

        - `created` — task created, not yet submitted for polling.

        - `polling` — waiting for Veracore to finish generating the report (`poll_attempts`
        counts checks so far).

        - `done` — report retrieved, awaiting processing.

        - `processed` — report rows applied (`rows_matched` reports how many rows
        matched local records).

        - `failed` — the run failed (`error_message` explains why); it can be retried.

        - `superseded` — replaced by a retry and no longer polled.


        **Filters**

        - `filter[status]` — exact status value from the list above.

        - `filter[date_from]` / `filter[date_to]` — created date range (inclusive,
        whole days).

        - Operator-suffixed filters are also available: `filter[created_at.<op>]`
        and `filter[processed_at.<op>]` with date operators (`is`, `is_not`, `before`,
        `after`, `on_or_before`, `on_or_after`, `between`, `is_empty`, `is_not_empty`,
        `today`, `yesterday`, `past_week`, `past_month`, `past_year`, `days_ago`,
        `past_days`, and more), and `filter[report_name.<op>]` with text operators
        (`contains`, `does_not_contain`, `is`, `is_not`, `is_one_of`, `is_not_one_of`,
        `starts_with`, `ends_with`, `is_empty`, `is_not_empty`, and more).

        - `filter_groups` — a base64-encoded JSON tree combining the operator-suffixed
        filters with nested and/or groups.


        **Sorting**

        `sort` accepts `id`, `status`, `report_name`, `created_at`, `processed_at`,
        `poll_attempts`, `rows_matched` (prefix with `-` for descending). Default
        sort is `-id`.


        **Errors**

        - `404` when the integration instance does not exist or is not a Veracore
        instance.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        veracore_task_id:
                          type: string
                        report_name:
                          type: string
                        status:
                          type: string
                        status_label:
                          type: string
                        status_color:
                          type: string
                        filter_start_date:
                          type: string
                        filter_end_date:
                          type: string
                        poll_attempts:
                          type: integer
                        rows_matched:
                          type: integer
                        error_message:
                          type: string
                          nullable: true
                        processed_at:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                    items:
                      type: object
                      properties:
                        url:
                          type: string
                          nullable: true
                        label:
                          type: string
                        active:
                          type: boolean
                  next_page_url:
                    type: string
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 77
                    integration_instance_id: 1
                    veracore_task_id: a1b2c3d4-5678-90ab-cdef-1234567890ab
                    report_name: Shipped Orders Export
                    status: processed
                    status_label: Processed
                    status_color: success
                    filter_start_date: '2026-06-28T00:00:00+00:00'
                    filter_end_date: '2026-07-05T23:59:59+00:00'
                    poll_attempts: 3
                    rows_matched: 148
                    error_message: null
                    processed_at: '2026-07-05T06:15:22+00:00'
                    created_at: '2026-07-05T06:00:04+00:00'
                    updated_at: '2026-07-05T06:15:22+00:00'
                  - id: 76
                    integration_instance_id: 1
                    veracore_task_id: 0f9e8d7c-6543-21ba-fedc-0987654321ba
                    report_name: Shipped Orders Export
                    status: failed
                    status_label: Failed
                    status_color: error
                    filter_start_date: '2026-06-27T00:00:00+00:00'
                    filter_end_date: '2026-07-04T23:59:59+00:00'
                    poll_attempts: 20
                    rows_matched: null
                    error_message: Report generation timed out after 20 poll attempts
                    processed_at: null
                    created_at: '2026-07-04T06:00:02+00:00'
                    updated_at: '2026-07-04T08:40:19+00:00'
                  first_page_url: https://app.example.com/api/veracore/integration-instances/1/report-tasks?page=1
                  from: 1
                  last_page: 4
                  last_page_url: https://app.example.com/api/veracore/integration-instances/1/report-tasks?page=4
                  links:
                  - url: null
                    label: '&laquo; Previous'
                    active: false
                  - url: https://app.example.com/api/veracore/integration-instances/1/report-tasks?page=1
                    label: '1'
                    active: true
                  - url: https://app.example.com/api/veracore/integration-instances/1/report-tasks?page=2
                    label: Next &raquo;
                    active: false
                  next_page_url: https://app.example.com/api/veracore/integration-instances/1/report-tasks?page=2
                  path: https://app.example.com/api/veracore/integration-instances/1/report-tasks
                  per_page: 15
                  prev_page_url: null
                  to: 15
                  total: 52
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-veracore-integration-instances-integration-instance-report-tasks
  /api/veracore/integration-instances/{integration_instance}/report-tasks/{report_task}/retry:
    post:
      tags:
      - Veracore
      summary: Retry Report Task
      description: 'Retry a Veracore report task. The original task is marked `superseded`
        (so it stops being polled) and a fresh task is created with the same report
        name and date range in `created` status. A background job is queued to submit
        and poll the new run against the Veracore API.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        The response returns the newly created task immediately; watch its status
        via the report task list.


        **Errors**

        - `404` when the report task does not exist or belongs to a different integration
        instance.


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: report_task
        in: path
        schema:
          type: integer
        required: true
        example: '76'
        description: The report task ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      veracore_task_id:
                        type: string
                      report_name:
                        type: string
                      status:
                        type: string
                      status_label:
                        type: string
                      status_color:
                        type: string
                      filter_start_date:
                        type: string
                      filter_end_date:
                        type: string
                      poll_attempts:
                        type: integer
                      rows_matched:
                        type: string
                        nullable: true
                      error_message:
                        type: string
                        nullable: true
                      processed_at:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                  message:
                    type: string
                  status:
                    type: string
                example:
                  data:
                    id: 81
                    integration_instance_id: 1
                    veracore_task_id: ''
                    report_name: Shipped Orders Export
                    status: created
                    status_label: Created
                    status_color: info
                    filter_start_date: '2026-06-27T00:00:00+00:00'
                    filter_end_date: '2026-07-04T23:59:59+00:00'
                    poll_attempts: 0
                    rows_matched: null
                    error_message: null
                    processed_at: null
                    created_at: '2026-07-06T10:12:44+00:00'
                    updated_at: '2026-07-06T10:12:44+00:00'
                  message: Report task retry queued
                  status: success
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  status:
                    type: string
                example:
                  message: Report task not found for this instance
                  status: failure
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-veracore-integration-instances-integration-instance-report-tasks-report-task-retry
  /api/veracore/integration-instances/{integration_instance}/shipping-methods:
    get:
      tags:
      - Veracore
      summary: List Shipping Method Mappings
      description: 'List every carrier + service combination observed on this instance''s
        Veracore orders, joined with any existing mapping to a SKU.io shipping method,
        plus the full list of SKU.io shipping methods available to map to.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Each entry in `services` has a `code` in the form `Carrier|Service Description`
        (e.g. `UPS|UPS Ground`), how many orders were seen with that combination,
        and the current `mapping` (or `null` when unmapped). Combinations that were
        mapped previously but no longer appear on any order are still included with
        `order_count: 0`.


        All data is read from locally stored orders; no call is made to the Veracore
        API.


        Use the returned `code` values with the map and unmap endpoints.


        **Errors**

        - `404` when the integration instance does not exist or is not a Veracore
        instance.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      services:
                        type: array
                        items:
                          type: object
                          properties:
                            code:
                              type: string
                            carrier:
                              type: string
                            carrier_description:
                              type: string
                            order_count:
                              type: integer
                            mapping:
                              type: object
                              properties:
                                id:
                                  type: integer
                                shipping_method_id:
                                  type: integer
                                shipping_method_name:
                                  type: string
                                shipping_method_type:
                                  type: string
                      sku_shipping_methods:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            full_name:
                              type: string
                            type:
                              type: string
                  status:
                    type: string
                example:
                  data:
                    services:
                    - code: UPS|UPS Ground
                      carrier: UPS
                      carrier_description: UPS Ground
                      order_count: 412
                      mapping:
                        id: 9
                        shipping_method_id: 3
                        shipping_method_name: UPS Ground
                        shipping_method_type: standard
                    - code: FedEx|FedEx 2Day
                      carrier: FedEx
                      carrier_description: FedEx 2Day
                      order_count: 57
                      mapping: null
                    sku_shipping_methods:
                    - id: 3
                      name: Ground
                      full_name: UPS Ground
                      type: standard
                    - id: 7
                      name: 2Day
                      full_name: FedEx 2Day
                      type: expedited
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-veracore-integration-instances-integration-instance-shipping-methods
  /api/veracore/integration-instances/{integration_instance}/shipping-methods/map:
    put:
      tags:
      - Veracore
      summary: Map Shipping Method
      description: 'Create or update the mapping from a Veracore carrier + service
        combination to a SKU.io shipping method.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        `code` is the combination identifier in the form `Carrier|Service Description`
        (e.g. `UPS|UPS Ground`), as returned by the shipping method list endpoint.
        Mapping the same `code` again replaces the previous target shipping method.


        **Errors**

        - `404` when the integration instance does not exist or is not a Veracore
        instance.

        - `422` when `code` is missing/too long or `shipping_method_id` is not an
        existing shipping method.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                code:
                  type: string
                shipping_method_id:
                  type: integer
              example:
                code: UPS|UPS Ground
                shipping_method_id: 3
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      code:
                        type: string
                      shipping_method_id:
                        type: integer
                  message:
                    type: string
                  status:
                    type: string
                example:
                  data:
                    id: 9
                    code: UPS|UPS Ground
                    shipping_method_id: 3
                  message: Mapping saved
                  status: success
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      shipping_method_id:
                        type: array
                        items:
                          type: string
                example:
                  message: The selected shipping method id is invalid.
                  errors:
                    shipping_method_id:
                    - The selected shipping method id is invalid.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: put-api-veracore-integration-instances-integration-instance-shipping-methods-map
  /api/veracore/integration-instances/{integration_instance}/shipping-methods/map/{code}:
    delete:
      tags:
      - Veracore
      summary: Delete Shipping Method Mapping
      description: 'Remove the mapping for a Veracore carrier + service combination
        so it is no longer translated to a SKU.io shipping method.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        `code` is the combination identifier in the form `Carrier|Service Description`
        (e.g. `UPS|UPS Ground`). URL-encode it in the path (the pipe becomes `%7C`,
        spaces become `%20`); slashes inside the code are also accepted.


        **Errors**

        - `404` when no mapping exists for that code, or the integration instance
        does not exist.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: code
        in: path
        schema:
          type: string
        required: true
        example: UPS|UPS Ground
        description: The code ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  status:
                    type: string
                example:
                  message: Mapping removed
                  status: success
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  status:
                    type: string
                example:
                  message: Mapping not found
                  status: failure
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: delete-api-veracore-integration-instances-integration-instance-shipping-methods-map-code
  /api/veracore/integration-instances/{integration_instance}/source-code-mappings:
    get:
      tags:
      - Veracore
      summary: List Source Code Mappings
      description: 'List all source code mappings for a Veracore integration instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        A source code mapping determines the Veracore source code stamped on orders
        submitted to Veracore, based on the sales channel the order came from. A mapping
        with a `sub_sales_channel_id` applies only to orders from that sub channel;
        a mapping with `sub_sales_channel_id: null` is the catch-all for the whole
        sales channel.


        The response is a plain array (not paginated).


        **Errors**

        - `404` when the integration instance does not exist or is not a Veracore
        instance.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        sales_channel_integration_instance_id:
                          type: integer
                        sales_channel_integration_instance_name:
                          type: string
                        sub_sales_channel_id:
                          type: integer
                        sub_sales_channel_name:
                          type: string
                        source_code:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  status:
                    type: string
                example:
                  data:
                  - id: 3
                    integration_instance_id: 1
                    sales_channel_integration_instance_id: 5
                    sales_channel_integration_instance_name: Shopify - Main Store
                    sub_sales_channel_id: 8
                    sub_sales_channel_name: Retail
                    source_code: SHOP-RETAIL
                    created_at: '2026-06-01T12:00:00.000000Z'
                    updated_at: '2026-06-15T09:30:00.000000Z'
                  - id: 4
                    integration_instance_id: 1
                    sales_channel_integration_instance_id: 5
                    sales_channel_integration_instance_name: Shopify - Main Store
                    sub_sales_channel_id: null
                    sub_sales_channel_name: null
                    source_code: SHOP-DEFAULT
                    created_at: '2026-06-01T12:05:00.000000Z'
                    updated_at: '2026-06-01T12:05:00.000000Z'
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-veracore-integration-instances-integration-instance-source-code-mappings
    post:
      tags:
      - Veracore
      summary: Create Source Code Mapping
      description: 'Create a source code mapping for a Veracore integration instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Body fields**

        - `sales_channel_integration_instance_id` (required, integer) — the sales
        channel integration instance the mapping applies to; must exist.

        - `sub_sales_channel_id` (optional, integer) — restrict the mapping to one
        sub sales channel; must exist when provided. Omit or send `null` to create
        the channel''s catch-all mapping.

        - `source_code` (optional, string, defaults to empty) — the Veracore source
        code to stamp on matching orders.


        Only one mapping may exist per sales channel + sub channel combination.


        **Errors**

        - `404` when the integration instance does not exist or is not a Veracore
        instance.

        - `422` when the referenced sales channel instance or sub channel does not
        exist, or a mapping for the same combination already exists.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                sales_channel_integration_instance_id:
                  type: integer
                sub_sales_channel_id:
                  type: integer
                source_code:
                  type: string
              example:
                sales_channel_integration_instance_id: 5
                sub_sales_channel_id: 8
                source_code: SHOP-RETAIL
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      sales_channel_integration_instance_id:
                        type: integer
                      sales_channel_integration_instance_name:
                        type: string
                      sub_sales_channel_id:
                        type: integer
                      sub_sales_channel_name:
                        type: string
                      source_code:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                  status:
                    type: string
                example:
                  data:
                    id: 3
                    integration_instance_id: 1
                    sales_channel_integration_instance_id: 5
                    sales_channel_integration_instance_name: Shopify - Main Store
                    sub_sales_channel_id: 8
                    sub_sales_channel_name: Retail
                    source_code: SHOP-RETAIL
                    created_at: '2026-07-06T10:20:00.000000Z'
                    updated_at: '2026-07-06T10:20:00.000000Z'
                  status: success
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: object
                    properties:
                      sales_channel_integration_instance_id:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: array
                  message:
                    type: string
                  status:
                    type: string
                example:
                  errors:
                    sales_channel_integration_instance_id:
                    - message: A mapping for this sales channel and subchannel combination
                        already exists.
                      code: SourceCodeMappingError
                      data: []
                  message: A mapping for this sales channel and subchannel combination
                    already exists.
                  status: failure
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-veracore-integration-instances-integration-instance-source-code-mappings
  /api/veracore/integration-instances/{integration_instance}/source-code-mappings/preview:
    get:
      tags:
      - Veracore
      summary: Preview Source Code for Sales Order
      description: 'Preview which Veracore source code would be applied to a given
        sales order under the current mappings. This is a read-only computation —
        nothing is stored and no call is made to the Veracore API.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Resolution order:

        1. A mapping matching the order''s sales channel **and** sub sales channel
        (`matched_type: "sub_channel"`).

        2. The sales channel''s catch-all mapping with no sub channel (`matched_type:
        "catch_all"`).

        3. No match — `source_code` and `matched_type` are `null`.


        The response also includes the sales channel and sub channel context used
        for resolution so you can see why a mapping did or did not match.


        **Errors**

        - `404` when no sales order exists with the given `sales_order_id`, or the
        integration instance does not exist.


        Authentication: Requires Bearer token.'
      parameters:
      - name: sales_order_id
        in: query
        schema:
          type: integer
        description: Id of the sales order to resolve a source code for. Required.
        example: '900'
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 OK — mapping matched
                  value:
                    data:
                      source_code: SHOP-RETAIL
                      matched_type: sub_channel
                      sales_channel_integration_instance_id: 5
                      sales_channel_integration_instance_name: Shopify - Main Store
                      sub_sales_channel_id: 8
                      sub_sales_channel_name: Retail
                    status: success
                example-1:
                  summary: 200 OK — no mapping
                  value:
                    data:
                      source_code: null
                      matched_type: null
                      sales_channel_integration_instance_id: 6
                      sales_channel_integration_instance_name: Amazon US
                      sub_sales_channel_id: null
                      sub_sales_channel_name: null
                    status: success
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: object
                    properties:
                      sales_order_id:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: array
                  message:
                    type: string
                  status:
                    type: string
                example:
                  errors:
                    sales_order_id:
                    - message: Sales order not found
                      code: NotFound
                      data: []
                  message: Sales order not found
                  status: failure
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-veracore-integration-instances-integration-instance-source-code-mappings-preview
  /api/veracore/integration-instances/{integration_instance}/source-code-mappings/{source_code_mapping}:
    put:
      tags:
      - Veracore
      summary: Update Source Code Mapping
      description: 'Update a source code mapping. Only the fields provided are changed;
        `null` values are ignored.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Body fields**

        - `sub_sales_channel_id` (optional, integer) — move the mapping to a different
        sub sales channel; must exist when provided. Note: because `null` values are
        ignored, a sub-channel mapping cannot be converted to a catch-all here — delete
        it and create a new one instead.

        - `source_code` (optional, string) — the Veracore source code to stamp on
        matching orders.


        The sales channel of a mapping cannot be changed.


        **Errors**

        - `404` when the mapping or integration instance does not exist.

        - `422` when `sub_sales_channel_id` does not reference an existing sub sales
        channel.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                sub_sales_channel_id:
                  type: integer
                source_code:
                  type: string
              example:
                sub_sales_channel_id: 8
                source_code: SHOP-RETAIL-2026
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: source_code_mapping
        in: path
        schema:
          type: integer
        required: true
        example: '3'
        description: The source code mapping ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      sales_channel_integration_instance_id:
                        type: integer
                      sales_channel_integration_instance_name:
                        type: string
                      sub_sales_channel_id:
                        type: integer
                      sub_sales_channel_name:
                        type: string
                      source_code:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                  status:
                    type: string
                example:
                  data:
                    id: 3
                    integration_instance_id: 1
                    sales_channel_integration_instance_id: 5
                    sales_channel_integration_instance_name: Shopify - Main Store
                    sub_sales_channel_id: 8
                    sub_sales_channel_name: Retail
                    source_code: SHOP-RETAIL-2026
                    created_at: '2026-06-01T12:00:00.000000Z'
                    updated_at: '2026-07-06T10:25:00.000000Z'
                  status: success
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      sub_sales_channel_id:
                        type: array
                        items:
                          type: string
                example:
                  message: The selected sub sales channel id is invalid.
                  errors:
                    sub_sales_channel_id:
                    - The selected sub sales channel id is invalid.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: put-api-veracore-integration-instances-integration-instance-source-code-mappings-source-code-mapping
    delete:
      tags:
      - Veracore
      summary: Delete Source Code Mapping
      description: 'Delete a source code mapping. Orders from the affected sales channel
        fall back to the channel''s catch-all mapping (if one exists) or to no source
        code.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Errors**

        - `404` when the mapping or integration instance does not exist.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The integration instance ID.
      - name: source_code_mapping
        in: path
        schema:
          type: integer
        required: true
        example: '3'
        description: The source code mapping ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  status:
                    type: string
                example:
                  message: Source code mapping deleted successfully
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-veracore-integration-instances-integration-instance-source-code-mappings-source-code-mapping
  /api/3pl/products:
    get:
      tags:
      - 3PL
      summary: List Products
      description: 'Returns paginated product catalog for 3PL partners with essential
        fulfillment information.

        Authentication: Requires 3PL integration Bearer token (with 3pl:read ability).

        Rate limit: 120 requests per 60 seconds.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        example: '1'
        description: Page number (default 1).
      - name: per_page
        in: query
        schema:
          type: integer
        example: '100'
        description: Results per page (default 10).
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-3pl-products
  /api/3pl/asns:
    get:
      tags:
      - 3PL
      summary: List ASNs (Advanced Shipping Notices)
      description: 'Returns paginated Advanced Shipping Notices (inbound shipments
        and/or RMAs) destined for the 3PL''s warehouses.

        Authentication: Requires 3PL integration Bearer token (with 3pl:read ability).

        Rate limit: 120 requests per 60 seconds.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        example: '1'
        description: Page number (default 1).
      - name: per_page
        in: query
        schema:
          type: integer
        example: '100'
        description: Results per page (default 10).
      - name: type
        in: query
        schema:
          type: string
        example: inbound_shipment
      - name: sort
        in: query
        schema:
          type: string
        example: -updated_at
        description: Sort field; prefix with - for descending (e.g. -created_at).
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-3pl-asns
  /api/3pl/asns/receipt:
    post:
      tags:
      - 3PL
      summary: Receive ASN (Report Receipt)
      description: 'Reports receipt of an ASN at the 3PL warehouse. Creates purchase
        receipts or return receipts in SKU.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Request fields:

        - type (required): one of `purchase_order`, `rma`, `inbound_shipment`. Determines
        which entity the `line_id` values reference.

        - reference_number (required): the SKU reference of the PO / RMA / inbound
        shipment being received.

        - received_at (required): ISO-8601 datetime the goods were received.

        - lines (required, min 1): array of receipt lines.

        - lines[].line_id (required): the purchase order line / RMA line / inbound
        shipment line ID, depending on `type`.

        - lines[].quantity_received (required): quantity received for that line (>=
        0).


        Warehouse resolution: a `purchase_order`-type ASN is accepted when the 3PL
        partner can access EITHER the purchase order''s header destination warehouse
        OR any of the destination warehouses of the purchase order''s inbound shipments.
        Received goods land in the inbound shipment''s destination warehouse — which
        may differ from the PO header — so one PO can be received across multiple
        3PL warehouses.


        Idempotency: Identical receipts are de-duplicated within a 10-minute window.
        The dedup key is (integration instance, type, reference_number, received_at,
        sorted line/quantity pairs) — any two requests with the same fingerprint will
        only materialise one receipt. The duplicate request still returns HTTP 200,
        but with the message `ASN receipt already processed (duplicate ignored).`
        This protects against client retries (e.g. Infor IONAPI Mingle re-firing with
        a fresh request id after a slow receive times out). To submit a genuinely
        distinct receipt for the same document, vary `received_at` or the line/quantity
        payload.


        Authentication: Requires 3PL integration Bearer token (with 3pl:write ability).

        Rate limit: 120 requests per 60 seconds.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                type:
                  type: string
                reference_number:
                  type: string
                received_at:
                  type: string
                lines:
                  type: array
                  items:
                    type: object
                    properties:
                      line_id:
                        type: integer
                      quantity_received:
                        type: integer
              example:
                type: inbound_shipment
                reference_number: IS-2024-0042
                received_at: '2024-01-20T14:00:00Z'
                lines:
                - line_id: 150
                  quantity_received: 98
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 Receipt Recorded
                  value:
                    message: Receipt recorded successfully.
                    data:
                      type: inbound_shipment
                      reference_number: IS-2024-0042
                      received_at: '2024-01-20T14:00:00Z'
                      lines:
                      - line_id: 150
                        quantity_received: 98
                example-1:
                  summary: 200 Duplicate Ignored (Idempotency)
                  value:
                    message: ASN receipt already processed (duplicate ignored).
        '422':
          description: Unprocessable Content
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      reference_number:
                        type: array
                        items:
                          type: string
                example:
                  message: The selected reference number is invalid.
                  errors:
                    reference_number:
                    - The selected reference number is invalid.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-3pl-asns-receipt
  /api/3pl/orders:
    get:
      tags:
      - 3PL
      summary: List Orders (Outbound Fulfillments)
      description: 'Returns paginated outbound fulfillment orders for the 3PL''s warehouses.

        Authentication: Requires 3PL integration Bearer token (with 3pl:read ability).

        Rate limit: 120 requests per 60 seconds.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Each order now also returns its lifecycle state: `request_status` (submitted=Released,
        accepted=Downloaded, acknowledged=Acknowledged), `downloaded_at`, and `acknowledged_at`.
        Acknowledged orders remain in this list until they ship.


        The `order_number` is the FulfillmentOrder''s sequenced reference `{sales_order_number}.{sequence}`
        (e.g. `#14522.1`) — one routed slice of the sales order. The `.{sequence}`
        suffix distinguishes slices and re-submits after a void; pull partners (e.g.
        D3) match orders on this value. Each line''s `id` is the FulfillmentOrderLine
        id (echo it back on fulfill) and `quantity` is the remaining quantity still
        to ship.'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        example: '1'
        description: Page number (default 1).
      - name: per_page
        in: query
        schema:
          type: integer
        example: '100'
        description: Results per page (default 10).
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        order_number:
                          type: string
                        order_date:
                          type: string
                        ship_by_date:
                          type: string
                        delivery_date:
                          type: string
                          nullable: true
                        warehouse:
                          type: string
                        shipping_address:
                          type: object
                          properties:
                            name:
                              type: string
                            company:
                              type: string
                            address1:
                              type: string
                            address2:
                              type: string
                            address3:
                              type: string
                              nullable: true
                            city:
                              type: string
                            province:
                              type: string
                            province_code:
                              type: string
                            zip:
                              type: string
                            country:
                              type: string
                            country_code:
                              type: string
                            phone:
                              type: string
                            email:
                              type: string
                        shipping_method:
                          type: string
                        custom_fields:
                          type: array
                        lines:
                          type: array
                          items:
                            type: object
                            properties:
                              id:
                                type: integer
                              sales_order_line_id:
                                type: integer
                              sku:
                                type: string
                              quantity:
                                type: integer
                        request_status:
                          type: string
                        downloaded_at:
                          type: string
                        acknowledged_at:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 7155
                    order_number: '#14522.1'
                    order_date: '2026-05-13T03:15:48.000000Z'
                    ship_by_date: '2026-06-21T14:00:00.000000Z'
                    delivery_date: null
                    warehouse: D3 Sydney
                    shipping_address:
                      name: Brooke Walker Baxter
                      company: collabbWAY
                      address1: 119 Eggleston Street
                      address2: ''
                      address3: null
                      city: Ocean Grove
                      province: Victoria
                      province_code: VIC
                      zip: '3226'
                      country: Australia
                      country_code: AU
                      phone: 0401918991
                      email: hello@collabbway.com.au
                    shipping_method: Designer Transport DT Standard
                    custom_fields: []
                    lines:
                    - id: 8111
                      sales_order_line_id: 7035
                      sku: T-CH01-OACA
                      quantity: 8
                    - id: 8112
                      sales_order_line_id: 7036
                      sku: T-SS02OAK
                      quantity: 8
                    request_status: accepted
                    downloaded_at: '2026-06-22T00:00:02.000000Z'
                    acknowledged_at: null
                    created_at: '2026-06-18T22:31:12.000000Z'
                    updated_at: '2026-06-22T00:00:02.000000Z'
                  first_page_url: https://example.sku.io/api/3pl/orders?page=1
                  from: 1
                  last_page: 1
                  last_page_url: https://example.sku.io/api/3pl/orders?page=1
                  next_page_url: null
                  path: https://example.sku.io/api/3pl/orders
                  per_page: 100
                  prev_page_url: null
                  to: 1
                  total: 1
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-3pl-orders
  /api/3pl/orders/{salesOrderFulfillment}/fulfill:
    post:
      tags:
      - 3PL
      summary: Fulfill Order
      description: 'Reports that an order has been fulfilled by the 3PL. Updates fulfillment
        status in SKU.

        Authentication: Requires 3PL integration Bearer token (with 3pl:write ability).

        Rate limit: 120 requests per 60 seconds.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                lines:
                  type: array
                  items:
                    type: object
                    properties:
                      id:
                        type: integer
                      quantity_fulfilled:
                        type: integer
                fulfilled_at:
                  type: string
                shipping_method:
                  type: string
                tracking_number:
                  type: string
              example:
                lines:
                - id: 600
                  quantity_fulfilled: 3
                fulfilled_at: '2024-01-17T15:00:00Z'
                shipping_method: UPS Ground
                tracking_number: 1Z999AA10123456784
      parameters:
      - name: salesOrderFulfillment
        in: path
        schema:
          type: integer
        required: true
        example: '500'
        description: The sales order fulfillment ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-3pl-orders-salesorderfulfillment-fulfill
  /api/3pl/inventory-adjustments:
    post:
      tags:
      - 3PL
      summary: Create Inventory Adjustment
      description: 'Creates an inventory adjustment from the 3PL partner for their
        warehouse.

        Authentication: Requires 3PL integration Bearer token (with 3pl:write ability).

        Rate limit: 120 requests per 60 seconds.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                sku:
                  type: string
                quantity:
                  type: integer
                adjustment_type:
                  type: string
                notes:
                  type: string
                adjustment_date:
                  type: string
              example:
                sku: WIDGET-001
                quantity: 5
                adjustment_type: decrease
                notes: Damaged in transit
                adjustment_date: '2024-01-20'
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-3pl-inventory-adjustments
  /api/3pl/orders/fulfillmentOrder/fulfill:
    post:
      tags:
      - 3PL
      summary: Fulfill Order
      description: 'Report a shipment for a fulfillment order — the partner confirms
        what it shipped. Creates one SalesOrderFulfillment against the FO (inventory
        + COGS post at ship-time), decrements each line''s remaining, and advances
        the FO Open → Incomplete ("Partially shipped") → Closed.


        Body:

        - `lines` (required, min 1): `{id, quantity_fulfilled}` where `id` is the
        FULFILLMENT ORDER LINE id (from List Orders), `quantity_fulfilled` numeric
        ≥ 0 (clamped to remaining).

        - `fulfilled_at` (required date): the actual shipped timestamp (drives COGS
        dating).

        - `shipping_method`, `tracking_number` (optional).

        - `provider_shipment_id` (optional): idempotent dedup — a retried fulfill
        never records a duplicate shipment.


        All-zero report → 422.


        Auth: 3PL Integration Token (Bearer).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                lines:
                  type: array
                  items:
                    type: object
                    properties:
                      id:
                        type: integer
                      quantity_fulfilled:
                        type: integer
                fulfilled_at:
                  type: string
                shipping_method:
                  type: string
                tracking_number:
                  type: string
                provider_shipment_id:
                  type: string
              example:
                lines:
                - id: 9
                  quantity_fulfilled: 2
                fulfilled_at: '2026-06-03T14:10:00Z'
                shipping_method: UPS Ground
                tracking_number: 1Z999AA10123456784
                provider_shipment_id: SHP-7781
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-3pl-orders-fulfillmentorder-fulfill
  /api/3pl/orders/fulfillmentOrder/acknowledge:
    post:
      tags:
      - 3PL
      summary: Acknowledge Order
      description: 'OPTIONAL pull-provider acknowledgment. After the partner has downloaded
        an order (the List Orders poll marks each served order as "downloaded" / request_status
        = accepted), the partner may explicitly acknowledge it — "we have it and will
        ship it" — advancing it to request_status = acknowledged and stamping acknowledged_at.


        This is OPTIONAL and never gates the shipment: a partner that skips it simply
        ships from the downloaded state via Fulfill Order. Idempotent — re-acknowledging
        is a no-op (acknowledged_at is preserved). An acknowledged order still appears
        in List Orders until it ships.


        Path param: `fulfillmentOrder` — the FO id (from List Orders).


        No request body.


        Responses: 200 (acknowledged, returns the order); 422 (the order is completed
        or cancelled); 404 (the order is not at one of this partner''s mapped warehouses).


        Auth: 3PL Integration Token (Bearer).'
      requestBody:
        content: {}
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      order_number:
                        type: string
                      order_date:
                        type: string
                      ship_by_date:
                        type: string
                      delivery_date:
                        type: string
                        nullable: true
                      warehouse:
                        type: string
                      shipping_address:
                        type: object
                        properties:
                          name:
                            type: string
                          company:
                            type: string
                            nullable: true
                          address1:
                            type: string
                          address2:
                            type: string
                            nullable: true
                          address3:
                            type: string
                            nullable: true
                          city:
                            type: string
                          province:
                            type: string
                          province_code:
                            type: string
                          zip:
                            type: string
                          country:
                            type: string
                          country_code:
                            type: string
                          phone:
                            type: string
                          email:
                            type: string
                      shipping_method:
                        type: string
                      custom_fields:
                        type: array
                      lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            sales_order_line_id:
                              type: integer
                            sku:
                              type: string
                            quantity:
                              type: integer
                      request_status:
                        type: string
                      downloaded_at:
                        type: string
                      acknowledged_at:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  message: Fulfillment order acknowledged.
                  data:
                    id: 500
                    order_number: SO-0204
                    order_date: '2026-06-18'
                    ship_by_date: '2026-06-20'
                    delivery_date: null
                    warehouse: EXT_WAREHOUSE_001
                    shipping_address:
                      name: Jane Doe
                      company: null
                      address1: 12 Erskine Park Rd
                      address2: null
                      address3: null
                      city: Erskine Park
                      province: NSW
                      province_code: NSW
                      zip: '2759'
                      country: Australia
                      country_code: AU
                      phone: +61 2 1234 5678
                      email: jane@example.com
                    shipping_method: TNT Express
                    custom_fields: []
                    lines:
                    - id: 9
                      sales_order_line_id: 7683
                      sku: SS-ST31BR
                      quantity: 1
                    request_status: acknowledged
                    downloaded_at: '2026-06-18T02:59:25+00:00'
                    acknowledged_at: '2026-06-18T13:36:26+00:00'
                    created_at: '2026-06-18T15:13:46+00:00'
                    updated_at: '2026-06-18T13:36:26+00:00'
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Fulfillment order not found.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Cannot acknowledge a completed or cancelled fulfillment
                    order.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-3pl-orders-fulfillmentorder-acknowledge
  /api/3pl/tokens:
    post:
      tags:
      - 3PL
      summary: Create 3PL Integration Token
      description: 'Creates an integration instance and generates an API token for
        a 3PL shipping provider.

        Authentication: Requires Sanctum Bearer token (regular user auth).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                integration_name:
                  type: string
                name:
                  type: string
                warehouse_mappings:
                  type: array
                  items:
                    type: object
                    properties:
                      warehouse_id:
                        type: integer
                      external_warehouse_id:
                        type: string
              example:
                integration_name: D3
                name: D3 Production Instance
                warehouse_mappings:
                - warehouse_id: 1
                  external_warehouse_id: EXT-WH-001
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-3pl-tokens
  /api/3pl/tokens/{integrationInstance}:
    delete:
      tags:
      - 3PL
      summary: Delete 3PL Integration Token
      description: 'Deletes a 3PL integration instance and all associated tokens and
        warehouse mappings.

        Authentication: Requires Sanctum Bearer token (regular user auth).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        example: '25'
        description: The integration instance ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-3pl-tokens-integrationinstance
  /api/trackstar/integration-instances:
    post:
      tags:
      - Trackstar
      summary: Create Integration Instance
      description: 'Create a new Trackstar WMS integration instance. Requires Bearer
        token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Request body fields:

        - name (required, string, unique): Display name for this integration

        - integration_id (required, integer): ID of the Trackstar integration type

        - connection_settings.access_token (optional, string): Trackstar API access
        token

        - connection_settings.connection_id (optional, string): Trackstar connection
        identifier

        - integration_settings.enable_fulfillment (optional, boolean): Enable fulfillment
        via Trackstar

        - is_automatic_sync_enabled (optional, boolean): Toggle automatic background
        sync'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                integration_id:
                  type: integer
                connection_settings:
                  type: object
                  properties:
                    access_token:
                      type: string
                    connection_id:
                      type: string
                integration_settings:
                  type: object
                  properties:
                    enable_fulfillment:
                      type: boolean
                is_automatic_sync_enabled:
                  type: boolean
              example:
                name: My Trackstar WMS
                integration_id: 5
                connection_settings:
                  access_token: tk_live_abc123
                  connection_id: conn_xyz789
                integration_settings:
                  enable_fulfillment: true
                is_automatic_sync_enabled: false
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      integration_id:
                        type: integer
                      connection_settings:
                        type: object
                        properties:
                          connection_id:
                            type: string
                      integration_settings:
                        type: object
                        properties:
                          enable_fulfillment:
                            type: boolean
                      is_automatic_sync_enabled:
                        type: boolean
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 10
                    name: My Trackstar WMS
                    integration_id: 5
                    connection_settings:
                      connection_id: conn_xyz789
                    integration_settings:
                      enable_fulfillment: true
                    is_automatic_sync_enabled: false
                    created_at: '2024-06-01T12:00:00.000Z'
                    updated_at: '2024-06-01T12:00:00.000Z'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      name:
                        type: array
                        items:
                          type: string
                      integration_id:
                        type: array
                        items:
                          type: string
                example:
                  message: The given data was invalid.
                  errors:
                    name:
                    - The name has already been taken.
                    integration_id:
                    - The selected integration id is invalid.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-trackstar-integration-instances
  /api/trackstar/connections/preview:
    post:
      tags:
      - Trackstar
      summary: Preview Connection Name
      description: 'Preview the WMS integration name for a connection before it is
        saved. Requires Bearer token.


        Given an access token and connection ID, this looks up the matching connection
        and returns a suggested display name (e.g. "Mintsoft") so a create form can
        auto-default the integration name. No integration instance is created and
        nothing is persisted.


        Request body fields:

        - access_token (required, string): Access token for the connection

        - connection_id (required, string): Identifier of the connection to look up


        Response fields (under `data`):

        - matched (boolean): Whether a connection matched the supplied connection
        ID

        - connection_id (string): The connection ID that was looked up

        - integration_name (string|null): Machine name of the matched WMS (e.g. "mintsoft")

        - integration_display_name (string|null): Human-friendly WMS name (e.g. "Mintsoft")

        - suggested_name (string|null): Recommended default name (display name, falling
        back to machine name)

        - message (string|null): Explanation when no match was found or the lookup
        could not be completed'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                access_token:
                  type: string
                connection_id:
                  type: string
              example:
                access_token: tk_live_abc123
                connection_id: conn_xyz789
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 OK (Matched)
                  value:
                    data:
                      matched: true
                      connection_id: conn_xyz789
                      integration_name: mintsoft
                      integration_display_name: Mintsoft
                      suggested_name: Mintsoft
                      message: null
                example-1:
                  summary: 200 OK (No Match)
                  value:
                    data:
                      matched: false
                      connection_id: conn_missing
                      integration_name: null
                      integration_display_name: null
                      suggested_name: null
                      message: No connection matched that connection ID for this access
                        token.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      access_token:
                        type: array
                        items:
                          type: string
                      connection_id:
                        type: array
                        items:
                          type: string
                example:
                  message: An access token is required to look up the connection name.
                  errors:
                    access_token:
                    - An access token is required to look up the connection name.
                    connection_id:
                    - A connection ID is required to look up the connection name.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-trackstar-connections-preview
  /api/trackstar/integration-instances/{integration_instance}:
    get:
      tags:
      - Trackstar
      summary: Show Integration Instance
      description: 'Retrieve a single Trackstar integration instance with its settings.
        Requires Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '10'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      integration_id:
                        type: integer
                      connection_settings:
                        type: object
                        properties:
                          connection_id:
                            type: string
                      integration_settings:
                        type: object
                        properties:
                          enable_fulfillment:
                            type: boolean
                      is_automatic_sync_enabled:
                        type: boolean
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 10
                    name: My Trackstar WMS
                    integration_id: 5
                    connection_settings:
                      connection_id: conn_xyz789
                    integration_settings:
                      enable_fulfillment: true
                    is_automatic_sync_enabled: false
                    created_at: '2024-06-01T12:00:00.000Z'
                    updated_at: '2024-06-01T12:00:00.000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-trackstar-integration-instances-integration-instance
    put:
      tags:
      - Trackstar
      summary: Update Integration Instance
      description: 'Update an existing Trackstar integration instance. All fields
        optional. Requires Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        integration_settings includes:

        - fulfillment_cost_financial_line_type_id (optional, int|null): COST financial
        line type used for Trackstar shipping cost lines. null = auto (default "Shipping
        Cost"). Must be a cost type or returns 422.


        When the effective cost-line type changes, a reconcile tracked job is dispatched
        (rewires existing Trackstar cost lines old→new and backfills missing from
        stored payloads) and the response includes reconcile_tracked_job_log_id.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                integration_settings:
                  type: object
                  properties:
                    fulfillment_cost_financial_line_type_id:
                      type: integer
              example:
                integration_settings:
                  fulfillment_cost_financial_line_type_id: 10
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '10'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      integration_id:
                        type: integer
                      is_automatic_sync_enabled:
                        type: boolean
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 10
                    name: My Trackstar WMS Updated
                    integration_id: 5
                    is_automatic_sync_enabled: true
                    created_at: '2024-06-01T12:00:00.000Z'
                    updated_at: '2024-06-20T10:00:00.000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-trackstar-integration-instances-integration-instance
    delete:
      tags:
      - Trackstar
      summary: Delete Integration Instance
      description: 'Delete a Trackstar integration instance and all associated data.
        Requires Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '10'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: string
                    nullable: true
                  message:
                    type: string
                example:
                  data: null
                  message: Integration instance deleted successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-trackstar-integration-instances-integration-instance
  /api/trackstar/integration-instances/{integration_instance}/dashboard:
    get:
      tags:
      - Trackstar
      summary: Dashboard Metrics
      description: 'Get dashboard summary metrics for a Trackstar integration instance
        (order counts, inventory totals, sync status, etc.). Requires Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '10'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      orders_count:
                        type: integer
                      inventory_items_count:
                        type: integer
                      products_count:
                        type: integer
                      bills_count:
                        type: integer
                      last_order_sync_at:
                        type: string
                      last_inventory_sync_at:
                        type: string
                example:
                  data:
                    orders_count: 1250
                    inventory_items_count: 320
                    products_count: 180
                    bills_count: 450
                    last_order_sync_at: '2024-06-20T08:30:00.000Z'
                    last_inventory_sync_at: '2024-06-20T07:00:00.000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-trackstar-integration-instances-integration-instance-dashboard
  /api/trackstar/integration-instances/{integration_instance}/test-connection:
    post:
      tags:
      - Trackstar
      summary: Test Connection
      description: 'Test the connection to the Trackstar API for this integration
        instance. Returns success/failure with any error details. Requires Bearer
        token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '10'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 OK - Success
                  value:
                    data:
                      success: true
                      message: Connection successful
                      response_time_ms: 245
                example-1:
                  summary: 200 OK - Failed
                  value:
                    data:
                      success: false
                      message: 'Authentication failed: Invalid access token'
                      response_time_ms: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-trackstar-integration-instances-integration-instance-test-connection
  /api/trackstar/integration-instances/{integrationInstance}/cost-line-type/preview:
    post:
      tags:
      - Trackstar
      summary: Preview Cost Line Type Impact
      description: 'Preview how many Trackstar cost financial lines and sales orders
        would be touched if the fulfillment-cost financial line type changed to new_type_id.
        Read-only. Requires Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Request body:

        - new_type_id (optional, int|null): Proposed cost financial line type id.
        null = auto default. Must exist.


        backfill_lines counts Trackstar fulfillments whose stored payload carries
        shipping_cost but have no line yet.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                new_type_id:
                  type: integer
              example:
                new_type_id: 10
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Trackstar integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      rewire_lines:
                        type: integer
                      backfill_lines:
                        type: integer
                      sales_orders_impacted:
                        type: integer
                      is_noop:
                        type: boolean
                example:
                  data:
                    rewire_lines: 4
                    backfill_lines: 318
                    sales_orders_impacted: 320
                    is_noop: false
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-trackstar-integration-instances-integrationinstance-cost-line-type-preview
  /api/trackstar/integration-instances/{integration_instance}/connection:
    get:
      tags:
      - Trackstar
      summary: Get Connection Info
      description: 'Fetch the live Trackstar connection payload for the instance —
        connection metadata, the WMS `available_actions` (which capabilities this
        WMS supports), and sync schedules. Read-only; degrades gracefully with a `success:
        false` + message if the connection cannot be reached. Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '10'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      success:
                        type: boolean
                      message:
                        type: string
                        nullable: true
                      connection:
                        type: object
                        properties:
                          connection_id:
                            type: string
                          integration_name:
                            type: string
                          integration_display_name:
                            type: string
                          available_actions:
                            type: array
                            items:
                              type: string
                          sync_schedules:
                            type: array
                            items:
                              type: object
                              properties:
                                function_name:
                                  type: string
                                sync_frequency:
                                  type: integer
                                sync_status:
                                  type: string
                                last_crawl_start:
                                  type: string
                                last_crawl_end:
                                  type: string
                      available_actions:
                        type: array
                        items:
                          type: string
                      fetched_at:
                        type: string
                example:
                  data:
                    success: true
                    message: null
                    connection:
                      connection_id: conn_9d04a322e67043b683406f1b609f9a53
                      integration_name: mintsoft
                      integration_display_name: Mintsoft
                      available_actions:
                      - get_inventory
                      - get_products
                      - get_orders
                      - get_inbound_shipments
                      - get_returns
                      sync_schedules:
                      - function_name: get_inventory
                        sync_frequency: 3600
                        sync_status: enabled
                        last_crawl_start: '2026-07-08T00:00:00Z'
                        last_crawl_end: '2026-07-08T00:05:00Z'
                    available_actions:
                    - get_inventory
                    - get_products
                    - get_orders
                    - get_inbound_shipments
                    - get_returns
                    fetched_at: '2026-07-08T12:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-trackstar-integration-instances-integration-instance-connection
  /api/trackstar/integration-instances/{integration_instance}/connection/refresh:
    post:
      tags:
      - Trackstar
      summary: Refresh Connection
      description: Re-fetch the Trackstar connection and persist the snapshot (and
        derived `available_actions`) onto the instance so capability-aware behaviour
        reflects any change in what the WMS supports. Returns the same shape as Get
        Connection Info. Requires Bearer token.
      requestBody:
        content: {}
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '10'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      success:
                        type: boolean
                      message:
                        type: string
                        nullable: true
                      connection:
                        type: object
                        properties:
                          connection_id:
                            type: string
                          integration_name:
                            type: string
                          integration_display_name:
                            type: string
                          available_actions:
                            type: array
                            items:
                              type: string
                          sync_schedules:
                            type: array
                            items:
                              type: object
                              properties:
                                function_name:
                                  type: string
                                sync_frequency:
                                  type: integer
                                sync_status:
                                  type: string
                                last_crawl_start:
                                  type: string
                                last_crawl_end:
                                  type: string
                      available_actions:
                        type: array
                        items:
                          type: string
                      fetched_at:
                        type: string
                example:
                  data:
                    success: true
                    message: null
                    connection:
                      connection_id: conn_9d04a322e67043b683406f1b609f9a53
                      integration_name: mintsoft
                      integration_display_name: Mintsoft
                      available_actions:
                      - get_inventory
                      - get_products
                      - get_orders
                      - get_inbound_shipments
                      - get_returns
                      sync_schedules:
                      - function_name: get_inventory
                        sync_frequency: 3600
                        sync_status: enabled
                        last_crawl_start: '2026-07-08T00:00:00Z'
                        last_crawl_end: '2026-07-08T00:05:00Z'
                    available_actions:
                    - get_inventory
                    - get_products
                    - get_orders
                    - get_inbound_shipments
                    - get_returns
                    fetched_at: '2026-07-08T12:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-trackstar-integration-instances-integration-instance-connection-refresh
  /api/trackstar/integration-instances/{integration_instance}/warehouse-mappings:
    get:
      tags:
      - Trackstar
      summary: List Warehouse Mappings
      description: 'List all Trackstar warehouse-to-SKU.io warehouse mappings for
        an integration instance. Returns full warehouse details including locations.
        Requires Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '10'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        trackstar_warehouse_id:
                          type: string
                        trackstar_warehouse:
                          type: object
                          properties:
                            id:
                              type: integer
                            trackstar_warehouse_id:
                              type: string
                            name:
                              type: string
                            code:
                              type: string
                            address1:
                              type: string
                            city:
                              type: string
                            state:
                              type: string
                            postal_code:
                              type: string
                            country:
                              type: string
                            locations:
                              type: array
                        warehouse_id:
                          type: integer
                        warehouse_name:
                          type: string
                        is_active:
                          type: boolean
                        created_at:
                          type: string
                        updated_at:
                          type: string
                example:
                  data:
                  - id: 1
                    integration_instance_id: 10
                    trackstar_warehouse_id: wh_abc123
                    trackstar_warehouse:
                      id: 5
                      trackstar_warehouse_id: wh_abc123
                      name: East Coast Warehouse
                      code: ECW
                      address1: 123 Storage Blvd
                      city: Newark
                      state: NJ
                      postal_code: '07102'
                      country: US
                      locations: []
                    warehouse_id: 3
                    warehouse_name: NJ Warehouse
                    is_active: true
                    created_at: '2024-06-01T12:00:00.000Z'
                    updated_at: '2024-06-01T12:00:00.000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-trackstar-integration-instances-integration-instance-warehouse-mappings
    post:
      tags:
      - Trackstar
      summary: Create Warehouse Mapping
      description: 'Create a mapping between a Trackstar warehouse and a SKU.io warehouse.
        Returns 422 if the Trackstar warehouse is not found or the mapping already
        exists. Requires Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Request body fields:

        - trackstar_warehouse_id (required, string): The Trackstar warehouse identifier

        - warehouse_id (optional, integer): The SKU.io warehouse ID to map to'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                trackstar_warehouse_id:
                  type: string
                warehouse_id:
                  type: integer
              example:
                trackstar_warehouse_id: wh_abc123
                warehouse_id: 3
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '10'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      trackstar_warehouse_id:
                        type: string
                      warehouse_id:
                        type: integer
                      warehouse_name:
                        type: string
                      is_active:
                        type: boolean
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 1
                    integration_instance_id: 10
                    trackstar_warehouse_id: wh_abc123
                    warehouse_id: 3
                    warehouse_name: NJ Warehouse
                    is_active: true
                    created_at: '2024-06-01T12:00:00.000Z'
                    updated_at: '2024-06-01T12:00:00.000Z'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: object
                    properties:
                      trackstar_warehouse_id:
                        type: string
                example:
                  errors:
                    trackstar_warehouse_id: Trackstar warehouse not found
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-trackstar-integration-instances-integration-instance-warehouse-mappings
  /api/trackstar/integration-instances/{integration_instance}/warehouse-mappings/sync-warehouses:
    post:
      tags:
      - Trackstar
      summary: Sync Warehouses from Trackstar
      description: 'Pull warehouses from Trackstar API, sync them to the local database,
        and auto-create warehouse mappings for any new warehouses. Requires Bearer
        token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '10'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      warehouses:
                        type: object
                        properties:
                          synced:
                            type: integer
                          created:
                            type: integer
                          updated:
                            type: integer
                      mappings_created:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    warehouses:
                      synced: 3
                      created: 1
                      updated: 2
                    mappings_created: 1
                  message: Synced 3 warehouses (1 created, 2 updated). Created 1 new
                    mappings.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-trackstar-integration-instances-integration-instance-warehouse-mappings-sync-warehouses
  /api/trackstar/integration-instances/{integration_instance}/warehouse-mappings/{warehouse_mapping}:
    put:
      tags:
      - Trackstar
      summary: Update Warehouse Mapping
      description: 'Update a warehouse mapping — change the SKU.io warehouse it maps
        to or toggle active status. Requires Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Request body fields (all optional):

        - warehouse_id (integer|null): SKU.io warehouse ID (null to unmap)

        - is_active (boolean): Activate or deactivate the mapping'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                warehouse_id:
                  type: integer
                is_active:
                  type: boolean
              example:
                warehouse_id: 4
                is_active: true
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '10'
      - name: warehouse_mapping
        in: path
        schema:
          type: integer
        required: true
        description: Warehouse mapping ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      trackstar_warehouse_id:
                        type: string
                      warehouse_id:
                        type: integer
                      warehouse_name:
                        type: string
                      is_active:
                        type: boolean
                      updated_at:
                        type: string
                example:
                  data:
                    id: 1
                    integration_instance_id: 10
                    trackstar_warehouse_id: wh_abc123
                    warehouse_id: 4
                    warehouse_name: CA Warehouse
                    is_active: true
                    updated_at: '2024-06-20T10:00:00.000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-trackstar-integration-instances-integration-instance-warehouse-mappings-warehouse-mapping
    delete:
      tags:
      - Trackstar
      summary: Delete Warehouse Mapping
      description: 'Delete a warehouse mapping. Requires Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '10'
      - name: warehouse_mapping
        in: path
        schema:
          type: integer
        required: true
        description: Warehouse mapping ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: string
                    nullable: true
                  message:
                    type: string
                example:
                  data: null
                  message: Warehouse mapping deleted successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-trackstar-integration-instances-integration-instance-warehouse-mappings-warehouse-mapping
  /api/trackstar/integration-instances/{integration_instance}/orders:
    get:
      tags:
      - Trackstar
      summary: List Orders
      description: 'List Trackstar orders for an integration instance with pagination,
        filtering, and sorting.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Filters (Spatie QueryBuilder):

        - filter[search]: Partial match on order_number or trackstar_order_id

        - filter[status]: Exact enum match. Values: processing, picked, packed, fulfilled,
        cancelled, other

        - filter[has_fulfillment]: true/1 or false/0

        - filter[date_from]: Orders on or after this date (reads from json_object.order_date
        or created_date)

        - filter[date_to]: Orders on or before this date


        Allowed sorts: id, order_number, status, created_at, updated_at

        Default sort: -created_at'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        description: 'Page number (default: 1)'
        example: '1'
      - name: per_page
        in: query
        schema:
          type: integer
        description: 'Items per page (default: 15)'
        example: '15'
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '10'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        trackstar_id:
                          type: string
                        order_number:
                          type: string
                        status:
                          type: string
                        warehouse:
                          type: string
                        tracking_number:
                          type: string
                        carrier:
                          type: string
                        order_date:
                          type: string
                        shipped_at:
                          type: string
                        channel_id:
                          type: string
                        channel_name:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - id: 301
                    integration_instance_id: 10
                    trackstar_id: ts-ord-001
                    order_number: ORD-12345
                    status: fulfilled
                    warehouse: wh_abc123
                    tracking_number: 1Z999AA10123456784
                    carrier: UPS
                    order_date: '2024-06-01T00:00:00.000Z'
                    shipped_at: '2024-06-03T14:00:00.000Z'
                    channel_id: SO-2024-001
                    channel_name: Shopify Store
                    created_at: '2024-06-01T12:00:00.000Z'
                    updated_at: '2024-06-03T14:00:00.000Z'
                  current_page: 1
                  last_page: 84
                  per_page: 15
                  total: 1250
                  from: 1
                  to: 15
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-trackstar-integration-instances-integration-instance-orders
  /api/trackstar/integration-instances/{integration_instance}/orders/sync:
    post:
      tags:
      - Trackstar
      summary: Sync Orders (Queued)
      description: 'Queue a background job to sync orders from Trackstar API. Returns
        a tracked_job_log_id to monitor progress via the sync-progress endpoint. Requires
        Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Query parameters:

        - start_date (optional): Date range start for sync

        - end_date (optional): Date range end for sync

        - status (optional): Filter by order status; pass ''all'' to sync all statuses'
      requestBody:
        content: {}
      parameters:
      - name: start_date
        in: query
        schema:
          type: string
        description: Optional start date for order sync range
        example: '2024-01-01'
      - name: end_date
        in: query
        schema:
          type: string
        description: Optional end date for order sync range
        example: '2024-06-30'
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '10'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 892
                  message: Order sync job has been queued
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-trackstar-integration-instances-integration-instance-orders-sync
  /api/trackstar/integration-instances/{integration_instance}/orders/sync-progress/{trackedJobLogId}:
    get:
      tags:
      - Trackstar
      summary: Get Sync Progress
      description: 'Poll the progress of a queued order sync job. Requires Bearer
        token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '10'
      - name: trackedJobLogId
        in: path
        schema:
          type: integer
        required: true
        description: Tracked job log ID from sync response
        example: '892'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      job_name:
                        type: string
                      status:
                        type: string
                      progress:
                        type: integer
                      total:
                        type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 892
                    job_name: 'Sync Trackstar Orders: My Trackstar WMS'
                    status: processing
                    progress: 45
                    total: 100
                    created_at: '2024-06-20T09:00:00.000Z'
                    updated_at: '2024-06-20T09:01:30.000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-trackstar-integration-instances-integration-instance-orders-sync-progress-trackedjoblogid
  /api/trackstar/integration-instances/{integration_instance}/orders/by-trackstar-id/{trackstar_id}:
    get:
      tags:
      - Trackstar
      summary: Show Order by Trackstar ID
      description: 'Retrieve an order by its Trackstar ID string. Includes json_object
        in the response. Returns 404 if not found. Requires Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '10'
      - name: trackstar_id
        in: path
        schema:
          type: string
        required: true
        description: The Trackstar order ID string
        example: ts-ord-001
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      trackstar_id:
                        type: string
                      order_number:
                        type: string
                      status:
                        type: string
                      warehouse:
                        type: string
                      tracking_number:
                        type: string
                      carrier:
                        type: string
                      order_date:
                        type: string
                      shipped_at:
                        type: string
                      channel_id:
                        type: string
                      channel_name:
                        type: string
                      json_object:
                        type: object
                        properties:
                          id:
                            type: string
                          order_number:
                            type: string
                          shipments:
                            type: array
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 301
                    integration_instance_id: 10
                    trackstar_id: ts-ord-001
                    order_number: ORD-12345
                    status: fulfilled
                    warehouse: wh_abc123
                    tracking_number: 1Z999AA10123456784
                    carrier: UPS
                    order_date: '2024-06-01T00:00:00.000Z'
                    shipped_at: '2024-06-03T14:00:00.000Z'
                    channel_id: SO-2024-001
                    channel_name: Shopify Store
                    json_object:
                      id: ts-ord-001
                      order_number: ORD-12345
                      shipments: []
                    created_at: '2024-06-01T12:00:00.000Z'
                    updated_at: '2024-06-03T14:00:00.000Z'
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: object
                    properties:
                      order:
                        type: string
                  message:
                    type: string
                example:
                  errors:
                    order: Order not found
                  message: OrderNotFound
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-trackstar-integration-instances-integration-instance-orders-by-trackstar-id-trackstar-id
  /api/trackstar/integration-instances/{integration_instance}/orders/{order}:
    get:
      tags:
      - Trackstar
      summary: Show Order by Database ID
      description: 'Retrieve an order by its database ID. Includes json_object. Verifies
        the order belongs to the integration instance. Requires Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '10'
      - name: order
        in: path
        schema:
          type: integer
        required: true
        description: Order database ID
        example: '301'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      trackstar_id:
                        type: string
                      order_number:
                        type: string
                      status:
                        type: string
                      json_object:
                        type: object
                        properties:
                          id:
                            type: string
                          shipments:
                            type: array
                            items:
                              type: object
                              properties:
                                shipped_date:
                                  type: string
                                packages:
                                  type: array
                                  items:
                                    type: object
                                    properties:
                                      tracking_number:
                                        type: string
                                      carrier_name:
                                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 301
                    integration_instance_id: 10
                    trackstar_id: ts-ord-001
                    order_number: ORD-12345
                    status: fulfilled
                    json_object:
                      id: ts-ord-001
                      shipments:
                      - shipped_date: '2024-06-03'
                        packages:
                        - tracking_number: 1Z999AA10123456784
                          carrier_name: UPS
                    created_at: '2024-06-01T12:00:00.000Z'
                    updated_at: '2024-06-03T14:00:00.000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-trackstar-integration-instances-integration-instance-orders-order
  /api/trackstar/integration-instances/{integration_instance}/orders/{order}/detail:
    get:
      tags:
      - Trackstar
      summary: Order Detail (Raw JSON)
      description: 'Get the full raw json_object for an order as stored from the Trackstar
        API. Requires Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '10'
      - name: order
        in: path
        schema:
          type: integer
        required: true
        description: Order database ID
        example: '301'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      json_object:
                        type: object
                        properties:
                          id:
                            type: string
                          order_number:
                            type: string
                          status:
                            type: string
                          shipments:
                            type: array
                            items:
                              type: object
                              properties:
                                shipped_date:
                                  type: string
                                packages:
                                  type: array
                                  items:
                                    type: object
                                    properties:
                                      tracking_number:
                                        type: string
                                      carrier_name:
                                        type: string
                example:
                  data:
                    json_object:
                      id: ts-ord-001
                      order_number: ORD-12345
                      status: fulfilled
                      shipments:
                      - shipped_date: '2024-06-03'
                        packages:
                        - tracking_number: 1Z999AA10123456784
                          carrier_name: UPS
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-trackstar-integration-instances-integration-instance-orders-order-detail
  /api/trackstar/integration-instances/{integration_instance}/orders/{order}/sync-detail:
    post:
      tags:
      - Trackstar
      summary: Sync Order Detail
      description: 'Pull fresh order detail from the Trackstar API and update the
        local record. Returns the updated order data. Requires Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '10'
      - name: order
        in: path
        schema:
          type: integer
        required: true
        description: Order database ID
        example: '301'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      trackstar_id:
                        type: string
                      order_number:
                        type: string
                      status:
                        type: string
                      warehouse_id:
                        type: string
                        nullable: true
                      order_date:
                        type: string
                      sku_fulfillment_id:
                        type: integer
                      tracking_number:
                        type: string
                      carrier:
                        type: string
                      shipped_at:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 301
                    integration_instance_id: 10
                    trackstar_id: ts-ord-001
                    order_number: ORD-12345
                    status: fulfilled
                    warehouse_id: null
                    order_date: '2024-06-01'
                    sku_fulfillment_id: 55
                    tracking_number: 1Z999AA10123456784
                    carrier: UPS
                    shipped_at: '2024-06-03T14:00:00.000Z'
                    created_at: '2024-06-01T12:00:00.000Z'
                    updated_at: '2024-06-20T10:00:00.000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-trackstar-integration-instances-integration-instance-orders-order-sync-detail
  /api/trackstar/integration-instances/{integration_instance}/orders/{order}/raw:
    get:
      tags:
      - Trackstar
      summary: Get Raw Order from Trackstar
      description: Fetch the order LIVE from the Trackstar API as the raw, untransformed
        payload (nothing is persisted). The order payload is returned under `data.product`.
        Requires Bearer token.
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '10'
      - name: order
        in: path
        schema:
          type: integer
        required: true
        description: Order database ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      product:
                        type: object
                        properties:
                          id:
                            type: string
                          order_number:
                            type: string
                          reference_id:
                            type: string
                          status:
                            type: string
                          warehouse_id:
                            type: string
                          line_items:
                            type: array
                            items:
                              type: object
                              properties:
                                sku:
                                  type: string
                                product_id:
                                  type: string
                                quantity:
                                  type: integer
                          created_date:
                            type: string
                          updated_date:
                            type: string
                  fetched_at:
                    type: string
                example:
                  data:
                    product:
                      id: ord_2b7c1e
                      order_number: 915404R
                      reference_id: '#915404R'
                      status: fulfilled
                      warehouse_id: '3'
                      line_items:
                      - sku: TEST-UK-001
                        product_id: prod_18
                        quantity: 2
                      created_date: '2026-05-20T07:38:00Z'
                      updated_date: '2026-06-02T02:10:00Z'
                  fetched_at: '2026-07-08T12:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-trackstar-integration-instances-integration-instance-orders-order-raw
  /api/trackstar/integration-instances/{integration_instance}/orders/sync-info:
    get:
      tags:
      - Trackstar
      summary: Get Orders Sync Info
      description: 'Baseline info for the Refresh Orders modal: the latest synced
        order (identifier + date) and the total synced count, so the UI can offer
        a "fetch since latest sync" option. Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '10'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      latest_order_number:
                        type: string
                      latest_order_date:
                        type: string
                      total_orders:
                        type: integer
                example:
                  data:
                    latest_order_number: 915404R
                    latest_order_date: '2026-06-02T02:10:00.000000Z'
                    total_orders: 42
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-trackstar-integration-instances-integration-instance-orders-sync-info
  /api/trackstar/integration-instances/{integration_instance}/orders/search:
    post:
      tags:
      - Trackstar
      summary: Search Orders
      description: Search Trackstar live for orders matching a query (order number
        / reference, or a Trackstar order id). Each result is flagged with whether
        it already exists locally so the caller can decide to download vs update.
        Requires Bearer token.
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                query:
                  type: string
              example:
                query: 915404R
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '10'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: string
                        order_number:
                          type: string
                        reference_id:
                          type: string
                        status:
                          type: string
                        created_date:
                          type: string
                        total_price:
                          type: number
                        currency:
                          type: string
                        exists_in_database:
                          type: boolean
                example:
                  data:
                  - id: ord_2b7c1e
                    order_number: 915404R
                    reference_id: '#915404R'
                    status: fulfilled
                    created_date: '2026-05-20T07:38:00Z'
                    total_price: 129.99
                    currency: USD
                    exists_in_database: true
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-trackstar-integration-instances-integration-instance-orders-search
  /api/trackstar/integration-instances/{integration_instance}/orders/refresh-order:
    post:
      tags:
      - Trackstar
      summary: Download Order from Trackstar
      description: Download (or update) a single order live from Trackstar by its
        Trackstar order id and persist it. Backs the search tab's per-result Download/Update
        action. Requires Bearer token.
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                uniqueId:
                  type: string
              example:
                uniqueId: ord_2b7c1e
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '10'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    id: 1
                  message: Order refreshed from Trackstar
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-trackstar-integration-instances-integration-instance-orders-refresh-order
  /api/trackstar/integration-instances/{integration_instance}/orders/{order}/activity-log:
    get:
      tags:
      - Trackstar
      summary: Order Activity Log
      description: Paginated activity log for a single order (order detail page Activity
        Log tab). Supports `filter[search]`, `per_page`. Requires Bearer token.
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '10'
      - name: order
        in: path
        schema:
          type: integer
        required: true
        description: Order database ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        description:
                          type: string
                        event:
                          type: string
                        subject_type:
                          type: string
                        subject_id:
                          type: integer
                        properties:
                          type: object
                          properties:
                            attributes:
                              type: object
                              properties:
                                status:
                                  type: string
                        causer_name:
                          type: string
                        created_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - id: 1
                    description: updated
                    event: updated
                    subject_type: TrackstarOrder
                    subject_id: 1
                    properties:
                      attributes:
                        status: fulfilled
                    causer_name: System
                    created_at: '2026-07-08T12:00:00.000000Z'
                  current_page: 1
                  last_page: 1
                  per_page: 15
                  total: 1
                  from: 1
                  to: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-trackstar-integration-instances-integration-instance-orders-order-activity-log
  /api/trackstar/integration-instances/{integration_instance}/order-shipments:
    get:
      tags:
      - Trackstar
      summary: List Order Shipments
      description: 'List outbound fulfillment shipments for a Trackstar integration
        instance, with pagination, filtering, and sorting.


        Authentication: Requires Bearer token.


        Each shipment is scoped to the integration instance through its parent order.


        Search:

        - filter[search]: Partial match across tracking_number, trackstar_shipment_id,
        carrier, and shipping_method


        Operator filters use the form filter[column.operator]=value (a bare filter[column]=value
        is treated as an exact ''is'' match):

        - Text columns (tracking_number, trackstar_shipment_id, carrier, shipping_method):
        is, is_not, contains, does_not_contain, starts_with, ends_with, is_one_of,
        is_not_one_of, is_empty, is_not_empty

        - Numeric columns (id, shipping_cost): is, is_not, greater_than, less_than,
        greater_than_or_equal, less_than_or_equal, between, is_one_of, is_empty, is_not_empty

        - Date-time columns (shipped_at, created_at, updated_at): is, before, after,
        on_or_before, on_or_after, between, today, yesterday, past_week, past_month,
        past_year, past_days, is_empty, is_not_empty


        Allowed sorts: id, trackstar_shipment_id, tracking_number, carrier, shipping_method,
        shipping_cost, shipped_at, created_at, updated_at

        Default sort: -shipped_at

        Pagination default: 10 per page'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        description: 'Page number (default: 1)'
        example: '1'
      - name: per_page
        in: query
        schema:
          type: integer
        description: 'Items per page (default: 10)'
        example: '10'
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '10'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        trackstar_order_id:
                          type: integer
                        trackstar_shipment_id:
                          type: string
                        tracking_number:
                          type: string
                        carrier:
                          type: string
                        shipping_method:
                          type: string
                        shipping_cost:
                          type: number
                        shipped_at:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                        order:
                          type: object
                          properties:
                            id:
                              type: integer
                            order_number:
                              type: string
                            trackstar_order_id:
                              type: string
                            link_reference:
                              type: string
                            link_type_label:
                              type: string
                            link_id:
                              type: integer
                            link_route:
                              type: string
                        sku_sales_order_fulfillment_id:
                          type: integer
                        sku_fulfillment:
                          type: object
                          properties:
                            id:
                              type: integer
                            link_reference:
                              type: integer
                            link_type_label:
                              type: string
                            link_id:
                              type: integer
                            link_route:
                              type: string
                            status:
                              type: string
                            tracking_number:
                              type: string
                            tracking_url:
                              type: string
                            sales_order_id:
                              type: integer
                            sales_order_number:
                              type: string
                        sales_order_id:
                          type: integer
                        sales_order_number:
                          type: string
                        warehouse:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - id: 5001
                    trackstar_order_id: 301
                    trackstar_shipment_id: ts-ship-001
                    tracking_number: 1Z999AA10123456784
                    carrier: UPS
                    shipping_method: Ground
                    shipping_cost: 12.45
                    shipped_at: '2024-06-03T14:00:00+00:00'
                    created_at: '2024-06-03T14:05:00+00:00'
                    updated_at: '2024-06-03T14:05:00+00:00'
                    order:
                      id: 301
                      order_number: ORD-12345
                      trackstar_order_id: ts-ord-001
                      link_reference: ORD-12345
                      link_type_label: Trackstar Order
                      link_id: 301
                      link_route: /integrations/trackstar/10/orders/301
                    sku_sales_order_fulfillment_id: 8801
                    sku_fulfillment:
                      id: 8801
                      link_reference: 8801
                      link_type_label: Sales Order Fulfillment
                      link_id: 8801
                      link_route: /orders/sales-orders/fulfillments/8801
                      status: shipped
                      tracking_number: 1Z999AA10123456784
                      tracking_url: https://www.ups.com/track?tracknum=1Z999AA10123456784
                      sales_order_id: 4501
                      sales_order_number: SO-2024-001
                    sales_order_id: 4501
                    sales_order_number: SO-2024-001
                    warehouse:
                      id: 12
                      name: Main Warehouse
                  current_page: 1
                  last_page: 12
                  per_page: 10
                  total: 118
                  from: 1
                  to: 10
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-trackstar-integration-instances-integration-instance-order-shipments
  /api/trackstar/integration-instances/{integration_instance}/order-shipments/{order_shipment}:
    get:
      tags:
      - Trackstar
      summary: Get Order Shipment
      description: 'Retrieve a single order shipment by its database ID, scoped to
        the integration instance. The response always includes the raw json_object
        payload received from Trackstar. Returns 404 if the shipment does not exist
        or does not belong to the integration instance.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '10'
      - name: order_shipment
        in: path
        schema:
          type: integer
        required: true
        description: Order shipment database ID
        example: '5001'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      trackstar_order_id:
                        type: integer
                      trackstar_shipment_id:
                        type: string
                      tracking_number:
                        type: string
                      carrier:
                        type: string
                      shipping_method:
                        type: string
                      shipping_cost:
                        type: number
                      shipped_at:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      order:
                        type: object
                        properties:
                          id:
                            type: integer
                          order_number:
                            type: string
                          trackstar_order_id:
                            type: string
                          link_reference:
                            type: string
                          link_type_label:
                            type: string
                          link_id:
                            type: integer
                          link_route:
                            type: string
                      sku_sales_order_fulfillment_id:
                        type: integer
                      sku_fulfillment:
                        type: object
                        properties:
                          id:
                            type: integer
                          link_reference:
                            type: integer
                          link_type_label:
                            type: string
                          link_id:
                            type: integer
                          link_route:
                            type: string
                          status:
                            type: string
                          tracking_number:
                            type: string
                          tracking_url:
                            type: string
                          sales_order_id:
                            type: integer
                          sales_order_number:
                            type: string
                      sales_order_id:
                        type: integer
                      sales_order_number:
                        type: string
                      warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      json_object:
                        type: object
                        properties:
                          id:
                            type: string
                          order_id:
                            type: string
                          tracking_number:
                            type: string
                          carrier:
                            type: string
                          shipping_method:
                            type: string
                          shipping_cost:
                            type: number
                          shipped_date:
                            type: string
                example:
                  data:
                    id: 5001
                    trackstar_order_id: 301
                    trackstar_shipment_id: ts-ship-001
                    tracking_number: 1Z999AA10123456784
                    carrier: UPS
                    shipping_method: Ground
                    shipping_cost: 12.45
                    shipped_at: '2024-06-03T14:00:00+00:00'
                    created_at: '2024-06-03T14:05:00+00:00'
                    updated_at: '2024-06-03T14:05:00+00:00'
                    order:
                      id: 301
                      order_number: ORD-12345
                      trackstar_order_id: ts-ord-001
                      link_reference: ORD-12345
                      link_type_label: Trackstar Order
                      link_id: 301
                      link_route: /integrations/trackstar/10/orders/301
                    sku_sales_order_fulfillment_id: 8801
                    sku_fulfillment:
                      id: 8801
                      link_reference: 8801
                      link_type_label: Sales Order Fulfillment
                      link_id: 8801
                      link_route: /orders/sales-orders/fulfillments/8801
                      status: shipped
                      tracking_number: 1Z999AA10123456784
                      tracking_url: https://www.ups.com/track?tracknum=1Z999AA10123456784
                      sales_order_id: 4501
                      sales_order_number: SO-2024-001
                    sales_order_id: 4501
                    sales_order_number: SO-2024-001
                    warehouse:
                      id: 12
                      name: Main Warehouse
                    json_object:
                      id: ts-ship-001
                      order_id: ts-ord-001
                      tracking_number: 1Z999AA10123456784
                      carrier: UPS
                      shipping_method: Ground
                      shipping_cost: 12.45
                      shipped_date: '2024-06-03T14:00:00Z'
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      order_shipment:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: array
                example:
                  status: failure
                  message: Shipment not found
                  errors:
                    order_shipment:
                    - message: Shipment not found
                      code: ShipmentNotFound
                      data: []
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-trackstar-integration-instances-integration-instance-order-shipments-order-shipment
  /api/trackstar/integration-instances/{integration_instance}/inventory:
    get:
      tags:
      - Trackstar
      summary: List Inventory
      description: 'List all inventory items for a Trackstar integration instance.
        Optionally filter by warehouse. Requires Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Query parameters:

        - warehouse_id (optional, string): Trackstar warehouse ID to filter by'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '10'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        sku:
                          type: string
                        warehouse_id:
                          type: string
                        on_hand:
                          type: integer
                        available:
                          type: integer
                        committed:
                          type: integer
                        incoming:
                          type: integer
                        json_object:
                          type: object
                          properties: {}
                        created_at:
                          type: string
                        updated_at:
                          type: string
                example:
                  data:
                  - id: 201
                    integration_instance_id: 10
                    sku: PROD-001
                    warehouse_id: wh_abc123
                    on_hand: 150
                    available: 120
                    committed: 30
                    incoming: 50
                    json_object: {}
                    created_at: '2024-06-01T00:00:00.000Z'
                    updated_at: '2024-06-20T06:00:00.000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-trackstar-integration-instances-integration-instance-inventory
  /api/trackstar/integration-instances/{integration_instance}/inventory/sync:
    post:
      tags:
      - Trackstar
      summary: Sync Inventory
      description: 'Pull current inventory levels from the Trackstar API and update
        the local database. Requires Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '10'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  synced_count:
                    type: integer
                example:
                  message: Inventory synced successfully
                  synced_count: 320
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-trackstar-integration-instances-integration-instance-inventory-sync
  /api/trackstar/integration-instances/{integration_instance}/inventory/low-stock:
    get:
      tags:
      - Trackstar
      summary: Low Stock Items
      description: 'Get inventory items with available quantity at or below the threshold.
        Requires Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Query parameters:

        - threshold (optional, integer): Available quantity ceiling (default: 10)'
      parameters:
      - name: threshold
        in: query
        schema:
          type: integer
        description: 'Available quantity threshold (default: 10). Items with available
          <= threshold are returned.'
        example: '10'
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '10'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        sku:
                          type: string
                        warehouse_id:
                          type: string
                        on_hand:
                          type: integer
                        available:
                          type: integer
                        committed:
                          type: integer
                        incoming:
                          type: integer
                        created_at:
                          type: string
                        updated_at:
                          type: string
                example:
                  data:
                  - id: 202
                    integration_instance_id: 10
                    sku: PROD-LOW-001
                    warehouse_id: wh_abc123
                    on_hand: 8
                    available: 5
                    committed: 3
                    incoming: 0
                    created_at: '2024-06-01T00:00:00.000Z'
                    updated_at: '2024-06-20T06:00:00.000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-trackstar-integration-instances-integration-instance-inventory-low-stock
  /api/trackstar/integration-instances/{integration_instance}/inventory/out-of-stock:
    get:
      tags:
      - Trackstar
      summary: Out of Stock Items
      description: 'Get inventory items with zero available quantity. Requires Bearer
        token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '10'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        sku:
                          type: string
                        warehouse_id:
                          type: string
                        on_hand:
                          type: integer
                        available:
                          type: integer
                        committed:
                          type: integer
                        incoming:
                          type: integer
                example:
                  data:
                  - id: 203
                    sku: PROD-OOS-001
                    warehouse_id: wh_abc123
                    on_hand: 0
                    available: 0
                    committed: 0
                    incoming: 25
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-trackstar-integration-instances-integration-instance-inventory-out-of-stock
  /api/trackstar/integration-instances/{integration_instance}/inventory/totals-by-sku:
    get:
      tags:
      - Trackstar
      summary: Totals by SKU
      description: 'Get inventory quantities aggregated (summed) by SKU across all
        warehouses. Requires Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '10'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        sku:
                          type: string
                        on_hand:
                          type: integer
                        available:
                          type: integer
                        committed:
                          type: integer
                        incoming:
                          type: integer
                example:
                  data:
                  - sku: PROD-001
                    on_hand: 300
                    available: 240
                    committed: 60
                    incoming: 100
                  - sku: PROD-002
                    on_hand: 80
                    available: 80
                    committed: 0
                    incoming: 0
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-trackstar-integration-instances-integration-instance-inventory-totals-by-sku
  /api/trackstar/integration-instances/{integration_instance}/inventory/discrepancies:
    get:
      tags:
      - Trackstar
      summary: Inventory Discrepancies
      description: 'Compare Trackstar inventory levels to SKU.io inventory and return
        items where quantities differ. Also returns warehouse list and last sync timestamp.
        Requires Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '10'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        sku:
                          type: string
                        trackstar_qty:
                          type: integer
                        sku_qty:
                          type: integer
                        discrepancy:
                          type: integer
                  warehouses:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: string
                        name:
                          type: string
                  last_synced_at:
                    type: string
                example:
                  data:
                  - sku: PROD-001
                    trackstar_qty: 150
                    sku_qty: 140
                    discrepancy: 10
                  warehouses:
                  - id: wh_abc123
                    name: East Coast Warehouse
                  last_synced_at: '2024-06-20T07:00:00+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-trackstar-integration-instances-integration-instance-inventory-discrepancies
  /api/trackstar/integration-instances/{integration_instance}/inventory/without-sku-products:
    get:
      tags:
      - Trackstar
      summary: Items Without SKU Products
      description: 'Get Trackstar inventory items that have no matching SKU.io product
        (by SKU). Useful for finding new products to create. Requires Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '10'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        sku:
                          type: string
                        warehouse_id:
                          type: string
                        on_hand:
                          type: integer
                        available:
                          type: integer
                example:
                  data:
                  - sku: NEW-SKU-001
                    warehouse_id: wh_abc123
                    on_hand: 25
                    available: 25
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-trackstar-integration-instances-integration-instance-inventory-without-sku-products
  /api/trackstar/integration-instances/{integration_instance}/inventory/without-trackstar-inventory:
    get:
      tags:
      - Trackstar
      summary: SKU Products Without Trackstar Inventory
      description: 'Get SKU.io products that have no matching Trackstar inventory
        record. Requires Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '10'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        sku:
                          type: string
                        name:
                          type: string
                example:
                  data:
                  - id: 55
                    sku: PROD-MISSING
                    name: Missing Product
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-trackstar-integration-instances-integration-instance-inventory-without-trackstar-inventory
  /api/trackstar/integration-instances/{integration_instance}/inventory/last-synced-at:
    get:
      tags:
      - Trackstar
      summary: Get Last Synced At
      description: 'Get the timestamp of the most recent inventory sync for this integration
        instance. Requires Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '10'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      last_synced_at:
                        type: string
                example:
                  data:
                    last_synced_at: '2024-06-20T07:00:00+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-trackstar-integration-instances-integration-instance-inventory-last-synced-at
  /api/trackstar/integration-instances/{integration_instance}/inventory/create-stock-take:
    post:
      tags:
      - Trackstar
      summary: Create Stock Take from Discrepancies
      description: 'Create a SKU.io stock take pre-populated with quantities from
        Trackstar inventory discrepancies. Requires Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Request body fields:

        - product_ids (optional, array of integers): Limit stock take to specific
        product IDs

        - warehouse_id (optional, integer): SKU.io warehouse ID for the stock take

        - notes (optional, string, max 500): Notes for the stock take

        - date (optional, date Y-m-d): Stock take date

        - status (optional, string): draft, open, or closed'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                product_ids:
                  type: array
                  items:
                    type: integer
                warehouse_id:
                  type: integer
                notes:
                  type: string
                date:
                  type: string
                status:
                  type: string
              example:
                product_ids:
                - 55
                - 56
                - 57
                warehouse_id: 3
                notes: Stock take from Trackstar discrepancy report
                date: '2024-06-20'
                status: open
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '10'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      warehouse_id:
                        type: integer
                      status:
                        type: string
                      date:
                        type: string
                      notes:
                        type: string
                      lines_count:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    id: 42
                    warehouse_id: 3
                    status: open
                    date: '2024-06-20'
                    notes: Stock take from Trackstar discrepancy report
                    lines_count: 3
                  message: Stock take created successfully from Trackstar discrepancies
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      status:
                        type: array
                        items:
                          type: string
                      date:
                        type: array
                        items:
                          type: string
                example:
                  message: The given data was invalid.
                  errors:
                    status:
                    - The selected status is invalid.
                    date:
                    - The date does not match the format Y-m-d.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-trackstar-integration-instances-integration-instance-inventory-create-stock-take
  /api/trackstar/integration-instances/{integration_instance}/inventory-ledger:
    get:
      tags:
      - Trackstar
      summary: List Inventory Ledger
      description: 'List paginated inventory ledger entries (movement history) for
        a Trackstar integration instance. Requires Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        description: Page number
        example: '1'
      - name: per_page
        in: query
        schema:
          type: integer
        description: Items per page
        example: '15'
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '10'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        trackstar_ledger_id:
                          type: string
                        inventory_item_id:
                          type: string
                        sku:
                          type: string
                        quantity:
                          type: integer
                        event_type:
                          type: string
                        raw_event_type:
                          type: string
                        reason:
                          type: string
                        object_id:
                          type: string
                        object_type:
                          type: string
                        warehouse_id:
                          type: string
                        location_id:
                          type: string
                        additional_fields:
                          type: string
                          nullable: true
                        entry_date:
                          type: string
                        trackstar_created_at:
                          type: string
                        trackstar_updated_at:
                          type: string
                        event_type_display:
                          type: string
                        formatted_quantity:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 1001
                    integration_instance_id: 10
                    trackstar_ledger_id: led_001
                    inventory_item_id: item_abc
                    sku: PROD-001
                    quantity: -5
                    event_type: outbound
                    raw_event_type: SHIP
                    reason: Order fulfillment
                    object_id: ts-ord-001
                    object_type: order
                    warehouse_id: wh_abc123
                    location_id: loc_001
                    additional_fields: null
                    entry_date: '2024-06-03T14:00:00.000Z'
                    trackstar_created_at: '2024-06-03T14:05:00.000Z'
                    trackstar_updated_at: '2024-06-03T14:05:00.000Z'
                    event_type_display: Outbound
                    formatted_quantity: '-5'
                    created_at: '2024-06-03T14:10:00.000Z'
                    updated_at: '2024-06-03T14:10:00.000Z'
                  current_page: 1
                  last_page: 200
                  per_page: 15
                  total: 3000
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-trackstar-integration-instances-integration-instance-inventory-ledger
  /api/trackstar/integration-instances/{integration_instance}/inventory-ledger/sync:
    post:
      tags:
      - Trackstar
      summary: Sync Inventory Ledger
      description: 'Pull inventory ledger entries from the Trackstar API and sync
        to the local database. Requires Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '10'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  synced:
                    type: integer
                  created:
                    type: integer
                  updated:
                    type: integer
                example:
                  message: Inventory ledger synced successfully
                  synced: 150
                  created: 80
                  updated: 70
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-trackstar-integration-instances-integration-instance-inventory-ledger-sync
  /api/trackstar/integration-instances/{integration_instance}/inventory-ledger/filters:
    get:
      tags:
      - Trackstar
      summary: Get Ledger Filters
      description: 'Get available filter options for the inventory ledger (distinct
        event types, object types, and warehouse IDs). Useful for populating filter
        dropdowns in the UI. Requires Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '10'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  event_types:
                    type: array
                    items:
                      type: string
                  object_types:
                    type: array
                    items:
                      type: string
                  warehouse_ids:
                    type: array
                    items:
                      type: string
                example:
                  event_types:
                  - inbound
                  - outbound
                  - adjustment
                  - transfer
                  object_types:
                  - order
                  - receipt
                  - adjustment
                  warehouse_ids:
                  - wh_abc123
                  - wh_def456
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-trackstar-integration-instances-integration-instance-inventory-ledger-filters
  /api/trackstar/integration-instances/{integration_instance}/inventory-ledger/summary:
    get:
      tags:
      - Trackstar
      summary: Get Ledger Summary
      description: 'Get summary statistics for the inventory ledger (totals by event
        type, date ranges, etc.). Requires Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '10'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  total_entries:
                    type: integer
                  total_inbound:
                    type: integer
                  total_outbound:
                    type: integer
                  earliest_entry:
                    type: string
                  latest_entry:
                    type: string
                example:
                  total_entries: 3000
                  total_inbound: 1200
                  total_outbound: 1800
                  earliest_entry: '2024-01-01T00:00:00.000Z'
                  latest_entry: '2024-06-20T14:00:00.000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-trackstar-integration-instances-integration-instance-inventory-ledger-summary
  /api/trackstar/integration-instances/{integration_instance}/products:
    get:
      tags:
      - Trackstar
      summary: List Products
      description: 'List all Trackstar products for an integration instance. Supports
        search and active-only filtering. Requires Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Query parameters:

        - search (optional, string): Search by SKU or product name

        - active_only (optional, boolean): Return only active products'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '10'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        trackstar_product_id:
                          type: string
                        sku:
                          type: string
                        name:
                          type: string
                        gtin:
                          type: string
                        unit_price:
                          type: number
                        is_kit:
                          type: boolean
                        active:
                          type: boolean
                        supplier:
                          type: string
                        country_of_origin:
                          type: string
                        harmonized_code:
                          type: string
                        warehouse_customer_id:
                          type: string
                        inventory_items:
                          type: array
                        supplier_products:
                          type: array
                        trackstar_tags:
                          type: array
                          items:
                            type: string
                        additional_fields:
                          type: string
                          nullable: true
                        external_system_url:
                          type: string
                          nullable: true
                        json_object:
                          type: object
                          properties: {}
                        trackstar_created_at:
                          type: string
                        trackstar_updated_at:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                example:
                  data:
                  - id: 401
                    integration_instance_id: 10
                    trackstar_product_id: prod_abc123
                    sku: PROD-001
                    name: Blue Widget
                    gtin: 012345678901
                    unit_price: 24.99
                    is_kit: false
                    active: true
                    supplier: Acme Corp
                    country_of_origin: US
                    harmonized_code: '8473.30'
                    warehouse_customer_id: cust_001
                    inventory_items: []
                    supplier_products: []
                    trackstar_tags:
                    - widget
                    - blue
                    additional_fields: null
                    external_system_url: null
                    json_object: {}
                    trackstar_created_at: '2024-01-01T00:00:00.000Z'
                    trackstar_updated_at: '2024-06-01T00:00:00.000Z'
                    created_at: '2024-01-01T00:00:00.000Z'
                    updated_at: '2024-06-01T00:00:00.000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-trackstar-integration-instances-integration-instance-products
  /api/trackstar/integration-instances/{integration_instance}/products/sync:
    post:
      tags:
      - Trackstar
      summary: Sync Products
      description: 'Pull all products from the Trackstar API and sync to the local
        database. Requires Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '10'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  synced_count:
                    type: integer
                example:
                  message: Products synced successfully
                  synced_count: 180
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-trackstar-integration-instances-integration-instance-products-sync
  /api/trackstar/integration-instances/{integration_instance}/products/kits:
    get:
      tags:
      - Trackstar
      summary: List Kit Products
      description: 'Get all Trackstar products that are kits (is_kit = true). Requires
        Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '10'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        sku:
                          type: string
                        name:
                          type: string
                        is_kit:
                          type: boolean
                        active:
                          type: boolean
                        inventory_items:
                          type: array
                          items:
                            type: object
                            properties:
                              sku:
                                type: string
                              quantity:
                                type: integer
                example:
                  data:
                  - id: 402
                    sku: KIT-001
                    name: Widget Bundle
                    is_kit: true
                    active: true
                    inventory_items:
                    - sku: PROD-001
                      quantity: 2
                    - sku: PROD-002
                      quantity: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-trackstar-integration-instances-integration-instance-products-kits
  /api/trackstar/integration-instances/{integration_instance}/products/by-sku:
    get:
      tags:
      - Trackstar
      summary: Get Product by SKU
      description: 'Find a Trackstar product by its SKU. Returns null data if not
        found or if sku parameter is missing. Requires Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Query parameters:

        - sku (optional, string): Product SKU to find'
      parameters:
      - name: sku
        in: query
        schema:
          type: string
        description: The SKU to look up
        example: PROD-001
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '10'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 OK - Found
                  value:
                    data:
                      id: 401
                      trackstar_product_id: prod_abc123
                      sku: PROD-001
                      name: Blue Widget
                      active: true
                      unit_price: 24.99
                example-1:
                  summary: 200 OK - Not Found
                  value:
                    data: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-trackstar-integration-instances-integration-instance-products-by-sku
  /api/trackstar/integration-instances/{integration_instance}/products/{product}:
    get:
      tags:
      - Trackstar
      summary: Show Product
      description: 'Get a single Trackstar product by database ID. Requires Bearer
        token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '10'
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: Trackstar product database ID
        example: '401'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      trackstar_product_id:
                        type: string
                      sku:
                        type: string
                      name:
                        type: string
                      gtin:
                        type: string
                      unit_price:
                        type: number
                      is_kit:
                        type: boolean
                      active:
                        type: boolean
                      supplier:
                        type: string
                      country_of_origin:
                        type: string
                      harmonized_code:
                        type: string
                      warehouse_customer_id:
                        type: string
                      inventory_items:
                        type: array
                      supplier_products:
                        type: array
                      trackstar_tags:
                        type: array
                        items:
                          type: string
                      trackstar_created_at:
                        type: string
                      trackstar_updated_at:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 401
                    integration_instance_id: 10
                    trackstar_product_id: prod_abc123
                    sku: PROD-001
                    name: Blue Widget
                    gtin: 012345678901
                    unit_price: 24.99
                    is_kit: false
                    active: true
                    supplier: Acme Corp
                    country_of_origin: US
                    harmonized_code: '8473.30'
                    warehouse_customer_id: cust_001
                    inventory_items: []
                    supplier_products: []
                    trackstar_tags:
                    - widget
                    - blue
                    trackstar_created_at: '2024-01-01T00:00:00.000Z'
                    trackstar_updated_at: '2024-06-01T00:00:00.000Z'
                    created_at: '2024-01-01T00:00:00.000Z'
                    updated_at: '2024-06-01T00:00:00.000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-trackstar-integration-instances-integration-instance-products-product
  /api/trackstar/integration-instances/{integration_instance}/products/{product}/raw:
    get:
      tags:
      - Trackstar
      summary: Get Raw Product from Trackstar
      description: Fetch the product LIVE from the Trackstar API as the raw, untransformed
        payload (nothing is persisted). The product payload is returned under `data.product`.
        Requires Bearer token.
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '10'
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: Product database ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      product:
                        type: object
                        properties:
                          id:
                            type: string
                          sku:
                            type: string
                          name:
                            type: string
                          active:
                            type: boolean
                          unit_price:
                            type: integer
                          inventory_items:
                            type: array
                            items:
                              type: object
                              properties:
                                inventory_item_id:
                                  type: string
                                quantity:
                                  type: integer
                  fetched_at:
                    type: string
                example:
                  data:
                    product:
                      id: prod_18
                      sku: EasyRemote
                      name: Remote for Max, Ultimate and Horizon
                      active: true
                      unit_price: 0
                      inventory_items:
                      - inventory_item_id: ii_101
                        quantity: 42
                  fetched_at: '2026-07-08T12:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-trackstar-integration-instances-integration-instance-products-product-raw
  /api/trackstar/integration-instances/{integration_instance}/products/sync-info:
    get:
      tags:
      - Trackstar
      summary: Get Products Sync Info
      description: 'Baseline for the Refresh Products modal: latest synced product
        + total count. Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '10'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      latest_product_title:
                        type: string
                      latest_product_date:
                        type: string
                      total_products:
                        type: integer
                example:
                  data:
                    latest_product_title: Rouge Max G3 Wall Mounted
                    latest_product_date: '2026-07-08T15:05:00.000000Z'
                    total_products: 19
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-trackstar-integration-instances-integration-instance-products-sync-info
  /api/trackstar/integration-instances/{integration_instance}/products/{product}/activity-log:
    get:
      tags:
      - Trackstar
      summary: Product Activity Log
      description: Paginated activity log for a single product (product detail page
        Activity Log tab). Supports `filter[search]`, `per_page`. Requires Bearer
        token.
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '10'
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: Product database ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        description:
                          type: string
                        event:
                          type: string
                        subject_type:
                          type: string
                        subject_id:
                          type: integer
                        properties:
                          type: object
                          properties:
                            attributes:
                              type: object
                              properties:
                                status:
                                  type: string
                        causer_name:
                          type: string
                        created_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - id: 1
                    description: updated
                    event: updated
                    subject_type: TrackstarOrder
                    subject_id: 1
                    properties:
                      attributes:
                        status: fulfilled
                    causer_name: System
                    created_at: '2026-07-08T12:00:00.000000Z'
                  current_page: 1
                  last_page: 1
                  per_page: 15
                  total: 1
                  from: 1
                  to: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-trackstar-integration-instances-integration-instance-products-product-activity-log
  /api/trackstar/integration-instances/{integration_instance}/bills:
    get:
      tags:
      - Trackstar
      summary: List Bills
      description: 'List paginated Trackstar bills (WMS charges) for an integration
        instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Filters (Spatie QueryBuilder):

        - filter[search]: Partial match on trackstar_bill_id, object_id, warehouse_customer_id,
        charge_type

        - filter[charge_type]: Exact match on charge type

        - filter[object_type]: Exact match on object type

        - filter[object_id]: Exact match on object ID

        - filter[date_from]: Bills with trackstar_created_at on or after this date

        - filter[date_to]: Bills with trackstar_created_at on or before this date


        Allowed sorts: id, charge_type, object_type, amount, trackstar_created_at,
        created_at

        Default sort: -trackstar_created_at'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        description: 'Page number (default: 1)'
        example: '1'
      - name: per_page
        in: query
        schema:
          type: integer
        description: 'Items per page (default: 15)'
        example: '15'
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '10'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        trackstar_bill_id:
                          type: string
                        warehouse_customer_id:
                          type: string
                        object_id:
                          type: string
                        object_type:
                          type: string
                        charge_type:
                          type: string
                        amount:
                          type: number
                        currency_code:
                          type: string
                        formatted_amount:
                          type: string
                        additional_fields:
                          type: string
                          nullable: true
                        trackstar_created_at:
                          type: string
                        trackstar_updated_at:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 601
                    integration_instance_id: 10
                    trackstar_bill_id: bill_001
                    warehouse_customer_id: cust_001
                    object_id: ts-ord-001
                    object_type: order
                    charge_type: pick_and_pack
                    amount: 3.5
                    currency_code: USD
                    formatted_amount: $3.50
                    additional_fields: null
                    trackstar_created_at: '2024-06-03T15:00:00.000Z'
                    trackstar_updated_at: '2024-06-03T15:00:00.000Z'
                    created_at: '2024-06-03T15:05:00.000Z'
                    updated_at: '2024-06-03T15:05:00.000Z'
                  current_page: 1
                  last_page: 30
                  per_page: 15
                  total: 450
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-trackstar-integration-instances-integration-instance-bills
  /api/trackstar/integration-instances/{integration_instance}/bills/sync:
    post:
      tags:
      - Trackstar
      summary: Sync Bills
      description: 'Pull bills from the Trackstar API and sync to the local database.
        Requires Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '10'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  synced_count:
                    type: integer
                example:
                  message: Bills synced successfully
                  synced_count: 450
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-trackstar-integration-instances-integration-instance-bills-sync
  /api/trackstar/integration-instances/{integration_instance}/bills/charge-types:
    get:
      tags:
      - Trackstar
      summary: Get Charge Types
      description: 'Get all distinct charge types present in bills for this integration
        instance. Useful for populating filter dropdowns. Requires Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '10'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: string
                example:
                  data:
                  - pick_and_pack
                  - receiving
                  - storage
                  - shipping
                  - special_handling
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-trackstar-integration-instances-integration-instance-bills-charge-types
  /api/trackstar/integration-instances/{integration_instance}/bills/object-types:
    get:
      tags:
      - Trackstar
      summary: Get Object Types
      description: 'Get all distinct object types present in bills for this integration
        instance. Requires Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '10'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: string
                example:
                  data:
                  - order
                  - receipt
                  - adjustment
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-trackstar-integration-instances-integration-instance-bills-object-types
  /api/trackstar/integration-instances/{integration_instance}/bills/summary:
    get:
      tags:
      - Trackstar
      summary: Bills Summary
      description: 'Get bill totals grouped by charge type and currency. Provides
        a financial overview of WMS charges. Requires Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '10'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        charge_type:
                          type: string
                        total_amount:
                          type: number
                        bill_count:
                          type: integer
                        currency_code:
                          type: string
                example:
                  data:
                  - charge_type: pick_and_pack
                    total_amount: 1575.0
                    bill_count: 450
                    currency_code: USD
                  - charge_type: receiving
                    total_amount: 320.0
                    bill_count: 64
                    currency_code: USD
                  - charge_type: storage
                    total_amount: 890.5
                    bill_count: 90
                    currency_code: USD
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-trackstar-integration-instances-integration-instance-bills-summary
  /api/trackstar/integration-instances/{integration_instance}/shipping-methods:
    get:
      tags:
      - Trackstar
      summary: List Shipping Methods
      description: 'List every Trackstar shipping method for this integration instance
        together with the SKU.io shipping methods available to map onto. Drives the
        mapping editor. Requires a Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '10'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      services:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            trackstar_shipping_method_id:
                              type: string
                            name:
                              type: string
                            carrier:
                              type: string
                            carrier_name:
                              type: string
                            carrier_id:
                              type: string
                            scac:
                              type: string
                            shipping_method_id:
                              type: integer
                            sku_shipping_method_name:
                              type: string
                      sku_shipping_methods:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            full_name:
                              type: string
                            type:
                              type: string
                example:
                  data:
                    services:
                    - id: 12
                      trackstar_shipping_method_id: sm_9f3a2b7c
                      name: Ground
                      carrier: UPS
                      carrier_name: UPS
                      carrier_id: ups
                      scac: UPSN
                      shipping_method_id: 5
                      sku_shipping_method_name: UPS Ground
                    - id: 13
                      trackstar_shipping_method_id: sm_1a2b3c4d
                      name: Priority Mail
                      carrier: USPS
                      carrier_name: USPS
                      carrier_id: usps
                      scac: USPS
                      shipping_method_id: null
                      sku_shipping_method_name: null
                    sku_shipping_methods:
                    - id: 5
                      name: Ground
                      full_name: UPS Ground
                      type: domestic
                    - id: 6
                      name: Priority Mail
                      full_name: USPS Priority Mail
                      type: domestic
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-trackstar-integration-instances-integration-instance-shipping-methods
  /api/trackstar/integration-instances/{integration_instance}/shipping-methods/sync:
    post:
      tags:
      - Trackstar
      summary: Sync Shipping Methods
      description: 'Pull shipping methods from the Trackstar API and sync to the local
        database. Requires Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '10'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  synced_count:
                    type: integer
                example:
                  message: Shipping methods synced successfully
                  synced_count: 15
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-trackstar-integration-instances-integration-instance-shipping-methods-sync
  /api/trackstar/integration-instances/{integration_instance}/shipping-methods/carriers:
    get:
      tags:
      - Trackstar
      summary: Get Carriers
      description: 'Get a list of distinct carrier names available in Trackstar shipping
        methods for this integration. Useful for populating carrier filter dropdowns.
        Requires Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '10'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: string
                example:
                  data:
                  - DHL
                  - FedEx
                  - UPS
                  - USPS
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-trackstar-integration-instances-integration-instance-shipping-methods-carriers
  /api/trackstar/integration-instances/{integration_instance}/shipping-methods/{trackstar_shipping_method}/mapping:
    put:
      tags:
      - Trackstar
      summary: Update Shipping Method Mapping
      description: 'Map a Trackstar shipping method to a SKU.io shipping method. Set
        shipping_method_id to null to unmap. Requires Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Request body fields:

        - shipping_method_id (nullable, integer): SKU.io shipping method ID to map
        to'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                shipping_method_id:
                  type: integer
              example:
                shipping_method_id: 12
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '10'
      - name: trackstar_shipping_method
        in: path
        schema:
          type: integer
        required: true
        description: Trackstar shipping method database ID
        example: '701'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      trackstar_shipping_method_id:
                        type: string
                      name:
                        type: string
                      carrier:
                        type: string
                      shipping_method_id:
                        type: integer
                      sku_shipping_method:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          full_name:
                            type: string
                          carrier_name:
                            type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 701
                    trackstar_shipping_method_id: sm_001
                    name: UPS Ground
                    carrier: UPS
                    shipping_method_id: 12
                    sku_shipping_method:
                      id: 12
                      name: UPS Ground
                      full_name: UPS Ground - Standard
                      carrier_name: UPS
                    updated_at: '2024-06-20T10:00:00.000Z'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      shipping_method_id:
                        type: array
                        items:
                          type: string
                example:
                  message: The given data was invalid.
                  errors:
                    shipping_method_id:
                    - The selected shipping method id is invalid.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: put-api-trackstar-integration-instances-integration-instance-shipping-methods-trackstar-shipping-method-mapping
  /api/trackstar/integration-instances/{integration_instance}/shipping-methods/bulk-map:
    put:
      tags:
      - Trackstar
      summary: Bulk Map Shipping Methods
      description: 'Map many Trackstar shipping methods (by their SKU.io record id)
        to a single SKU.io shipping method in one call. Set shipping_method_id to
        null to clear the mappings. Requires a Bearer token.


        Body: ids (array of integers, required) — the Trackstar shipping-method ids;
        shipping_method_id (integer, nullable) — the SKU.io shipping method to assign,
        or null to unmap.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
                shipping_method_id:
                  type: integer
              example:
                ids:
                - 12
                - 13
                - 14
                shipping_method_id: 5
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '10'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      updated_count:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    updated_count: 3
                  message: 3 mapping(s) saved
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      ids:
                        type: array
                        items:
                          type: string
                example:
                  message: The ids field is required.
                  errors:
                    ids:
                    - The ids field is required.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: put-api-trackstar-integration-instances-integration-instance-shipping-methods-bulk-map
  /api/trackstar/integration-instances/{integration_instance}/shipping-methods/auto-match:
    post:
      tags:
      - Trackstar
      summary: Auto-match Shipping Methods
      description: Auto-link unmapped Trackstar shipping methods to SKU.io shipping
        methods whose name matches (case, spacing and punctuation are ignored; also
        tries carrier + name). Never overwrites an existing mapping. Runs automatically
        on sync; this endpoint re-runs it on demand. Requires a Bearer token.
      requestBody:
        content: {}
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '10'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      matched_count:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    matched_count: 5
                  message: 5 method(s) auto-matched
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-trackstar-integration-instances-integration-instance-shipping-methods-auto-match
  /api/trackstar/integration-instances/{integration_instance}/shipping-methods/export:
    get:
      tags:
      - Trackstar
      summary: Export Shipping Method Mappings
      description: 'Download the current shipping-method mappings as a re-importable
        CSV (columns: trackstar_shipping_method_id, name, carrier, carrier_name, scac,
        shipping_method_id, shipping_method_name). A row with a blank shipping method
        clears that mapping on import. Requires a Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '10'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: text/csv
          content:
            text/plain:
              schema:
                type: string
                example: 'trackstar_shipping_method_id,name,carrier,carrier_name,scac,shipping_method_id,shipping_method_name

                  sm_9f3a2b7c,Ground,UPS,UPS,UPSN,5,UPS Ground

                  sm_1a2b3c4d,Priority Mail,USPS,USPS,USPS,,

                  '
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-trackstar-integration-instances-integration-instance-shipping-methods-export
  /api/trackstar/integration-instances/{integration_instance}/shipping-methods/import:
    post:
      tags:
      - Trackstar
      summary: Import Shipping Method Mappings
      description: Import shipping-method mappings from a CSV. Each row is matched
        to a Trackstar method by trackstar_shipping_method_id and resolves the SKU.io
        method by shipping_method_id (preferred) or shipping_method_name. Requires
        a Bearer token.
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                file:
                  type: string
                  description: 'CSV file (max 2MB). Columns: trackstar_shipping_method_id
                    (required), and either shipping_method_id or shipping_method_name.
                    Leave both blank to clear a mapping.'
                  format: binary
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '10'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      created:
                        type: integer
                      updated:
                        type: integer
                      deleted:
                        type: integer
                      errors:
                        type: array
                        items:
                          type: string
                  message:
                    type: string
                example:
                  data:
                    created: 2
                    updated: 1
                    deleted: 0
                    errors:
                    - 'Line 4: SKU shipping method id ''99999'' not found'
                  message: Import processed
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-trackstar-integration-instances-integration-instance-shipping-methods-import
  /api/trackstar/integration-instances/{integration_instance}/inbound-shipments:
    get:
      tags:
      - Trackstar
      summary: List Inbound Shipments
      description: 'List paginated inbound shipments (receipts/PO receipts) for a
        Trackstar integration instance. Requires Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        description: Page number
        example: '1'
      - name: per_page
        in: query
        schema:
          type: integer
        description: Items per page
        example: '15'
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '10'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        trackstar_id:
                          type: string
                        purchase_order_number:
                          type: string
                        status:
                          type: string
                        warehouse:
                          type: string
                        expected_arrival_date:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 801
                    integration_instance_id: 10
                    trackstar_id: ship_001
                    purchase_order_number: PO-2024-001
                    status: received
                    warehouse: wh_abc123
                    expected_arrival_date: '2024-06-15'
                    created_at: '2024-06-01T00:00:00.000Z'
                    updated_at: '2024-06-15T12:00:00.000Z'
                  current_page: 1
                  last_page: 5
                  per_page: 15
                  total: 72
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-trackstar-integration-instances-integration-instance-inbound-shipments
  /api/trackstar/integration-instances/{integration_instance}/inbound-shipments/sync:
    post:
      tags:
      - Trackstar
      summary: Sync Inbound Shipments
      description: 'Pull inbound shipments from the Trackstar API and sync to the
        local database. Requires Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '10'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  synced_count:
                    type: integer
                example:
                  message: Inbound shipments synced successfully
                  synced_count: 72
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-trackstar-integration-instances-integration-instance-inbound-shipments-sync
  /api/trackstar/integration-instances/{integration_instance}/inbound-shipments/in-transit:
    get:
      tags:
      - Trackstar
      summary: In-Transit Shipments
      description: 'Get inbound shipments currently in transit (not yet received).
        Requires Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '10'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        trackstar_id:
                          type: string
                        purchase_order_number:
                          type: string
                        status:
                          type: string
                        warehouse:
                          type: string
                        expected_arrival_date:
                          type: string
                example:
                  data:
                  - id: 802
                    trackstar_id: ship_002
                    purchase_order_number: PO-2024-002
                    status: in_transit
                    warehouse: wh_abc123
                    expected_arrival_date: '2024-06-25'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-trackstar-integration-instances-integration-instance-inbound-shipments-in-transit
  /api/trackstar/integration-instances/{integration_instance}/inbound-shipments/{inbound_shipment}:
    get:
      tags:
      - Trackstar
      summary: Show Inbound Shipment
      description: 'Get a single inbound shipment. Includes json_object in the response.
        Requires Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '10'
      - name: inbound_shipment
        in: path
        schema:
          type: integer
        required: true
        description: Inbound shipment database ID
        example: '801'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      trackstar_id:
                        type: string
                      purchase_order_number:
                        type: string
                      status:
                        type: string
                      warehouse:
                        type: string
                      expected_arrival_date:
                        type: string
                      json_object:
                        type: object
                        properties:
                          id:
                            type: string
                          purchase_order_number:
                            type: string
                          line_items:
                            type: array
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 801
                    integration_instance_id: 10
                    trackstar_id: ship_001
                    purchase_order_number: PO-2024-001
                    status: received
                    warehouse: wh_abc123
                    expected_arrival_date: '2024-06-15'
                    json_object:
                      id: ship_001
                      purchase_order_number: PO-2024-001
                      line_items: []
                    created_at: '2024-06-01T00:00:00.000Z'
                    updated_at: '2024-06-15T12:00:00.000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-trackstar-integration-instances-integration-instance-inbound-shipments-inbound-shipment
  /api/trackstar/integration-instances/{integration_instance}/inbound-shipments/{inbound_shipment}/raw:
    get:
      tags:
      - Trackstar
      summary: Get Inbound Shipment Raw Data
      description: Fetch an inbound shipment LIVE from the Trackstar API (untransformed)
        for the raw-data viewer. Requires Bearer token.
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '10'
      - name: inbound_shipment
        in: path
        schema:
          type: integer
        required: true
        description: Inbound shipment database ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      product:
                        type: object
                        properties:
                          id:
                            type: string
                          purchase_order_number:
                            type: string
                          status:
                            type: string
                          warehouse_id:
                            type: string
                          line_items:
                            type: array
                            items:
                              type: object
                              properties:
                                sku:
                                  type: string
                                product_id:
                                  type: string
                                expected_quantity:
                                  type: integer
                                received_quantity:
                                  type: integer
                          expected_arrival_date:
                            type: string
                          created_date:
                            type: string
                          updated_date:
                            type: string
                  fetched_at:
                    type: string
                example:
                  data:
                    product:
                      id: ship_2b7c1e
                      purchase_order_number: PO-915404
                      status: in_transit
                      warehouse_id: '3'
                      line_items:
                      - sku: TEST-UK-001
                        product_id: prod_18
                        expected_quantity: 100
                        received_quantity: 0
                      expected_arrival_date: '2026-06-10T00:00:00Z'
                      created_date: '2026-05-20T07:38:00Z'
                      updated_date: '2026-06-02T02:10:00Z'
                  fetched_at: '2026-07-08T12:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-trackstar-integration-instances-integration-instance-inbound-shipments-inbound-shipment-raw
  /api/trackstar/integration-instances/{integration_instance}/returns:
    get:
      tags:
      - Trackstar
      summary: List Returns
      description: 'List paginated customer returns for a Trackstar integration instance.
        Requires Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        description: Page number
        example: '1'
      - name: per_page
        in: query
        schema:
          type: integer
        description: Items per page
        example: '15'
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '10'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        trackstar_id:
                          type: string
                        order_id:
                          type: string
                        status:
                          type: string
                        raw_status:
                          type: string
                        warehouse_customer_id:
                          type: string
                        warehouse_id:
                          type: string
                        tracking_number:
                          type: string
                        carrier:
                          type: string
                        notes:
                          type: string
                        notes_array:
                          type: array
                          items:
                            type: string
                        line_items:
                          type: array
                          items:
                            type: object
                            properties:
                              inventory_item_id:
                                type: string
                              sku:
                                type: string
                              quantity:
                                type: integer
                              return_reason:
                                type: string
                              restocked_quantity:
                                type: integer
                        shipments:
                          type: array
                        trackstar_created_date:
                          type: string
                        trackstar_updated_date:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 901
                    integration_instance_id: 10
                    trackstar_id: ret_001
                    order_id: ts-ord-001
                    status: received
                    raw_status: RECEIVED
                    warehouse_customer_id: cust_001
                    warehouse_id: wh_abc123
                    tracking_number: 1Z999AA10123456999
                    carrier: UPS
                    notes: Customer return - wrong size
                    notes_array:
                    - Customer return - wrong size
                    line_items:
                    - inventory_item_id: item_abc
                      sku: PROD-001
                      quantity: 1
                      return_reason: wrong_size
                      restocked_quantity: 1
                    shipments: []
                    trackstar_created_date: '2024-06-10T00:00:00.000Z'
                    trackstar_updated_date: '2024-06-12T00:00:00.000Z'
                    created_at: '2024-06-10T00:00:00.000Z'
                    updated_at: '2024-06-12T00:00:00.000Z'
                  current_page: 1
                  last_page: 4
                  per_page: 15
                  total: 55
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-trackstar-integration-instances-integration-instance-returns
  /api/trackstar/integration-instances/{integration_instance}/returns/sync:
    post:
      tags:
      - Trackstar
      summary: Sync Returns
      description: 'Pull returns from the Trackstar API and sync to the local database.
        Requires Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '10'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  synced_count:
                    type: integer
                example:
                  message: Returns synced successfully
                  synced_count: 55
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-trackstar-integration-instances-integration-instance-returns-sync
  /api/trackstar/integration-instances/{integration_instance}/returns/pending:
    get:
      tags:
      - Trackstar
      summary: Pending Returns
      description: 'Get returns that are in a pending state (not yet received/processed).
        Requires Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '10'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        trackstar_id:
                          type: string
                        status:
                          type: string
                        order_id:
                          type: string
                        line_items:
                          type: array
                          items:
                            type: object
                            properties:
                              sku:
                                type: string
                              quantity:
                                type: integer
                example:
                  data:
                  - id: 902
                    trackstar_id: ret_002
                    status: pending
                    order_id: ts-ord-005
                    line_items:
                    - sku: PROD-002
                      quantity: 2
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-trackstar-integration-instances-integration-instance-returns-pending
  /api/trackstar/integration-instances/{integration_instance}/returns/{return}:
    get:
      tags:
      - Trackstar
      summary: Show Return
      description: 'Get a single return by database ID. Includes json_object in the
        response. Requires Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '10'
      - name: return
        in: path
        schema:
          type: integer
        required: true
        description: Return database ID
        example: '901'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      trackstar_id:
                        type: string
                      order_id:
                        type: string
                      status:
                        type: string
                      raw_status:
                        type: string
                      tracking_number:
                        type: string
                      carrier:
                        type: string
                      line_items:
                        type: array
                        items:
                          type: object
                          properties:
                            sku:
                              type: string
                            quantity:
                              type: integer
                            return_reason:
                              type: string
                            restocked_quantity:
                              type: integer
                      json_object:
                        type: object
                        properties:
                          id:
                            type: string
                          status:
                            type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 901
                    integration_instance_id: 10
                    trackstar_id: ret_001
                    order_id: ts-ord-001
                    status: received
                    raw_status: RECEIVED
                    tracking_number: 1Z999AA10123456999
                    carrier: UPS
                    line_items:
                    - sku: PROD-001
                      quantity: 1
                      return_reason: wrong_size
                      restocked_quantity: 1
                    json_object:
                      id: ret_001
                      status: RECEIVED
                    created_at: '2024-06-10T00:00:00.000Z'
                    updated_at: '2024-06-12T00:00:00.000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-trackstar-integration-instances-integration-instance-returns-return
  /api/trackstar/integration-instances/{integration_instance}/returns/{return}/raw:
    get:
      tags:
      - Trackstar
      summary: Get Return Raw Data
      description: Fetch a return LIVE from the Trackstar API (untransformed) for
        the raw-data viewer. Requires Bearer token.
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '10'
      - name: return
        in: path
        schema:
          type: integer
        required: true
        description: Return database ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      product:
                        type: object
                        properties:
                          id:
                            type: string
                          order_id:
                            type: string
                          reference_id:
                            type: string
                          status:
                            type: string
                          warehouse_id:
                            type: string
                          line_items:
                            type: array
                            items:
                              type: object
                              properties:
                                sku:
                                  type: string
                                product_id:
                                  type: string
                                quantity:
                                  type: integer
                                condition:
                                  type: string
                          created_date:
                            type: string
                          updated_date:
                            type: string
                  fetched_at:
                    type: string
                example:
                  data:
                    product:
                      id: ret_2b7c1e
                      order_id: ord_2b7c1e
                      reference_id: '#915404R'
                      status: received
                      warehouse_id: '3'
                      line_items:
                      - sku: TEST-UK-001
                        product_id: prod_18
                        quantity: 1
                        condition: sellable
                      created_date: '2026-05-20T07:38:00Z'
                      updated_date: '2026-06-02T02:10:00Z'
                  fetched_at: '2026-07-08T12:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-trackstar-integration-instances-integration-instance-returns-return-raw
  /api/trackstar/integration-instances/{integration_instance}/webhook-events:
    get:
      tags:
      - Trackstar
      summary: List Webhook Events
      description: 'List recent webhook events received from Trackstar for an integration
        instance. Requires Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Query parameters:

        - limit (optional, integer): Number of most recent events to return (default:
        50)'
      parameters:
      - name: limit
        in: query
        schema:
          type: integer
        description: 'Number of recent events to return (default: 50)'
        example: '50'
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '10'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        event_type:
                          type: string
                        trackstar_event_id:
                          type: string
                        processed:
                          type: boolean
                        processed_at:
                          type: string
                        error_message:
                          type: string
                          nullable: true
                        payload:
                          type: object
                          properties:
                            order_id:
                              type: string
                            status:
                              type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                example:
                  data:
                  - id: 1001
                    integration_instance_id: 10
                    event_type: order.shipped
                    trackstar_event_id: evt_abc123
                    processed: true
                    processed_at: '2024-06-20T09:01:00.000Z'
                    error_message: null
                    payload:
                      order_id: ts-ord-001
                      status: shipped
                    created_at: '2024-06-20T09:00:00.000Z'
                    updated_at: '2024-06-20T09:01:00.000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-trackstar-integration-instances-integration-instance-webhook-events
  /api/trackstar/integration-instances/{integration_instance}/webhook-events/unprocessed:
    get:
      tags:
      - Trackstar
      summary: Unprocessed Webhook Events
      description: 'Get all webhook events that have not yet been processed. Useful
        for debugging stuck or failed webhook handlers. Requires Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '10'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        event_type:
                          type: string
                        trackstar_event_id:
                          type: string
                        processed:
                          type: boolean
                        processed_at:
                          type: string
                          nullable: true
                        error_message:
                          type: string
                        payload:
                          type: object
                          properties:
                            sku:
                              type: string
                            quantity:
                              type: integer
                        created_at:
                          type: string
                        updated_at:
                          type: string
                example:
                  data:
                  - id: 1002
                    event_type: inventory.updated
                    trackstar_event_id: evt_def456
                    processed: false
                    processed_at: null
                    error_message: SKU not found
                    payload:
                      sku: UNKNOWN-SKU
                      quantity: 10
                    created_at: '2024-06-20T08:00:00.000Z'
                    updated_at: '2024-06-20T08:00:00.000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-trackstar-integration-instances-integration-instance-webhook-events-unprocessed
  /api/trackstar/integration-instances/{integration_instance}/webhook-events/{webhook_event}:
    get:
      tags:
      - Trackstar
      summary: Show Webhook Event
      description: 'Get a single webhook event by database ID. Includes full payload.
        Requires Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Integration instance ID
        example: '10'
      - name: webhook_event
        in: path
        schema:
          type: integer
        required: true
        description: Webhook event database ID
        example: '1001'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      event_type:
                        type: string
                      trackstar_event_id:
                        type: string
                      payload:
                        type: object
                        properties:
                          order_id:
                            type: string
                          status:
                            type: string
                          tracking:
                            type: string
                      processed_at:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 1001
                    integration_instance_id: 10
                    event_type: order.shipped
                    trackstar_event_id: evt_abc123
                    payload:
                      order_id: ts-ord-001
                      status: shipped
                      tracking: 1Z999AA10123456784
                    processed_at: '2024-06-20T09:01:00.000Z'
                    created_at: '2024-06-20T09:00:00.000Z'
                    updated_at: '2024-06-20T09:01:00.000Z'
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: object
                    properties:
                      webhook_event:
                        type: string
                  message:
                    type: string
                example:
                  errors:
                    webhook_event: Webhook event not found
                  message: WebhookEventNotFound
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-trackstar-integration-instances-integration-instance-webhook-events-webhook-event
  /api/starshipit/integration-instances/{integration_instance}/orders-chart:
    get:
      tags:
      - Starshipit
      summary: Get Orders Chart (Date Range)
      description: 'Returns a daily order-count time series for a StarShipIt integration
        instance over the given date range.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        The response contains one bucket per day in [start_date, end_date], filling
        zero-counts for days with no orders. Used by the dashboard chart to render
        the orders trend.


        Query parameters:

        - start_date (required, YYYY-MM-DD): start of the range

        - end_date (required, YYYY-MM-DD): end of the range; must be >= start_date


        Authentication: Requires Bearer token.'
      parameters:
      - name: start_date
        in: query
        schema:
          type: string
        description: Start date of the range (YYYY-MM-DD). Required.
        example: '2026-04-29'
      - name: end_date
        in: query
        schema:
          type: string
        description: End date of the range (YYYY-MM-DD). Must be on or after start_date.
          Required.
        example: '2026-05-29'
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        date:
                          type: string
                        orders_count:
                          type: integer
                example:
                  data:
                  - date: '2026-04-29'
                    orders_count: 0
                  - date: '2026-04-30'
                    orders_count: 3
                  - date: '2026-05-01'
                    orders_count: 7
                  - date: '2026-05-02'
                    orders_count: 12
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      end_date:
                        type: array
                        items:
                          type: string
                example:
                  message: The end date field must be a date after or equal to start
                    date.
                  errors:
                    end_date:
                    - The end date field must be a date after or equal to start date.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-starshipit-integration-instances-integration-instance-orders-chart
  /api/starshipit/integration-instances/{integration_instance}:
    get:
      tags:
      - Starshipit
      summary: Get Integration Instance
      description: 'Returns the configuration for a single StarShipIt integration
        instance, including connection credentials and behavioural settings.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        `connection_settings` keys:

        - `apiKey` — StarShipIt API key.

        - `subscriptionKey` — StarShipIt subscription (Ocp-Apim) key sent with every
        API call.

        - `webhookSecret` — optional; used to verify signatures on inbound webhook
        notifications.


        `integration_settings` keys (all optional):

        - `fulfillment.enabledWarehousesIds` / `fulfillment.automatedWarehousesIds`
        — warehouse routing selection (see the warehouse routing endpoint).

        - `sync_days_back` — default sync window in days when no start date is set
        (default 30).

        - `order_start_date` — earliest order date to sync.

        - `last_sync.orders` / `last_sync.tracking_info` — timestamps maintained automatically
        by the background sync processes.


        Returns 404 when the instance does not exist.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      integration_id:
                        type: integer
                      connection_settings:
                        type: object
                        properties:
                          apiKey:
                            type: string
                          subscriptionKey:
                            type: string
                          webhookSecret:
                            type: string
                      integration_settings:
                        type: object
                        properties:
                          fulfillment:
                            type: object
                            properties:
                              enabledWarehousesIds:
                                type: array
                                items:
                                  type: integer
                              automatedWarehousesIds:
                                type: array
                                items:
                                  type: integer
                          sync_days_back:
                            type: integer
                          order_start_date:
                            type: string
                          last_sync:
                            type: object
                            properties:
                              orders:
                                type: string
                              tracking_info:
                                type: string
                      is_automatic_sync_enabled:
                        type: boolean
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 2
                    name: StarShipIt AU
                    integration_id: 24
                    connection_settings:
                      apiKey: f2a1c9e4-0000-4b1a-9e77-example
                      subscriptionKey: 0123456789abcdef0123456789abcdef
                      webhookSecret: whsec_example_secret
                    integration_settings:
                      fulfillment:
                        enabledWarehousesIds:
                        - 1
                        - 3
                        automatedWarehousesIds:
                        - 3
                      sync_days_back: 30
                      order_start_date: '2026-01-01'
                      last_sync:
                        orders: '2026-07-06T02:15:00.000000Z'
                        tracking_info: '2026-07-06T02:20:00.000000Z'
                    is_automatic_sync_enabled: true
                    created_at: '2026-03-10T09:00:00+00:00'
                    updated_at: '2026-07-06T02:20:01+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-starshipit-integration-instances-integration-instance
    put:
      tags:
      - Starshipit
      summary: Update Integration Instance
      description: 'Updates a StarShipIt integration instance. All body fields are
        optional — send only what should change.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Merge semantics: top-level keys inside `connection_settings` and `integration_settings`
        are merged into the stored objects. Keys you send overwrite existing values;
        keys you omit are preserved. For example, sending only `integration_settings.sync_days_back`
        leaves the stored `fulfillment` routing untouched.


        Body fields:

        - `name` (string, optional) — must remain unique across all integration instances.

        - `connection_settings` (object, optional) — any of `apiKey`, `subscriptionKey`,
        `webhookSecret`.

        - `integration_settings` (object, optional) — any of `sync_days_back`, `order_start_date`,
        `fulfillment` (with `enabledWarehousesIds` / `automatedWarehousesIds`).

        - `is_automatic_sync_enabled` (boolean, optional).


        A PATCH request to the same URL behaves identically to PUT.


        Returns the full updated instance. Returns 422 when the new `name` is already
        taken; 404 when the instance does not exist.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                connection_settings:
                  type: object
                  properties:
                    apiKey:
                      type: string
                integration_settings:
                  type: object
                  properties:
                    sync_days_back:
                      type: integer
                    fulfillment:
                      type: object
                      properties:
                        enabledWarehousesIds:
                          type: array
                          items:
                            type: integer
                        automatedWarehousesIds:
                          type: array
                          items:
                            type: integer
                is_automatic_sync_enabled:
                  type: boolean
              example:
                name: StarShipIt AU (Main)
                connection_settings:
                  apiKey: f2a1c9e4-1111-4b1a-9e77-rotated
                integration_settings:
                  sync_days_back: 60
                  fulfillment:
                    enabledWarehousesIds:
                    - 1
                    - 3
                    automatedWarehousesIds:
                    - 3
                is_automatic_sync_enabled: false
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      integration_id:
                        type: integer
                      connection_settings:
                        type: object
                        properties:
                          apiKey:
                            type: string
                          subscriptionKey:
                            type: string
                          webhookSecret:
                            type: string
                      integration_settings:
                        type: object
                        properties:
                          fulfillment:
                            type: object
                            properties:
                              enabledWarehousesIds:
                                type: array
                                items:
                                  type: integer
                              automatedWarehousesIds:
                                type: array
                                items:
                                  type: integer
                          sync_days_back:
                            type: integer
                          order_start_date:
                            type: string
                          last_sync:
                            type: object
                            properties:
                              orders:
                                type: string
                              tracking_info:
                                type: string
                      is_automatic_sync_enabled:
                        type: boolean
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 2
                    name: StarShipIt AU (Main)
                    integration_id: 24
                    connection_settings:
                      apiKey: f2a1c9e4-1111-4b1a-9e77-rotated
                      subscriptionKey: 0123456789abcdef0123456789abcdef
                      webhookSecret: whsec_example_secret
                    integration_settings:
                      fulfillment:
                        enabledWarehousesIds:
                        - 1
                        - 3
                        automatedWarehousesIds:
                        - 3
                      sync_days_back: 60
                      order_start_date: '2026-01-01'
                      last_sync:
                        orders: '2026-07-06T02:15:00.000000Z'
                        tracking_info: '2026-07-06T02:20:00.000000Z'
                    is_automatic_sync_enabled: false
                    created_at: '2026-03-10T09:00:00+00:00'
                    updated_at: '2026-07-06T11:41:12+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-starshipit-integration-instances-integration-instance
    delete:
      tags:
      - Starshipit
      summary: Delete Integration Instance
      description: 'Deletes a StarShipIt integration instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        The deletion is performed asynchronously: this endpoint queues a background
        job and returns immediately. The background job removes the instance''s cached
        orders, webhook events, and API logs before deleting the instance record itself.
        Large instances may take a while to fully disappear.


        Returns 404 when the instance does not exist.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Integration instance deleted successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-starshipit-integration-instances-integration-instance
  /api/starshipit/integration-instances:
    post:
      tags:
      - Starshipit
      summary: Create Integration Instance
      description: 'Creates a new StarShipIt integration instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Body fields:

        - `name` (string, required) — must be unique across all integration instances.

        - `connection_settings` (object, required) — credentials: `apiKey` (StarShipIt
        API key), `subscriptionKey` (subscription key), and optionally `webhookSecret`
        for verifying inbound webhook signatures.

        - `integration_settings` (object, optional) — behavioural settings such as
        `sync_days_back`, `order_start_date`, and `fulfillment` warehouse routing
        (`enabledWarehousesIds`, `automatedWarehousesIds`).

        - `is_automatic_sync_enabled` (boolean, optional) — whether scheduled syncs
        run automatically.


        Creating an instance immediately queues a background job that backfills orders
        from StarShipIt. Shipping methods are derived from carriers observed on synced
        orders, so the same backfill also populates shipping method data. Progress
        is reported through the tracked background job facilities.


        Returns 422 when validation fails (missing/duplicate `name`, missing `connection_settings`).


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                connection_settings:
                  type: object
                  properties:
                    apiKey:
                      type: string
                    subscriptionKey:
                      type: string
                    webhookSecret:
                      type: string
                integration_settings:
                  type: object
                  properties:
                    sync_days_back:
                      type: integer
                    order_start_date:
                      type: string
                is_automatic_sync_enabled:
                  type: boolean
              example:
                name: StarShipIt AU
                connection_settings:
                  apiKey: f2a1c9e4-0000-4b1a-9e77-example
                  subscriptionKey: 0123456789abcdef0123456789abcdef
                  webhookSecret: whsec_example_secret
                integration_settings:
                  sync_days_back: 30
                  order_start_date: '2026-01-01'
                is_automatic_sync_enabled: true
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                example:
                  data:
                    id: 2
                    name: StarShipIt AU
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      name:
                        type: array
                        items:
                          type: string
                example:
                  message: The name has already been taken.
                  errors:
                    name:
                    - The name has already been taken.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-starshipit-integration-instances
  /api/starshipit/integration-instances/{integration_instance}/test-connection:
    post:
      tags:
      - Starshipit
      summary: Test Connection
      description: 'Verifies the stored StarShipIt credentials by making a live call
        to the StarShipIt API (it fetches a single unshipped order). No request body.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Returns 200 with a success message when StarShipIt accepts the credentials,
        or 400 when the call fails (bad API key / subscription key, network failure).


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Connection successful
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Connection test failed. Please verify your API credentials.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-starshipit-integration-instances-integration-instance-test-connection
  /api/starshipit/integration-instances/{integration_instance}/dashboard:
    get:
      tags:
      - Starshipit
      summary: Get Dashboard Metrics
      description: 'Returns aggregated operational metrics for the instance:


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        - `totalOrders` — total orders in the local cache.

        - `ordersByStatus` — count per order status. Statuses: `Unshipped`, `Printed`,
        `Shipped`, `Delivered`, `Saved`, `Cancelled`, `Archived`, `Error`, `Unknown`
        (every status is present, zero-filled).

        - `ordersByCarrier` — top carriers by order count (up to 20).

        - `unprocessedWebhookEvents` / `failedWebhookEvents` — inbound webhook events
        not yet processed, and events that recorded an error.

        - `unlinkedOrders` — cached orders not linked to a sales order fulfillment.

        - `ordersLastSyncedAt` / `trackingInfoLastUpdatedAt` — ISO-8601 timestamps
        of the most recent order sync and tracking refresh (null when never run).

        - `ordersChart` — orders per day for the last 30 days, zero-filled so the
        series is continuous.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      totalOrders:
                        type: integer
                      ordersByStatus:
                        type: array
                        items:
                          type: object
                          properties:
                            status:
                              type: string
                            status_label:
                              type: string
                            count:
                              type: integer
                      ordersByCarrier:
                        type: array
                        items:
                          type: object
                          properties:
                            carrier:
                              type: string
                            count:
                              type: integer
                      unprocessedWebhookEvents:
                        type: integer
                      failedWebhookEvents:
                        type: integer
                      ordersLastSyncedAt:
                        type: string
                      trackingInfoLastUpdatedAt:
                        type: string
                      unlinkedOrders:
                        type: integer
                      ordersChart:
                        type: array
                        items:
                          type: object
                          properties:
                            date:
                              type: string
                            orders_count:
                              type: integer
                example:
                  data:
                    totalOrders: 1482
                    ordersByStatus:
                    - status: Unshipped
                      status_label: Unshipped
                      count: 34
                    - status: Printed
                      status_label: Printed
                      count: 6
                    - status: Shipped
                      status_label: Shipped
                      count: 1287
                    - status: Delivered
                      status_label: Delivered
                      count: 112
                    - status: Saved
                      status_label: Saved
                      count: 0
                    - status: Cancelled
                      status_label: Cancelled
                      count: 28
                    - status: Archived
                      status_label: Archived
                      count: 12
                    - status: Error
                      status_label: Error
                      count: 3
                    - status: Unknown
                      status_label: Unknown
                      count: 0
                    ordersByCarrier:
                    - carrier: Australia Post
                      count: 903
                    - carrier: Aramex
                      count: 421
                    - carrier: DHL Express
                      count: 118
                    unprocessedWebhookEvents: 2
                    failedWebhookEvents: 1
                    ordersLastSyncedAt: '2026-07-06T02:15:00+00:00'
                    trackingInfoLastUpdatedAt: '2026-07-06T02:20:00+00:00'
                    unlinkedOrders: 17
                    ordersChart:
                    - date: '2026-06-07'
                      orders_count: 42
                    - date: '2026-06-08'
                      orders_count: 0
                    - date: '2026-06-09'
                      orders_count: 51
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-starshipit-integration-instances-integration-instance-dashboard
  /api/starshipit/integration-instances/{integration_instance}/warehouse-routing:
    get:
      tags:
      - Starshipit
      summary: Get Warehouse Routing
      description: 'Returns the data used to configure which warehouses route fulfillments
        through this StarShipIt instance:


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        - `warehouses` — every warehouse eligible for routing (supplier-owned warehouses
        are excluded), with `id`, `name`, and `supplier_name`.

        - `fulfillment.enabledWarehousesIds` — warehouses currently enabled for this
        instance (fulfillments from these warehouses may be submitted to StarShipIt).

        - `fulfillment.automatedWarehousesIds` — warehouses whose fulfillments are
        submitted automatically without user action.

        - `automated_warehouses` — a map keyed by warehouse ID of warehouses already
        automated by a *different* shipping provider instance (`integration_instance_id`,
        `integration_name`). A warehouse can only be automated by one shipping provider
        at a time, so these warehouses cannot be automated here until released by
        the other provider.


        To change the selection, write `integration_settings.fulfillment` via the
        update endpoint.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      warehouses:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            supplier_name:
                              type: string
                              nullable: true
                      fulfillment:
                        type: object
                        properties:
                          enabledWarehousesIds:
                            type: array
                            items:
                              type: integer
                          automatedWarehousesIds:
                            type: array
                            items:
                              type: integer
                      automated_warehouses:
                        type: object
                        properties:
                          '5':
                            type: object
                            properties:
                              integration_instance_id:
                                type: integer
                              integration_name:
                                type: string
                example:
                  data:
                    warehouses:
                    - id: 1
                      name: Melbourne DC
                      supplier_name: null
                    - id: 3
                      name: Sydney 3PL
                      supplier_name: null
                    fulfillment:
                      enabledWarehousesIds:
                      - 1
                      - 3
                      automatedWarehousesIds:
                      - 3
                    automated_warehouses:
                      '5':
                        integration_instance_id: 7
                        integration_name: ShipStation
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-starshipit-integration-instances-integration-instance-warehouse-routing
  /api/starshipit/integration-instances/{integration_instance}/orders/{order}:
    get:
      tags:
      - Starshipit
      summary: Get Order
      description: 'Returns the full details for a single Starshipit order including
        resolved destination, sender, flags, writeback status, tracking URL, and the
        linked SKU.io sales order fulfillment (if any).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        When `include_json=1` is supplied, the raw StarShipIt JSON payload is included
        as `json_object` (used by the order detail page''s "Raw" panel).


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: order
        in: path
        schema:
          type: integer
        required: true
        description: Internal StarshipitOrder ID
        example: '656'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      starshipit_order_id:
                        type: string
                      order_number:
                        type: string
                      reference:
                        type: string
                      status:
                        type: string
                      status_label:
                        type: string
                      status_color:
                        type: string
                      carrier:
                        type: string
                      carrier_name:
                        type: string
                      carrier_service_code:
                        type: string
                      tracking_number:
                        type: string
                      tracking_url:
                        type: string
                      order_date:
                        type: string
                      shipped_at:
                        type: string
                      manifest_number:
                        type: string
                      total_shipping_price:
                        type: number
                      currency:
                        type: string
                      declared_value:
                        type: number
                      insurance_value:
                        type: number
                      type:
                        type: string
                      export_type:
                        type: string
                      shipping_description:
                        type: string
                      flags:
                        type: object
                        properties:
                          signature_required:
                            type: boolean
                          dangerous_goods:
                            type: boolean
                          add_insurance:
                            type: boolean
                          dtp:
                            type: boolean
                          plt:
                            type: boolean
                          create_return:
                            type: boolean
                          address_validation:
                            type: boolean
                      writeback:
                        type: object
                        properties:
                          status:
                            type: string
                          details:
                            type: string
                          success:
                            type: boolean
                      destination:
                        type: object
                        properties:
                          name:
                            type: string
                          email:
                            type: string
                          phone:
                            type: string
                          company:
                            type: string
                            nullable: true
                          street:
                            type: string
                          suburb:
                            type: string
                          city:
                            type: string
                          state:
                            type: string
                          post_code:
                            type: string
                          country:
                            type: string
                          country_code:
                            type: string
                          delivery_instructions:
                            type: string
                      sender:
                        type: object
                        properties:
                          name:
                            type: string
                          company:
                            type: string
                          email:
                            type: string
                          phone:
                            type: string
                          street:
                            type: string
                          suburb:
                            type: string
                          city:
                            type: string
                          state:
                            type: string
                          post_code:
                            type: string
                          country:
                            type: string
                          country_code:
                            type: string
                      sku_fulfillment:
                        type: object
                        properties:
                          id:
                            type: integer
                          link_reference:
                            type: integer
                          link_type_label:
                            type: string
                          link_id:
                            type: integer
                          link_route:
                            type: string
                      has_detailed_data:
                        type: boolean
                      details_last_updated:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 656
                    integration_instance_id: 2
                    starshipit_order_id: '12345'
                    order_number: SO-1234
                    reference: ACME-PO-9999
                    status: shipped
                    status_label: Shipped
                    status_color: success
                    carrier: starshipit_australia_post
                    carrier_name: Australia Post
                    carrier_service_code: AUS_PARCEL_REGULAR
                    tracking_number: TRK-AU-1234567890
                    tracking_url: https://track.starshipit.com/track/TRK-AU-1234567890
                    order_date: '2026-05-25'
                    shipped_at: '2026-05-26T03:14:00+00:00'
                    manifest_number: MAN-2026-05-26-001
                    total_shipping_price: 12.45
                    currency: AUD
                    declared_value: 199.99
                    insurance_value: 200.0
                    type: international
                    export_type: permanent
                    shipping_description: Books and apparel
                    flags:
                      signature_required: true
                      dangerous_goods: false
                      add_insurance: true
                      dtp: false
                      plt: true
                      create_return: false
                      address_validation: true
                    writeback:
                      status: Success
                      details: Tracking pushed to Shopify
                      success: true
                    destination:
                      name: Jane Doe
                      email: jane@example.com
                      phone: +61 400 000 000
                      company: null
                      street: 1 Smith Street
                      suburb: Richmond
                      city: Melbourne
                      state: VIC
                      post_code: '3121'
                      country: Australia
                      country_code: AU
                      delivery_instructions: Leave at front door
                    sender:
                      name: Acme Warehouse
                      company: Acme Pty Ltd
                      email: ops@acme.example
                      phone: +61 3 9000 0000
                      street: 10 Industrial Way
                      suburb: Port Melbourne
                      city: Melbourne
                      state: VIC
                      post_code: '3207'
                      country: Australia
                      country_code: AU
                    sku_fulfillment:
                      id: 4321
                      link_reference: 4321
                      link_type_label: Sales Order Fulfillment
                      link_id: 4321
                      link_route: /orders/sales-orders/fulfillments/4321
                    has_detailed_data: true
                    details_last_updated: '2026-05-26T03:15:00+00:00'
                    created_at: '2026-05-25T14:02:00+00:00'
                    updated_at: '2026-05-26T03:15:01+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-starshipit-integration-instances-integration-instance-orders-order
  /api/starshipit/integration-instances/{integration_instance}/orders/{order}/webhook-events:
    get:
      tags:
      - Starshipit
      summary: Get Order Webhook Events
      description: 'Returns the most recent webhook events (up to 25) related to this
        Starshipit order.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Events are matched by the order''s `order_number` OR `tracking_number` against
        the `starshipit_webhook_events` table. Each event includes the event type,
        tracking status, processed flag, and any error message.


        Used by the Order Detail page to render a per-order webhook audit trail (operational
        debugging — "did we receive the delivered event?").


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: order
        in: path
        schema:
          type: integer
        required: true
        description: Internal StarshipitOrder ID
        example: '656'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        event_type:
                          type: string
                        tracking_status:
                          type: string
                        tracking_status_label:
                          type: string
                        tracking_status_color:
                          type: string
                        order_number:
                          type: string
                        tracking_number:
                          type: string
                        signature_valid:
                          type: boolean
                        payload:
                          type: object
                          properties:
                            status:
                              type: string
                            tracking_number:
                              type: string
                        processed:
                          type: boolean
                        processed_at:
                          type: string
                        error_message:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                        updated_at:
                          type: string
                example:
                  data:
                  - id: 9011
                    integration_instance_id: 2
                    event_type: tracking_update
                    tracking_status: delivered
                    tracking_status_label: Delivered
                    tracking_status_color: success
                    order_number: SO-1234
                    tracking_number: TRK-AU-1234567890
                    signature_valid: true
                    payload:
                      status: delivered
                      tracking_number: TRK-AU-1234567890
                    processed: true
                    processed_at: '2026-05-27T08:01:11+00:00'
                    error_message: null
                    created_at: '2026-05-27T08:01:09+00:00'
                    updated_at: '2026-05-27T08:01:11+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-starshipit-integration-instances-integration-instance-orders-order-webhook-events
  /api/starshipit/integration-instances/{integration_instance}/orders/{order}/label:
    get:
      tags:
      - Starshipit
      summary: Download Label (PDF base64)
      description: 'Proxies StarShipIt''s GET /api/orders/labels endpoint and returns
        the base64-encoded PDF label for the order.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        The response contains `filename`, `mime_type`, and `base64`. The frontend
        decodes the base64 string client-side and triggers a download.


        Returns 400 if the local order has no `starshipit_order_id` (i.e. was never
        submitted to Starshipit). Returns 502 if the StarShipIt API call fails or
        returns no label.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: order
        in: path
        schema:
          type: integer
        required: true
        description: Internal StarshipitOrder ID
        example: '656'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      filename:
                        type: string
                      mime_type:
                        type: string
                      base64:
                        type: string
                example:
                  data:
                    filename: starshipit-label-SO-1234.pdf
                    mime_type: application/pdf
                    base64: JVBERi0xLjQKJ...truncated
        '502':
          description: Bad Gateway
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: StarShipIt did not return a label for this order
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-starshipit-integration-instances-integration-instance-orders-order-label
  /api/starshipit/integration-instances/{integration_instance}/orders/{order}/packing-slip:
    get:
      tags:
      - Starshipit
      summary: Download Packing Slip (PDF base64)
      description: 'Proxies StarShipIt''s GET /api/orders/packingslip endpoint and
        returns the base64-encoded PDF packing slip for the order.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        The response contains `filename`, `mime_type`, and `base64`. The frontend
        decodes the base64 string client-side and triggers a download.


        Returns 400 if the local order has no `starshipit_order_id`. Returns 502 if
        the StarShipIt API call fails or returns no packing slip.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: order
        in: path
        schema:
          type: integer
        required: true
        description: Internal StarshipitOrder ID
        example: '656'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      filename:
                        type: string
                      mime_type:
                        type: string
                      base64:
                        type: string
                example:
                  data:
                    filename: starshipit-packing-slip-SO-1234.pdf
                    mime_type: application/pdf
                    base64: JVBERi0xLjQKJ...truncated
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-starshipit-integration-instances-integration-instance-orders-order-packing-slip
  /api/starshipit/integration-instances/{integration_instance}/orders:
    get:
      tags:
      - Starshipit
      summary: List Orders
      description: 'List Starshipit orders for the integration instance (paginated).
        Each order includes a `tracking_numbers` array of per-package tracking (tracking_number,
        tracking_url, name, carrier_service_name, delivery_status) — multi-package
        orders carry more than one entry, while the scalar `tracking_number` holds
        only the single value Starshipit returns at the order root. Authenticate with
        a Personal Access Token (PAT) Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: filter[status]
        in: query
        schema:
          type: string
        description: Exact match on status (Unshipped, Shipped, Cancelled, Archived,
          Error)
        example: Shipped
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        starshipit_order_id:
                          type: string
                        order_number:
                          type: string
                        reference:
                          type: string
                        status:
                          type: string
                        status_label:
                          type: string
                        status_color:
                          type: string
                        carrier:
                          type: string
                        carrier_name:
                          type: string
                        carrier_service_code:
                          type: string
                        tracking_number:
                          type: string
                        tracking_url:
                          type: string
                        tracking_numbers:
                          type: array
                          items:
                            type: object
                            properties:
                              tracking_number:
                                type: string
                              tracking_url:
                                type: string
                              name:
                                type: string
                              carrier_service_name:
                                type: string
                              delivery_status:
                                type: string
                        order_date:
                          type: string
                        shipped_at:
                          type: string
                        manifest_number:
                          type: string
                        total_shipping_price:
                          type: number
                        currency:
                          type: string
                        type:
                          type: string
                        customer_name:
                          type: string
                        sku_fulfillment:
                          type: object
                          properties:
                            id:
                              type: integer
                            link_reference:
                              type: integer
                            link_type_label:
                              type: string
                            link_id:
                              type: integer
                            link_route:
                              type: string
                        has_detailed_data:
                          type: boolean
                        details_last_updated:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - id: 172468
                    integration_instance_id: 6
                    starshipit_order_id: '711344099'
                    order_number: BG125116.1
                    reference: SKUio_production676781
                    status: Shipped
                    status_label: Shipped
                    status_color: success
                    carrier: AusPost
                    carrier_name: Australia Post
                    carrier_service_code: 7D85
                    tracking_number: 4H2388922102000935105
                    tracking_url: https://track.starshipit.com/track/4H2388922102000935105
                    tracking_numbers:
                    - tracking_number: 4H2388922101000931506
                      tracking_url: https://track.starshipit.com/track/4H2388922101000931506
                      name: Box A
                      carrier_service_name: PARCEL POST + SIGNATURE
                      delivery_status: Delivered
                    - tracking_number: 4H2388922102000935105
                      tracking_url: https://track.starshipit.com/track/4H2388922102000935105
                      name: Box B
                      carrier_service_name: PARCEL POST + SIGNATURE
                      delivery_status: Delivered
                    order_date: '2023-03-10'
                    shipped_at: '2023-03-10T09:02:00+00:00'
                    manifest_number: '117908497'
                    total_shipping_price: 13.24
                    currency: AUD
                    type: Outgoing
                    customer_name: Kim Moran
                    sku_fulfillment:
                      id: 256917
                      link_reference: 256917
                      link_type_label: Sales Order Fulfillment
                      link_id: 256917
                      link_route: /orders/sales-orders/fulfillments/256917
                    has_detailed_data: true
                    details_last_updated: '2026-06-08T12:42:00+00:00'
                    created_at: '2026-06-09T04:47:00+00:00'
                    updated_at: '2026-06-09T05:42:00+00:00'
                  current_page: 1
                  last_page: 5
                  per_page: 10
                  total: 48
                  from: 1
                  to: 10
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-starshipit-integration-instances-integration-instance-orders
  /api/starshipit/integration-instances/{integration_instance}/orders/sync:
    post:
      tags:
      - Starshipit
      summary: Sync Orders (Queue Job)
      description: "Queue a background (tracked) job to sync orders from StarShipIt\
        \ into SKU.io. Progress is reported through the tracked job log endpoints\
        \ and can also be polled via **Get Order Sync Progress**.\n\n:::info[Authorization]\n\
        Any valid API token can call this endpoint — no specific scope required. [Manage\
        \ tokens](https://app.sku.io/settings/api).\n:::\n\n**Body parameters (all\
        \ optional):**\n- `mode` — one of `since_latest` | `date_range` | `all`.\n\
        \  - `since_latest`: sync orders dated on/after the most recently synced order.\
        \ Send the latest synced order date as `date_from`.\n  - `date_range`: sync\
        \ orders between `date_from` and `date_to` (inclusive). StarShipIt's API only\
        \ bounds the start date, so the end date (`date_to`) is applied by post-filtering\
        \ fetched pages.\n  - `all`: pull full order history; `date_from`/`date_to`\
        \ are ignored.\n- `date_from` — start date (`YYYY-MM-DD`). Lower bound for\
        \ `since_latest` and `date_range`.\n- `date_to` — end date (`YYYY-MM-DD`).\
        \ Upper bound for `date_range` only.\n- `since_date` — **legacy** alias for\
        \ `date_from`, kept for backward compatibility with the previous one-click\
        \ refresh. Used only when `date_from` is absent.\n\nWhen `mode` is omitted\
        \ the job falls back to the instance's configured order start date (or its\
        \ sync-days-back window).\n\nAuthentication: Requires Bearer token."
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                mode:
                  type: string
                date_from:
                  type: string
                date_to:
                  type: string
                since_date:
                  type: string
              example:
                mode: since_latest
                date_from: '2026-05-01'
                date_to: '2026-05-31'
                since_date: '2026-05-01'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                  status:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 4321
                  message: Order sync queued
                  status: Success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-starshipit-integration-instances-integration-instance-orders-sync
  /api/starshipit/integration-instances/{integration_instance}/orders/sync-progress/{trackedJobLogId}:
    get:
      tags:
      - Starshipit
      summary: Get Order Sync Progress
      description: 'Poll the progress of a queued order sync job by its tracked job
        log ID (returned from **Sync Orders**). On completion, `results` carries the
        sync summary — `orders_fetched` (orders retrieved from StarShipIt) and `orders_saved`
        (orders upserted into SKU.io).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Returns 404 if no job exists for the given ID.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: trackedJobLogId
        in: path
        schema:
          type: integer
        required: true
        example: '4321'
        description: The tracked job log ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      status:
                        type: string
                      job_name:
                        type: string
                      total_items:
                        type: integer
                      processed_items:
                        type: integer
                      progress_percentage:
                        type: integer
                      messages:
                        type: array
                        items:
                          type: string
                      results:
                        type: object
                        properties:
                          orders_fetched:
                            type: integer
                          orders_saved:
                            type: integer
                      attempted_at:
                        type: string
                      completed_at:
                        type: string
                  status:
                    type: string
                example:
                  data:
                    id: 4321
                    status: completed
                    job_name: 'Refresh StarShipIt Orders: 6 (Curvy AU)'
                    total_items: 250
                    processed_items: 250
                    progress_percentage: 100
                    messages:
                    - Fetched 250 orders
                    - Saved 250 orders
                    results:
                      orders_fetched: 250
                      orders_saved: 250
                    attempted_at: '2026-05-26T03:14:00.000000Z'
                    completed_at: '2026-05-26T03:15:02.000000Z'
                  status: Success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-starshipit-integration-instances-integration-instance-orders-sync-progress-trackedjoblogid
  /api/starshipit/integration-instances/{integration_instance}/orders/sync-info:
    get:
      tags:
      - Starshipit
      summary: Get Order Sync Info
      description: 'Header data for the orders refresh modal: the most recently dated
        order (`latest_order_number` + `latest_order_date`, keyed on `order_date`),
        the total order count, and the **effective** order start date the "Fetch from
        Start Date" mode will use.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        `order_start_date` (`YYYY-MM-DD`) is always returned and resolves through
        a fallback chain, with `order_start_date_source` naming where it came from:

        - `StarShipIt Order Start Date` — the instance''s configured Order Start Date
        (StarShipIt settings)

        - `Inventory Start Date` — the general inventory start date, when no StarShipIt
        start date is set

        - `Default sync window (last N days)` — a `now − sync_days_back` window, when
        neither start date is configured


        The frontend uses this to seed the "since latest" and "from start date" sync
        modes (always showing the resolved date and its source) and to show how many
        orders are currently stored.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      latest_order_number:
                        type: string
                      latest_order_date:
                        type: string
                      total_orders:
                        type: integer
                      order_start_date:
                        type: string
                      order_start_date_source:
                        type: string
                  status:
                    type: string
                example:
                  data:
                    latest_order_number: SO-1234
                    latest_order_date: '2026-05-25T00:00:00+00:00'
                    total_orders: 250
                    order_start_date: '2026-01-01'
                    order_start_date_source: StarShipIt Order Start Date
                  status: Success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-starshipit-integration-instances-integration-instance-orders-sync-info
  /api/starshipit/integration-instances/{integration_instance}/orders/search:
    post:
      tags:
      - Starshipit
      summary: Search Orders
      description: 'Search StarShipIt **live** for orders matching a phrase, for the
        refresh modal''s "Search Specific Order" tab. StarShipIt''s `/orders/search`
        matches across order number, reference, recipient, and the internal order
        id, so a single phrase covers every identifier a user might paste in. Each
        result is flagged with whether it already exists in this instance''s local
        cache so the UI can offer Download (new) vs Update (existing).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Body parameters:**

        - `query` — **required** string (max 255). The order number, reference, recipient,
        or StarShipIt order id to search for.


        Errors:

        - 422 if `query` is missing

        - 502 if the upstream StarShipIt call fails


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                query:
                  type: string
              example:
                query: SO-1234
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        starshipit_order_id:
                          type: string
                        order_number:
                          type: string
                        status:
                          type: string
                        order_date:
                          type: string
                        email:
                          type: string
                        exists_in_database:
                          type: boolean
                        database_id:
                          type: integer
                  status:
                    type: string
                example:
                  data:
                  - starshipit_order_id: '708495527'
                    order_number: SO-1234
                    status: Shipped
                    order_date: '2026-05-25T00:00:00Z'
                    email: customer@example.com
                    exists_in_database: true
                    database_id: 650
                  - starshipit_order_id: '708495530'
                    order_number: SO-1240
                    status: Unshipped
                    order_date: '2026-05-27T00:00:00Z'
                    email: another@example.com
                    exists_in_database: false
                    database_id: null
                  status: Success
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      query:
                        type: array
                        items:
                          type: string
                example:
                  message: The query field is required.
                  errors:
                    query:
                    - The query field is required.
        '502':
          description: Bad Gateway
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 'Search failed: Starshipit API Error: Invalid API key'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-starshipit-integration-instances-integration-instance-orders-search
  /api/starshipit/integration-instances/{integration_instance}/orders/refresh-order:
    post:
      tags:
      - Starshipit
      summary: Refresh Single Order (Download)
      description: 'Download (or update) a **single** order live from StarShipIt by
        its StarShipIt order id and persist it to the local cache. Backs the search
        tab''s per-result Download / Update buttons.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Body parameters:**

        - `uniqueId` — **required** string. The StarShipIt order id (the `starshipit_order_id`
        returned by **Search Orders**).


        Fetches the order via StarShipIt''s `GET /orders?order_id=`, upserts it (with
        detailed fields), and returns the refreshed order resource (with `json_object`
        included).


        Errors:

        - 422 if `uniqueId` is missing

        - 502 if the upstream StarShipIt call fails or the order cannot be persisted


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                uniqueId:
                  type: string
              example:
                uniqueId: '708495527'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      starshipit_order_id:
                        type: string
                      order_number:
                        type: string
                      status:
                        type: string
                      status_label:
                        type: string
                      status_color:
                        type: string
                      carrier_name:
                        type: string
                      tracking_number:
                        type: string
                      shipped_at:
                        type: string
                      order_date:
                        type: string
                      has_detailed_data:
                        type: boolean
                      details_last_updated:
                        type: string
                      json_object:
                        type: object
                        properties:
                          order_id:
                            type: string
                          order_number:
                            type: string
                example:
                  message: Order refreshed from StarShipIt
                  data:
                    id: 650
                    integration_instance_id: 2
                    starshipit_order_id: '708495527'
                    order_number: SO-1234
                    status: shipped
                    status_label: Shipped
                    status_color: success
                    carrier_name: Australia Post
                    tracking_number: TRK-AU-1234567890
                    shipped_at: '2026-05-26T03:14:00+00:00'
                    order_date: '2026-05-25T00:00:00+00:00'
                    has_detailed_data: true
                    details_last_updated: '2026-05-26T03:18:00+00:00'
                    json_object:
                      order_id: '708495527'
                      order_number: SO-1234
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      uniqueId:
                        type: array
                        items:
                          type: string
                example:
                  message: The unique id field is required.
                  errors:
                    uniqueId:
                    - The unique id field is required.
        '502':
          description: Bad Gateway
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 'Failed to refresh order: Starshipit API Error: Order not
                    found'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-starshipit-integration-instances-integration-instance-orders-refresh-order
  /api/starshipit/integration-instances/{integration_instance}/orders/{order}/tracking:
    post:
      tags:
      - Starshipit
      summary: Refresh Order Tracking
      description: 'Refreshes live tracking events for a single order by calling Starshipit''s
        GET /track endpoint with the order''s `order_number`. The carrier-reported
        events are persisted to `starshipit_orders.json_object.events` so the order
        detail page can render an up-to-date tracking timeline.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Also updates: `tracking_number`, `carrier_name` (when previously empty), local
        `status` (mapped from the tracking status enum), and `details_last_updated`.


        Returns the refreshed order resource (with `json_object` included) and a success
        message.


        Errors:

        - 400 if the order has no `order_number` (Starshipit requires it to look up
        tracking)

        - 404 if the order does not belong to the given integration instance

        - 502 if the upstream Starshipit /track call fails (auth, network, etc.)


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: order
        in: path
        schema:
          type: integer
        required: true
        description: Local StarShipIt order ID (numeric primary key on `starshipit_orders`)
        example: '650'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      starshipit_order_id:
                        type: string
                      order_number:
                        type: string
                      status:
                        type: string
                      status_label:
                        type: string
                      status_color:
                        type: string
                      carrier_name:
                        type: string
                      tracking_number:
                        type: string
                      tracking_url:
                        type: string
                      shipped_at:
                        type: string
                      has_detailed_data:
                        type: boolean
                      details_last_updated:
                        type: string
                      json_object:
                        type: object
                        properties:
                          order_id:
                            type: string
                          order_number:
                            type: string
                          tracking_status:
                            type: string
                          events:
                            type: array
                            items:
                              type: object
                              properties:
                                status:
                                  type: string
                                timestamp:
                                  type: string
                                location:
                                  type: string
                                description:
                                  type: string
                example:
                  message: Tracking refreshed from StarShipIt
                  data:
                    id: 650
                    integration_instance_id: 2
                    starshipit_order_id: '708495527'
                    order_number: SO-1234
                    status: shipped
                    status_label: Shipped
                    status_color: success
                    carrier_name: Australia Post
                    tracking_number: TRK-AU-1234567890
                    tracking_url: https://track.starshipit.com/track/TRK-AU-1234567890
                    shipped_at: '2026-05-26T03:14:00+00:00'
                    has_detailed_data: true
                    details_last_updated: '2026-05-26T03:18:00+00:00'
                    json_object:
                      order_id: '708495527'
                      order_number: SO-1234
                      tracking_status: InTransit
                      events:
                      - status: Manifested
                        timestamp: '2026-05-25T10:00:00Z'
                        location: Sydney DC
                        description: Shipment manifested
                      - status: InTransit
                        timestamp: '2026-05-26T08:00:00Z'
                        location: Melbourne Hub
                        description: In transit to delivery hub
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Order is missing an order number, which Starshipit requires
                    to look up tracking.
        '502':
          description: Bad Gateway
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 'Failed to refresh tracking: Saloon RequestException (401
                    Unauthorized)'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-starshipit-integration-instances-integration-instance-orders-order-tracking
  /api/starshipit/integration-instances/{integration_instance}/orders/{order}/activity-log:
    get:
      tags:
      - Starshipit
      summary: Get Order Activity Log
      description: 'Paginated Spatie activity-log entries for a single Starshipit
        order (by local row id) — the order detail page''s Activity Log tab. Each
        entry: id, description, event (created/updated/deleted), subject_type, subject_id,
        properties (changed attributes), causer_name, created_at. Ordered newest first.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Pagination: page (default 1), per_page (default 15).


        Authentication: Requires Bearer token.


        Filters: filter[event] (exact event), filter[source] (matches properties->source),
        filter[batch_uuid] (exact batch uuid), filter[search] (LIKE over causer name
        / properties / event).'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: order
        in: path
        schema:
          type: integer
        required: true
        description: Internal StarshipitOrder ID
        example: '656'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        description:
                          type: string
                        event:
                          type: string
                        subject_type:
                          type: string
                        subject_id:
                          type: integer
                        properties:
                          type: object
                          properties:
                            attributes:
                              type: object
                              properties:
                                tracking_number:
                                  type: string
                            old:
                              type: object
                              properties:
                                tracking_number:
                                  type: string
                                  nullable: true
                        causer_name:
                          type: string
                        created_at:
                          type: string
                  current_page:
                    type: integer
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 90412
                    description: updated
                    event: updated
                    subject_type: StarshipitOrder
                    subject_id: 656
                    properties:
                      attributes:
                        tracking_number: 1Z999AA10123456784
                      old:
                        tracking_number: null
                    causer_name: Sync Job
                    created_at: '2026-06-11T14:33:00.000000Z'
                  - id: 90380
                    description: created
                    event: created
                    subject_type: StarshipitOrder
                    subject_id: 656
                    properties:
                      attributes:
                        order_number: SO-100245
                    causer_name: null
                    created_at: '2026-06-10T09:15:00.000000Z'
                  current_page: 1
                  first_page_url: '{{protocol}}://{{domain}}/api/starshipit/...?page=1'
                  from: 1
                  last_page: 1
                  per_page: 15
                  to: 2
                  total: 2
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Order not found for this instance
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-starshipit-integration-instances-integration-instance-orders-order-activity-log
  /api/starshipit/integration-instances/{integration_instance}/orders/{order}/detail:
    get:
      tags:
      - Starshipit
      summary: Get Order Detail
      description: 'Returns the locally cached raw StarShipIt payload for a single
        order.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Response fields:

        - `json_object` — the raw order payload as last received from StarShipIt (items,
        packages, destination, tracking events, writeback status, etc.).

        - `has_detailed_data` — whether a full per-order detail fetch has ever been
        performed. List syncs store a summary payload; the detail fetch enriches it.

        - `details_last_updated` — when the detail payload was last refreshed from
        StarShipIt (null when never).


        This endpoint reads only the local cache and never calls StarShipIt. To refresh
        the payload live from StarShipIt, use the companion `POST .../orders/:order/sync-detail`
        endpoint.


        Returns 404 when the order does not belong to this instance.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: order
        in: path
        schema:
          type: integer
        required: true
        example: '656'
        description: The order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      starshipit_order_id:
                        type: string
                      order_number:
                        type: string
                      json_object:
                        type: object
                        properties:
                          order_id:
                            type: integer
                          order_number:
                            type: string
                          reference:
                            type: string
                          status:
                            type: string
                          carrier:
                            type: string
                          carrier_name:
                            type: string
                          tracking_number:
                            type: string
                          currency:
                            type: string
                          destination:
                            type: object
                            properties:
                              name:
                                type: string
                              street:
                                type: string
                              city:
                                type: string
                              state:
                                type: string
                              post_code:
                                type: string
                              country:
                                type: string
                          items:
                            type: array
                            items:
                              type: object
                              properties:
                                sku:
                                  type: string
                                description:
                                  type: string
                                quantity:
                                  type: integer
                                weight:
                                  type: number
                                value:
                                  type: number
                          packages:
                            type: array
                            items:
                              type: object
                              properties:
                                name:
                                  type: string
                                tracking_number:
                                  type: string
                                carrier_service_name:
                                  type: string
                                delivery_status:
                                  type: string
                      has_detailed_data:
                        type: boolean
                      details_last_updated:
                        type: string
                example:
                  data:
                    id: 656
                    starshipit_order_id: '123456789'
                    order_number: SO-1234
                    json_object:
                      order_id: 123456789
                      order_number: SO-1234
                      reference: ACME-PO-9999
                      status: Shipped
                      carrier: AusPost
                      carrier_name: Australia Post
                      tracking_number: TRK-AU-1234567890
                      currency: AUD
                      destination:
                        name: Jane Doe
                        street: 1 Smith Street
                        city: Melbourne
                        state: VIC
                        post_code: '3121'
                        country: Australia
                      items:
                      - sku: TSHIRT-BLK-M
                        description: T-Shirt Black M
                        quantity: 2
                        weight: 0.2
                        value: 29.95
                      packages:
                      - name: Box A
                        tracking_number: TRK-AU-1234567890
                        carrier_service_name: Parcel Post
                        delivery_status: Delivered
                    has_detailed_data: true
                    details_last_updated: '2026-07-05T22:10:00+00:00'
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Order not found for this instance
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-starshipit-integration-instances-integration-instance-orders-order-detail
  /api/starshipit/integration-instances/{integration_instance}/orders/{order}/sync-detail:
    post:
      tags:
      - Starshipit
      summary: Sync Order Detail
      description: 'Fetches the latest data for a single order live from the StarShipIt
        API and persists it to the local cache (updating `json_object`, setting `has_detailed_data`
        and `details_last_updated`). Returns the refreshed order, including the raw
        payload.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        This is the live-refresh companion to `GET .../orders/:order/detail`, which
        reads the cache without calling StarShipIt.


        If the order has no StarShipIt order ID yet (for example a deferred submission
        placeholder), the order is returned unchanged. Returns 404 when the order
        does not belong to this instance, and 502 when the StarShipIt API call fails.


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: order
        in: path
        schema:
          type: integer
        required: true
        example: '656'
        description: The order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      starshipit_order_id:
                        type: string
                      order_number:
                        type: string
                      external_url:
                        type: string
                      reference:
                        type: string
                      status:
                        type: string
                      status_label:
                        type: string
                      status_color:
                        type: string
                      carrier:
                        type: string
                      carrier_name:
                        type: string
                      carrier_service_code:
                        type: string
                      tracking_number:
                        type: string
                      tracking_url:
                        type: string
                      tracking_numbers:
                        type: array
                        items:
                          type: object
                          properties:
                            tracking_number:
                              type: string
                            tracking_url:
                              type: string
                            name:
                              type: string
                            carrier_service_name:
                              type: string
                            delivery_status:
                              type: string
                      order_date:
                        type: string
                      shipped_at:
                        type: string
                      manifest_number:
                        type: string
                      total_shipping_price:
                        type: number
                      currency:
                        type: string
                      declared_value:
                        type: number
                      insurance_value:
                        type: integer
                      type:
                        type: string
                      export_type:
                        type: string
                      shipping_description:
                        type: string
                      flags:
                        type: object
                        properties:
                          signature_required:
                            type: boolean
                          dangerous_goods:
                            type: boolean
                          add_insurance:
                            type: boolean
                          dtp:
                            type: boolean
                          plt:
                            type: boolean
                          create_return:
                            type: boolean
                          address_validation:
                            type: boolean
                      writeback:
                        type: object
                        properties:
                          status:
                            type: string
                          details:
                            type: string
                          success:
                            type: boolean
                      customer_name:
                        type: string
                      destination:
                        type: object
                        properties:
                          name:
                            type: string
                          email:
                            type: string
                          phone:
                            type: string
                          company:
                            type: string
                            nullable: true
                          street:
                            type: string
                          suburb:
                            type: string
                          city:
                            type: string
                          state:
                            type: string
                          post_code:
                            type: string
                          country:
                            type: string
                          country_code:
                            type: string
                          delivery_instructions:
                            type: string
                      sender:
                        type: object
                        properties:
                          name:
                            type: string
                          company:
                            type: string
                          email:
                            type: string
                          phone:
                            type: string
                          street:
                            type: string
                          suburb:
                            type: string
                          city:
                            type: string
                          state:
                            type: string
                          post_code:
                            type: string
                          country:
                            type: string
                          country_code:
                            type: string
                      sku_fulfillment:
                        type: object
                        properties:
                          id:
                            type: integer
                          link_reference:
                            type: string
                          link_type_label:
                            type: string
                          link_id:
                            type: integer
                          link_route:
                            type: string
                          status:
                            type: string
                          sales_order_id:
                            type: integer
                          sales_order_number:
                            type: string
                          fulfillment_order_id:
                            type: integer
                      items:
                        type: array
                        items:
                          type: object
                          properties:
                            sku:
                              type: string
                            description:
                              type: string
                            quantity:
                              type: integer
                            weight:
                              type: number
                            value:
                              type: number
                            product_id:
                              type: integer
                      has_detailed_data:
                        type: boolean
                      details_last_updated:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      json_object:
                        type: object
                        properties:
                          order_id:
                            type: integer
                          order_number:
                            type: string
                          status:
                            type: string
                example:
                  data:
                    id: 656
                    integration_instance_id: 2
                    starshipit_order_id: '123456789'
                    order_number: SO-1234
                    external_url: https://app2.starshipit.com/orders/new/123456789
                    reference: ACME-PO-9999
                    status: Shipped
                    status_label: Shipped
                    status_color: success
                    carrier: AusPost
                    carrier_name: Australia Post
                    carrier_service_code: AUS_PARCEL_REGULAR
                    tracking_number: TRK-AU-1234567890
                    tracking_url: https://track.starshipit.com/track/TRK-AU-1234567890
                    tracking_numbers:
                    - tracking_number: TRK-AU-1234567890
                      tracking_url: https://track.starshipit.com/track/TRK-AU-1234567890
                      name: Box A
                      carrier_service_name: Parcel Post
                      delivery_status: Delivered
                    order_date: '2026-06-25'
                    shipped_at: '2026-06-26T03:14:00+00:00'
                    manifest_number: MAN-2026-06-26-001
                    total_shipping_price: 12.45
                    currency: AUD
                    declared_value: 199.99
                    insurance_value: 200
                    type: international
                    export_type: permanent
                    shipping_description: Books and apparel
                    flags:
                      signature_required: true
                      dangerous_goods: false
                      add_insurance: true
                      dtp: false
                      plt: false
                      create_return: false
                      address_validation: true
                    writeback:
                      status: Success
                      details: Tracking pushed to Shopify
                      success: true
                    customer_name: Jane Doe
                    destination:
                      name: Jane Doe
                      email: jane@example.com
                      phone: +61 400 000 000
                      company: null
                      street: 1 Smith Street
                      suburb: Richmond
                      city: Melbourne
                      state: VIC
                      post_code: '3121'
                      country: Australia
                      country_code: AU
                      delivery_instructions: Leave at front door
                    sender:
                      name: Acme Warehouse
                      company: Acme Pty Ltd
                      email: ops@acme.example
                      phone: +61 3 9000 0000
                      street: 10 Industrial Way
                      suburb: Port Melbourne
                      city: Melbourne
                      state: VIC
                      post_code: '3207'
                      country: Australia
                      country_code: AU
                    sku_fulfillment:
                      id: 4321
                      link_reference: F-4321
                      link_type_label: Sales Order Fulfillment
                      link_id: 4321
                      link_route: /orders/sales-orders/fulfillments/4321
                      status: shipped
                      sales_order_id: 887
                      sales_order_number: SO-1234
                      fulfillment_order_id: 5120
                    items:
                    - sku: TSHIRT-BLK-M
                      description: T-Shirt Black M
                      quantity: 2
                      weight: 0.2
                      value: 29.95
                      product_id: 1045
                    has_detailed_data: true
                    details_last_updated: '2026-07-06T11:42:00+00:00'
                    created_at: '2026-06-25T14:02:00+00:00'
                    updated_at: '2026-07-06T11:42:00+00:00'
                    json_object:
                      order_id: 123456789
                      order_number: SO-1234
                      status: Shipped
        '502':
          description: Bad Gateway
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 'Failed to fetch order detail: StarShipIt API returned
                    401 Unauthorized'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-starshipit-integration-instances-integration-instance-orders-order-sync-detail
  /api/starshipit/integration-instances/{integration_instance}/orders/{order}/link-fulfillment:
    post:
      tags:
      - Starshipit
      summary: Link Order To Fulfillment
      description: 'Manually links a cached StarShipIt order to a sales order fulfillment.
        Use this to repair orders the automatic matching could not link (they show
        as "unlinked" on the dashboard metrics).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Body:

        - `sku_fulfillment_id` (integer, required) — the sales order fulfillment ID
        to link.


        Returns the updated order, including the linked fulfillment summary under
        `sku_fulfillment`. Returns 400 when `sku_fulfillment_id` is missing, and 404
        when the order cannot be found.


        To remove the link again, use the unlink endpoint.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                sku_fulfillment_id:
                  type: integer
              example:
                sku_fulfillment_id: 4321
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: order
        in: path
        schema:
          type: integer
        required: true
        example: '656'
        description: The order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      starshipit_order_id:
                        type: string
                      order_number:
                        type: string
                      status:
                        type: string
                      status_label:
                        type: string
                      status_color:
                        type: string
                      carrier_name:
                        type: string
                      tracking_number:
                        type: string
                      sku_fulfillment:
                        type: object
                        properties:
                          id:
                            type: integer
                          link_reference:
                            type: string
                          link_type_label:
                            type: string
                          link_id:
                            type: integer
                          link_route:
                            type: string
                          status:
                            type: string
                          sales_order_id:
                            type: integer
                          sales_order_number:
                            type: string
                          fulfillment_order_id:
                            type: string
                            nullable: true
                      has_detailed_data:
                        type: boolean
                      details_last_updated:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 656
                    integration_instance_id: 2
                    starshipit_order_id: '123456789'
                    order_number: SO-1234
                    status: Shipped
                    status_label: Shipped
                    status_color: success
                    carrier_name: Australia Post
                    tracking_number: TRK-AU-1234567890
                    sku_fulfillment:
                      id: 4321
                      link_reference: F-4321
                      link_type_label: Sales Order Fulfillment
                      link_id: 4321
                      link_route: /orders/sales-orders/fulfillments/4321
                      status: shipped
                      sales_order_id: 887
                      sales_order_number: SO-1234
                      fulfillment_order_id: null
                    has_detailed_data: true
                    details_last_updated: '2026-07-05T22:10:00+00:00'
                    created_at: '2026-06-25T14:02:00+00:00'
                    updated_at: '2026-07-06T11:45:00+00:00'
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: sku_fulfillment_id required
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Order not found
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-starshipit-integration-instances-integration-instance-orders-order-link-fulfillment
  /api/starshipit/integration-instances/{integration_instance}/orders/{order}/unlink-fulfillment:
    post:
      tags:
      - Starshipit
      summary: Unlink Order From Fulfillment
      description: 'Removes the manual link between a cached StarShipIt order and
        its sales order fulfillment. No request body.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Returns the updated order with `sku_fulfillment` cleared (unless the order
        still resolves to a fulfillment through its fulfillment-order association,
        which this endpoint does not touch). Returns 404 when the order does not belong
        to this instance.


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: order
        in: path
        schema:
          type: integer
        required: true
        example: '656'
        description: The order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      starshipit_order_id:
                        type: string
                      order_number:
                        type: string
                      status:
                        type: string
                      status_label:
                        type: string
                      status_color:
                        type: string
                      carrier_name:
                        type: string
                      tracking_number:
                        type: string
                      sku_fulfillment:
                        type: string
                        nullable: true
                      has_detailed_data:
                        type: boolean
                      details_last_updated:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 656
                    integration_instance_id: 2
                    starshipit_order_id: '123456789'
                    order_number: SO-1234
                    status: Shipped
                    status_label: Shipped
                    status_color: success
                    carrier_name: Australia Post
                    tracking_number: TRK-AU-1234567890
                    sku_fulfillment: null
                    has_detailed_data: true
                    details_last_updated: '2026-07-05T22:10:00+00:00'
                    created_at: '2026-06-25T14:02:00+00:00'
                    updated_at: '2026-07-06T11:47:00+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-starshipit-integration-instances-integration-instance-orders-order-unlink-fulfillment
  /api/starshipit/integration-instances/{integration_instance}/orders/submit-fulfillment:
    post:
      tags:
      - Starshipit
      summary: Submit Fulfillment
      description: 'Manually submits a sales order fulfillment to StarShipIt through
        the canonical fulfillment dispatch flow.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Body:

        - `sku_fulfillment_id` (integer, required) — the sales order fulfillment whose
        parent sales order should be dispatched.


        The dispatch runs synchronously and covers the whole parent sales order: it
        performs duplicate-order detection and is idempotent — fulfillments already
        submitted to the carrier (or in a terminal state) are skipped rather than
        resubmitted.


        Returns 400 when `sku_fulfillment_id` is missing, 404 when the fulfillment
        or its sales order cannot be found, and 502 when the dispatch fails (for example
        a StarShipIt API error).


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                sku_fulfillment_id:
                  type: integer
              example:
                sku_fulfillment_id: 4321
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      sales_order_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    sales_order_id: 887
                  message: Order dispatched to StarShipIt
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Fulfillment not found
        '502':
          description: Bad Gateway
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 'Failed to submit fulfillment: StarShipIt API returned
                    400 Bad Request'
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-starshipit-integration-instances-integration-instance-orders-submit-fulfillment
  /api/starshipit/submit-orders:
    get:
      tags:
      - Starshipit
      summary: Submit Open Orders (Power User)
      description: '**Warning: this GET request has side effects — it queues a bulk
        submission of orders to StarShipIt.** It is a legacy power-user endpoint kept
        for backward compatibility; treat it as an action, not a read.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Queues a background job that submits every open, not-yet-submitted fulfillment
        routed to a StarShipIt-enabled warehouse to the carrier. The sweep is idempotent:
        fulfillments already submitted or in a terminal state are skipped.


        This endpoint is not instance-scoped — it resolves the single active StarShipIt
        integration instance itself. When no StarShipIt instance is configured, it
        returns HTTP 200 with an error payload (code `StarshipitNotIntegrated`).


        Requires the power user role.


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 OK
                  value:
                    message: Added to the queue, it will be processed shortly
                example-1:
                  summary: 200 OK (Not Integrated)
                  value:
                    message: The system does not integrate with Starshipit
                    errors:
                      starshipit:
                      - message: The system does not integrate with Starshipit
                        code: StarshipitNotIntegrated
                        data: []
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: get-api-starshipit-submit-orders
  /api/starshipit/view-order/{sales_order_fulfillment}:
    get:
      tags:
      - Starshipit
      summary: Get Order For Fulfillment (Power User)
      description: 'Returns the locally cached StarShipIt order linked to the given
        sales order fulfillment. Read-only — no calls to StarShipIt are made. This
        is a legacy power-user endpoint kept for backward compatibility; it is not
        instance-scoped and resolves the single active StarShipIt integration instance
        itself.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Returns 404 when the fulfillment exists but has no linked StarShipIt order
        (or the fulfillment ID is unknown). When no StarShipIt instance is configured,
        it returns HTTP 200 with an error payload (code `StarshipitNotIntegrated`).


        Requires the power user role.


        Authentication: Requires Bearer token.'
      parameters:
      - name: sales_order_fulfillment
        in: path
        schema:
          type: integer
        required: true
        example: '4321'
        description: The sales order fulfillment ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      starshipit_order_id:
                        type: string
                      order_number:
                        type: string
                      external_url:
                        type: string
                      reference:
                        type: string
                      status:
                        type: string
                      status_label:
                        type: string
                      status_color:
                        type: string
                      carrier:
                        type: string
                      carrier_name:
                        type: string
                      carrier_service_code:
                        type: string
                      tracking_number:
                        type: string
                      tracking_url:
                        type: string
                      order_date:
                        type: string
                      shipped_at:
                        type: string
                      manifest_number:
                        type: string
                      total_shipping_price:
                        type: number
                      currency:
                        type: string
                      customer_name:
                        type: string
                      sku_fulfillment:
                        type: object
                        properties:
                          id:
                            type: integer
                          link_reference:
                            type: string
                          link_type_label:
                            type: string
                          link_id:
                            type: integer
                          link_route:
                            type: string
                          status:
                            type: string
                          sales_order_id:
                            type: integer
                          sales_order_number:
                            type: string
                          fulfillment_order_id:
                            type: integer
                      has_detailed_data:
                        type: boolean
                      details_last_updated:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 656
                    integration_instance_id: 2
                    starshipit_order_id: '123456789'
                    order_number: SO-1234
                    external_url: https://app2.starshipit.com/orders/new/123456789
                    reference: ACME-PO-9999
                    status: Shipped
                    status_label: Shipped
                    status_color: success
                    carrier: AusPost
                    carrier_name: Australia Post
                    carrier_service_code: AUS_PARCEL_REGULAR
                    tracking_number: TRK-AU-1234567890
                    tracking_url: https://track.starshipit.com/track/TRK-AU-1234567890
                    order_date: '2026-06-25'
                    shipped_at: '2026-06-26T03:14:00+00:00'
                    manifest_number: MAN-2026-06-26-001
                    total_shipping_price: 12.45
                    currency: AUD
                    customer_name: Jane Doe
                    sku_fulfillment:
                      id: 4321
                      link_reference: F-4321
                      link_type_label: Sales Order Fulfillment
                      link_id: 4321
                      link_route: /orders/sales-orders/fulfillments/4321
                      status: shipped
                      sales_order_id: 887
                      sales_order_number: SO-1234
                      fulfillment_order_id: 5120
                    has_detailed_data: true
                    details_last_updated: '2026-07-05T22:10:00+00:00'
                    created_at: '2026-06-25T14:02:00+00:00'
                    updated_at: '2026-07-06T02:20:00+00:00'
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      id:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: array
                example:
                  message: The Starshipit details not available
                  errors:
                    id:
                    - message: The Starshipit details not available
                      code: NotFound
                      data: []
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: get-api-starshipit-view-order-sales-order-fulfillment
  /api/starshipit/update-order/{sales_order_fulfillment}:
    put:
      tags:
      - Starshipit
      summary: Update Order From Fulfillment (Power User)
      description: 'Pushes the current state of a sales order fulfillment to StarShipIt.
        If the fulfillment already has a linked StarShipIt order, that order is updated
        live via the StarShipIt API (preserving existing line identifiers); otherwise
        a new StarShipIt order is created. The result is persisted to the local order
        cache and returned.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        The path parameter is the sales order fulfillment ID. No request body.


        Before submitting, the fulfillment is validated as a StarShipIt order payload
        (destination address, line items, etc.); when validation fails, a 400 is returned
        with per-field errors. A 502 is returned when the StarShipIt API call fails.


        This is a legacy power-user endpoint kept for backward compatibility; it is
        not instance-scoped and resolves the single active StarShipIt integration
        instance itself. When no StarShipIt instance is configured, it returns HTTP
        200 with an error payload (code `StarshipitNotIntegrated`).


        Requires the power user role.


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: sales_order_fulfillment
        in: path
        schema:
          type: integer
        required: true
        example: '4321'
        description: The sales order fulfillment ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      starshipit_order_id:
                        type: string
                      order_number:
                        type: string
                      external_url:
                        type: string
                      status:
                        type: string
                      status_label:
                        type: string
                      status_color:
                        type: string
                      carrier:
                        type: string
                      carrier_name:
                        type: string
                      carrier_service_code:
                        type: string
                      tracking_number:
                        type: string
                        nullable: true
                      tracking_url:
                        type: string
                        nullable: true
                      order_date:
                        type: string
                      shipped_at:
                        type: string
                        nullable: true
                      total_shipping_price:
                        type: number
                      customer_name:
                        type: string
                      sku_fulfillment:
                        type: object
                        properties:
                          id:
                            type: integer
                          link_reference:
                            type: string
                          link_type_label:
                            type: string
                          link_id:
                            type: integer
                          link_route:
                            type: string
                          status:
                            type: string
                          sales_order_id:
                            type: integer
                          sales_order_number:
                            type: string
                          fulfillment_order_id:
                            type: integer
                      has_detailed_data:
                        type: boolean
                      details_last_updated:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 656
                    integration_instance_id: 2
                    starshipit_order_id: '123456789'
                    order_number: SO-1234
                    external_url: https://app2.starshipit.com/orders/new/123456789
                    status: Unshipped
                    status_label: Unshipped
                    status_color: info
                    carrier: AusPost
                    carrier_name: Australia Post
                    carrier_service_code: AUS_PARCEL_REGULAR
                    tracking_number: null
                    tracking_url: null
                    order_date: '2026-07-05'
                    shipped_at: null
                    total_shipping_price: 12.45
                    customer_name: Jane Doe
                    sku_fulfillment:
                      id: 4321
                      link_reference: F-4321
                      link_type_label: Sales Order Fulfillment
                      link_id: 4321
                      link_route: /orders/sales-orders/fulfillments/4321
                      status: pending
                      sales_order_id: 887
                      sales_order_number: SO-1234
                      fulfillment_order_id: 5120
                    has_detailed_data: false
                    details_last_updated: null
                    created_at: '2026-07-05T14:02:00+00:00'
                    updated_at: '2026-07-06T11:50:00+00:00'
                  message: The Starshipit Order 'SO-1234' updated successfully
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      destination.post_code:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: array
                example:
                  message: Can't submit order to Starshipit
                  errors:
                    destination.post_code:
                    - message: The destination post code is required.
                      code: Required
                      data: []
        '502':
          description: Bad Gateway
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 'The Starshipit Order failed to update.: StarShipIt API
                    returned 400 Bad Request'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-session-only: true
      operationId: put-api-starshipit-update-order-sales-order-fulfillment
  /api/starshipit/integration-instances/{integration_instance}/packages:
    get:
      tags:
      - Starshipit
      summary: List Packages
      description: 'Paginated list of packages across all orders for this Starshipit
        integration instance. Each package is promoted out of its parent order''s
        `json_object.packages[]` array into its own row so packages are searchable
        by their per-package `tracking_number` (multi-package orders carry distinct
        tracking numbers that the order-level tracking_number drops).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Supports Spatie QueryBuilder filtering, sorting, and pagination.


        Filters:

        - `filter[search]` — partial match across tracking_number, starshipit_package_id,
        carrier_service_name, and the parent order''s order_number

        - `filter[delivery_status]` — exact match on delivery status (e.g. Pending,
        InTransit, Delivered)

        - `filter[order_id]` — exact match on the local parent order id (starshipit_orders.id)

        - Advanced per-column operators are available for: id, tracking_number, starshipit_package_id,
        name, carrier_service_name, carrier_service_code, delivery_status, packaging_type,
        shipment_type, weight (numeric), label_created_date, created_at, updated_at
        (datetime)


        Allowed sorts: id, tracking_number, name, weight, delivery_status, carrier_service_name,
        packaging_type, shipment_type, label_created_date, created_at, updated_at,
        order (sorts by the related order number) (prefix with `-` for DESC; default
        `-id`).


        Pagination: `page` (default 1), `per_page` (default 10).


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        order_id:
                          type: integer
                        package_index:
                          type: integer
                        starshipit_package_id:
                          type: string
                        name:
                          type: string
                        weight:
                          type: number
                        height:
                          type: number
                        width:
                          type: number
                        length:
                          type: number
                        packaging_type:
                          type: string
                        carrier_service_code:
                          type: string
                        carrier_service_name:
                          type: string
                        tracking_number:
                          type: string
                        tracking_url:
                          type: string
                        delivery_status:
                          type: string
                        shipment_type:
                          type: string
                        label_created_date:
                          type: string
                        order:
                          type: object
                          properties:
                            id:
                              type: integer
                            order_number:
                              type: string
                            starshipit_order_id:
                              type: string
                            link_reference:
                              type: string
                            link_type_label:
                              type: string
                            link_id:
                              type: integer
                            link_route:
                              type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 9001
                    integration_instance_id: 2
                    order_id: 656
                    package_index: 0
                    starshipit_package_id: '778812'
                    name: Carton
                    weight: 1.5
                    height: 0.2
                    width: 0.3
                    length: 0.4
                    packaging_type: Box
                    carrier_service_code: eParcel
                    carrier_service_name: Australia Post eParcel
                    tracking_number: TRK-AU-1234567890
                    tracking_url: https://track.starshipit.com/track/TRK-AU-1234567890
                    delivery_status: Delivered
                    shipment_type: Domestic
                    label_created_date: '2026-05-26T03:14:00+00:00'
                    order:
                      id: 656
                      order_number: SO-1234
                      starshipit_order_id: '12345'
                      link_reference: SO-1234
                      link_type_label: Starshipit Order
                      link_id: 656
                      link_route: /integrations/starshipit/2/orders/656
                    created_at: '2026-05-25T14:02:00+00:00'
                    updated_at: '2026-05-26T03:15:01+00:00'
                  current_page: 1
                  first_page_url: '{{protocol}}{{domain}}/api/starshipit/integration-instances/2/packages?page=1'
                  from: 1
                  last_page: 1
                  last_page_url: '{{protocol}}{{domain}}/api/starshipit/integration-instances/2/packages?page=1'
                  links: []
                  next_page_url: null
                  path: '{{protocol}}{{domain}}/api/starshipit/integration-instances/2/packages'
                  per_page: 10
                  prev_page_url: null
                  to: 1
                  total: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-starshipit-integration-instances-integration-instance-packages
  /api/starshipit/integration-instances/{integration_instance}/packages/{package}:
    get:
      tags:
      - Starshipit
      summary: Get Package
      description: 'Returns a single Starshipit package by its internal id, including
        its dimensions, carrier service, per-package tracking number/URL, delivery
        status, and a cross-link (`order`) back to the parent Starshipit order detail
        page. The raw package payload is always included as `json_object`.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: package
        in: path
        schema:
          type: integer
        required: true
        description: Internal StarshipitPackage ID
        example: '9001'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      order_id:
                        type: integer
                      package_index:
                        type: integer
                      starshipit_package_id:
                        type: string
                      name:
                        type: string
                      weight:
                        type: number
                      height:
                        type: number
                      width:
                        type: number
                      length:
                        type: number
                      packaging_type:
                        type: string
                      carrier_service_code:
                        type: string
                      carrier_service_name:
                        type: string
                      tracking_number:
                        type: string
                      tracking_url:
                        type: string
                      delivery_status:
                        type: string
                      shipment_type:
                        type: string
                      label_created_date:
                        type: string
                      order:
                        type: object
                        properties:
                          id:
                            type: integer
                          order_number:
                            type: string
                          starshipit_order_id:
                            type: string
                          link_reference:
                            type: string
                          link_type_label:
                            type: string
                          link_id:
                            type: integer
                          link_route:
                            type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      json_object:
                        type: object
                        properties:
                          package_id:
                            type: string
                          name:
                            type: string
                          weight:
                            type: number
                          height:
                            type: number
                          width:
                            type: number
                          length:
                            type: number
                          tracking_number:
                            type: string
                          carrier_service_code:
                            type: string
                          carrier_service_name:
                            type: string
                example:
                  data:
                    id: 9001
                    integration_instance_id: 2
                    order_id: 656
                    package_index: 0
                    starshipit_package_id: '778812'
                    name: Carton
                    weight: 1.5
                    height: 0.2
                    width: 0.3
                    length: 0.4
                    packaging_type: Box
                    carrier_service_code: eParcel
                    carrier_service_name: Australia Post eParcel
                    tracking_number: TRK-AU-1234567890
                    tracking_url: https://track.starshipit.com/track/TRK-AU-1234567890
                    delivery_status: Delivered
                    shipment_type: Domestic
                    label_created_date: '2026-05-26T03:14:00+00:00'
                    order:
                      id: 656
                      order_number: SO-1234
                      starshipit_order_id: '12345'
                      link_reference: SO-1234
                      link_type_label: Starshipit Order
                      link_id: 656
                      link_route: /integrations/starshipit/2/orders/656
                    created_at: '2026-05-25T14:02:00+00:00'
                    updated_at: '2026-05-26T03:15:01+00:00'
                    json_object:
                      package_id: '778812'
                      name: Carton
                      weight: 1.5
                      height: 0.2
                      width: 0.3
                      length: 0.4
                      tracking_number: TRK-AU-1234567890
                      carrier_service_code: eParcel
                      carrier_service_name: Australia Post eParcel
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Package not found for this instance
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-starshipit-integration-instances-integration-instance-packages-package
  /api/starshipit/integration-instances/{integration_instance}/shipping-methods:
    get:
      tags:
      - Starshipit
      summary: List Shipping Method Mappings
      description: 'Lists every distinct carrier + service pair observed on previously
        synced Starshipit orders for this integration instance, joined with any existing
        SKU shipping-method mapping. Stored-but-no-longer-observed mappings are also
        included.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Each service carries a stable `code` of the form `"{carrier}|{carrier_service_code}"`
        which is the key used by the map / bulk-map / unmap endpoints. `mapping` is
        null when the pair is not yet mapped.


        `sku_shipping_methods` lists the available (non-archived) SKU shipping methods
        to map onto, ordered by full name.


        This endpoint takes no query parameters.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Starshipit integration instance ID
        example: '6'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      services:
                        type: array
                        items:
                          type: object
                          properties:
                            code:
                              type: string
                            carrier:
                              type: string
                            carrier_name:
                              type: string
                            carrier_service_code:
                              type: string
                            order_count:
                              type: integer
                            mapping:
                              type: object
                              properties:
                                id:
                                  type: integer
                                shipping_method_id:
                                  type: integer
                                shipping_method_name:
                                  type: string
                                shipping_method_type:
                                  type: string
                      sku_shipping_methods:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            full_name:
                              type: string
                            type:
                              type: string
                example:
                  data:
                    services:
                    - code: AusPost|eParcel
                      carrier: AusPost
                      carrier_name: Australia Post
                      carrier_service_code: eParcel
                      order_count: 128
                      mapping:
                        id: 41
                        shipping_method_id: 7
                        shipping_method_name: Australia Post - eParcel
                        shipping_method_type: standard
                    - code: DHL|Express
                      carrier: DHL
                      carrier_name: DHL Express
                      carrier_service_code: Express
                      order_count: 16
                      mapping: null
                    sku_shipping_methods:
                    - id: 7
                      name: eParcel
                      full_name: Australia Post - eParcel
                      type: standard
                    - id: 8
                      name: Express
                      full_name: DHL Express - Express
                      type: express
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-starshipit-integration-instances-integration-instance-shipping-methods
  /api/starshipit/integration-instances/{integration_instance}/shipping-methods/export:
    get:
      tags:
      - Starshipit
      summary: Export Mappings (CSV)
      description: 'Downloads the current carrier/service-to-SKU-shipping-method mappings
        as a CSV file (Content-Type `text/csv`, Content-Disposition `attachment`).
        Filename: `starshipit-shipping-methods-{instanceId}-{YYYY-MM-DD}.csv`.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Columns: `code`, `carrier`, `carrier_name`, `carrier_service_code`, `order_count`,
        `shipping_method_id`, `shipping_method_name`. Rows for unmapped pairs leave
        `shipping_method_id` / `shipping_method_name` blank.


        This is the template for the Import endpoint: export, edit the shipping method
        columns, then re-import. Response is a file download, not JSON.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Starshipit integration instance ID
        example: '6'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: text/csv
          content:
            text/plain:
              schema:
                type: string
                example: 'code,carrier,carrier_name,carrier_service_code,order_count,shipping_method_id,shipping_method_name

                  AusPost|eParcel,AusPost,Australia Post,eParcel,128,7,Australia Post
                  - eParcel

                  DHL|Express,DHL,DHL Express,Express,16,,

                  '
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-starshipit-integration-instances-integration-instance-shipping-methods-export
  /api/starshipit/integration-instances/{integration_instance}/shipping-methods/import:
    post:
      tags:
      - Starshipit
      summary: Import Mappings (CSV)
      description: 'Bulk-applies carrier/service-to-SKU-shipping-method mappings from
        an uploaded CSV (multipart/form-data, field `file`).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Per row the target SKU shipping method is resolved by `shipping_method_id`
        first (authoritative), then by `shipping_method_name` (case-insensitive, matches
        the method name or full name). A row with both shipping-method columns blank
        removes the mapping for that code. The `code` is taken from the `code` column,
        or derived from `carrier` + `carrier_service_code` as `"{carrier}|{carrier_service_code}"`.


        Returns a summary of created / updated / deleted counts plus a list of human-readable
        per-line `errors` (e.g. unknown shipping method, missing code). Rows with
        errors are skipped; valid rows still apply.


        Validation: `file` is required, must be a file of type csv or txt, max 2048
        KB.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                file:
                  type: string
                  description: 'CSV file to import. Required. Allowed types: csv,
                    txt (mimes:csv,txt). Max size 2048 KB. Must include a header row
                    with a `code` column (or `carrier` + `carrier_service_code` columns)
                    plus a `shipping_method_id` (authoritative) and/or `shipping_method_name`
                    (fallback) column. Leave both shipping-method columns blank on
                    a row to REMOVE that mapping.'
                  format: binary
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Starshipit integration instance ID
        example: '6'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      created:
                        type: integer
                      updated:
                        type: integer
                      deleted:
                        type: integer
                      errors:
                        type: array
                        items:
                          type: string
                example:
                  message: Import processed
                  data:
                    created: 3
                    updated: 5
                    deleted: 1
                    errors:
                    - 'Line 9: shipping method id ''9999'' not found'
                    - 'Line 12: missing code (and carrier/service)'
        '422':
          description: Unprocessable Content
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      file:
                        type: array
                        items:
                          type: string
                example:
                  message: The file field is required.
                  errors:
                    file:
                    - The file field is required.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-starshipit-integration-instances-integration-instance-shipping-methods-import
  /api/starshipit/integration-instances/{integration_instance}/shipping-methods/map:
    put:
      tags:
      - Starshipit
      summary: Map Carrier/Service
      description: 'Creates or updates the mapping for a single carrier/service `code`
        to a SKU shipping method.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Request body:

        - `code` (string, required, max 255) — the carrier/service code, format `"{carrier}|{carrier_service_code}"`

        - `shipping_method_id` (integer, required) — must exist in `shipping_methods`


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                code:
                  type: string
                shipping_method_id:
                  type: integer
              example:
                code: AusPost|eParcel
                shipping_method_id: 7
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Starshipit integration instance ID
        example: '6'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      code:
                        type: string
                      shipping_method_id:
                        type: integer
                example:
                  message: Mapping saved
                  data:
                    id: 41
                    code: AusPost|eParcel
                    shipping_method_id: 7
        '422':
          description: Unprocessable Content
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      shipping_method_id:
                        type: array
                        items:
                          type: string
                example:
                  message: The selected shipping method id is invalid.
                  errors:
                    shipping_method_id:
                    - The selected shipping method id is invalid.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: put-api-starshipit-integration-instances-integration-instance-shipping-methods-map
  /api/starshipit/integration-instances/{integration_instance}/shipping-methods/bulk-map:
    put:
      tags:
      - Starshipit
      summary: Bulk Map Carrier/Services
      description: 'Maps many carrier/service codes to a single SKU shipping method
        in one call (used by the bulk-select "Apply to selected" action on the mappings
        page). Codes are de-duplicated and blank entries skipped.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Request body:

        - `codes` (array of string, required, min 1; each max 255) — the carrier/service
        codes to map, format `"{carrier}|{carrier_service_code}"`

        - `shipping_method_id` (integer, required) — must exist in `shipping_methods`


        Returns the number of mappings written.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                codes:
                  type: array
                  items:
                    type: string
                shipping_method_id:
                  type: integer
              example:
                codes:
                - AusPost|eParcel
                - DHL|Express
                - FedEx|Priority
                shipping_method_id: 7
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Starshipit integration instance ID
        example: '6'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      updated_count:
                        type: integer
                example:
                  message: 3 mapping(s) saved
                  data:
                    updated_count: 3
        '422':
          description: Unprocessable Content
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      codes:
                        type: array
                        items:
                          type: string
                example:
                  message: The codes field is required.
                  errors:
                    codes:
                    - The codes field is required.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: put-api-starshipit-integration-instances-integration-instance-shipping-methods-bulk-map
  /api/starshipit/integration-instances/{integration_instance}/shipping-methods/map/{code}:
    delete:
      tags:
      - Starshipit
      summary: Unmap Carrier/Service
      description: 'Removes the mapping for a single carrier/service `code`. The `code`
        path segment may contain a pipe and other special characters (the route is
        registered with `where(''code'', ''.*'')`).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Returns 404 if no mapping exists for that code on this instance.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: integer
        required: true
        description: Starshipit integration instance ID
        example: '6'
      - name: code
        in: path
        schema:
          type: string
        required: true
        description: Carrier/service code to unmap, format "{carrier}|{carrier_service_code}".
          May contain a pipe; the route allows any characters.
        example: AusPost|eParcel
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Mapping removed
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Mapping not found
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: delete-api-starshipit-integration-instances-integration-instance-shipping-methods-map-code
  /api/starshipit/integration-instances/{integration_instance}/webhook-events:
    get:
      tags:
      - Starshipit
      summary: List Webhook Events
      description: 'Returns a paginated list of inbound webhook events received from
        StarShipIt for this instance, newest first.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Each event records the raw payload, whether its signature was valid, the extracted
        `order_number` / `tracking_number` / `tracking_status`, and its processing
        state: `processed` + `processed_at` when handled successfully, or `error_message`
        when processing failed (failed events can be re-queued via the retry endpoint).


        `tracking_status` values: `Printed`, `Dispatched`, `InTransit`, `OutForDelivery`,
        `Delivered`, `PickupInStore`, `AttemptedDelivery`, `Exception`, `AwaitingCollection`,
        `Cancelled`, `Manifested`, `ReturnPickupPrinted`, `ReturnDropoffPrinted`,
        `DroppedOff`, `ReturnLink`, `ReturnLabel`.


        Filtering uses operator-aware syntax: `filter[column.operator]=value` (text
        operators: `contains`, `does_not_contain`, `is`, `is_not`, `is_one_of`, `is_not_one_of`,
        `starts_with`, `ends_with`, `is_empty`, `is_not_empty`; datetime operators
        include `between`). A bare `filter[column]=value` acts as `is`.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        event_type:
                          type: string
                        tracking_status:
                          type: string
                        tracking_status_label:
                          type: string
                        tracking_status_color:
                          type: string
                        order_number:
                          type: string
                        tracking_number:
                          type: string
                        signature_valid:
                          type: boolean
                        payload:
                          type: object
                          properties:
                            order_number:
                              type: string
                            tracking_number:
                              type: string
                            tracking_status:
                              type: string
                            carrier_name:
                              type: string
                        processed:
                          type: boolean
                        processed_at:
                          type: string
                        error_message:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                    items:
                      type: object
                      properties:
                        url:
                          type: string
                          nullable: true
                        label:
                          type: string
                        active:
                          type: boolean
                  next_page_url:
                    type: string
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 9011
                    integration_instance_id: 2
                    event_type: tracking_updated
                    tracking_status: Delivered
                    tracking_status_label: Delivered
                    tracking_status_color: success
                    order_number: SO-1234
                    tracking_number: TRK-AU-1234567890
                    signature_valid: true
                    payload:
                      order_number: SO-1234
                      tracking_number: TRK-AU-1234567890
                      tracking_status: Delivered
                      carrier_name: Australia Post
                    processed: true
                    processed_at: '2026-07-05T08:01:11+00:00'
                    error_message: null
                    created_at: '2026-07-05T08:01:09+00:00'
                    updated_at: '2026-07-05T08:01:11+00:00'
                  - id: 9008
                    integration_instance_id: 2
                    event_type: tracking_updated
                    tracking_status: InTransit
                    tracking_status_label: In Transit
                    tracking_status_color: primary
                    order_number: SO-1230
                    tracking_number: TRK-AU-0009988776
                    signature_valid: true
                    payload:
                      order_number: SO-1230
                      tracking_number: TRK-AU-0009988776
                      tracking_status: InTransit
                    processed: false
                    processed_at: null
                    error_message: No matching order found for order_number SO-1230
                    created_at: '2026-07-04T21:14:33+00:00'
                    updated_at: '2026-07-04T21:14:35+00:00'
                  current_page: 1
                  first_page_url: https://example.sku.io/api/starshipit/integration-instances/2/webhook-events?page=1
                  from: 1
                  last_page: 34
                  last_page_url: https://example.sku.io/api/starshipit/integration-instances/2/webhook-events?page=34
                  links:
                  - url: null
                    label: '&laquo; Previous'
                    active: false
                  - url: https://example.sku.io/api/starshipit/integration-instances/2/webhook-events?page=1
                    label: '1'
                    active: true
                  - url: https://example.sku.io/api/starshipit/integration-instances/2/webhook-events?page=2
                    label: Next &raquo;
                    active: false
                  next_page_url: https://example.sku.io/api/starshipit/integration-instances/2/webhook-events?page=2
                  path: https://example.sku.io/api/starshipit/integration-instances/2/webhook-events
                  per_page: 15
                  prev_page_url: null
                  to: 15
                  total: 502
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-starshipit-integration-instances-integration-instance-webhook-events
  /api/starshipit/integration-instances/{integration_instance}/webhook-events/{webhook_event}:
    get:
      tags:
      - Starshipit
      summary: Get Webhook Event
      description: 'Returns a single inbound webhook event, including the full raw
        payload StarShipIt delivered, the signature verification result, and the processing
        outcome (`processed` / `processed_at` on success, `error_message` on failure).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Returns 404 when the event does not exist or belongs to a different integration
        instance.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: webhook_event
        in: path
        schema:
          type: integer
        required: true
        example: '9011'
        description: The webhook event ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      event_type:
                        type: string
                      tracking_status:
                        type: string
                      tracking_status_label:
                        type: string
                      tracking_status_color:
                        type: string
                      order_number:
                        type: string
                      tracking_number:
                        type: string
                      signature_valid:
                        type: boolean
                      payload:
                        type: object
                        properties:
                          order_number:
                            type: string
                          tracking_number:
                            type: string
                          tracking_status:
                            type: string
                          carrier_name:
                            type: string
                          carrier_service:
                            type: string
                      processed:
                        type: boolean
                      processed_at:
                        type: string
                      error_message:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 9011
                    integration_instance_id: 2
                    event_type: tracking_updated
                    tracking_status: Delivered
                    tracking_status_label: Delivered
                    tracking_status_color: success
                    order_number: SO-1234
                    tracking_number: TRK-AU-1234567890
                    signature_valid: true
                    payload:
                      order_number: SO-1234
                      tracking_number: TRK-AU-1234567890
                      tracking_status: Delivered
                      carrier_name: Australia Post
                      carrier_service: Parcel Post
                    processed: true
                    processed_at: '2026-07-05T08:01:11+00:00'
                    error_message: null
                    created_at: '2026-07-05T08:01:09+00:00'
                    updated_at: '2026-07-05T08:01:11+00:00'
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Event not found
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-starshipit-integration-instances-integration-instance-webhook-events-webhook-event
  /api/starshipit/integration-instances/{integration_instance}/webhook-events/{webhook_event}/retry:
    post:
      tags:
      - Starshipit
      summary: Retry Webhook Event
      description: 'Queues a background job to reprocess a webhook event — typically
        one that failed and recorded an `error_message`. No request body.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Reprocessing re-applies the stored payload as if the webhook had just arrived:
        the event is matched to a cached order by order number or tracking number,
        the tracking status is applied (which can update order status, record fulfillment
        shipment, and push tracking to the sales channel), and the event is marked
        `processed` on success or gets a fresh `error_message` on failure. The job
        retries up to 5 times with increasing backoff.


        Retrying is safe: events already marked as processed are skipped by the background
        job, so re-queuing a successful event is a no-op.


        Returns 404 when the event does not exist or belongs to a different integration
        instance.


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: webhook_event
        in: path
        schema:
          type: integer
        required: true
        example: '9008'
        description: The webhook event ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Webhook event queued for retry
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Event not found
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-starshipit-integration-instances-integration-instance-webhook-events-webhook-event-retry
  /api/api-shipping-providers:
    post:
      tags:
      - API Shipping Provider
      summary: Create Provider
      description: 'Create a new API Shipping Provider integration instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Request Body Fields:**


        | Field | Type | Required | Description |

        |-------|------|----------|-------------|

        | `name` | string | **Yes** | Display name for the provider (max 255 chars)
        |


        **Post-Request Script:**


        Automatically sets the {{provider-id}} collection variable on success.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
              example:
                name: My 3PL Provider
      parameters: []
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      integration_id:
                        type: integer
                      connection_settings:
                        type: string
                        nullable: true
                      integration_settings:
                        type: string
                        nullable: true
                      sync_status:
                        type: string
                        nullable: true
                      is_automatic_sync_enabled:
                        type: boolean
                      warehouse_mappings:
                        type: array
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 1
                    name: My 3PL Provider
                    integration_id: 15
                    connection_settings: null
                    integration_settings: null
                    sync_status: null
                    is_automatic_sync_enabled: false
                    warehouse_mappings: []
                    created_at: '2026-01-15T10:30:00.000000Z'
                    updated_at: '2026-01-15T10:30:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-api-shipping-providers
  /api/api-shipping-providers/{provider-id}:
    get:
      tags:
      - API Shipping Provider
      summary: Show Provider
      description: 'Show a single shipping provider integration instance by ID.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **URL Parameters:**


        | Parameter | Type | Description |

        |-----------|------|-------------|

        | `id` | integer | The integration instance ID |'
      parameters:
      - name: provider-id
        in: path
        schema:
          type: string
        required: true
        description: The provider ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      integration_id:
                        type: integer
                      connection_settings:
                        type: string
                        nullable: true
                      integration_settings:
                        type: object
                        properties:
                          ignore_fulfillments_without_tracking:
                            type: boolean
                      sync_status:
                        type: string
                        nullable: true
                      is_automatic_sync_enabled:
                        type: boolean
                      warehouse_mappings:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            warehouse_id:
                              type: integer
                            external_warehouse_id:
                              type: string
                            warehouse:
                              type: object
                              properties:
                                id:
                                  type: integer
                                name:
                                  type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 1
                    name: My 3PL Provider
                    integration_id: 15
                    connection_settings: null
                    integration_settings:
                      ignore_fulfillments_without_tracking: false
                    sync_status: null
                    is_automatic_sync_enabled: false
                    warehouse_mappings:
                    - id: 1
                      warehouse_id: 5
                      external_warehouse_id: WH-001
                      warehouse:
                        id: 5
                        name: Main Warehouse
                    created_at: '2026-01-15T10:30:00.000000Z'
                    updated_at: '2026-01-15T10:30:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-api-shipping-providers-provider-id
    put:
      tags:
      - API Shipping Provider
      summary: Update Provider
      description: 'Update a shipping provider integration instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Request Body Fields:**


        | Field | Type | Required | Description |

        |-------|------|----------|-------------|

        | `name` | string | No | Display name for the provider |

        | `integration_settings` | object | No | Provider-specific settings |

        | `integration_settings.ignore_fulfillments_without_tracking` | boolean |
        No | Skip fulfillments that lack tracking numbers |

        | `warehouse_mappings` | array | No | Warehouse mapping array |

        | `warehouse_mappings.*.warehouse_id` | integer | Required with warehouse_mappings
        | SKU.io warehouse ID |

        | `warehouse_mappings.*.external_warehouse_id` | string | Required with warehouse_mappings
        | External warehouse identifier |'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                integration_settings:
                  type: object
                  properties:
                    ignore_fulfillments_without_tracking:
                      type: boolean
                warehouse_mappings:
                  type: array
                  items:
                    type: object
                    properties:
                      warehouse_id:
                        type: integer
                      external_warehouse_id:
                        type: string
              example:
                name: Updated Provider Name
                integration_settings:
                  ignore_fulfillments_without_tracking: true
                warehouse_mappings:
                - warehouse_id: 5
                  external_warehouse_id: WH-001
                - warehouse_id: 8
                  external_warehouse_id: WH-002
      parameters:
      - name: provider-id
        in: path
        schema:
          type: string
        required: true
        description: The provider ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      integration_id:
                        type: integer
                      connection_settings:
                        type: string
                        nullable: true
                      integration_settings:
                        type: object
                        properties:
                          ignore_fulfillments_without_tracking:
                            type: boolean
                      sync_status:
                        type: string
                        nullable: true
                      is_automatic_sync_enabled:
                        type: boolean
                      warehouse_mappings:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            warehouse_id:
                              type: integer
                            external_warehouse_id:
                              type: string
                            warehouse:
                              type: object
                              properties:
                                id:
                                  type: integer
                                name:
                                  type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 1
                    name: Updated Provider Name
                    integration_id: 15
                    connection_settings: null
                    integration_settings:
                      ignore_fulfillments_without_tracking: true
                    sync_status: null
                    is_automatic_sync_enabled: false
                    warehouse_mappings:
                    - id: 1
                      warehouse_id: 5
                      external_warehouse_id: WH-001
                      warehouse:
                        id: 5
                        name: Main Warehouse
                    created_at: '2026-01-15T10:30:00.000000Z'
                    updated_at: '2026-01-15T12:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-api-shipping-providers-provider-id
    delete:
      tags:
      - API Shipping Provider
      summary: Delete Provider
      description: 'Delete a shipping provider integration instance and all associated
        data.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **URL Parameters:**


        | Parameter | Type | Description |

        |-----------|------|-------------|

        | `integrationInstance` | integer | The integration instance ID |


        **Response:** HTTP 204 No Content on success.'
      parameters:
      - name: provider-id
        in: path
        schema:
          type: string
        required: true
        description: The provider ID.
      responses:
        '204':
          description: No Content
          content:
            text/plain:
              schema:
                type: string
                example: ''
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-api-shipping-providers-provider-id
  /api/api-shipping-providers/{provider-id}/dashboard:
    get:
      tags:
      - API Shipping Provider
      summary: Get Dashboard Stats
      description: 'Get dashboard statistics for a shipping provider instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **URL Parameters:**


        | Parameter | Type | Description |

        |-----------|------|-------------|

        | `id` | integer | The integration instance ID |


        **Response:** Returns aggregated stats for the provider.'
      parameters:
      - name: provider-id
        in: path
        schema:
          type: string
        required: true
        description: The provider ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      total_events:
                        type: integer
                      processed_events:
                        type: integer
                      failed_events:
                        type: integer
                      pending_events:
                        type: integer
                      skipped_events:
                        type: integer
                example:
                  data:
                    total_events: 150
                    processed_events: 120
                    failed_events: 10
                    pending_events: 15
                    skipped_events: 5
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-api-shipping-providers-provider-id-dashboard
  /api/api-shipping-providers/{provider-id}/tokens:
    post:
      tags:
      - API Shipping Provider
      summary: Generate Token
      description: 'Generate a new API token for a shipping provider instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Request Body Fields:**


        | Field | Type | Required | Description |

        |-------|------|----------|-------------|

        | `name` | string | **Yes** | Descriptive name for the token (max 255 chars)
        |


        **Important:** Store the token securely after generation - the plain text
        token cannot be retrieved again.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
              example:
                name: Production Token
      parameters:
      - name: provider-id
        in: path
        schema:
          type: string
        required: true
        description: The provider ID.
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      token:
                        type: string
                      name:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    token: 1|laravel_sanctum_abcdefghijklmnop1234567890
                    name: Production Token
                  message: Token generated successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-api-shipping-providers-provider-id-tokens
    get:
      tags:
      - API Shipping Provider
      summary: List Tokens
      description: 'List all API tokens for a shipping provider instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **URL Parameters:**


        | Parameter | Type | Description |

        |-----------|------|-------------|

        | `id` | integer | The integration instance ID |


        **Note:** Token values are not returned - only metadata (name, abilities,
        last used, created at).'
      parameters:
      - name: provider-id
        in: path
        schema:
          type: string
        required: true
        description: The provider ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        abilities:
                          type: array
                          items:
                            type: string
                        last_used_at:
                          type: string
                        created_at:
                          type: string
                example:
                  data:
                  - id: 1
                    name: Production Token
                    abilities:
                    - '*'
                    last_used_at: '2026-01-20T08:00:00.000000Z'
                    created_at: '2026-01-15T10:30:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-api-shipping-providers-provider-id-tokens
  /api/api-shipping-providers/{provider-id}/tokens/{token-id}:
    delete:
      tags:
      - API Shipping Provider
      summary: Revoke Token
      description: 'Revoke a specific API token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **URL Parameters:**


        | Parameter | Type | Description |

        |-----------|------|-------------|

        | `id` | integer | The integration instance ID |

        | `tokenId` | integer | The token ID to revoke |


        **Note:** Once revoked, the token can no longer be used for authentication.'
      parameters:
      - name: provider-id
        in: path
        schema:
          type: string
        required: true
        description: The provider ID.
      - name: token-id
        in: path
        schema:
          type: string
        required: true
        description: The token ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Token revoked successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-api-shipping-providers-provider-id-tokens-token-id
  /api/api-shipping-providers/{provider-id}/inbound-events:
    get:
      tags:
      - API Shipping Provider
      summary: List Inbound Events (Paginated)
      description: 'List paginated inbound events for a shipping provider instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **URL Parameters:**


        | Parameter | Type | Description |

        |-----------|------|-------------|

        | `id` | integer | The integration instance ID |


        **Query Parameters:**


        | Parameter | Type | Description |

        |-----------|------|-------------|

        | `per_page` | integer | Items per page (default: 10) |

        | `page` | integer | Page number |

        | `filter[status]` | string | Filter by processing_status |

        | `filter[endpoint]` | string | Filter by endpoint |

        | `filter[linked_resource]` | string | yes/no - filter by linked resource
        presence |

        | `filter[date_from]` | string | Filter from date (YYYY-MM-DD) |

        | `filter[date_to]` | string | Filter to date (YYYY-MM-DD) |

        | `filter[search]` | string | Advanced search across ID, unique_id, linked
        resource |

        | `sort` | string | Sort field (prefix with - for descending) |'
      parameters:
      - name: per_page
        in: query
        schema:
          type: integer
        description: 'Items per page (default: 10)'
        example: '10'
      - name: page
        in: query
        schema:
          type: integer
        description: Page number
        example: '1'
      - name: provider-id
        in: path
        schema:
          type: string
        required: true
        description: The provider ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        endpoint:
                          type: string
                        http_method:
                          type: string
                        processing_status:
                          type: string
                        ip_address:
                          type: string
                        user_agent:
                          type: string
                        request_payload:
                          type: object
                          properties:
                            lines:
                              type: array
                              items:
                                type: object
                                properties:
                                  id:
                                    type: integer
                                  quantity_fulfilled:
                                    type: integer
                            tracking_number:
                              type: string
                            shipping_method:
                              type: string
                        response_payload:
                          type: object
                          properties:
                            message:
                              type: string
                        request_headers:
                          type: object
                          properties:
                            content-type:
                              type: array
                              items:
                                type: string
                            authorization:
                              type: array
                              items:
                                type: string
                        linked_resource_type:
                          type: string
                        linked_resource_id:
                          type: integer
                        unique_id:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                        processed_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                  first_page_url:
                    type: string
                  next_page_url:
                    type: string
                  prev_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                example:
                  data:
                  - id: 42
                    integration_instance_id: 1
                    endpoint: 3pl.orders.fulfill
                    http_method: POST
                    processing_status: success
                    ip_address: 203.0.113.10
                    user_agent: D3-Logistics/1.0
                    request_payload:
                      lines:
                      - id: 88
                        quantity_fulfilled: 5
                      tracking_number: TRACK123456
                      shipping_method: FedEx Ground
                    response_payload:
                      message: Order fulfillment processed successfully.
                    request_headers:
                      content-type:
                      - application/json
                      authorization:
                      - '[REDACTED]'
                    linked_resource_type: App\Models\SalesOrderFulfillment
                    linked_resource_id: 88
                    unique_id: null
                    created_at: '2026-06-12T22:48:00.000000Z'
                    processed_at: '2026-06-12T22:48:00.000000Z'
                  current_page: 1
                  last_page: 13
                  per_page: 10
                  total: 124
                  from: 1
                  to: 10
                  first_page_url: '{{protocol}}{{domain}}/api/api-shipping-providers/1/inbound-events?page=1'
                  next_page_url: '{{protocol}}{{domain}}/api/api-shipping-providers/1/inbound-events?page=2'
                  prev_page_url: null
                  path: '{{protocol}}{{domain}}/api/api-shipping-providers/1/inbound-events'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-api-shipping-providers-provider-id-inbound-events
  /api/api-shipping-providers/{provider-id}/inbound-events/stats:
    get:
      tags:
      - API Shipping Provider
      summary: Get Inbound Event Stats
      description: 'Get inbound event statistics and distinct endpoints for a shipping
        provider instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **URL Parameters:**


        | Parameter | Type | Description |

        |-----------|------|-------------|

        | `id` | integer | The integration instance ID |


        **Response:** Returns counts by status and a list of distinct endpoints.'
      parameters:
      - name: provider-id
        in: path
        schema:
          type: string
        required: true
        description: The provider ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      total:
                        type: integer
                      success:
                        type: integer
                      error:
                        type: integer
                      endpoints:
                        type: array
                        items:
                          type: string
                example:
                  data:
                    total: 124
                    success: 118
                    error: 6
                    endpoints:
                    - 3pl.products.index
                    - 3pl.orders.index
                    - 3pl.orders.fulfill
                    - 3pl.inventory-adjustments.store
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-api-shipping-providers-provider-id-inbound-events-stats
  /api/api-shipping-providers/inbound-events/{event-id}:
    get:
      tags:
      - API Shipping Provider
      summary: Show Inbound Event
      description: 'Show a single inbound event with full payload details.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **URL Parameters:**


        | Parameter | Type | Description |

        |-----------|------|-------------|

        | `eventId` | integer | The inbound event ID |


        **Note:** This endpoint is not scoped to a provider instance since event IDs
        are globally unique.'
      parameters:
      - name: event-id
        in: path
        schema:
          type: string
        required: true
        description: The event ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      endpoint:
                        type: string
                      http_method:
                        type: string
                      processing_status:
                        type: string
                      ip_address:
                        type: string
                      user_agent:
                        type: string
                      request_payload:
                        type: object
                        properties:
                          lines:
                            type: array
                            items:
                              type: object
                              properties:
                                id:
                                  type: integer
                                quantity_fulfilled:
                                  type: integer
                          tracking_number:
                            type: string
                          shipping_method:
                            type: string
                      response_payload:
                        type: object
                        properties:
                          message:
                            type: string
                      request_headers:
                        type: object
                        properties:
                          content-type:
                            type: array
                            items:
                              type: string
                          authorization:
                            type: array
                            items:
                              type: string
                      linked_resource_type:
                        type: string
                      linked_resource_id:
                        type: integer
                      unique_id:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      processed_at:
                        type: string
                example:
                  data:
                    id: 42
                    integration_instance_id: 1
                    endpoint: 3pl.orders.fulfill
                    http_method: POST
                    processing_status: success
                    ip_address: 203.0.113.10
                    user_agent: D3-Logistics/1.0
                    request_payload:
                      lines:
                      - id: 88
                        quantity_fulfilled: 5
                      tracking_number: TRACK123456
                      shipping_method: FedEx Ground
                    response_payload:
                      message: Order fulfillment processed successfully.
                    request_headers:
                      content-type:
                      - application/json
                      authorization:
                      - '[REDACTED]'
                    linked_resource_type: App\Models\SalesOrderFulfillment
                    linked_resource_id: 88
                    unique_id: null
                    created_at: '2026-06-12T22:48:00.000000Z'
                    processed_at: '2026-06-12T22:48:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-api-shipping-providers-inbound-events-event-id
  /api/api-shipping-providers/inbound-events/bulk-delete:
    delete:
      tags:
      - API Shipping Provider
      summary: Bulk Delete Events
      description: 'Bulk delete multiple inbound events.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Request Body Fields:**


        | Field | Type | Required | Description |

        |-------|------|----------|-------------|

        | `ids` | array | **Yes** | Array of event IDs to delete (min: 1) |

        | `ids.*` | integer | **Yes** | Individual event ID |'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 3 event(s) deleted.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: delete-api-api-shipping-providers-inbound-events-bulk-delete
  /api/api-shipping-providers/{provider-id}/inbound-events/delete-all:
    delete:
      tags:
      - API Shipping Provider
      summary: Delete All Events for Instance
      description: 'Delete all inbound events for a shipping provider instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **URL Parameters:**


        | Parameter | Type | Description |

        |-----------|------|-------------|

        | `id` | integer | The integration instance ID |


        **Warning:** This is a destructive operation that removes all events.'
      parameters:
      - name: provider-id
        in: path
        schema:
          type: string
        required: true
        description: The provider ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 42 event(s) deleted.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-api-shipping-providers-provider-id-inbound-events-delete-all
  /api/shippit/test:
    post:
      tags:
      - Shippit
      summary: Test Connection
      description: 'Validates a Shippit API key without saving a connection. Shippit
        is a courier aggregator; this probes the supplied key against Shippit''s merchant
        endpoint and returns the merchant profile it resolves to, so you can confirm
        the key is correct before creating an instance.


        Body fields:

        - api_key (string, required): the Shippit API key to validate. Minimum 8 characters.

        - environment (string, optional): which Shippit environment the key belongs
        to, either "production" or "sandbox". Defaults to "production".


        Returns 200 with the resolved merchant name and company/contact details when
        the key is accepted. Returns 422 with a "code" of "invalid_key" when Shippit
        rejects the key, or "api_error" when Shippit could not be reached. Returns
        422 with field errors when the request body itself is invalid.


        Authentication: Requires a Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                api_key:
                  type: string
                environment:
                  type: string
              example:
                api_key: sku_live_9f2c1a7b4e6d0c3a8f5b2e91
                environment: production
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      merchant:
                        type: object
                        properties:
                          name:
                            type: string
                          company_name:
                            type: string
                          contact_name:
                            type: string
                  message:
                    type: string
                example:
                  data:
                    merchant:
                      name: Acme Fulfillment
                      company_name: Acme Fulfillment Pty Ltd
                      contact_name: Jordan Blake
                  message: Connection successful
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 422 Invalid API Key
                  value:
                    message: Invalid API key
                    code: invalid_key
                example-1:
                  summary: 422 Validation Error
                  value:
                    message: The Shippit API key is required.
                    errors:
                      api_key:
                      - The Shippit API key is required.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-shippit-test
  /api/shippit/instances:
    post:
      tags:
      - Shippit
      summary: Create Integration Instance
      description: 'Creates and connects a new Shippit integration instance for the
        current account, then returns it together with a live dashboard summary (merchant
        profile, order-state counts, courier and warehouse-mapping counts, and the
        webhook URL to paste into your Shippit account).


        Body fields:

        - name (string, required): a label for this connection. Max 255 characters.

        - api_key (string, required): the Shippit API key. Minimum 8 characters.

        - environment (string, optional): "production" or "sandbox". Defaults to "production".

        - auto_book (boolean, optional): automatically book shipments with Shippit.
        Defaults to true.

        - record_shipping_costs (boolean, optional): capture Shippit shipping costs
        against orders. Defaults to true.

        - default_courier_type (string, optional, nullable): default Shippit courier
        type to request, e.g. "standard" or "express". Max 100 characters.


        Returns 201 with the created instance and its dashboard summary. Returns 422
        with field errors when validation fails.


        Authentication: Requires a Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                api_key:
                  type: string
                environment:
                  type: string
                auto_book:
                  type: boolean
                record_shipping_costs:
                  type: boolean
                default_courier_type:
                  type: string
              example:
                name: Shippit AU
                api_key: sku_live_9f2c1a7b4e6d0c3a8f5b2e91
                environment: production
                auto_book: true
                record_shipping_costs: true
                default_courier_type: standard
      parameters: []
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      environment:
                        type: string
                      is_sandbox:
                        type: boolean
                      is_automatic_sync_enabled:
                        type: boolean
                      auto_book:
                        type: boolean
                      default_courier_type:
                        type: string
                      record_shipping_costs:
                        type: boolean
                      sync_start_date:
                        type: string
                      sync_status:
                        type: string
                      merchant:
                        type: object
                        properties:
                          name:
                            type: string
                          company_name:
                            type: string
                          contact_name:
                            type: string
                      order_state_counts:
                        type: object
                        properties:
                          ready_for_pickup:
                            type: integer
                          in_transit:
                            type: integer
                          delivered:
                            type: integer
                          cancelled:
                            type: integer
                      order_count:
                        type: integer
                      courier_count:
                        type: integer
                      warehouse_mapping_count:
                        type: integer
                      webhook_url:
                        type: string
                      webhook_subscribed_at:
                        type: string
                      last_webhook_at:
                        type: string
                      last_synced_at:
                        type: string
                      is_connected:
                        type: boolean
                      created_at:
                        type: string
                      updated_at:
                        type: string
                  merchant:
                    type: object
                    properties:
                      name:
                        type: string
                      company_name:
                        type: string
                      contact_name:
                        type: string
                  order_state_counts:
                    type: object
                    properties:
                      ready_for_pickup:
                        type: integer
                      in_transit:
                        type: integer
                      delivered:
                        type: integer
                      cancelled:
                        type: integer
                  order_count:
                    type: integer
                  courier_count:
                    type: integer
                  warehouse_mapping_count:
                    type: integer
                  last_webhook_at:
                    type: string
                  last_synced_at:
                    type: string
                  webhook_url:
                    type: string
                  webhook_subscribed_at:
                    type: string
                  is_connected:
                    type: boolean
                example:
                  data:
                    id: 12
                    name: Shippit AU
                    environment: production
                    is_sandbox: false
                    is_automatic_sync_enabled: true
                    auto_book: true
                    default_courier_type: standard
                    record_shipping_costs: true
                    sync_start_date: '2026-01-01T00:00:00+00:00'
                    sync_status: idle
                    merchant:
                      name: Acme Fulfillment
                      company_name: Acme Fulfillment Pty Ltd
                      contact_name: Jordan Blake
                    order_state_counts:
                      ready_for_pickup: 12
                      in_transit: 340
                      delivered: 1180
                      cancelled: 8
                    order_count: 1540
                    courier_count: 6
                    warehouse_mapping_count: 3
                    webhook_url: https://acme.sku.io/api/webhooks/shippit/abc123def456
                    webhook_subscribed_at: '2026-07-08T21:31:36+00:00'
                    last_webhook_at: '2026-07-07T22:14:05+00:00'
                    last_synced_at: '2026-07-08T01:30:00+00:00'
                    is_connected: true
                    created_at: '2026-03-10T09:00:00+00:00'
                    updated_at: '2026-07-08T01:30:01+00:00'
                  merchant:
                    name: Acme Fulfillment
                    company_name: Acme Fulfillment Pty Ltd
                    contact_name: Jordan Blake
                  order_state_counts:
                    ready_for_pickup: 12
                    in_transit: 340
                    delivered: 1180
                    cancelled: 8
                  order_count: 1540
                  courier_count: 6
                  warehouse_mapping_count: 3
                  last_webhook_at: '2026-07-07T22:14:05+00:00'
                  last_synced_at: '2026-07-08T01:30:00+00:00'
                  webhook_url: https://acme.sku.io/api/webhooks/shippit/abc123def456
                  webhook_subscribed_at: '2026-07-08T21:31:36+00:00'
                  is_connected: true
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      name:
                        type: array
                        items:
                          type: string
                example:
                  message: A name for this Shippit connection is required.
                  errors:
                    name:
                    - A name for this Shippit connection is required.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-shippit-instances
  /api/shippit/instances/{integration_instance}:
    get:
      tags:
      - Shippit
      summary: Get Integration Instance
      description: 'Returns a single Shippit integration instance together with a
        live dashboard summary: the resolved Shippit merchant profile, per-state order
        counts, total order/courier/warehouse-mapping counts, the webhook URL, and
        the last webhook and sync timestamps.


        Path parameter:

        - instance: the numeric ID of the Shippit integration instance.


        Returns 404 when the instance does not exist.


        Authentication: Requires a Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      environment:
                        type: string
                      is_sandbox:
                        type: boolean
                      is_automatic_sync_enabled:
                        type: boolean
                      auto_book:
                        type: boolean
                      default_courier_type:
                        type: string
                      record_shipping_costs:
                        type: boolean
                      sync_start_date:
                        type: string
                      sync_status:
                        type: string
                      merchant:
                        type: object
                        properties:
                          name:
                            type: string
                          company_name:
                            type: string
                          contact_name:
                            type: string
                      order_state_counts:
                        type: object
                        properties:
                          ready_for_pickup:
                            type: integer
                          in_transit:
                            type: integer
                          delivered:
                            type: integer
                          cancelled:
                            type: integer
                      order_count:
                        type: integer
                      courier_count:
                        type: integer
                      warehouse_mapping_count:
                        type: integer
                      webhook_url:
                        type: string
                      webhook_subscribed_at:
                        type: string
                      last_webhook_at:
                        type: string
                      last_synced_at:
                        type: string
                      is_connected:
                        type: boolean
                      created_at:
                        type: string
                      updated_at:
                        type: string
                  merchant:
                    type: object
                    properties:
                      name:
                        type: string
                      company_name:
                        type: string
                      contact_name:
                        type: string
                  order_state_counts:
                    type: object
                    properties:
                      ready_for_pickup:
                        type: integer
                      in_transit:
                        type: integer
                      delivered:
                        type: integer
                      cancelled:
                        type: integer
                  order_count:
                    type: integer
                  courier_count:
                    type: integer
                  warehouse_mapping_count:
                    type: integer
                  last_webhook_at:
                    type: string
                  last_synced_at:
                    type: string
                  webhook_url:
                    type: string
                  webhook_subscribed_at:
                    type: string
                  is_connected:
                    type: boolean
                example:
                  data:
                    id: 12
                    name: Shippit AU
                    environment: production
                    is_sandbox: false
                    is_automatic_sync_enabled: true
                    auto_book: true
                    default_courier_type: standard
                    record_shipping_costs: true
                    sync_start_date: '2026-01-01T00:00:00+00:00'
                    sync_status: idle
                    merchant:
                      name: Acme Fulfillment
                      company_name: Acme Fulfillment Pty Ltd
                      contact_name: Jordan Blake
                    order_state_counts:
                      ready_for_pickup: 12
                      in_transit: 340
                      delivered: 1180
                      cancelled: 8
                    order_count: 1540
                    courier_count: 6
                    warehouse_mapping_count: 3
                    webhook_url: https://acme.sku.io/api/webhooks/shippit/abc123def456
                    webhook_subscribed_at: '2026-07-08T21:31:36+00:00'
                    last_webhook_at: '2026-07-07T22:14:05+00:00'
                    last_synced_at: '2026-07-08T01:30:00+00:00'
                    is_connected: true
                    created_at: '2026-03-10T09:00:00+00:00'
                    updated_at: '2026-07-08T01:30:01+00:00'
                  merchant:
                    name: Acme Fulfillment
                    company_name: Acme Fulfillment Pty Ltd
                    contact_name: Jordan Blake
                  order_state_counts:
                    ready_for_pickup: 12
                    in_transit: 340
                    delivered: 1180
                    cancelled: 8
                  order_count: 1540
                  courier_count: 6
                  warehouse_mapping_count: 3
                  last_webhook_at: '2026-07-07T22:14:05+00:00'
                  last_synced_at: '2026-07-08T01:30:00+00:00'
                  webhook_url: https://acme.sku.io/api/webhooks/shippit/abc123def456
                  webhook_subscribed_at: '2026-07-08T21:31:36+00:00'
                  is_connected: true
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shippit-instances-integration-instance
    put:
      tags:
      - Shippit
      summary: Update Integration Instance
      description: 'Updates settings on an existing Shippit integration instance.
        All fields are optional — send only what should change; omitted fields are
        left untouched. Returns the updated instance with a refreshed dashboard summary.


        Path parameter:

        - instance: the numeric ID of the Shippit integration instance.


        Body fields (all optional):

        - name (string): connection label. Max 255 characters.

        - api_key (string): rotate the Shippit API key. Minimum 8 characters.

        - environment (string): "production" or "sandbox".

        - auto_book (boolean): automatically book shipments with Shippit.

        - record_shipping_costs (boolean): capture Shippit shipping costs against
        orders.

        - default_courier_type (string, nullable): default Shippit courier type. Max
        100 characters.

        - sync_start_date (date, nullable): earliest order date to sync (YYYY-MM-DD).

        - is_automatic_sync_enabled (boolean): whether scheduled syncs run automatically.


        Returns 422 with field errors when validation fails; 404 when the instance
        does not exist.


        Authentication: Requires a Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                api_key:
                  type: string
                environment:
                  type: string
                auto_book:
                  type: boolean
                record_shipping_costs:
                  type: boolean
                default_courier_type:
                  type: string
                sync_start_date:
                  type: string
                is_automatic_sync_enabled:
                  type: boolean
              example:
                name: Shippit AU (Primary)
                api_key: sku_live_1a2b3c4d5e6f7g8h9i0j1k2l
                environment: production
                auto_book: false
                record_shipping_costs: true
                default_courier_type: express
                sync_start_date: '2026-01-01'
                is_automatic_sync_enabled: true
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      environment:
                        type: string
                      is_sandbox:
                        type: boolean
                      is_automatic_sync_enabled:
                        type: boolean
                      auto_book:
                        type: boolean
                      default_courier_type:
                        type: string
                      record_shipping_costs:
                        type: boolean
                      sync_start_date:
                        type: string
                      sync_status:
                        type: string
                      merchant:
                        type: object
                        properties:
                          name:
                            type: string
                          company_name:
                            type: string
                          contact_name:
                            type: string
                      order_state_counts:
                        type: object
                        properties:
                          ready_for_pickup:
                            type: integer
                          in_transit:
                            type: integer
                          delivered:
                            type: integer
                          cancelled:
                            type: integer
                      order_count:
                        type: integer
                      courier_count:
                        type: integer
                      warehouse_mapping_count:
                        type: integer
                      webhook_url:
                        type: string
                      webhook_subscribed_at:
                        type: string
                      last_webhook_at:
                        type: string
                      last_synced_at:
                        type: string
                      is_connected:
                        type: boolean
                      created_at:
                        type: string
                      updated_at:
                        type: string
                  merchant:
                    type: object
                    properties:
                      name:
                        type: string
                      company_name:
                        type: string
                      contact_name:
                        type: string
                  order_state_counts:
                    type: object
                    properties:
                      ready_for_pickup:
                        type: integer
                      in_transit:
                        type: integer
                      delivered:
                        type: integer
                      cancelled:
                        type: integer
                  order_count:
                    type: integer
                  courier_count:
                    type: integer
                  warehouse_mapping_count:
                    type: integer
                  last_webhook_at:
                    type: string
                  last_synced_at:
                    type: string
                  webhook_url:
                    type: string
                  webhook_subscribed_at:
                    type: string
                  is_connected:
                    type: boolean
                example:
                  data:
                    id: 12
                    name: Shippit AU (Primary)
                    environment: production
                    is_sandbox: false
                    is_automatic_sync_enabled: true
                    auto_book: false
                    default_courier_type: express
                    record_shipping_costs: true
                    sync_start_date: '2026-01-01T00:00:00+00:00'
                    sync_status: idle
                    merchant:
                      name: Acme Fulfillment
                      company_name: Acme Fulfillment Pty Ltd
                      contact_name: Jordan Blake
                    order_state_counts:
                      ready_for_pickup: 12
                      in_transit: 340
                      delivered: 1180
                      cancelled: 8
                    order_count: 1540
                    courier_count: 6
                    warehouse_mapping_count: 3
                    webhook_url: https://acme.sku.io/api/webhooks/shippit/abc123def456
                    webhook_subscribed_at: '2026-07-08T21:31:36+00:00'
                    last_webhook_at: '2026-07-07T22:14:05+00:00'
                    last_synced_at: '2026-07-08T01:30:00+00:00'
                    is_connected: true
                    created_at: '2026-03-10T09:00:00+00:00'
                    updated_at: '2026-07-08T02:05:11+00:00'
                  merchant:
                    name: Acme Fulfillment
                    company_name: Acme Fulfillment Pty Ltd
                    contact_name: Jordan Blake
                  order_state_counts:
                    ready_for_pickup: 12
                    in_transit: 340
                    delivered: 1180
                    cancelled: 8
                  order_count: 1540
                  courier_count: 6
                  warehouse_mapping_count: 3
                  last_webhook_at: '2026-07-07T22:14:05+00:00'
                  last_synced_at: '2026-07-08T01:30:00+00:00'
                  webhook_url: https://acme.sku.io/api/webhooks/shippit/abc123def456
                  webhook_subscribed_at: '2026-07-08T21:31:36+00:00'
                  is_connected: true
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      environment:
                        type: array
                        items:
                          type: string
                example:
                  message: The environment must be either production or sandbox.
                  errors:
                    environment:
                    - The environment must be either production or sandbox.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: put-api-shippit-instances-integration-instance
    delete:
      tags:
      - Shippit
      summary: Delete Integration Instance
      description: 'Disconnects and removes a Shippit integration instance. The teardown
        runs asynchronously: this endpoint records the disconnect and hands the cascade
        cleanup (cached orders, couriers, webhook events, and related records) to
        a background job, then returns immediately with no content.


        Path parameter:

        - instance: the numeric ID of the Shippit integration instance.


        Returns 204 No Content on success. Returns 404 when the instance does not
        exist.


        Authentication: Requires a Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '204':
          description: No Content
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties: {}
                example: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-shippit-instances-integration-instance
  /api/shippit/instances/{integration_instance}/dashboard:
    get:
      tags:
      - Shippit
      summary: Get Dashboard Metrics
      description: 'Returns just the live dashboard summary for a Shippit integration
        instance — the lightweight refresh endpoint for the dashboard widget, without
        the full instance settings payload.


        Path parameter:

        - instance: the numeric ID of the Shippit integration instance.


        The response "data" object contains:

        - merchant: the resolved Shippit merchant profile (name, company_name, contact_name),
        or an "error" message when the merchant lookup failed.

        - environment: "production" or "sandbox".

        - order_state_counts: a map of Shippit order state to count.

        - order_count / courier_count / warehouse_mapping_count: totals for the instance.

        - auto_book / record_shipping_costs: current setting values.

        - last_webhook_at / last_synced_at: ISO-8601 timestamps, or null when never
        run.

        - webhook_url: the URL to paste into your Shippit account for webhook delivery.

        - is_connected: whether the Shippit merchant lookup currently succeeds.


        Returns 404 when the instance does not exist.


        Authentication: Requires a Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      merchant:
                        type: object
                        properties:
                          name:
                            type: string
                          company_name:
                            type: string
                          contact_name:
                            type: string
                      environment:
                        type: string
                      order_state_counts:
                        type: object
                        properties:
                          ready_for_pickup:
                            type: integer
                          in_transit:
                            type: integer
                          delivered:
                            type: integer
                          cancelled:
                            type: integer
                      order_count:
                        type: integer
                      courier_count:
                        type: integer
                      warehouse_mapping_count:
                        type: integer
                      auto_book:
                        type: boolean
                      record_shipping_costs:
                        type: boolean
                      last_webhook_at:
                        type: string
                      last_synced_at:
                        type: string
                      webhook_url:
                        type: string
                      webhook_subscribed_at:
                        type: string
                      is_connected:
                        type: boolean
                example:
                  data:
                    merchant:
                      name: Acme Fulfillment
                      company_name: Acme Fulfillment Pty Ltd
                      contact_name: Jordan Blake
                    environment: production
                    order_state_counts:
                      ready_for_pickup: 12
                      in_transit: 340
                      delivered: 1180
                      cancelled: 8
                    order_count: 1540
                    courier_count: 6
                    warehouse_mapping_count: 3
                    auto_book: true
                    record_shipping_costs: true
                    last_webhook_at: '2026-07-07T22:14:05+00:00'
                    last_synced_at: '2026-07-08T01:30:00+00:00'
                    webhook_url: https://acme.sku.io/api/webhooks/shippit/abc123def456
                    webhook_subscribed_at: '2026-07-08T21:31:36+00:00'
                    is_connected: true
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shippit-instances-integration-instance-dashboard
  /api/shippit/instances/{integration_instance}/orders:
    get:
      tags:
      - Shippit
      summary: List Orders
      description: 'Paginated, filterable list of Shippit orders for the integration
        instance.


        Every filter[&lt;column>] parameter also accepts an operator suffix as filter[&lt;column>.&lt;operator>]=&lt;value>;
        a bare filter[&lt;column>]=&lt;value> is treated as "is".


        - Text columns support: contains, does_not_contain, is, is_not, is_one_of,
        is_not_one_of, starts_with, does_not_start_with, ends_with, does_not_end_with,
        is_empty, is_not_empty.

        - Numeric columns support: is, is_not, is_one_of, is_not_one_of, greater_than,
        less_than, greater_than_or_equal, less_than_or_equal, between, is_empty, is_not_empty.

        - Date columns support: is, is_not, before, after, on_or_before, on_or_after,
        between, today, yesterday, tomorrow, past_week, past_month, past_year, next_week,
        next_month, next_year, days_ago, days_from_now, past_days, next_days, is_empty,
        is_not_empty.


        filter[search] does a fuzzy partial match across tracking_number, retailer_order_number,
        retailer_reference, receiver_name and courier_name.


        Sort with the sort parameter (prefix - for descending). Allowed sort fields:
        id, shippit_id, state, courier_type, courier_name, tracking_number, receiver_name,
        retailer_order_number, retailer_reference, price, expected_delivery_date,
        details_last_updated, created_at, updated_at. The default sort is -id (newest
        first).


        Results are paginated; per_page defaults to 10.


        Authentication: requires a Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        shippit_id:
                          type: integer
                        tracking_number:
                          type: string
                        slug:
                          type: string
                        courier_type:
                          type: string
                        courier_allocation:
                          type: string
                        courier_name:
                          type: string
                        service_level:
                          type: string
                        state:
                          type: string
                        processing_state:
                          type: string
                        retailer_order_number:
                          type: string
                        retailer_reference:
                          type: string
                        receiver_name:
                          type: string
                        delivery_address:
                          type: string
                        delivery_suburb:
                          type: string
                        delivery_postcode:
                          type: string
                        delivery_state:
                          type: string
                        delivery_country_code:
                          type: string
                        authority_to_leave:
                          type: boolean
                        price:
                          type: number
                        tracking_url:
                          type: string
                        expected_delivery_date:
                          type: string
                        details_last_updated:
                          type: string
                        external_url:
                          type: string
                        sku_fulfillment_order_id:
                          type: integer
                        sales_order_number:
                          type: string
                        link_type_label:
                          type: string
                        link_id:
                          type: integer
                        link_reference:
                          type: string
                        link_route:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                  first_page_url:
                    type: string
                  last_page_url:
                    type: string
                  next_page_url:
                    type: string
                  prev_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                example:
                  data:
                  - id: 4821
                    integration_instance_id: 3
                    shippit_id: 7712345
                    tracking_number: DZ1000456789
                    slug: acme-couriers
                    courier_type: standard
                    courier_allocation: CouriersPlease
                    courier_name: CouriersPlease
                    service_level: standard
                    state: ready_for_pickup
                    processing_state: completed
                    retailer_order_number: SO-100482
                    retailer_reference: ACME-REF-9931
                    receiver_name: Jane Doe
                    delivery_address: 1 Smith Street
                    delivery_suburb: Richmond
                    delivery_postcode: '3121'
                    delivery_state: VIC
                    delivery_country_code: AU
                    authority_to_leave: true
                    price: 8.95
                    tracking_url: https://www.shippit.com/tracking/DZ1000456789
                    expected_delivery_date: '2026-07-11T00:00:00+00:00'
                    details_last_updated: '2026-07-08T04:15:00+00:00'
                    external_url: https://app.shippit.com/orders/DZ1000456789
                    sku_fulfillment_order_id: 55210
                    sales_order_number: SO-100482
                    link_type_label: Fulfillment Order
                    link_id: 55210
                    link_reference: SO-100482
                    link_route: /orders/sales-orders/8842?tab=fulfillment
                    created_at: '2026-07-07T22:40:00+00:00'
                    updated_at: '2026-07-08T04:15:01+00:00'
                  current_page: 1
                  last_page: 5
                  per_page: 10
                  total: 48
                  from: 1
                  to: 10
                  first_page_url: '{{protocol}}://{{domain}}/api/shippit/instances/3/orders?page=1'
                  last_page_url: '{{protocol}}://{{domain}}/api/shippit/instances/3/orders?page=5'
                  next_page_url: '{{protocol}}://{{domain}}/api/shippit/instances/3/orders?page=2'
                  prev_page_url: null
                  path: '{{protocol}}://{{domain}}/api/shippit/instances/3/orders'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shippit-instances-integration-instance-orders
  /api/shippit/instances/{integration_instance}/orders/sync:
    post:
      tags:
      - Shippit
      summary: Sync Orders
      description: 'Queue a background job that reconciles the current state of existing
        Shippit orders for this instance (Shippit has no bulk order list, so the sweep
        refreshes each non-terminal order individually via its tracking number). The
        response returns the tracked job log id, which you can poll for progress.


        All body fields are optional — send an empty body {} to sweep every non-terminal
        order.


        - since — only refresh orders last updated before this date/time (ISO 8601
        or Y-m-d). Targets stale rows.

        - date_from — only include orders created on or after this date (Y-m-d).

        - date_to — only include orders created on or before this date (Y-m-d); must
        be on or after date_from.

        - tracking_number — refresh only the single order carrying this tracking number
        (max 255 chars).


        Authentication: requires a Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                since:
                  type: string
                date_from:
                  type: string
                date_to:
                  type: string
                tracking_number:
                  type: string
              example:
                since: '2026-07-01T00:00:00+00:00'
                date_from: '2026-07-01'
                date_to: '2026-07-08'
                tracking_number: DZ1000456789
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 4321
                  message: Order sync started — track progress in the job tray.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-shippit-instances-integration-instance-orders-sync
  /api/shippit/instances/{integration_instance}/orders/{order}:
    get:
      tags:
      - Shippit
      summary: Get Order
      description: 'Returns the full details for a single Shippit order scoped to
        the integration instance. Includes the raw provider identifiers (shippit_id,
        tracking_number, state), courier and delivery fields, price, tracking URL,
        a deep link to the Shippit merchant portal (external_url), and cross-link
        fields to the originating fulfillment order / sales order.


        When include_json=1 is supplied, the response also includes items — normalized
        line items with each SKU resolved to its product id for cross-linking — and
        the stored provider payload as json_object.


        A tracking number / instance mismatch returns 404.


        Authentication: requires a Bearer token.'
      parameters:
      - name: include_json
        in: query
        schema:
          type: integer
        description: Set to 1 to include the stored provider payload as json_object
          in the response.
        example: '1'
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: order
        in: path
        schema:
          type: integer
        required: true
        description: Internal Shippit order id (scoped to the instance).
        example: '4821'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      shippit_id:
                        type: integer
                      tracking_number:
                        type: string
                      slug:
                        type: string
                      courier_type:
                        type: string
                      courier_allocation:
                        type: string
                      courier_name:
                        type: string
                      service_level:
                        type: string
                      state:
                        type: string
                      processing_state:
                        type: string
                      retailer_order_number:
                        type: string
                      retailer_reference:
                        type: string
                      receiver_name:
                        type: string
                      delivery_address:
                        type: string
                      delivery_suburb:
                        type: string
                      delivery_postcode:
                        type: string
                      delivery_state:
                        type: string
                      delivery_country_code:
                        type: string
                      authority_to_leave:
                        type: boolean
                      price:
                        type: number
                      tracking_url:
                        type: string
                      expected_delivery_date:
                        type: string
                      details_last_updated:
                        type: string
                      external_url:
                        type: string
                      sku_fulfillment_order_id:
                        type: integer
                      sales_order_number:
                        type: string
                      link_type_label:
                        type: string
                      link_id:
                        type: integer
                      link_reference:
                        type: string
                      link_route:
                        type: string
                      items:
                        type: array
                        items:
                          type: object
                          properties:
                            sku:
                              type: string
                            name:
                              type: string
                            quantity:
                              type: integer
                            price:
                              type: number
                            weight:
                              type: number
                            product_id:
                              type: integer
                      json_object:
                        type: object
                        properties:
                          retailer_order_number:
                            type: string
                          products:
                            type: array
                            items:
                              type: object
                              properties:
                                sku:
                                  type: string
                                title:
                                  type: string
                                quantity:
                                  type: integer
                                price:
                                  type: number
                                weight:
                                  type: number
                          last_tracking:
                            type: object
                            properties:
                              current_state:
                                type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 4821
                    integration_instance_id: 3
                    shippit_id: 7712345
                    tracking_number: DZ1000456789
                    slug: acme-couriers
                    courier_type: standard
                    courier_allocation: CouriersPlease
                    courier_name: CouriersPlease
                    service_level: standard
                    state: ready_for_pickup
                    processing_state: completed
                    retailer_order_number: SO-100482
                    retailer_reference: ACME-REF-9931
                    receiver_name: Jane Doe
                    delivery_address: 1 Smith Street
                    delivery_suburb: Richmond
                    delivery_postcode: '3121'
                    delivery_state: VIC
                    delivery_country_code: AU
                    authority_to_leave: true
                    price: 8.95
                    tracking_url: https://www.shippit.com/tracking/DZ1000456789
                    expected_delivery_date: '2026-07-11T00:00:00+00:00'
                    details_last_updated: '2026-07-08T04:15:00+00:00'
                    external_url: https://app.shippit.com/orders/DZ1000456789
                    sku_fulfillment_order_id: 55210
                    sales_order_number: SO-100482
                    link_type_label: Fulfillment Order
                    link_id: 55210
                    link_reference: SO-100482
                    link_route: /orders/sales-orders/8842?tab=fulfillment
                    items:
                    - sku: ACME-WIDGET-01
                      name: Acme Widget
                      quantity: 2
                      price: 24.5
                      weight: 0.35
                      product_id: 90231
                    json_object:
                      retailer_order_number: SO-100482
                      products:
                      - sku: ACME-WIDGET-01
                        title: Acme Widget
                        quantity: 2
                        price: 24.5
                        weight: 0.35
                      last_tracking:
                        current_state: ready_for_pickup
                    created_at: '2026-07-07T22:40:00+00:00'
                    updated_at: '2026-07-08T04:15:01+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shippit-instances-integration-instance-orders-order
  /api/shippit/instances/{integration_instance}/orders/{order}/book:
    post:
      tags:
      - Shippit
      summary: Book Order
      description: 'Books a courier pickup for an already-created Shippit order (transitions
        it out of order_placed toward despatch). Runs as a background job; the response
        returns the tracked job log id, which you can poll for progress.


        No request body is required. A tracking number / instance mismatch returns
        404.


        Authentication: requires a Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: string
              example: ''
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: order
        in: path
        schema:
          type: integer
        required: true
        description: Internal Shippit order id (scoped to the instance).
        example: '4821'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 4322
                  message: Booking started — track progress in the job tray.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-shippit-instances-integration-instance-orders-order-book
  /api/shippit/instances/{integration_instance}/shipments:
    get:
      tags:
      - Shippit
      summary: List Shipments
      description: 'List shipments (consignments) for the shipping-provider instance,
        paginated. Each shipment carries the despatch data — courier job, tracking
        number and URL, service level, price, parcel count, and despatch/delivery
        timestamps — a deep link into the Shippit portal (`external_url`), plus a
        cross-link to the fulfillment it realized (link_type_label / link_reference
        / link_route). Shipments belonging to another instance are not returned.


        Sort field. Prefix with - for descending. Allowed: id, shippit_order_id, courier_name,
        tracking_number, shipping_price, number_of_parcels, despatched_at, delivered_at,
        created_at, updated_at. Default: -id (newest first).


        Authenticate with a Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        shippit_order_id:
                          type: integer
                        order_tracking_number:
                          type: string
                        courier_job_id:
                          type: string
                        courier_name:
                          type: string
                        tracking_number:
                          type: string
                        tracking_url:
                          type: string
                        service_level:
                          type: string
                        shipping_price:
                          type: number
                        number_of_parcels:
                          type: integer
                        despatched_at:
                          type: string
                        delivered_at:
                          type: string
                          nullable: true
                        external_url:
                          type: string
                        sku_sales_order_fulfillment_id:
                          type: integer
                        link_type_label:
                          type: string
                        link_id:
                          type: integer
                        link_reference:
                          type: string
                        link_route:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - id: 4821
                    shippit_order_id: 3310
                    order_tracking_number: SPT-AU-88213345
                    courier_job_id: JOB-7GQ2K
                    courier_name: Australia Post
                    tracking_number: AP4H2388922102000935105
                    tracking_url: https://app.shippit.com/tracking/AP4H2388922102000935105
                    service_level: standard
                    shipping_price: 12.45
                    number_of_parcels: 2
                    despatched_at: '2026-06-30T02:14:00+00:00'
                    delivered_at: null
                    external_url: https://app.staging.shippit.com/orders/SPT-AU-88213345
                    sku_sales_order_fulfillment_id: 256917
                    link_type_label: Sales Order Fulfillment
                    link_id: 256917
                    link_reference: F-256917
                    link_route: /orders/sales-orders/fulfillments/256917
                    created_at: '2026-06-30T02:14:05+00:00'
                    updated_at: '2026-06-30T02:14:05+00:00'
                  - id: 4799
                    shippit_order_id: 3288
                    order_tracking_number: SPT-AU-88210012
                    courier_job_id: JOB-5KM1A
                    courier_name: Couriers Please
                    tracking_number: CP99001122334455
                    tracking_url: https://app.shippit.com/tracking/CP99001122334455
                    service_level: express
                    shipping_price: 18.9
                    number_of_parcels: 1
                    despatched_at: '2026-06-29T23:41:00+00:00'
                    delivered_at: '2026-07-01T04:12:00+00:00'
                    external_url: https://app.staging.shippit.com/orders/SPT-AU-88210012
                    sku_sales_order_fulfillment_id: null
                    link_type_label: null
                    link_id: null
                    link_reference: null
                    link_route: null
                    created_at: '2026-06-29T23:41:03+00:00'
                    updated_at: '2026-07-01T04:12:07+00:00'
                  current_page: 1
                  last_page: 3
                  per_page: 10
                  total: 27
                  from: 1
                  to: 10
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shippit-instances-integration-instance-shipments
  /api/shippit/instances/{integration_instance}/shipments/sync:
    post:
      tags:
      - Shippit
      summary: Sync Shipments
      description: 'Queue a background (tracked) job that reconciles despatch and
        delivery timestamps for the instance''s undelivered shipments against the
        provider''s current tracking state. Poll the returned tracked_job_log_id for
        progress.


        Body parameters (all optional — send an empty body to sweep every undelivered
        shipment):

        - since (date) — only reconcile shipments observed on/after this date.

        - date_from (date) — lower bound on the reconcile window.

        - date_to (date) — upper bound on the reconcile window; must be on or after
        date_from.

        - tracking_number (string, max 255) — restrict the sweep to a single consignment.


        Authenticate with a Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                since:
                  type: string
                date_from:
                  type: string
                date_to:
                  type: string
                tracking_number:
                  type: string
              example:
                since: '2026-06-01'
                date_from: '2026-06-01'
                date_to: '2026-06-30'
                tracking_number: AP4H2388922102000935105
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 90211
                  message: Shipment sync started — track progress in the job tray.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-shippit-instances-integration-instance-shipments-sync
  /api/shippit/instances/{integration_instance}/shipments/{shipment}:
    get:
      tags:
      - Shippit
      summary: Get Shipment
      description: 'Retrieve a single shipment scoped to the instance. Returns 404
        if the shipment does not exist or belongs to another instance. Pass include_json=1
        to include the stored provider tracking payload.


        Authenticate with a Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: shipment
        in: path
        schema:
          type: integer
        required: true
        description: The shipment id.
        example: '4821'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      shippit_order_id:
                        type: integer
                      order_tracking_number:
                        type: string
                      courier_job_id:
                        type: string
                      courier_name:
                        type: string
                      tracking_number:
                        type: string
                      tracking_url:
                        type: string
                      service_level:
                        type: string
                      shipping_price:
                        type: number
                      number_of_parcels:
                        type: integer
                      despatched_at:
                        type: string
                      delivered_at:
                        type: string
                        nullable: true
                      external_url:
                        type: string
                      sku_sales_order_fulfillment_id:
                        type: integer
                      link_type_label:
                        type: string
                      link_id:
                        type: integer
                      link_reference:
                        type: string
                      link_route:
                        type: string
                      json_object:
                        type: object
                        properties:
                          last_tracking:
                            type: object
                            properties:
                              status:
                                type: string
                              status_owner:
                                type: string
                              latest_estimated_delivery_date:
                                type: string
                              tracking:
                                type: array
                                items:
                                  type: object
                                  properties:
                                    status:
                                      type: string
                                    date:
                                      type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 4821
                    shippit_order_id: 3310
                    order_tracking_number: SPT-AU-88213345
                    courier_job_id: JOB-7GQ2K
                    courier_name: Australia Post
                    tracking_number: AP4H2388922102000935105
                    tracking_url: https://app.shippit.com/tracking/AP4H2388922102000935105
                    service_level: standard
                    shipping_price: 12.45
                    number_of_parcels: 2
                    despatched_at: '2026-06-30T02:14:00+00:00'
                    delivered_at: null
                    external_url: https://app.staging.shippit.com/orders/SPT-AU-88213345
                    sku_sales_order_fulfillment_id: 256917
                    link_type_label: Sales Order Fulfillment
                    link_id: 256917
                    link_reference: F-256917
                    link_route: /orders/sales-orders/fulfillments/256917
                    json_object:
                      last_tracking:
                        status: in_transit
                        status_owner: AusPost
                        latest_estimated_delivery_date: '2026-07-02'
                        tracking:
                        - status: order_placed
                          date: '2026-06-30T02:14:00+00:00'
                        - status: in_transit
                          date: '2026-06-30T09:50:00+00:00'
                    created_at: '2026-06-30T02:14:05+00:00'
                    updated_at: '2026-06-30T02:14:05+00:00'
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Shippit shipment not found.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-shippit-instances-integration-instance-shipments-shipment
  /api/shippit/instances/{integration_instance}/couriers:
    get:
      tags:
      - Shippit
      summary: List Couriers
      description: 'List couriers for the shipping-provider instance, paginated. Each
        row is one courier type + service-level combination the merchant offers, with
        its enabled state and an optional mapping to an internal shipping method (sku_shipping_method_id
        / shipping_method_name). Unmapped couriers have null link fields.


        Sort field. Prefix with - for descending. Allowed: id, courier_type, service_level,
        courier_name, enabled, created_at. Default: courier_name (A–Z).


        Authenticate with a Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        courier_type:
                          type: string
                        service_level:
                          type: string
                        courier_name:
                          type: string
                        enabled:
                          type: boolean
                        sku_shipping_method_id:
                          type: integer
                        shipping_method_name:
                          type: string
                        link_type_label:
                          type: string
                        link_id:
                          type: integer
                        link_reference:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - id: 55
                    integration_instance_id: 6
                    courier_type: AusPost
                    service_level: standard
                    courier_name: Australia Post
                    enabled: true
                    sku_shipping_method_id: 12
                    shipping_method_name: Standard Shipping
                    link_type_label: Shipping Method
                    link_id: 12
                    link_reference: Standard Shipping
                    created_at: '2026-06-10T08:00:00+00:00'
                    updated_at: '2026-06-28T15:30:00+00:00'
                  - id: 56
                    integration_instance_id: 6
                    courier_type: CouriersPlease
                    service_level: express
                    courier_name: Couriers Please
                    enabled: true
                    sku_shipping_method_id: null
                    shipping_method_name: null
                    link_type_label: null
                    link_id: null
                    link_reference: null
                    created_at: '2026-06-10T08:00:00+00:00'
                    updated_at: '2026-06-10T08:00:00+00:00'
                  current_page: 1
                  last_page: 1
                  per_page: 10
                  total: 8
                  from: 1
                  to: 8
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shippit-instances-integration-instance-couriers
  /api/shippit/instances/{integration_instance}/couriers/sync:
    post:
      tags:
      - Shippit
      summary: Sync Couriers
      description: 'Queue a background (tracked) job that discovers the couriers and
        service levels available to the merchant and upserts them for the instance.
        Takes no request body. Poll the returned tracked_job_log_id for progress.


        Authenticate with a Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: string
              example: ''
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 90233
                  message: Courier sync started — track progress in the job tray.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-shippit-instances-integration-instance-couriers-sync
  /api/shippit/instances/{integration_instance}/couriers/{courier}:
    get:
      tags:
      - Shippit
      summary: Get Courier
      description: 'Retrieve a single courier scoped to the instance, including its
        mapping to an internal shipping method (if any). Returns 404 if the courier
        does not exist or belongs to another instance.


        Authenticate with a Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: courier
        in: path
        schema:
          type: integer
        required: true
        description: The courier id.
        example: '55'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      courier_type:
                        type: string
                      service_level:
                        type: string
                      courier_name:
                        type: string
                      enabled:
                        type: boolean
                      sku_shipping_method_id:
                        type: integer
                      shipping_method_name:
                        type: string
                      link_type_label:
                        type: string
                      link_id:
                        type: integer
                      link_reference:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 55
                    integration_instance_id: 6
                    courier_type: AusPost
                    service_level: standard
                    courier_name: Australia Post
                    enabled: true
                    sku_shipping_method_id: 12
                    shipping_method_name: Standard Shipping
                    link_type_label: Shipping Method
                    link_id: 12
                    link_reference: Standard Shipping
                    created_at: '2026-06-10T08:00:00+00:00'
                    updated_at: '2026-06-28T15:30:00+00:00'
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Shippit courier not found.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-shippit-instances-integration-instance-couriers-courier
  /api/shippit/instances/{integration_instance}/couriers/{courier}/link:
    post:
      tags:
      - Shippit
      summary: Map Courier To Shipping Method
      description: 'Map a courier (its courier type / service level) to an internal
        shipping method so the dispatcher knows which courier to request when submitting
        an order. Send shipping_method_id as null (or omit it) to remove an existing
        mapping. Returns the updated courier.


        Body parameters:

        - shipping_method_id (integer, nullable) — the internal shipping method id
        to map to. Must reference an existing shipping method. Null or omitted unlinks
        the courier.


        Returns 404 when the courier cannot be found, and 422 when shipping_method_id
        does not reference an existing shipping method.


        Authenticate with a Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                shipping_method_id:
                  type: integer
              example:
                shipping_method_id: 12
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: courier
        in: path
        schema:
          type: integer
        required: true
        description: The courier id to map.
        example: '55'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      courier_type:
                        type: string
                      service_level:
                        type: string
                      courier_name:
                        type: string
                      enabled:
                        type: boolean
                      sku_shipping_method_id:
                        type: integer
                      shipping_method_name:
                        type: string
                      link_type_label:
                        type: string
                      link_id:
                        type: integer
                      link_reference:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 55
                    integration_instance_id: 6
                    courier_type: AusPost
                    service_level: standard
                    courier_name: Australia Post
                    enabled: true
                    sku_shipping_method_id: 12
                    shipping_method_name: Standard Shipping
                    link_type_label: Shipping Method
                    link_id: 12
                    link_reference: Standard Shipping
                    created_at: '2026-06-10T08:00:00+00:00'
                    updated_at: '2026-06-28T15:30:00+00:00'
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Shippit courier not found.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      shipping_method_id:
                        type: array
                        items:
                          type: string
                example:
                  message: The selected shipping method does not exist.
                  errors:
                    shipping_method_id:
                    - The selected shipping method does not exist.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-shippit-instances-integration-instance-couriers-courier-link
  /api/shippit/instances/{integration_instance}/warehouses:
    get:
      tags:
      - Shippit
      summary: List Warehouse Mappings
      description: 'Returns a paginated list of warehouse-to-sender mappings for this
        Shippit instance, newest first. Each mapping links one of your warehouses
        to the Shippit sender (pickup origin) details used when despatching from it.


        Sortable columns: `id`, `sku_warehouse_id`, `sender_name`, `enabled`, `created_at`
        (default `-id`). Default page size is 10.


        Filtering uses operator-aware syntax `filter[field.operator]=value`; a bare
        `filter[field]=value` means equals. `filter[search]` matches the sender name
        and the linked warehouse name.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        enabled:
                          type: boolean
                        sender_name:
                          type: string
                        sender_address:
                          type: object
                          properties:
                            line1:
                              type: string
                            line2:
                              type: string
                            suburb:
                              type: string
                            state:
                              type: string
                            postcode:
                              type: string
                            country_code:
                              type: string
                        sku_warehouse_id:
                          type: integer
                        warehouse_name:
                          type: string
                        link_type_label:
                          type: string
                        link_id:
                          type: integer
                        link_reference:
                          type: string
                        link_route:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 51
                    integration_instance_id: 2
                    enabled: true
                    sender_name: Main Distribution Center
                    sender_address:
                      line1: 12 Warehouse Road
                      line2: Unit 4
                      suburb: Botany
                      state: NSW
                      postcode: '2019'
                      country_code: AU
                    sku_warehouse_id: 42
                    warehouse_name: Sydney Main
                    link_type_label: Warehouse
                    link_id: 42
                    link_reference: Sydney Main
                    link_route: /crm/warehouses/42
                    created_at: '2026-06-14T09:22:41+00:00'
                    updated_at: '2026-07-05T18:03:12+00:00'
                  - id: 48
                    integration_instance_id: 2
                    enabled: false
                    sender_name: Melbourne Overflow
                    sender_address:
                      line1: 88 Logistics Way
                      suburb: Tullamarine
                      state: VIC
                      postcode: '3043'
                      country_code: AU
                    sku_warehouse_id: 39
                    warehouse_name: Melbourne DC
                    link_type_label: Warehouse
                    link_id: 39
                    link_reference: Melbourne DC
                    link_route: /crm/warehouses/39
                    created_at: '2026-05-30T11:10:05+00:00'
                    updated_at: '2026-06-28T14:41:33+00:00'
                  current_page: 1
                  first_page_url: https://example.sku.io/api/shippit/instances/2/warehouses?page=1
                  from: 1
                  last_page: 1
                  last_page_url: https://example.sku.io/api/shippit/instances/2/warehouses?page=1
                  next_page_url: null
                  path: https://example.sku.io/api/shippit/instances/2/warehouses
                  per_page: 10
                  prev_page_url: null
                  to: 2
                  total: 2
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shippit-instances-integration-instance-warehouses
  /api/shippit/instances/{integration_instance}/warehouses/link:
    post:
      tags:
      - Shippit
      summary: Map Warehouse
      description: 'Links one of your warehouses to Shippit sender (pickup origin)
        details so despatches from that warehouse originate from the correct address.
        Idempotent upsert on the (instance, warehouse) pair: calling it again for
        an already-linked warehouse updates its sender details in place rather than
        creating a duplicate.


        Request fields:

        - `sku_warehouse_id` (required, integer) — the id of the warehouse to link;
        must reference an existing warehouse.

        - `enabled` (optional, boolean) — whether the mapping is active; defaults
        to `true`.

        - `sender_name` (optional, string, max 255) — display name for the sender/pickup
        origin.

        - `sender_address` (optional, object) — free-form address object stored verbatim
        as the pickup origin override.


        Returns `201 Created` with the resulting mapping. Returns `422` when validation
        fails (e.g. missing or unknown warehouse).


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                sku_warehouse_id:
                  type: integer
                enabled:
                  type: boolean
                sender_name:
                  type: string
                sender_address:
                  type: object
                  properties:
                    line1:
                      type: string
                    line2:
                      type: string
                    suburb:
                      type: string
                    state:
                      type: string
                    postcode:
                      type: string
                    country_code:
                      type: string
              example:
                sku_warehouse_id: 42
                enabled: true
                sender_name: Main Distribution Center
                sender_address:
                  line1: 12 Warehouse Road
                  line2: Unit 4
                  suburb: Botany
                  state: NSW
                  postcode: '2019'
                  country_code: AU
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      enabled:
                        type: boolean
                      sender_name:
                        type: string
                      sender_address:
                        type: object
                        properties:
                          line1:
                            type: string
                          line2:
                            type: string
                          suburb:
                            type: string
                          state:
                            type: string
                          postcode:
                            type: string
                          country_code:
                            type: string
                      sku_warehouse_id:
                        type: integer
                      warehouse_name:
                        type: string
                      link_type_label:
                        type: string
                      link_id:
                        type: integer
                      link_reference:
                        type: string
                      link_route:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 51
                    integration_instance_id: 2
                    enabled: true
                    sender_name: Main Distribution Center
                    sender_address:
                      line1: 12 Warehouse Road
                      line2: Unit 4
                      suburb: Botany
                      state: NSW
                      postcode: '2019'
                      country_code: AU
                    sku_warehouse_id: 42
                    warehouse_name: Sydney Main
                    link_type_label: Warehouse
                    link_id: 42
                    link_reference: Sydney Main
                    link_route: /crm/warehouses/42
                    created_at: '2026-06-14T09:22:41+00:00'
                    updated_at: '2026-07-05T18:03:12+00:00'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      sku_warehouse_id:
                        type: array
                        items:
                          type: string
                example:
                  message: The selected warehouse does not exist.
                  errors:
                    sku_warehouse_id:
                    - The selected warehouse does not exist.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-shippit-instances-integration-instance-warehouses-link
  /api/shippit/instances/{integration_instance}/warehouses/{mapping}:
    delete:
      tags:
      - Shippit
      summary: Unmap Warehouse
      description: 'Removes a warehouse-to-sender mapping. Despatches from that warehouse
        will no longer use the stored sender override.


        Returns `204 No Content` on success. Returns `404` when the mapping does not
        exist or belongs to a different integration instance.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: mapping
        in: path
        schema:
          type: integer
        required: true
        description: The warehouse mapping id to remove.
        example: '51'
      responses:
        '204':
          description: No Content
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties: {}
                example: {}
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Shippit warehouse mapping not found.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: delete-api-shippit-instances-integration-instance-warehouses-mapping
  /api/shippit/instances/{integration_instance}/warehouses/{mapping}/toggle:
    patch:
      tags:
      - Shippit
      summary: Toggle Warehouse Mapping
      description: 'Flips a mapping''s enabled flag: an enabled mapping becomes disabled
        and vice versa. Disabled mappings are retained but no longer supply sender
        details for despatch.


        No request body is required. Returns `200 OK` with the updated mapping (note
        the flipped `enabled` value). Returns `404` when the mapping does not exist
        or belongs to a different integration instance.


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: mapping
        in: path
        schema:
          type: integer
        required: true
        description: The warehouse mapping id to toggle.
        example: '51'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      enabled:
                        type: boolean
                      sender_name:
                        type: string
                      sender_address:
                        type: object
                        properties:
                          line1:
                            type: string
                          line2:
                            type: string
                          suburb:
                            type: string
                          state:
                            type: string
                          postcode:
                            type: string
                          country_code:
                            type: string
                      sku_warehouse_id:
                        type: integer
                      warehouse_name:
                        type: string
                      link_type_label:
                        type: string
                      link_id:
                        type: integer
                      link_reference:
                        type: string
                      link_route:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 51
                    integration_instance_id: 2
                    enabled: false
                    sender_name: Main Distribution Center
                    sender_address:
                      line1: 12 Warehouse Road
                      line2: Unit 4
                      suburb: Botany
                      state: NSW
                      postcode: '2019'
                      country_code: AU
                    sku_warehouse_id: 42
                    warehouse_name: Sydney Main
                    link_type_label: Warehouse
                    link_id: 42
                    link_reference: Sydney Main
                    link_route: /crm/warehouses/42
                    created_at: '2026-06-14T09:22:41+00:00'
                    updated_at: '2026-07-05T18:03:12+00:00'
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Shippit warehouse mapping not found.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: patch-api-shippit-instances-integration-instance-warehouses-mapping-toggle
  /api/shippit/instances/{integration_instance}/webhooks/subscribe:
    post:
      tags:
      - Shippit
      summary: Subscribe Webhook
      description: 'Register this instance''s inbound webhook URL with Shippit via
        the merchant API (PUT /merchant), so despatch and delivery events are delivered
        without pasting the URL into the Shippit dashboard. Runs automatically on
        connect; this endpoint re-registers it.


        Authentication: Requires Bearer token. No request body.


        Returns 200 with the subscription timestamp, or 422 {code: invalid_key|api_error}
        if Shippit rejects the call.'
      requestBody:
        content: {}
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  webhook_subscribed_at:
                    type: string
                example:
                  message: Webhook registered with Shippit.
                  webhook_subscribed_at: '2026-07-08T21:31:36+00:00'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  code:
                    type: string
                example:
                  message: Could not register the webhook with Shippit. Please try
                    again.
                  code: api_error
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-shippit-instances-integration-instance-webhooks-subscribe
    delete:
      tags:
      - Shippit
      summary: Unsubscribe Webhook
      description: 'Clear this instance''s webhook URL at Shippit (PUT /merchant with
        null), stopping inbound events.


        Authentication: Requires Bearer token. No request body.


        Returns 200, or 422 {code: invalid_key|api_error} on failure.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Webhook cleared at Shippit.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-shippit-instances-integration-instance-webhooks-subscribe
  /api/shippit/instances/{integration_instance}/webhooks:
    get:
      tags:
      - Shippit
      summary: List Webhook Events
      description: 'Returns a paginated list of inbound webhook events received from
        Shippit for this instance, newest first. Every inbound webhook is persisted
        so you can audit and inspect deliveries; each row records the event type,
        tracking number, courier job id, the dedup key, the raw payload, and whether
        it has been processed yet (`processed` / `processed_at`).


        Sortable columns: `id`, `event_type`, `tracking_number`, `received_at`, `processed_at`,
        `created_at` (default `-received_at`). Default page size is 15.


        Filtering uses operator-aware syntax `filter[field.operator]=value`; a bare
        `filter[field]=value` means equals. Available filters: `id`, `event_type`,
        `tracking_number`, `courier_job_id`, `dedup_key`, `processed` (1 = processed,
        0 = pending, all = no filter), `received_at`, `processed_at`, `created_at`.
        `filter[search]` matches tracking number, event type, courier job id, and
        dedup key.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        event_type:
                          type: string
                        tracking_number:
                          type: string
                        courier_job_id:
                          type: string
                        dedup_key:
                          type: string
                        payload:
                          type: object
                          properties:
                            tracking_number:
                              type: string
                            courier_job_id:
                              type: string
                            status:
                              type: string
                            courier_name:
                              type: string
                            updated_at:
                              type: string
                        processed:
                          type: boolean
                        processed_at:
                          type: string
                        received_at:
                          type: string
                        created_at:
                          type: string
                  current_page:
                    type: integer
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  next_page_url:
                    type: string
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 9011
                    integration_instance_id: 2
                    event_type: order.status.updated
                    tracking_number: AUP0091234567
                    courier_job_id: JOB-88231
                    dedup_key: 2:order.status.updated:JOB-88231:delivered
                    payload:
                      tracking_number: AUP0091234567
                      courier_job_id: JOB-88231
                      status: delivered
                      courier_name: Australia Post
                      updated_at: '2026-07-05T08:00:59+10:00'
                    processed: true
                    processed_at: '2026-07-05T08:01:11+00:00'
                    received_at: '2026-07-05T08:01:09+00:00'
                    created_at: '2026-07-05T08:01:09+00:00'
                  - id: 9008
                    integration_instance_id: 2
                    event_type: order.status.updated
                    tracking_number: AUP0099887766
                    courier_job_id: JOB-88117
                    dedup_key: 2:order.status.updated:JOB-88117:in_transit
                    payload:
                      tracking_number: AUP0099887766
                      courier_job_id: JOB-88117
                      status: in_transit
                      courier_name: Couriers Please
                    processed: false
                    processed_at: null
                    received_at: '2026-07-04T21:14:33+00:00'
                    created_at: '2026-07-04T21:14:33+00:00'
                  current_page: 1
                  first_page_url: https://example.sku.io/api/shippit/instances/2/webhooks?page=1
                  from: 1
                  last_page: 34
                  last_page_url: https://example.sku.io/api/shippit/instances/2/webhooks?page=34
                  next_page_url: https://example.sku.io/api/shippit/instances/2/webhooks?page=2
                  path: https://example.sku.io/api/shippit/instances/2/webhooks
                  per_page: 15
                  prev_page_url: null
                  to: 15
                  total: 502
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shippit-instances-integration-instance-webhooks
  /api/shippit/instances/{integration_instance}/webhooks/{webhookEvent}:
    get:
      tags:
      - Shippit
      summary: Get Webhook Event
      description: 'Returns a single webhook event received from Shippit, including
        its full raw `payload`. `processed_at` (and the `processed` flag) reflect
        whether the ingest pipeline has already handled the event.


        Returns `404` when the event does not exist or belongs to a different integration
        instance.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      - name: webhookEvent
        in: path
        schema:
          type: integer
        required: true
        description: The webhook event id.
        example: '9011'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      event_type:
                        type: string
                      tracking_number:
                        type: string
                      courier_job_id:
                        type: string
                      dedup_key:
                        type: string
                      payload:
                        type: object
                        properties:
                          tracking_number:
                            type: string
                          courier_job_id:
                            type: string
                          status:
                            type: string
                          courier_name:
                            type: string
                          updated_at:
                            type: string
                      processed:
                        type: boolean
                      processed_at:
                        type: string
                      received_at:
                        type: string
                      created_at:
                        type: string
                example:
                  data:
                    id: 9011
                    integration_instance_id: 2
                    event_type: order.status.updated
                    tracking_number: AUP0091234567
                    courier_job_id: JOB-88231
                    dedup_key: 2:order.status.updated:JOB-88231:delivered
                    payload:
                      tracking_number: AUP0091234567
                      courier_job_id: JOB-88231
                      status: delivered
                      courier_name: Australia Post
                      updated_at: '2026-07-05T08:00:59+10:00'
                    processed: true
                    processed_at: '2026-07-05T08:01:11+00:00'
                    received_at: '2026-07-05T08:01:09+00:00'
                    created_at: '2026-07-05T08:01:09+00:00'
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Shippit webhook event not found.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-shippit-instances-integration-instance-webhooks-webhookevent
  /api/shippit/instances/{integration_instance}/activity:
    get:
      tags:
      - Shippit
      summary: List Activity
      description: 'Returns a paginated activity feed for this Shippit instance, newest
        first — the audit trail of actions taken across the integration (connect,
        settings update, disconnect, syncs, order submit/book/cancel, warehouse link/unlink,
        etc.). Each entry carries the acting user (`causer`, `null` for system-generated
        entries), a human description, and a `properties` bag of contextual data.


        Sortable columns: `created_at`, `event`, `id` (default `-created_at`, tie-broken
        by `-id`). Default page size is 15.


        Filtering: `filter[search]` matches the description; `filter[event]` / `filter[description]`
        are operator-aware text filters; `filter[event_type]` and `filter[causer_id]`
        accept comma-separated lists; `filter[created_at.*]` supports datetime operators.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integration_instance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        event:
                          type: string
                        description:
                          type: string
                        causer:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            email:
                              type: string
                        properties:
                          type: object
                          properties:
                            integration_instance_id:
                              type: integer
                            shippit_warehouse_mapping_id:
                              type: integer
                            sku_warehouse_id:
                              type: integer
                        created_at:
                          type: string
                        occurred_at_human:
                          type: string
                  current_page:
                    type: integer
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  next_page_url:
                    type: string
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 14032
                    event: warehouse_linked
                    description: 'Linked warehouse #42 to Shippit'
                    causer:
                      id: 7
                      name: Dana Ops
                      email: dana@example.com
                    properties:
                      integration_instance_id: 2
                      shippit_warehouse_mapping_id: 51
                      sku_warehouse_id: 42
                    created_at: '2026-07-05T18:03:12+00:00'
                    occurred_at_human: 2 days ago
                  - id: 14020
                    event: orders_synced
                    description: Synced 37 orders from Shippit
                    causer: null
                    properties:
                      integration_instance_id: 2
                      synced_count: 37
                    created_at: '2026-07-05T06:00:04+00:00'
                    occurred_at_human: 3 days ago
                  current_page: 1
                  first_page_url: https://example.sku.io/api/shippit/instances/2/activity?page=1
                  from: 1
                  last_page: 9
                  last_page_url: https://example.sku.io/api/shippit/instances/2/activity?page=9
                  next_page_url: https://example.sku.io/api/shippit/instances/2/activity?page=2
                  path: https://example.sku.io/api/shippit/instances/2/activity
                  per_page: 15
                  prev_page_url: null
                  to: 15
                  total: 128
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-shippit-instances-integration-instance-activity
  /api/qbo/integrations:
    get:
      tags:
      - QuickBooks Online
      summary: List Integrations
      description: 'Returns all QBO integration instances with connection status.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        realm_id:
                          type: string
                        environment:
                          type: string
                        is_authenticated:
                          type: boolean
                        is_auto_sync_enabled:
                          type: boolean
                        sync_due_dates:
                          type: boolean
                        connection_status:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                example:
                  success: true
                  data:
                  - id: 1
                    name: My Company
                    realm_id: '123456789'
                    environment: production
                    is_authenticated: true
                    is_auto_sync_enabled: true
                    sync_due_dates: true
                    connection_status: connected
                    created_at: '2024-01-01T00:00:00.000000Z'
                    updated_at: '2024-01-01T00:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-qbo-integrations
  /api/qbo/integrations/initialize:
    post:
      tags:
      - QuickBooks Online
      summary: Initialize OAuth
      description: 'Generates a QBO OAuth authorization URL. Works for both initial
        setup and reconnection.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Optional `environment` (`sandbox` | `production`) selects which QuickBooks
        environment to connect to. It is honoured only on non-production servers (production
        always connects to production) and defaults to `sandbox` when omitted. For
        a reconnect the existing connection''s environment is reused. The environment
        is fixed once connected - to switch, disconnect and reconnect.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                environment:
                  type: string
              example:
                environment: sandbox
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      state:
                        type: string
                      authorization_url:
                        type: string
                      is_reconnect:
                        type: boolean
                      environment:
                        type: string
                      instructions:
                        type: array
                        items:
                          type: string
                example:
                  success: true
                  data:
                    state: 42_4f1a9b2e-37c5-4d8a-9b1f-7c4e9d2a5b18
                    authorization_url: https://appcenter.intuit.com/connect/oauth2?client_id=...&scope=com.intuit.quickbooks.accounting&redirect_uri=https%3A%2F%2Fapp.sku.io%2Fqbo%2Fcallback&response_type=code&access_type=offline&state=42_4f1a9b2e-37c5-4d8a-9b1f-7c4e9d2a5b18
                    is_reconnect: false
                    environment: sandbox
                    instructions:
                    - 1. Visit the authorization_url in your browser
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-qbo-integrations-initialize
  /api/qbo/integrations/complete:
    post:
      tags:
      - QuickBooks Online
      summary: Complete OAuth Setup
      description: 'Completes new QBO integration setup using the OAuth state. Only
        for new integrations (reconnections are handled automatically via callback).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Deprecation note:** the `is_auto_sync_enabled` field uses legacy naming
        — it sets the coarse sync-schedule flag, which is slated for rename to `sync_schedule_active`.
        The field is kept for backward compatibility.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                state:
                  type: string
                is_auto_sync_enabled:
                  type: boolean
              example:
                state: abc123
                is_auto_sync_enabled: true
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      integration_instance_id:
                        type: integer
                      name:
                        type: string
                      realm_id:
                        type: string
                      environment:
                        type: string
                      is_authenticated:
                        type: boolean
                      is_auto_sync_enabled:
                        type: boolean
                      created_at:
                        type: string
                example:
                  success: true
                  data:
                    integration_instance_id: 1
                    name: My Company
                    realm_id: '123456789'
                    environment: production
                    is_authenticated: true
                    is_auto_sync_enabled: true
                    created_at: '2024-01-01T00:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-qbo-integrations-complete
  /api/qbo/integrations/test-connection:
    get:
      tags:
      - QuickBooks Online
      summary: Test Connection
      description: 'Tests the QBO API connection by making a CompanyInfo API call.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      success:
                        type: boolean
                      company_name:
                        type: string
                      realm_id:
                        type: string
                example:
                  success: true
                  data:
                    success: true
                    company_name: My Company
                    realm_id: '123456789'
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-qbo-integrations-test-connection
  /api/qbo/integrations/{id}:
    patch:
      tags:
      - QuickBooks Online
      summary: Update Integration Settings
      description: 'Updates settings for a QBO integration instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                is_automatic_sync_enabled:
                  type: boolean
                name:
                  type: string
              example:
                is_automatic_sync_enabled: true
                name: My Company QBO
      parameters:
      - name: id
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The record ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      realm_id:
                        type: string
                      environment:
                        type: string
                      is_authenticated:
                        type: boolean
                      is_auto_sync_enabled:
                        type: boolean
                      sync_due_dates:
                        type: boolean
                      connection_status:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  success: true
                  message: Settings updated successfully
                  data:
                    id: 1
                    name: My Company QBO
                    realm_id: '123456789'
                    environment: production
                    is_authenticated: true
                    is_auto_sync_enabled: true
                    sync_due_dates: true
                    connection_status: connected
                    created_at: '2024-01-01T00:00:00.000000Z'
                    updated_at: '2024-01-01T00:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: patch-api-qbo-integrations-id
    delete:
      tags:
      - QuickBooks Online
      summary: Delete Integration
      description: 'Queues deletion of a QBO integration instance and all associated
        data.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: id
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The record ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      instance_id:
                        type: integer
                      status:
                        type: string
                example:
                  success: true
                  message: QBO integration instance deletion has been queued
                  data:
                    instance_id: 1
                    status: deletion_queued
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-qbo-integrations-id
  /api/qbo/dashboard:
    get:
      tags:
      - QuickBooks Online
      summary: Get Dashboard
      description: 'Returns comprehensive dashboard metrics including entity counts,
        sync status, and connection health.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      connection:
                        type: object
                        properties:
                          status:
                            type: string
                          realm_id:
                            type: string
                      entity_counts:
                        type: object
                        properties:
                          accounts:
                            type: integer
                          invoices:
                            type: integer
                          customers:
                            type: integer
                      sync_status:
                        type: object
                        properties:
                          last_sync_at:
                            type: string
                example:
                  success: true
                  data:
                    connection:
                      status: connected
                      realm_id: '123456789'
                    entity_counts:
                      accounts: 150
                      invoices: 500
                      customers: 200
                    sync_status:
                      last_sync_at: '2024-01-01T00:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-qbo-dashboard
  /api/qbo/accounts:
    get:
      tags:
      - QuickBooks Online
      summary: List Accounts
      description: 'Paginated list of QBO accounts with filtering and sorting. Defaults
        to active accounts only.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Searchable columns (filter[search]): id, qbo_id, name, acct_num, fully_qualified_name,
        account_sub_type.'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        example: '1'
        description: Page number (default 1).
      - name: per_page
        in: query
        schema:
          type: integer
        example: '15'
        description: Results per page (default 10).
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        qbo_id:
                          type: string
                        name:
                          type: string
                        account_type:
                          type: string
                        account_sub_type:
                          type: string
                        acct_num:
                          type: string
                        classification:
                          type: string
                        active:
                          type: boolean
                        sync_status:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 1
                    qbo_id: '1'
                    name: Checking
                    account_type: Bank
                    account_sub_type: Checking
                    acct_num: '1000'
                    classification: Asset
                    active: true
                    sync_status: synced
                  current_page: 1
                  last_page: 1
                  per_page: 15
                  total: 1
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-qbo-accounts
    delete:
      tags:
      - QuickBooks Online
      summary: Delete Accounts
      description: 'Delete one or more QBO accounts by ID.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      deleted_count:
                        type: integer
                example:
                  success: true
                  message: Successfully deleted 3 QBO accounts(s)
                  data:
                    deleted_count: 3
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: delete-api-qbo-accounts
  /api/qbo/accounts/{id}:
    get:
      tags:
      - QuickBooks Online
      summary: Get Account
      description: 'Get a single QBO account by ID.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: id
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The record ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      qbo_id:
                        type: string
                      name:
                        type: string
                      account_type:
                        type: string
                      classification:
                        type: string
                      active:
                        type: boolean
                example:
                  success: true
                  data:
                    id: 1
                    qbo_id: '1'
                    name: Checking
                    account_type: Bank
                    classification: Asset
                    active: true
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-qbo-accounts-id
  /api/qbo/accounts/refresh:
    post:
      tags:
      - QuickBooks Online
      summary: Refresh Accounts
      description: 'Syncs accounts from QBO API. Omit body for incremental sync, pass
        full_sync=true for complete resync.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                start_date:
                  type: string
                end_date:
                  type: string
                full_sync:
                  type: boolean
              example:
                start_date: 01/01/2024
                end_date: 12/31/2024
                full_sync: false
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      created:
                        type: integer
                      updated:
                        type: integer
                      sync_type:
                        type: string
                example:
                  success: true
                  message: QBO accounts refresh completed successfully
                  data:
                    created: 5
                    updated: 10
                    sync_type: date_range
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-qbo-accounts-refresh
  /api/qbo/accounts/refresh-tracked:
    post:
      tags:
      - QuickBooks Online
      summary: Refresh Accounts in Background
      description: 'Starts a background refresh of accounts from QuickBooks and returns
        a job id you can poll for progress. Send no parameters for an incremental
        sync (records changed since the last sync), `full_sync: true` to re-pull everything,
        or `start_date` + `end_date` (MM/DD/YYYY) to pull records updated within a
        date range.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                full_sync:
                  type: boolean
              example:
                full_sync: false
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                      sync_type:
                        type: string
                      sync_description:
                        type: string
                example:
                  success: true
                  message: QBO accounts refresh started.
                  data:
                    tracked_job_log_id: 8123
                    sync_type: incremental
                    sync_description: Incremental sync (changes since last sync)
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-qbo-accounts-refresh-tracked
  /api/qbo/accounts/sync-info:
    get:
      tags:
      - QuickBooks Online
      summary: Get Accounts Sync Info
      description: Returns the latest synced account identifier and timestamp, the
        total number of accounts already stored, and the fields you can search QuickBooks
        by for this entity.
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      latest_identifier:
                        type: string
                      latest_date:
                        type: string
                      total_count:
                        type: integer
                      searchable_fields:
                        type: array
                        items:
                          type: object
                          properties:
                            value:
                              type: string
                            label:
                              type: string
                            qbo_field:
                              type: string
                            exact:
                              type: boolean
                example:
                  success: true
                  data:
                    latest_identifier: REF-1042
                    latest_date: '2026-07-16T18:22:05.000000Z'
                    total_count: 128
                    searchable_fields:
                    - value: doc_number
                      label: Doc Number
                      qbo_field: DocNumber
                      exact: false
                    - value: qbo_id
                      label: QuickBooks ID
                      qbo_field: Id
                      exact: true
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-qbo-accounts-sync-info
  /api/qbo/accounts/search-qbo:
    post:
      tags:
      - QuickBooks Online
      summary: Search Accounts in QuickBooks
      description: Searches QuickBooks directly for accounts matching a field/value
        (without importing them). `field` must be one of the values returned by Get
        Accounts Sync Info (e.g. `doc_number`, `qbo_id`). Each result flags whether
        it already exists in your database.
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                field:
                  type: string
                value:
                  type: string
              example:
                field: doc_number
                value: '1042'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        qbo_id:
                          type: string
                        label:
                          type: string
                        sub_label:
                          type: string
                        exists_in_database:
                          type: boolean
                example:
                  success: true
                  data:
                  - qbo_id: '1042'
                    label: INV-1042
                    sub_label: QuickBooks ID 1042
                    exists_in_database: true
                  - qbo_id: '1043'
                    label: INV-1043
                    sub_label: QuickBooks ID 1043
                    exists_in_database: false
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-qbo-accounts-search-qbo
  /api/qbo/accounts/refresh-single:
    post:
      tags:
      - QuickBooks Online
      summary: Pull Account from QuickBooks
      description: Fetches a single account from QuickBooks by its QuickBooks id and
        imports (or updates) it in your database.
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                qbo_id:
                  type: string
              example:
                qbo_id: '1043'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      success:
                        type: boolean
                      qbo_id:
                        type: string
                      id:
                        type: integer
                example:
                  success: true
                  message: QBO account pulled from QuickBooks.
                  data:
                    success: true
                    qbo_id: '1043'
                    id: 991
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-qbo-accounts-refresh-single
  /api/qbo/accounts/export:
    get:
      tags:
      - QuickBooks Online
      summary: Export Accounts
      description: 'Export accounts to CSV. Supports date range filtering.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: format
        in: query
        schema:
          type: string
        example: csv
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-qbo-accounts-export
  /api/qbo/accounts/statistics:
    get:
      tags:
      - QuickBooks Online
      summary: Get Account Statistics
      description: 'Get aggregate statistics for QBO accounts.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      total:
                        type: integer
                      active:
                        type: integer
                      archived:
                        type: integer
                      by_type:
                        type: object
                        properties:
                          Bank:
                            type: integer
                          Accounts Receivable:
                            type: integer
                example:
                  success: true
                  data:
                    total: 150
                    active: 140
                    archived: 10
                    by_type:
                      Bank: 20
                      Accounts Receivable: 5
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-qbo-accounts-statistics
  /api/qbo/accounts/archive:
    post:
      tags:
      - QuickBooks Online
      summary: Archive Accounts
      description: 'Archive one or more QBO accounts by ID.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1
                - 2
                - 3
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      archived_count:
                        type: integer
                example:
                  success: true
                  message: Successfully archived 3 QBO accounts(s)
                  data:
                    archived_count: 3
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-qbo-accounts-archive
  /api/qbo/accounts/unarchive:
    post:
      tags:
      - QuickBooks Online
      summary: Unarchive Accounts
      description: 'Unarchive one or more QBO accounts by ID.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1
                - 2
                - 3
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      unarchived_count:
                        type: integer
                example:
                  success: true
                  message: Successfully unarchived 3 QBO accounts(s)
                  data:
                    unarchived_count: 3
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-qbo-accounts-unarchive
  /api/qbo/accounts/nominal-codes:
    post:
      tags:
      - QuickBooks Online
      summary: Create Nominal Codes
      description: 'Creates SKU nominal codes from selected QBO accounts.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                account_ids:
                  type: array
                  items:
                    type: integer
              example:
                account_ids:
                - 1
                - 2
                - 3
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      created:
                        type: integer
                      existing:
                        type: integer
                example:
                  success: true
                  message: Nominal codes created successfully. Created 3, skipped
                    0 existing.
                  data:
                    created: 3
                    existing: 0
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-qbo-accounts-nominal-codes
  /api/qbo/accounts/adopt-chart:
    post:
      tags:
      - QuickBooks Online
      summary: Adopt QuickBooks Chart of Accounts (hard-replace)
      description: 'Onboarding: hard-replace SKU''s chart of accounts with QuickBooks''s.
        Imports every mapped QBO account as a nominal code (code = AcctNum or QBO
        id, type mapped from the QBO account type), re-points every reference (sales
        order lines, settings roles, product/channel/warehouse overrides, …) onto
        the replacements, then deletes the old chart. EVERY existing nominal code
        must appear in `mappings` (a complete old→new map is what makes the delete
        safe) — otherwise the job fails listing the unmapped ids. Requires a connected
        QuickBooks accounting integration (404 otherwise). Runs as a tracked job;
        returns its log id so the UI can follow progress via the tracked job log endpoints.
        Pass `repost: true` to also repost every current ledger entry after the replace
        (chained inside the job) so posted GL lines pick up the new accounts.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Body:** `mappings[]` (required) — each `{ nominal_code_id, qbo_account_id
        }`. `repost` (optional bool).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                mappings:
                  type: array
                  items:
                    type: object
                    properties:
                      nominal_code_id:
                        type: integer
                      qbo_account_id:
                        type: integer
                repost:
                  type: boolean
              example:
                mappings:
                - nominal_code_id: 12
                  qbo_account_id: 5
                - nominal_code_id: 7
                  qbo_account_id: 9
                repost: true
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 4821
                  message: Adopting the QuickBooks chart of accounts — track progress
                    in the job tray.
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                example:
                  success: false
                  message: No QuickBooks accounting integration found
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      mappings:
                        type: array
                        items:
                          type: string
                example:
                  message: The mappings field is required.
                  errors:
                    mappings:
                    - The mappings field is required.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-qbo-accounts-adopt-chart
  /api/qbo/accounts/{id}/activity-log:
    get:
      tags:
      - QuickBooks Online
      summary: Get Account Activity Log
      description: 'Retrieve the audit trail for a synced QuickBooks Online account.
        Each entry records a create, update, or delete event on the local copy of
        the record, including the changed attributes, their previous values, and the
        user or process that made the change.


        Results are ordered newest first and paginated (standard pagination metadata
        is included in the response).


        Returns 404 if the account does not exist.


        Authentication: Requires Bearer token.'
      parameters:
      - name: id
        in: path
        schema:
          type: string
        required: true
        description: The record ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        description:
                          type: string
                        event:
                          type: string
                        subject_type:
                          type: string
                        subject_id:
                          type: integer
                        batch_uuid:
                          type: string
                          nullable: true
                        properties:
                          type: object
                          properties:
                            attributes:
                              type: object
                              properties:
                                sync_status:
                                  type: string
                            old:
                              type: object
                              properties:
                                sync_status:
                                  type: string
                            metadata:
                              type: object
                              properties:
                                id:
                                  type: integer
                                name:
                                  type: string
                                qbo_id:
                                  type: string
                        causer_name:
                          type: string
                        created_at:
                          type: string
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 5821
                    description: updated
                    event: updated
                    subject_type: QboAccount
                    subject_id: 87
                    batch_uuid: null
                    properties:
                      attributes:
                        sync_status: ok
                      old:
                        sync_status: sku_updated_pending_sync
                      metadata:
                        id: 87
                        name: Inventory Asset
                        qbo_id: '55'
                    causer_name: Jane Smith
                    created_at: '2026-06-18T14:22:31.000000Z'
                  first_page_url: …?page=1
                  from: 1
                  last_page: 1
                  last_page_url: …?page=1
                  links: []
                  next_page_url: null
                  path: …/api/qbo/accounts/87/activity-log
                  per_page: 15
                  prev_page_url: null
                  to: 1
                  total: 1
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Record not found.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-qbo-accounts-id-activity-log
  /api/qbo/bills:
    get:
      tags:
      - QuickBooks Online
      summary: List Bills
      description: 'Paginated list of QBO bills with filtering and sorting.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Searchable columns (filter[search]): id, qbo_id, doc_number, vendor_name.'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        example: '1'
        description: Page number (default 1).
      - name: per_page
        in: query
        schema:
          type: integer
        example: '15'
        description: Results per page (default 10).
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        qbo_id:
                          type: string
                        doc_number:
                          type: string
                        total_amount:
                          type: string
                        sync_status:
                          type: string
                        qbo_link:
                          type: string
                  current_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 1
                    qbo_id: '1'
                    doc_number: BILL-001
                    total_amount: '500.00'
                    sync_status: synced
                    qbo_link: https://app.qbo.intuit.com/app/bill?txnId=201
                  current_page: 1
                  total: 1
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-qbo-bills
    delete:
      tags:
      - QuickBooks Online
      summary: Delete Bills
      description: 'Delete one or more QBO bills.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: delete-api-qbo-bills
  /api/qbo/bills/{id}:
    get:
      tags:
      - QuickBooks Online
      summary: Get Bill
      description: 'Get a single QBO bill by ID.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        This document is pushed to QuickBooks by SKU''s ledger, so the response includes
        reverse cross-link fields: `ledger_entry_id` and `ledger_entry_reference`
        identify the SKU ledger entry that pushed it, while `sku_link_type`, `sku_link_id`,
        `sku_link_label`, and `sku_link_route` point back to the originating SKU document.
        These are `null` when the document originated in QuickBooks rather than being
        pushed by SKU. `vendor_link_id` cross-links to the mirrored QuickBooks vendor.
        Returns `line_items` (normalized line rows parsed from the stored QuickBooks
        payload) and `detail_payload` (the full raw QuickBooks payload); both are
        null until the document is re-synced from QuickBooks.


        Also returns an `amounts` summary (`subtotal`, `tax`, `total`, `balance`,
        `paid`) and a `tax_code` on each `line_items` row.'
      parameters:
      - name: id
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The record ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      qbo_id:
                        type: string
                      doc_number:
                        type: string
                      name:
                        type: string
                      vendor_id:
                        type: string
                      vendor_name:
                        type: string
                      total_amount:
                        type: string
                      currency:
                        type: string
                      due_date:
                        type: string
                      txn_date:
                        type: string
                      status:
                        type: string
                      active:
                        type: boolean
                      sync_status:
                        type: string
                      last_synced_at:
                        type: string
                      last_qbo_check_at:
                        type: string
                      sync_error_message:
                        type: string
                        nullable: true
                      qbo_created_at:
                        type: string
                      qbo_updated_at:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      integration_instance:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      qbo_link:
                        type: string
                      vendor_link_id:
                        type: integer
                      ledger_entry_id:
                        type: integer
                      ledger_entry_reference:
                        type: string
                      sku_link_type:
                        type: string
                      sku_link_id:
                        type: integer
                      sku_link_label:
                        type: string
                      sku_link_route:
                        type: string
                      amounts:
                        type: object
                        properties:
                          subtotal:
                            type: integer
                          tax:
                            type: integer
                          total:
                            type: integer
                          balance:
                            type: integer
                          paid:
                            type: integer
                      line_items:
                        type: array
                        items:
                          type: object
                          properties:
                            line_num:
                              type: integer
                            description:
                              type: string
                            detail_type:
                              type: string
                            item:
                              type: string
                              nullable: true
                            item_id:
                              type: string
                              nullable: true
                            item_link_id:
                              type: string
                              nullable: true
                            account:
                              type: string
                            quantity:
                              type: string
                              nullable: true
                            unit_price:
                              type: string
                              nullable: true
                            amount:
                              type: integer
                            tax_code:
                              type: string
                            posting_type:
                              type: string
                              nullable: true
                      detail_payload:
                        type: object
                        properties:
                          Id:
                            type: string
                          DocNumber:
                            type: string
                          TxnDate:
                            type: string
                          TotalAmt:
                            type: integer
                          VendorRef:
                            type: object
                            properties:
                              value:
                                type: string
                              name:
                                type: string
                          CurrencyRef:
                            type: object
                            properties:
                              value:
                                type: string
                          Line:
                            type: array
                            items:
                              type: object
                              properties:
                                Id:
                                  type: string
                                Amount:
                                  type: integer
                                DetailType:
                                  type: string
                                Description:
                                  type: string
                                AccountBasedExpenseLineDetail:
                                  type: object
                                  properties:
                                    AccountRef:
                                      type: object
                                      properties:
                                        value:
                                          type: string
                                        name:
                                          type: string
                          sparse:
                            type: boolean
                example:
                  success: true
                  data:
                    id: 61
                    integration_instance_id: 3
                    qbo_id: '201'
                    doc_number: BILL-8114
                    name: BILL-8114
                    vendor_id: '56'
                    vendor_name: Shanghai Supplier Co
                    total_amount: '1250.00'
                    currency: USD
                    due_date: '2026-08-15'
                    txn_date: '2026-07-05'
                    status: Open
                    active: true
                    sync_status: ok
                    last_synced_at: '2026-07-15T10:00:00.000000Z'
                    last_qbo_check_at: '2026-07-15T10:00:00.000000Z'
                    sync_error_message: null
                    qbo_created_at: '2026-07-01T09:00:00.000000Z'
                    qbo_updated_at: '2026-07-14T18:30:00.000000Z'
                    created_at: '2026-07-01T09:05:00.000000Z'
                    updated_at: '2026-07-14T18:35:00.000000Z'
                    integration_instance:
                      id: 3
                      name: QuickBooks Online
                    qbo_link: https://app.qbo.intuit.com/app/bill?txnId=201
                    vendor_link_id: 57
                    ledger_entry_id: 12506
                    ledger_entry_reference: O260724VOY4F6/R1
                    sku_link_type: App\Models\SalesOrder
                    sku_link_id: 4242
                    sku_link_label: Sales Order
                    sku_link_route: /orders/sales-orders/4242
                    amounts:
                      subtotal: 550
                      tax: 40
                      total: 590
                      balance: 90
                      paid: 500
                    line_items:
                    - line_num: 1
                      description: Cold-chain freight
                      detail_type: AccountBasedExpenseLineDetail
                      item: null
                      item_id: null
                      item_link_id: null
                      account: Shipping & Freight
                      quantity: null
                      unit_price: null
                      amount: 125
                      tax_code: TAX
                      posting_type: null
                    detail_payload:
                      Id: '201'
                      DocNumber: BILL-8114
                      TxnDate: '2026-07-05'
                      TotalAmt: 1250
                      VendorRef:
                        value: '56'
                        name: Shanghai Supplier Co
                      CurrencyRef:
                        value: USD
                      Line:
                      - Id: '1'
                        Amount: 125
                        DetailType: AccountBasedExpenseLineDetail
                        Description: Cold-chain freight
                        AccountBasedExpenseLineDetail:
                          AccountRef:
                            value: '63'
                            name: Shipping & Freight
                      sparse: false
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-qbo-bills-id
  /api/qbo/bills/refresh:
    post:
      tags:
      - QuickBooks Online
      summary: Refresh Bills
      description: 'Syncs bills from QBO API.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                full_sync:
                  type: boolean
              example:
                full_sync: false
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-qbo-bills-refresh
  /api/qbo/bills/refresh-tracked:
    post:
      tags:
      - QuickBooks Online
      summary: Refresh Bills in Background
      description: 'Starts a background refresh of bills from QuickBooks and returns
        a job id you can poll for progress. Send no parameters for an incremental
        sync (records changed since the last sync), `full_sync: true` to re-pull everything,
        or `start_date` + `end_date` (MM/DD/YYYY) to pull records updated within a
        date range.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                full_sync:
                  type: boolean
              example:
                full_sync: false
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                      sync_type:
                        type: string
                      sync_description:
                        type: string
                example:
                  success: true
                  message: QBO bills refresh started.
                  data:
                    tracked_job_log_id: 8123
                    sync_type: incremental
                    sync_description: Incremental sync (changes since last sync)
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-qbo-bills-refresh-tracked
  /api/qbo/bills/sync-info:
    get:
      tags:
      - QuickBooks Online
      summary: Get Bills Sync Info
      description: Returns the latest synced bill identifier and timestamp, the total
        number of bills already stored, and the fields you can search QuickBooks by
        for this entity.
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      latest_identifier:
                        type: string
                      latest_date:
                        type: string
                      total_count:
                        type: integer
                      searchable_fields:
                        type: array
                        items:
                          type: object
                          properties:
                            value:
                              type: string
                            label:
                              type: string
                            qbo_field:
                              type: string
                            exact:
                              type: boolean
                example:
                  success: true
                  data:
                    latest_identifier: REF-1042
                    latest_date: '2026-07-16T18:22:05.000000Z'
                    total_count: 128
                    searchable_fields:
                    - value: doc_number
                      label: Doc Number
                      qbo_field: DocNumber
                      exact: false
                    - value: qbo_id
                      label: QuickBooks ID
                      qbo_field: Id
                      exact: true
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-qbo-bills-sync-info
  /api/qbo/bills/search-qbo:
    post:
      tags:
      - QuickBooks Online
      summary: Search Bills in QuickBooks
      description: Searches QuickBooks directly for bills matching a field/value (without
        importing them). `field` must be one of the values returned by Get Bills Sync
        Info (e.g. `doc_number`, `qbo_id`). Each result flags whether it already exists
        in your database.
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                field:
                  type: string
                value:
                  type: string
              example:
                field: doc_number
                value: '1042'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        qbo_id:
                          type: string
                        label:
                          type: string
                        sub_label:
                          type: string
                        exists_in_database:
                          type: boolean
                example:
                  success: true
                  data:
                  - qbo_id: '1042'
                    label: INV-1042
                    sub_label: QuickBooks ID 1042
                    exists_in_database: true
                  - qbo_id: '1043'
                    label: INV-1043
                    sub_label: QuickBooks ID 1043
                    exists_in_database: false
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-qbo-bills-search-qbo
  /api/qbo/bills/refresh-single:
    post:
      tags:
      - QuickBooks Online
      summary: Pull Bill from QuickBooks
      description: Fetches a single bill from QuickBooks by its QuickBooks id and
        imports (or updates) it in your database.
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                qbo_id:
                  type: string
              example:
                qbo_id: '1043'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      success:
                        type: boolean
                      qbo_id:
                        type: string
                      id:
                        type: integer
                example:
                  success: true
                  message: QBO bill pulled from QuickBooks.
                  data:
                    success: true
                    qbo_id: '1043'
                    id: 991
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-qbo-bills-refresh-single
  /api/qbo/bills/export:
    get:
      tags:
      - QuickBooks Online
      summary: Export Bills
      description: 'Export bills to CSV.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: format
        in: query
        schema:
          type: string
        example: csv
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-qbo-bills-export
  /api/qbo/bills/statistics:
    get:
      tags:
      - QuickBooks Online
      summary: Get Bill Statistics
      description: 'Get aggregate statistics for QBO bills.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-qbo-bills-statistics
  /api/qbo/bills/archive:
    post:
      tags:
      - QuickBooks Online
      summary: Archive Bills
      description: 'Archive one or more QBO bills.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-qbo-bills-archive
  /api/qbo/bills/unarchive:
    post:
      tags:
      - QuickBooks Online
      summary: Unarchive Bills
      description: 'Unarchive one or more QBO bills.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-qbo-bills-unarchive
  /api/qbo/bills/{id}/activity-log:
    get:
      tags:
      - QuickBooks Online
      summary: Get Bill Activity Log
      description: 'Retrieve the audit trail for a synced QuickBooks Online bill.
        Each entry records a create, update, or delete event on the local copy of
        the record, including the changed attributes, their previous values, and the
        user or process that made the change.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Results are ordered newest first and paginated (standard pagination metadata
        is included in the response).


        Returns 404 if the bill does not exist.


        Authentication: Requires Bearer token.'
      parameters:
      - name: id
        in: path
        schema:
          type: string
        required: true
        description: The record ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        description:
                          type: string
                        event:
                          type: string
                        subject_type:
                          type: string
                        subject_id:
                          type: integer
                        batch_uuid:
                          type: string
                          nullable: true
                        properties:
                          type: object
                          properties:
                            attributes:
                              type: object
                              properties:
                                sync_status:
                                  type: string
                            old:
                              type: object
                              properties:
                                sync_status:
                                  type: string
                            source:
                              type: string
                        causer_name:
                          type: string
                        created_at:
                          type: string
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                    items:
                      type: object
                      properties:
                        url:
                          type: string
                          nullable: true
                        label:
                          type: string
                        active:
                          type: boolean
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 5821
                    description: updated
                    event: updated
                    subject_type: QboBill
                    subject_id: 87
                    batch_uuid: null
                    properties:
                      attributes:
                        sync_status: synced
                      old:
                        sync_status: pending
                      source: qbo_sync
                    causer_name: Jane Smith
                    created_at: '2026-06-18T14:22:31.000000Z'
                  first_page_url: '{{protocol}}://{{domain}}/api/qbo/bills/87/activity-log?page=1'
                  from: 1
                  last_page: 1
                  last_page_url: '{{protocol}}://{{domain}}/api/qbo/bills/87/activity-log?page=1'
                  links:
                  - url: null
                    label: '&laquo; Previous'
                    active: false
                  - url: '{{protocol}}://{{domain}}/api/qbo/bills/87/activity-log?page=1'
                    label: '1'
                    active: true
                  - url: null
                    label: Next &raquo;
                    active: false
                  next_page_url: null
                  path: '{{protocol}}://{{domain}}/api/qbo/bills/87/activity-log'
                  per_page: 15
                  prev_page_url: null
                  to: 1
                  total: 1
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: object
                    properties:
                      id:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: array
                example:
                  errors:
                    id:
                    - message: Record not found.
                      code: NotFound
                      data: []
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-qbo-bills-id-activity-log
  /api/qbo/credit-memos:
    get:
      tags:
      - QuickBooks Online
      summary: List Credit Memos
      description: 'Paginated list of QBO credit memos.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Searchable columns (filter[search]): id, qbo_id, doc_number, customer_name.'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        example: '1'
        description: Page number (default 1).
      - name: per_page
        in: query
        schema:
          type: integer
        example: '15'
        description: Results per page (default 10).
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-qbo-credit-memos
    delete:
      tags:
      - QuickBooks Online
      summary: Delete Credit Memos
      description: 'Delete one or more QBO credit memos.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: delete-api-qbo-credit-memos
  /api/qbo/credit-memos/{id}:
    get:
      tags:
      - QuickBooks Online
      summary: Get Credit Memo
      description: 'Get a single QBO credit memo by ID.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        This document is pushed to QuickBooks by SKU''s ledger, so the response includes
        reverse cross-link fields: `ledger_entry_id` and `ledger_entry_reference`
        identify the SKU ledger entry that pushed it, while `sku_link_type`, `sku_link_id`,
        `sku_link_label`, and `sku_link_route` point back to the originating SKU document.
        These are `null` when the document originated in QuickBooks rather than being
        pushed by SKU. `customer_link_id` and `sku_customer_id` cross-link to the
        mirrored QuickBooks customer and its linked SKU customer. Returns `line_items`
        (normalized line rows parsed from the stored QuickBooks payload) and `detail_payload`
        (the full raw QuickBooks payload); both are null until the document is re-synced
        from QuickBooks.


        Also returns an `amounts` summary (`subtotal`, `tax`, `total`, `balance`,
        `paid`) and a `tax_code` on each `line_items` row.'
      parameters:
      - name: id
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The record ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      qbo_id:
                        type: string
                      doc_number:
                        type: string
                      name:
                        type: string
                      customer_id:
                        type: string
                      customer_name:
                        type: string
                      total_amount:
                        type: string
                      currency:
                        type: string
                      txn_date:
                        type: string
                      status:
                        type: string
                      active:
                        type: boolean
                      sync_status:
                        type: string
                      last_synced_at:
                        type: string
                      last_qbo_check_at:
                        type: string
                      sync_error_message:
                        type: string
                        nullable: true
                      qbo_created_at:
                        type: string
                      qbo_updated_at:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      integration_instance:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      qbo_link:
                        type: string
                      customer_link_id:
                        type: integer
                      sku_customer_id:
                        type: integer
                      ledger_entry_id:
                        type: integer
                      ledger_entry_reference:
                        type: string
                      sku_link_type:
                        type: string
                      sku_link_id:
                        type: integer
                      sku_link_label:
                        type: string
                      sku_link_route:
                        type: string
                      amounts:
                        type: object
                        properties:
                          subtotal:
                            type: integer
                          tax:
                            type: integer
                          total:
                            type: integer
                          balance:
                            type: integer
                          paid:
                            type: integer
                      line_items:
                        type: array
                        items:
                          type: object
                          properties:
                            line_num:
                              type: integer
                            description:
                              type: string
                            detail_type:
                              type: string
                            item:
                              type: string
                            item_id:
                              type: string
                            item_link_id:
                              type: integer
                            account:
                              type: string
                              nullable: true
                            quantity:
                              type: integer
                            unit_price:
                              type: number
                            amount:
                              type: integer
                            tax_code:
                              type: string
                            posting_type:
                              type: string
                              nullable: true
                      detail_payload:
                        type: object
                        properties:
                          Id:
                            type: string
                          DocNumber:
                            type: string
                          TxnDate:
                            type: string
                          TotalAmt:
                            type: integer
                          CustomerRef:
                            type: object
                            properties:
                              value:
                                type: string
                              name:
                                type: string
                          CurrencyRef:
                            type: object
                            properties:
                              value:
                                type: string
                          Line:
                            type: array
                            items:
                              type: object
                              properties:
                                Id:
                                  type: string
                                LineNum:
                                  type: integer
                                Amount:
                                  type: integer
                                DetailType:
                                  type: string
                                Description:
                                  type: string
                                SalesItemLineDetail:
                                  type: object
                                  properties:
                                    ItemRef:
                                      type: object
                                      properties:
                                        value:
                                          type: string
                                        name:
                                          type: string
                                    Qty:
                                      type: integer
                                    UnitPrice:
                                      type: number
                          sparse:
                            type: boolean
                example:
                  success: true
                  data:
                    id: 44
                    integration_instance_id: 3
                    qbo_id: '305'
                    doc_number: CN-8231
                    name: CN-8231
                    customer_id: '12'
                    customer_name: Bar Supply Co
                    total_amount: '99.00'
                    currency: USD
                    txn_date: '2026-07-03'
                    status: Open
                    active: true
                    sync_status: ok
                    last_synced_at: '2026-07-15T10:00:00.000000Z'
                    last_qbo_check_at: '2026-07-15T10:00:00.000000Z'
                    sync_error_message: null
                    qbo_created_at: '2026-07-01T09:00:00.000000Z'
                    qbo_updated_at: '2026-07-14T18:30:00.000000Z'
                    created_at: '2026-07-01T09:05:00.000000Z'
                    updated_at: '2026-07-14T18:35:00.000000Z'
                    integration_instance:
                      id: 3
                      name: QuickBooks Online
                    qbo_link: https://app.qbo.intuit.com/app/creditmemo?txnId=305
                    customer_link_id: 88
                    sku_customer_id: 1420
                    ledger_entry_id: 12506
                    ledger_entry_reference: O260724VOY4F6/R1
                    sku_link_type: App\Models\SalesOrder
                    sku_link_id: 4242
                    sku_link_label: Sales Order
                    sku_link_route: /orders/sales-orders/4242
                    amounts:
                      subtotal: 550
                      tax: 40
                      total: 590
                      balance: 90
                      paid: 500
                    line_items:
                    - line_num: 1
                      description: Osetra Caviar 4.4 oz
                      detail_type: SalesItemLineDetail
                      item: RO125G
                      item_id: '70'
                      item_link_id: 42
                      account: null
                      quantity: 4
                      unit_price: 147.5
                      amount: 590
                      tax_code: TAX
                      posting_type: null
                    detail_payload:
                      Id: '305'
                      DocNumber: CN-8231
                      TxnDate: '2026-07-03'
                      TotalAmt: 99
                      CustomerRef:
                        value: '12'
                        name: Bar Supply Co
                      CurrencyRef:
                        value: USD
                      Line:
                      - Id: '1'
                        LineNum: 1
                        Amount: 590
                        DetailType: SalesItemLineDetail
                        Description: Osetra Caviar 4.4 oz
                        SalesItemLineDetail:
                          ItemRef:
                            value: '21'
                            name: RO125G
                          Qty: 4
                          UnitPrice: 147.5
                      sparse: false
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-qbo-credit-memos-id
  /api/qbo/credit-memos/refresh:
    post:
      tags:
      - QuickBooks Online
      summary: Refresh Credit Memos
      description: 'Syncs credit memos from QBO API.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                full_sync:
                  type: boolean
              example:
                full_sync: false
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-qbo-credit-memos-refresh
  /api/qbo/credit-memos/refresh-tracked:
    post:
      tags:
      - QuickBooks Online
      summary: Refresh Credit Memos in Background
      description: 'Starts a background refresh of credit memos from QuickBooks and
        returns a job id you can poll for progress. Send no parameters for an incremental
        sync (records changed since the last sync), `full_sync: true` to re-pull everything,
        or `start_date` + `end_date` (MM/DD/YYYY) to pull records updated within a
        date range.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                full_sync:
                  type: boolean
              example:
                full_sync: false
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                      sync_type:
                        type: string
                      sync_description:
                        type: string
                example:
                  success: true
                  message: QBO credit-memos refresh started.
                  data:
                    tracked_job_log_id: 8123
                    sync_type: incremental
                    sync_description: Incremental sync (changes since last sync)
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-qbo-credit-memos-refresh-tracked
  /api/qbo/credit-memos/sync-info:
    get:
      tags:
      - QuickBooks Online
      summary: Get Credit Memos Sync Info
      description: Returns the latest synced credit memo identifier and timestamp,
        the total number of credit memos already stored, and the fields you can search
        QuickBooks by for this entity.
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      latest_identifier:
                        type: string
                      latest_date:
                        type: string
                      total_count:
                        type: integer
                      searchable_fields:
                        type: array
                        items:
                          type: object
                          properties:
                            value:
                              type: string
                            label:
                              type: string
                            qbo_field:
                              type: string
                            exact:
                              type: boolean
                example:
                  success: true
                  data:
                    latest_identifier: REF-1042
                    latest_date: '2026-07-16T18:22:05.000000Z'
                    total_count: 128
                    searchable_fields:
                    - value: doc_number
                      label: Doc Number
                      qbo_field: DocNumber
                      exact: false
                    - value: qbo_id
                      label: QuickBooks ID
                      qbo_field: Id
                      exact: true
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-qbo-credit-memos-sync-info
  /api/qbo/credit-memos/search-qbo:
    post:
      tags:
      - QuickBooks Online
      summary: Search Credit Memos in QuickBooks
      description: Searches QuickBooks directly for credit memos matching a field/value
        (without importing them). `field` must be one of the values returned by Get
        Credit Memos Sync Info (e.g. `doc_number`, `qbo_id`). Each result flags whether
        it already exists in your database.
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                field:
                  type: string
                value:
                  type: string
              example:
                field: doc_number
                value: '1042'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        qbo_id:
                          type: string
                        label:
                          type: string
                        sub_label:
                          type: string
                        exists_in_database:
                          type: boolean
                example:
                  success: true
                  data:
                  - qbo_id: '1042'
                    label: INV-1042
                    sub_label: QuickBooks ID 1042
                    exists_in_database: true
                  - qbo_id: '1043'
                    label: INV-1043
                    sub_label: QuickBooks ID 1043
                    exists_in_database: false
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-qbo-credit-memos-search-qbo
  /api/qbo/credit-memos/refresh-single:
    post:
      tags:
      - QuickBooks Online
      summary: Pull Credit Memo from QuickBooks
      description: Fetches a single credit memo from QuickBooks by its QuickBooks
        id and imports (or updates) it in your database.
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                qbo_id:
                  type: string
              example:
                qbo_id: '1043'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      success:
                        type: boolean
                      qbo_id:
                        type: string
                      id:
                        type: integer
                example:
                  success: true
                  message: QBO credit memo pulled from QuickBooks.
                  data:
                    success: true
                    qbo_id: '1043'
                    id: 991
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-qbo-credit-memos-refresh-single
  /api/qbo/credit-memos/export:
    get:
      tags:
      - QuickBooks Online
      summary: Export Credit Memos
      description: 'Export credit memos to CSV.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: format
        in: query
        schema:
          type: string
        example: csv
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-qbo-credit-memos-export
  /api/qbo/credit-memos/statistics:
    get:
      tags:
      - QuickBooks Online
      summary: Get Credit Memo Statistics
      description: 'Get aggregate statistics for QBO credit memos.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-qbo-credit-memos-statistics
  /api/qbo/credit-memos/archive:
    post:
      tags:
      - QuickBooks Online
      summary: Archive Credit Memos
      description: 'Archive one or more QBO credit memos.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-qbo-credit-memos-archive
  /api/qbo/credit-memos/unarchive:
    post:
      tags:
      - QuickBooks Online
      summary: Unarchive Credit Memos
      description: 'Unarchive one or more QBO credit memos.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-qbo-credit-memos-unarchive
  /api/qbo/credit-memos/{id}/activity-log:
    get:
      tags:
      - QuickBooks Online
      summary: Get Credit Memo Activity Log
      description: 'Retrieve the audit trail for a synced QuickBooks Online credit
        memo. Each entry records a create, update, or delete event on the local copy
        of the record, including the changed attributes, their previous values, and
        the user or process that made the change.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Results are ordered newest first and paginated (standard pagination metadata
        is included in the response).


        Returns 404 if the credit memo does not exist.


        Authentication: Requires Bearer token.'
      parameters:
      - name: id
        in: path
        schema:
          type: string
        required: true
        description: The record ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        description:
                          type: string
                        event:
                          type: string
                        subject_type:
                          type: string
                        subject_id:
                          type: integer
                        batch_uuid:
                          type: string
                          nullable: true
                        properties:
                          type: object
                          properties:
                            attributes:
                              type: object
                              properties:
                                sync_status:
                                  type: string
                            old:
                              type: object
                              properties:
                                sync_status:
                                  type: string
                            source:
                              type: string
                        causer_name:
                          type: string
                        created_at:
                          type: string
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                    items:
                      type: object
                      properties:
                        url:
                          type: string
                          nullable: true
                        label:
                          type: string
                        active:
                          type: boolean
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 5821
                    description: updated
                    event: updated
                    subject_type: QboCreditMemo
                    subject_id: 42
                    batch_uuid: null
                    properties:
                      attributes:
                        sync_status: synced
                      old:
                        sync_status: pending
                      source: qbo_sync
                    causer_name: Jane Smith
                    created_at: '2026-06-18T14:22:31.000000Z'
                  first_page_url: '{{protocol}}://{{domain}}/api/qbo/credit-memos/42/activity-log?page=1'
                  from: 1
                  last_page: 1
                  last_page_url: '{{protocol}}://{{domain}}/api/qbo/credit-memos/42/activity-log?page=1'
                  links:
                  - url: null
                    label: '&laquo; Previous'
                    active: false
                  - url: '{{protocol}}://{{domain}}/api/qbo/credit-memos/42/activity-log?page=1'
                    label: '1'
                    active: true
                  - url: null
                    label: Next &raquo;
                    active: false
                  next_page_url: null
                  path: '{{protocol}}://{{domain}}/api/qbo/credit-memos/42/activity-log'
                  per_page: 15
                  prev_page_url: null
                  to: 1
                  total: 1
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: object
                    properties:
                      id:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: array
                example:
                  errors:
                    id:
                    - message: Record not found.
                      code: NotFound
                      data: []
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-qbo-credit-memos-id-activity-log
  /api/qbo/customers:
    get:
      tags:
      - QuickBooks Online
      summary: List Customers
      description: 'Paginated list of QBO customers. Filter by linked=true/false to
        see SKU-linked customers.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Searchable columns (filter[search]): id, qbo_id, display_name, company_name,
        given_name, family_name, email.'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        example: '1'
        description: Page number (default 1).
      - name: per_page
        in: query
        schema:
          type: integer
        example: '15'
        description: Results per page (default 10).
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        qbo_id:
                          type: string
                        display_name:
                          type: string
                        company_name:
                          type: string
                        email:
                          type: string
                        active:
                          type: boolean
                        sku_customer_id:
                          type: string
                          nullable: true
                  current_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 1
                    qbo_id: '1'
                    display_name: John Doe
                    company_name: ACME Corp
                    email: john@acme.com
                    active: true
                    sku_customer_id: null
                  current_page: 1
                  total: 1
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-qbo-customers
    delete:
      tags:
      - QuickBooks Online
      summary: Delete Customers
      description: 'Delete one or more QBO customers.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: delete-api-qbo-customers
  /api/qbo/customers/{id}:
    get:
      tags:
      - QuickBooks Online
      summary: Get Customer
      description: 'Get a single QBO customer by ID.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: id
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The record ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-qbo-customers-id
  /api/qbo/customers/unlinked:
    get:
      tags:
      - QuickBooks Online
      summary: Get Unlinked Customers
      description: 'Returns QBO customers not yet linked to a SKU customer.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-qbo-customers-unlinked
  /api/qbo/customers/linked:
    get:
      tags:
      - QuickBooks Online
      summary: Get Linked Customers
      description: 'Returns QBO customers that are linked to a SKU customer.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-qbo-customers-linked
  /api/qbo/customers/create-sku-customers:
    post:
      tags:
      - QuickBooks Online
      summary: Create SKU Customers from QBO
      description: 'Bulk creates SKU customers from unlinked QBO customers. Omit ids
        to process all unlinked.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1
                - 2
                - 3
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                  created:
                    type: integer
                  linked:
                    type: integer
                  failed:
                    type: integer
                example:
                  success: true
                  message: Created 3, linked to existing 0, failed 0.
                  created: 3
                  linked: 0
                  failed: 0
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-qbo-customers-create-sku-customers
  /api/qbo/customers/refresh-sku-customers:
    post:
      tags:
      - QuickBooks Online
      summary: Refresh SKU Customers from QBO
      description: 'Bulk refreshes linked SKU customers from their QBO counterparts.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1
                - 2
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-qbo-customers-refresh-sku-customers
  /api/qbo/customers/unlink-sku-customers:
    post:
      tags:
      - QuickBooks Online
      summary: Unlink SKU Customers (Bulk)
      description: 'Bulk unlinks SKU customers from their QBO customer links.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1
                - 2
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-qbo-customers-unlink-sku-customers
  /api/qbo/customers/{qboCustomer}/link-sku-customer:
    post:
      tags:
      - QuickBooks Online
      summary: Link SKU Customer
      description: 'Links an existing SKU customer to a specific QBO customer.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                sku_customer_id:
                  type: integer
              example:
                sku_customer_id: 5
      parameters:
      - name: qboCustomer
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The qbo customer ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-qbo-customers-qbocustomer-link-sku-customer
  /api/qbo/customers/{qboCustomer}/unlink-sku-customer:
    delete:
      tags:
      - QuickBooks Online
      summary: Unlink SKU Customer
      description: 'Removes the SKU customer link from a QBO customer.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: qboCustomer
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The qbo customer ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-qbo-customers-qbocustomer-unlink-sku-customer
  /api/qbo/customers/refresh:
    post:
      tags:
      - QuickBooks Online
      summary: Refresh Customers
      description: 'Syncs customers from QBO API.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                full_sync:
                  type: boolean
              example:
                full_sync: false
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-qbo-customers-refresh
  /api/qbo/customers/refresh-tracked:
    post:
      tags:
      - QuickBooks Online
      summary: Refresh Customers in Background
      description: 'Starts a background refresh of customers from QuickBooks and returns
        a job id you can poll for progress. Send no parameters for an incremental
        sync (records changed since the last sync), `full_sync: true` to re-pull everything,
        or `start_date` + `end_date` (MM/DD/YYYY) to pull records updated within a
        date range.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                full_sync:
                  type: boolean
              example:
                full_sync: false
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                      sync_type:
                        type: string
                      sync_description:
                        type: string
                example:
                  success: true
                  message: QBO customers refresh started.
                  data:
                    tracked_job_log_id: 8123
                    sync_type: incremental
                    sync_description: Incremental sync (changes since last sync)
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-qbo-customers-refresh-tracked
  /api/qbo/customers/sync-info:
    get:
      tags:
      - QuickBooks Online
      summary: Get Customers Sync Info
      description: Returns the latest synced customer identifier and timestamp, the
        total number of customers already stored, and the fields you can search QuickBooks
        by for this entity.
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      latest_identifier:
                        type: string
                      latest_date:
                        type: string
                      total_count:
                        type: integer
                      searchable_fields:
                        type: array
                        items:
                          type: object
                          properties:
                            value:
                              type: string
                            label:
                              type: string
                            qbo_field:
                              type: string
                            exact:
                              type: boolean
                example:
                  success: true
                  data:
                    latest_identifier: REF-1042
                    latest_date: '2026-07-16T18:22:05.000000Z'
                    total_count: 128
                    searchable_fields:
                    - value: doc_number
                      label: Doc Number
                      qbo_field: DocNumber
                      exact: false
                    - value: qbo_id
                      label: QuickBooks ID
                      qbo_field: Id
                      exact: true
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-qbo-customers-sync-info
  /api/qbo/customers/search-qbo:
    post:
      tags:
      - QuickBooks Online
      summary: Search Customers in QuickBooks
      description: Searches QuickBooks directly for customers matching a field/value
        (without importing them). `field` must be one of the values returned by Get
        Customers Sync Info (e.g. `doc_number`, `qbo_id`). Each result flags whether
        it already exists in your database.
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                field:
                  type: string
                value:
                  type: string
              example:
                field: doc_number
                value: '1042'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        qbo_id:
                          type: string
                        label:
                          type: string
                        sub_label:
                          type: string
                        exists_in_database:
                          type: boolean
                example:
                  success: true
                  data:
                  - qbo_id: '1042'
                    label: INV-1042
                    sub_label: QuickBooks ID 1042
                    exists_in_database: true
                  - qbo_id: '1043'
                    label: INV-1043
                    sub_label: QuickBooks ID 1043
                    exists_in_database: false
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-qbo-customers-search-qbo
  /api/qbo/customers/refresh-single:
    post:
      tags:
      - QuickBooks Online
      summary: Pull Customer from QuickBooks
      description: Fetches a single customer from QuickBooks by its QuickBooks id
        and imports (or updates) it in your database.
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                qbo_id:
                  type: string
              example:
                qbo_id: '1043'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      success:
                        type: boolean
                      qbo_id:
                        type: string
                      id:
                        type: integer
                example:
                  success: true
                  message: QBO customer pulled from QuickBooks.
                  data:
                    success: true
                    qbo_id: '1043'
                    id: 991
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-qbo-customers-refresh-single
  /api/qbo/customers/export:
    get:
      tags:
      - QuickBooks Online
      summary: Export Customers
      description: 'Export customers to CSV.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: format
        in: query
        schema:
          type: string
        example: csv
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-qbo-customers-export
  /api/qbo/customers/archive:
    post:
      tags:
      - QuickBooks Online
      summary: Archive Customers
      description: 'Archive one or more QBO customers.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-qbo-customers-archive
  /api/qbo/customers/statistics:
    get:
      tags:
      - QuickBooks Online
      summary: Get Customer Statistics
      description: 'Get aggregate counts for the QuickBooks Online customers synced
        into SKU.io: the total number of records, how many are active, and how many
        are archived.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Counts are computed from the locally synced copies; no request is made to
        QuickBooks.


        Returns a 500 error if no QuickBooks Online integration has been set up.


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      total:
                        type: integer
                      active:
                        type: integer
                      archived:
                        type: integer
                example:
                  success: true
                  data:
                    total: 412
                    active: 395
                    archived: 17
        '500':
          description: Internal Server Error
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  error:
                    type: string
                  message:
                    type: string
                example:
                  success: false
                  error: Failed to get QBO customers statistics
                  message: No QBO integration instance found. Please set up your QuickBooks
                    Online integration first.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-qbo-customers-statistics
  /api/qbo/customers/merge:
    post:
      tags:
      - QuickBooks Online
      summary: Merge Duplicate Customers
      description: 'Merge one QuickBooks Online customer (the secondary) into another
        (the primary).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **This endpoint modifies data in QuickBooks itself and is irreversible.**
        QuickBooks has no native merge or unmerge, so the merge is performed by deactivating
        (soft-deleting) the secondary customer in QuickBooks Online. The secondary
        customer cannot be restored through this API afterwards.


        What happens, in order:

        1. Both customers are re-fetched from QuickBooks to obtain a fresh sync token.

        2. A snapshot of both records is stored in a merge log for auditing.

        3. If the secondary customer was linked to a SKU.io customer and the primary
        was not, the link is moved to the primary.

        4. The secondary customer is deactivated in QuickBooks and its local synced
        copy is deleted from SKU.io. (If QuickBooks reports the secondary was already
        deleted upstream, only the local cleanup is performed.)


        Both customers must belong to the same integration instance. QuickBooks refuses
        to deactivate a customer with a non-zero balance or open transactions; in
        that case the API returns a 422 with a `qbo_customer_has_open_balance` error
        - resolve the balance in QuickBooks and retry.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                primary_qbo_customer_id:
                  type: integer
                secondary_qbo_customer_id:
                  type: integer
              example:
                primary_qbo_customer_id: 501
                secondary_qbo_customer_id: 512
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      merge_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    merge_log_id: 7
                  message: QBO customers merged. This action cannot be undone.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 422 Open Balance
                  value:
                    message: Can't merge "Acme Supplies" (QBO ID 158) because it has
                      a non-zero balance in QuickBooks Online. Resolve the balance
                      in QuickBooks (apply payments, void open transactions, or write
                      the balance off) and try again.
                    error:
                      type: qbo_customer_has_open_balance
                      message: Can't merge "Acme Supplies" (QBO ID 158) because it
                        has a non-zero balance in QuickBooks Online. Resolve the balance
                        in QuickBooks (apply payments, void open transactions, or
                        write the balance off) and try again.
                      customer:
                        id: 512
                        qbo_id: '158'
                        display_name: Acme Supplies
                example-1:
                  summary: 422 Validation Error
                  value:
                    message: The secondary qbo customer id field and primary qbo customer
                      id must be different.
                    errors:
                      secondary_qbo_customer_id:
                      - The secondary qbo customer id field and primary qbo customer
                        id must be different.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-qbo-customers-merge
  /api/qbo/customers/unarchive:
    post:
      tags:
      - QuickBooks Online
      summary: Unarchive Customers
      description: 'Restore one or more archived QuickBooks Online customers by ID,
        marking them active again in SKU.io.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        This only restores the archived local synced copy in SKU.io; it does not modify
        anything in QuickBooks itself. Archiving and unarchiving control visibility
        within SKU.io only.


        Returns the number of records that were updated.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1
                - 2
                - 3
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      unarchived_count:
                        type: integer
                example:
                  success: true
                  message: Successfully unarchived 3 QBO customers(s)
                  data:
                    unarchived_count: 3
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  error:
                    type: string
                  details:
                    type: object
                    properties:
                      ids:
                        type: array
                        items:
                          type: string
                example:
                  success: false
                  error: Validation failed
                  details:
                    ids:
                    - The ids field is required.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-qbo-customers-unarchive
  /api/qbo/customers/{id}/activity-log:
    get:
      tags:
      - QuickBooks Online
      summary: Get Customer Activity Log
      description: 'Retrieve the audit trail for a synced QuickBooks Online customer.
        Each entry records a create, update, or delete event on the local copy of
        the record, including the changed attributes, their previous values, and the
        user or process that made the change.


        Results are ordered newest first and paginated (standard pagination metadata
        is included in the response).


        Returns 404 if the customer does not exist.


        Authentication: Requires Bearer token.'
      parameters:
      - name: id
        in: path
        schema:
          type: string
        required: true
        description: The record ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        description:
                          type: string
                        event:
                          type: string
                        subject_type:
                          type: string
                        subject_id:
                          type: integer
                        batch_uuid:
                          type: string
                          nullable: true
                        properties:
                          type: object
                          properties:
                            attributes:
                              type: object
                              properties:
                                sync_status:
                                  type: string
                            old:
                              type: object
                              properties:
                                sync_status:
                                  type: string
                            metadata:
                              type: object
                              properties:
                                id:
                                  type: integer
                                display_name:
                                  type: string
                                qbo_id:
                                  type: string
                        causer_name:
                          type: string
                        created_at:
                          type: string
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 5821
                    description: updated
                    event: updated
                    subject_type: QboCustomer
                    subject_id: 87
                    batch_uuid: null
                    properties:
                      attributes:
                        sync_status: ok
                      old:
                        sync_status: sku_updated_pending_sync
                      metadata:
                        id: 87
                        display_name: Bar Supply Co
                        qbo_id: '12'
                    causer_name: Jane Smith
                    created_at: '2026-06-18T14:22:31.000000Z'
                  first_page_url: …?page=1
                  from: 1
                  last_page: 1
                  last_page_url: …?page=1
                  links: []
                  next_page_url: null
                  path: …/api/qbo/customers/87/activity-log
                  per_page: 15
                  prev_page_url: null
                  to: 1
                  total: 1
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Record not found.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-qbo-customers-id-activity-log
  /api/qbo/invoices:
    get:
      tags:
      - QuickBooks Online
      summary: List Invoices
      description: 'Paginated list of QBO invoices. Supports filtering by doc_number,
        customer_name, status, and sync_status.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Searchable columns (filter[search]): id, qbo_id, doc_number, customer_name.'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        example: '1'
        description: Page number (default 1).
      - name: per_page
        in: query
        schema:
          type: integer
        example: '15'
        description: Results per page (default 10).
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        qbo_id:
                          type: string
                        doc_number:
                          type: string
                        customer_name:
                          type: string
                        total_amount:
                          type: string
                        status:
                          type: string
                        sync_status:
                          type: string
                        qbo_link:
                          type: string
                  current_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 1
                    qbo_id: '1'
                    doc_number: INV-001
                    customer_name: ACME Corp
                    total_amount: '1000.00'
                    status: Paid
                    sync_status: synced
                    qbo_link: https://app.qbo.intuit.com/app/invoice?txnId=184
                  current_page: 1
                  total: 1
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-qbo-invoices
    delete:
      tags:
      - QuickBooks Online
      summary: Delete Invoices
      description: 'Delete one or more QBO invoices.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: delete-api-qbo-invoices
  /api/qbo/invoices/{id}:
    get:
      tags:
      - QuickBooks Online
      summary: Get Invoice
      description: 'Get a single QBO invoice by ID.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        This document is pushed to QuickBooks by SKU''s ledger, so the response includes
        reverse cross-link fields: `ledger_entry_id` and `ledger_entry_reference`
        identify the SKU ledger entry that pushed it, while `sku_link_type`, `sku_link_id`,
        `sku_link_label`, and `sku_link_route` point back to the originating SKU document.
        These are `null` when the document originated in QuickBooks rather than being
        pushed by SKU. `customer_link_id` and `sku_customer_id` cross-link to the
        mirrored QuickBooks customer and its linked SKU customer. Returns `line_items`
        (normalized line rows parsed from the stored QuickBooks payload) and `detail_payload`
        (the full raw QuickBooks payload); both are null until the document is re-synced
        from QuickBooks.


        Also returns an `amounts` summary (`subtotal`, `tax`, `total`, `balance`,
        `paid`) and a `tax_code` on each `line_items` row.'
      parameters:
      - name: id
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The record ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      qbo_id:
                        type: string
                      doc_number:
                        type: string
                      name:
                        type: string
                      customer_id:
                        type: string
                      customer_name:
                        type: string
                      total_amount:
                        type: string
                      currency:
                        type: string
                      due_date:
                        type: string
                      txn_date:
                        type: string
                      status:
                        type: string
                      active:
                        type: boolean
                      sync_status:
                        type: string
                      last_synced_at:
                        type: string
                      last_qbo_check_at:
                        type: string
                      sync_error_message:
                        type: string
                        nullable: true
                      qbo_created_at:
                        type: string
                      qbo_updated_at:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      integration_instance:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      qbo_link:
                        type: string
                      customer_link_id:
                        type: integer
                      sku_customer_id:
                        type: integer
                      ledger_entry_id:
                        type: integer
                      ledger_entry_reference:
                        type: string
                      sku_link_type:
                        type: string
                      sku_link_id:
                        type: integer
                      sku_link_label:
                        type: string
                      sku_link_route:
                        type: string
                      amounts:
                        type: object
                        properties:
                          subtotal:
                            type: integer
                          tax:
                            type: integer
                          total:
                            type: integer
                          balance:
                            type: integer
                          paid:
                            type: integer
                      line_items:
                        type: array
                        items:
                          type: object
                          properties:
                            line_num:
                              type: integer
                            description:
                              type: string
                            detail_type:
                              type: string
                            item:
                              type: string
                            item_id:
                              type: string
                            item_link_id:
                              type: integer
                            account:
                              type: string
                              nullable: true
                            quantity:
                              type: integer
                            unit_price:
                              type: number
                            amount:
                              type: integer
                            tax_code:
                              type: string
                            posting_type:
                              type: string
                              nullable: true
                      detail_payload:
                        type: object
                        properties:
                          Id:
                            type: string
                          DocNumber:
                            type: string
                          TxnDate:
                            type: string
                          TotalAmt:
                            type: integer
                          CustomerRef:
                            type: object
                            properties:
                              value:
                                type: string
                              name:
                                type: string
                          CurrencyRef:
                            type: object
                            properties:
                              value:
                                type: string
                          Line:
                            type: array
                            items:
                              type: object
                              properties:
                                Id:
                                  type: string
                                LineNum:
                                  type: integer
                                Amount:
                                  type: integer
                                DetailType:
                                  type: string
                                Description:
                                  type: string
                                SalesItemLineDetail:
                                  type: object
                                  properties:
                                    ItemRef:
                                      type: object
                                      properties:
                                        value:
                                          type: string
                                        name:
                                          type: string
                                    Qty:
                                      type: integer
                                    UnitPrice:
                                      type: number
                          sparse:
                            type: boolean
                example:
                  success: true
                  data:
                    id: 87
                    integration_instance_id: 3
                    qbo_id: '184'
                    doc_number: INV-1042
                    name: INV-1042
                    customer_id: '12'
                    customer_name: Bar Supply Co
                    total_amount: '842.00'
                    currency: USD
                    due_date: '2026-07-31'
                    txn_date: '2026-07-01'
                    status: Open
                    active: true
                    sync_status: ok
                    last_synced_at: '2026-07-15T10:00:00.000000Z'
                    last_qbo_check_at: '2026-07-15T10:00:00.000000Z'
                    sync_error_message: null
                    qbo_created_at: '2026-07-01T09:00:00.000000Z'
                    qbo_updated_at: '2026-07-14T18:30:00.000000Z'
                    created_at: '2026-07-01T09:05:00.000000Z'
                    updated_at: '2026-07-14T18:35:00.000000Z'
                    integration_instance:
                      id: 3
                      name: QuickBooks Online
                    qbo_link: https://app.qbo.intuit.com/app/invoice?txnId=184
                    customer_link_id: 88
                    sku_customer_id: 1420
                    ledger_entry_id: 12506
                    ledger_entry_reference: O260724VOY4F6/R1
                    sku_link_type: App\Models\SalesOrder
                    sku_link_id: 4242
                    sku_link_label: Sales Order
                    sku_link_route: /orders/sales-orders/4242
                    amounts:
                      subtotal: 550
                      tax: 40
                      total: 590
                      balance: 90
                      paid: 500
                    line_items:
                    - line_num: 1
                      description: Osetra Caviar 4.4 oz
                      detail_type: SalesItemLineDetail
                      item: RO125G
                      item_id: '70'
                      item_link_id: 42
                      account: null
                      quantity: 4
                      unit_price: 147.5
                      amount: 590
                      tax_code: TAX
                      posting_type: null
                    detail_payload:
                      Id: '184'
                      DocNumber: INV-1042
                      TxnDate: '2026-07-01'
                      TotalAmt: 842
                      CustomerRef:
                        value: '12'
                        name: Bar Supply Co
                      CurrencyRef:
                        value: USD
                      Line:
                      - Id: '1'
                        LineNum: 1
                        Amount: 590
                        DetailType: SalesItemLineDetail
                        Description: Osetra Caviar 4.4 oz
                        SalesItemLineDetail:
                          ItemRef:
                            value: '21'
                            name: RO125G
                          Qty: 4
                          UnitPrice: 147.5
                      sparse: false
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-qbo-invoices-id
  /api/qbo/invoices/sync:
    post:
      tags:
      - QuickBooks Online
      summary: Sync Invoices to QBO
      description: 'Syncs accounting transactions to QBO as invoices. Pass specific
        IDs to force-sync those transactions, or omit for auto-sync of all eligible
        transactions.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                accounting_transaction_ids:
                  type: array
                  items:
                    type: integer
              example:
                accounting_transaction_ids:
                - 101
                - 102
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      processed_count:
                        type: integer
                      synced:
                        type: integer
                      failed:
                        type: integer
                  sync_mode:
                    type: string
                example:
                  success: true
                  message: Synced 2 specific transaction(s) to QuickBooks Online
                  data:
                    processed_count: 2
                    synced: 2
                    failed: 0
                  sync_mode: specific_transactions
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-qbo-invoices-sync
  /api/qbo/invoices/sync-status:
    get:
      tags:
      - QuickBooks Online
      summary: Get Invoice Sync Status
      description: 'Returns the current sync status and summary for QBO invoices.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  status:
                    type: object
                    properties:
                      total_eligible:
                        type: integer
                      synced:
                        type: integer
                      pending:
                        type: integer
                      failed:
                        type: integer
                      last_sync_at:
                        type: string
                example:
                  success: true
                  status:
                    total_eligible: 50
                    synced: 45
                    pending: 5
                    failed: 0
                    last_sync_at: '2024-01-01T00:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-qbo-invoices-sync-status
  /api/qbo/invoices/refresh:
    post:
      tags:
      - QuickBooks Online
      summary: Refresh Invoices
      description: 'Syncs invoices from QBO API.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                full_sync:
                  type: boolean
              example:
                full_sync: false
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-qbo-invoices-refresh
  /api/qbo/invoices/refresh-tracked:
    post:
      tags:
      - QuickBooks Online
      summary: Refresh Invoices in Background
      description: 'Starts a background refresh of invoices from QuickBooks and returns
        a job id you can poll for progress. Send no parameters for an incremental
        sync (records changed since the last sync), `full_sync: true` to re-pull everything,
        or `start_date` + `end_date` (MM/DD/YYYY) to pull records updated within a
        date range.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                full_sync:
                  type: boolean
              example:
                full_sync: false
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                      sync_type:
                        type: string
                      sync_description:
                        type: string
                example:
                  success: true
                  message: QBO invoices refresh started.
                  data:
                    tracked_job_log_id: 8123
                    sync_type: incremental
                    sync_description: Incremental sync (changes since last sync)
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-qbo-invoices-refresh-tracked
  /api/qbo/invoices/sync-info:
    get:
      tags:
      - QuickBooks Online
      summary: Get Invoices Sync Info
      description: Returns the latest synced invoice identifier and timestamp, the
        total number of invoices already stored, and the fields you can search QuickBooks
        by for this entity.
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      latest_identifier:
                        type: string
                      latest_date:
                        type: string
                      total_count:
                        type: integer
                      searchable_fields:
                        type: array
                        items:
                          type: object
                          properties:
                            value:
                              type: string
                            label:
                              type: string
                            qbo_field:
                              type: string
                            exact:
                              type: boolean
                example:
                  success: true
                  data:
                    latest_identifier: INV-1042
                    latest_date: '2026-07-16T18:22:05.000000Z'
                    total_count: 128
                    searchable_fields:
                    - value: doc_number
                      label: Doc Number
                      qbo_field: DocNumber
                      exact: false
                    - value: qbo_id
                      label: QuickBooks ID
                      qbo_field: Id
                      exact: true
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-qbo-invoices-sync-info
  /api/qbo/invoices/search-qbo:
    post:
      tags:
      - QuickBooks Online
      summary: Search Invoices in QuickBooks
      description: Searches QuickBooks directly for invoices matching a field/value
        (without importing them). `field` must be one of the values returned by Get
        Invoices Sync Info (e.g. `doc_number`, `qbo_id`). Each result flags whether
        it already exists in your database.
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                field:
                  type: string
                value:
                  type: string
              example:
                field: doc_number
                value: '1042'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        qbo_id:
                          type: string
                        label:
                          type: string
                        sub_label:
                          type: string
                        exists_in_database:
                          type: boolean
                example:
                  success: true
                  data:
                  - qbo_id: '1042'
                    label: INV-1042
                    sub_label: QuickBooks ID 1042
                    exists_in_database: true
                  - qbo_id: '1043'
                    label: INV-1043
                    sub_label: QuickBooks ID 1043
                    exists_in_database: false
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-qbo-invoices-search-qbo
  /api/qbo/invoices/refresh-single:
    post:
      tags:
      - QuickBooks Online
      summary: Pull Invoice from QuickBooks
      description: Fetches a single invoice from QuickBooks by its QuickBooks id and
        imports (or updates) it in your database.
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                qbo_id:
                  type: string
              example:
                qbo_id: '1043'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      success:
                        type: boolean
                      qbo_id:
                        type: string
                      id:
                        type: integer
                example:
                  success: true
                  message: QBO invoice pulled from QuickBooks.
                  data:
                    success: true
                    qbo_id: '1043'
                    id: 991
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-qbo-invoices-refresh-single
  /api/qbo/invoices/export:
    get:
      tags:
      - QuickBooks Online
      summary: Export Invoices
      description: 'Export invoices to CSV.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: format
        in: query
        schema:
          type: string
        example: csv
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-qbo-invoices-export
  /api/qbo/invoices/archive:
    post:
      tags:
      - QuickBooks Online
      summary: Archive Invoices
      description: 'Archive one or more QBO invoices.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-qbo-invoices-archive
  /api/qbo/invoices/statistics:
    get:
      tags:
      - QuickBooks Online
      summary: Get Invoice Statistics
      description: 'Get aggregate counts for the QuickBooks Online invoices synced
        into SKU.io: the total number of records, how many are active, and how many
        are archived.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Counts are computed from the locally synced copies; no request is made to
        QuickBooks.


        Returns a 500 error if no QuickBooks Online integration has been set up.


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      total:
                        type: integer
                      active:
                        type: integer
                      archived:
                        type: integer
                example:
                  success: true
                  data:
                    total: 1280
                    active: 1244
                    archived: 36
        '500':
          description: Internal Server Error
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  error:
                    type: string
                  message:
                    type: string
                example:
                  success: false
                  error: Failed to get QBO invoices statistics
                  message: No QBO integration instance found. Please set up your QuickBooks
                    Online integration first.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-qbo-invoices-statistics
  /api/qbo/invoices/{id}/activity-log:
    get:
      tags:
      - QuickBooks Online
      summary: Get Invoice Activity Log
      description: 'Retrieve the audit trail for a synced QuickBooks Online invoice.
        Each entry records a create, update, or delete event on the local copy of
        the record, including the changed attributes, their previous values, and the
        user or process that made the change.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Results are ordered newest first and paginated (standard pagination metadata
        is included in the response).


        Returns 404 if the invoice does not exist.


        Authentication: Requires Bearer token.'
      parameters:
      - name: id
        in: path
        schema:
          type: string
        required: true
        description: The record ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        description:
                          type: string
                        event:
                          type: string
                        subject_type:
                          type: string
                        subject_id:
                          type: integer
                        batch_uuid:
                          type: string
                          nullable: true
                        properties:
                          type: object
                          properties:
                            attributes:
                              type: object
                              properties:
                                sync_status:
                                  type: string
                            old:
                              type: object
                              properties:
                                sync_status:
                                  type: string
                            source:
                              type: string
                        causer_name:
                          type: string
                        created_at:
                          type: string
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                    items:
                      type: object
                      properties:
                        url:
                          type: string
                          nullable: true
                        label:
                          type: string
                        active:
                          type: boolean
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 5821
                    description: updated
                    event: updated
                    subject_type: QboInvoice
                    subject_id: 314
                    batch_uuid: null
                    properties:
                      attributes:
                        sync_status: synced
                      old:
                        sync_status: pending
                      source: qbo_sync
                    causer_name: Jane Smith
                    created_at: '2026-06-18T14:22:31.000000Z'
                  first_page_url: '{{protocol}}://{{domain}}/api/qbo/invoices/314/activity-log?page=1'
                  from: 1
                  last_page: 1
                  last_page_url: '{{protocol}}://{{domain}}/api/qbo/invoices/314/activity-log?page=1'
                  links:
                  - url: null
                    label: '&laquo; Previous'
                    active: false
                  - url: '{{protocol}}://{{domain}}/api/qbo/invoices/314/activity-log?page=1'
                    label: '1'
                    active: true
                  - url: null
                    label: Next &raquo;
                    active: false
                  next_page_url: null
                  path: '{{protocol}}://{{domain}}/api/qbo/invoices/314/activity-log'
                  per_page: 15
                  prev_page_url: null
                  to: 1
                  total: 1
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: object
                    properties:
                      id:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: array
                example:
                  errors:
                    id:
                    - message: Record not found.
                      code: NotFound
                      data: []
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-qbo-invoices-id-activity-log
  /api/qbo/invoices/unarchive:
    post:
      tags:
      - QuickBooks Online
      summary: Unarchive Invoices
      description: 'Restore one or more archived QuickBooks Online invoices by ID,
        marking them active again in SKU.io.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        This only restores the archived local synced copy in SKU.io; it does not modify
        anything in QuickBooks itself. Archiving and unarchiving control visibility
        within SKU.io only.


        Returns the number of records that were updated.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1
                - 2
                - 3
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      unarchived_count:
                        type: integer
                example:
                  success: true
                  message: Successfully unarchived 3 QBO invoices(s)
                  data:
                    unarchived_count: 3
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  error:
                    type: string
                  details:
                    type: object
                    properties:
                      ids:
                        type: array
                        items:
                          type: string
                example:
                  success: false
                  error: Validation failed
                  details:
                    ids:
                    - The ids field is required.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-qbo-invoices-unarchive
  /api/qbo/items:
    get:
      tags:
      - QuickBooks Online
      summary: List Items
      description: 'Paginated list of QBO items/products.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Searchable columns (filter[search]): id, qbo_id, name, sku, description.'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        example: '1'
        description: Page number (default 1).
      - name: per_page
        in: query
        schema:
          type: integer
        example: '15'
        description: Results per page (default 10).
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-qbo-items
    delete:
      tags:
      - QuickBooks Online
      summary: Delete Items
      description: 'Delete one or more QBO items.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: delete-api-qbo-items
  /api/qbo/items/{id}:
    get:
      tags:
      - QuickBooks Online
      summary: Get Item
      description: 'Get a single QBO item by ID.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: id
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The record ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-qbo-items-id
  /api/qbo/items/refresh:
    post:
      tags:
      - QuickBooks Online
      summary: Refresh Items
      description: 'Syncs items from QBO API.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                full_sync:
                  type: boolean
              example:
                full_sync: false
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-qbo-items-refresh
  /api/qbo/items/refresh-tracked:
    post:
      tags:
      - QuickBooks Online
      summary: Refresh Items in Background
      description: 'Starts a background refresh of items from QuickBooks and returns
        a job id you can poll for progress. Send no parameters for an incremental
        sync (records changed since the last sync), `full_sync: true` to re-pull everything,
        or `start_date` + `end_date` (MM/DD/YYYY) to pull records updated within a
        date range.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                full_sync:
                  type: boolean
              example:
                full_sync: false
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                      sync_type:
                        type: string
                      sync_description:
                        type: string
                example:
                  success: true
                  message: QBO items refresh started.
                  data:
                    tracked_job_log_id: 8123
                    sync_type: incremental
                    sync_description: Incremental sync (changes since last sync)
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-qbo-items-refresh-tracked
  /api/qbo/items/sync-info:
    get:
      tags:
      - QuickBooks Online
      summary: Get Items Sync Info
      description: Returns the latest synced item identifier and timestamp, the total
        number of items already stored, and the fields you can search QuickBooks by
        for this entity.
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      latest_identifier:
                        type: string
                      latest_date:
                        type: string
                      total_count:
                        type: integer
                      searchable_fields:
                        type: array
                        items:
                          type: object
                          properties:
                            value:
                              type: string
                            label:
                              type: string
                            qbo_field:
                              type: string
                            exact:
                              type: boolean
                example:
                  success: true
                  data:
                    latest_identifier: REF-1042
                    latest_date: '2026-07-16T18:22:05.000000Z'
                    total_count: 128
                    searchable_fields:
                    - value: doc_number
                      label: Doc Number
                      qbo_field: DocNumber
                      exact: false
                    - value: qbo_id
                      label: QuickBooks ID
                      qbo_field: Id
                      exact: true
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-qbo-items-sync-info
  /api/qbo/items/search-qbo:
    post:
      tags:
      - QuickBooks Online
      summary: Search Items in QuickBooks
      description: Searches QuickBooks directly for items matching a field/value (without
        importing them). `field` must be one of the values returned by Get Items Sync
        Info (e.g. `doc_number`, `qbo_id`). Each result flags whether it already exists
        in your database.
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                field:
                  type: string
                value:
                  type: string
              example:
                field: doc_number
                value: '1042'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        qbo_id:
                          type: string
                        label:
                          type: string
                        sub_label:
                          type: string
                        exists_in_database:
                          type: boolean
                example:
                  success: true
                  data:
                  - qbo_id: '1042'
                    label: INV-1042
                    sub_label: QuickBooks ID 1042
                    exists_in_database: true
                  - qbo_id: '1043'
                    label: INV-1043
                    sub_label: QuickBooks ID 1043
                    exists_in_database: false
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-qbo-items-search-qbo
  /api/qbo/items/refresh-single:
    post:
      tags:
      - QuickBooks Online
      summary: Pull Item from QuickBooks
      description: Fetches a single item from QuickBooks by its QuickBooks id and
        imports (or updates) it in your database.
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                qbo_id:
                  type: string
              example:
                qbo_id: '1043'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      success:
                        type: boolean
                      qbo_id:
                        type: string
                      id:
                        type: integer
                example:
                  success: true
                  message: QBO item pulled from QuickBooks.
                  data:
                    success: true
                    qbo_id: '1043'
                    id: 991
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-qbo-items-refresh-single
  /api/qbo/items/export:
    get:
      tags:
      - QuickBooks Online
      summary: Export Items
      description: 'Export items to CSV.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: format
        in: query
        schema:
          type: string
        example: csv
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-qbo-items-export
  /api/qbo/items/archive:
    post:
      tags:
      - QuickBooks Online
      summary: Archive Items
      description: 'Archive one or more QBO items.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-qbo-items-archive
  /api/qbo/items/statistics:
    get:
      tags:
      - QuickBooks Online
      summary: Get Item Statistics
      description: 'Get aggregate counts for the QuickBooks Online items synced into
        SKU.io: the total number of records, how many are active, and how many are
        archived.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Counts are computed from the locally synced copies; no request is made to
        QuickBooks.


        Returns a 500 error if no QuickBooks Online integration has been set up.


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      total:
                        type: integer
                      active:
                        type: integer
                      archived:
                        type: integer
                example:
                  success: true
                  data:
                    total: 356
                    active: 340
                    archived: 16
        '500':
          description: Internal Server Error
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  error:
                    type: string
                  message:
                    type: string
                example:
                  success: false
                  error: Failed to get QBO items statistics
                  message: No QBO integration instance found. Please set up your QuickBooks
                    Online integration first.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-qbo-items-statistics
  /api/qbo/items/unarchive:
    post:
      tags:
      - QuickBooks Online
      summary: Unarchive Items
      description: 'Restore one or more archived QuickBooks Online items by ID, marking
        them active again in SKU.io.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        This only restores the archived local synced copy in SKU.io; it does not modify
        anything in QuickBooks itself. Archiving and unarchiving control visibility
        within SKU.io only.


        Returns the number of records that were updated.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1
                - 2
                - 3
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      unarchived_count:
                        type: integer
                example:
                  success: true
                  message: Successfully unarchived 3 QBO items(s)
                  data:
                    unarchived_count: 3
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  error:
                    type: string
                  details:
                    type: object
                    properties:
                      ids:
                        type: array
                        items:
                          type: string
                example:
                  success: false
                  error: Validation failed
                  details:
                    ids:
                    - The ids field is required.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-qbo-items-unarchive
  /api/qbo/items/{id}/activity-log:
    get:
      tags:
      - QuickBooks Online
      summary: Get Item Activity Log
      description: 'Retrieve the audit trail for a synced QuickBooks Online item.
        Each entry records a create, update, or delete event on the local copy of
        the record, including the changed attributes, their previous values, and the
        user or process that made the change.


        Results are ordered newest first and paginated (standard pagination metadata
        is included in the response).


        Returns 404 if the item does not exist.


        Authentication: Requires Bearer token.'
      parameters:
      - name: id
        in: path
        schema:
          type: string
        required: true
        description: The record ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        description:
                          type: string
                        event:
                          type: string
                        subject_type:
                          type: string
                        subject_id:
                          type: integer
                        batch_uuid:
                          type: string
                          nullable: true
                        properties:
                          type: object
                          properties:
                            attributes:
                              type: object
                              properties:
                                sync_status:
                                  type: string
                            old:
                              type: object
                              properties:
                                sync_status:
                                  type: string
                            source:
                              type: string
                        causer_name:
                          type: string
                        created_at:
                          type: string
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                    items:
                      type: object
                      properties:
                        url:
                          type: string
                          nullable: true
                        label:
                          type: string
                        active:
                          type: boolean
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 5821
                    description: updated
                    event: updated
                    subject_type: QboItem
                    subject_id: 87
                    batch_uuid: null
                    properties:
                      attributes:
                        sync_status: synced
                      old:
                        sync_status: pending
                      source: qbo_sync
                    causer_name: Jane Smith
                    created_at: '2026-06-18T14:22:31.000000Z'
                  first_page_url: '{{protocol}}://{{domain}}/api/qbo/items/87/activity-log?page=1'
                  from: 1
                  last_page: 1
                  last_page_url: '{{protocol}}://{{domain}}/api/qbo/items/87/activity-log?page=1'
                  links:
                  - url: null
                    label: '&laquo; Previous'
                    active: false
                  - url: '{{protocol}}://{{domain}}/api/qbo/items/87/activity-log?page=1'
                    label: '1'
                    active: true
                  - url: null
                    label: Next &raquo;
                    active: false
                  next_page_url: null
                  path: '{{protocol}}://{{domain}}/api/qbo/items/87/activity-log'
                  per_page: 15
                  prev_page_url: null
                  to: 1
                  total: 1
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: object
                    properties:
                      id:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: array
                example:
                  errors:
                    id:
                    - message: Record not found.
                      code: NotFound
                      data: []
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-qbo-items-id-activity-log
  /api/qbo/journals:
    get:
      tags:
      - QuickBooks Online
      summary: List Journals
      description: 'Paginated list of QBO journal entries.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Searchable columns (filter[search]): id, qbo_id, doc_number, description.'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        example: '1'
        description: Page number (default 1).
      - name: per_page
        in: query
        schema:
          type: integer
        example: '15'
        description: Results per page (default 10).
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-qbo-journals
    delete:
      tags:
      - QuickBooks Online
      summary: Delete Journals
      description: 'Delete one or more QBO journals.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: delete-api-qbo-journals
  /api/qbo/journals/{id}:
    get:
      tags:
      - QuickBooks Online
      summary: Get Journal
      description: 'Get a single QBO journal entry by ID.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        This document is pushed to QuickBooks by SKU''s ledger, so the response includes
        reverse cross-link fields: `ledger_entry_id` and `ledger_entry_reference`
        identify the SKU ledger entry that pushed it, while `sku_link_type`, `sku_link_id`,
        `sku_link_label`, and `sku_link_route` point back to the originating SKU document.
        These are `null` when the document originated in QuickBooks rather than being
        pushed by SKU. Returns `line_items` (normalized line rows parsed from the
        stored QuickBooks payload) and `detail_payload` (the full raw QuickBooks payload);
        both are null until the document is re-synced from QuickBooks.


        Also returns an `amounts` summary (`subtotal`, `tax`, `total`, `balance`,
        `paid`) and a `tax_code` on each `line_items` row.'
      parameters:
      - name: id
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The record ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      qbo_id:
                        type: string
                      doc_number:
                        type: string
                      name:
                        type: string
                      description:
                        type: string
                      total_amount:
                        type: string
                      adjustment:
                        type: boolean
                      txn_date:
                        type: string
                      active:
                        type: boolean
                      sync_status:
                        type: string
                      last_synced_at:
                        type: string
                      last_qbo_check_at:
                        type: string
                      sync_error_message:
                        type: string
                        nullable: true
                      qbo_created_at:
                        type: string
                      qbo_updated_at:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      integration_instance:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      qbo_link:
                        type: string
                      ledger_entry_id:
                        type: integer
                      ledger_entry_reference:
                        type: string
                      sku_link_type:
                        type: string
                      sku_link_id:
                        type: integer
                      sku_link_label:
                        type: string
                      sku_link_route:
                        type: string
                      amounts:
                        type: object
                        properties:
                          subtotal:
                            type: integer
                          tax:
                            type: integer
                          total:
                            type: integer
                          balance:
                            type: integer
                          paid:
                            type: integer
                      line_items:
                        type: array
                        items:
                          type: object
                          properties:
                            line_num:
                              type: integer
                            description:
                              type: string
                            detail_type:
                              type: string
                            item:
                              type: string
                              nullable: true
                            item_id:
                              type: string
                              nullable: true
                            item_link_id:
                              type: string
                              nullable: true
                            account:
                              type: string
                            quantity:
                              type: string
                              nullable: true
                            unit_price:
                              type: string
                              nullable: true
                            amount:
                              type: integer
                            tax_code:
                              type: string
                            posting_type:
                              type: string
                      detail_payload:
                        type: object
                        properties:
                          Id:
                            type: string
                          DocNumber:
                            type: string
                          TxnDate:
                            type: string
                          TotalAmt:
                            type: integer
                          Line:
                            type: array
                            items:
                              type: object
                              properties:
                                Id:
                                  type: string
                                Description:
                                  type: string
                                Amount:
                                  type: integer
                                DetailType:
                                  type: string
                                JournalEntryLineDetail:
                                  type: object
                                  properties:
                                    PostingType:
                                      type: string
                                    AccountRef:
                                      type: object
                                      properties:
                                        value:
                                          type: string
                                        name:
                                          type: string
                          sparse:
                            type: boolean
                example:
                  success: true
                  data:
                    id: 29
                    integration_instance_id: 3
                    qbo_id: '406'
                    doc_number: JE-9007
                    name: JE-9007
                    description: Monthly COGS summary
                    total_amount: '5230.00'
                    adjustment: false
                    txn_date: '2026-06-30'
                    active: true
                    sync_status: ok
                    last_synced_at: '2026-07-15T10:00:00.000000Z'
                    last_qbo_check_at: '2026-07-15T10:00:00.000000Z'
                    sync_error_message: null
                    qbo_created_at: '2026-07-01T09:00:00.000000Z'
                    qbo_updated_at: '2026-07-14T18:30:00.000000Z'
                    created_at: '2026-07-01T09:05:00.000000Z'
                    updated_at: '2026-07-14T18:35:00.000000Z'
                    integration_instance:
                      id: 3
                      name: QuickBooks Online
                    qbo_link: https://app.qbo.intuit.com/app/journal?txnId=406
                    ledger_entry_id: 12506
                    ledger_entry_reference: O260724VOY4F6/R1
                    sku_link_type: App\Models\SalesOrder
                    sku_link_id: 4242
                    sku_link_label: Sales Order
                    sku_link_route: /orders/sales-orders/4242
                    amounts:
                      subtotal: 550
                      tax: 40
                      total: 590
                      balance: 90
                      paid: 500
                    line_items:
                    - line_num: 1
                      description: Inventory revaluation
                      detail_type: JournalEntryLineDetail
                      item: null
                      item_id: null
                      item_link_id: null
                      account: Inventory Asset
                      quantity: null
                      unit_price: null
                      amount: 5230
                      tax_code: TAX
                      posting_type: Debit
                    - line_num: 2
                      description: Inventory revaluation
                      detail_type: JournalEntryLineDetail
                      item: null
                      item_id: null
                      item_link_id: null
                      account: Cost of Goods Sold
                      quantity: null
                      unit_price: null
                      amount: 5230
                      tax_code: TAX
                      posting_type: Credit
                    detail_payload:
                      Id: '406'
                      DocNumber: JE-9007
                      TxnDate: '2026-06-30'
                      TotalAmt: 5230
                      Line:
                      - Id: '0'
                        Description: Inventory revaluation
                        Amount: 5230
                        DetailType: JournalEntryLineDetail
                        JournalEntryLineDetail:
                          PostingType: Debit
                          AccountRef:
                            value: '81'
                            name: Inventory Asset
                      - Id: '1'
                        Description: Inventory revaluation
                        Amount: 5230
                        DetailType: JournalEntryLineDetail
                        JournalEntryLineDetail:
                          PostingType: Credit
                          AccountRef:
                            value: '80'
                            name: Cost of Goods Sold
                      sparse: false
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-qbo-journals-id
  /api/qbo/journals/refresh:
    post:
      tags:
      - QuickBooks Online
      summary: Refresh Journals
      description: 'Syncs journals from QBO API.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                full_sync:
                  type: boolean
              example:
                full_sync: false
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-qbo-journals-refresh
  /api/qbo/journals/refresh-tracked:
    post:
      tags:
      - QuickBooks Online
      summary: Refresh Journals in Background
      description: 'Starts a background refresh of journals from QuickBooks and returns
        a job id you can poll for progress. Send no parameters for an incremental
        sync (records changed since the last sync), `full_sync: true` to re-pull everything,
        or `start_date` + `end_date` (MM/DD/YYYY) to pull records updated within a
        date range.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                full_sync:
                  type: boolean
              example:
                full_sync: false
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                      sync_type:
                        type: string
                      sync_description:
                        type: string
                example:
                  success: true
                  message: QBO journals refresh started.
                  data:
                    tracked_job_log_id: 8123
                    sync_type: incremental
                    sync_description: Incremental sync (changes since last sync)
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-qbo-journals-refresh-tracked
  /api/qbo/journals/sync-info:
    get:
      tags:
      - QuickBooks Online
      summary: Get Journals Sync Info
      description: Returns the latest synced journal identifier and timestamp, the
        total number of journals already stored, and the fields you can search QuickBooks
        by for this entity.
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      latest_identifier:
                        type: string
                      latest_date:
                        type: string
                      total_count:
                        type: integer
                      searchable_fields:
                        type: array
                        items:
                          type: object
                          properties:
                            value:
                              type: string
                            label:
                              type: string
                            qbo_field:
                              type: string
                            exact:
                              type: boolean
                example:
                  success: true
                  data:
                    latest_identifier: REF-1042
                    latest_date: '2026-07-16T18:22:05.000000Z'
                    total_count: 128
                    searchable_fields:
                    - value: doc_number
                      label: Doc Number
                      qbo_field: DocNumber
                      exact: false
                    - value: qbo_id
                      label: QuickBooks ID
                      qbo_field: Id
                      exact: true
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-qbo-journals-sync-info
  /api/qbo/journals/search-qbo:
    post:
      tags:
      - QuickBooks Online
      summary: Search Journals in QuickBooks
      description: Searches QuickBooks directly for journals matching a field/value
        (without importing them). `field` must be one of the values returned by Get
        Journals Sync Info (e.g. `doc_number`, `qbo_id`). Each result flags whether
        it already exists in your database.
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                field:
                  type: string
                value:
                  type: string
              example:
                field: doc_number
                value: '1042'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        qbo_id:
                          type: string
                        label:
                          type: string
                        sub_label:
                          type: string
                        exists_in_database:
                          type: boolean
                example:
                  success: true
                  data:
                  - qbo_id: '1042'
                    label: INV-1042
                    sub_label: QuickBooks ID 1042
                    exists_in_database: true
                  - qbo_id: '1043'
                    label: INV-1043
                    sub_label: QuickBooks ID 1043
                    exists_in_database: false
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-qbo-journals-search-qbo
  /api/qbo/journals/refresh-single:
    post:
      tags:
      - QuickBooks Online
      summary: Pull Journal from QuickBooks
      description: Fetches a single journal from QuickBooks by its QuickBooks id and
        imports (or updates) it in your database.
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                qbo_id:
                  type: string
              example:
                qbo_id: '1043'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      success:
                        type: boolean
                      qbo_id:
                        type: string
                      id:
                        type: integer
                example:
                  success: true
                  message: QBO journal pulled from QuickBooks.
                  data:
                    success: true
                    qbo_id: '1043'
                    id: 991
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-qbo-journals-refresh-single
  /api/qbo/journals/archive:
    post:
      tags:
      - QuickBooks Online
      summary: Archive Journals
      description: 'Archive one or more QBO journals.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-qbo-journals-archive
  /api/qbo/journals/export:
    get:
      tags:
      - QuickBooks Online
      summary: Export Journals
      description: 'Download the QuickBooks Online journals synced into SKU.io as
        a CSV file. The export is streamed from the locally synced copies; no request
        is made to QuickBooks.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        CSV columns: QBO ID, Doc Number, Description, Total Amount, Transaction Date,
        Adjustment, Active, QBO Created At, QBO Updated At, Local Created At, Local
        Updated At.


        The response is a file download (`Content-Type: text/csv`) with a filename
        of the form `qbo_journals_export_2026-07-07_10-30-00.csv`. By default all
        records (active and archived) are included; use the query parameters to narrow
        the export.


        Returns a 500 error if no QuickBooks Online integration has been set up, and
        a 422 error if a date parameter is not in MM/DD/YYYY format.


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-qbo-journals-export
  /api/qbo/journals/statistics:
    get:
      tags:
      - QuickBooks Online
      summary: Get Journal Statistics
      description: 'Get aggregate counts for the QuickBooks Online journals synced
        into SKU.io: the total number of records, how many are active, and how many
        are archived.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Counts are computed from the locally synced copies; no request is made to
        QuickBooks.


        Returns a 500 error if no QuickBooks Online integration has been set up.


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      total:
                        type: integer
                      active:
                        type: integer
                      archived:
                        type: integer
                example:
                  success: true
                  data:
                    total: 94
                    active: 90
                    archived: 4
        '500':
          description: Internal Server Error
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  error:
                    type: string
                  message:
                    type: string
                example:
                  success: false
                  error: Failed to get QBO journals statistics
                  message: No QBO integration instance found. Please set up your QuickBooks
                    Online integration first.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-qbo-journals-statistics
  /api/qbo/journals/{id}/activity-log:
    get:
      tags:
      - QuickBooks Online
      summary: Get Journal Activity Log
      description: 'Retrieve the audit trail for a synced QuickBooks Online journal.
        Each entry records a create, update, or delete event on the local copy of
        the record, including the changed attributes, their previous values, and the
        user or process that made the change.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Results are ordered newest first and paginated (standard pagination metadata
        is included in the response).


        Returns 404 if the journal does not exist.


        Authentication: Requires Bearer token.'
      parameters:
      - name: id
        in: path
        schema:
          type: string
        required: true
        description: The record ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        description:
                          type: string
                        event:
                          type: string
                        subject_type:
                          type: string
                        subject_id:
                          type: integer
                        batch_uuid:
                          type: string
                          nullable: true
                        properties:
                          type: object
                          properties:
                            attributes:
                              type: object
                              properties:
                                sync_status:
                                  type: string
                            old:
                              type: object
                              properties:
                                sync_status:
                                  type: string
                            source:
                              type: string
                        causer_name:
                          type: string
                        created_at:
                          type: string
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                    items:
                      type: object
                      properties:
                        url:
                          type: string
                          nullable: true
                        label:
                          type: string
                        active:
                          type: boolean
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 5821
                    description: updated
                    event: updated
                    subject_type: QboJournal
                    subject_id: 128
                    batch_uuid: null
                    properties:
                      attributes:
                        sync_status: synced
                      old:
                        sync_status: pending
                      source: qbo_sync
                    causer_name: Jane Smith
                    created_at: '2026-06-18T14:22:31.000000Z'
                  first_page_url: '{{protocol}}://{{domain}}/api/qbo/journals/128/activity-log?page=1'
                  from: 1
                  last_page: 1
                  last_page_url: '{{protocol}}://{{domain}}/api/qbo/journals/128/activity-log?page=1'
                  links:
                  - url: null
                    label: '&laquo; Previous'
                    active: false
                  - url: '{{protocol}}://{{domain}}/api/qbo/journals/128/activity-log?page=1'
                    label: '1'
                    active: true
                  - url: null
                    label: Next &raquo;
                    active: false
                  next_page_url: null
                  path: '{{protocol}}://{{domain}}/api/qbo/journals/128/activity-log'
                  per_page: 15
                  prev_page_url: null
                  to: 1
                  total: 1
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: object
                    properties:
                      id:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: array
                example:
                  errors:
                    id:
                    - message: Record not found.
                      code: NotFound
                      data: []
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-qbo-journals-id-activity-log
  /api/qbo/journals/unarchive:
    post:
      tags:
      - QuickBooks Online
      summary: Unarchive Journals
      description: 'Restore one or more archived QuickBooks Online journals by ID,
        marking them active again in SKU.io.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        This only restores the archived local synced copy in SKU.io; it does not modify
        anything in QuickBooks itself. Archiving and unarchiving control visibility
        within SKU.io only.


        Returns the number of records that were updated.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1
                - 2
                - 3
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      unarchived_count:
                        type: integer
                example:
                  success: true
                  message: Successfully unarchived 3 QBO journals(s)
                  data:
                    unarchived_count: 3
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  error:
                    type: string
                  details:
                    type: object
                    properties:
                      ids:
                        type: array
                        items:
                          type: string
                example:
                  success: false
                  error: Validation failed
                  details:
                    ids:
                    - The ids field is required.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-qbo-journals-unarchive
  /api/qbo/payments:
    get:
      tags:
      - QuickBooks Online
      summary: List Payments
      description: 'Paginated list of QBO payments.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Searchable columns (filter[search]): id, qbo_id, customer_name.'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        example: '1'
        description: Page number (default 1).
      - name: per_page
        in: query
        schema:
          type: integer
        example: '15'
        description: Results per page (default 10).
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-qbo-payments
    delete:
      tags:
      - QuickBooks Online
      summary: Delete Payments
      description: 'Delete one or more QBO payments.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: delete-api-qbo-payments
  /api/qbo/payments/{id}:
    get:
      tags:
      - QuickBooks Online
      summary: Get Payment
      description: 'Get a single QBO payment by ID.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        This document is pushed to QuickBooks by SKU''s ledger, so the response includes
        reverse cross-link fields: `ledger_entry_id` and `ledger_entry_reference`
        identify the SKU ledger entry that pushed it, while `sku_link_type`, `sku_link_id`,
        `sku_link_label`, and `sku_link_route` point back to the originating SKU document.
        These are `null` when the document originated in QuickBooks rather than being
        pushed by SKU. `customer_link_id` and `sku_customer_id` cross-link to the
        mirrored QuickBooks customer and its linked SKU customer. Returns `line_items`
        (normalized line rows parsed from the stored QuickBooks payload) and `detail_payload`
        (the full raw QuickBooks payload); both are null until the document is re-synced
        from QuickBooks.


        Also returns an `amounts` summary (`subtotal`, `tax`, `total`, `balance`,
        `paid`) and a `tax_code` on each `line_items` row.


        Payments additionally include the `bank` account name and an `applied` array
        of the invoices the payment was applied to (`txn_type`, `txn_id`, `amount`).'
      parameters:
      - name: id
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The record ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      qbo_id:
                        type: string
                      customer_id:
                        type: string
                      customer_name:
                        type: string
                      name:
                        type: string
                      total_amount:
                        type: string
                      currency:
                        type: string
                      txn_date:
                        type: string
                      payment_method:
                        type: string
                      reference_number:
                        type: string
                      active:
                        type: boolean
                      sync_status:
                        type: string
                      last_synced_at:
                        type: string
                      last_qbo_check_at:
                        type: string
                      sync_error_message:
                        type: string
                        nullable: true
                      qbo_created_at:
                        type: string
                      qbo_updated_at:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      integration_instance:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      qbo_link:
                        type: string
                      customer_link_id:
                        type: integer
                      sku_customer_id:
                        type: integer
                      ledger_entry_id:
                        type: integer
                      ledger_entry_reference:
                        type: string
                      sku_link_type:
                        type: string
                      sku_link_id:
                        type: integer
                      sku_link_label:
                        type: string
                      sku_link_route:
                        type: string
                      amounts:
                        type: object
                        properties:
                          subtotal:
                            type: integer
                          tax:
                            type: integer
                          total:
                            type: integer
                          balance:
                            type: integer
                          paid:
                            type: integer
                      bank:
                        type: string
                      applied:
                        type: array
                        items:
                          type: object
                          properties:
                            txn_type:
                              type: string
                            txn_id:
                              type: string
                            amount:
                              type: integer
                      line_items:
                        type: array
                        items:
                          type: object
                          properties:
                            line_num:
                              type: integer
                            description:
                              type: string
                            detail_type:
                              type: string
                            item:
                              type: string
                            item_id:
                              type: string
                            item_link_id:
                              type: integer
                            account:
                              type: string
                              nullable: true
                            quantity:
                              type: integer
                            unit_price:
                              type: number
                            amount:
                              type: integer
                            tax_code:
                              type: string
                            posting_type:
                              type: string
                              nullable: true
                      detail_payload:
                        type: object
                        properties:
                          Id:
                            type: string
                          TxnDate:
                            type: string
                          TotalAmt:
                            type: integer
                          CustomerRef:
                            type: object
                            properties:
                              value:
                                type: string
                              name:
                                type: string
                          CurrencyRef:
                            type: object
                            properties:
                              value:
                                type: string
                          Line:
                            type: array
                            items:
                              type: object
                              properties:
                                Id:
                                  type: string
                                LineNum:
                                  type: integer
                                Amount:
                                  type: integer
                                DetailType:
                                  type: string
                                Description:
                                  type: string
                                SalesItemLineDetail:
                                  type: object
                                  properties:
                                    ItemRef:
                                      type: object
                                      properties:
                                        value:
                                          type: string
                                        name:
                                          type: string
                                    Qty:
                                      type: integer
                                    UnitPrice:
                                      type: number
                          sparse:
                            type: boolean
                example:
                  success: true
                  data:
                    id: 74
                    integration_instance_id: 3
                    qbo_id: '509'
                    customer_id: '12'
                    customer_name: Bar Supply Co
                    name: Bar Supply Co
                    total_amount: '842.00'
                    currency: USD
                    txn_date: '2026-07-10'
                    payment_method: Credit Card
                    reference_number: PMT-509
                    active: true
                    sync_status: ok
                    last_synced_at: '2026-07-15T10:00:00.000000Z'
                    last_qbo_check_at: '2026-07-15T10:00:00.000000Z'
                    sync_error_message: null
                    qbo_created_at: '2026-07-01T09:00:00.000000Z'
                    qbo_updated_at: '2026-07-14T18:30:00.000000Z'
                    created_at: '2026-07-01T09:05:00.000000Z'
                    updated_at: '2026-07-14T18:35:00.000000Z'
                    integration_instance:
                      id: 3
                      name: QuickBooks Online
                    qbo_link: https://app.qbo.intuit.com/app/recvpayment?txnId=509
                    customer_link_id: 88
                    sku_customer_id: 1420
                    ledger_entry_id: 12506
                    ledger_entry_reference: O260724VOY4F6/R1
                    sku_link_type: App\Models\SalesOrder
                    sku_link_id: 4242
                    sku_link_label: Sales Order
                    sku_link_route: /orders/sales-orders/4242
                    amounts:
                      subtotal: 550
                      tax: 40
                      total: 590
                      balance: 90
                      paid: 500
                    bank: Checking
                    applied:
                    - txn_type: Invoice
                      txn_id: '8061'
                      amount: 180
                    line_items:
                    - line_num: 1
                      description: Osetra Caviar 4.4 oz
                      detail_type: SalesItemLineDetail
                      item: RO125G
                      item_id: '70'
                      item_link_id: 42
                      account: null
                      quantity: 4
                      unit_price: 147.5
                      amount: 590
                      tax_code: TAX
                      posting_type: null
                    detail_payload:
                      Id: '509'
                      TxnDate: '2026-07-10'
                      TotalAmt: 842
                      CustomerRef:
                        value: '12'
                        name: Bar Supply Co
                      CurrencyRef:
                        value: USD
                      Line:
                      - Id: '1'
                        LineNum: 1
                        Amount: 590
                        DetailType: SalesItemLineDetail
                        Description: Osetra Caviar 4.4 oz
                        SalesItemLineDetail:
                          ItemRef:
                            value: '21'
                            name: RO125G
                          Qty: 4
                          UnitPrice: 147.5
                      sparse: false
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-qbo-payments-id
  /api/qbo/payments/refresh:
    post:
      tags:
      - QuickBooks Online
      summary: Refresh Payments
      description: 'Syncs payments from QBO API.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                full_sync:
                  type: boolean
              example:
                full_sync: false
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-qbo-payments-refresh
  /api/qbo/payments/refresh-tracked:
    post:
      tags:
      - QuickBooks Online
      summary: Refresh Payments in Background
      description: 'Starts a background refresh of payments from QuickBooks and returns
        a job id you can poll for progress. Send no parameters for an incremental
        sync (records changed since the last sync), `full_sync: true` to re-pull everything,
        or `start_date` + `end_date` (MM/DD/YYYY) to pull records updated within a
        date range.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                full_sync:
                  type: boolean
              example:
                full_sync: false
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                      sync_type:
                        type: string
                      sync_description:
                        type: string
                example:
                  success: true
                  message: QBO payments refresh started.
                  data:
                    tracked_job_log_id: 8123
                    sync_type: incremental
                    sync_description: Incremental sync (changes since last sync)
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-qbo-payments-refresh-tracked
  /api/qbo/payments/sync-info:
    get:
      tags:
      - QuickBooks Online
      summary: Get Payments Sync Info
      description: Returns the latest synced payment identifier and timestamp, the
        total number of payments already stored, and the fields you can search QuickBooks
        by for this entity.
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      latest_identifier:
                        type: string
                      latest_date:
                        type: string
                      total_count:
                        type: integer
                      searchable_fields:
                        type: array
                        items:
                          type: object
                          properties:
                            value:
                              type: string
                            label:
                              type: string
                            qbo_field:
                              type: string
                            exact:
                              type: boolean
                example:
                  success: true
                  data:
                    latest_identifier: REF-1042
                    latest_date: '2026-07-16T18:22:05.000000Z'
                    total_count: 128
                    searchable_fields:
                    - value: doc_number
                      label: Doc Number
                      qbo_field: DocNumber
                      exact: false
                    - value: qbo_id
                      label: QuickBooks ID
                      qbo_field: Id
                      exact: true
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-qbo-payments-sync-info
  /api/qbo/payments/search-qbo:
    post:
      tags:
      - QuickBooks Online
      summary: Search Payments in QuickBooks
      description: Searches QuickBooks directly for payments matching a field/value
        (without importing them). `field` must be one of the values returned by Get
        Payments Sync Info (e.g. `doc_number`, `qbo_id`). Each result flags whether
        it already exists in your database.
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                field:
                  type: string
                value:
                  type: string
              example:
                field: doc_number
                value: '1042'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        qbo_id:
                          type: string
                        label:
                          type: string
                        sub_label:
                          type: string
                        exists_in_database:
                          type: boolean
                example:
                  success: true
                  data:
                  - qbo_id: '1042'
                    label: INV-1042
                    sub_label: QuickBooks ID 1042
                    exists_in_database: true
                  - qbo_id: '1043'
                    label: INV-1043
                    sub_label: QuickBooks ID 1043
                    exists_in_database: false
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-qbo-payments-search-qbo
  /api/qbo/payments/refresh-single:
    post:
      tags:
      - QuickBooks Online
      summary: Pull Payment from QuickBooks
      description: Fetches a single payment from QuickBooks by its QuickBooks id and
        imports (or updates) it in your database.
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                qbo_id:
                  type: string
              example:
                qbo_id: '1043'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      success:
                        type: boolean
                      qbo_id:
                        type: string
                      id:
                        type: integer
                example:
                  success: true
                  message: QBO payment pulled from QuickBooks.
                  data:
                    success: true
                    qbo_id: '1043'
                    id: 991
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-qbo-payments-refresh-single
  /api/qbo/payments/archive:
    post:
      tags:
      - QuickBooks Online
      summary: Archive Payments
      description: 'Archive one or more QBO payments.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-qbo-payments-archive
  /api/qbo/payments/export:
    get:
      tags:
      - QuickBooks Online
      summary: Export Payments
      description: 'Download the QuickBooks Online payments synced into SKU.io as
        a CSV file. The export is streamed from the locally synced copies; no request
        is made to QuickBooks.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        CSV columns: QBO ID, Customer ID, Customer Name, Total Amount, Currency, Transaction
        Date, Payment Method, Reference Number, Active, QBO Created At, QBO Updated
        At, Local Created At, Local Updated At.


        The response is a file download (`Content-Type: text/csv`) with a filename
        of the form `qbo_payments_export_2026-07-07_10-30-00.csv`. By default all
        records (active and archived) are included; use the query parameters to narrow
        the export.


        Returns a 500 error if no QuickBooks Online integration has been set up, and
        a 422 error if a date parameter is not in MM/DD/YYYY format.


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-qbo-payments-export
  /api/qbo/payments/statistics:
    get:
      tags:
      - QuickBooks Online
      summary: Get Payment Statistics
      description: 'Get aggregate counts for the QuickBooks Online payments synced
        into SKU.io: the total number of records, how many are active, and how many
        are archived.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Counts are computed from the locally synced copies; no request is made to
        QuickBooks.


        Returns a 500 error if no QuickBooks Online integration has been set up.


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      total:
                        type: integer
                      active:
                        type: integer
                      archived:
                        type: integer
                example:
                  success: true
                  data:
                    total: 873
                    active: 861
                    archived: 12
        '500':
          description: Internal Server Error
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  error:
                    type: string
                  message:
                    type: string
                example:
                  success: false
                  error: Failed to get QBO payments statistics
                  message: No QBO integration instance found. Please set up your QuickBooks
                    Online integration first.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-qbo-payments-statistics
  /api/qbo/payments/{id}/activity-log:
    get:
      tags:
      - QuickBooks Online
      summary: Get Payment Activity Log
      description: 'Retrieve the audit trail for a synced QuickBooks Online payment.
        Each entry records a create, update, or delete event on the local copy of
        the record, including the changed attributes, their previous values, and the
        user or process that made the change.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Results are ordered newest first and paginated (standard pagination metadata
        is included in the response).


        Returns 404 if the payment does not exist.


        Authentication: Requires Bearer token.'
      parameters:
      - name: id
        in: path
        schema:
          type: string
        required: true
        description: The record ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        description:
                          type: string
                        event:
                          type: string
                        subject_type:
                          type: string
                        subject_id:
                          type: integer
                        batch_uuid:
                          type: string
                          nullable: true
                        properties:
                          type: object
                          properties:
                            attributes:
                              type: object
                              properties:
                                sync_status:
                                  type: string
                            old:
                              type: object
                              properties:
                                sync_status:
                                  type: string
                            source:
                              type: string
                        causer_name:
                          type: string
                        created_at:
                          type: string
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                    items:
                      type: object
                      properties:
                        url:
                          type: string
                          nullable: true
                        label:
                          type: string
                        active:
                          type: boolean
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 5821
                    description: updated
                    event: updated
                    subject_type: QboPayment
                    subject_id: 209
                    batch_uuid: null
                    properties:
                      attributes:
                        sync_status: synced
                      old:
                        sync_status: pending
                      source: qbo_sync
                    causer_name: Jane Smith
                    created_at: '2026-06-18T14:22:31.000000Z'
                  first_page_url: '{{protocol}}://{{domain}}/api/qbo/payments/209/activity-log?page=1'
                  from: 1
                  last_page: 1
                  last_page_url: '{{protocol}}://{{domain}}/api/qbo/payments/209/activity-log?page=1'
                  links:
                  - url: null
                    label: '&laquo; Previous'
                    active: false
                  - url: '{{protocol}}://{{domain}}/api/qbo/payments/209/activity-log?page=1'
                    label: '1'
                    active: true
                  - url: null
                    label: Next &raquo;
                    active: false
                  next_page_url: null
                  path: '{{protocol}}://{{domain}}/api/qbo/payments/209/activity-log'
                  per_page: 15
                  prev_page_url: null
                  to: 1
                  total: 1
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: object
                    properties:
                      id:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: array
                example:
                  errors:
                    id:
                    - message: Record not found.
                      code: NotFound
                      data: []
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-qbo-payments-id-activity-log
  /api/qbo/payments/unarchive:
    post:
      tags:
      - QuickBooks Online
      summary: Unarchive Payments
      description: 'Restore one or more archived QuickBooks Online payments by ID,
        marking them active again in SKU.io.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        This only restores the archived local synced copy in SKU.io; it does not modify
        anything in QuickBooks itself. Archiving and unarchiving control visibility
        within SKU.io only.


        Returns the number of records that were updated.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1
                - 2
                - 3
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      unarchived_count:
                        type: integer
                example:
                  success: true
                  message: Successfully unarchived 3 QBO payments(s)
                  data:
                    unarchived_count: 3
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  error:
                    type: string
                  details:
                    type: object
                    properties:
                      ids:
                        type: array
                        items:
                          type: string
                example:
                  success: false
                  error: Validation failed
                  details:
                    ids:
                    - The ids field is required.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-qbo-payments-unarchive
  /api/qbo/purchase-orders:
    get:
      tags:
      - QuickBooks Online
      summary: List Purchase Orders
      description: 'Paginated list of QBO purchase orders.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Searchable columns (filter[search]): id, qbo_id, doc_number, vendor_name.'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        example: '1'
        description: Page number (default 1).
      - name: per_page
        in: query
        schema:
          type: integer
        example: '15'
        description: Results per page (default 10).
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-qbo-purchase-orders
    delete:
      tags:
      - QuickBooks Online
      summary: Delete Purchase Orders
      description: 'Delete one or more QBO purchase orders.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: delete-api-qbo-purchase-orders
  /api/qbo/purchase-orders/{id}:
    get:
      tags:
      - QuickBooks Online
      summary: Get Purchase Order
      description: 'Get a single QBO purchase order by ID.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        The `linked_sku_purchase_order` field identifies the SKU purchase order this
        QuickBooks document was pushed from (id, purchase order number, and an app
        route); it is null when no such origin exists. `qbo_link` deep-links to the
        purchase order in the QuickBooks web UI.


        The response includes `vendor_link_id`, cross-linking to the mirrored QuickBooks
        vendor. The reverse ledger cross-link fields `ledger_entry_id`, `ledger_entry_reference`,
        `sku_link_type`, `sku_link_id`, `sku_link_label`, and `sku_link_route` are
        also present but are always `null` for purchase orders, which are not pushed
        by SKU''s ledger. Returns `line_items` (normalized line rows parsed from the
        stored QuickBooks payload) and `detail_payload` (the full raw QuickBooks payload);
        both are null until the document is re-synced from QuickBooks.


        Also returns an `amounts` summary (`subtotal`, `tax`, `total`, `balance`,
        `paid`) and a `tax_code` on each `line_items` row.


        Purchase orders additionally include a `shipping` block (`ship_to_address`,
        `due_date`, `ship_method`, `memo`, `po_status`).'
      parameters:
      - name: id
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The record ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      qbo_id:
                        type: string
                      doc_number:
                        type: string
                      vendor_id:
                        type: string
                      vendor_name:
                        type: string
                      total_amount:
                        type: string
                      currency:
                        type: string
                      txn_date:
                        type: string
                      status:
                        type: string
                      active:
                        type: boolean
                      sync_status:
                        type: string
                      last_synced_at:
                        type: string
                      last_qbo_check_at:
                        type: string
                      sync_error_message:
                        type: string
                        nullable: true
                      qbo_created_at:
                        type: string
                      qbo_updated_at:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      integration_instance:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      qbo_link:
                        type: string
                      vendor_link_id:
                        type: integer
                      ledger_entry_id:
                        type: string
                        nullable: true
                      ledger_entry_reference:
                        type: string
                        nullable: true
                      sku_link_type:
                        type: string
                        nullable: true
                      sku_link_id:
                        type: string
                        nullable: true
                      sku_link_label:
                        type: string
                        nullable: true
                      sku_link_route:
                        type: string
                        nullable: true
                      linked_sku_purchase_order:
                        type: object
                        properties:
                          id:
                            type: integer
                          purchase_order_number:
                            type: string
                          route:
                            type: string
                      amounts:
                        type: object
                        properties:
                          subtotal:
                            type: integer
                          tax:
                            type: integer
                          total:
                            type: integer
                          balance:
                            type: integer
                          paid:
                            type: integer
                      shipping:
                        type: object
                        properties:
                          ship_to_address:
                            type: string
                          due_date:
                            type: string
                          ship_method:
                            type: string
                          memo:
                            type: string
                          po_status:
                            type: string
                      line_items:
                        type: array
                        items:
                          type: object
                          properties:
                            line_num:
                              type: integer
                            description:
                              type: string
                            detail_type:
                              type: string
                            item:
                              type: string
                              nullable: true
                            item_id:
                              type: string
                              nullable: true
                            item_link_id:
                              type: string
                              nullable: true
                            account:
                              type: string
                            quantity:
                              type: string
                              nullable: true
                            unit_price:
                              type: string
                              nullable: true
                            amount:
                              type: integer
                            tax_code:
                              type: string
                            posting_type:
                              type: string
                              nullable: true
                      detail_payload:
                        type: object
                        properties:
                          Id:
                            type: string
                          DocNumber:
                            type: string
                          TxnDate:
                            type: string
                          TotalAmt:
                            type: integer
                          VendorRef:
                            type: object
                            properties:
                              value:
                                type: string
                              name:
                                type: string
                          CurrencyRef:
                            type: object
                            properties:
                              value:
                                type: string
                          Line:
                            type: array
                            items:
                              type: object
                              properties:
                                Id:
                                  type: string
                                Amount:
                                  type: integer
                                DetailType:
                                  type: string
                                Description:
                                  type: string
                                AccountBasedExpenseLineDetail:
                                  type: object
                                  properties:
                                    AccountRef:
                                      type: object
                                      properties:
                                        value:
                                          type: string
                                        name:
                                          type: string
                          sparse:
                            type: boolean
                example:
                  success: true
                  data:
                    id: 52
                    integration_instance_id: 3
                    qbo_id: '612'
                    doc_number: PO-1450
                    vendor_id: '56'
                    vendor_name: Shanghai Supplier Co
                    total_amount: '20000.00'
                    currency: USD
                    txn_date: '2026-06-20'
                    status: Open
                    active: true
                    sync_status: ok
                    last_synced_at: '2026-07-15T10:00:00.000000Z'
                    last_qbo_check_at: '2026-07-15T10:00:00.000000Z'
                    sync_error_message: null
                    qbo_created_at: '2026-07-01T09:00:00.000000Z'
                    qbo_updated_at: '2026-07-14T18:30:00.000000Z'
                    created_at: '2026-07-01T09:05:00.000000Z'
                    updated_at: '2026-07-14T18:35:00.000000Z'
                    integration_instance:
                      id: 3
                      name: QuickBooks Online
                    qbo_link: https://app.qbo.intuit.com/app/purchaseorder?txnId=612
                    vendor_link_id: 57
                    ledger_entry_id: null
                    ledger_entry_reference: null
                    sku_link_type: null
                    sku_link_id: null
                    sku_link_label: null
                    sku_link_route: null
                    linked_sku_purchase_order:
                      id: 1450
                      purchase_order_number: PO-1450
                      route: /orders/purchase-orders/1450
                    amounts:
                      subtotal: 550
                      tax: 40
                      total: 590
                      balance: 90
                      paid: 500
                    shipping:
                      ship_to_address: 123 Main St, Austin, TX, 78701
                      due_date: '2026-02-11'
                      ship_method: UPS Ground
                      memo: Deliver to dock B; call warehouse on arrival.
                      po_status: Open
                    line_items:
                    - line_num: 1
                      description: Cold-chain freight
                      detail_type: AccountBasedExpenseLineDetail
                      item: null
                      item_id: null
                      item_link_id: null
                      account: Shipping & Freight
                      quantity: null
                      unit_price: null
                      amount: 125
                      tax_code: TAX
                      posting_type: null
                    detail_payload:
                      Id: '612'
                      DocNumber: PO-1450
                      TxnDate: '2026-06-20'
                      TotalAmt: 20000
                      VendorRef:
                        value: '56'
                        name: Shanghai Supplier Co
                      CurrencyRef:
                        value: USD
                      Line:
                      - Id: '1'
                        Amount: 125
                        DetailType: AccountBasedExpenseLineDetail
                        Description: Cold-chain freight
                        AccountBasedExpenseLineDetail:
                          AccountRef:
                            value: '63'
                            name: Shipping & Freight
                      sparse: false
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-qbo-purchase-orders-id
  /api/qbo/purchase-orders/refresh:
    post:
      tags:
      - QuickBooks Online
      summary: Refresh Purchase Orders
      description: 'Syncs purchase orders from QBO API.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                full_sync:
                  type: boolean
              example:
                full_sync: false
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-qbo-purchase-orders-refresh
  /api/qbo/purchase-orders/refresh-tracked:
    post:
      tags:
      - QuickBooks Online
      summary: Refresh Purchase Orders in Background
      description: 'Starts a background refresh of purchase orders from QuickBooks
        and returns a job id you can poll for progress. Send no parameters for an
        incremental sync (records changed since the last sync), `full_sync: true`
        to re-pull everything, or `start_date` + `end_date` (MM/DD/YYYY) to pull records
        updated within a date range.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                full_sync:
                  type: boolean
              example:
                full_sync: false
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                      sync_type:
                        type: string
                      sync_description:
                        type: string
                example:
                  success: true
                  message: QBO purchase-orders refresh started.
                  data:
                    tracked_job_log_id: 8123
                    sync_type: incremental
                    sync_description: Incremental sync (changes since last sync)
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-qbo-purchase-orders-refresh-tracked
  /api/qbo/purchase-orders/sync-info:
    get:
      tags:
      - QuickBooks Online
      summary: Get Purchase Orders Sync Info
      description: Returns the latest synced purchase order identifier and timestamp,
        the total number of purchase orders already stored, and the fields you can
        search QuickBooks by for this entity.
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      latest_identifier:
                        type: string
                      latest_date:
                        type: string
                      total_count:
                        type: integer
                      searchable_fields:
                        type: array
                        items:
                          type: object
                          properties:
                            value:
                              type: string
                            label:
                              type: string
                            qbo_field:
                              type: string
                            exact:
                              type: boolean
                example:
                  success: true
                  data:
                    latest_identifier: REF-1042
                    latest_date: '2026-07-16T18:22:05.000000Z'
                    total_count: 128
                    searchable_fields:
                    - value: doc_number
                      label: Doc Number
                      qbo_field: DocNumber
                      exact: false
                    - value: qbo_id
                      label: QuickBooks ID
                      qbo_field: Id
                      exact: true
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-qbo-purchase-orders-sync-info
  /api/qbo/purchase-orders/search-qbo:
    post:
      tags:
      - QuickBooks Online
      summary: Search Purchase Orders in QuickBooks
      description: Searches QuickBooks directly for purchase orders matching a field/value
        (without importing them). `field` must be one of the values returned by Get
        Purchase Orders Sync Info (e.g. `doc_number`, `qbo_id`). Each result flags
        whether it already exists in your database.
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                field:
                  type: string
                value:
                  type: string
              example:
                field: doc_number
                value: '1042'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        qbo_id:
                          type: string
                        label:
                          type: string
                        sub_label:
                          type: string
                        exists_in_database:
                          type: boolean
                example:
                  success: true
                  data:
                  - qbo_id: '1042'
                    label: INV-1042
                    sub_label: QuickBooks ID 1042
                    exists_in_database: true
                  - qbo_id: '1043'
                    label: INV-1043
                    sub_label: QuickBooks ID 1043
                    exists_in_database: false
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-qbo-purchase-orders-search-qbo
  /api/qbo/purchase-orders/refresh-single:
    post:
      tags:
      - QuickBooks Online
      summary: Pull Purchase Order from QuickBooks
      description: Fetches a single purchase order from QuickBooks by its QuickBooks
        id and imports (or updates) it in your database.
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                qbo_id:
                  type: string
              example:
                qbo_id: '1043'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      success:
                        type: boolean
                      qbo_id:
                        type: string
                      id:
                        type: integer
                example:
                  success: true
                  message: QBO purchase order pulled from QuickBooks.
                  data:
                    success: true
                    qbo_id: '1043'
                    id: 991
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-qbo-purchase-orders-refresh-single
  /api/qbo/purchase-orders/archive:
    post:
      tags:
      - QuickBooks Online
      summary: Archive Purchase Orders
      description: 'Archive one or more QBO purchase orders.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-qbo-purchase-orders-archive
  /api/qbo/purchase-orders/export:
    get:
      tags:
      - QuickBooks Online
      summary: Export Purchase Orders
      description: 'Download the QuickBooks Online purchase orders synced into SKU.io
        as a CSV file. The export is streamed from the locally synced copies; no request
        is made to QuickBooks.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        CSV columns: QBO ID, Doc Number, Vendor ID, Vendor Name, Total Amount, Currency,
        Transaction Date, Status, Active, QBO Created At, QBO Updated At, Local Created
        At, Local Updated At.


        The response is a file download (`Content-Type: text/csv`) with a filename
        of the form `qbo_purchase-orders_export_2026-07-07_10-30-00.csv`. By default
        all records (active and archived) are included; use the query parameters to
        narrow the export.


        Returns a 500 error if no QuickBooks Online integration has been set up, and
        a 422 error if a date parameter is not in MM/DD/YYYY format.


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-qbo-purchase-orders-export
  /api/qbo/purchase-orders/statistics:
    get:
      tags:
      - QuickBooks Online
      summary: Get Purchase Order Statistics
      description: 'Get aggregate counts for the QuickBooks Online purchase orders
        synced into SKU.io: the total number of records, how many are active, and
        how many are archived.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Counts are computed from the locally synced copies; no request is made to
        QuickBooks.


        Returns a 500 error if no QuickBooks Online integration has been set up.


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      total:
                        type: integer
                      active:
                        type: integer
                      archived:
                        type: integer
                example:
                  success: true
                  data:
                    total: 211
                    active: 198
                    archived: 13
        '500':
          description: Internal Server Error
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  error:
                    type: string
                  message:
                    type: string
                example:
                  success: false
                  error: Failed to get QBO purchase-orders statistics
                  message: No QBO integration instance found. Please set up your QuickBooks
                    Online integration first.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-qbo-purchase-orders-statistics
  /api/qbo/purchase-orders/unarchive:
    post:
      tags:
      - QuickBooks Online
      summary: Unarchive Purchase Orders
      description: 'Restore one or more archived QuickBooks Online purchase orders
        by ID, marking them active again in SKU.io.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        This only restores the archived local synced copy in SKU.io; it does not modify
        anything in QuickBooks itself. Archiving and unarchiving control visibility
        within SKU.io only.


        Returns the number of records that were updated.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1
                - 2
                - 3
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      unarchived_count:
                        type: integer
                example:
                  success: true
                  message: Successfully unarchived 3 QBO purchase-orders(s)
                  data:
                    unarchived_count: 3
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  error:
                    type: string
                  details:
                    type: object
                    properties:
                      ids:
                        type: array
                        items:
                          type: string
                example:
                  success: false
                  error: Validation failed
                  details:
                    ids:
                    - The ids field is required.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-qbo-purchase-orders-unarchive
  /api/qbo/purchase-orders/{id}/activity-log:
    get:
      tags:
      - QuickBooks Online
      summary: Get Purchase Order Activity Log
      description: 'Retrieve the audit trail for a synced QuickBooks Online purchase
        order. Each entry records a create, update, or delete event on the local copy
        of the record, including the changed attributes, their previous values, and
        the user or process that made the change.


        Results are ordered newest first and paginated (standard pagination metadata
        is included in the response).


        Returns 404 if the purchase order does not exist.


        Authentication: Requires Bearer token.'
      parameters:
      - name: id
        in: path
        schema:
          type: string
        required: true
        description: The record ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        description:
                          type: string
                        event:
                          type: string
                        subject_type:
                          type: string
                        subject_id:
                          type: integer
                        batch_uuid:
                          type: string
                          nullable: true
                        properties:
                          type: object
                          properties:
                            attributes:
                              type: object
                              properties:
                                sync_status:
                                  type: string
                            old:
                              type: object
                              properties:
                                sync_status:
                                  type: string
                            source:
                              type: string
                        causer_name:
                          type: string
                        created_at:
                          type: string
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                    items:
                      type: object
                      properties:
                        url:
                          type: string
                          nullable: true
                        label:
                          type: string
                        active:
                          type: boolean
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 5821
                    description: updated
                    event: updated
                    subject_type: QboPurchaseOrder
                    subject_id: 87
                    batch_uuid: null
                    properties:
                      attributes:
                        sync_status: synced
                      old:
                        sync_status: pending
                      source: qbo_sync
                    causer_name: Jane Smith
                    created_at: '2026-06-18T14:22:31.000000Z'
                  first_page_url: '{{protocol}}://{{domain}}/api/qbo/purchase-orders/87/activity-log?page=1'
                  from: 1
                  last_page: 1
                  last_page_url: '{{protocol}}://{{domain}}/api/qbo/purchase-orders/87/activity-log?page=1'
                  links:
                  - url: null
                    label: '&laquo; Previous'
                    active: false
                  - url: '{{protocol}}://{{domain}}/api/qbo/purchase-orders/87/activity-log?page=1'
                    label: '1'
                    active: true
                  - url: null
                    label: Next &raquo;
                    active: false
                  next_page_url: null
                  path: '{{protocol}}://{{domain}}/api/qbo/purchase-orders/87/activity-log'
                  per_page: 15
                  prev_page_url: null
                  to: 1
                  total: 1
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: object
                    properties:
                      id:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: array
                example:
                  errors:
                    id:
                    - message: Record not found.
                      code: NotFound
                      data: []
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-qbo-purchase-orders-id-activity-log
  /api/qbo/tax-codes:
    get:
      tags:
      - QuickBooks Online
      summary: List Tax Codes
      description: 'Paginated list of QBO tax codes.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Searchable columns (filter[search]): id, qbo_id, name, description.'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        example: '1'
        description: Page number (default 1).
      - name: per_page
        in: query
        schema:
          type: integer
        example: '15'
        description: Results per page (default 10).
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-qbo-tax-codes
    delete:
      tags:
      - QuickBooks Online
      summary: Delete Tax Codes
      description: 'Delete one or more QBO tax codes.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: delete-api-qbo-tax-codes
  /api/qbo/tax-codes/{id}:
    get:
      tags:
      - QuickBooks Online
      summary: Get Tax Code
      description: 'Get a single QBO tax code by ID.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: id
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The record ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-qbo-tax-codes-id
  /api/qbo/tax-codes/refresh:
    post:
      tags:
      - QuickBooks Online
      summary: Refresh Tax Codes
      description: 'Syncs tax codes from QBO API.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                full_sync:
                  type: boolean
              example:
                full_sync: false
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-qbo-tax-codes-refresh
  /api/qbo/tax-codes/refresh-tracked:
    post:
      tags:
      - QuickBooks Online
      summary: Refresh Tax Codes in Background
      description: 'Starts a background refresh of tax codes from QuickBooks and returns
        a job id you can poll for progress. Send no parameters for an incremental
        sync (records changed since the last sync), `full_sync: true` to re-pull everything,
        or `start_date` + `end_date` (MM/DD/YYYY) to pull records updated within a
        date range.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                full_sync:
                  type: boolean
              example:
                full_sync: false
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                      sync_type:
                        type: string
                      sync_description:
                        type: string
                example:
                  success: true
                  message: QBO tax-codes refresh started.
                  data:
                    tracked_job_log_id: 8123
                    sync_type: incremental
                    sync_description: Incremental sync (changes since last sync)
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-qbo-tax-codes-refresh-tracked
  /api/qbo/tax-codes/sync-info:
    get:
      tags:
      - QuickBooks Online
      summary: Get Tax Codes Sync Info
      description: Returns the latest synced tax code identifier and timestamp, the
        total number of tax codes already stored, and the fields you can search QuickBooks
        by for this entity.
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      latest_identifier:
                        type: string
                      latest_date:
                        type: string
                      total_count:
                        type: integer
                      searchable_fields:
                        type: array
                        items:
                          type: object
                          properties:
                            value:
                              type: string
                            label:
                              type: string
                            qbo_field:
                              type: string
                            exact:
                              type: boolean
                example:
                  success: true
                  data:
                    latest_identifier: REF-1042
                    latest_date: '2026-07-16T18:22:05.000000Z'
                    total_count: 128
                    searchable_fields:
                    - value: doc_number
                      label: Doc Number
                      qbo_field: DocNumber
                      exact: false
                    - value: qbo_id
                      label: QuickBooks ID
                      qbo_field: Id
                      exact: true
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-qbo-tax-codes-sync-info
  /api/qbo/tax-codes/search-qbo:
    post:
      tags:
      - QuickBooks Online
      summary: Search Tax Codes in QuickBooks
      description: Searches QuickBooks directly for tax codes matching a field/value
        (without importing them). `field` must be one of the values returned by Get
        Tax Codes Sync Info (e.g. `doc_number`, `qbo_id`). Each result flags whether
        it already exists in your database.
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                field:
                  type: string
                value:
                  type: string
              example:
                field: doc_number
                value: '1042'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        qbo_id:
                          type: string
                        label:
                          type: string
                        sub_label:
                          type: string
                        exists_in_database:
                          type: boolean
                example:
                  success: true
                  data:
                  - qbo_id: '1042'
                    label: INV-1042
                    sub_label: QuickBooks ID 1042
                    exists_in_database: true
                  - qbo_id: '1043'
                    label: INV-1043
                    sub_label: QuickBooks ID 1043
                    exists_in_database: false
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-qbo-tax-codes-search-qbo
  /api/qbo/tax-codes/refresh-single:
    post:
      tags:
      - QuickBooks Online
      summary: Pull Tax Code from QuickBooks
      description: Fetches a single tax code from QuickBooks by its QuickBooks id
        and imports (or updates) it in your database.
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                qbo_id:
                  type: string
              example:
                qbo_id: '1043'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      success:
                        type: boolean
                      qbo_id:
                        type: string
                      id:
                        type: integer
                example:
                  success: true
                  message: QBO tax code pulled from QuickBooks.
                  data:
                    success: true
                    qbo_id: '1043'
                    id: 991
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-qbo-tax-codes-refresh-single
  /api/qbo/tax-codes/archive:
    post:
      tags:
      - QuickBooks Online
      summary: Archive Tax Codes
      description: 'Archive one or more QBO tax codes.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-qbo-tax-codes-archive
  /api/qbo/tax-codes/export:
    get:
      tags:
      - QuickBooks Online
      summary: Export Tax Codes
      description: 'Download the QuickBooks Online tax codes synced into SKU.io as
        a CSV file. The export is streamed from the locally synced copies; no request
        is made to QuickBooks.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        CSV columns: QBO ID, Name, Description, Taxable, Active, QBO Created At, QBO
        Updated At, Local Created At, Local Updated At.


        The response is a file download (`Content-Type: text/csv`) with a filename
        of the form `qbo_tax-codes_export_2026-07-07_10-30-00.csv`. By default all
        records (active and archived) are included; use the query parameters to narrow
        the export.


        Returns a 500 error if no QuickBooks Online integration has been set up, and
        a 422 error if a date parameter is not in MM/DD/YYYY format.


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-qbo-tax-codes-export
  /api/qbo/tax-codes/statistics:
    get:
      tags:
      - QuickBooks Online
      summary: Get Tax Code Statistics
      description: 'Get aggregate counts for the QuickBooks Online tax codes synced
        into SKU.io: the total number of records, how many are active, and how many
        are archived.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Counts are computed from the locally synced copies; no request is made to
        QuickBooks.


        Returns a 500 error if no QuickBooks Online integration has been set up.


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      total:
                        type: integer
                      active:
                        type: integer
                      archived:
                        type: integer
                example:
                  success: true
                  data:
                    total: 14
                    active: 12
                    archived: 2
        '500':
          description: Internal Server Error
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  error:
                    type: string
                  message:
                    type: string
                example:
                  success: false
                  error: Failed to get QBO tax-codes statistics
                  message: No QBO integration instance found. Please set up your QuickBooks
                    Online integration first.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-qbo-tax-codes-statistics
  /api/qbo/tax-codes/unarchive:
    post:
      tags:
      - QuickBooks Online
      summary: Unarchive Tax Codes
      description: 'Restore one or more archived QuickBooks Online tax codes by ID,
        marking them active again in SKU.io.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        This only restores the archived local synced copy in SKU.io; it does not modify
        anything in QuickBooks itself. Archiving and unarchiving control visibility
        within SKU.io only.


        Returns the number of records that were updated.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1
                - 2
                - 3
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      unarchived_count:
                        type: integer
                example:
                  success: true
                  message: Successfully unarchived 3 QBO tax-codes(s)
                  data:
                    unarchived_count: 3
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  error:
                    type: string
                  details:
                    type: object
                    properties:
                      ids:
                        type: array
                        items:
                          type: string
                example:
                  success: false
                  error: Validation failed
                  details:
                    ids:
                    - The ids field is required.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-qbo-tax-codes-unarchive
  /api/qbo/tax-rates:
    get:
      tags:
      - QuickBooks Online
      summary: List Tax Rates
      description: 'Paginated list of QBO tax rates.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Searchable columns (filter[search]): id, qbo_id, name, description.'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        example: '1'
        description: Page number (default 1).
      - name: per_page
        in: query
        schema:
          type: integer
        example: '15'
        description: Results per page (default 10).
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-qbo-tax-rates
    delete:
      tags:
      - QuickBooks Online
      summary: Delete Tax Rates
      description: 'Delete one or more QBO tax rates.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: delete-api-qbo-tax-rates
  /api/qbo/tax-rates/{id}:
    get:
      tags:
      - QuickBooks Online
      summary: Get Tax Rate
      description: 'Get a single QBO tax rate by ID.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: id
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The record ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-qbo-tax-rates-id
  /api/qbo/tax-rates/refresh:
    post:
      tags:
      - QuickBooks Online
      summary: Refresh Tax Rates
      description: 'Syncs tax rates from QBO API.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                full_sync:
                  type: boolean
              example:
                full_sync: false
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-qbo-tax-rates-refresh
  /api/qbo/tax-rates/refresh-tracked:
    post:
      tags:
      - QuickBooks Online
      summary: Refresh Tax Rates in Background
      description: 'Starts a background refresh of tax rates from QuickBooks and returns
        a job id you can poll for progress. Send no parameters for an incremental
        sync (records changed since the last sync), `full_sync: true` to re-pull everything,
        or `start_date` + `end_date` (MM/DD/YYYY) to pull records updated within a
        date range.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                full_sync:
                  type: boolean
              example:
                full_sync: false
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                      sync_type:
                        type: string
                      sync_description:
                        type: string
                example:
                  success: true
                  message: QBO tax-rates refresh started.
                  data:
                    tracked_job_log_id: 8123
                    sync_type: incremental
                    sync_description: Incremental sync (changes since last sync)
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-qbo-tax-rates-refresh-tracked
  /api/qbo/tax-rates/sync-info:
    get:
      tags:
      - QuickBooks Online
      summary: Get Tax Rates Sync Info
      description: Returns the latest synced tax rate identifier and timestamp, the
        total number of tax rates already stored, and the fields you can search QuickBooks
        by for this entity.
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      latest_identifier:
                        type: string
                      latest_date:
                        type: string
                      total_count:
                        type: integer
                      searchable_fields:
                        type: array
                        items:
                          type: object
                          properties:
                            value:
                              type: string
                            label:
                              type: string
                            qbo_field:
                              type: string
                            exact:
                              type: boolean
                example:
                  success: true
                  data:
                    latest_identifier: REF-1042
                    latest_date: '2026-07-16T18:22:05.000000Z'
                    total_count: 128
                    searchable_fields:
                    - value: doc_number
                      label: Doc Number
                      qbo_field: DocNumber
                      exact: false
                    - value: qbo_id
                      label: QuickBooks ID
                      qbo_field: Id
                      exact: true
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-qbo-tax-rates-sync-info
  /api/qbo/tax-rates/search-qbo:
    post:
      tags:
      - QuickBooks Online
      summary: Search Tax Rates in QuickBooks
      description: Searches QuickBooks directly for tax rates matching a field/value
        (without importing them). `field` must be one of the values returned by Get
        Tax Rates Sync Info (e.g. `doc_number`, `qbo_id`). Each result flags whether
        it already exists in your database.
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                field:
                  type: string
                value:
                  type: string
              example:
                field: doc_number
                value: '1042'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        qbo_id:
                          type: string
                        label:
                          type: string
                        sub_label:
                          type: string
                        exists_in_database:
                          type: boolean
                example:
                  success: true
                  data:
                  - qbo_id: '1042'
                    label: INV-1042
                    sub_label: QuickBooks ID 1042
                    exists_in_database: true
                  - qbo_id: '1043'
                    label: INV-1043
                    sub_label: QuickBooks ID 1043
                    exists_in_database: false
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-qbo-tax-rates-search-qbo
  /api/qbo/tax-rates/refresh-single:
    post:
      tags:
      - QuickBooks Online
      summary: Pull Tax Rate from QuickBooks
      description: Fetches a single tax rate from QuickBooks by its QuickBooks id
        and imports (or updates) it in your database.
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                qbo_id:
                  type: string
              example:
                qbo_id: '1043'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      success:
                        type: boolean
                      qbo_id:
                        type: string
                      id:
                        type: integer
                example:
                  success: true
                  message: QBO tax rate pulled from QuickBooks.
                  data:
                    success: true
                    qbo_id: '1043'
                    id: 991
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-qbo-tax-rates-refresh-single
  /api/qbo/tax-rates/archive:
    post:
      tags:
      - QuickBooks Online
      summary: Archive Tax Rates
      description: 'Archive one or more QBO tax rates.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-qbo-tax-rates-archive
  /api/qbo/tax-rates/export:
    get:
      tags:
      - QuickBooks Online
      summary: Export Tax Rates
      description: 'Download the QuickBooks Online tax rates synced into SKU.io as
        a CSV file. The export is streamed from the locally synced copies; no request
        is made to QuickBooks.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        CSV columns: QBO ID, Name, Description, Rate Value, Agency ID, Agency Name,
        Active, QBO Created At, QBO Updated At, Local Created At, Local Updated At.


        The response is a file download (`Content-Type: text/csv`) with a filename
        of the form `qbo_tax-rates_export_2026-07-07_10-30-00.csv`. By default all
        records (active and archived) are included; use the query parameters to narrow
        the export.


        Returns a 500 error if no QuickBooks Online integration has been set up, and
        a 422 error if a date parameter is not in MM/DD/YYYY format.


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-qbo-tax-rates-export
  /api/qbo/tax-rates/statistics:
    get:
      tags:
      - QuickBooks Online
      summary: Get Tax Rate Statistics
      description: 'Get aggregate counts for the QuickBooks Online tax rates synced
        into SKU.io: the total number of records, how many are active, and how many
        are archived.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Counts are computed from the locally synced copies; no request is made to
        QuickBooks.


        Returns a 500 error if no QuickBooks Online integration has been set up.


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      total:
                        type: integer
                      active:
                        type: integer
                      archived:
                        type: integer
                example:
                  success: true
                  data:
                    total: 22
                    active: 20
                    archived: 2
        '500':
          description: Internal Server Error
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  error:
                    type: string
                  message:
                    type: string
                example:
                  success: false
                  error: Failed to get QBO tax-rates statistics
                  message: No QBO integration instance found. Please set up your QuickBooks
                    Online integration first.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-qbo-tax-rates-statistics
  /api/qbo/tax-rates/unarchive:
    post:
      tags:
      - QuickBooks Online
      summary: Unarchive Tax Rates
      description: 'Restore one or more archived QuickBooks Online tax rates by ID,
        marking them active again in SKU.io.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        This only restores the archived local synced copy in SKU.io; it does not modify
        anything in QuickBooks itself. Archiving and unarchiving control visibility
        within SKU.io only.


        Returns the number of records that were updated.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1
                - 2
                - 3
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      unarchived_count:
                        type: integer
                example:
                  success: true
                  message: Successfully unarchived 3 QBO tax-rates(s)
                  data:
                    unarchived_count: 3
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  error:
                    type: string
                  details:
                    type: object
                    properties:
                      ids:
                        type: array
                        items:
                          type: string
                example:
                  success: false
                  error: Validation failed
                  details:
                    ids:
                    - The ids field is required.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-qbo-tax-rates-unarchive
  /api/qbo/vendors:
    get:
      tags:
      - QuickBooks Online
      summary: List Vendors
      description: 'Paginated list of QBO vendors.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Searchable columns (filter[search]): id, qbo_id, name, display_name, company_name.'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        example: '1'
        description: Page number (default 1).
      - name: per_page
        in: query
        schema:
          type: integer
        example: '15'
        description: Results per page (default 10).
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-qbo-vendors
    delete:
      tags:
      - QuickBooks Online
      summary: Delete Vendors
      description: 'Delete one or more QBO vendors.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: delete-api-qbo-vendors
  /api/qbo/vendors/{id}:
    get:
      tags:
      - QuickBooks Online
      summary: Get Vendor
      description: 'Get a single QBO vendor by ID.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: id
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The record ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      qbo_id:
                        type: string
                      name:
                        type: string
                      display_name:
                        type: string
                      company_name:
                        type: string
                      active:
                        type: boolean
                      sync_status:
                        type: string
                      last_synced_at:
                        type: string
                      last_qbo_check_at:
                        type: string
                      sync_error_message:
                        type: string
                        nullable: true
                      qbo_created_at:
                        type: string
                      qbo_updated_at:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      integration_instance:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      qbo_link:
                        type: string
                example:
                  success: true
                  data:
                    id: 18
                    integration_instance_id: 3
                    qbo_id: '56'
                    name: Shanghai Supplier Co
                    display_name: Shanghai Supplier Co
                    company_name: Shanghai Supplier Co Ltd
                    active: true
                    sync_status: ok
                    last_synced_at: '2026-07-15T10:00:00.000000Z'
                    last_qbo_check_at: '2026-07-15T10:00:00.000000Z'
                    sync_error_message: null
                    qbo_created_at: '2026-07-01T09:00:00.000000Z'
                    qbo_updated_at: '2026-07-14T18:30:00.000000Z'
                    created_at: '2026-07-01T09:05:00.000000Z'
                    updated_at: '2026-07-14T18:35:00.000000Z'
                    integration_instance:
                      id: 3
                      name: QuickBooks Online
                    qbo_link: https://app.qbo.intuit.com/app/vendordetail?nameId=56
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-qbo-vendors-id
  /api/qbo/vendors/refresh:
    post:
      tags:
      - QuickBooks Online
      summary: Refresh Vendors
      description: 'Syncs vendors from QBO API.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                full_sync:
                  type: boolean
              example:
                full_sync: false
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-qbo-vendors-refresh
  /api/qbo/vendors/refresh-tracked:
    post:
      tags:
      - QuickBooks Online
      summary: Refresh Vendors in Background
      description: 'Starts a background refresh of vendors from QuickBooks and returns
        a job id you can poll for progress. Send no parameters for an incremental
        sync (records changed since the last sync), `full_sync: true` to re-pull everything,
        or `start_date` + `end_date` (MM/DD/YYYY) to pull records updated within a
        date range.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                full_sync:
                  type: boolean
              example:
                full_sync: false
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                      sync_type:
                        type: string
                      sync_description:
                        type: string
                example:
                  success: true
                  message: QBO vendors refresh started.
                  data:
                    tracked_job_log_id: 8123
                    sync_type: incremental
                    sync_description: Incremental sync (changes since last sync)
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-qbo-vendors-refresh-tracked
  /api/qbo/vendors/sync-info:
    get:
      tags:
      - QuickBooks Online
      summary: Get Vendors Sync Info
      description: Returns the latest synced vendor identifier and timestamp, the
        total number of vendors already stored, and the fields you can search QuickBooks
        by for this entity.
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      latest_identifier:
                        type: string
                      latest_date:
                        type: string
                      total_count:
                        type: integer
                      searchable_fields:
                        type: array
                        items:
                          type: object
                          properties:
                            value:
                              type: string
                            label:
                              type: string
                            qbo_field:
                              type: string
                            exact:
                              type: boolean
                example:
                  success: true
                  data:
                    latest_identifier: REF-1042
                    latest_date: '2026-07-16T18:22:05.000000Z'
                    total_count: 128
                    searchable_fields:
                    - value: doc_number
                      label: Doc Number
                      qbo_field: DocNumber
                      exact: false
                    - value: qbo_id
                      label: QuickBooks ID
                      qbo_field: Id
                      exact: true
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-qbo-vendors-sync-info
  /api/qbo/vendors/search-qbo:
    post:
      tags:
      - QuickBooks Online
      summary: Search Vendors in QuickBooks
      description: Searches QuickBooks directly for vendors matching a field/value
        (without importing them). `field` must be one of the values returned by Get
        Vendors Sync Info (e.g. `doc_number`, `qbo_id`). Each result flags whether
        it already exists in your database.
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                field:
                  type: string
                value:
                  type: string
              example:
                field: doc_number
                value: '1042'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        qbo_id:
                          type: string
                        label:
                          type: string
                        sub_label:
                          type: string
                        exists_in_database:
                          type: boolean
                example:
                  success: true
                  data:
                  - qbo_id: '1042'
                    label: INV-1042
                    sub_label: QuickBooks ID 1042
                    exists_in_database: true
                  - qbo_id: '1043'
                    label: INV-1043
                    sub_label: QuickBooks ID 1043
                    exists_in_database: false
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-qbo-vendors-search-qbo
  /api/qbo/vendors/refresh-single:
    post:
      tags:
      - QuickBooks Online
      summary: Pull Vendor from QuickBooks
      description: Fetches a single vendor from QuickBooks by its QuickBooks id and
        imports (or updates) it in your database.
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                qbo_id:
                  type: string
              example:
                qbo_id: '1043'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      success:
                        type: boolean
                      qbo_id:
                        type: string
                      id:
                        type: integer
                example:
                  success: true
                  message: QBO vendor pulled from QuickBooks.
                  data:
                    success: true
                    qbo_id: '1043'
                    id: 991
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-qbo-vendors-refresh-single
  /api/qbo/vendors/archive:
    post:
      tags:
      - QuickBooks Online
      summary: Archive Vendors
      description: 'Archive one or more QBO vendors.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-qbo-vendors-archive
  /api/qbo/vendors/export:
    get:
      tags:
      - QuickBooks Online
      summary: Export Vendors
      description: 'Download the QuickBooks Online vendors synced into SKU.io as a
        CSV file. The export is streamed from the locally synced copies; no request
        is made to QuickBooks.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        CSV columns: QBO ID, Name, Display Name, Company Name, Active, QBO Created
        At, QBO Updated At, Local Created At, Local Updated At.


        The response is a file download (`Content-Type: text/csv`) with a filename
        of the form `qbo_vendors_export_2026-07-07_10-30-00.csv`. By default all records
        (active and archived) are included; use the query parameters to narrow the
        export.


        Returns a 500 error if no QuickBooks Online integration has been set up, and
        a 422 error if a date parameter is not in MM/DD/YYYY format.


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-qbo-vendors-export
  /api/qbo/vendors/statistics:
    get:
      tags:
      - QuickBooks Online
      summary: Get Vendor Statistics
      description: 'Get aggregate counts for the QuickBooks Online vendors synced
        into SKU.io: the total number of records, how many are active, and how many
        are archived.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Counts are computed from the locally synced copies; no request is made to
        QuickBooks.


        Returns a 500 error if no QuickBooks Online integration has been set up.


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      total:
                        type: integer
                      active:
                        type: integer
                      archived:
                        type: integer
                example:
                  success: true
                  data:
                    total: 167
                    active: 158
                    archived: 9
        '500':
          description: Internal Server Error
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  error:
                    type: string
                  message:
                    type: string
                example:
                  success: false
                  error: Failed to get QBO vendors statistics
                  message: No QBO integration instance found. Please set up your QuickBooks
                    Online integration first.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-qbo-vendors-statistics
  /api/qbo/vendors/unarchive:
    post:
      tags:
      - QuickBooks Online
      summary: Unarchive Vendors
      description: 'Restore one or more archived QuickBooks Online vendors by ID,
        marking them active again in SKU.io.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        This only restores the archived local synced copy in SKU.io; it does not modify
        anything in QuickBooks itself. Archiving and unarchiving control visibility
        within SKU.io only.


        Returns the number of records that were updated.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1
                - 2
                - 3
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      unarchived_count:
                        type: integer
                example:
                  success: true
                  message: Successfully unarchived 3 QBO vendors(s)
                  data:
                    unarchived_count: 3
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  error:
                    type: string
                  details:
                    type: object
                    properties:
                      ids:
                        type: array
                        items:
                          type: string
                example:
                  success: false
                  error: Validation failed
                  details:
                    ids:
                    - The ids field is required.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-qbo-vendors-unarchive
  /api/qbo/vendors/{id}/activity-log:
    get:
      tags:
      - QuickBooks Online
      summary: Get Vendor Activity Log
      description: 'Retrieve the audit trail for a synced QuickBooks Online vendor.
        Each entry records a create, update, or delete event on the local copy of
        the record, including the changed attributes, their previous values, and the
        user or process that made the change.


        Results are ordered newest first and paginated (standard pagination metadata
        is included in the response).


        Returns 404 if the vendor does not exist.


        Authentication: Requires Bearer token.'
      parameters:
      - name: id
        in: path
        schema:
          type: string
        required: true
        description: The record ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        description:
                          type: string
                        event:
                          type: string
                        subject_type:
                          type: string
                        subject_id:
                          type: integer
                        batch_uuid:
                          type: string
                          nullable: true
                        properties:
                          type: object
                          properties:
                            attributes:
                              type: object
                              properties:
                                sync_status:
                                  type: string
                            old:
                              type: object
                              properties:
                                sync_status:
                                  type: string
                            source:
                              type: string
                        causer_name:
                          type: string
                        created_at:
                          type: string
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                    items:
                      type: object
                      properties:
                        url:
                          type: string
                          nullable: true
                        label:
                          type: string
                        active:
                          type: boolean
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 5821
                    description: updated
                    event: updated
                    subject_type: QboVendor
                    subject_id: 87
                    batch_uuid: null
                    properties:
                      attributes:
                        sync_status: synced
                      old:
                        sync_status: pending
                      source: qbo_sync
                    causer_name: Jane Smith
                    created_at: '2026-06-18T14:22:31.000000Z'
                  first_page_url: '{{protocol}}://{{domain}}/api/qbo/vendors/87/activity-log?page=1'
                  from: 1
                  last_page: 1
                  last_page_url: '{{protocol}}://{{domain}}/api/qbo/vendors/87/activity-log?page=1'
                  links:
                  - url: null
                    label: '&laquo; Previous'
                    active: false
                  - url: '{{protocol}}://{{domain}}/api/qbo/vendors/87/activity-log?page=1'
                    label: '1'
                    active: true
                  - url: null
                    label: Next &raquo;
                    active: false
                  next_page_url: null
                  path: '{{protocol}}://{{domain}}/api/qbo/vendors/87/activity-log'
                  per_page: 15
                  prev_page_url: null
                  to: 1
                  total: 1
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: object
                    properties:
                      id:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: array
                example:
                  errors:
                    id:
                    - message: Record not found.
                      code: NotFound
                      data: []
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-qbo-vendors-id-activity-log
  /api/qbo/conflicts/summary:
    get:
      tags:
      - QuickBooks Online
      summary: Get Conflict Summary
      description: 'Returns aggregate conflict statistics across all entity types.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  summary:
                    type: object
                    properties:
                      total_conflicts:
                        type: integer
                      by_type:
                        type: object
                        properties:
                          invoices:
                            type: integer
                          customers:
                            type: integer
                  integration_instance:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                example:
                  summary:
                    total_conflicts: 5
                    by_type:
                      invoices: 3
                      customers: 2
                  integration_instance:
                    id: 1
                    name: My Company
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-qbo-conflicts-summary
  /api/qbo/conflicts/detect:
    post:
      tags:
      - QuickBooks Online
      summary: Detect Conflicts
      description: 'Runs conflict detection across all entity types and returns newly
        found conflicts.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  conflicts_detected:
                    type: integer
                  conflicts_by_type:
                    type: object
                    properties:
                      invoices:
                        type: integer
                  message:
                    type: string
                example:
                  conflicts_detected: 3
                  conflicts_by_type:
                    invoices: 3
                  message: Conflict detection completed
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-qbo-conflicts-detect
  /api/qbo/conflicts/{entityType}:
    get:
      tags:
      - QuickBooks Online
      summary: List Conflicts by Entity Type
      description: 'Lists conflicted entities of a given type. Valid entity types:
        invoices, purchase-orders, accounts, customers, items, tax-codes, tax-rates.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        example: '1'
        description: Page number (default 1).
      - name: per_page
        in: query
        schema:
          type: integer
        example: '15'
        description: Results per page (default 10).
      - name: entityType
        in: path
        schema:
          type: string
        required: true
        description: 'One of: invoices, purchase-orders, accounts, customers, items,
          tax-codes, tax-rates'
        example: invoices
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-qbo-conflicts-entitytype
  /api/qbo/conflicts/{entityType}/{entityId}:
    get:
      tags:
      - QuickBooks Online
      summary: Get Conflict Details
      description: 'Get detailed conflict information for a specific entity including
        resolution options.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: entityType
        in: path
        schema:
          type: string
        required: true
        example: invoices
        description: The entity type ID.
      - name: entityId
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The entity ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-qbo-conflicts-entitytype-entityid
  /api/qbo/conflicts/{entityType}/{entityId}/resolve:
    post:
      tags:
      - QuickBooks Online
      summary: Resolve Conflict
      description: 'Resolves a conflict for a specific entity. Actions: delete_qbo,
        delete_sku, resync_to_qbo, break_link, mark_do_not_sync.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                action:
                  type: string
                reason:
                  type: string
                confirm_impacts:
                  type: boolean
              example:
                action: resync_to_qbo
                reason: Manual review confirmed SKU data is correct
                confirm_impacts: true
      parameters:
      - name: entityType
        in: path
        schema:
          type: string
        required: true
        example: invoices
        description: The entity type ID.
      - name: entityId
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The entity ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  entity_id:
                    type: integer
                  action_taken:
                    type: string
                  new_status:
                    type: string
                example:
                  message: Conflict resolved successfully
                  entity_id: 1
                  action_taken: resync_to_qbo
                  new_status: synced
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-qbo-conflicts-entitytype-entityid-resolve
  /api/qbo/conflicts/{entityType}/bulk-resolve:
    post:
      tags:
      - QuickBooks Online
      summary: Bulk Resolve Conflicts
      description: 'Bulk resolves up to 50 conflicts at once for entities of a given
        type.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                entity_ids:
                  type: array
                  items:
                    type: integer
                action:
                  type: string
                reason:
                  type: string
                confirm_impacts:
                  type: boolean
              example:
                entity_ids:
                - 1
                - 2
                - 3
                action: resync_to_qbo
                reason: Bulk resolution
                confirm_impacts: true
      parameters:
      - name: entityType
        in: path
        schema:
          type: string
        required: true
        example: invoices
        description: The entity type ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  results:
                    type: object
                    properties:
                      successful:
                        type: array
                        items:
                          type: object
                          properties:
                            entity_id:
                              type: integer
                            new_status:
                              type: string
                      failed:
                        type: array
                  message:
                    type: string
                example:
                  results:
                    successful:
                    - entity_id: 1
                      new_status: synced
                    failed: []
                  message: 'Bulk resolution completed: 1 successful, 0 failed'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-qbo-conflicts-entitytype-bulk-resolve
  /api/qbo/payment-type-mappings:
    get:
      tags:
      - QuickBooks Online
      summary: List Payment Type Mappings
      description: 'Lists all payment types with their mapped QBO bank accounts.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        payment_type_id:
                          type: integer
                        payment_type_name:
                          type: string
                        qbo_account:
                          type: string
                          nullable: true
                        is_mapped:
                          type: boolean
                  meta:
                    type: object
                    properties:
                      total_payment_types:
                        type: integer
                      mapped_count:
                        type: integer
                      unmapped_count:
                        type: integer
                example:
                  success: true
                  data:
                  - payment_type_id: 1
                    payment_type_name: Credit Card
                    qbo_account: null
                    is_mapped: false
                  meta:
                    total_payment_types: 5
                    mapped_count: 2
                    unmapped_count: 3
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-qbo-payment-type-mappings
  /api/qbo/payment-type-mappings/{paymentTypeId}:
    get:
      tags:
      - QuickBooks Online
      summary: Get Payment Type Mapping
      description: 'Get the QBO account mapping for a specific payment type.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: paymentTypeId
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The payment type ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-qbo-payment-type-mappings-paymenttypeid
    put:
      tags:
      - QuickBooks Online
      summary: Update Payment Type Mapping
      description: 'Maps a payment type to a QBO bank account. Pass null for qbo_account_id
        to clear the mapping.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                qbo_account_id:
                  type: integer
              example:
                qbo_account_id: 5
      parameters:
      - name: paymentTypeId
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The payment type ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-qbo-payment-type-mappings-paymenttypeid
  /api/qbo/payment-type-mappings/available-accounts:
    get:
      tags:
      - QuickBooks Online
      summary: Get Available Bank Accounts
      description: 'Returns all active QBO Bank accounts available for payment type
        mapping.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-qbo-payment-type-mappings-available-accounts
  /api/qbo/payment-type-mappings/bulk-update:
    post:
      tags:
      - QuickBooks Online
      summary: Bulk Update Payment Type Mappings
      description: 'Updates QBO bank account mappings for multiple payment types in
        one request.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                mappings:
                  type: array
                  items:
                    type: object
                    properties:
                      payment_type_id:
                        type: integer
                      qbo_account_id:
                        type: integer
              example:
                mappings:
                - payment_type_id: 1
                  qbo_account_id: 5
                - payment_type_id: 2
                  qbo_account_id: 6
                - payment_type_id: 3
                  qbo_account_id: null
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      results:
                        type: array
                        items:
                          type: object
                          properties:
                            payment_type_id:
                              type: integer
                            success:
                              type: boolean
                      summary:
                        type: object
                        properties:
                          total:
                            type: integer
                          successful:
                            type: integer
                          failed:
                            type: integer
                example:
                  success: true
                  message: Updated 3 mapping(s)
                  data:
                    results:
                    - payment_type_id: 1
                      success: true
                    summary:
                      total: 3
                      successful: 3
                      failed: 0
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-qbo-payment-type-mappings-bulk-update
  /api/qbo/custom-field-mappings:
    get:
      tags:
      - QuickBooks Online
      summary: Get Custom Field Mappings
      description: 'Returns the saved QBO invoice custom field mappings (`sales_rep`,
        `po_number`) and the list of available QBO custom fields fetched from the
        company''s preferences.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Requires a Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      custom_field_mappings:
                        type: object
                        properties:
                          sales_rep:
                            type: object
                            properties:
                              enabled:
                                type: boolean
                              definition_id:
                                type: string
                          po_number:
                            type: object
                            properties:
                              enabled:
                                type: boolean
                              definition_id:
                                type: string
                      qbo_custom_fields:
                        type: array
                        items:
                          type: object
                          properties:
                            definition_id:
                              type: string
                            name:
                              type: string
                            enabled:
                              type: boolean
                example:
                  success: true
                  data:
                    custom_field_mappings:
                      sales_rep:
                        enabled: true
                        definition_id: '1'
                      po_number:
                        enabled: true
                        definition_id: '3'
                    qbo_custom_fields:
                    - definition_id: '1'
                      name: Sales Rep
                      enabled: true
                    - definition_id: '2'
                      name: UPS/FedEx Tracking
                      enabled: true
                    - definition_id: '3'
                      name: PO Number
                      enabled: true
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-qbo-custom-field-mappings
    put:
      tags:
      - QuickBooks Online
      summary: Update Custom Field Mappings
      description: 'Updates the QBO invoice custom field mapping config. `sales_rep`
        (required) maps the Sales Order''s sales rep, and `po_number` (optional) maps
        the Sales Order''s customer PO number — each to a QBO legacy custom field
        on invoices. For each mapping, `definition_id` must be "1", "2", or "3" (QBO
        supports three legacy custom fields) and may be null when `enabled` is false.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Requires a Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                custom_field_mappings:
                  type: object
                  properties:
                    sales_rep:
                      type: object
                      properties:
                        enabled:
                          type: boolean
                        definition_id:
                          type: string
                    po_number:
                      type: object
                      properties:
                        enabled:
                          type: boolean
                        definition_id:
                          type: string
              example:
                custom_field_mappings:
                  sales_rep:
                    enabled: true
                    definition_id: '1'
                  po_number:
                    enabled: true
                    definition_id: '3'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      custom_field_mappings:
                        type: object
                        properties:
                          sales_rep:
                            type: object
                            properties:
                              enabled:
                                type: boolean
                              definition_id:
                                type: string
                          po_number:
                            type: object
                            properties:
                              enabled:
                                type: boolean
                              definition_id:
                                type: string
                example:
                  success: true
                  message: Custom field mappings updated successfully.
                  data:
                    custom_field_mappings:
                      sales_rep:
                        enabled: true
                        definition_id: '1'
                      po_number:
                        enabled: true
                        definition_id: '3'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      custom_field_mappings.po_number.definition_id:
                        type: array
                        items:
                          type: string
                example:
                  message: The custom field mappings.po number.definition id field
                    must be 1, 2, or 3.
                  errors:
                    custom_field_mappings.po_number.definition_id:
                    - The custom field mappings.po number.definition id field must
                      be 1, 2, or 3.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: put-api-qbo-custom-field-mappings
  /api/qbo/custom-field-mappings/fetch-fields:
    post:
      tags:
      - QuickBooks Online
      summary: Fetch Custom Fields from QBO
      description: 'Fetches available custom fields from QBO Preferences API and stores
        them locally.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      qbo_custom_fields:
                        type: array
                        items:
                          type: object
                          properties:
                            definition_id:
                              type: string
                            name:
                              type: string
                            enabled:
                              type: boolean
                example:
                  success: true
                  message: Custom fields fetched successfully from QuickBooks.
                  data:
                    qbo_custom_fields:
                    - definition_id: '1'
                      name: Sales Rep
                      enabled: true
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-qbo-custom-field-mappings-fetch-fields
  /api/qbo/tax-code-mappings:
    get:
      tags:
      - QuickBooks Online
      summary: List Tax Code Mappings
      description: 'Lists all SKU tax rates with their mapped QBO tax codes.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        tax_rate_id:
                          type: integer
                        tax_rate_name:
                          type: string
                        tax_rate_value:
                          type: string
                        qbo_tax_code:
                          type: string
                          nullable: true
                        is_mapped:
                          type: boolean
                  meta:
                    type: object
                    properties:
                      total_tax_rates:
                        type: integer
                      mapped_count:
                        type: integer
                      unmapped_count:
                        type: integer
                example:
                  success: true
                  data:
                  - tax_rate_id: 1
                    tax_rate_name: CA Tax
                    tax_rate_value: '0.08'
                    qbo_tax_code: null
                    is_mapped: false
                  meta:
                    total_tax_rates: 3
                    mapped_count: 1
                    unmapped_count: 2
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-qbo-tax-code-mappings
  /api/qbo/tax-code-mappings/{taxRateId}:
    get:
      tags:
      - QuickBooks Online
      summary: Get Tax Code Mapping
      description: 'Get the QBO tax code mapping for a specific SKU tax rate.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: taxRateId
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The tax rate ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-qbo-tax-code-mappings-taxrateid
    put:
      tags:
      - QuickBooks Online
      summary: Update Tax Code Mapping
      description: 'Maps a SKU tax rate to a QBO tax code. Pass null for qbo_tax_code_id
        to clear the mapping.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                qbo_tax_code_id:
                  type: integer
              example:
                qbo_tax_code_id: 3
      parameters:
      - name: taxRateId
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The tax rate ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-qbo-tax-code-mappings-taxrateid
  /api/qbo/tax-code-mappings/available-tax-codes:
    get:
      tags:
      - QuickBooks Online
      summary: Get Available Tax Codes
      description: 'Returns all active QBO tax codes available for mapping.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-qbo-tax-code-mappings-available-tax-codes
  /api/qbo/tax-code-mappings/bulk-update:
    post:
      tags:
      - QuickBooks Online
      summary: Bulk Update Tax Code Mappings
      description: 'Updates QBO tax code mappings for multiple SKU tax rates in one
        request.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                mappings:
                  type: array
                  items:
                    type: object
                    properties:
                      tax_rate_id:
                        type: integer
                      qbo_tax_code_id:
                        type: integer
              example:
                mappings:
                - tax_rate_id: 1
                  qbo_tax_code_id: 3
                - tax_rate_id: 2
                  qbo_tax_code_id: null
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      results:
                        type: array
                        items:
                          type: object
                          properties:
                            tax_rate_id:
                              type: integer
                            success:
                              type: boolean
                      summary:
                        type: object
                        properties:
                          total:
                            type: integer
                          successful:
                            type: integer
                          failed:
                            type: integer
                example:
                  success: true
                  message: Updated 2 mapping(s)
                  data:
                    results:
                    - tax_rate_id: 1
                      success: true
                    summary:
                      total: 2
                      successful: 2
                      failed: 0
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-qbo-tax-code-mappings-bulk-update
  /api/qbo/customers/match-runs/{matchRun}:
    delete:
      tags:
      - QuickBooks Online
      summary: Cancel Customer Match Run
      description: 'Cancel a customer match run. All of the run''s still-pending proposals
        are deleted and the run status is set to `cancelled`. If the scoring job is
        still running in the background, it stops at its next checkpoint.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        This only affects SKU.io''s local match-run data; it does not modify anything
        in QuickBooks itself. Links already committed from this run are kept - cancelling
        does not undo them.


        Returns 404 if the run does not exist.


        Authentication: Requires Bearer token.'
      parameters:
      - name: matchRun
        in: path
        schema:
          type: string
        required: true
        description: The match run ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Run cancelled.
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: object
                    properties:
                      id:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: array
                example:
                  errors:
                    id:
                    - message: Record not found.
                      code: NotFound
                      data: []
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: delete-api-qbo-customers-match-runs-matchrun
    get:
      tags:
      - QuickBooks Online
      summary: Get Customer Match Run
      description: 'Get the current state of a customer match run, including its status,
        the matching configuration snapshot the run was scored with, how many QuickBooks
        customers were evaluated, proposal counts per confidence bucket, proposal
        counts per decision status, and the background job log ID for progress tracking.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Run statuses: `running`, `awaiting_review`, `committing`, `completed`, `cancelled`,
        `failed`.


        `pending_bucket_counts` reflects the actionable review queue (pending and
        approved proposals per bucket); `status_counts` shows all proposals in the
        run by decision status.


        Returns 404 if the run does not exist.


        Authentication: Requires Bearer token.'
      parameters:
      - name: matchRun
        in: path
        schema:
          type: string
        required: true
        description: The match run ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      user_id:
                        type: integer
                      status:
                        type: string
                      config_snapshot:
                        type: object
                        properties:
                          weights:
                            type: object
                            properties:
                              email:
                                type: integer
                              company:
                                type: integer
                              name:
                                type: integer
                              address:
                                type: integer
                              phone:
                                type: integer
                          thresholds:
                            type: object
                            properties:
                              auto:
                                type: integer
                              review:
                                type: integer
                          generic_email_handling:
                            type: string
                          generic_local_parts:
                            type: array
                            items:
                              type: string
                          fuzzy_company:
                            type: boolean
                          fuzzy_name:
                            type: boolean
                          auto_commit_auto_suggested:
                            type: boolean
                      qbo_customers_evaluated:
                        type: integer
                      proposals_auto:
                        type: integer
                      proposals_review:
                        type: integer
                      proposals_hidden:
                        type: integer
                      committed_count:
                        type: integer
                      status_counts:
                        type: object
                        properties:
                          pending:
                            type: integer
                          approved:
                            type: integer
                          rejected:
                            type: integer
                          committed:
                            type: integer
                          superseded:
                            type: integer
                      pending_bucket_counts:
                        type: object
                        properties:
                          auto:
                            type: integer
                          review:
                            type: integer
                          hidden:
                            type: integer
                      tracked_job_log_id:
                        type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 12
                    integration_instance_id: 3
                    user_id: 7
                    status: awaiting_review
                    config_snapshot:
                      weights:
                        email: 50
                        company: 30
                        name: 15
                        address: 3
                        phone: 2
                      thresholds:
                        auto: 90
                        review: 60
                      generic_email_handling: demote
                      generic_local_parts:
                      - info
                      - sales
                      - accounts
                      - accounting
                      - orders
                      - billing
                      - admin
                      - contact
                      - hello
                      - office
                      - support
                      - payments
                      fuzzy_company: true
                      fuzzy_name: true
                      auto_commit_auto_suggested: false
                    qbo_customers_evaluated: 480
                    proposals_auto: 55
                    proposals_review: 120
                    proposals_hidden: 210
                    committed_count: 0
                    status_counts:
                      pending: 385
                      approved: 0
                      rejected: 0
                      committed: 0
                      superseded: 0
                    pending_bucket_counts:
                      auto: 55
                      review: 120
                      hidden: 210
                    tracked_job_log_id: 3411
                    created_at: '2026-07-01T09:15:00.000000Z'
                    updated_at: '2026-07-01T09:18:42.000000Z'
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: object
                    properties:
                      id:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: array
                example:
                  errors:
                    id:
                    - message: Record not found.
                      code: NotFound
                      data: []
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-qbo-customers-match-runs-matchrun
  /api/qbo/customers/match-runs/{matchRun}/proposals:
    get:
      tags:
      - QuickBooks Online
      summary: List Match Run Proposals
      description: 'List the scored match proposals produced by a customer match run,
        ordered by score (highest first) and paginated (standard pagination metadata
        is included in the response). Each proposal pairs one QuickBooks Online customer
        with one SKU.io customer and includes the overall score (0-100), the confidence
        bucket, and a per-field breakdown of the signals (email, company, name, address,
        phone) that produced the score.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Buckets: `auto` (score at or above the auto threshold), `review` (between
        the review and auto thresholds), `hidden` (below the review threshold).


        Proposal statuses: `pending`, `approved`, `rejected`, `committed`, `superseded`.
        `rejection_reason` is set when a proposal was auto-rejected because one side
        was already linked (`qbo_customer_already_linked` or `sku_customer_already_linked`).


        Returns 404 if the run does not exist.


        Authentication: Requires Bearer token.'
      parameters:
      - name: matchRun
        in: path
        schema:
          type: string
        required: true
        description: The match run ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        qbo_customer_id:
                          type: integer
                        sku_customer_id:
                          type: integer
                        run_id:
                          type: integer
                        score:
                          type: integer
                        bucket:
                          type: string
                        signals:
                          type: array
                          items:
                            type: object
                            properties:
                              field:
                                type: string
                              score:
                                type: integer
                              weight:
                                type: integer
                              contribution:
                                type: integer
                              note:
                                type: string
                        status:
                          type: string
                        rejection_reason:
                          type: string
                          nullable: true
                        decided_at:
                          type: string
                          nullable: true
                        qbo_customer:
                          type: object
                          properties:
                            id:
                              type: integer
                            qbo_id:
                              type: string
                            display_name:
                              type: string
                            company_name:
                              type: string
                            given_name:
                              type: string
                            family_name:
                              type: string
                            email:
                              type: string
                            ship_addr:
                              type: object
                              properties:
                                Line1:
                                  type: string
                                City:
                                  type: string
                                PostalCode:
                                  type: string
                            bill_addr:
                              type: object
                              properties:
                                Line1:
                                  type: string
                                City:
                                  type: string
                                PostalCode:
                                  type: string
                        sku_customer:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            company:
                              type: string
                            email:
                              type: string
                            address1:
                              type: string
                            zip:
                              type: string
                            phone:
                              type: string
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                    items:
                      type: object
                      properties:
                        url:
                          type: string
                          nullable: true
                        label:
                          type: string
                        active:
                          type: boolean
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 9101
                    integration_instance_id: 3
                    qbo_customer_id: 512
                    sku_customer_id: 2048
                    run_id: 12
                    score: 96
                    bucket: auto
                    signals:
                    - field: email
                      score: 1
                      weight: 50
                      contribution: 50
                      note: exact
                    - field: company
                      score: 1
                      weight: 30
                      contribution: 30
                      note: exact
                    - field: name
                      score: 0.8
                      weight: 15
                      contribution: 12
                      note: fuzzy
                    - field: address
                      score: 1
                      weight: 3
                      contribution: 3
                      note: null
                    - field: phone
                      score: 0.5
                      weight: 2
                      contribution: 1
                      note: null
                    status: pending
                    rejection_reason: null
                    decided_at: null
                    qbo_customer:
                      id: 512
                      qbo_id: '158'
                      display_name: Acme Supplies
                      company_name: Acme Supplies LLC
                      given_name: John
                      family_name: Doe
                      email: orders@acmesupplies.com
                      ship_addr:
                        Line1: 12 Main St
                        City: Austin
                        PostalCode: '78701'
                      bill_addr:
                        Line1: 12 Main St
                        City: Austin
                        PostalCode: '78701'
                    sku_customer:
                      id: 2048
                      name: John Doe
                      company: Acme Supplies
                      email: orders@acmesupplies.com
                      address1: 12 Main St
                      zip: '78701'
                      phone: +1 512 555 0193
                  first_page_url: '{{protocol}}://{{domain}}/api/qbo/customers/match-runs/12/proposals?page=1'
                  from: 1
                  last_page: 1
                  last_page_url: '{{protocol}}://{{domain}}/api/qbo/customers/match-runs/12/proposals?page=1'
                  links:
                  - url: null
                    label: '&laquo; Previous'
                    active: false
                  - url: '{{protocol}}://{{domain}}/api/qbo/customers/match-runs/12/proposals?page=1'
                    label: '1'
                    active: true
                  - url: null
                    label: Next &raquo;
                    active: false
                  next_page_url: null
                  path: '{{protocol}}://{{domain}}/api/qbo/customers/match-runs/12/proposals'
                  per_page: 25
                  prev_page_url: null
                  to: 1
                  total: 385
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: object
                    properties:
                      id:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: array
                example:
                  errors:
                    id:
                    - message: Record not found.
                      code: NotFound
                      data: []
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-qbo-customers-match-runs-matchrun-proposals
  /api/qbo/integration-instances/{integrationInstance}/matching-config:
    get:
      tags:
      - QuickBooks Online
      summary: Get Customer Matching Configuration
      description: 'Get the customer matching configuration for a QuickBooks Online
        integration instance. If no configuration has been saved yet, the defaults
        are returned.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Fields:

        - `weights` - relative importance (0-100) of each signal: email, company,
        name, address, phone.

        - `thresholds` - score cutoffs (0-100): proposals scoring at or above `auto`
        are auto-suggested; at or above `review` they land in the review queue; below
        `review` they are hidden.

        - `generic_email_handling` - how shared mailbox addresses (info@, sales@,
        ...) are scored: `demote` (half credit), `ignore` (no credit), or `accept`
        (full credit).

        - `generic_local_parts` - the list of email local parts treated as generic.

        - `fuzzy_company` / `fuzzy_name` - whether near-matches count for the company
        and name signals.

        - `auto_commit_auto_suggested` - whether proposals in the auto bucket should
        be committed without manual review.


        Returns 404 if the integration instance does not exist.


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      weights:
                        type: object
                        properties:
                          email:
                            type: integer
                          company:
                            type: integer
                          name:
                            type: integer
                          address:
                            type: integer
                          phone:
                            type: integer
                      thresholds:
                        type: object
                        properties:
                          auto:
                            type: integer
                          review:
                            type: integer
                      generic_email_handling:
                        type: string
                      generic_local_parts:
                        type: array
                        items:
                          type: string
                      fuzzy_company:
                        type: boolean
                      fuzzy_name:
                        type: boolean
                      auto_commit_auto_suggested:
                        type: boolean
                example:
                  data:
                    weights:
                      email: 50
                      company: 30
                      name: 15
                      address: 3
                      phone: 2
                    thresholds:
                      auto: 90
                      review: 60
                    generic_email_handling: demote
                    generic_local_parts:
                    - info
                    - sales
                    - accounts
                    - accounting
                    - orders
                    - billing
                    - admin
                    - contact
                    - hello
                    - office
                    - support
                    - payments
                    fuzzy_company: true
                    fuzzy_name: true
                    auto_commit_auto_suggested: false
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: object
                    properties:
                      id:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: array
                example:
                  errors:
                    id:
                    - message: Record not found.
                      code: NotFound
                      data: []
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-qbo-integration-instances-integrationinstance-matching-config
    put:
      tags:
      - QuickBooks Online
      summary: Update Customer Matching Configuration
      description: 'Save the customer matching configuration for a QuickBooks Online
        integration instance. The full configuration must be sent - all fields except
        `generic_local_parts` are required.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Validation rules beyond per-field types:

        - The five weights must sum to more than 0.

        - `thresholds.review` must be less than or equal to `thresholds.auto`.

        - `generic_email_handling` must be one of `demote`, `ignore`, `accept`.


        The saved configuration is used by subsequent match runs and previews (each
        run also stores a snapshot of the configuration it was scored with). Saving
        the configuration does not modify anything in QuickBooks.


        Returns the normalized configuration that was saved. Returns 404 if the integration
        instance does not exist.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                weights:
                  type: object
                  properties:
                    email:
                      type: integer
                    company:
                      type: integer
                    name:
                      type: integer
                    address:
                      type: integer
                    phone:
                      type: integer
                thresholds:
                  type: object
                  properties:
                    auto:
                      type: integer
                    review:
                      type: integer
                generic_email_handling:
                  type: string
                generic_local_parts:
                  type: array
                  items:
                    type: string
                fuzzy_company:
                  type: boolean
                fuzzy_name:
                  type: boolean
                auto_commit_auto_suggested:
                  type: boolean
              example:
                weights:
                  email: 50
                  company: 30
                  name: 15
                  address: 3
                  phone: 2
                thresholds:
                  auto: 90
                  review: 60
                generic_email_handling: demote
                generic_local_parts:
                - info
                - sales
                - accounts
                - billing
                - support
                fuzzy_company: true
                fuzzy_name: true
                auto_commit_auto_suggested: false
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      weights:
                        type: object
                        properties:
                          email:
                            type: integer
                          company:
                            type: integer
                          name:
                            type: integer
                          address:
                            type: integer
                          phone:
                            type: integer
                      thresholds:
                        type: object
                        properties:
                          auto:
                            type: integer
                          review:
                            type: integer
                      generic_email_handling:
                        type: string
                      generic_local_parts:
                        type: array
                        items:
                          type: string
                      fuzzy_company:
                        type: boolean
                      fuzzy_name:
                        type: boolean
                      auto_commit_auto_suggested:
                        type: boolean
                  message:
                    type: string
                example:
                  data:
                    weights:
                      email: 50
                      company: 30
                      name: 15
                      address: 3
                      phone: 2
                    thresholds:
                      auto: 90
                      review: 60
                    generic_email_handling: demote
                    generic_local_parts:
                    - info
                    - sales
                    - accounts
                    - billing
                    - support
                    fuzzy_company: true
                    fuzzy_name: true
                    auto_commit_auto_suggested: false
                  message: Matching configuration saved.
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: object
                    properties:
                      id:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: array
                example:
                  errors:
                    id:
                    - message: Record not found.
                      code: NotFound
                      data: []
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      thresholds.review:
                        type: array
                        items:
                          type: string
                example:
                  message: Review threshold must be ≤ auto threshold.
                  errors:
                    thresholds.review:
                    - Review threshold must be ≤ auto threshold.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: put-api-qbo-integration-instances-integrationinstance-matching-config
  /api/qbo/customers/match-runs:
    post:
      tags:
      - QuickBooks Online
      summary: Start Customer Match Run
      description: 'Start a new customer match run. The run scores every active, unlinked
        QuickBooks Online customer (or only the customers listed in `qbo_customer_ids`)
        against the SKU.io customer pool using the current matching configuration,
        and stores up to five scored proposals per QuickBooks customer.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        This endpoint queues a background job to do the scoring and returns immediately.
        The response contains the new run ID and a background job log ID that can
        be used to track progress. Poll `GET /api/qbo/customers/match-runs/{id}` until
        the run status changes from `running` to `awaiting_review` before fetching
        proposals.


        Scoring reads only locally synced data and creates proposal records in SKU.io;
        it does not modify anything in QuickBooks. Any pending proposals from earlier
        runs for the same QuickBooks customers are marked `superseded`.


        Run statuses: `running`, `awaiting_review`, `committing`, `completed`, `cancelled`,
        `failed`.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                integration_instance_id:
                  type: integer
                qbo_customer_ids:
                  type: array
                  items:
                    type: integer
              example:
                integration_instance_id: 3
                qbo_customer_ids:
                - 512
                - 513
                - 514
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      run_id:
                        type: integer
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    run_id: 12
                    tracked_job_log_id: 3411
                  message: Match run started.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      integration_instance_id:
                        type: array
                        items:
                          type: string
                example:
                  message: The integration instance id field is required.
                  errors:
                    integration_instance_id:
                    - The integration instance id field is required.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-qbo-customers-match-runs
  /api/qbo/customers/match-runs/{matchRun}/approve-all:
    post:
      tags:
      - QuickBooks Online
      summary: Approve All Match Proposals
      description: 'Approve every pending proposal in a match run, optionally narrowed
        to one confidence bucket and/or a search term. This is a bulk shortcut with
        the same behavior as submitting decisions: each approved proposal is linked
        immediately (the SKU.io customer ID is written onto the locally synced QuickBooks
        customer record and the proposal moves to `committed`).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Body fields (both optional): `bucket` limits the approval to one confidence
        bucket (`auto`, `review`, or `hidden`); `search` limits it to proposals whose
        QuickBooks or SKU.io customer matches the term (name, company, or email, max
        255 characters). Omit both to approve every pending proposal in the run.


        Linking modifies only the local synced copy in SKU.io; it does not modify
        anything in QuickBooks itself.


        Proposals whose QuickBooks customer or SKU.io customer is already linked elsewhere
        are skipped and marked rejected with a `rejection_reason`. The response reports
        how many proposals were committed, rejected, and skipped.


        Returns 404 if the run does not exist.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                bucket:
                  type: string
                search:
                  type: string
              example:
                bucket: auto
                search: acme
      parameters:
      - name: matchRun
        in: path
        schema:
          type: string
        required: true
        description: The match run ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      committed:
                        type: integer
                      rejected:
                        type: integer
                      skipped:
                        type: integer
                      errors:
                        type: array
                  message:
                    type: string
                example:
                  data:
                    committed: 54
                    rejected: 0
                    skipped: 1
                    errors: []
                  message: Approved 54 match(es).
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: object
                    properties:
                      id:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: array
                example:
                  errors:
                    id:
                    - message: Record not found.
                      code: NotFound
                      data: []
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      bucket:
                        type: array
                        items:
                          type: string
                example:
                  message: The selected bucket is invalid.
                  errors:
                    bucket:
                    - The selected bucket is invalid.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-qbo-customers-match-runs-matchrun-approve-all
  /api/qbo/customers/match-runs/{matchRun}/commit:
    post:
      tags:
      - QuickBooks Online
      summary: Commit Approved Match Proposals
      description: 'Apply every proposal in the run that is still in `approved` status:
        each one writes the SKU.io customer ID onto the locally synced QuickBooks
        customer record and moves the proposal to `committed`. The run transitions
        through `committing` and finishes as `completed`.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        This commits only the local synced copies in SKU.io; it does not modify anything
        in QuickBooks itself.


        Note that the decisions and approve-all endpoints already link approved proposals
        immediately, so this endpoint typically finds nothing left to commit unless
        proposals were approved through another flow. Proposals whose QuickBooks customer
        or SKU.io customer is already linked elsewhere are marked rejected with a
        `rejection_reason` instead of being committed; per-proposal failures are reported
        in `errors`.


        Returns 404 if the run does not exist.


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: matchRun
        in: path
        schema:
          type: string
        required: true
        description: The match run ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      committed:
                        type: integer
                      errors:
                        type: array
                  message:
                    type: string
                example:
                  data:
                    committed: 5
                    errors: []
                  message: Committed 5 match(es).
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: object
                    properties:
                      id:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: array
                example:
                  errors:
                    id:
                    - message: Record not found.
                      code: NotFound
                      data: []
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-qbo-customers-match-runs-matchrun-commit
  /api/qbo/customers/match-runs/{matchRun}/decisions:
    post:
      tags:
      - QuickBooks Online
      summary: Submit Match Proposal Decisions
      description: 'Approve and/or reject match proposals in bulk. Pass proposal IDs
        in `approve` and/or `reject`; IDs that do not belong to this run are silently
        ignored.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Approving a proposal applies the link immediately: the SKU.io customer ID
        is written onto the locally synced QuickBooks customer record and the proposal
        moves to `committed` status. Rejecting simply marks the proposal `rejected`.


        Linking modifies only the local synced copy in SKU.io; it does not modify
        anything in QuickBooks itself.


        A proposal is skipped (counted in `skipped` and marked rejected with a `rejection_reason`)
        when the QuickBooks customer is already linked to a SKU.io customer, or when
        the SKU.io customer is already linked to a different QuickBooks customer.
        Per-proposal failures are reported in `errors` without failing the whole request.


        Returns 404 if the run does not exist.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                approve:
                  type: array
                  items:
                    type: integer
                reject:
                  type: array
                  items:
                    type: integer
              example:
                approve:
                - 9101
                - 9102
                reject:
                - 9103
      parameters:
      - name: matchRun
        in: path
        schema:
          type: string
        required: true
        description: The match run ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      committed:
                        type: integer
                      rejected:
                        type: integer
                      skipped:
                        type: integer
                      errors:
                        type: array
                  message:
                    type: string
                example:
                  data:
                    committed: 2
                    rejected: 1
                    skipped: 0
                    errors: []
                  message: Decisions saved.
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: object
                    properties:
                      id:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: array
                example:
                  errors:
                    id:
                    - message: Record not found.
                      code: NotFound
                      data: []
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      approve.0:
                        type: array
                        items:
                          type: string
                example:
                  message: The approve.0 field must be an integer.
                  errors:
                    approve.0:
                    - The approve.0 field must be an integer.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-qbo-customers-match-runs-matchrun-decisions
  /api/qbo/integration-instances/{integrationInstance}/matching-config/dry-run:
    post:
      tags:
      - QuickBooks Online
      summary: Preview Customer Matching Results
      description: 'Preview how the currently saved matching configuration would classify
        a sample of unlinked QuickBooks Online customers, without creating a match
        run or persisting any proposals. Up to `sample_size` active, unlinked QuickBooks
        customers are scored against the SKU.io customer pool and the response reports
        how many would land in each bucket.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Buckets: `auto` (score at or above the auto threshold), `review` (between
        the review and auto thresholds), `hidden` (below the review threshold), plus
        `unmatched` for customers with no scoring candidate at all.


        This is a read-only preview computed synchronously from locally synced data
        - nothing is written in SKU.io and nothing is modified in QuickBooks. Save
        configuration changes first: the preview always uses the saved configuration,
        not values sent in this request.


        Returns 404 if the integration instance does not exist.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                sample_size:
                  type: integer
              example:
                sample_size: 100
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      sample_size:
                        type: integer
                      auto:
                        type: integer
                      review:
                        type: integer
                      hidden:
                        type: integer
                      unmatched:
                        type: integer
                example:
                  data:
                    sample_size: 100
                    auto: 12
                    review: 30
                    hidden: 40
                    unmatched: 18
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: object
                    properties:
                      id:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: array
                example:
                  errors:
                    id:
                    - message: Record not found.
                      code: NotFound
                      data: []
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      sample_size:
                        type: array
                        items:
                          type: string
                example:
                  message: The sample size field must not be greater than 500.
                  errors:
                    sample_size:
                    - The sample size field must not be greater than 500.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-qbo-integration-instances-integrationinstance-matching-config-dry-run
  /api/qbo/vendor-credits:
    get:
      tags:
      - QuickBooks Online
      summary: List Vendor Credits
      description: 'List mirrored QuickBooks vendor credits, paginated.


        Allowed sorts: id, doc_number, vendor_name, txn_date, total_amount, status,
        sync_status, last_synced_at, qbo_created_at, qbo_updated_at, created_at, updated_at.
        Prefix with - for descending. Default sort: -created_at.


        Searchable columns (filter[search]): id, qbo_id, doc_number, vendor_name.


        These documents are written to QuickBooks by SKU''s ledger sync (or mirrored
        from QuickBooks), so the API surface is read-only — list and get only.


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        qbo_id:
                          type: string
                        doc_number:
                          type: string
                        vendor_id:
                          type: string
                        vendor_name:
                          type: string
                        total_amount:
                          type: string
                        currency:
                          type: string
                        txn_date:
                          type: string
                        status:
                          type: string
                        active:
                          type: boolean
                        sync_status:
                          type: string
                        last_synced_at:
                          type: string
                        last_qbo_check_at:
                          type: string
                        sync_error_message:
                          type: string
                          nullable: true
                        qbo_created_at:
                          type: string
                        qbo_updated_at:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                        integration_instance:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        qbo_link:
                          type: string
                  meta:
                    type: object
                    properties:
                      total:
                        type: integer
                      per_page:
                        type: integer
                      current_page:
                        type: integer
                      last_page:
                        type: integer
                      from:
                        type: integer
                      to:
                        type: integer
                  links:
                    type: object
                    properties:
                      first:
                        type: string
                      last:
                        type: string
                      prev:
                        type: string
                        nullable: true
                      next:
                        type: string
                        nullable: true
                example:
                  success: true
                  data:
                  - id: 12
                    integration_instance_id: 3
                    qbo_id: '184'
                    doc_number: VC-1042
                    vendor_id: '56'
                    vendor_name: Shanghai Supplier Co
                    total_amount: '1250.00'
                    currency: USD
                    txn_date: '2026-07-01'
                    status: Open
                    active: true
                    sync_status: ok
                    last_synced_at: '2026-07-15T10:00:00.000000Z'
                    last_qbo_check_at: '2026-07-15T10:00:00.000000Z'
                    sync_error_message: null
                    qbo_created_at: '2026-07-01T09:00:00.000000Z'
                    qbo_updated_at: '2026-07-14T18:30:00.000000Z'
                    created_at: '2026-07-01T09:05:00.000000Z'
                    updated_at: '2026-07-14T18:35:00.000000Z'
                    integration_instance:
                      id: 3
                      name: QuickBooks Online
                    qbo_link: https://app.qbo.intuit.com/app/vendorcredit?txnId=184
                  meta:
                    total: 1
                    per_page: 15
                    current_page: 1
                    last_page: 1
                    from: 1
                    to: 1
                  links:
                    first: …?page=1
                    last: …?page=1
                    prev: null
                    next: null
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-qbo-vendor-credits
  /api/qbo/vendor-credits/{id}:
    get:
      tags:
      - QuickBooks Online
      summary: Get Vendor Credit
      description: 'Get one mirrored QuickBooks vendor credit.


        The `linked_ledger_entry` field identifies the SKU ledger entry this QuickBooks
        document was created from (id, document number, and an app route). It is `null`
        when the document originated in QuickBooks rather than being pushed by SKU.
        This field is only present on the detail response, not on list rows.


        `qbo_link` deep-links to the vendor credit in the QuickBooks web UI.


        This document is pushed to QuickBooks by SKU''s ledger, so the response includes
        reverse cross-link fields: `ledger_entry_id` and `ledger_entry_reference`
        identify the SKU ledger entry that pushed it, while `sku_link_type`, `sku_link_id`,
        `sku_link_label`, and `sku_link_route` point back to the originating SKU document.
        These are `null` when the document originated in QuickBooks rather than being
        pushed by SKU. `vendor_link_id` cross-links to the mirrored QuickBooks vendor.


        Authentication: Requires Bearer token. Returns `line_items` (normalized line
        rows parsed from the stored QuickBooks payload) and `detail_payload` (the
        full raw QuickBooks payload); both are null until the document is re-synced
        from QuickBooks.


        Also returns an `amounts` summary (`subtotal`, `tax`, `total`, `balance`,
        `paid`) and a `tax_code` on each `line_items` row.'
      parameters:
      - name: id
        in: path
        schema:
          type: string
        required: true
        description: The record ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      qbo_id:
                        type: string
                      doc_number:
                        type: string
                      vendor_id:
                        type: string
                      vendor_name:
                        type: string
                      total_amount:
                        type: string
                      currency:
                        type: string
                      txn_date:
                        type: string
                      status:
                        type: string
                      active:
                        type: boolean
                      sync_status:
                        type: string
                      last_synced_at:
                        type: string
                      last_qbo_check_at:
                        type: string
                      sync_error_message:
                        type: string
                        nullable: true
                      qbo_created_at:
                        type: string
                      qbo_updated_at:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      integration_instance:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      qbo_link:
                        type: string
                      vendor_link_id:
                        type: integer
                      ledger_entry_id:
                        type: integer
                      ledger_entry_reference:
                        type: string
                      sku_link_type:
                        type: string
                      sku_link_id:
                        type: integer
                      sku_link_label:
                        type: string
                      sku_link_route:
                        type: string
                      linked_ledger_entry:
                        type: object
                        properties:
                          id:
                            type: integer
                          document_number:
                            type: string
                          route:
                            type: string
                      amounts:
                        type: object
                        properties:
                          subtotal:
                            type: integer
                          tax:
                            type: integer
                          total:
                            type: integer
                          balance:
                            type: integer
                          paid:
                            type: integer
                      line_items:
                        type: array
                        items:
                          type: object
                          properties:
                            line_num:
                              type: integer
                            description:
                              type: string
                            detail_type:
                              type: string
                            item:
                              type: string
                            item_id:
                              type: string
                            item_link_id:
                              type: integer
                            account:
                              type: string
                              nullable: true
                            quantity:
                              type: integer
                            unit_price:
                              type: number
                            amount:
                              type: integer
                            tax_code:
                              type: string
                            posting_type:
                              type: string
                              nullable: true
                      detail_payload:
                        type: object
                        properties:
                          Id:
                            type: string
                          DocNumber:
                            type: string
                          TxnDate:
                            type: string
                          TotalAmt:
                            type: integer
                          VendorRef:
                            type: object
                            properties:
                              value:
                                type: string
                              name:
                                type: string
                          CurrencyRef:
                            type: object
                            properties:
                              value:
                                type: string
                          Line:
                            type: array
                            items:
                              type: object
                              properties:
                                Id:
                                  type: string
                                LineNum:
                                  type: integer
                                Amount:
                                  type: integer
                                DetailType:
                                  type: string
                                Description:
                                  type: string
                                SalesItemLineDetail:
                                  type: object
                                  properties:
                                    ItemRef:
                                      type: object
                                      properties:
                                        value:
                                          type: string
                                        name:
                                          type: string
                                    Qty:
                                      type: integer
                                    UnitPrice:
                                      type: number
                          sparse:
                            type: boolean
                example:
                  success: true
                  data:
                    id: 12
                    integration_instance_id: 3
                    qbo_id: '184'
                    doc_number: VC-1042
                    vendor_id: '56'
                    vendor_name: Shanghai Supplier Co
                    total_amount: '1250.00'
                    currency: USD
                    txn_date: '2026-07-01'
                    status: Open
                    active: true
                    sync_status: ok
                    last_synced_at: '2026-07-15T10:00:00.000000Z'
                    last_qbo_check_at: '2026-07-15T10:00:00.000000Z'
                    sync_error_message: null
                    qbo_created_at: '2026-07-01T09:00:00.000000Z'
                    qbo_updated_at: '2026-07-14T18:30:00.000000Z'
                    created_at: '2026-07-01T09:05:00.000000Z'
                    updated_at: '2026-07-14T18:35:00.000000Z'
                    integration_instance:
                      id: 3
                      name: QuickBooks Online
                    qbo_link: https://app.qbo.intuit.com/app/vendorcredit?txnId=184
                    vendor_link_id: 57
                    ledger_entry_id: 12506
                    ledger_entry_reference: O260724VOY4F6/R1
                    sku_link_type: App\Models\SalesOrder
                    sku_link_id: 4242
                    sku_link_label: Sales Order
                    sku_link_route: /orders/sales-orders/4242
                    linked_ledger_entry:
                      id: 9021
                      document_number: VC-9021
                      route: /ledger/entries/9021
                    amounts:
                      subtotal: 550
                      tax: 40
                      total: 590
                      balance: 90
                      paid: 500
                    line_items:
                    - line_num: 1
                      description: Osetra Caviar 4.4 oz
                      detail_type: SalesItemLineDetail
                      item: RO125G
                      item_id: '70'
                      item_link_id: 42
                      account: null
                      quantity: 4
                      unit_price: 147.5
                      amount: 590
                      tax_code: TAX
                      posting_type: null
                    detail_payload:
                      Id: '184'
                      DocNumber: VC-1042
                      TxnDate: '2026-07-01'
                      TotalAmt: 1250
                      VendorRef:
                        value: '56'
                        name: Shanghai Supplier Co
                      CurrencyRef:
                        value: USD
                      Line:
                      - Id: '1'
                        LineNum: 1
                        Amount: 590
                        DetailType: SalesItemLineDetail
                        Description: Osetra Caviar 4.4 oz
                        SalesItemLineDetail:
                          ItemRef:
                            value: '21'
                            name: RO125G
                          Qty: 4
                          UnitPrice: 147.5
                      sparse: false
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  error:
                    type: string
                  message:
                    type: string
                example:
                  success: false
                  error: QBO vendor-credit not found
                  message: No query results for model.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-qbo-vendor-credits-id
  /api/qbo/vendor-credits/{id}/activity-log:
    get:
      tags:
      - QuickBooks Online
      summary: Get Vendor Credit Activity Log
      description: 'Retrieve the audit trail for a synced QuickBooks Online vendor
        credit. Each entry records a create, update, or delete event on the local
        copy of the record, including the changed attributes, their previous values,
        and the user or process that made the change.


        Results are ordered newest first and paginated (standard pagination metadata
        is included in the response).


        Returns 404 if the vendor credit does not exist.


        Authentication: Requires Bearer token.'
      parameters:
      - name: id
        in: path
        schema:
          type: string
        required: true
        description: The record ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        description:
                          type: string
                        event:
                          type: string
                        subject_type:
                          type: string
                        subject_id:
                          type: integer
                        batch_uuid:
                          type: string
                          nullable: true
                        properties:
                          type: object
                          properties:
                            attributes:
                              type: object
                              properties:
                                sync_status:
                                  type: string
                            old:
                              type: object
                              properties:
                                sync_status:
                                  type: string
                            source:
                              type: string
                        causer_name:
                          type: string
                        created_at:
                          type: string
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                    items:
                      type: object
                      properties:
                        url:
                          type: string
                          nullable: true
                        label:
                          type: string
                        active:
                          type: boolean
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 5821
                    description: updated
                    event: updated
                    subject_type: QboVendorCredit
                    subject_id: 87
                    batch_uuid: null
                    properties:
                      attributes:
                        sync_status: synced
                      old:
                        sync_status: pending
                      source: qbo_sync
                    causer_name: Jane Smith
                    created_at: '2026-06-18T14:22:31.000000Z'
                  first_page_url: '{{protocol}}://{{domain}}/api/qbo/vendor-credits/87/activity-log?page=1'
                  from: 1
                  last_page: 1
                  last_page_url: '{{protocol}}://{{domain}}/api/qbo/vendor-credits/87/activity-log?page=1'
                  links:
                  - url: null
                    label: '&laquo; Previous'
                    active: false
                  - url: '{{protocol}}://{{domain}}/api/qbo/vendor-credits/87/activity-log?page=1'
                    label: '1'
                    active: true
                  - url: null
                    label: Next &raquo;
                    active: false
                  next_page_url: null
                  path: '{{protocol}}://{{domain}}/api/qbo/vendor-credits/87/activity-log'
                  per_page: 15
                  prev_page_url: null
                  to: 1
                  total: 1
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: object
                    properties:
                      id:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: array
                example:
                  errors:
                    id:
                    - message: Record not found.
                      code: NotFound
                      data: []
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-qbo-vendor-credits-id-activity-log
  /api/qbo/deposits:
    get:
      tags:
      - QuickBooks Online
      summary: List Deposits
      description: 'List mirrored QuickBooks bank deposits, paginated.


        Allowed sorts: id, txn_date, total_amount, sync_status, last_synced_at, qbo_created_at,
        qbo_updated_at, created_at, updated_at. Prefix with - for descending. Default
        sort: -created_at.


        Searchable columns (filter[search]): id, qbo_id.


        These documents are written to QuickBooks by SKU''s ledger sync (or mirrored
        from QuickBooks), so the API surface is read-only — list and get only.


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        qbo_id:
                          type: string
                        total_amount:
                          type: string
                        txn_date:
                          type: string
                        active:
                          type: boolean
                        sync_status:
                          type: string
                        last_synced_at:
                          type: string
                        last_qbo_check_at:
                          type: string
                        sync_error_message:
                          type: string
                          nullable: true
                        qbo_created_at:
                          type: string
                        qbo_updated_at:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                        integration_instance:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        qbo_link:
                          type: string
                  meta:
                    type: object
                    properties:
                      total:
                        type: integer
                      per_page:
                        type: integer
                      current_page:
                        type: integer
                      last_page:
                        type: integer
                      from:
                        type: integer
                      to:
                        type: integer
                  links:
                    type: object
                    properties:
                      first:
                        type: string
                      last:
                        type: string
                      prev:
                        type: string
                        nullable: true
                      next:
                        type: string
                        nullable: true
                example:
                  success: true
                  data:
                  - id: 7
                    integration_instance_id: 3
                    qbo_id: '441'
                    total_amount: '10000.00'
                    txn_date: '2026-07-01'
                    active: true
                    sync_status: ok
                    last_synced_at: '2026-07-15T10:00:00.000000Z'
                    last_qbo_check_at: '2026-07-15T10:00:00.000000Z'
                    sync_error_message: null
                    qbo_created_at: '2026-07-01T09:00:00.000000Z'
                    qbo_updated_at: '2026-07-14T18:30:00.000000Z'
                    created_at: '2026-07-01T09:05:00.000000Z'
                    updated_at: '2026-07-14T18:35:00.000000Z'
                    integration_instance:
                      id: 3
                      name: QuickBooks Online
                    qbo_link: https://app.qbo.intuit.com/app/deposit?txnId=441
                  meta:
                    total: 1
                    per_page: 15
                    current_page: 1
                    last_page: 1
                    from: 1
                    to: 1
                  links:
                    first: …?page=1
                    last: …?page=1
                    prev: null
                    next: null
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-qbo-deposits
  /api/qbo/deposits/{id}:
    get:
      tags:
      - QuickBooks Online
      summary: Get Deposit
      description: 'Get one mirrored QuickBooks bank deposit.


        The `linked_ledger_entry` field identifies the SKU ledger entry this QuickBooks
        document was created from (id, document number, and an app route). It is `null`
        when the document originated in QuickBooks rather than being pushed by SKU.
        This field is only present on the detail response, not on list rows.


        `qbo_link` deep-links to the deposit in the QuickBooks web UI.


        This document is pushed to QuickBooks by SKU''s ledger, so the response includes
        reverse cross-link fields: `ledger_entry_id` and `ledger_entry_reference`
        identify the SKU ledger entry that pushed it, while `sku_link_type`, `sku_link_id`,
        `sku_link_label`, and `sku_link_route` point back to the originating SKU document.
        These are `null` when the document originated in QuickBooks rather than being
        pushed by SKU.


        Authentication: Requires Bearer token. Returns `line_items` (normalized line
        rows parsed from the stored QuickBooks payload) and `detail_payload` (the
        full raw QuickBooks payload); both are null until the document is re-synced
        from QuickBooks.


        Also returns an `amounts` summary (`subtotal`, `tax`, `total`, `balance`,
        `paid`) and a `tax_code` on each `line_items` row.'
      parameters:
      - name: id
        in: path
        schema:
          type: string
        required: true
        description: The record ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      qbo_id:
                        type: string
                      total_amount:
                        type: string
                      txn_date:
                        type: string
                      active:
                        type: boolean
                      sync_status:
                        type: string
                      last_synced_at:
                        type: string
                      last_qbo_check_at:
                        type: string
                      sync_error_message:
                        type: string
                        nullable: true
                      qbo_created_at:
                        type: string
                      qbo_updated_at:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      integration_instance:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      qbo_link:
                        type: string
                      linked_ledger_entry:
                        type: object
                        properties:
                          id:
                            type: integer
                          document_number:
                            type: string
                          route:
                            type: string
                      ledger_entry_id:
                        type: integer
                      ledger_entry_reference:
                        type: string
                      sku_link_type:
                        type: string
                      sku_link_id:
                        type: integer
                      sku_link_label:
                        type: string
                      sku_link_route:
                        type: string
                      amounts:
                        type: object
                        properties:
                          subtotal:
                            type: integer
                          tax:
                            type: integer
                          total:
                            type: integer
                          balance:
                            type: integer
                          paid:
                            type: integer
                      line_items:
                        type: array
                        items:
                          type: object
                          properties:
                            line_num:
                              type: integer
                            description:
                              type: string
                            detail_type:
                              type: string
                            item:
                              type: string
                            item_id:
                              type: string
                            item_link_id:
                              type: integer
                            account:
                              type: string
                              nullable: true
                            quantity:
                              type: integer
                            unit_price:
                              type: number
                            amount:
                              type: integer
                            tax_code:
                              type: string
                            posting_type:
                              type: string
                              nullable: true
                      detail_payload:
                        type: object
                        properties:
                          Id:
                            type: string
                          TxnDate:
                            type: string
                          TotalAmt:
                            type: integer
                          Line:
                            type: array
                            items:
                              type: object
                              properties:
                                Id:
                                  type: string
                                LineNum:
                                  type: integer
                                Amount:
                                  type: integer
                                DetailType:
                                  type: string
                                Description:
                                  type: string
                                SalesItemLineDetail:
                                  type: object
                                  properties:
                                    ItemRef:
                                      type: object
                                      properties:
                                        value:
                                          type: string
                                        name:
                                          type: string
                                    Qty:
                                      type: integer
                                    UnitPrice:
                                      type: number
                          sparse:
                            type: boolean
                example:
                  success: true
                  data:
                    id: 7
                    integration_instance_id: 3
                    qbo_id: '441'
                    total_amount: '10000.00'
                    txn_date: '2026-07-01'
                    active: true
                    sync_status: ok
                    last_synced_at: '2026-07-15T10:00:00.000000Z'
                    last_qbo_check_at: '2026-07-15T10:00:00.000000Z'
                    sync_error_message: null
                    qbo_created_at: '2026-07-01T09:00:00.000000Z'
                    qbo_updated_at: '2026-07-14T18:30:00.000000Z'
                    created_at: '2026-07-01T09:05:00.000000Z'
                    updated_at: '2026-07-14T18:35:00.000000Z'
                    integration_instance:
                      id: 3
                      name: QuickBooks Online
                    qbo_link: https://app.qbo.intuit.com/app/deposit?txnId=441
                    linked_ledger_entry:
                      id: 9105
                      document_number: PPR-9105
                      route: /ledger/entries/9105
                    ledger_entry_id: 12506
                    ledger_entry_reference: O260724VOY4F6/R1
                    sku_link_type: App\Models\SalesOrder
                    sku_link_id: 4242
                    sku_link_label: Sales Order
                    sku_link_route: /orders/sales-orders/4242
                    amounts:
                      subtotal: 550
                      tax: 40
                      total: 590
                      balance: 90
                      paid: 500
                    line_items:
                    - line_num: 1
                      description: Osetra Caviar 4.4 oz
                      detail_type: SalesItemLineDetail
                      item: RO125G
                      item_id: '70'
                      item_link_id: 42
                      account: null
                      quantity: 4
                      unit_price: 147.5
                      amount: 590
                      tax_code: TAX
                      posting_type: null
                    detail_payload:
                      Id: '441'
                      TxnDate: '2026-07-01'
                      TotalAmt: 10000
                      Line:
                      - Id: '1'
                        LineNum: 1
                        Amount: 590
                        DetailType: SalesItemLineDetail
                        Description: Osetra Caviar 4.4 oz
                        SalesItemLineDetail:
                          ItemRef:
                            value: '21'
                            name: RO125G
                          Qty: 4
                          UnitPrice: 147.5
                      sparse: false
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  error:
                    type: string
                  message:
                    type: string
                example:
                  success: false
                  error: QBO deposit not found
                  message: No query results for model.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-qbo-deposits-id
  /api/qbo/deposits/{id}/activity-log:
    get:
      tags:
      - QuickBooks Online
      summary: Get Deposit Activity Log
      description: 'Retrieve the audit trail for a synced QuickBooks Online deposit.
        Each entry records a create, update, or delete event on the local copy of
        the record, including the changed attributes, their previous values, and the
        user or process that made the change.


        Results are ordered newest first and paginated (standard pagination metadata
        is included in the response).


        Returns 404 if the deposit does not exist.


        Authentication: Requires Bearer token.'
      parameters:
      - name: id
        in: path
        schema:
          type: string
        required: true
        description: The record ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        description:
                          type: string
                        event:
                          type: string
                        subject_type:
                          type: string
                        subject_id:
                          type: integer
                        batch_uuid:
                          type: string
                          nullable: true
                        properties:
                          type: object
                          properties:
                            attributes:
                              type: object
                              properties:
                                sync_status:
                                  type: string
                            old:
                              type: object
                              properties:
                                sync_status:
                                  type: string
                            source:
                              type: string
                        causer_name:
                          type: string
                        created_at:
                          type: string
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                    items:
                      type: object
                      properties:
                        url:
                          type: string
                          nullable: true
                        label:
                          type: string
                        active:
                          type: boolean
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 5821
                    description: updated
                    event: updated
                    subject_type: QboDeposit
                    subject_id: 87
                    batch_uuid: null
                    properties:
                      attributes:
                        sync_status: synced
                      old:
                        sync_status: pending
                      source: qbo_sync
                    causer_name: Jane Smith
                    created_at: '2026-06-18T14:22:31.000000Z'
                  first_page_url: '{{protocol}}://{{domain}}/api/qbo/deposits/87/activity-log?page=1'
                  from: 1
                  last_page: 1
                  last_page_url: '{{protocol}}://{{domain}}/api/qbo/deposits/87/activity-log?page=1'
                  links:
                  - url: null
                    label: '&laquo; Previous'
                    active: false
                  - url: '{{protocol}}://{{domain}}/api/qbo/deposits/87/activity-log?page=1'
                    label: '1'
                    active: true
                  - url: null
                    label: Next &raquo;
                    active: false
                  next_page_url: null
                  path: '{{protocol}}://{{domain}}/api/qbo/deposits/87/activity-log'
                  per_page: 15
                  prev_page_url: null
                  to: 1
                  total: 1
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: object
                    properties:
                      id:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: array
                example:
                  errors:
                    id:
                    - message: Record not found.
                      code: NotFound
                      data: []
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-qbo-deposits-id-activity-log
  /api/qbo/purchases:
    get:
      tags:
      - QuickBooks Online
      summary: List Purchases
      description: 'List mirrored QuickBooks purchases (expenses), paginated.


        Allowed sorts: id, doc_number, payment_type, txn_date, total_amount, sync_status,
        last_synced_at, qbo_created_at, qbo_updated_at, created_at, updated_at. Prefix
        with - for descending. Default sort: -created_at.


        Searchable columns (filter[search]): id, qbo_id, doc_number, payment_type.


        These documents are written to QuickBooks by SKU''s ledger sync (or mirrored
        from QuickBooks), so the API surface is read-only — list and get only.


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        qbo_id:
                          type: string
                        doc_number:
                          type: string
                        payment_type:
                          type: string
                        total_amount:
                          type: string
                        txn_date:
                          type: string
                        active:
                          type: boolean
                        sync_status:
                          type: string
                        last_synced_at:
                          type: string
                        last_qbo_check_at:
                          type: string
                        sync_error_message:
                          type: string
                          nullable: true
                        qbo_created_at:
                          type: string
                        qbo_updated_at:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                        integration_instance:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        qbo_link:
                          type: string
                  meta:
                    type: object
                    properties:
                      total:
                        type: integer
                      per_page:
                        type: integer
                      current_page:
                        type: integer
                      last_page:
                        type: integer
                      from:
                        type: integer
                      to:
                        type: integer
                  links:
                    type: object
                    properties:
                      first:
                        type: string
                      last:
                        type: string
                      prev:
                        type: string
                        nullable: true
                      next:
                        type: string
                        nullable: true
                example:
                  success: true
                  data:
                  - id: 21
                    integration_instance_id: 3
                    qbo_id: '512'
                    doc_number: PP-10285
                    payment_type: Check
                    total_amount: '10000.00'
                    txn_date: '2026-06-28'
                    active: true
                    sync_status: ok
                    last_synced_at: '2026-07-15T10:00:00.000000Z'
                    last_qbo_check_at: '2026-07-15T10:00:00.000000Z'
                    sync_error_message: null
                    qbo_created_at: '2026-07-01T09:00:00.000000Z'
                    qbo_updated_at: '2026-07-14T18:30:00.000000Z'
                    created_at: '2026-07-01T09:05:00.000000Z'
                    updated_at: '2026-07-14T18:35:00.000000Z'
                    integration_instance:
                      id: 3
                      name: QuickBooks Online
                    qbo_link: https://app.qbo.intuit.com/app/expense?txnId=512
                  meta:
                    total: 1
                    per_page: 15
                    current_page: 1
                    last_page: 1
                    from: 1
                    to: 1
                  links:
                    first: …?page=1
                    last: …?page=1
                    prev: null
                    next: null
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-qbo-purchases
  /api/qbo/purchases/{id}:
    get:
      tags:
      - QuickBooks Online
      summary: Get Purchase
      description: 'Get one mirrored QuickBooks purchase (expense).


        The `linked_ledger_entry` field identifies the SKU ledger entry this QuickBooks
        document was created from (id, document number, and an app route). It is `null`
        when the document originated in QuickBooks rather than being pushed by SKU.
        This field is only present on the detail response, not on list rows.


        `qbo_link` deep-links to the expense in the QuickBooks web UI.


        This document is pushed to QuickBooks by SKU''s ledger, so the response includes
        reverse cross-link fields: `ledger_entry_id` and `ledger_entry_reference`
        identify the SKU ledger entry that pushed it, while `sku_link_type`, `sku_link_id`,
        `sku_link_label`, and `sku_link_route` point back to the originating SKU document.
        These are `null` when the document originated in QuickBooks rather than being
        pushed by SKU.


        Authentication: Requires Bearer token. Returns `line_items` (normalized line
        rows parsed from the stored QuickBooks payload) and `detail_payload` (the
        full raw QuickBooks payload); both are null until the document is re-synced
        from QuickBooks.


        Also returns an `amounts` summary (`subtotal`, `tax`, `total`, `balance`,
        `paid`) and a `tax_code` on each `line_items` row.'
      parameters:
      - name: id
        in: path
        schema:
          type: string
        required: true
        description: The record ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      qbo_id:
                        type: string
                      doc_number:
                        type: string
                      payment_type:
                        type: string
                      total_amount:
                        type: string
                      txn_date:
                        type: string
                      active:
                        type: boolean
                      sync_status:
                        type: string
                      last_synced_at:
                        type: string
                      last_qbo_check_at:
                        type: string
                      sync_error_message:
                        type: string
                        nullable: true
                      qbo_created_at:
                        type: string
                      qbo_updated_at:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      integration_instance:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      qbo_link:
                        type: string
                      linked_ledger_entry:
                        type: object
                        properties:
                          id:
                            type: integer
                          document_number:
                            type: string
                          route:
                            type: string
                      ledger_entry_id:
                        type: integer
                      ledger_entry_reference:
                        type: string
                      sku_link_type:
                        type: string
                      sku_link_id:
                        type: integer
                      sku_link_label:
                        type: string
                      sku_link_route:
                        type: string
                      amounts:
                        type: object
                        properties:
                          subtotal:
                            type: integer
                          tax:
                            type: integer
                          total:
                            type: integer
                          balance:
                            type: integer
                          paid:
                            type: integer
                      line_items:
                        type: array
                        items:
                          type: object
                          properties:
                            line_num:
                              type: integer
                            description:
                              type: string
                            detail_type:
                              type: string
                            item:
                              type: string
                              nullable: true
                            item_id:
                              type: string
                              nullable: true
                            item_link_id:
                              type: string
                              nullable: true
                            account:
                              type: string
                            quantity:
                              type: string
                              nullable: true
                            unit_price:
                              type: string
                              nullable: true
                            amount:
                              type: integer
                            tax_code:
                              type: string
                            posting_type:
                              type: string
                              nullable: true
                      detail_payload:
                        type: object
                        properties:
                          Id:
                            type: string
                          DocNumber:
                            type: string
                          TxnDate:
                            type: string
                          TotalAmt:
                            type: integer
                          PaymentType:
                            type: string
                          Line:
                            type: array
                            items:
                              type: object
                              properties:
                                Id:
                                  type: string
                                Amount:
                                  type: integer
                                DetailType:
                                  type: string
                                Description:
                                  type: string
                                AccountBasedExpenseLineDetail:
                                  type: object
                                  properties:
                                    AccountRef:
                                      type: object
                                      properties:
                                        value:
                                          type: string
                                        name:
                                          type: string
                          sparse:
                            type: boolean
                example:
                  success: true
                  data:
                    id: 21
                    integration_instance_id: 3
                    qbo_id: '512'
                    doc_number: PP-10285
                    payment_type: Check
                    total_amount: '10000.00'
                    txn_date: '2026-06-28'
                    active: true
                    sync_status: ok
                    last_synced_at: '2026-07-15T10:00:00.000000Z'
                    last_qbo_check_at: '2026-07-15T10:00:00.000000Z'
                    sync_error_message: null
                    qbo_created_at: '2026-07-01T09:00:00.000000Z'
                    qbo_updated_at: '2026-07-14T18:30:00.000000Z'
                    created_at: '2026-07-01T09:05:00.000000Z'
                    updated_at: '2026-07-14T18:35:00.000000Z'
                    integration_instance:
                      id: 3
                      name: QuickBooks Online
                    qbo_link: https://app.qbo.intuit.com/app/expense?txnId=512
                    linked_ledger_entry:
                      id: 10285
                      document_number: PP-10285
                      route: /ledger/entries/10285
                    ledger_entry_id: 12506
                    ledger_entry_reference: O260724VOY4F6/R1
                    sku_link_type: App\Models\SalesOrder
                    sku_link_id: 4242
                    sku_link_label: Sales Order
                    sku_link_route: /orders/sales-orders/4242
                    amounts:
                      subtotal: 550
                      tax: 40
                      total: 590
                      balance: 90
                      paid: 500
                    line_items:
                    - line_num: 1
                      description: Cold-chain freight
                      detail_type: AccountBasedExpenseLineDetail
                      item: null
                      item_id: null
                      item_link_id: null
                      account: Shipping & Freight
                      quantity: null
                      unit_price: null
                      amount: 125
                      tax_code: TAX
                      posting_type: null
                    detail_payload:
                      Id: '512'
                      DocNumber: PP-10285
                      TxnDate: '2026-06-28'
                      TotalAmt: 10000
                      PaymentType: Check
                      Line:
                      - Id: '1'
                        Amount: 125
                        DetailType: AccountBasedExpenseLineDetail
                        Description: Cold-chain freight
                        AccountBasedExpenseLineDetail:
                          AccountRef:
                            value: '63'
                            name: Shipping & Freight
                      sparse: false
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  error:
                    type: string
                  message:
                    type: string
                example:
                  success: false
                  error: QBO purchase not found
                  message: No query results for model.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-qbo-purchases-id
  /api/qbo/purchases/{id}/activity-log:
    get:
      tags:
      - QuickBooks Online
      summary: Get Purchase Activity Log
      description: 'Retrieve the audit trail for a synced QuickBooks Online purchase.
        Each entry records a create, update, or delete event on the local copy of
        the record, including the changed attributes, their previous values, and the
        user or process that made the change.


        Results are ordered newest first and paginated (standard pagination metadata
        is included in the response).


        Returns 404 if the purchase does not exist.


        Authentication: Requires Bearer token.'
      parameters:
      - name: id
        in: path
        schema:
          type: string
        required: true
        description: The record ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        description:
                          type: string
                        event:
                          type: string
                        subject_type:
                          type: string
                        subject_id:
                          type: integer
                        batch_uuid:
                          type: string
                          nullable: true
                        properties:
                          type: object
                          properties:
                            attributes:
                              type: object
                              properties:
                                sync_status:
                                  type: string
                            old:
                              type: object
                              properties:
                                sync_status:
                                  type: string
                            source:
                              type: string
                        causer_name:
                          type: string
                        created_at:
                          type: string
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                    items:
                      type: object
                      properties:
                        url:
                          type: string
                          nullable: true
                        label:
                          type: string
                        active:
                          type: boolean
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 5821
                    description: updated
                    event: updated
                    subject_type: QboPurchase
                    subject_id: 87
                    batch_uuid: null
                    properties:
                      attributes:
                        sync_status: synced
                      old:
                        sync_status: pending
                      source: qbo_sync
                    causer_name: Jane Smith
                    created_at: '2026-06-18T14:22:31.000000Z'
                  first_page_url: '{{protocol}}://{{domain}}/api/qbo/purchases/87/activity-log?page=1'
                  from: 1
                  last_page: 1
                  last_page_url: '{{protocol}}://{{domain}}/api/qbo/purchases/87/activity-log?page=1'
                  links:
                  - url: null
                    label: '&laquo; Previous'
                    active: false
                  - url: '{{protocol}}://{{domain}}/api/qbo/purchases/87/activity-log?page=1'
                    label: '1'
                    active: true
                  - url: null
                    label: Next &raquo;
                    active: false
                  next_page_url: null
                  path: '{{protocol}}://{{domain}}/api/qbo/purchases/87/activity-log'
                  per_page: 15
                  prev_page_url: null
                  to: 1
                  total: 1
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: object
                    properties:
                      id:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: array
                example:
                  errors:
                    id:
                    - message: Record not found.
                      code: NotFound
                      data: []
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-qbo-purchases-id-activity-log
  /api/qbo/bill-payments:
    get:
      tags:
      - QuickBooks Online
      summary: List Bill Payments
      description: 'List mirrored QuickBooks bill payments, paginated. Each row includes
        its allocations — the bills / vendor credits the payment was applied to, with
        per-line amounts.


        Allowed sorts: id, doc_number, vendor_name, txn_date, total_amount, pay_type,
        sync_status, last_synced_at, qbo_created_at, qbo_updated_at, created_at, updated_at.
        Prefix with - for descending. Default sort: -created_at.


        Searchable columns (filter[search]): id, qbo_id, doc_number, vendor_name,
        private_note.


        These documents are written to QuickBooks by SKU''s ledger sync (or mirrored
        from QuickBooks), so the API surface is read-only — list and get only.


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        qbo_id:
                          type: string
                        vendor_id:
                          type: string
                        vendor_name:
                          type: string
                        total_amount:
                          type: string
                        currency:
                          type: string
                        txn_date:
                          type: string
                        pay_type:
                          type: string
                        doc_number:
                          type: string
                        private_note:
                          type: string
                        active:
                          type: boolean
                        sync_status:
                          type: string
                        last_synced_at:
                          type: string
                        last_qbo_check_at:
                          type: string
                        sync_error_message:
                          type: string
                          nullable: true
                        qbo_created_at:
                          type: string
                        qbo_updated_at:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                        integration_instance:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        allocations:
                          type: array
                          items:
                            type: object
                            properties:
                              id:
                                type: integer
                              txn_type:
                                type: string
                              linked_txn_id:
                                type: string
                              amount:
                                type: string
                        qbo_link:
                          type: string
                  meta:
                    type: object
                    properties:
                      total:
                        type: integer
                      per_page:
                        type: integer
                      current_page:
                        type: integer
                      last_page:
                        type: integer
                      from:
                        type: integer
                      to:
                        type: integer
                  links:
                    type: object
                    properties:
                      first:
                        type: string
                      last:
                        type: string
                      prev:
                        type: string
                        nullable: true
                      next:
                        type: string
                        nullable: true
                example:
                  success: true
                  data:
                  - id: 33
                    integration_instance_id: 3
                    qbo_id: '901'
                    vendor_id: '56'
                    vendor_name: Shanghai Supplier Co
                    total_amount: '0.00'
                    currency: USD
                    txn_date: '2026-07-02'
                    pay_type: Check
                    doc_number: PPA-10290
                    private_note: Vendor credit applied to bill
                    active: true
                    sync_status: ok
                    last_synced_at: '2026-07-15T10:00:00.000000Z'
                    last_qbo_check_at: '2026-07-15T10:00:00.000000Z'
                    sync_error_message: null
                    qbo_created_at: '2026-07-01T09:00:00.000000Z'
                    qbo_updated_at: '2026-07-14T18:30:00.000000Z'
                    created_at: '2026-07-01T09:05:00.000000Z'
                    updated_at: '2026-07-14T18:35:00.000000Z'
                    integration_instance:
                      id: 3
                      name: QuickBooks Online
                    allocations:
                    - id: 61
                      txn_type: Bill
                      linked_txn_id: '777'
                      amount: '125.50'
                    - id: 62
                      txn_type: VendorCredit
                      linked_txn_id: '184'
                      amount: '-125.50'
                    qbo_link: https://app.qbo.intuit.com/app/billpayment?txnId=901
                  meta:
                    total: 1
                    per_page: 15
                    current_page: 1
                    last_page: 1
                    from: 1
                    to: 1
                  links:
                    first: …?page=1
                    last: …?page=1
                    prev: null
                    next: null
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-qbo-bill-payments
  /api/qbo/bill-payments/{id}:
    get:
      tags:
      - QuickBooks Online
      summary: Get Bill Payment
      description: 'Get one mirrored QuickBooks bill payment, including its allocations
        (which bills / vendor credits it settled and for how much).


        The `linked_ledger_entry` field identifies the SKU ledger entry this QuickBooks
        document was created from (id, document number, and an app route). It is `null`
        when the document originated in QuickBooks rather than being pushed by SKU.
        This field is only present on the detail response, not on list rows.


        `qbo_link` deep-links to the bill payment in the QuickBooks web UI.


        This document is pushed to QuickBooks by SKU''s ledger, so the response includes
        reverse cross-link fields: `ledger_entry_id` and `ledger_entry_reference`
        identify the SKU ledger entry that pushed it, while `sku_link_type`, `sku_link_id`,
        `sku_link_label`, and `sku_link_route` point back to the originating SKU document.
        These are `null` when the document originated in QuickBooks rather than being
        pushed by SKU. `vendor_link_id` cross-links to the mirrored QuickBooks vendor.


        Authentication: Requires Bearer token. Returns `line_items` (normalized line
        rows parsed from the stored QuickBooks payload) and `detail_payload` (the
        full raw QuickBooks payload); both are null until the document is re-synced
        from QuickBooks.


        Also returns an `amounts` summary (`subtotal`, `tax`, `total`, `balance`,
        `paid`) and a `tax_code` on each `line_items` row.'
      parameters:
      - name: id
        in: path
        schema:
          type: string
        required: true
        description: The record ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      qbo_id:
                        type: string
                      vendor_id:
                        type: string
                      vendor_name:
                        type: string
                      total_amount:
                        type: string
                      currency:
                        type: string
                      txn_date:
                        type: string
                      pay_type:
                        type: string
                      doc_number:
                        type: string
                      private_note:
                        type: string
                      active:
                        type: boolean
                      sync_status:
                        type: string
                      last_synced_at:
                        type: string
                      last_qbo_check_at:
                        type: string
                      sync_error_message:
                        type: string
                        nullable: true
                      qbo_created_at:
                        type: string
                      qbo_updated_at:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      integration_instance:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      allocations:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            txn_type:
                              type: string
                            linked_txn_id:
                              type: string
                            amount:
                              type: string
                      qbo_link:
                        type: string
                      vendor_link_id:
                        type: integer
                      ledger_entry_id:
                        type: integer
                      ledger_entry_reference:
                        type: string
                      sku_link_type:
                        type: string
                      sku_link_id:
                        type: integer
                      sku_link_label:
                        type: string
                      sku_link_route:
                        type: string
                      linked_ledger_entry:
                        type: object
                        properties:
                          id:
                            type: integer
                          document_number:
                            type: string
                          route:
                            type: string
                      amounts:
                        type: object
                        properties:
                          subtotal:
                            type: integer
                          tax:
                            type: integer
                          total:
                            type: integer
                          balance:
                            type: integer
                          paid:
                            type: integer
                      line_items:
                        type: array
                        items:
                          type: object
                          properties:
                            line_num:
                              type: integer
                            description:
                              type: string
                            detail_type:
                              type: string
                            item:
                              type: string
                            item_id:
                              type: string
                            item_link_id:
                              type: integer
                            account:
                              type: string
                              nullable: true
                            quantity:
                              type: integer
                            unit_price:
                              type: number
                            amount:
                              type: integer
                            tax_code:
                              type: string
                            posting_type:
                              type: string
                              nullable: true
                      detail_payload:
                        type: object
                        properties:
                          Id:
                            type: string
                          DocNumber:
                            type: string
                          TxnDate:
                            type: string
                          TotalAmt:
                            type: integer
                          VendorRef:
                            type: object
                            properties:
                              value:
                                type: string
                              name:
                                type: string
                          CurrencyRef:
                            type: object
                            properties:
                              value:
                                type: string
                          Line:
                            type: array
                            items:
                              type: object
                              properties:
                                Id:
                                  type: string
                                LineNum:
                                  type: integer
                                Amount:
                                  type: integer
                                DetailType:
                                  type: string
                                Description:
                                  type: string
                                SalesItemLineDetail:
                                  type: object
                                  properties:
                                    ItemRef:
                                      type: object
                                      properties:
                                        value:
                                          type: string
                                        name:
                                          type: string
                                    Qty:
                                      type: integer
                                    UnitPrice:
                                      type: number
                          sparse:
                            type: boolean
                example:
                  success: true
                  data:
                    id: 33
                    integration_instance_id: 3
                    qbo_id: '901'
                    vendor_id: '56'
                    vendor_name: Shanghai Supplier Co
                    total_amount: '0.00'
                    currency: USD
                    txn_date: '2026-07-02'
                    pay_type: Check
                    doc_number: PPA-10290
                    private_note: Vendor credit applied to bill
                    active: true
                    sync_status: ok
                    last_synced_at: '2026-07-15T10:00:00.000000Z'
                    last_qbo_check_at: '2026-07-15T10:00:00.000000Z'
                    sync_error_message: null
                    qbo_created_at: '2026-07-01T09:00:00.000000Z'
                    qbo_updated_at: '2026-07-14T18:30:00.000000Z'
                    created_at: '2026-07-01T09:05:00.000000Z'
                    updated_at: '2026-07-14T18:35:00.000000Z'
                    integration_instance:
                      id: 3
                      name: QuickBooks Online
                    allocations:
                    - id: 61
                      txn_type: Bill
                      linked_txn_id: '777'
                      amount: '125.50'
                    - id: 62
                      txn_type: VendorCredit
                      linked_txn_id: '184'
                      amount: '-125.50'
                    qbo_link: https://app.qbo.intuit.com/app/billpayment?txnId=901
                    vendor_link_id: 57
                    ledger_entry_id: 12506
                    ledger_entry_reference: O260724VOY4F6/R1
                    sku_link_type: App\Models\SalesOrder
                    sku_link_id: 4242
                    sku_link_label: Sales Order
                    sku_link_route: /orders/sales-orders/4242
                    linked_ledger_entry:
                      id: 10290
                      document_number: PPA-10290
                      route: /ledger/entries/10290
                    amounts:
                      subtotal: 550
                      tax: 40
                      total: 590
                      balance: 90
                      paid: 500
                    line_items:
                    - line_num: 1
                      description: Osetra Caviar 4.4 oz
                      detail_type: SalesItemLineDetail
                      item: RO125G
                      item_id: '70'
                      item_link_id: 42
                      account: null
                      quantity: 4
                      unit_price: 147.5
                      amount: 590
                      tax_code: TAX
                      posting_type: null
                    detail_payload:
                      Id: '901'
                      DocNumber: PPA-10290
                      TxnDate: '2026-07-02'
                      TotalAmt: 0
                      VendorRef:
                        value: '56'
                        name: Shanghai Supplier Co
                      CurrencyRef:
                        value: USD
                      Line:
                      - Id: '1'
                        LineNum: 1
                        Amount: 590
                        DetailType: SalesItemLineDetail
                        Description: Osetra Caviar 4.4 oz
                        SalesItemLineDetail:
                          ItemRef:
                            value: '21'
                            name: RO125G
                          Qty: 4
                          UnitPrice: 147.5
                      sparse: false
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  error:
                    type: string
                  message:
                    type: string
                example:
                  success: false
                  error: QBO bill-payment not found
                  message: No query results for model.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-qbo-bill-payments-id
  /api/qbo/bill-payments/{id}/activity-log:
    get:
      tags:
      - QuickBooks Online
      summary: Get Bill Payment Activity Log
      description: 'Retrieve the audit trail for a synced QuickBooks Online bill payment.
        Each entry records a create, update, or delete event on the local copy of
        the record, including the changed attributes, their previous values, and the
        user or process that made the change.


        Results are ordered newest first and paginated (standard pagination metadata
        is included in the response).


        Returns 404 if the bill payment does not exist.


        Authentication: Requires Bearer token.'
      parameters:
      - name: id
        in: path
        schema:
          type: string
        required: true
        description: The record ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        description:
                          type: string
                        event:
                          type: string
                        subject_type:
                          type: string
                        subject_id:
                          type: integer
                        batch_uuid:
                          type: string
                          nullable: true
                        properties:
                          type: object
                          properties:
                            attributes:
                              type: object
                              properties:
                                sync_status:
                                  type: string
                            old:
                              type: object
                              properties:
                                sync_status:
                                  type: string
                            source:
                              type: string
                        causer_name:
                          type: string
                        created_at:
                          type: string
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                    items:
                      type: object
                      properties:
                        url:
                          type: string
                          nullable: true
                        label:
                          type: string
                        active:
                          type: boolean
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 5821
                    description: updated
                    event: updated
                    subject_type: QboBillPayment
                    subject_id: 87
                    batch_uuid: null
                    properties:
                      attributes:
                        sync_status: synced
                      old:
                        sync_status: pending
                      source: qbo_sync
                    causer_name: Jane Smith
                    created_at: '2026-06-18T14:22:31.000000Z'
                  first_page_url: '{{protocol}}://{{domain}}/api/qbo/bill-payments/87/activity-log?page=1'
                  from: 1
                  last_page: 1
                  last_page_url: '{{protocol}}://{{domain}}/api/qbo/bill-payments/87/activity-log?page=1'
                  links:
                  - url: null
                    label: '&laquo; Previous'
                    active: false
                  - url: '{{protocol}}://{{domain}}/api/qbo/bill-payments/87/activity-log?page=1'
                    label: '1'
                    active: true
                  - url: null
                    label: Next &raquo;
                    active: false
                  next_page_url: null
                  path: '{{protocol}}://{{domain}}/api/qbo/bill-payments/87/activity-log'
                  per_page: 15
                  prev_page_url: null
                  to: 1
                  total: 1
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: object
                    properties:
                      id:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: array
                example:
                  errors:
                    id:
                    - message: Record not found.
                      code: NotFound
                      data: []
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-qbo-bill-payments-id-activity-log
  /api/qbo/sync-activity:
    get:
      tags:
      - QuickBooks Online
      summary: List Sync Activity
      description: 'List QuickBooks sync-status transitions, newest first.


        Default window: when no created_at filter is supplied, results cover the LAST
        7 DAYS only. Supply any filter[created_at...] parameter to query older history.


        Each row records one status transition on a mirrored QuickBooks record: the
        record type and id, the old and new status, a human-readable reason, structured
        metadata, the acting user (null for system/polling changes), and the timestamp.
        The `entity` object resolves the mirrored record''s QuickBooks id and its
        document identifier (document number or name) when the record still exists.


        Searchable columns (filter[search]): id, reason, entity_type.


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        entity_type:
                          type: string
                        entity_type_label:
                          type: string
                        entity_id:
                          type: integer
                        entity:
                          type: object
                          properties:
                            qbo_id:
                              type: string
                            doc_identifier:
                              type: string
                        old_status:
                          type: string
                        new_status:
                          type: string
                        reason:
                          type: string
                        metadata:
                          type: object
                          properties:
                            qbo_id:
                              type: string
                            source:
                              type: string
                        user:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 311
                    entity_type: Modules\Qbo\Entities\QboInvoice
                    entity_type_label: QboInvoice
                    entity_id: 87
                    entity:
                      qbo_id: '184'
                      doc_identifier: INV-1042
                    old_status: ok
                    new_status: qbo_updated
                    reason: Status updated from QuickBooks data ingestion (refresh/CDC
                      pull)
                    metadata:
                      qbo_id: '184'
                      source: qbo_data_ingestion
                    user: null
                    created_at: '2026-07-15T10:00:00.000000Z'
                  first_page_url: …?page=1
                  from: 1
                  last_page: 1
                  last_page_url: …?page=1
                  links: []
                  next_page_url: null
                  path: …/api/qbo/sync-activity
                  per_page: 25
                  prev_page_url: null
                  to: 1
                  total: 1
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-qbo-sync-activity
  /api/xero/v2/bank-transactions:
    get:
      tags:
      - Xero
      summary: List Bank Transactions
      description: 'Paginated, filterable, sortable list of locally-cached Xero bank
        transactions (synced from Xero''s BankTransactions API).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Authentication:** Requires Bearer token.


        Filtering goes through XeroEntityListing + AdvancedFilterBuilder, so every
        column accepts the full operator set both as `filter[column.operator]=value`
        AND inside the base64 `filter_groups` tree (the advanced-filter modal and
        the ever-present Type/Status/Reconciled/Date dropdowns).


        Each column also supports the `is_not` operator (e.g. `filter[status.is_not]=DELETED`
        to exclude voided transactions), plus the full operator set inside `filter_groups`.


        Allowed sorts: id, date, total, type, status, is_reconciled, contact_name,
        bank_account_name, reference, updated_at, created_at (default -date).'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        xero_uuid:
                          type: string
                        bank_transaction_id:
                          type: string
                        type:
                          type: string
                        status:
                          type: string
                        is_reconciled:
                          type: boolean
                        reference:
                          type: string
                        contact_id:
                          type: string
                        contact_name:
                          type: string
                        bank_account_id:
                          type: string
                        bank_account_code:
                          type: string
                        bank_account_name:
                          type: string
                        currency_code:
                          type: string
                        sub_total:
                          type: string
                        total_tax:
                          type: string
                        total:
                          type: string
                        date:
                          type: string
                        updated_date_utc:
                          type: string
                        url:
                          type: string
                        sync_status:
                          type: string
                          nullable: true
                        last_error:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  per_page:
                    type: integer
                  last_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - id: 11501
                    xero_uuid: a5343cfe-f398-4c61-a550-6888c1e26e73
                    bank_transaction_id: a5343cfe-f398-4c61-a550-6888c1e26e73
                    type: SPEND
                    status: AUTHORISED
                    is_reconciled: false
                    reference: BELL SPORTS 866-5252357
                    contact_id: c-1
                    contact_name: Bell Sports
                    bank_account_id: ba-1
                    bank_account_code: '202'
                    bank_account_name: AMEX xx-2001
                    currency_code: USD
                    sub_total: '157.4700'
                    total_tax: '0.0000'
                    total: '157.4700'
                    date: '2025-08-31T00:00:00+00:00'
                    updated_date_utc: '2016-07-30T12:23:00+00:00'
                    url: https://go.xero.com/Bank/ViewTransaction.aspx?bankTransactionID=a5343cfe-f398-4c61-a550-6888c1e26e73
                    sync_status: null
                    last_error: null
                    created_at: '2026-06-26T22:50:00+00:00'
                    updated_at: '2026-06-26T22:50:00+00:00'
                  current_page: 1
                  per_page: 15
                  last_page: 700
                  total: 17500
                  from: 1
                  to: 15
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-xero-v2-bank-transactions
  /api/xero/v2/bank-transactions/{bankTransaction}:
    get:
      tags:
      - Xero
      summary: Get Bank Transaction Detail
      description: 'Full detail view for a single cached Xero bank transaction — header,
        contact, bank account, amounts, every line item, and the raw Xero `json_object`
        payload.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Authentication:** Requires Bearer token.


        Returns 404 if the id does not exist.'
      parameters:
      - name: bankTransaction
        in: path
        schema:
          type: integer
        required: true
        description: Local XeroBankTransaction id.
        example: '11501'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      xero_uuid:
                        type: string
                      bank_transaction_id:
                        type: string
                      type:
                        type: string
                      status:
                        type: string
                      is_reconciled:
                        type: boolean
                      reference:
                        type: string
                      line_amount_types:
                        type: string
                      contact_id:
                        type: string
                      contact_name:
                        type: string
                      bank_account_id:
                        type: string
                      bank_account_code:
                        type: string
                      bank_account_name:
                        type: string
                      currency_code:
                        type: string
                      currency_rate:
                        type: string
                      sub_total:
                        type: string
                      total_tax:
                        type: string
                      total:
                        type: string
                      date:
                        type: string
                      updated_date_utc:
                        type: string
                      line_items:
                        type: array
                        items:
                          type: object
                          properties:
                            line_item_id:
                              type: string
                            description:
                              type: string
                              nullable: true
                            account_code:
                              type: string
                            quantity:
                              type: integer
                            unit_amount:
                              type: number
                            tax_type:
                              type: string
                            tax_amount:
                              type: integer
                            line_amount:
                              type: number
                            item_code:
                              type: string
                              nullable: true
                      url:
                        type: string
                      sync_status:
                        type: string
                        nullable: true
                      last_error:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      json_object:
                        type: object
                        properties:
                          BankTransactionID:
                            type: string
                          Type:
                            type: string
                          Status:
                            type: string
                          IsReconciled:
                            type: boolean
                          Total:
                            type: string
                          Contact:
                            type: object
                            properties:
                              ContactID:
                                type: string
                              Name:
                                type: string
                          BankAccount:
                            type: object
                            properties:
                              AccountID:
                                type: string
                              Code:
                                type: string
                              Name:
                                type: string
                          LineItems:
                            type: array
                            items:
                              type: object
                              properties:
                                LineItemID:
                                  type: string
                                AccountCode:
                                  type: string
                                LineAmount:
                                  type: number
                example:
                  data:
                    id: 11501
                    xero_uuid: a5343cfe-f398-4c61-a550-6888c1e26e73
                    bank_transaction_id: a5343cfe-f398-4c61-a550-6888c1e26e73
                    type: SPEND
                    status: AUTHORISED
                    is_reconciled: false
                    reference: BELL SPORTS 866-5252357
                    line_amount_types: NoTax
                    contact_id: c-1
                    contact_name: Bell Sports
                    bank_account_id: ba-1
                    bank_account_code: '202'
                    bank_account_name: AMEX xx-2001
                    currency_code: USD
                    currency_rate: '1.000000'
                    sub_total: '157.4700'
                    total_tax: '0.0000'
                    total: '157.4700'
                    date: '2025-08-31T00:00:00+00:00'
                    updated_date_utc: '2016-07-30T12:23:00+00:00'
                    line_items:
                    - line_item_id: li-1
                      description: null
                      account_code: '500'
                      quantity: 1
                      unit_amount: 157.47
                      tax_type: NONE
                      tax_amount: 0
                      line_amount: 157.47
                      item_code: null
                    url: https://go.xero.com/Bank/ViewTransaction.aspx?bankTransactionID=a5343cfe-f398-4c61-a550-6888c1e26e73
                    sync_status: null
                    last_error: null
                    created_at: '2026-06-26T22:50:00+00:00'
                    updated_at: '2026-06-26T22:50:00+00:00'
                    json_object:
                      BankTransactionID: a5343cfe-f398-4c61-a550-6888c1e26e73
                      Type: SPEND
                      Status: AUTHORISED
                      IsReconciled: false
                      Total: '157.47'
                      Contact:
                        ContactID: c-1
                        Name: Bell Sports
                      BankAccount:
                        AccountID: ba-1
                        Code: '202'
                        Name: AMEX xx-2001
                      LineItems:
                      - LineItemID: li-1
                        AccountCode: '500'
                        LineAmount: 157.47
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No query results for model [Modules\\Xero\\Entities\\XeroBankTransaction]
                    99999
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-xero-v2-bank-transactions-banktransaction
  /api/xero/bank-transactions/download:
    post:
      tags:
      - Xero
      summary: Sync Bank Transactions from Xero
      description: 'Dispatch a tracked background sync that pulls bank transactions
        from Xero''s BankTransactions API into the local cache (paged 100/request,
        upserted by BankTransactionID).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Authentication:** Requires Bearer token.


        **Body (all optional, nullable dates Y-m-d):**

        - `date_from` — only transactions dated on/after (builds the Xero OData `Date
        >= DateTime(...)` filter)

        - `date_to` — only transactions dated on/before

        - `modified_after` — incremental: only records changed since (If-Modified-Since)


        All null = full pull. Returns the tracked-job id so the UI can follow progress
        via the tracked job log endpoints.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                date_from:
                  type: string
                date_to:
                  type: string
                modified_after:
                  type: string
                  nullable: true
              example:
                date_from: '2024-01-01'
                date_to: '2026-06-27'
                modified_after: null
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                example:
                  data:
                    tracked_job_log_id: 12345
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-xero-bank-transactions-download
  /api/xero/authorize:
    get:
      tags:
      - Xero
      summary: Generate OAuth URL
      description: 'Generate a Xero OAuth 2.0 authorization URL to initiate the connection
        flow. Redirect the user to the returned URL to authenticate with Xero.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      url:
                        type: string
                example:
                  data:
                    url: https://login.xero.com/identity/connect/authorize?response_type=code&client_id=...&redirect_uri=...&scope=openid+profile+email+accounting.transactions+offline_access&state=...
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-xero-authorize
  /api/xero/integrations:
    get:
      tags:
      - Xero
      summary: List Integration Instances
      description: 'List all Xero integration instances. Used by the application UI
        to determine whether to show the empty state (Connect to Xero) or the dashboard.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        tenant_id:
                          type: string
                        sync_status:
                          type: string
                        is_automatic_sync_enabled:
                          type: boolean
                        xero_webhook_enabled:
                          type: boolean
                        integration_settings:
                          type: object
                          properties:
                            settings:
                              type: object
                              properties:
                                sync_start_date:
                                  type: string
                example:
                  data:
                  - id: 1
                    name: Xero Production
                    tenant_id: abc123-tenant-uuid
                    sync_status: active
                    is_automatic_sync_enabled: true
                    xero_webhook_enabled: false
                    integration_settings:
                      settings:
                        sync_start_date: '2024-01-01'
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-xero-integrations
  /api/xero/integrations/{id}:
    patch:
      tags:
      - Xero
      summary: Update Integration Instance
      description: 'Update Xero integration settings. All fields are optional.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Fields:

        - is_automatic_sync_enabled (optional, boolean): Enable/disable automatic
        sync

        - name (optional, string, max 255): Display name

        - sync_start_date (optional, date Y-m-d | null): Only sync transactions on
        or after this date'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                is_automatic_sync_enabled:
                  type: boolean
                name:
                  type: string
                sync_start_date:
                  type: string
              example:
                is_automatic_sync_enabled: true
                name: Xero Production
                sync_start_date: '2024-01-01'
      parameters:
      - name: id
        in: path
        schema:
          type: integer
        required: true
        description: Xero integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      is_automatic_sync_enabled:
                        type: boolean
                example:
                  message: Settings saved.
                  data:
                    id: 1
                    name: Xero Production
                    is_automatic_sync_enabled: true
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: patch-api-xero-integrations-id
    delete:
      tags:
      - Xero
      summary: Delete Integration Instance
      description: 'Delete a Xero integration instance and all associated data.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: id
        in: path
        schema:
          type: integer
        required: true
        description: Xero integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Xero integration deleted.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-xero-integrations-id
  /api/xero/dashboard:
    get:
      tags:
      - Xero
      summary: Show Dashboard
      description: 'Get the Xero integration dashboard data including integration
        status, connection health, entity counts, and webhook summary.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Returns null data if no integration instance is configured.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 Success
                  value:
                    data:
                      integration_status:
                        id: 1
                        name: Xero Production
                        tenant_id: abc123-tenant-uuid
                        is_authenticated: true
                        is_automatic_sync_enabled: true
                        sync_status: active
                        sync_start_date: '2024-01-01'
                      connection_health:
                        daily_api_limit: 5000
                        daily_api_remaining: 9850
                        daily_api_reset_at: '2024-05-02T00:00:00Z'
                        webhook_enabled: false
                      entity_counts:
                        accounts: 142
                        tax_rates: 8
                        contacts: 356
                        invoices: 1204
                        bills: 892
                        credit_notes: 47
                        purchase_orders: 211
                        payments: 2103
                        manual_journals: 15
                      webhook_summary:
                        enabled: false
                        events_last_24h: 0
                        failed_last_24h: 0
                example-1:
                  summary: 200 No Integration
                  value:
                    data: null
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-xero-dashboard
  /api/xero/accounts/download:
    post:
      tags:
      - Xero
      summary: Download Accounts from Xero
      description: 'Fetch and sync all accounts from the Xero API into the local database.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Xero Accounts downloaded successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-xero-accounts-download
  /api/xero/accounts/create-nominal-codes:
    post:
      tags:
      - Xero
      summary: Create Nominal Codes from Accounts
      description: 'Create SKU.io nominal codes from selected Xero account records.
        Requires an active Xero accounting integration.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Body:

        - ids (required, array of integers, min 1): Xero account IDs to create nominal
        codes from'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1
                - 2
                - 5
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                example:
                  success: true
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: array
                    items:
                      type: object
                      properties:
                        message:
                          type: string
                example:
                  errors:
                  - message: No Xero accounting integration found
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-xero-accounts-create-nominal-codes
  /api/xero/accounts/create:
    post:
      tags:
      - Xero
      summary: Create Account in Xero (asset)
      description: 'Create a GL account in the connected Xero tenant and mirror it
        locally. Type is restricted to Xero ASSET types (CURRENT/FIXED/NONCURRENT)
        — used by the onboarding flow to provision a missing inventory ASSET account
        (Xero won''t let you post inventory journal movements to an INVENTORY-type
        account). Requires a connected Xero accounting integration.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authenticate with a PAT.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                code:
                  type: string
                name:
                  type: string
                type:
                  type: string
              example:
                code: '1000'
                name: Inventory Asset
                type: CURRENT
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      code:
                        type: string
                      name:
                        type: string
                      type:
                        type: string
                      class:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 42
                    code: '1000'
                    name: Inventory Asset
                    type: CURRENT
                    class: ASSET
                  message: Account created in Xero.
        '422':
          description: Unprocessable Content
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      type:
                        type: array
                        items:
                          type: string
                example:
                  message: The inventory account must be an asset account (Current,
                    Fixed, or Non-current) — not an INVENTORY-type account.
                  errors:
                    type:
                    - The inventory account must be an asset account (Current, Fixed,
                      or Non-current) — not an INVENTORY-type account.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-xero-accounts-create
  /api/xero/accounts/nominal-code-suggestions:
    get:
      tags:
      - Xero
      summary: Nominal Code → Xero Account Suggestions
      description: 'Smart-default suggestions for the onboarding mapping step: for
        each SKU nominal code, the Xero account it most likely maps to (matched by
        exact code → type → name). Read-only.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        nominal_code_id:
                          type: integer
                        nominal_code:
                          type: string
                        nominal_name:
                          type: string
                        nominal_type:
                          type: string
                        xero_account_id:
                          type: integer
                        xero_code:
                          type: string
                        xero_name:
                          type: string
                        xero_type:
                          type: string
                        xero_class:
                          type: string
                        reason:
                          type: string
                example:
                  data:
                  - nominal_code_id: 12
                    nominal_code: '4000'
                    nominal_name: Sales
                    nominal_type: Revenue
                    xero_account_id: 5
                    xero_code: '4000'
                    xero_name: Sales
                    xero_type: REVENUE
                    xero_class: REVENUE
                    reason: code
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-xero-accounts-nominal-code-suggestions
  /api/xero/accounts/nominal-code-mappings:
    post:
      tags:
      - Xero
      summary: Map Nominal Codes → Xero Accounts
      description: 'Persist SKU nominal code → Xero account mappings (polymorphic
        integration_account link). Enforces the inventory→ASSET guard: rejects mapping
        any code to a Xero INVENTORY-type account, and requires the inventory-control
        role''s code to map to an ASSET-class account (422 otherwise).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                mappings:
                  type: array
                  items:
                    type: object
                    properties:
                      nominal_code_id:
                        type: integer
                      xero_account_id:
                        type: integer
              example:
                mappings:
                - nominal_code_id: 12
                  xero_account_id: 5
                - nominal_code_id: 7
                  xero_account_id: 9
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Nominal code mappings saved.
        '422':
          description: Unprocessable Content
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: '"630 Xero Inventory" is a Xero INVENTORY account — SKU
                    can''t post inventory movements to it. Map to a current-asset
                    account instead.'
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-xero-accounts-nominal-code-mappings
  /api/xero/accounts/adopt-chart:
    post:
      tags:
      - Xero
      summary: Adopt Xero Chart of Accounts (hard-replace)
      description: 'Onboarding: hard-replace SKU''s chart of accounts with Xero''s.
        Imports every mapped Xero account as a nominal code, re-points every reference
        (sales order lines, settings roles, product/channel/warehouse overrides, …)
        onto the replacements, then deletes the old chart. EVERY existing nominal
        code must appear in `mappings` (a complete old→new map is what makes the delete
        safe) — otherwise 422-equivalent failure listing the unmapped ids. Runs as
        a tracked job; returns its log id so the UI can follow progress via the tracked
        job log endpoints. Pass `repost: true` to also repost every current ledger
        entry after the replace (chained inside the job) so posted GL lines pick up
        the new accounts.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                mappings:
                  type: array
                  items:
                    type: object
                    properties:
                      nominal_code_id:
                        type: integer
                      xero_account_id:
                        type: integer
                repost:
                  type: boolean
              example:
                mappings:
                - nominal_code_id: 12
                  xero_account_id: 5
                - nominal_code_id: 7
                  xero_account_id: 9
                repost: true
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                example:
                  data:
                    tracked_job_log_id: 4821
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No Xero accounting integration found
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-xero-accounts-adopt-chart
  /api/xero/tax-rates/download:
    post:
      tags:
      - Xero
      summary: Download Tax Rates from Xero
      description: 'Fetch and sync tax rates from the Xero API.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Tax rates downloaded successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-xero-tax-rates-download
  /api/xero/contacts/sync:
    post:
      tags:
      - Xero
      summary: Sync Contacts
      description: 'Push your suppliers to Xero as contacts — creates or updates the
        matching Xero contact for each supplier. Requires a connected Xero integration
        with syncing active.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Returns 422 with an `XeroNotConnected` error when the Xero connection is disconnected
        or its authorization has expired; reauthorize Xero before retrying.'
      requestBody:
        content: {}
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Contacts synced successfully.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      XeroNotConnected:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: array
                example:
                  status: failure
                  message: Xero is not connected. Reauthorize Xero in Settings before
                    syncing contacts.
                  errors:
                    XeroNotConnected:
                    - message: Xero is not connected. Reauthorize Xero in Settings
                        before syncing contacts.
                      code: XeroNotConnected
                      data: []
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-xero-contacts-sync
  /api/xero/v2/contacts/{contact}/link-sku-entity:
    post:
      tags:
      - Xero
      summary: Link Contact to SKU Entity
      description: 'Link this Xero contact to a SKU.io customer or supplier via its
        polymorphic reverse link. Provide `link_type` (the SKU.io model class — `App\\Models\\Customer`
        or `App\\Models\\Supplier`) and `link_id` (that record''s ID). Returns the
        updated contact with its resolved `sku_link_type`, `sku_link_id`, and `sku_link_reference`.


        Returns 422 when the referenced customer or supplier does not exist.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                link_type:
                  type: string
                link_id:
                  type: integer
              example:
                link_type: App\Models\Customer
                link_id: 1420
      parameters:
      - name: contact
        in: path
        schema:
          type: integer
        required: true
        description: Internal contact record ID
        example: '87'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      contact_id:
                        type: string
                      name:
                        type: string
                      email:
                        type: string
                      phone:
                        type: string
                      is_customer:
                        type: boolean
                      is_supplier:
                        type: boolean
                      status:
                        type: string
                      addresses:
                        type: array
                        items:
                          type: object
                          properties:
                            type:
                              type: string
                            line1:
                              type: string
                            line2:
                              type: string
                            line3:
                              type: string
                              nullable: true
                            city:
                              type: string
                            postal_code:
                              type: string
                            country:
                              type: string
                      sku_link_type:
                        type: string
                      sku_link_id:
                        type: integer
                      sku_link_reference:
                        type: string
                      last_error:
                        type: string
                        nullable: true
                      url:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  success: true
                  message: SKU Customer linked successfully.
                  data:
                    id: 87
                    contact_id: d4e5f6a7-b8c9-40d1-a2b3-c4d5e6f7a8b9
                    name: Acme Retail Group
                    email: accounts@acmeretail.com
                    phone: 1 415 5550172
                    is_customer: true
                    is_supplier: false
                    status: ACTIVE
                    addresses:
                    - type: STREET
                      line1: 2251 Harrison St
                      line2: Suite 400
                      line3: null
                      city: San Francisco
                      postal_code: '94110'
                      country: United States
                    sku_link_type: App\Models\Customer
                    sku_link_id: 1420
                    sku_link_reference: Acme Corp
                    last_error: null
                    url: https://go.xero.com/Contacts/View/d4e5f6a7-b8c9-40d1-a2b3-c4d5e6f7a8b9
                    created_at: '2026-02-03T11:18:52+00:00'
                    updated_at: '2026-06-28T04:02:19+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-xero-v2-contacts-contact-link-sku-entity
  /api/xero/v2/contacts/{contact}/unlink-sku-entity:
    delete:
      tags:
      - Xero
      summary: Unlink Contact from SKU Entity
      description: 'Clear this Xero contact''s link to a SKU.io customer or supplier
        (nulls the polymorphic reverse link). Read-safe — leaves the contact record
        otherwise untouched.


        Authentication: Requires Bearer token.'
      parameters:
      - name: contact
        in: path
        schema:
          type: integer
        required: true
        description: Internal contact record ID
        example: '87'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                example:
                  success: true
                  message: SKU entity unlinked successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-xero-v2-contacts-contact-unlink-sku-entity
  /api/xero/v2/accounts:
    get:
      tags:
      - Xero
      summary: List Accounts (V2)
      description: 'Paginated list of Xero accounts with advanced filtering via Spatie
        QueryBuilder + GroupedFilterSupport.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Query Parameters:

        - page (optional, integer, default 1): Page number

        - per_page (optional, integer, default 15): Records per page

        - sort (optional, string): Allowed sorts: id, Name, Code, Type, Status, Class,
        created_at. Default: Name

        - filter[search] (optional, string): Search across id, Name, Code


        Advanced Filters (filter_groups):

        Supports all operators: is, is_not, contains, does_not_contain, starts_with,
        ends_with, is_empty, is_not_empty, is_one_of (text fields); greater_than,
        less_than, between (numeric).

        Filterable columns: id (numeric), Name (text), Code (text), Type (text), Class
        (text), Status (text)'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        description: 'Page number (default: 1)'
        example: '1'
      - name: per_page
        in: query
        schema:
          type: integer
        description: 'Records per page (default: 15)'
        example: '15'
      - name: sort
        in: query
        schema:
          type: string
        description: 'Sort column. Allowed: id, Name, Code, Type, Status, Class, created_at.
          Prefix with - for descending (e.g. -Name)'
        example: Name
      - name: filter[search]
        in: query
        schema:
          type: string
        description: Search by id, Name, or Code
        example: revenue
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        xero_integration_instance_id:
                          type: integer
                        Code:
                          type: string
                        Name:
                          type: string
                        Type:
                          type: string
                        Status:
                          type: string
                        Class:
                          type: string
                        Description:
                          type: string
                        nominalCode:
                          type: object
                          properties:
                            id:
                              type: integer
                            code:
                              type: string
                            name:
                              type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 1
                    xero_integration_instance_id: 1
                    Code: '200'
                    Name: Sales
                    Type: REVENUE
                    Status: ACTIVE
                    Class: REVENUE
                    Description: Revenue from product sales
                    nominalCode:
                      id: 3
                      code: '200'
                      name: Sales
                  current_page: 1
                  last_page: 10
                  per_page: 15
                  total: 142
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-xero-v2-accounts
  /api/xero/v2/tax-rates:
    get:
      tags:
      - Xero
      summary: List Tax Rates (V2)
      description: 'Paginated list of Xero tax rates.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Sort options: id, Name, TaxType, EffectiveRate, created_at


        Filterable columns: id (numeric), Name (text), TaxType (text), EffectiveRate
        (numeric)'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        description: Page number
        example: '1'
      - name: per_page
        in: query
        schema:
          type: integer
        description: 'Records per page (default: 15)'
        example: '15'
      - name: sort
        in: query
        schema:
          type: string
        description: 'Allowed: id, Name, TaxType, EffectiveRate, created_at. Prefix
          - for descending'
        example: Name
      - name: filter[search]
        in: query
        schema:
          type: string
        description: Search by id, Name, TaxType
        example: GST
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        Name:
                          type: string
                        TaxType:
                          type: string
                        EffectiveRate:
                          type: number
                        Status:
                          type: string
                        created_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 1
                    Name: GST on Income
                    TaxType: OUTPUT
                    EffectiveRate: 10.0
                    Status: ACTIVE
                    created_at: '2024-01-01T00:00:00.000000Z'
                  current_page: 1
                  last_page: 1
                  per_page: 15
                  total: 8
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-xero-v2-tax-rates
  /api/xero/v2/contacts:
    get:
      tags:
      - Xero
      summary: List Contacts (V2)
      description: 'Paginated list of Xero contacts with advanced filtering.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Sort options: id, Name, ContactID, created_at


        Filterable columns: id (numeric), Name (text), ContactID (text), link_type
        (text — polymorphic FQN e.g. App\Models\Supplier)


        Also includes computed fields: IsCustomer, IsSupplier (extracted from JSON
        object)'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        description: Page number
        example: '1'
      - name: per_page
        in: query
        schema:
          type: integer
        description: 'Records per page (default: 15)'
        example: '15'
      - name: sort
        in: query
        schema:
          type: string
        description: 'Allowed: id, Name, ContactID, created_at. Prefix - for descending'
        example: Name
      - name: filter[search]
        in: query
        schema:
          type: string
        description: Search by id, Name, ContactID
        example: acme
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        xero_integration_instance_id:
                          type: integer
                        ContactID:
                          type: string
                        Name:
                          type: string
                        link_type:
                          type: string
                        link_id:
                          type: integer
                        IsCustomer:
                          type: string
                        IsSupplier:
                          type: string
                        created_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 10
                    xero_integration_instance_id: 1
                    ContactID: xero-contact-uuid
                    Name: Acme Corp
                    link_type: App\Models\Supplier
                    link_id: 5
                    IsCustomer: 'false'
                    IsSupplier: 'true'
                    created_at: '2024-01-15T10:00:00.000000Z'
                  current_page: 1
                  last_page: 24
                  per_page: 15
                  total: 356
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-xero-v2-contacts
  /api/xero/v2/invoices:
    get:
      tags:
      - Xero
      summary: List Invoices (V2)
      description: 'Paginated list of Xero invoices (ACCREC type) with advanced filtering
        via Spatie QueryBuilder + GroupedFilterSupport.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Sort options: id, xero_uuid, InvoiceNumber, Status, Date, DueDate, Total,
        AmountDue, AmountPaid, ContactName, CurrencyCode, updated_at, created_at.
        Default: -updated_at


        Filterable columns:

        - Text: xero_uuid, InvoiceNumber, Reference, Status, sync_status, CurrencyCode,
        ContactID, ContactName, last_error, has_error (boolean-like), has_sku_link
        (boolean-like), sku_reference

        - Numeric: id, Total, SubTotal, TotalTax, AmountDue, AmountPaid, AmountCredited

        - Date (millis): Date, DueDate, FullyPaidOnDate, UpdatedDateUTC


        Each row includes: at_id, at_reference, at_type, sku_link_type, sku_link_id
        (flattened from accountingTransaction relation)'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        description: Page number
        example: '1'
      - name: per_page
        in: query
        schema:
          type: integer
        description: 'Records per page (default: 15)'
        example: '15'
      - name: sort
        in: query
        schema:
          type: string
        description: 'Allowed: id, xero_uuid, InvoiceNumber, Status, Date, DueDate,
          Total, AmountDue, AmountPaid, ContactName, CurrencyCode, updated_at, created_at'
        example: -updated_at
      - name: filter[search]
        in: query
        schema:
          type: string
        description: Search by id, xero_uuid, InvoiceNumber, Reference, ContactName,
          last_error
        example: INV-001
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        xero_uuid:
                          type: string
                        InvoiceNumber:
                          type: string
                        Status:
                          type: string
                        sync_status:
                          type: string
                        ContactID:
                          type: string
                        ContactName:
                          type: string
                        Date:
                          type: integer
                        DueDate:
                          type: integer
                        Total:
                          type: number
                        SubTotal:
                          type: number
                        TotalTax:
                          type: number
                        AmountDue:
                          type: number
                        AmountPaid:
                          type: number
                        AmountCredited:
                          type: number
                        CurrencyCode:
                          type: string
                        last_error:
                          type: string
                          nullable: true
                        at_id:
                          type: integer
                        at_reference:
                          type: string
                        at_type:
                          type: string
                        sku_link_type:
                          type: string
                        sku_link_id:
                          type: integer
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 100
                    xero_uuid: xero-invoice-uuid-001
                    InvoiceNumber: INV-001
                    Status: AUTHORISED
                    sync_status: synced
                    ContactID: contact-uuid
                    ContactName: Acme Corp
                    Date: 1714521600000
                    DueDate: 1717113600000
                    Total: 1250.0
                    SubTotal: 1136.36
                    TotalTax: 113.64
                    AmountDue: 0.0
                    AmountPaid: 1250.0
                    AmountCredited: 0.0
                    CurrencyCode: AUD
                    last_error: null
                    at_id: 55
                    at_reference: C-1001
                    at_type: sales_order
                    sku_link_type: App\Models\SalesOrder
                    sku_link_id: 1001
                    created_at: '2024-05-01T10:00:00.000000Z'
                    updated_at: '2024-05-01T10:00:00.000000Z'
                  current_page: 1
                  last_page: 81
                  per_page: 15
                  total: 1204
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-xero-v2-invoices
  /api/xero/v2/bills:
    get:
      tags:
      - Xero
      summary: List Bills (V2)
      description: 'Paginated list of Xero bills (ACCPAY type). Same filter and sort
        options as invoices.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Filterable columns (identical to invoices): id, xero_uuid, InvoiceNumber,
        Reference, Status, sync_status, CurrencyCode, ContactID, ContactName, Total,
        SubTotal, TotalTax, AmountDue, AmountPaid, AmountCredited, Date (millis),
        DueDate (millis), FullyPaidOnDate (millis), UpdatedDateUTC (millis), last_error,
        has_error, has_sku_link, sku_reference'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        description: Page number
        example: '1'
      - name: per_page
        in: query
        schema:
          type: integer
        description: 'Records per page (default: 15)'
        example: '15'
      - name: sort
        in: query
        schema:
          type: string
        description: 'Allowed: id, xero_uuid, InvoiceNumber, Status, Date, DueDate,
          Total, AmountDue, AmountPaid, ContactName, CurrencyCode, updated_at, created_at'
        example: -updated_at
      - name: filter[search]
        in: query
        schema:
          type: string
        description: Search by id, xero_uuid, InvoiceNumber, Reference, ContactName,
          last_error
        example: BILL-001
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        xero_uuid:
                          type: string
                        InvoiceNumber:
                          type: string
                        Status:
                          type: string
                        ContactName:
                          type: string
                        Total:
                          type: number
                        AmountDue:
                          type: number
                        AmountPaid:
                          type: number
                        Date:
                          type: integer
                        DueDate:
                          type: integer
                        CurrencyCode:
                          type: string
                        at_id:
                          type: string
                          nullable: true
                        at_reference:
                          type: string
                          nullable: true
                        at_type:
                          type: string
                          nullable: true
                        sku_link_type:
                          type: string
                          nullable: true
                        sku_link_id:
                          type: string
                          nullable: true
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 200
                    xero_uuid: xero-bill-uuid-001
                    InvoiceNumber: BILL-001
                    Status: AUTHORISED
                    ContactName: Global Supplies
                    Total: 890.0
                    AmountDue: 890.0
                    AmountPaid: 0.0
                    Date: 1714521600000
                    DueDate: 1717113600000
                    CurrencyCode: USD
                    at_id: null
                    at_reference: null
                    at_type: null
                    sku_link_type: null
                    sku_link_id: null
                  current_page: 1
                  last_page: 60
                  per_page: 15
                  total: 892
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-xero-v2-bills
  /api/xero/v2/credit-notes:
    get:
      tags:
      - Xero
      summary: List Credit Notes (V2)
      description: 'Paginated list of Xero credit notes. Same filter and sort options
        as invoices.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        description: Page number
        example: '1'
      - name: per_page
        in: query
        schema:
          type: integer
        description: 'Records per page (default: 15)'
        example: '15'
      - name: sort
        in: query
        schema:
          type: string
        description: Sort column (same options as invoices endpoint)
        example: -updated_at
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        xero_uuid:
                          type: string
                        InvoiceNumber:
                          type: string
                        Status:
                          type: string
                        ContactName:
                          type: string
                        Total:
                          type: number
                        CurrencyCode:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 300
                    xero_uuid: xero-cn-uuid-001
                    InvoiceNumber: CN-001
                    Status: AUTHORISED
                    ContactName: Acme Corp
                    Total: 250.0
                    CurrencyCode: AUD
                  current_page: 1
                  last_page: 4
                  per_page: 15
                  total: 47
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-xero-v2-credit-notes
  /api/xero/v2/purchase-orders:
    get:
      tags:
      - Xero
      summary: List Purchase Orders (V2)
      description: 'Paginated list of Xero purchase orders. Same filter and sort options
        as invoices.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        description: Page number
        example: '1'
      - name: per_page
        in: query
        schema:
          type: integer
        description: 'Records per page (default: 15)'
        example: '15'
      - name: sort
        in: query
        schema:
          type: string
        description: Sort column
        example: -updated_at
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        xero_uuid:
                          type: string
                        InvoiceNumber:
                          type: string
                        Status:
                          type: string
                        ContactName:
                          type: string
                        Total:
                          type: number
                        CurrencyCode:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 400
                    xero_uuid: xero-po-uuid-001
                    InvoiceNumber: PO-001
                    Status: AUTHORISED
                    ContactName: Global Supplies
                    Total: 5000.0
                    CurrencyCode: USD
                  current_page: 1
                  last_page: 15
                  per_page: 15
                  total: 211
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-xero-v2-purchase-orders
  /api/xero/v2/manual-journals:
    get:
      tags:
      - Xero
      summary: List Manual Journals (V2)
      description: 'Paginated list of Xero manual journal entries.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        description: Page number
        example: '1'
      - name: per_page
        in: query
        schema:
          type: integer
        description: 'Records per page (default: 15)'
        example: '15'
      - name: sort
        in: query
        schema:
          type: string
        description: Sort column
        example: -updated_at
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        xero_uuid:
                          type: string
                        Status:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 500
                    xero_uuid: xero-mj-uuid-001
                    Status: POSTED
                    created_at: '2024-04-01T10:00:00.000000Z'
                    updated_at: '2024-04-01T10:00:00.000000Z'
                  current_page: 1
                  last_page: 1
                  per_page: 15
                  total: 15
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-xero-v2-manual-journals
  /api/xero/v2/journals:
    get:
      tags:
      - Xero
      summary: List Journals (V2)
      description: 'Paginated list of Xero general-ledger journal lines.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Each row is one flattened GL journal line pulled from Xero''s immutable Journals
        feed (GET /Journals) — the provider side of the daily inventory reconciliation.
        Distinct from Manual Journals (/api/xero/v2/manual-journals), which are user-authored
        journals.


        Authentication: Requires Bearer token.


        Pagination: page (default 1), per_page (default 15).


        Sorting (sort, prefix with - for DESC). Default: -journal_number (newest journals
        first, lines of the same journal kept adjacent). Allowed: id, journal_number,
        journal_date, account_code, account_name, source_type, net_amount, gross_amount,
        tax_amount, created_at, updated_at.


        Search (filter[search]): partial match across account_code, account_name,
        source_type, source_id, journal_id (and exact id / journal_number when numeric).


        Advanced filters (base64 filter_groups tree OR flat filter[&lt;col>][&lt;op>]=v).
        Numeric: id, journal_number, net_amount, gross_amount, tax_amount. Text: journal_id,
        account_code, account_name, source_type, source_id. Date: journal_date.


        net_amount is signed: positive = debit, negative = credit.


        account_local_id: the local XeroAccount id this line''s account resolves to
        (account_id GUID first, account_code second). Use it to deep-link the account
        columns to /v2/integrations/xero/accounts/{id}. null when the account is not
        synced locally.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        journal_id:
                          type: string
                        journal_number:
                          type: integer
                        journal_date:
                          type: string
                        source_id:
                          type: string
                        source_type:
                          type: string
                        journal_line_id:
                          type: string
                        account_id:
                          type: string
                        account_code:
                          type: string
                        account_name:
                          type: string
                        account_local_id:
                          type: integer
                        net_amount:
                          type: string
                        gross_amount:
                          type: string
                        tax_amount:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 9001
                    integration_instance_id: 12
                    journal_id: b1d2c3e4-0000-4a1b-9c2d-3e4f5a6b7c8d
                    journal_number: 4821
                    journal_date: '2024-04-30'
                    source_id: f7e6d5c4-1111-4b2c-8d3e-4f5a6b7c8d9e
                    source_type: ACCREC
                    journal_line_id: a9b8c7d6-2222-4c3d-9e4f-5a6b7c8d9e0f
                    account_id: c3d4e5f6-3333-4d4e-af5a-6b7c8d9e0f1a
                    account_code: '200'
                    account_name: Sales
                    account_local_id: 3
                    net_amount: '-1250.00'
                    gross_amount: '-1375.00'
                    tax_amount: '-125.00'
                    created_at: '2024-05-01T03:15:22.000000Z'
                    updated_at: '2024-05-01T03:15:22.000000Z'
                  current_page: 1
                  last_page: 1
                  per_page: 15
                  total: 8
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-xero-v2-journals
  /api/xero/v2/journals/{id}:
    get:
      tags:
      - Xero
      summary: Get Journal Detail (V2)
      description: 'Detail view of a single Xero general-ledger journal, grouped by
        journal_number.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Returns the journal header (number, Xero journal_id, date, source type/id,
        integration instance), every flattened GL line of that journal (including
        account_local_id for deep-linking each line''s account), and computed totals
        (line_count, total_debit, total_credit, net, tax, gross, is_balanced).


        Path param: journalNumber (integer) — the Xero journal number.


        Query param: integration_instance_id (integer, optional) — scope to a single
        connection. journal_number is only unique per connection, so pass this when
        more than one Xero connection exists.


        Authentication: Requires Bearer token.


        net_amount is signed: positive = debit, negative = credit. total_debit / total_credit
        are the absolute sums of the positive / negative net_amounts; is_balanced
        is true when they''re equal.


        404 ''Journal not found.'' when no lines match the journal number (and instance,
        if supplied).'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      journal_number:
                        type: integer
                      journal_id:
                        type: string
                      journal_date:
                        type: string
                      integration_instance_id:
                        type: integer
                      source_type:
                        type: string
                      source_id:
                        type: string
                      lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            integration_instance_id:
                              type: integer
                            journal_id:
                              type: string
                            journal_number:
                              type: integer
                            journal_date:
                              type: string
                            source_id:
                              type: string
                            source_type:
                              type: string
                            journal_line_id:
                              type: string
                            account_id:
                              type: string
                            account_code:
                              type: string
                            account_name:
                              type: string
                            account_local_id:
                              type: integer
                            net_amount:
                              type: string
                            gross_amount:
                              type: string
                            tax_amount:
                              type: string
                            created_at:
                              type: string
                            updated_at:
                              type: string
                      totals:
                        type: object
                        properties:
                          line_count:
                            type: integer
                          total_debit:
                            type: string
                          total_credit:
                            type: string
                          net:
                            type: string
                          tax:
                            type: string
                          gross:
                            type: string
                          is_balanced:
                            type: boolean
                example:
                  data:
                    journal_number: 4821
                    journal_id: b1d2c3e4-0000-4a1b-9c2d-3e4f5a6b7c8d
                    journal_date: '2024-04-30'
                    integration_instance_id: 12
                    source_type: ACCREC
                    source_id: f7e6d5c4-1111-4b2c-8d3e-4f5a6b7c8d9e
                    lines:
                    - id: 9001
                      integration_instance_id: 12
                      journal_id: b1d2c3e4-0000-4a1b-9c2d-3e4f5a6b7c8d
                      journal_number: 4821
                      journal_date: '2024-04-30'
                      source_id: f7e6d5c4-1111-4b2c-8d3e-4f5a6b7c8d9e
                      source_type: ACCREC
                      journal_line_id: a9b8c7d6-2222-4c3d-9e4f-5a6b7c8d9e0f
                      account_id: c3d4e5f6-3333-4d4e-af5a-6b7c8d9e0f1a
                      account_code: '200'
                      account_name: Sales
                      account_local_id: 3
                      net_amount: '-1250.00'
                      gross_amount: '-1375.00'
                      tax_amount: '-125.00'
                      created_at: '2024-05-01T03:15:22.000000Z'
                      updated_at: '2024-05-01T03:15:22.000000Z'
                    - id: 9002
                      integration_instance_id: 12
                      journal_id: b1d2c3e4-0000-4a1b-9c2d-3e4f5a6b7c8d
                      journal_number: 4821
                      journal_date: '2024-04-30'
                      source_id: f7e6d5c4-1111-4b2c-8d3e-4f5a6b7c8d9e
                      source_type: ACCREC
                      journal_line_id: b8c7d6e5-3333-4d4e-af5a-6b7c8d9e0f1b
                      account_id: d4e5f6a7-4444-4e5f-b06b-7c8d9e0f1a2b
                      account_code: '610'
                      account_name: Accounts Receivable
                      account_local_id: 7
                      net_amount: '1375.00'
                      gross_amount: '1375.00'
                      tax_amount: '0.00'
                      created_at: '2024-05-01T03:15:22.000000Z'
                      updated_at: '2024-05-01T03:15:22.000000Z'
                    totals:
                      line_count: 2
                      total_debit: '1375.00'
                      total_credit: '1250.00'
                      net: '125.00'
                      tax: '-125.00'
                      gross: '0.00'
                      is_balanced: false
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Journal not found.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-xero-v2-journals-id
  /api/xero/v2/payments:
    get:
      tags:
      - Xero
      summary: List Payments (V2)
      description: 'Paginated list of Xero payments. Payments use a payment relation
        (not accountingTransaction) to link to SKU.io Payment entities.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        description: Page number
        example: '1'
      - name: per_page
        in: query
        schema:
          type: integer
        description: 'Records per page (default: 15)'
        example: '15'
      - name: sort
        in: query
        schema:
          type: string
        description: Sort column
        example: -updated_at
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        xero_uuid:
                          type: string
                        Amount:
                          type: number
                        Date:
                          type: integer
                        at_id:
                          type: string
                          nullable: true
                        at_reference:
                          type: string
                          nullable: true
                        at_type:
                          type: string
                        sku_link_type:
                          type: string
                        sku_link_id:
                          type: integer
                        created_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 600
                    xero_uuid: xero-payment-uuid-001
                    Amount: 1250.0
                    Date: 1714521600000
                    at_id: null
                    at_reference: null
                    at_type: payment
                    sku_link_type: App\Models\SalesOrder
                    sku_link_id: 1001
                    created_at: '2024-05-01T10:00:00.000000Z'
                  current_page: 1
                  last_page: 141
                  per_page: 15
                  total: 2103
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-xero-v2-payments
  /api/xero/v2/accounts/{account}:
    get:
      tags:
      - Xero
      summary: Get Account (V2)
      description: 'Detail view-model for a single Xero account (chart of accounts)
        — backs the /v2/integrations/xero/accounts/{id} detail page. Returns the stored
        generated columns, descriptive fields that only live in the raw Xero json_object
        payload, the linked SKU nominal code, and local sync metadata.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Authentication:** Requires Bearer token.


        **Path parameters:**

        - account (required, integer): xero_accounts.id


        **nominal_code** is the SKU nominal code this account links to (null when
        unlinked). `link_basis` records how the link was resolved: `mapping` = an
        explicit polymorphic mapping (set by the onboarding wizard / QBO), `code`
        = inferred by matching xero_accounts.Code ⇄ nominal_codes.code (the fallback
        Xero''s sync uses when a tenant adopted its chart). The frontend deep-links
        from here to /v2/ledger/accounts/{nominal_code.id}.


        Xero accounts are config records: there is no remote deep-link, no line items
        and no per-record sync status, so those are intentionally omitted.'
      parameters:
      - name: account
        in: path
        schema:
          type: integer
        required: true
        description: xero_accounts.id
        example: '61'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: integer
                  account_id:
                    type: string
                  code:
                    type: string
                  name:
                    type: string
                  type:
                    type: string
                  class:
                    type: string
                  status:
                    type: string
                  description:
                    type: string
                  tax_type:
                    type: string
                  enable_payments_to_account:
                    type: boolean
                  show_in_expense_claims:
                    type: boolean
                  bank_account_number:
                    type: string
                    nullable: true
                  bank_account_type:
                    type: string
                    nullable: true
                  currency_code:
                    type: string
                    nullable: true
                  reporting_code:
                    type: string
                  reporting_code_name:
                    type: string
                  system_account:
                    type: string
                    nullable: true
                  updated_date_utc:
                    type: string
                  nominal_code:
                    type: object
                    properties:
                      id:
                        type: integer
                      code:
                        type: string
                      name:
                        type: string
                      type:
                        type: string
                      link_basis:
                        type: string
                  created_at:
                    type: string
                  updated_at:
                    type: string
                example:
                  id: 61
                  account_id: 2c8b3e10-7f4a-4d2e-9b1c-5a6f8e0d1234
                  code: '510'
                  name: Shipping
                  type: EXPENSE
                  class: EXPENSE
                  status: ACTIVE
                  description: Shipping and freight costs
                  tax_type: NONE
                  enable_payments_to_account: false
                  show_in_expense_claims: false
                  bank_account_number: null
                  bank_account_type: null
                  currency_code: null
                  reporting_code: EXP
                  reporting_code_name: Expense
                  system_account: null
                  updated_date_utc: /Date(1718200000000+0000)/
                  nominal_code:
                    id: 20
                    code: '510'
                    name: Shipping
                    type: Expense
                    link_basis: code
                  created_at: '2026-05-20T08:14:32+00:00'
                  updated_at: '2026-06-10T11:02:51+00:00'
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No query results for model [Modules\\Xero\\Entities\\XeroAccount]
                    99999
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-xero-v2-accounts-account
  /api/xero/v2/bills/{bill}:
    get:
      tags:
      - Xero
      summary: Get Bill (V2)
      description: 'Get a single synced Xero bill (an ACCPAY invoice in Xero) — header
        fields, line items, the reverse link to the SKU.io record it was generated
        from, and sync metadata (`sync_status`, `last_error`, and `url`, a deep link
        to the bill in Xero). Monetary amounts are in the bill''s currency; datetimes
        are UTC ISO-8601.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Path parameters:**

        - `bill` (integer, required): internal bill record ID — the `id` returned
        by List Bills (V2).


        **Reverse link fields:** `at_id`/`at_reference` identify the SKU.io accounting
        transaction the record was generated from (null when the record was synced
        via the ledger pipeline instead — then `ledger_entry_id`/`ledger_entry_reference`
        are set). `sku_link_type`/`sku_link_id` identify the underlying SKU.io source
        record (e.g. a sales order or purchase order); `sku_link_label` and `sku_link_route`
        are only populated when the link was resolved through the ledger.


        Returns 404 when no bill with that ID exists.


        **Authentication:** Bearer token.


        Returns `raw_payload` (the full raw Xero payload); present only on the detail/show
        endpoint.'
      parameters:
      - name: bill
        in: path
        schema:
          type: integer
        required: true
        description: Internal bill record ID
        example: '128'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      xero_uuid:
                        type: string
                      invoice_number:
                        type: string
                      type:
                        type: string
                      reference:
                        type: string
                      status:
                        type: string
                      contact_name:
                        type: string
                      contact_id:
                        type: string
                      currency_code:
                        type: string
                      sub_total:
                        type: integer
                      total_tax:
                        type: integer
                      total:
                        type: integer
                      amount_due:
                        type: integer
                      amount_paid:
                        type: integer
                      amount_credited:
                        type: integer
                      date:
                        type: string
                      due_date:
                        type: string
                      fully_paid_on_date:
                        type: string
                        nullable: true
                      updated_date_utc:
                        type: string
                      line_items:
                        type: array
                        items:
                          type: object
                          properties:
                            description:
                              type: string
                            account_code:
                              type: string
                            item_code:
                              type: string
                            quantity:
                              type: integer
                            unit_amount:
                              type: number
                            tax_type:
                              type: string
                            tax_amount:
                              type: integer
                            line_amount:
                              type: integer
                      at_id:
                        type: integer
                      at_reference:
                        type: string
                      ledger_entry_id:
                        type: string
                        nullable: true
                      ledger_entry_reference:
                        type: string
                        nullable: true
                      sku_link_type:
                        type: string
                      sku_link_id:
                        type: integer
                      sku_link_label:
                        type: string
                        nullable: true
                      sku_link_route:
                        type: string
                        nullable: true
                      sync_status:
                        type: string
                      last_error:
                        type: string
                        nullable: true
                      url:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      raw_payload:
                        type: object
                        properties:
                          InvoiceID:
                            type: string
                          Type:
                            type: string
                          InvoiceNumber:
                            type: string
                          Reference:
                            type: string
                          Status:
                            type: string
                          LineAmountTypes:
                            type: string
                          Contact:
                            type: object
                            properties:
                              ContactID:
                                type: string
                              Name:
                                type: string
                          CurrencyCode:
                            type: string
                          SubTotal:
                            type: integer
                          TotalTax:
                            type: integer
                          Total:
                            type: integer
                          AmountDue:
                            type: integer
                          AmountPaid:
                            type: integer
                          Date:
                            type: string
                          DueDate:
                            type: string
                          LineItems:
                            type: array
                            items:
                              type: object
                              properties:
                                LineItemID:
                                  type: string
                                Description:
                                  type: string
                                Quantity:
                                  type: integer
                                UnitAmount:
                                  type: number
                                AccountCode:
                                  type: string
                                TaxType:
                                  type: string
                                TaxAmount:
                                  type: integer
                                LineAmount:
                                  type: integer
                          UpdatedDateUTC:
                            type: string
                example:
                  data:
                    id: 128
                    xero_uuid: 3f1c9a2e-8b4d-4e7f-9a2c-6d5e4f3a2b1c
                    invoice_number: BILL-0042
                    type: ACCPAY
                    reference: PO-812254
                    status: AUTHORISED
                    contact_name: Pacific Packaging Supplies
                    contact_id: 9c2d5e8f-1a4b-47c6-8d9e-3b2a1c4d5e6f
                    currency_code: USD
                    sub_total: 1250
                    total_tax: 125
                    total: 1375
                    amount_due: 1375
                    amount_paid: 0
                    amount_credited: 0
                    date: '2026-05-14T00:00:00+00:00'
                    due_date: '2026-06-13T00:00:00+00:00'
                    fully_paid_on_date: null
                    updated_date_utc: '2026-05-15T08:21:44+00:00'
                    line_items:
                    - description: Corrugated shipping boxes 12x9x4 (case of 250)
                      account_code: '310'
                      item_code: BOX-1294
                      quantity: 4
                      unit_amount: 262.5
                      tax_type: INPUT
                      tax_amount: 105
                      line_amount: 1050
                    - description: Packing tape 48mm (36 rolls)
                      account_code: '310'
                      item_code: TAPE-48
                      quantity: 2
                      unit_amount: 100
                      tax_type: INPUT
                      tax_amount: 20
                      line_amount: 200
                    at_id: 5121
                    at_reference: PO-812254
                    ledger_entry_id: null
                    ledger_entry_reference: null
                    sku_link_type: App\Models\PurchaseInvoice
                    sku_link_id: 344
                    sku_link_label: null
                    sku_link_route: null
                    sync_status: OK
                    last_error: null
                    url: https://go.xero.com/AccountsPayable/View.aspx?InvoiceID=3f1c9a2e-8b4d-4e7f-9a2c-6d5e4f3a2b1c
                    created_at: '2026-05-14T18:03:29+00:00'
                    updated_at: '2026-06-01T02:15:07+00:00'
                    raw_payload:
                      InvoiceID: 3f1c9a2e-8b4d-4e7f-9a2c-6d5e4f3a2b1c
                      Type: ACCPAY
                      InvoiceNumber: BILL-0042
                      Reference: PO-812254
                      Status: AUTHORISED
                      LineAmountTypes: Exclusive
                      Contact:
                        ContactID: 9c2d5e8f-1a4b-47c6-8d9e-3b2a1c4d5e6f
                        Name: Pacific Packaging Supplies
                      CurrencyCode: USD
                      SubTotal: 1250
                      TotalTax: 125
                      Total: 1375
                      AmountDue: 1375
                      AmountPaid: 0
                      Date: '2026-05-14'
                      DueDate: '2026-06-13'
                      LineItems:
                      - LineItemID: 1d2c3b4a-5e6f-4a7b-8c9d-0e1f2a3b4c5d
                        Description: Corrugated shipping boxes 12x9x4 (case of 250)
                        Quantity: 4
                        UnitAmount: 262.5
                        AccountCode: '310'
                        TaxType: INPUT
                        TaxAmount: 105
                        LineAmount: 1050
                      UpdatedDateUTC: '2026-05-15T08:21:44+00:00'
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: object
                    properties:
                      Modules\Xero\Entities\XeroBill:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: array
                  status:
                    type: string
                  message:
                    type: string
                example:
                  errors:
                    Modules\Xero\Entities\XeroBill:
                    - message: No query results for model [Modules\Xero\Entities\XeroBill]
                        999999
                      code: NotFound
                      data: []
                  status: failure
                  message: No query results for model [Modules\Xero\Entities\XeroBill]
                    999999
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-xero-v2-bills-bill
  /api/xero/v2/contacts/{contact}:
    get:
      tags:
      - Xero
      summary: Get Contact (V2)
      description: 'Get a single synced Xero contact — name, primary email/phone,
        customer/supplier flags, status, addresses, the reverse link to the SKU.io
        customer or supplier it maps to (`sku_link_type`/`sku_link_id`), and sync
        metadata (`last_error`, plus `url`, a deep link to the contact in Xero).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Contacts are not a ledger sync target, so there is no accounting-transaction
        link — the SKU.io side is the contact''s own link to a customer or supplier
        record.


        **Path parameters:**

        - `contact` (integer, required): internal contact record ID — the `id` returned
        by List Contacts (V2).


        Returns 404 when no contact with that ID exists.


        **Authentication:** Bearer token.


        Also returns `sku_link_reference` — a human-readable label for the linked
        SKU.io customer or supplier.'
      parameters:
      - name: contact
        in: path
        schema:
          type: integer
        required: true
        description: Internal contact record ID
        example: '87'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      contact_id:
                        type: string
                      name:
                        type: string
                      email:
                        type: string
                      phone:
                        type: string
                      is_customer:
                        type: boolean
                      is_supplier:
                        type: boolean
                      status:
                        type: string
                      addresses:
                        type: array
                        items:
                          type: object
                          properties:
                            type:
                              type: string
                            line1:
                              type: string
                            line2:
                              type: string
                            line3:
                              type: string
                              nullable: true
                            city:
                              type: string
                            postal_code:
                              type: string
                            country:
                              type: string
                      sku_link_type:
                        type: string
                      sku_link_id:
                        type: integer
                      sku_link_reference:
                        type: string
                      last_error:
                        type: string
                        nullable: true
                      url:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 87
                    contact_id: d4e5f6a7-b8c9-40d1-a2b3-c4d5e6f7a8b9
                    name: Acme Retail Group
                    email: accounts@acmeretail.com
                    phone: 1 415 5550172
                    is_customer: true
                    is_supplier: false
                    status: ACTIVE
                    addresses:
                    - type: STREET
                      line1: 2251 Harrison St
                      line2: Suite 400
                      line3: null
                      city: San Francisco
                      postal_code: '94110'
                      country: United States
                    - type: POBOX
                      line1: PO Box 7712
                      line2: null
                      line3: null
                      city: San Francisco
                      postal_code: '94120'
                      country: United States
                    sku_link_type: App\Models\Customer
                    sku_link_id: 412
                    sku_link_reference: Acme Corp
                    last_error: null
                    url: https://go.xero.com/Contacts/View/d4e5f6a7-b8c9-40d1-a2b3-c4d5e6f7a8b9
                    created_at: '2026-02-03T11:18:52+00:00'
                    updated_at: '2026-06-28T04:02:19+00:00'
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: object
                    properties:
                      Modules\Xero\Entities\XeroContact:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: array
                  status:
                    type: string
                  message:
                    type: string
                example:
                  errors:
                    Modules\Xero\Entities\XeroContact:
                    - message: No query results for model [Modules\Xero\Entities\XeroContact]
                        999999
                      code: NotFound
                      data: []
                  status: failure
                  message: No query results for model [Modules\Xero\Entities\XeroContact]
                    999999
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-xero-v2-contacts-contact
  /api/xero/v2/credit-notes/{creditNote}:
    get:
      tags:
      - Xero
      summary: Get Credit Note (V2)
      description: 'Get a single synced Xero credit note (ACCRECCREDIT) — header fields
        including `remaining_credit`, line items, the reverse link to the SKU.io record
        it was generated from, and sync metadata (`sync_status`, `last_error`, and
        `url`, a deep link to the credit note in Xero). Monetary amounts are in the
        credit note''s currency; datetimes are UTC ISO-8601.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Path parameters:**

        - `creditNote` (integer, required): internal credit note record ID — the `id`
        returned by List Credit Notes (V2).


        **Reverse link fields:** `at_id`/`at_reference` identify the SKU.io accounting
        transaction the record was generated from (null when the record was synced
        via the ledger pipeline instead — then `ledger_entry_id`/`ledger_entry_reference`
        are set). `sku_link_type`/`sku_link_id` identify the underlying SKU.io source
        record (e.g. a sales order or purchase order); `sku_link_label` and `sku_link_route`
        are only populated when the link was resolved through the ledger.


        Returns 404 when no credit note with that ID exists.


        **Authentication:** Bearer token.


        Returns `raw_payload` (the full raw Xero payload); present only on the detail/show
        endpoint.'
      parameters:
      - name: creditNote
        in: path
        schema:
          type: integer
        required: true
        description: Internal credit note record ID
        example: '56'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      xero_uuid:
                        type: string
                      credit_note_number:
                        type: string
                      type:
                        type: string
                      reference:
                        type: string
                      status:
                        type: string
                      contact_name:
                        type: string
                      contact_id:
                        type: string
                      currency_code:
                        type: string
                      currency_rate:
                        type: integer
                      sub_total:
                        type: number
                      total_tax:
                        type: number
                      total:
                        type: integer
                      remaining_credit:
                        type: integer
                      date:
                        type: string
                      fully_paid_on_date:
                        type: string
                      updated_date_utc:
                        type: string
                      line_items:
                        type: array
                        items:
                          type: object
                          properties:
                            description:
                              type: string
                            account_code:
                              type: string
                            item_code:
                              type: string
                            quantity:
                              type: integer
                            unit_amount:
                              type: number
                            tax_type:
                              type: string
                            tax_amount:
                              type: number
                            line_amount:
                              type: number
                      at_id:
                        type: integer
                      at_reference:
                        type: string
                      ledger_entry_id:
                        type: string
                        nullable: true
                      ledger_entry_reference:
                        type: string
                        nullable: true
                      sku_link_type:
                        type: string
                      sku_link_id:
                        type: integer
                      sku_link_label:
                        type: string
                        nullable: true
                      sku_link_route:
                        type: string
                        nullable: true
                      sync_status:
                        type: string
                      last_error:
                        type: string
                        nullable: true
                      url:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      raw_payload:
                        type: object
                        properties:
                          CreditNoteID:
                            type: string
                          Type:
                            type: string
                          CreditNoteNumber:
                            type: string
                          Reference:
                            type: string
                          Status:
                            type: string
                          LineAmountTypes:
                            type: string
                          Contact:
                            type: object
                            properties:
                              ContactID:
                                type: string
                              Name:
                                type: string
                          CurrencyCode:
                            type: string
                          CurrencyRate:
                            type: integer
                          SubTotal:
                            type: number
                          TotalTax:
                            type: number
                          Total:
                            type: integer
                          RemainingCredit:
                            type: integer
                          Date:
                            type: string
                          LineItems:
                            type: array
                            items:
                              type: object
                              properties:
                                LineItemID:
                                  type: string
                                Description:
                                  type: string
                                Quantity:
                                  type: integer
                                UnitAmount:
                                  type: number
                                AccountCode:
                                  type: string
                                TaxType:
                                  type: string
                                TaxAmount:
                                  type: number
                                LineAmount:
                                  type: number
                          UpdatedDateUTC:
                            type: string
                example:
                  data:
                    id: 56
                    xero_uuid: a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d
                    credit_note_number: CN-0218
                    type: ACCRECCREDIT
                    reference: C-100308254
                    status: PAID
                    contact_name: Acme Retail Group
                    contact_id: 7b1e4f3a-2c8d-49e5-b6a7-1f2e3d4c5b6a
                    currency_code: USD
                    currency_rate: 1
                    sub_total: 45.45
                    total_tax: 4.55
                    total: 50
                    remaining_credit: 0
                    date: '2026-06-10T00:00:00+00:00'
                    fully_paid_on_date: '2026-06-12T00:00:00+00:00'
                    updated_date_utc: '2026-06-12T09:33:07+00:00'
                    line_items:
                    - description: Return — LED strip light kit 5m (damaged in transit)
                      account_code: '200'
                      item_code: LED-5M-WW
                      quantity: 1
                      unit_amount: 45.45
                      tax_type: OUTPUT
                      tax_amount: 4.55
                      line_amount: 45.45
                    at_id: 5236
                    at_reference: C-100308254
                    ledger_entry_id: null
                    ledger_entry_reference: null
                    sku_link_type: App\Models\SalesCredit
                    sku_link_id: 1187
                    sku_link_label: null
                    sku_link_route: null
                    sync_status: OK
                    last_error: null
                    url: https://go.xero.com/AccountsReceivable/ViewCreditNote.aspx?creditNoteID=a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d
                    created_at: '2026-06-10T14:47:33+00:00'
                    updated_at: '2026-06-12T09:33:18+00:00'
                    raw_payload:
                      CreditNoteID: a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d
                      Type: ACCRECCREDIT
                      CreditNoteNumber: CN-0031
                      Reference: C-100308254
                      Status: PAID
                      LineAmountTypes: Exclusive
                      Contact:
                        ContactID: d4e5f6a7-b8c9-40d1-a2b3-c4d5e6f7a8b9
                        Name: Acme Retail Group
                      CurrencyCode: USD
                      CurrencyRate: 1
                      SubTotal: 45.45
                      TotalTax: 4.55
                      Total: 50
                      RemainingCredit: 0
                      Date: '2026-05-20'
                      LineItems:
                      - LineItemID: 7f6e5d4c-3b2a-4190-8f7e-6d5c4b3a2190
                        Description: Return credit — Widget Pro
                        Quantity: 1
                        UnitAmount: 45.45
                        AccountCode: '200'
                        TaxType: OUTPUT
                        TaxAmount: 4.55
                        LineAmount: 45.45
                      UpdatedDateUTC: '2026-05-21T10:05:00+00:00'
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: object
                    properties:
                      Modules\Xero\Entities\XeroCreditNote:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: array
                  status:
                    type: string
                  message:
                    type: string
                example:
                  errors:
                    Modules\Xero\Entities\XeroCreditNote:
                    - message: No query results for model [Modules\Xero\Entities\XeroCreditNote]
                        999999
                      code: NotFound
                      data: []
                  status: failure
                  message: No query results for model [Modules\Xero\Entities\XeroCreditNote]
                    999999
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-xero-v2-credit-notes-creditnote
  /api/xero/v2/invoices/{invoice}:
    get:
      tags:
      - Xero
      summary: Get Invoice (V2)
      description: 'Get a single synced Xero sales invoice (ACCREC) — header fields,
        line items, the reverse link to the SKU.io record it was generated from, and
        sync metadata (`sync_status`, `last_error`, and `url`, a deep link to the
        invoice in Xero). Monetary amounts are in the invoice''s currency; datetimes
        are UTC ISO-8601.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Path parameters:**

        - `invoice` (integer, required): internal invoice record ID — the `id` returned
        by List Invoices (V2).


        **Reverse link fields:** `at_id`/`at_reference` identify the SKU.io accounting
        transaction the record was generated from (null when the record was synced
        via the ledger pipeline instead — then `ledger_entry_id`/`ledger_entry_reference`
        are set). `sku_link_type`/`sku_link_id` identify the underlying SKU.io source
        record (e.g. a sales order or purchase order); `sku_link_label` and `sku_link_route`
        are only populated when the link was resolved through the ledger.


        Returns 404 when no invoice with that ID exists.


        **Authentication:** Bearer token.


        Returns `raw_payload` (the full raw Xero payload); present only on the detail/show
        endpoint.'
      parameters:
      - name: invoice
        in: path
        schema:
          type: integer
        required: true
        description: Internal invoice record ID
        example: '342'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      xero_uuid:
                        type: string
                      invoice_number:
                        type: string
                      type:
                        type: string
                      reference:
                        type: string
                      status:
                        type: string
                      contact_name:
                        type: string
                      contact_id:
                        type: string
                      currency_code:
                        type: string
                      sub_total:
                        type: number
                      total_tax:
                        type: number
                      total:
                        type: number
                      amount_due:
                        type: integer
                      amount_paid:
                        type: number
                      amount_credited:
                        type: integer
                      date:
                        type: string
                      due_date:
                        type: string
                      fully_paid_on_date:
                        type: string
                      updated_date_utc:
                        type: string
                      line_items:
                        type: array
                        items:
                          type: object
                          properties:
                            description:
                              type: string
                            account_code:
                              type: string
                            item_code:
                              type: string
                            quantity:
                              type: integer
                            unit_amount:
                              type: number
                            tax_type:
                              type: string
                            tax_amount:
                              type: number
                            line_amount:
                              type: number
                      at_id:
                        type: integer
                      at_reference:
                        type: string
                      ledger_entry_id:
                        type: string
                        nullable: true
                      ledger_entry_reference:
                        type: string
                        nullable: true
                      sku_link_type:
                        type: string
                      sku_link_id:
                        type: integer
                      sku_link_label:
                        type: string
                        nullable: true
                      sku_link_route:
                        type: string
                        nullable: true
                      sync_status:
                        type: string
                      last_error:
                        type: string
                        nullable: true
                      url:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      raw_payload:
                        type: object
                        properties:
                          InvoiceID:
                            type: string
                          Type:
                            type: string
                          InvoiceNumber:
                            type: string
                          Reference:
                            type: string
                          Status:
                            type: string
                          LineAmountTypes:
                            type: string
                          Contact:
                            type: object
                            properties:
                              ContactID:
                                type: string
                              Name:
                                type: string
                          CurrencyCode:
                            type: string
                          SubTotal:
                            type: number
                          TotalTax:
                            type: number
                          Total:
                            type: number
                          AmountDue:
                            type: integer
                          AmountPaid:
                            type: number
                          Date:
                            type: string
                          DueDate:
                            type: string
                          LineItems:
                            type: array
                            items:
                              type: object
                              properties:
                                LineItemID:
                                  type: string
                                Description:
                                  type: string
                                Quantity:
                                  type: integer
                                UnitAmount:
                                  type: number
                                AccountCode:
                                  type: string
                                TaxType:
                                  type: string
                                TaxAmount:
                                  type: number
                                LineAmount:
                                  type: number
                          UpdatedDateUTC:
                            type: string
                example:
                  data:
                    id: 342
                    xero_uuid: b3a8c7d2-4e1f-4a9b-8c6d-2f5e7a9b1c3d
                    invoice_number: INV-10427
                    type: ACCREC
                    reference: SO-100482
                    status: PAID
                    contact_name: Acme Retail Group
                    contact_id: 7b1e4f3a-2c8d-49e5-b6a7-1f2e3d4c5b6a
                    currency_code: USD
                    sub_total: 206.82
                    total_tax: 20.68
                    total: 227.5
                    amount_due: 0
                    amount_paid: 227.5
                    amount_credited: 0
                    date: '2026-06-02T00:00:00+00:00'
                    due_date: '2026-07-02T00:00:00+00:00'
                    fully_paid_on_date: '2026-06-19T00:00:00+00:00'
                    updated_date_utc: '2026-06-19T10:41:03+00:00'
                    line_items:
                    - description: LED strip light kit 5m — warm white
                      account_code: '200'
                      item_code: LED-5M-WW
                      quantity: 5
                      unit_amount: 32.5
                      tax_type: OUTPUT
                      tax_amount: 16.25
                      line_amount: 162.5
                    - description: Aluminium mounting channel 1m
                      account_code: '200'
                      item_code: ALU-CH-1M
                      quantity: 8
                      unit_amount: 5.54
                      tax_type: OUTPUT
                      tax_amount: 4.43
                      line_amount: 44.32
                    at_id: 4890
                    at_reference: SO-100482
                    ledger_entry_id: null
                    ledger_entry_reference: null
                    sku_link_type: App\Models\SalesOrder
                    sku_link_id: 100482
                    sku_link_label: null
                    sku_link_route: null
                    sync_status: OK
                    last_error: null
                    url: https://go.xero.com/AccountsReceivable/View.aspx?InvoiceID=b3a8c7d2-4e1f-4a9b-8c6d-2f5e7a9b1c3d
                    created_at: '2026-06-02T15:22:40+00:00'
                    updated_at: '2026-06-19T10:41:12+00:00'
                    raw_payload:
                      InvoiceID: b3a8c7d2-4e1f-4a9b-8c6d-2f5e7a9b1c3d
                      Type: ACCREC
                      InvoiceNumber: INV-10427
                      Reference: SO-100482
                      Status: PAID
                      LineAmountTypes: Exclusive
                      Contact:
                        ContactID: d4e5f6a7-b8c9-40d1-a2b3-c4d5e6f7a8b9
                        Name: Acme Retail Group
                      CurrencyCode: USD
                      SubTotal: 206.82
                      TotalTax: 20.68
                      Total: 227.5
                      AmountDue: 0
                      AmountPaid: 227.5
                      Date: '2026-05-14'
                      DueDate: '2026-06-13'
                      LineItems:
                      - LineItemID: 5b1e0c8a-7d2f-4e3a-9b6c-1a2b3c4d5e6f
                        Description: Widget Pro (case of 12)
                        Quantity: 1
                        UnitAmount: 206.82
                        AccountCode: '200'
                        TaxType: OUTPUT
                        TaxAmount: 20.68
                        LineAmount: 206.82
                      UpdatedDateUTC: '2026-05-15T08:21:44+00:00'
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: object
                    properties:
                      Modules\Xero\Entities\XeroInvoice:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: array
                  status:
                    type: string
                  message:
                    type: string
                example:
                  errors:
                    Modules\Xero\Entities\XeroInvoice:
                    - message: No query results for model [Modules\Xero\Entities\XeroInvoice]
                        999999
                      code: NotFound
                      data: []
                  status: failure
                  message: No query results for model [Modules\Xero\Entities\XeroInvoice]
                    999999
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-xero-v2-invoices-invoice
  /api/xero/v2/manual-journals/{manualJournal}:
    get:
      tags:
      - Xero
      summary: Get Manual Journal (V2)
      description: 'Get a single synced Xero manual journal — status, narration, journal
        lines (positive amounts are debits, negative are credits), the reverse link
        to the SKU.io record it was generated from, and sync metadata (`sync_status`,
        `last_error`, and `url`, a deep link to the journal in Xero). Datetimes are
        UTC ISO-8601.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Path parameters:**

        - `manualJournal` (integer, required): internal manual journal record ID —
        the `id` returned by List Manual Journals (V2).


        **Reverse link fields:** `at_id`/`at_reference` identify the SKU.io accounting
        transaction the record was generated from (null when the record was synced
        via the ledger pipeline instead — then `ledger_entry_id`/`ledger_entry_reference`
        are set). `sku_link_type`/`sku_link_id` identify the underlying SKU.io source
        record (e.g. a sales order or purchase order); `sku_link_label` and `sku_link_route`
        are only populated when the link was resolved through the ledger.


        Returns 404 when no manual journal with that ID exists.


        **Authentication:** Bearer token.


        Returns `raw_payload` (the full raw Xero payload); present only on the detail/show
        endpoint.'
      parameters:
      - name: manualJournal
        in: path
        schema:
          type: integer
        required: true
        description: Internal manual journal record ID
        example: '44'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      xero_uuid:
                        type: string
                      manual_journal_id:
                        type: string
                      status:
                        type: string
                      narration:
                        type: string
                      line_amount_types:
                        type: string
                      show_on_cash_basis_reports:
                        type: boolean
                      date:
                        type: string
                      updated_date_utc:
                        type: string
                      line_items:
                        type: array
                        items:
                          type: object
                          properties:
                            description:
                              type: string
                            account_code:
                              type: string
                            tax_type:
                              type: string
                            tax_amount:
                              type: integer
                            line_amount:
                              type: number
                      at_id:
                        type: string
                        nullable: true
                      at_reference:
                        type: string
                        nullable: true
                      ledger_entry_id:
                        type: integer
                      ledger_entry_reference:
                        type: string
                      sku_link_type:
                        type: string
                        nullable: true
                      sku_link_id:
                        type: string
                        nullable: true
                      sku_link_label:
                        type: string
                        nullable: true
                      sku_link_route:
                        type: string
                        nullable: true
                      sync_status:
                        type: string
                      last_error:
                        type: string
                        nullable: true
                      url:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      raw_payload:
                        type: object
                        properties:
                          ManualJournalID:
                            type: string
                          Status:
                            type: string
                          Narration:
                            type: string
                          LineAmountTypes:
                            type: string
                          ShowOnCashBasisReports:
                            type: boolean
                          Date:
                            type: string
                          JournalLines:
                            type: array
                            items:
                              type: object
                              properties:
                                LineID:
                                  type: string
                                AccountCode:
                                  type: string
                                Description:
                                  type: string
                                TaxType:
                                  type: string
                                LineAmount:
                                  type: integer
                          UpdatedDateUTC:
                            type: string
                example:
                  data:
                    id: 44
                    xero_uuid: c9d8e7f6-a5b4-43c2-9d1e-8f7a6b5c4d3e
                    manual_journal_id: c9d8e7f6-a5b4-43c2-9d1e-8f7a6b5c4d3e
                    status: POSTED
                    narration: COGS accrual — June 2026 shipped orders
                    line_amount_types: NoTax
                    show_on_cash_basis_reports: true
                    date: '2026-06-30T00:00:00+00:00'
                    updated_date_utc: '2026-07-01T01:12:56+00:00'
                    line_items:
                    - description: Cost of goods sold — June 2026
                      account_code: '500'
                      tax_type: NONE
                      tax_amount: 0
                      line_amount: 18302.45
                    - description: Inventory asset relief — June 2026
                      account_code: '630'
                      tax_type: NONE
                      tax_amount: 0
                      line_amount: -18302.45
                    at_id: null
                    at_reference: null
                    ledger_entry_id: 771
                    ledger_entry_reference: JE-2026-06-COGS
                    sku_link_type: null
                    sku_link_id: null
                    sku_link_label: null
                    sku_link_route: null
                    sync_status: OK
                    last_error: null
                    url: https://go.xero.com/Journal/View.aspx?invoiceID=c9d8e7f6-a5b4-43c2-9d1e-8f7a6b5c4d3e
                    created_at: '2026-07-01T01:12:40+00:00'
                    updated_at: '2026-07-01T01:13:02+00:00'
                    raw_payload:
                      ManualJournalID: c9d8e7f6-a5b4-43c2-9d1e-8f7a6b5c4d3e
                      Status: POSTED
                      Narration: Month-end accrual — freight in transit
                      LineAmountTypes: NoTax
                      ShowOnCashBasisReports: true
                      Date: '2026-05-31'
                      JournalLines:
                      - LineID: 0a1b2c3d-4e5f-4061-8a7b-2c3d4e5f6071
                        AccountCode: '310'
                        Description: Freight accrual
                        TaxType: NONE
                        LineAmount: 320
                      - LineID: 1b2c3d4e-5f60-4172-9b8c-3d4e5f607182
                        AccountCode: '800'
                        Description: Accrued liabilities
                        TaxType: NONE
                        LineAmount: -320
                      UpdatedDateUTC: '2026-06-01T02:15:07+00:00'
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: object
                    properties:
                      Modules\Xero\Entities\XeroManualJournal:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: array
                  status:
                    type: string
                  message:
                    type: string
                example:
                  errors:
                    Modules\Xero\Entities\XeroManualJournal:
                    - message: No query results for model [Modules\Xero\Entities\XeroManualJournal]
                        999999
                      code: NotFound
                      data: []
                  status: failure
                  message: No query results for model [Modules\Xero\Entities\XeroManualJournal]
                    999999
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-xero-v2-manual-journals-manualjournal
  /api/xero/v2/payments/{payment}:
    get:
      tags:
      - Xero
      summary: Get Payment (V2)
      description: 'Get a single synced Xero payment — amount, bank account, reconciliation
        state, the Xero invoice it was applied to (`invoice_id`/`invoice_number`),
        the reverse link to the SKU.io payment''s source record (`sku_link_type`/`sku_link_id`/`sku_link_reference`),
        and sync metadata. Payments have no line items and no accounting-transaction
        link; sync health is derived from `last_error` (null = OK). Datetimes are
        UTC ISO-8601.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Path parameters:**

        - `payment` (integer, required): internal payment record ID — the `id` returned
        by List Payments (V2).


        Returns 404 when no payment with that ID exists.


        **Authentication:** Bearer token.


        Returns `raw_payload` (the full raw Xero payload); present only on the detail/show
        endpoint.'
      parameters:
      - name: payment
        in: path
        schema:
          type: integer
        required: true
        description: Internal payment record ID
        example: '519'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      payment_id:
                        type: string
                      reference:
                        type: string
                      status:
                        type: string
                      payment_type:
                        type: string
                      amount:
                        type: number
                      bank_amount:
                        type: number
                      currency_rate:
                        type: integer
                      is_reconciled:
                        type: boolean
                      bank_account_id:
                        type: string
                      bank_account_code:
                        type: string
                      bank_account_name:
                        type: string
                      invoice_id:
                        type: string
                      invoice_number:
                        type: string
                      date:
                        type: string
                      updated_date_utc:
                        type: string
                      sku_link_type:
                        type: string
                      sku_link_id:
                        type: integer
                      sku_link_reference:
                        type: string
                      last_error:
                        type: string
                        nullable: true
                      url:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      raw_payload:
                        type: object
                        properties:
                          PaymentID:
                            type: string
                          Reference:
                            type: string
                          Status:
                            type: string
                          PaymentType:
                            type: string
                          Amount:
                            type: number
                          BankAmount:
                            type: number
                          CurrencyRate:
                            type: integer
                          IsReconciled:
                            type: boolean
                          Date:
                            type: string
                          Account:
                            type: object
                            properties:
                              AccountID:
                                type: string
                              Code:
                                type: string
                              Name:
                                type: string
                          Invoice:
                            type: object
                            properties:
                              InvoiceID:
                                type: string
                              InvoiceNumber:
                                type: string
                          UpdatedDateUTC:
                            type: string
                example:
                  data:
                    id: 519
                    payment_id: e2f3a4b5-c6d7-48e9-8f0a-1b2c3d4e5f6a
                    reference: PAY-4471
                    status: AUTHORISED
                    payment_type: ACCRECPAYMENT
                    amount: 227.5
                    bank_amount: 227.5
                    currency_rate: 1
                    is_reconciled: true
                    bank_account_id: f1e2d3c4-b5a6-4798-8c9d-0a1b2c3d4e5f
                    bank_account_code: 090
                    bank_account_name: Business Checking
                    invoice_id: b3a8c7d2-4e1f-4a9b-8c6d-2f5e7a9b1c3d
                    invoice_number: INV-10427
                    date: '2026-06-19T00:00:00+00:00'
                    updated_date_utc: '2026-06-19T10:40:58+00:00'
                    sku_link_type: App\Models\SalesOrder
                    sku_link_id: 100482
                    sku_link_reference: 114-4382991-7620254
                    last_error: null
                    url: null
                    created_at: '2026-06-19T10:41:20+00:00'
                    updated_at: '2026-06-19T10:41:20+00:00'
                    raw_payload:
                      PaymentID: e1f2a3b4-c5d6-4e7f-8a9b-0c1d2e3f4a5b
                      Reference: PAY-4471
                      Status: AUTHORISED
                      PaymentType: ACCRECPAYMENT
                      Amount: 227.5
                      BankAmount: 227.5
                      CurrencyRate: 1
                      IsReconciled: true
                      Date: '2026-06-02'
                      Account:
                        AccountID: 6a5b4c3d-2e1f-4093-8a7b-6c5d4e3f2091
                        Code: 090
                        Name: Business Checking
                      Invoice:
                        InvoiceID: b3a8c7d2-4e1f-4a9b-8c6d-2f5e7a9b1c3d
                        InvoiceNumber: INV-10427
                      UpdatedDateUTC: '2026-06-02T09:30:11+00:00'
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: object
                    properties:
                      Modules\Xero\Entities\XeroPayment:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: array
                  status:
                    type: string
                  message:
                    type: string
                example:
                  errors:
                    Modules\Xero\Entities\XeroPayment:
                    - message: No query results for model [Modules\Xero\Entities\XeroPayment]
                        999999
                      code: NotFound
                      data: []
                  status: failure
                  message: No query results for model [Modules\Xero\Entities\XeroPayment]
                    999999
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-xero-v2-payments-payment
  /api/xero/v2/purchase-orders/{purchaseOrder}:
    get:
      tags:
      - Xero
      summary: Get Purchase Order (V2)
      description: 'Get a single synced Xero purchase order — header and delivery
        fields, line items, the reverse link to the SKU.io accounting transaction
        and purchase order it was generated from (`at_id`/`at_reference`, `sku_link_type`/`sku_link_id`),
        and sync metadata (`sync_status`, `last_error`, and `url`, a deep link to
        the purchase order in Xero). Monetary amounts are in the order''s currency;
        datetimes are UTC ISO-8601.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Path parameters:**

        - `purchaseOrder` (integer, required): internal purchase order record ID —
        the `id` returned by List Purchase Orders (V2).


        Returns 404 when no purchase order with that ID exists.


        **Authentication:** Bearer token.


        Returns `raw_payload` (the full raw Xero payload); present only on the detail/show
        endpoint.'
      parameters:
      - name: purchaseOrder
        in: path
        schema:
          type: integer
        required: true
        description: Internal purchase order record ID
        example: '73'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      xero_uuid:
                        type: string
                      purchase_order_number:
                        type: string
                      reference:
                        type: string
                      status:
                        type: string
                      contact_name:
                        type: string
                      contact_id:
                        type: string
                      attention_to:
                        type: string
                      telephone:
                        type: string
                      delivery_address:
                        type: string
                      delivery_instructions:
                        type: string
                      currency_code:
                        type: string
                      currency_rate:
                        type: integer
                      sub_total:
                        type: integer
                      total_tax:
                        type: integer
                      total:
                        type: integer
                      date:
                        type: string
                      delivery_date:
                        type: string
                      expected_arrival_date:
                        type: string
                      updated_date_utc:
                        type: string
                      line_items:
                        type: array
                        items:
                          type: object
                          properties:
                            description:
                              type: string
                            account_code:
                              type: string
                            item_code:
                              type: string
                            quantity:
                              type: integer
                            unit_amount:
                              type: number
                            tax_type:
                              type: string
                            tax_amount:
                              type: integer
                            line_amount:
                              type: integer
                      at_id:
                        type: integer
                      at_reference:
                        type: string
                      sku_link_type:
                        type: string
                      sku_link_id:
                        type: integer
                      sync_status:
                        type: string
                      last_error:
                        type: string
                        nullable: true
                      url:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      raw_payload:
                        type: object
                        properties:
                          PurchaseOrderID:
                            type: string
                          PurchaseOrderNumber:
                            type: string
                          Reference:
                            type: string
                          Status:
                            type: string
                          LineAmountTypes:
                            type: string
                          Contact:
                            type: object
                            properties:
                              ContactID:
                                type: string
                              Name:
                                type: string
                          CurrencyCode:
                            type: string
                          CurrencyRate:
                            type: integer
                          SubTotal:
                            type: integer
                          TotalTax:
                            type: integer
                          Total:
                            type: integer
                          Date:
                            type: string
                          DeliveryDate:
                            type: string
                          LineItems:
                            type: array
                            items:
                              type: object
                              properties:
                                LineItemID:
                                  type: string
                                Description:
                                  type: string
                                Quantity:
                                  type: integer
                                UnitAmount:
                                  type: number
                                AccountCode:
                                  type: string
                                TaxType:
                                  type: string
                                TaxAmount:
                                  type: integer
                                LineAmount:
                                  type: integer
                          UpdatedDateUTC:
                            type: string
                example:
                  data:
                    id: 73
                    xero_uuid: d7c6b5a4-e3f2-41a0-9b8c-7d6e5f4a3b2c
                    purchase_order_number: PO-812254
                    reference: Restock — Q3 packaging
                    status: BILLED
                    contact_name: Pacific Packaging Supplies
                    contact_id: 9c2d5e8f-1a4b-47c6-8d9e-3b2a1c4d5e6f
                    attention_to: Receiving Dept
                    telephone: 1 628 5550194
                    delivery_address: 48 Industrial Way, Oakland, CA 94607, United
                      States
                    delivery_instructions: Dock 3 — deliveries 8am-2pm only
                    currency_code: USD
                    currency_rate: 1
                    sub_total: 1250
                    total_tax: 125
                    total: 1375
                    date: '2026-05-08T00:00:00+00:00'
                    delivery_date: '2026-05-20T00:00:00+00:00'
                    expected_arrival_date: '2026-05-22T00:00:00+00:00'
                    updated_date_utc: '2026-05-15T08:20:31+00:00'
                    line_items:
                    - description: Corrugated shipping boxes 12x9x4 (case of 250)
                      account_code: '310'
                      item_code: BOX-1294
                      quantity: 4
                      unit_amount: 262.5
                      tax_type: INPUT
                      tax_amount: 105
                      line_amount: 1050
                    - description: Packing tape 48mm (36 rolls)
                      account_code: '310'
                      item_code: TAPE-48
                      quantity: 2
                      unit_amount: 100
                      tax_type: INPUT
                      tax_amount: 20
                      line_amount: 200
                    at_id: 5098
                    at_reference: PO-812254
                    sku_link_type: App\Models\PurchaseOrder
                    sku_link_id: 2254
                    sync_status: OK
                    last_error: null
                    url: https://go.xero.com/Accounts/Payable/PurchaseOrders/View/d7c6b5a4-e3f2-41a0-9b8c-7d6e5f4a3b2c
                    created_at: '2026-05-08T16:55:12+00:00'
                    updated_at: '2026-06-01T02:15:07+00:00'
                    raw_payload:
                      PurchaseOrderID: d7c6b5a4-e3f2-41a0-9b8c-7d6e5f4a3b2c
                      PurchaseOrderNumber: PO-812254
                      Reference: Restock — Q3 packaging
                      Status: BILLED
                      LineAmountTypes: Exclusive
                      Contact:
                        ContactID: 9c2d5e8f-1a4b-47c6-8d9e-3b2a1c4d5e6f
                        Name: Pacific Packaging Supplies
                      CurrencyCode: USD
                      CurrencyRate: 1
                      SubTotal: 1250
                      TotalTax: 125
                      Total: 1375
                      Date: '2026-05-10'
                      DeliveryDate: '2026-05-24'
                      LineItems:
                      - LineItemID: 2c3d4e5f-6071-4283-9c8d-4e5f60718293
                        Description: Corrugated shipping boxes 12x9x4 (case of 250)
                        Quantity: 4
                        UnitAmount: 262.5
                        AccountCode: '310'
                        TaxType: INPUT
                        TaxAmount: 105
                        LineAmount: 1050
                      UpdatedDateUTC: '2026-05-15T08:21:44+00:00'
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: object
                    properties:
                      Modules\Xero\Entities\XeroPurchaseOrder:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: array
                  status:
                    type: string
                  message:
                    type: string
                example:
                  errors:
                    Modules\Xero\Entities\XeroPurchaseOrder:
                    - message: No query results for model [Modules\Xero\Entities\XeroPurchaseOrder]
                        999999
                      code: NotFound
                      data: []
                  status: failure
                  message: No query results for model [Modules\Xero\Entities\XeroPurchaseOrder]
                    999999
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-xero-v2-purchase-orders-purchaseorder
  /api/xero/v2/tax-rates/{taxRate}:
    get:
      tags:
      - Xero
      summary: Get Tax Rate (V2)
      description: 'Get a single synced Xero tax rate — name, tax type, effective
        rate, status, applicability flags (`can_apply_to_*`), and the individual tax
        components that make up the rate. Tax rates are configuration records: they
        carry no line items and no reverse SKU.io link.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Path parameters:**

        - `taxRate` (integer, required): internal tax rate record ID — the `id` returned
        by List Tax Rates (V2).


        Returns 404 when no tax rate with that ID exists.


        **Authentication:** Bearer token.'
      parameters:
      - name: taxRate
        in: path
        schema:
          type: integer
        required: true
        description: Internal tax rate record ID
        example: '5'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      tax_type:
                        type: string
                      effective_rate:
                        type: number
                      status:
                        type: string
                      report_tax_type:
                        type: string
                      display_tax_rate:
                        type: number
                      can_apply_to_assets:
                        type: boolean
                      can_apply_to_equity:
                        type: boolean
                      can_apply_to_expenses:
                        type: boolean
                      can_apply_to_liabilities:
                        type: boolean
                      can_apply_to_revenue:
                        type: boolean
                      tax_components:
                        type: array
                        items:
                          type: object
                          properties:
                            name:
                              type: string
                            rate:
                              type: integer
                            is_compound:
                              type: boolean
                            is_non_recoverable:
                              type: boolean
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 5
                    name: Tax on Sales (8.875%)
                    tax_type: OUTPUT
                    effective_rate: 8.875
                    status: ACTIVE
                    report_tax_type: OUTPUT
                    display_tax_rate: 8.875
                    can_apply_to_assets: true
                    can_apply_to_equity: true
                    can_apply_to_expenses: true
                    can_apply_to_liabilities: true
                    can_apply_to_revenue: true
                    tax_components:
                    - name: NY State Tax
                      rate: 4
                      is_compound: false
                      is_non_recoverable: false
                    - name: NYC Local Tax
                      rate: 4.875
                      is_compound: false
                      is_non_recoverable: false
                    created_at: '2026-01-12T08:30:00+00:00'
                    updated_at: '2026-06-20T02:15:07+00:00'
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: object
                    properties:
                      Modules\Xero\Entities\XeroTaxRate:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: array
                  status:
                    type: string
                  message:
                    type: string
                example:
                  errors:
                    Modules\Xero\Entities\XeroTaxRate:
                    - message: No query results for model [Modules\Xero\Entities\XeroTaxRate]
                        999999
                      code: NotFound
                      data: []
                  status: failure
                  message: No query results for model [Modules\Xero\Entities\XeroTaxRate]
                    999999
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-xero-v2-tax-rates-taxrate
  /api/xero/v2/accounts/{account}/activity-log:
    get:
      tags:
      - Xero
      summary: Get Account Activity Log (V2)
      description: 'Paginated change history for a single synced Xero account — one
        entry per recorded change, newest first. Each entry includes the change type
        (`event`: created / updated / deleted / bulk_upsert), the changed field values
        (`properties.attributes` = new values, `properties.old` = previous values),
        the source tag of whatever made the change (`properties.source`), an optional
        `batch_uuid` grouping changes made by one bulk operation, and `causer_name`
        (the user who triggered it; null for system/sync changes).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Query parameters:** `page`, `per_page` (default 15), `filter[event]`, `filter[source]`,
        `filter[batch_uuid]`, `filter[search]` — all optional.


        **Path parameters:** the record ID is the `id` returned by List Accounts (V2).


        Returns 404 when the record does not exist.


        **Authentication:** Bearer token.'
      parameters:
      - name: account
        in: path
        schema:
          type: integer
        required: true
        description: Internal account record ID
        example: '61'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        description:
                          type: string
                        event:
                          type: string
                        subject_type:
                          type: string
                        subject_id:
                          type: integer
                        batch_uuid:
                          type: string
                          nullable: true
                        properties:
                          type: object
                          properties:
                            source:
                              type: string
                            attributes:
                              type: object
                              properties:
                                Name:
                                  type: string
                                Status:
                                  type: string
                            old:
                              type: object
                              properties:
                                Name:
                                  type: string
                                Status:
                                  type: string
                        causer_name:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                    items:
                      type: object
                      properties:
                        url:
                          type: string
                          nullable: true
                        label:
                          type: string
                        active:
                          type: boolean
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 98211
                    description: updated
                    event: updated
                    subject_type: XeroAccount
                    subject_id: 61
                    batch_uuid: null
                    properties:
                      source: xero_sync
                      attributes:
                        Name: Shipping & Freight
                        Status: ACTIVE
                      old:
                        Name: Shipping
                        Status: ACTIVE
                    causer_name: null
                    created_at: '2026-06-18T14:32:11.000000Z'
                  - id: 97104
                    description: created
                    event: created
                    subject_type: XeroAccount
                    subject_id: 61
                    batch_uuid: 9d3f2a68-1c2b-4e0f-8a4d-6b1e2f3a4c5d
                    properties:
                      source: xero_sync
                    causer_name: Jane Smith
                    created_at: '2026-06-15T09:12:45.000000Z'
                  first_page_url: https://app.sku.io/api/xero/v2/accounts/61/activity-log?page=1
                  from: 1
                  last_page: 1
                  last_page_url: https://app.sku.io/api/xero/v2/accounts/61/activity-log?page=1
                  links:
                  - url: null
                    label: '&laquo; Previous'
                    active: false
                  - url: https://app.sku.io/api/xero/v2/accounts/61/activity-log?page=1
                    label: '1'
                    active: true
                  - url: null
                    label: Next &raquo;
                    active: false
                  next_page_url: null
                  path: https://app.sku.io/api/xero/v2/accounts/61/activity-log
                  per_page: 15
                  prev_page_url: null
                  to: 2
                  total: 2
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-xero-v2-accounts-account-activity-log
  /api/xero/v2/bills/{bill}/activity-log:
    get:
      tags:
      - Xero
      summary: Get Bill Activity Log (V2)
      description: 'Paginated change history for a single synced Xero bill — one entry
        per recorded change, newest first. Each entry includes the change type (`event`:
        created / updated / deleted / bulk_upsert), the changed field values (`properties.attributes`
        = new values, `properties.old` = previous values), the source tag of whatever
        made the change (`properties.source`), an optional `batch_uuid` grouping changes
        made by one bulk operation, and `causer_name` (the user who triggered it;
        null for system/sync changes).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Query parameters:** `page`, `per_page` (default 15), `filter[event]`, `filter[source]`,
        `filter[batch_uuid]`, `filter[search]` — all optional.


        **Path parameters:** the record ID is the `id` returned by List Bills (V2).


        Returns 404 when the record does not exist.


        **Authentication:** Bearer token.'
      parameters:
      - name: bill
        in: path
        schema:
          type: integer
        required: true
        description: Internal bill record ID
        example: '128'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        description:
                          type: string
                        event:
                          type: string
                        subject_type:
                          type: string
                        subject_id:
                          type: integer
                        batch_uuid:
                          type: string
                          nullable: true
                        properties:
                          type: object
                          properties:
                            source:
                              type: string
                            attributes:
                              type: object
                              properties:
                                Status:
                                  type: string
                                AmountDue:
                                  type: integer
                                AmountPaid:
                                  type: integer
                            old:
                              type: object
                              properties:
                                Status:
                                  type: string
                                AmountDue:
                                  type: integer
                                AmountPaid:
                                  type: integer
                        causer_name:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                    items:
                      type: object
                      properties:
                        url:
                          type: string
                          nullable: true
                        label:
                          type: string
                        active:
                          type: boolean
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 98211
                    description: updated
                    event: updated
                    subject_type: XeroBill
                    subject_id: 128
                    batch_uuid: null
                    properties:
                      source: xero_sync
                      attributes:
                        Status: PAID
                        AmountDue: 0
                        AmountPaid: 1375
                      old:
                        Status: AUTHORISED
                        AmountDue: 1375
                        AmountPaid: 0
                    causer_name: null
                    created_at: '2026-06-18T14:32:11.000000Z'
                  - id: 97104
                    description: created
                    event: created
                    subject_type: XeroBill
                    subject_id: 128
                    batch_uuid: 9d3f2a68-1c2b-4e0f-8a4d-6b1e2f3a4c5d
                    properties:
                      source: xero_sync
                    causer_name: Jane Smith
                    created_at: '2026-06-15T09:12:45.000000Z'
                  first_page_url: https://app.sku.io/api/xero/v2/bills/128/activity-log?page=1
                  from: 1
                  last_page: 1
                  last_page_url: https://app.sku.io/api/xero/v2/bills/128/activity-log?page=1
                  links:
                  - url: null
                    label: '&laquo; Previous'
                    active: false
                  - url: https://app.sku.io/api/xero/v2/bills/128/activity-log?page=1
                    label: '1'
                    active: true
                  - url: null
                    label: Next &raquo;
                    active: false
                  next_page_url: null
                  path: https://app.sku.io/api/xero/v2/bills/128/activity-log
                  per_page: 15
                  prev_page_url: null
                  to: 2
                  total: 2
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-xero-v2-bills-bill-activity-log
  /api/xero/v2/contacts/{contact}/activity-log:
    get:
      tags:
      - Xero
      summary: Get Contact Activity Log (V2)
      description: 'Paginated change history for a single synced Xero contact — one
        entry per recorded change, newest first. Each entry includes the change type
        (`event`: created / updated / deleted / bulk_upsert), the changed field values
        (`properties.attributes` = new values, `properties.old` = previous values),
        the source tag of whatever made the change (`properties.source`), an optional
        `batch_uuid` grouping changes made by one bulk operation, and `causer_name`
        (the user who triggered it; null for system/sync changes).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Query parameters:** `page`, `per_page` (default 15), `filter[event]`, `filter[source]`,
        `filter[batch_uuid]`, `filter[search]` — all optional.


        **Path parameters:** the record ID is the `id` returned by List Contacts (V2).


        Returns 404 when the record does not exist.


        **Authentication:** Bearer token.'
      parameters:
      - name: contact
        in: path
        schema:
          type: integer
        required: true
        description: Internal contact record ID
        example: '87'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        description:
                          type: string
                        event:
                          type: string
                        subject_type:
                          type: string
                        subject_id:
                          type: integer
                        batch_uuid:
                          type: string
                          nullable: true
                        properties:
                          type: object
                          properties:
                            source:
                              type: string
                            attributes:
                              type: object
                              properties:
                                Name:
                                  type: string
                                link_id:
                                  type: integer
                                link_type:
                                  type: string
                            old:
                              type: object
                              properties:
                                Name:
                                  type: string
                                link_id:
                                  type: string
                                  nullable: true
                                link_type:
                                  type: string
                                  nullable: true
                        causer_name:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                    items:
                      type: object
                      properties:
                        url:
                          type: string
                          nullable: true
                        label:
                          type: string
                        active:
                          type: boolean
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 98211
                    description: updated
                    event: updated
                    subject_type: XeroContact
                    subject_id: 87
                    batch_uuid: null
                    properties:
                      source: xero_sync
                      attributes:
                        Name: Acme Retail Group
                        link_id: 412
                        link_type: App\Models\Customer
                      old:
                        Name: Acme Retail
                        link_id: null
                        link_type: null
                    causer_name: null
                    created_at: '2026-06-18T14:32:11.000000Z'
                  - id: 97104
                    description: created
                    event: created
                    subject_type: XeroContact
                    subject_id: 87
                    batch_uuid: 9d3f2a68-1c2b-4e0f-8a4d-6b1e2f3a4c5d
                    properties:
                      source: xero_sync
                    causer_name: Jane Smith
                    created_at: '2026-06-15T09:12:45.000000Z'
                  first_page_url: https://app.sku.io/api/xero/v2/contacts/87/activity-log?page=1
                  from: 1
                  last_page: 1
                  last_page_url: https://app.sku.io/api/xero/v2/contacts/87/activity-log?page=1
                  links:
                  - url: null
                    label: '&laquo; Previous'
                    active: false
                  - url: https://app.sku.io/api/xero/v2/contacts/87/activity-log?page=1
                    label: '1'
                    active: true
                  - url: null
                    label: Next &raquo;
                    active: false
                  next_page_url: null
                  path: https://app.sku.io/api/xero/v2/contacts/87/activity-log
                  per_page: 15
                  prev_page_url: null
                  to: 2
                  total: 2
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-xero-v2-contacts-contact-activity-log
  /api/xero/v2/credit-notes/{creditNote}/activity-log:
    get:
      tags:
      - Xero
      summary: Get Credit Note Activity Log (V2)
      description: 'Paginated change history for a single synced Xero credit note
        — one entry per recorded change, newest first. Each entry includes the change
        type (`event`: created / updated / deleted / bulk_upsert), the changed field
        values (`properties.attributes` = new values, `properties.old` = previous
        values), the source tag of whatever made the change (`properties.source`),
        an optional `batch_uuid` grouping changes made by one bulk operation, and
        `causer_name` (the user who triggered it; null for system/sync changes).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Query parameters:** `page`, `per_page` (default 15), `filter[event]`, `filter[source]`,
        `filter[batch_uuid]`, `filter[search]` — all optional.


        **Path parameters:** the record ID is the `id` returned by List Credit Notes
        (V2).


        Returns 404 when the record does not exist.


        **Authentication:** Bearer token.'
      parameters:
      - name: creditNote
        in: path
        schema:
          type: integer
        required: true
        description: Internal credit note record ID
        example: '56'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        description:
                          type: string
                        event:
                          type: string
                        subject_type:
                          type: string
                        subject_id:
                          type: integer
                        batch_uuid:
                          type: string
                          nullable: true
                        properties:
                          type: object
                          properties:
                            source:
                              type: string
                            attributes:
                              type: object
                              properties:
                                Status:
                                  type: string
                                RemainingCredit:
                                  type: integer
                            old:
                              type: object
                              properties:
                                Status:
                                  type: string
                                RemainingCredit:
                                  type: integer
                        causer_name:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                    items:
                      type: object
                      properties:
                        url:
                          type: string
                          nullable: true
                        label:
                          type: string
                        active:
                          type: boolean
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 98211
                    description: updated
                    event: updated
                    subject_type: XeroCreditNote
                    subject_id: 56
                    batch_uuid: null
                    properties:
                      source: xero_sync
                      attributes:
                        Status: PAID
                        RemainingCredit: 0
                      old:
                        Status: AUTHORISED
                        RemainingCredit: 50
                    causer_name: null
                    created_at: '2026-06-18T14:32:11.000000Z'
                  - id: 97104
                    description: created
                    event: created
                    subject_type: XeroCreditNote
                    subject_id: 56
                    batch_uuid: 9d3f2a68-1c2b-4e0f-8a4d-6b1e2f3a4c5d
                    properties:
                      source: xero_sync
                    causer_name: Jane Smith
                    created_at: '2026-06-15T09:12:45.000000Z'
                  first_page_url: https://app.sku.io/api/xero/v2/credit-notes/56/activity-log?page=1
                  from: 1
                  last_page: 1
                  last_page_url: https://app.sku.io/api/xero/v2/credit-notes/56/activity-log?page=1
                  links:
                  - url: null
                    label: '&laquo; Previous'
                    active: false
                  - url: https://app.sku.io/api/xero/v2/credit-notes/56/activity-log?page=1
                    label: '1'
                    active: true
                  - url: null
                    label: Next &raquo;
                    active: false
                  next_page_url: null
                  path: https://app.sku.io/api/xero/v2/credit-notes/56/activity-log
                  per_page: 15
                  prev_page_url: null
                  to: 2
                  total: 2
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-xero-v2-credit-notes-creditnote-activity-log
  /api/xero/v2/invoices/{invoice}/activity-log:
    get:
      tags:
      - Xero
      summary: Get Invoice Activity Log (V2)
      description: 'Paginated change history for a single synced Xero invoice — one
        entry per recorded change, newest first. Each entry includes the change type
        (`event`: created / updated / deleted / bulk_upsert), the changed field values
        (`properties.attributes` = new values, `properties.old` = previous values),
        the source tag of whatever made the change (`properties.source`), an optional
        `batch_uuid` grouping changes made by one bulk operation, and `causer_name`
        (the user who triggered it; null for system/sync changes).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Query parameters:** `page`, `per_page` (default 15), `filter[event]`, `filter[source]`,
        `filter[batch_uuid]`, `filter[search]` — all optional.


        **Path parameters:** the record ID is the `id` returned by List Invoices (V2).


        Returns 404 when the record does not exist.


        **Authentication:** Bearer token.'
      parameters:
      - name: invoice
        in: path
        schema:
          type: integer
        required: true
        description: Internal invoice record ID
        example: '342'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        description:
                          type: string
                        event:
                          type: string
                        subject_type:
                          type: string
                        subject_id:
                          type: integer
                        batch_uuid:
                          type: string
                          nullable: true
                        properties:
                          type: object
                          properties:
                            source:
                              type: string
                            attributes:
                              type: object
                              properties:
                                Status:
                                  type: string
                                AmountDue:
                                  type: integer
                                AmountPaid:
                                  type: number
                            old:
                              type: object
                              properties:
                                Status:
                                  type: string
                                AmountDue:
                                  type: number
                                AmountPaid:
                                  type: integer
                        causer_name:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                    items:
                      type: object
                      properties:
                        url:
                          type: string
                          nullable: true
                        label:
                          type: string
                        active:
                          type: boolean
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 98211
                    description: updated
                    event: updated
                    subject_type: XeroInvoice
                    subject_id: 342
                    batch_uuid: null
                    properties:
                      source: xero_sync
                      attributes:
                        Status: PAID
                        AmountDue: 0
                        AmountPaid: 227.5
                      old:
                        Status: AUTHORISED
                        AmountDue: 227.5
                        AmountPaid: 0
                    causer_name: null
                    created_at: '2026-06-18T14:32:11.000000Z'
                  - id: 97104
                    description: created
                    event: created
                    subject_type: XeroInvoice
                    subject_id: 342
                    batch_uuid: 9d3f2a68-1c2b-4e0f-8a4d-6b1e2f3a4c5d
                    properties:
                      source: xero_sync
                    causer_name: Jane Smith
                    created_at: '2026-06-15T09:12:45.000000Z'
                  first_page_url: https://app.sku.io/api/xero/v2/invoices/342/activity-log?page=1
                  from: 1
                  last_page: 1
                  last_page_url: https://app.sku.io/api/xero/v2/invoices/342/activity-log?page=1
                  links:
                  - url: null
                    label: '&laquo; Previous'
                    active: false
                  - url: https://app.sku.io/api/xero/v2/invoices/342/activity-log?page=1
                    label: '1'
                    active: true
                  - url: null
                    label: Next &raquo;
                    active: false
                  next_page_url: null
                  path: https://app.sku.io/api/xero/v2/invoices/342/activity-log
                  per_page: 15
                  prev_page_url: null
                  to: 2
                  total: 2
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-xero-v2-invoices-invoice-activity-log
  /api/xero/v2/manual-journals/{manualJournal}/activity-log:
    get:
      tags:
      - Xero
      summary: Get Manual Journal Activity Log (V2)
      description: 'Paginated change history for a single synced Xero manual journal
        — one entry per recorded change, newest first. Each entry includes the change
        type (`event`: created / updated / deleted / bulk_upsert), the changed field
        values (`properties.attributes` = new values, `properties.old` = previous
        values), the source tag of whatever made the change (`properties.source`),
        an optional `batch_uuid` grouping changes made by one bulk operation, and
        `causer_name` (the user who triggered it; null for system/sync changes).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Query parameters:** `page`, `per_page` (default 15), `filter[event]`, `filter[source]`,
        `filter[batch_uuid]`, `filter[search]` — all optional.


        **Path parameters:** the record ID is the `id` returned by List Manual Journals
        (V2).


        Returns 404 when the record does not exist.


        **Authentication:** Bearer token.'
      parameters:
      - name: manualJournal
        in: path
        schema:
          type: integer
        required: true
        description: Internal manual journal record ID
        example: '44'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        description:
                          type: string
                        event:
                          type: string
                        subject_type:
                          type: string
                        subject_id:
                          type: integer
                        batch_uuid:
                          type: string
                          nullable: true
                        properties:
                          type: object
                          properties:
                            source:
                              type: string
                            attributes:
                              type: object
                              properties:
                                Status:
                                  type: string
                                sync_status:
                                  type: string
                            old:
                              type: object
                              properties:
                                Status:
                                  type: string
                                sync_status:
                                  type: string
                                  nullable: true
                        causer_name:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                    items:
                      type: object
                      properties:
                        url:
                          type: string
                          nullable: true
                        label:
                          type: string
                        active:
                          type: boolean
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 98211
                    description: updated
                    event: updated
                    subject_type: XeroManualJournal
                    subject_id: 44
                    batch_uuid: null
                    properties:
                      source: xero_sync
                      attributes:
                        Status: POSTED
                        sync_status: OK
                      old:
                        Status: DRAFT
                        sync_status: null
                    causer_name: null
                    created_at: '2026-06-18T14:32:11.000000Z'
                  - id: 97104
                    description: created
                    event: created
                    subject_type: XeroManualJournal
                    subject_id: 44
                    batch_uuid: 9d3f2a68-1c2b-4e0f-8a4d-6b1e2f3a4c5d
                    properties:
                      source: xero_sync
                    causer_name: Jane Smith
                    created_at: '2026-06-15T09:12:45.000000Z'
                  first_page_url: https://app.sku.io/api/xero/v2/manual-journals/44/activity-log?page=1
                  from: 1
                  last_page: 1
                  last_page_url: https://app.sku.io/api/xero/v2/manual-journals/44/activity-log?page=1
                  links:
                  - url: null
                    label: '&laquo; Previous'
                    active: false
                  - url: https://app.sku.io/api/xero/v2/manual-journals/44/activity-log?page=1
                    label: '1'
                    active: true
                  - url: null
                    label: Next &raquo;
                    active: false
                  next_page_url: null
                  path: https://app.sku.io/api/xero/v2/manual-journals/44/activity-log
                  per_page: 15
                  prev_page_url: null
                  to: 2
                  total: 2
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-xero-v2-manual-journals-manualjournal-activity-log
  /api/xero/v2/payments/{payment}/activity-log:
    get:
      tags:
      - Xero
      summary: Get Payment Activity Log (V2)
      description: 'Paginated change history for a single synced Xero payment — one
        entry per recorded change, newest first. Each entry includes the change type
        (`event`: created / updated / deleted / bulk_upsert), the changed field values
        (`properties.attributes` = new values, `properties.old` = previous values),
        the source tag of whatever made the change (`properties.source`), an optional
        `batch_uuid` grouping changes made by one bulk operation, and `causer_name`
        (the user who triggered it; null for system/sync changes).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Query parameters:** `page`, `per_page` (default 15), `filter[event]`, `filter[source]`,
        `filter[batch_uuid]`, `filter[search]` — all optional.


        **Path parameters:** the record ID is the `id` returned by List Payments (V2).


        Returns 404 when the record does not exist.


        **Authentication:** Bearer token.'
      parameters:
      - name: payment
        in: path
        schema:
          type: integer
        required: true
        description: Internal payment record ID
        example: '519'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        description:
                          type: string
                        event:
                          type: string
                        subject_type:
                          type: string
                        subject_id:
                          type: integer
                        batch_uuid:
                          type: string
                          nullable: true
                        properties:
                          type: object
                          properties:
                            source:
                              type: string
                            attributes:
                              type: object
                              properties:
                                PaymentStatus:
                                  type: string
                                IsReconciled:
                                  type: boolean
                            old:
                              type: object
                              properties:
                                PaymentStatus:
                                  type: string
                                IsReconciled:
                                  type: boolean
                        causer_name:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                    items:
                      type: object
                      properties:
                        url:
                          type: string
                          nullable: true
                        label:
                          type: string
                        active:
                          type: boolean
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 98211
                    description: updated
                    event: updated
                    subject_type: XeroPayment
                    subject_id: 519
                    batch_uuid: null
                    properties:
                      source: xero_sync
                      attributes:
                        PaymentStatus: AUTHORISED
                        IsReconciled: true
                      old:
                        PaymentStatus: AUTHORISED
                        IsReconciled: false
                    causer_name: null
                    created_at: '2026-06-18T14:32:11.000000Z'
                  - id: 97104
                    description: created
                    event: created
                    subject_type: XeroPayment
                    subject_id: 519
                    batch_uuid: 9d3f2a68-1c2b-4e0f-8a4d-6b1e2f3a4c5d
                    properties:
                      source: xero_sync
                    causer_name: Jane Smith
                    created_at: '2026-06-15T09:12:45.000000Z'
                  first_page_url: https://app.sku.io/api/xero/v2/payments/519/activity-log?page=1
                  from: 1
                  last_page: 1
                  last_page_url: https://app.sku.io/api/xero/v2/payments/519/activity-log?page=1
                  links:
                  - url: null
                    label: '&laquo; Previous'
                    active: false
                  - url: https://app.sku.io/api/xero/v2/payments/519/activity-log?page=1
                    label: '1'
                    active: true
                  - url: null
                    label: Next &raquo;
                    active: false
                  next_page_url: null
                  path: https://app.sku.io/api/xero/v2/payments/519/activity-log
                  per_page: 15
                  prev_page_url: null
                  to: 2
                  total: 2
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-xero-v2-payments-payment-activity-log
  /api/xero/v2/purchase-orders/{purchaseOrder}/activity-log:
    get:
      tags:
      - Xero
      summary: Get Purchase Order Activity Log (V2)
      description: 'Paginated change history for a single synced Xero purchase order
        — one entry per recorded change, newest first. Each entry includes the change
        type (`event`: created / updated / deleted / bulk_upsert), the changed field
        values (`properties.attributes` = new values, `properties.old` = previous
        values), the source tag of whatever made the change (`properties.source`),
        an optional `batch_uuid` grouping changes made by one bulk operation, and
        `causer_name` (the user who triggered it; null for system/sync changes).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Query parameters:** `page`, `per_page` (default 15), `filter[event]`, `filter[source]`,
        `filter[batch_uuid]`, `filter[search]` — all optional.


        **Path parameters:** the record ID is the `id` returned by List Purchase Orders
        (V2).


        Returns 404 when the record does not exist.


        **Authentication:** Bearer token.'
      parameters:
      - name: purchaseOrder
        in: path
        schema:
          type: integer
        required: true
        description: Internal purchase order record ID
        example: '73'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        description:
                          type: string
                        event:
                          type: string
                        subject_type:
                          type: string
                        subject_id:
                          type: integer
                        batch_uuid:
                          type: string
                          nullable: true
                        properties:
                          type: object
                          properties:
                            source:
                              type: string
                            attributes:
                              type: object
                              properties:
                                Status:
                                  type: string
                                Total:
                                  type: integer
                            old:
                              type: object
                              properties:
                                Status:
                                  type: string
                                Total:
                                  type: integer
                        causer_name:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                    items:
                      type: object
                      properties:
                        url:
                          type: string
                          nullable: true
                        label:
                          type: string
                        active:
                          type: boolean
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 98211
                    description: updated
                    event: updated
                    subject_type: XeroPurchaseOrder
                    subject_id: 73
                    batch_uuid: null
                    properties:
                      source: xero_sync
                      attributes:
                        Status: BILLED
                        Total: 1375
                      old:
                        Status: AUTHORISED
                        Total: 1375
                    causer_name: null
                    created_at: '2026-06-18T14:32:11.000000Z'
                  - id: 97104
                    description: created
                    event: created
                    subject_type: XeroPurchaseOrder
                    subject_id: 73
                    batch_uuid: 9d3f2a68-1c2b-4e0f-8a4d-6b1e2f3a4c5d
                    properties:
                      source: xero_sync
                    causer_name: Jane Smith
                    created_at: '2026-06-15T09:12:45.000000Z'
                  first_page_url: https://app.sku.io/api/xero/v2/purchase-orders/73/activity-log?page=1
                  from: 1
                  last_page: 1
                  last_page_url: https://app.sku.io/api/xero/v2/purchase-orders/73/activity-log?page=1
                  links:
                  - url: null
                    label: '&laquo; Previous'
                    active: false
                  - url: https://app.sku.io/api/xero/v2/purchase-orders/73/activity-log?page=1
                    label: '1'
                    active: true
                  - url: null
                    label: Next &raquo;
                    active: false
                  next_page_url: null
                  path: https://app.sku.io/api/xero/v2/purchase-orders/73/activity-log
                  per_page: 15
                  prev_page_url: null
                  to: 2
                  total: 2
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-xero-v2-purchase-orders-purchaseorder-activity-log
  /api/xero/v2/tax-rates/{taxRate}/activity-log:
    get:
      tags:
      - Xero
      summary: Get Tax Rate Activity Log (V2)
      description: 'Paginated change history for a single synced Xero tax rate — one
        entry per recorded change, newest first. Each entry includes the change type
        (`event`: created / updated / deleted / bulk_upsert), the changed field values
        (`properties.attributes` = new values, `properties.old` = previous values),
        the source tag of whatever made the change (`properties.source`), an optional
        `batch_uuid` grouping changes made by one bulk operation, and `causer_name`
        (the user who triggered it; null for system/sync changes).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Query parameters:** `page`, `per_page` (default 15), `filter[event]`, `filter[source]`,
        `filter[batch_uuid]`, `filter[search]` — all optional.


        **Path parameters:** the record ID is the `id` returned by List Tax Rates
        (V2).


        Returns 404 when the record does not exist.


        **Authentication:** Bearer token.'
      parameters:
      - name: taxRate
        in: path
        schema:
          type: integer
        required: true
        description: Internal tax rate record ID
        example: '5'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        description:
                          type: string
                        event:
                          type: string
                        subject_type:
                          type: string
                        subject_id:
                          type: integer
                        batch_uuid:
                          type: string
                          nullable: true
                        properties:
                          type: object
                          properties:
                            source:
                              type: string
                            attributes:
                              type: object
                              properties:
                                Name:
                                  type: string
                                EffectiveRate:
                                  type: number
                            old:
                              type: object
                              properties:
                                Name:
                                  type: string
                                EffectiveRate:
                                  type: number
                        causer_name:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                    items:
                      type: object
                      properties:
                        url:
                          type: string
                          nullable: true
                        label:
                          type: string
                        active:
                          type: boolean
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 98211
                    description: updated
                    event: updated
                    subject_type: XeroTaxRate
                    subject_id: 5
                    batch_uuid: null
                    properties:
                      source: xero_sync
                      attributes:
                        Name: Tax on Sales (8.875%)
                        EffectiveRate: 8.875
                      old:
                        Name: Tax on Sales (8.5%)
                        EffectiveRate: 8.5
                    causer_name: null
                    created_at: '2026-06-18T14:32:11.000000Z'
                  - id: 97104
                    description: created
                    event: created
                    subject_type: XeroTaxRate
                    subject_id: 5
                    batch_uuid: 9d3f2a68-1c2b-4e0f-8a4d-6b1e2f3a4c5d
                    properties:
                      source: xero_sync
                    causer_name: Jane Smith
                    created_at: '2026-06-15T09:12:45.000000Z'
                  first_page_url: https://app.sku.io/api/xero/v2/tax-rates/5/activity-log?page=1
                  from: 1
                  last_page: 1
                  last_page_url: https://app.sku.io/api/xero/v2/tax-rates/5/activity-log?page=1
                  links:
                  - url: null
                    label: '&laquo; Previous'
                    active: false
                  - url: https://app.sku.io/api/xero/v2/tax-rates/5/activity-log?page=1
                    label: '1'
                    active: true
                  - url: null
                    label: Next &raquo;
                    active: false
                  next_page_url: null
                  path: https://app.sku.io/api/xero/v2/tax-rates/5/activity-log
                  per_page: 15
                  prev_page_url: null
                  to: 2
                  total: 2
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-xero-v2-tax-rates-taxrate-activity-log
  /api/xero/v2/accounts/export:
    get:
      tags:
      - Xero
      summary: Export Accounts (V2)
      description: 'Download the synced Xero chart of accounts as a CSV or XLSX file.
        Exports every account matching the given filters (no pagination) using the
        same filter parameters as List Accounts (V2). The response is a file attachment
        named `xero-accounts-<timestamp>.<format>`.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Columns:** ID, AccountID, Name, Code, Type, Status, Class, SKU Account (the
        linked SKU.io ledger account name, blank when unlinked), Created At, Updated
        At.


        **Query parameters:** `format` (csv, default, or xlsx) plus optional filters
        — `filter[search]`, exact-match filters on Name/Code/Type/Class/Status/id
        (each also supports operator variants such as `filter[Name.contains]` and
        `filter[Status.is_not]`), and `filter_groups` (base64-encoded JSON tree for
        and/or combinations).


        **Authentication:** Bearer token.'
      parameters:
      - name: format
        in: query
        schema:
          type: string
        description: 'File format: csv (default) or xlsx'
        example: csv
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: text/csv
          content:
            text/plain:
              schema:
                type: string
                example: 'ID,AccountID,Name,Code,Type,Status,Class,SKU Account,Created
                  At,Updated At

                  61,2c8b3e10-7f4a-4d2e-9b1c-5a6f8e0d1234,Shipping,510,EXPENSE,ACTIVE,EXPENSE,Shipping,2026-01-12
                  08:30:00,2026-06-20 02:15:07

                  62,9a1b2c3d-4e5f-4a6b-8c7d-0e1f2a3b4c5d,Sales,200,REVENUE,ACTIVE,REVENUE,Sales,2026-01-12
                  08:30:00,2026-06-20 02:15:07

                  63,5f4e3d2c-1b0a-49f8-8e7d-6c5b4a3f2e1d,Business Checking,090,BANK,ACTIVE,ASSET,,2026-01-12
                  08:30:00,2026-06-20 02:15:07

                  '
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-xero-v2-accounts-export
  /api/xero/webhook-settings/{integrationInstanceId}:
    get:
      tags:
      - Xero
      summary: Show Webhook Settings
      description: 'Get the webhook settings for a Xero integration instance. Lazily
        generates a webhook UUID if one doesn''t exist. Returns a masked signing key
        preview (first 4 + last 4 chars) and the 20 most recent webhook events.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: integrationInstanceId
        in: path
        schema:
          type: integer
        required: true
        description: Xero integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      webhook_enabled:
                        type: boolean
                      webhook_url:
                        type: string
                      has_signing_key:
                        type: boolean
                      signing_key_preview:
                        type: string
                      recent_events:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            event_category:
                              type: string
                            event_type:
                              type: string
                            resource_id:
                              type: string
                            status:
                              type: string
                            error_message:
                              type: string
                              nullable: true
                            created_at:
                              type: string
                            processed_at:
                              type: string
                example:
                  data:
                    webhook_enabled: false
                    webhook_url: https://app.sku.io/api/webhooks/xero/some-uuid-here
                    has_signing_key: true
                    signing_key_preview: abcd...wxyz
                    recent_events:
                    - id: 1
                      event_category: INVOICE
                      event_type: CREATE
                      resource_id: xero-resource-uuid
                      status: processed
                      error_message: null
                      created_at: '2024-05-01T09:00:00.000000Z'
                      processed_at: '2024-05-01T09:00:05.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-xero-webhook-settings-integrationinstanceid
    patch:
      tags:
      - Xero
      summary: Update Webhook Settings
      description: 'Enable or disable Xero webhooks and update the signing key. Key
        rotation is supported with a 1-hour grace period for the previous key.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Fields:

        - webhook_enabled (required, boolean): Enable or disable webhook processing

        - signing_key (optional, string, min 32 max 256): HMAC-SHA256 signing key
        from Xero


        Errors:

        - 422: Cannot enable webhooks without a signing key'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                webhook_enabled:
                  type: boolean
                signing_key:
                  type: string
              example:
                webhook_enabled: true
                signing_key: your-xero-webhook-signing-key-here-min-32-chars
      parameters:
      - name: integrationInstanceId
        in: path
        schema:
          type: integer
        required: true
        description: Xero integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      webhook_enabled:
                        type: boolean
                      webhook_url:
                        type: string
                      has_signing_key:
                        type: boolean
                example:
                  message: Webhook settings saved.
                  data:
                    webhook_enabled: true
                    webhook_url: https://app.sku.io/api/webhooks/xero/some-uuid-here
                    has_signing_key: true
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Cannot enable webhooks without a signing key.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: patch-api-xero-webhook-settings-integrationinstanceid
  /api/xero/webhook-settings/{integrationInstanceId}/events:
    get:
      tags:
      - Xero
      summary: List Webhook Events
      description: 'Paginated feed of the webhook events Xero has delivered for this
        connection, newest first (by `event_date_utc`). Each event records what changed
        in Xero (`event_category` CONTACT / INVOICE / CREDITNOTE, `event_type` CREATE
        / UPDATE, `resource_id` — the Xero GUID), how it was handled (`status`: received,
        processing, processed, failed, duplicate, ignored; `processing_attempts`;
        `error_message`), the raw event payload as delivered by Xero, and `app_link`/`app_link_label`
        — a path to the synced record inside SKU.io (null until the referenced record
        has been synced in).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Sorting:** id, event_category, event_type, status, processing_attempts,
        event_date_utc, created_at, processed_at (prefix with - for descending; default
        -event_date_utc).


        **Filters:** filter[search] plus per-column filters on status, event_category,
        event_type, resource_id, error_message, id, processing_attempts, event_date_utc,
        created_at, processed_at. Text/numeric/date columns also accept operator variants
        (`filter[column.operator]`, e.g. `filter[status.is_not]=processed`, `filter[event_date_utc.between]=2026-07-01,2026-07-07`).


        Returns 404 when the integration instance does not exist.


        **Authentication:** Bearer token.'
      parameters:
      - name: integrationInstanceId
        in: path
        schema:
          type: integer
        required: true
        description: Xero integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        event_category:
                          type: string
                        event_type:
                          type: string
                        resource_id:
                          type: string
                        resource_url:
                          type: string
                        status:
                          type: string
                        processing_attempts:
                          type: integer
                        error_message:
                          type: string
                          nullable: true
                        payload:
                          type: object
                          properties:
                            resourceUrl:
                              type: string
                            resourceId:
                              type: string
                            dataTypeName:
                              type: string
                            eventDateUtc:
                              type: string
                            eventType:
                              type: string
                            eventCategory:
                              type: string
                            tenantId:
                              type: string
                            tenantType:
                              type: string
                            eventSequence:
                              type: integer
                        app_link:
                          type: string
                        app_link_label:
                          type: string
                        event_date_utc:
                          type: string
                        processed_at:
                          type: string
                        created_at:
                          type: string
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                    items:
                      type: object
                      properties:
                        url:
                          type: string
                          nullable: true
                        label:
                          type: string
                        active:
                          type: boolean
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 1543
                    event_category: INVOICE
                    event_type: UPDATE
                    resource_id: b3a8c7d2-4e1f-4a9b-8c6d-2f5e7a9b1c3d
                    resource_url: https://api.xero.com/api.xro/2.0/Invoices/b3a8c7d2-4e1f-4a9b-8c6d-2f5e7a9b1c3d
                    status: processed
                    processing_attempts: 1
                    error_message: null
                    payload:
                      resourceUrl: https://api.xero.com/api.xro/2.0/Invoices/b3a8c7d2-4e1f-4a9b-8c6d-2f5e7a9b1c3d
                      resourceId: b3a8c7d2-4e1f-4a9b-8c6d-2f5e7a9b1c3d
                      dataTypeName: Invoice
                      eventDateUtc: '2026-07-01T14:05:22+00:00'
                      eventType: UPDATE
                      eventCategory: INVOICE
                      tenantId: 8f7a6b5c-4d3e-42f1-9b8c-7d6e5f4a3b2c
                      tenantType: ORGANISATION
                      eventSequence: 1
                    app_link: /integrations/xero/invoices/342
                    app_link_label: Xero Invoice
                    event_date_utc: '2026-07-01T14:05:22+00:00'
                    processed_at: '2026-07-01T14:05:31+00:00'
                    created_at: '2026-07-01T14:05:24+00:00'
                  - id: 1544
                    event_category: CONTACT
                    event_type: CREATE
                    resource_id: d4e5f6a7-b8c9-40d1-a2b3-c4d5e6f7a8b9
                    resource_url: https://api.xero.com/api.xro/2.0/Contacts/d4e5f6a7-b8c9-40d1-a2b3-c4d5e6f7a8b9
                    status: failed
                    processing_attempts: 3
                    error_message: Xero API rate limit exceeded while fetching contact
                      d4e5f6a7-b8c9-40d1-a2b3-c4d5e6f7a8b9
                    payload:
                      resourceUrl: https://api.xero.com/api.xro/2.0/Contacts/d4e5f6a7-b8c9-40d1-a2b3-c4d5e6f7a8b9
                      resourceId: d4e5f6a7-b8c9-40d1-a2b3-c4d5e6f7a8b9
                      dataTypeName: Contact
                      eventDateUtc: '2026-07-01T14:09:47+00:00'
                      eventType: CREATE
                      eventCategory: CONTACT
                      tenantId: 8f7a6b5c-4d3e-42f1-9b8c-7d6e5f4a3b2c
                      tenantType: ORGANISATION
                      eventSequence: 2
                    app_link: null
                    app_link_label: null
                    event_date_utc: '2026-07-01T14:09:47+00:00'
                    processed_at: null
                    created_at: '2026-07-01T14:09:49+00:00'
                  first_page_url: https://app.sku.io/api/xero/webhook-settings/1/events?page=1
                  from: 1
                  last_page: 1
                  last_page_url: https://app.sku.io/api/xero/webhook-settings/1/events?page=1
                  links:
                  - url: null
                    label: '&laquo; Previous'
                    active: false
                  - url: https://app.sku.io/api/xero/webhook-settings/1/events?page=1
                    label: '1'
                    active: true
                  - url: null
                    label: Next &raquo;
                    active: false
                  next_page_url: null
                  path: https://app.sku.io/api/xero/webhook-settings/1/events
                  per_page: 10
                  prev_page_url: null
                  to: 2
                  total: 362
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-xero-webhook-settings-integrationinstanceid-events
    delete:
      tags:
      - Xero
      summary: Bulk Delete Webhook Events
      description: 'Permanently delete webhook events in bulk. This only removes the
        stored event records (the audit feed); it does not undo any data changes the
        events triggered. Requires an explicit `confirmation` value of `YES`.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Body (one of two selection modes):**

        - `event_ids` (array of integers, required unless `apply_to_all` is true):
        explicit event IDs to delete. Each ID must exist.

        - `apply_to_all` (boolean, optional): when true, delete every event matching
        `filters` instead of an explicit ID list.

        - `filters` (object, optional, used with `apply_to_all`): flat filter map
        using the same keys as List Webhook Events'' `filter[...]` parameters, e.g.
        `{"status": "duplicate"}`.

        - `confirmation` (string, required): must be exactly `YES`.


        Returns the number of rows removed.


        **Authentication:** Bearer token.'
      parameters:
      - name: integrationInstanceId
        in: path
        schema:
          type: integer
        required: true
        description: Xero integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      deleted_count:
                        type: integer
                example:
                  message: 2 webhook event(s) deleted.
                  data:
                    deleted_count: 2
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      confirmation:
                        type: array
                        items:
                          type: string
                example:
                  status: failure
                  message: The confirmation field is required.
                  errors:
                    confirmation:
                    - The confirmation field is required.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-xero-webhook-settings-integrationinstanceid-events
  /api/xero/webhook-settings/{integrationInstanceId}/events/summary:
    get:
      tags:
      - Xero
      summary: Get Webhook Events Summary
      description: 'Per-status counts of every webhook event received for this connection,
        plus a `total`. Every known status is always present (zero-filled): received,
        processing, processed, failed, duplicate, ignored. Useful for monitoring webhook
        processing health — a growing `failed` count indicates events that need to
        be retried (see Retry Failed Webhook Events).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Authentication:** Bearer token.'
      parameters:
      - name: integrationInstanceId
        in: path
        schema:
          type: integer
        required: true
        description: Xero integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      received:
                        type: integer
                      processing:
                        type: integer
                      processed:
                        type: integer
                      failed:
                        type: integer
                      duplicate:
                        type: integer
                      ignored:
                        type: integer
                      total:
                        type: integer
                example:
                  data:
                    received: 2
                    processing: 0
                    processed: 341
                    failed: 4
                    duplicate: 12
                    ignored: 3
                    total: 362
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-xero-webhook-settings-integrationinstanceid-events-summary
  /api/xero/webhook-settings/{integrationInstanceId}/events/reprocess:
    post:
      tags:
      - Xero
      summary: Reprocess Webhook Events
      description: 'Reprocess webhook events in bulk: each targeted event is reset
        to `received` status and a background job is queued per event to re-fetch
        the referenced record''s current state from Xero. Returns immediately with
        the number of events queued; processing happens asynchronously.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Body (one of two selection modes):**

        - `event_ids` (array of integers, required unless `apply_to_all` is true):
        explicit event IDs to reprocess. Each ID must exist.

        - `apply_to_all` (boolean, optional): when true, reprocess every event matching
        `filters` instead of an explicit ID list.

        - `filters` (object, optional, used with `apply_to_all`): flat filter map
        using the same keys as List Webhook Events'' `filter[...]` parameters, e.g.
        `{"status": "failed", "event_category": "INVOICE"}`.


        **Authentication:** Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                event_ids:
                  type: array
                  items:
                    type: integer
              example:
                event_ids:
                - 1543
                - 1544
      parameters:
      - name: integrationInstanceId
        in: path
        schema:
          type: integer
        required: true
        description: Xero integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      reprocessed_count:
                        type: integer
                example:
                  message: Webhook events queued for reprocessing.
                  data:
                    reprocessed_count: 2
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-xero-webhook-settings-integrationinstanceid-events-reprocess
  /api/xero/webhook-settings/{integrationInstanceId}/events/retry-failed:
    post:
      tags:
      - Xero
      summary: Retry Failed Webhook Events
      description: 'Reprocess every currently-failed webhook event for this connection
        in one call — equivalent to Reprocess Webhook Events with all failed event
        IDs. Each failed event is reset to `received` and a background job is queued
        per event; the call returns immediately with the number of events queued,
        and processing happens asynchronously. No request body is required.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Authentication:** Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstanceId
        in: path
        schema:
          type: integer
        required: true
        description: Xero integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      reprocessed_count:
                        type: integer
                example:
                  message: Failed webhook events queued for reprocessing.
                  data:
                    reprocessed_count: 4
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-xero-webhook-settings-integrationinstanceid-events-retry-failed
  /api/xero/webhook-settings/{integrationInstanceId}/events/{event}/reprocess:
    post:
      tags:
      - Xero
      summary: Reprocess Webhook Event
      description: 'Reprocess a single webhook event: resets it to `received` status
        and queues a background job that re-fetches the referenced record''s current
        state from Xero. Returns the refreshed event immediately (status `received`,
        pending the queued job); processing happens asynchronously.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Path parameters:**

        - `integrationInstanceId` (integer, required): Xero integration instance ID.

        - `event` (integer, required): webhook event ID (the `id` from List Webhook
        Events).


        Returns 404 when the event does not exist.


        **Authentication:** Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstanceId
        in: path
        schema:
          type: integer
        required: true
        description: Xero integration instance ID
        example: '1'
      - name: event
        in: path
        schema:
          type: integer
        required: true
        description: Webhook event ID
        example: '1544'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      event_category:
                        type: string
                      event_type:
                        type: string
                      resource_id:
                        type: string
                      resource_url:
                        type: string
                      status:
                        type: string
                      processing_attempts:
                        type: integer
                      error_message:
                        type: string
                      payload:
                        type: object
                        properties:
                          resourceUrl:
                            type: string
                          resourceId:
                            type: string
                          dataTypeName:
                            type: string
                          eventDateUtc:
                            type: string
                          eventType:
                            type: string
                          eventCategory:
                            type: string
                          tenantId:
                            type: string
                          tenantType:
                            type: string
                          eventSequence:
                            type: integer
                      app_link:
                        type: string
                        nullable: true
                      app_link_label:
                        type: string
                        nullable: true
                      event_date_utc:
                        type: string
                      processed_at:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                example:
                  message: Webhook event queued for reprocessing.
                  data:
                    id: 1544
                    event_category: CONTACT
                    event_type: CREATE
                    resource_id: d4e5f6a7-b8c9-40d1-a2b3-c4d5e6f7a8b9
                    resource_url: https://api.xero.com/api.xro/2.0/Contacts/d4e5f6a7-b8c9-40d1-a2b3-c4d5e6f7a8b9
                    status: received
                    processing_attempts: 3
                    error_message: Xero API rate limit exceeded while fetching contact
                      d4e5f6a7-b8c9-40d1-a2b3-c4d5e6f7a8b9
                    payload:
                      resourceUrl: https://api.xero.com/api.xro/2.0/Contacts/d4e5f6a7-b8c9-40d1-a2b3-c4d5e6f7a8b9
                      resourceId: d4e5f6a7-b8c9-40d1-a2b3-c4d5e6f7a8b9
                      dataTypeName: Contact
                      eventDateUtc: '2026-07-01T14:09:47+00:00'
                      eventType: CREATE
                      eventCategory: CONTACT
                      tenantId: 8f7a6b5c-4d3e-42f1-9b8c-7d6e5f4a3b2c
                      tenantType: ORGANISATION
                      eventSequence: 2
                    app_link: null
                    app_link_label: null
                    event_date_utc: '2026-07-01T14:09:47+00:00'
                    processed_at: null
                    created_at: '2026-07-01T14:09:49+00:00'
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: object
                    properties:
                      Modules\Xero\Entities\XeroWebhookEvent:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: array
                  status:
                    type: string
                  message:
                    type: string
                example:
                  errors:
                    Modules\Xero\Entities\XeroWebhookEvent:
                    - message: No query results for model [Modules\Xero\Entities\XeroWebhookEvent]
                        999999
                      code: NotFound
                      data: []
                  status: failure
                  message: No query results for model [Modules\Xero\Entities\XeroWebhookEvent]
                    999999
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-xero-webhook-settings-integrationinstanceid-events-event-reprocess
  /api/xero/webhook-settings/{integrationInstanceId}/events/all:
    delete:
      tags:
      - Xero
      summary: Delete All Webhook Events
      description: 'Permanently delete every stored webhook event for this connection.
        This only clears the event history; it does not undo any data changes the
        events triggered, and it does not disable webhooks. Requires an explicit `confirmation`
        value of `YES`.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Body:**

        - `confirmation` (string, required): must be exactly `YES`.


        Returns the number of rows removed.


        **Authentication:** Bearer token.'
      parameters:
      - name: integrationInstanceId
        in: path
        schema:
          type: integer
        required: true
        description: Xero integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      deleted_count:
                        type: integer
                example:
                  message: 362 webhook event(s) deleted.
                  data:
                    deleted_count: 362
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      confirmation:
                        type: array
                        items:
                          type: string
                example:
                  status: failure
                  message: The confirmation field is required.
                  errors:
                    confirmation:
                    - The confirmation field is required.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-xero-webhook-settings-integrationinstanceid-events-all
  /api/stripe/integrations:
    post:
      tags:
      - Stripe
      summary: Create Stripe Integration
      description: 'Creates a new Stripe integration instance (a placeholder before
        OAuth).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Requires admin or power-user permissions. The newly created instance is returned
        with `connected: false` until the OAuth flow has been completed via Start
        Authorization.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
              example:
                name: Main Store
      parameters: []
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      sync_status:
                        type: string
                      connected:
                        type: boolean
                      charges_enabled:
                        type: boolean
                      payouts_enabled:
                        type: boolean
                      details_submitted:
                        type: boolean
                      default_currency:
                        type: string
                      country:
                        type: string
                      email:
                        type: string
                      display_name:
                        type: string
                      business_name:
                        type: string
                      business_url:
                        type: string
                      capabilities:
                        type: object
                        properties:
                          card_payments:
                            type: string
                          transfers:
                            type: string
                      stripe_account_id:
                        type: string
                        nullable: true
                      livemode:
                        type: boolean
                      webhook_registered:
                        type: boolean
                      last_reconciled_at:
                        type: string
                      disconnected_at:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 7
                    name: Main Store
                    sync_status: active
                    connected: false
                    charges_enabled: false
                    payouts_enabled: false
                    details_submitted: false
                    default_currency: USD
                    country: US
                    email: owner@example.com
                    display_name: Acme Inc
                    business_name: Acme Inc
                    business_url: https://acme.example.com
                    capabilities:
                      card_payments: active
                      transfers: active
                    stripe_account_id: null
                    livemode: false
                    webhook_registered: true
                    last_reconciled_at: '2026-05-01T07:00:00.000000Z'
                    disconnected_at: null
                    created_at: '2026-05-01T06:00:00.000000Z'
                    updated_at: '2026-05-01T07:00:00.000000Z'
                  message: Stripe integration created.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-stripe-integrations
  /api/stripe/integrations/{id}:
    get:
      tags:
      - Stripe
      summary: Show Integration Instance
      description: 'Returns a single Stripe integration instance with connection status,
        capabilities and account snapshot.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: id
        in: path
        schema:
          type: string
        required: true
        description: The record ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      sync_status:
                        type: string
                      connected:
                        type: boolean
                      charges_enabled:
                        type: boolean
                      payouts_enabled:
                        type: boolean
                      details_submitted:
                        type: boolean
                      default_currency:
                        type: string
                      country:
                        type: string
                      email:
                        type: string
                      display_name:
                        type: string
                      business_name:
                        type: string
                      business_url:
                        type: string
                      capabilities:
                        type: object
                        properties:
                          card_payments:
                            type: string
                          transfers:
                            type: string
                      stripe_account_id:
                        type: string
                      livemode:
                        type: boolean
                      webhook_registered:
                        type: boolean
                      last_reconciled_at:
                        type: string
                      disconnected_at:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 7
                    name: Main Store
                    sync_status: active
                    connected: true
                    charges_enabled: true
                    payouts_enabled: true
                    details_submitted: true
                    default_currency: USD
                    country: US
                    email: owner@example.com
                    display_name: Acme Inc
                    business_name: Acme Inc
                    business_url: https://acme.example.com
                    capabilities:
                      card_payments: active
                      transfers: active
                    stripe_account_id: acct_1Oxxxxxxx
                    livemode: false
                    webhook_registered: true
                    last_reconciled_at: '2026-05-01T07:00:00.000000Z'
                    disconnected_at: null
                    created_at: '2026-05-01T06:00:00.000000Z'
                    updated_at: '2026-05-01T07:00:00.000000Z'
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Stripe integration not found.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-stripe-integrations-id
  /api/stripe/integrations/{id}/authorize:
    post:
      tags:
      - Stripe
      summary: Start Authorization (OAuth)
      description: 'Begins the Stripe Connect OAuth flow. Returns an `authorize_url`
        that the merchant should be redirected to in order to grant access. Stripe
        will redirect back to `/api/stripe/oauth/callback`.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Requires admin or power-user permissions.'
      requestBody:
        content: {}
      parameters:
      - name: id
        in: path
        schema:
          type: string
        required: true
        description: The record ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      authorize_url:
                        type: string
                example:
                  data:
                    authorize_url: https://connect.stripe.com/oauth/authorize?response_type=code&client_id=ca_test&scope=read_write&state=stripe_state_token
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-stripe-integrations-id-authorize
  /api/stripe/integrations/{id}/disconnect:
    post:
      tags:
      - Stripe
      summary: Disconnect Integration
      description: 'Disconnects the Stripe integration — revokes the OAuth token at
        Stripe and clears the local access token. Past pay links continue to function,
        but new ones cannot be created until reconnected.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Requires admin or power-user permissions.'
      requestBody:
        content: {}
      parameters:
      - name: id
        in: path
        schema:
          type: string
        required: true
        description: The record ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      sync_status:
                        type: string
                      connected:
                        type: boolean
                      charges_enabled:
                        type: boolean
                      payouts_enabled:
                        type: boolean
                      details_submitted:
                        type: boolean
                      default_currency:
                        type: string
                      country:
                        type: string
                      email:
                        type: string
                      display_name:
                        type: string
                      business_name:
                        type: string
                      business_url:
                        type: string
                      capabilities:
                        type: object
                        properties:
                          card_payments:
                            type: string
                          transfers:
                            type: string
                      stripe_account_id:
                        type: string
                        nullable: true
                      livemode:
                        type: boolean
                      webhook_registered:
                        type: boolean
                      last_reconciled_at:
                        type: string
                      disconnected_at:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 7
                    name: Main Store
                    sync_status: active
                    connected: false
                    charges_enabled: true
                    payouts_enabled: true
                    details_submitted: true
                    default_currency: USD
                    country: US
                    email: owner@example.com
                    display_name: Acme Inc
                    business_name: Acme Inc
                    business_url: https://acme.example.com
                    capabilities:
                      card_payments: active
                      transfers: active
                    stripe_account_id: null
                    livemode: false
                    webhook_registered: true
                    last_reconciled_at: '2026-05-01T07:00:00.000000Z'
                    disconnected_at: '2026-05-01T07:00:00.000000Z'
                    created_at: '2026-05-01T06:00:00.000000Z'
                    updated_at: '2026-05-01T07:00:00.000000Z'
                  message: Stripe integration disconnected.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-stripe-integrations-id-disconnect
  /api/stripe/invoices:
    post:
      tags:
      - Stripe
      summary: Send Invoice
      description: 'Creates, finalizes, and sends a Stripe Invoice for a sales order.
        Stripe emails the customer the hosted invoice link automatically. If a payable
        open invoice already exists for the sales order it is returned instead of
        creating a new one (idempotent).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Fields:

        - `integration_instance_id` (required, integer) — the Stripe integration to
        charge through

        - `sales_order_id` (required, integer) — the sales order being invoiced

        - `amount_in_cents` (optional, integer, min 1) — override the order outstanding
        balance; if omitted the full outstanding balance is invoiced

        - `customer_email` (optional, email) — override the customer email on file
        (defaults to the sales order''s customer email)


        Rate limited: 30 requests/minute.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                integration_instance_id:
                  type: integer
                sales_order_id:
                  type: integer
                amount_in_cents:
                  type: integer
                customer_email:
                  type: string
              example:
                integration_instance_id: 7
                sales_order_id: 1234
                amount_in_cents: 19999
                customer_email: buyer@example.com
      parameters: []
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            text/plain:
              schema:
                type: string
                example: "{\"data\": {\"id\": 42, \"integration_instance_id\": 7,\
                  \ \"sales_order_id\": 1234, \"sales_order_number\": \"SO-2026-00100\"\
                  \x02 \"user_id\": 8, \"stripe_invoice_id\": \"in_1Oabc123\", \"\
                  stripe_customer_id\": \"cus_OabcDEF\", \"stripe_payment_intent_id\"\
                  : null, \"stripe_charge_id\": null, \"amount\": 19999, \"amount_paid\"\
                  : 0, \"amount_refunded\": 0, \"currency\": \"USD\", \"status\":\
                  \ \"open\", \"customer_email\": \"buyer@example.com\", \"hosted_invoice_url\"\
                  : \"https://invoice.stripe.com/i/acct_1Oabc/test_YWNjdF8x\", \"\
                  invoice_pdf\": \"https://pay.stripe.com/invoice/acct_1Oabc/invst_xxx/pdf\"\
                  , \"days_until_due\": 30, \"due_date\": \"2026-06-01T00:00:00.000000Z\"\
                  , \"finalized_at\": \"2026-05-01T07:30:00.000000Z\", \"paid_at\"\
                  : null, \"voided_at\": null, \"last_refunded_at\": null, \"metadata\"\
                  : {\"sku9_sales_order_id\": 1234, \"sku9_user_id\": 8}, \"created_at\"\
                  : \"2026-05-01T07:30:00.000000Z\", \"updated_at\": \"2026-05-01T07:30:00.000000Z\"\
                  }, \"message\": \"Invoice sent to customer.\"}"
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Sales order not found.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Stripe integration is not connected.
        '502':
          description: Bad Gateway
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 'Stripe API error: invoice could not be sent.'
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-stripe-invoices
  /api/stripe/invoices/{id}:
    get:
      tags:
      - Stripe
      summary: Show Invoice
      description: 'Returns a single Stripe Invoice with its linked Sales Order number
        (when set) and integration instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        The `sales_order_number` field on the response is loaded via `whenLoaded(''salesOrder'')`
        and reflects the SKU.io sales order''s human-readable number (e.g. `SO-2026-00100`).
        The `sales_order_id` may be null for orphaned invoices.


        Used by the Stripe Invoice detail page (`/v2/integrations/stripe/:id/invoices/:invoiceId`).'
      parameters:
      - name: id
        in: path
        schema:
          type: integer
        required: true
        description: Local SKU.io Stripe invoice ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      sales_order_id:
                        type: integer
                      sales_order_number:
                        type: string
                      user_id:
                        type: integer
                      stripe_invoice_id:
                        type: string
                      stripe_customer_id:
                        type: string
                      stripe_payment_intent_id:
                        type: string
                      stripe_charge_id:
                        type: string
                      amount:
                        type: integer
                      amount_paid:
                        type: integer
                      amount_refunded:
                        type: integer
                      currency:
                        type: string
                      status:
                        type: string
                      customer_email:
                        type: string
                      hosted_invoice_url:
                        type: string
                      invoice_pdf:
                        type: string
                      days_until_due:
                        type: integer
                      due_date:
                        type: string
                      finalized_at:
                        type: string
                      paid_at:
                        type: string
                      voided_at:
                        type: string
                        nullable: true
                      last_refunded_at:
                        type: string
                        nullable: true
                      metadata:
                        type: object
                        properties:
                          sales_order_id:
                            type: integer
                          order_number:
                            type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 42
                    integration_instance_id: 7
                    sales_order_id: 1234
                    sales_order_number: SO-2026-00100
                    user_id: 8
                    stripe_invoice_id: in_1Oabc123
                    stripe_customer_id: cus_OabcDEF
                    stripe_payment_intent_id: pi_3Oabc456
                    stripe_charge_id: ch_3Oabc789
                    amount: 19999
                    amount_paid: 19999
                    amount_refunded: 0
                    currency: USD
                    status: paid
                    customer_email: customer@example.com
                    hosted_invoice_url: https://invoice.stripe.com/i/acct_xxx/test_yyy
                    invoice_pdf: https://invoice.stripe.com/i/acct_xxx/test_yyy/pdf
                    days_until_due: 15
                    due_date: '2026-06-22T00:00:00.000000Z'
                    finalized_at: '2026-06-04T05:09:00.000000Z'
                    paid_at: '2026-06-05T05:09:00.000000Z'
                    voided_at: null
                    last_refunded_at: null
                    metadata:
                      sales_order_id: 1234
                      order_number: SO-2026-00100
                    created_at: '2026-06-02T05:09:00.000000Z'
                    updated_at: '2026-06-05T05:09:00.000000Z'
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Invoice not found.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-stripe-invoices-id
  /api/stripe/invoices/{id}/activity-log:
    get:
      tags:
      - Stripe
      summary: Get Invoice Activity Log
      description: 'Returns the chronological list of Stripe webhook events linked
        to this invoice via `related_object_id` matching the invoice''s `stripe_invoice_id`,
        `stripe_payment_intent_id`, or `stripe_charge_id`.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Acts as the audit / activity log for the invoice lifecycle (created → finalized
        → paid → refunded / voided). Events are sorted by `event_created_at` descending
        (newest first).


        The response is a flat collection — not paginated — because the activity log
        for one invoice is bounded (typically <20 events).'
      parameters:
      - name: id
        in: path
        schema:
          type: integer
        required: true
        description: Local SKU.io Stripe invoice ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        stripe_event_id:
                          type: string
                        event_type:
                          type: string
                        account_id:
                          type: string
                        livemode:
                          type: boolean
                        related_object_id:
                          type: string
                        status:
                          type: string
                        attempts:
                          type: integer
                        last_error:
                          type: string
                          nullable: true
                        event_created_at:
                          type: string
                        processed_at:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                example:
                  data:
                  - id: 305
                    integration_instance_id: 7
                    stripe_event_id: evt_3Oabc789
                    event_type: invoice.paid
                    account_id: acct_live_xxx
                    livemode: true
                    related_object_id: in_1Oabc123
                    status: processed
                    attempts: 1
                    last_error: null
                    event_created_at: '2026-06-05T05:09:00.000000Z'
                    processed_at: '2026-06-05T05:09:01.000000Z'
                    created_at: '2026-06-05T05:09:00.000000Z'
                    updated_at: '2026-06-05T05:09:01.000000Z'
                  - id: 303
                    integration_instance_id: 7
                    stripe_event_id: evt_3Oabc456
                    event_type: invoice.finalized
                    account_id: acct_live_xxx
                    livemode: true
                    related_object_id: in_1Oabc123
                    status: processed
                    attempts: 1
                    last_error: null
                    event_created_at: '2026-06-04T05:09:00.000000Z'
                    processed_at: '2026-06-04T05:09:01.000000Z'
                    created_at: '2026-06-04T05:09:00.000000Z'
                    updated_at: '2026-06-04T05:09:01.000000Z'
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Invoice not found.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-stripe-invoices-id-activity-log
  /api/stripe/invoices/{id}/void:
    post:
      tags:
      - Stripe
      summary: Void Invoice
      description: 'Voids an open Stripe Invoice. Voiding marks the invoice uncollectable
        at Stripe so the customer cannot pay it anymore. Only valid for invoices in
        `open` or `draft` status — paid invoices cannot be voided (issue a refund
        instead).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters:
      - name: id
        in: path
        schema:
          type: integer
        required: true
        description: Local SKU.io invoice ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            text/plain:
              schema:
                type: string
                example: "{\"data\": {\"id\": 42, \"integration_instance_id\": 7,\
                  \ \"sales_order_id\": 1234, \"sales_order_number\": \"SO-2026-00100\"\
                  \x02 \"user_id\": 8, \"stripe_invoice_id\": \"in_1Oabc123\", \"\
                  stripe_customer_id\": \"cus_OabcDEF\", \"stripe_payment_intent_id\"\
                  : null, \"stripe_charge_id\": null, \"amount\": 19999, \"amount_paid\"\
                  : 0, \"amount_refunded\": 0, \"currency\": \"USD\", \"status\":\
                  \ \"void\", \"customer_email\": \"buyer@example.com\", \"hosted_invoice_url\"\
                  : \"https://invoice.stripe.com/i/acct_1Oabc/test_YWNjdF8x\", \"\
                  invoice_pdf\": \"https://pay.stripe.com/invoice/acct_1Oabc/invst_xxx/pdf\"\
                  , \"days_until_due\": 30, \"due_date\": \"2026-06-01T00:00:00.000000Z\"\
                  , \"finalized_at\": \"2026-05-01T07:30:00.000000Z\", \"paid_at\"\
                  : null, \"voided_at\": \"2026-05-01T08:30:00.000000Z\", \"last_refunded_at\"\
                  : null, \"metadata\": {\"sku9_sales_order_id\": 1234, \"sku9_user_id\"\
                  : 8}, \"created_at\": \"2026-05-01T07:30:00.000000Z\", \"updated_at\"\
                  : \"2026-05-01T08:30:00.000000Z\"}, \"message\": \"Invoice voided.\"\
                  }"
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Invoice not found.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-stripe-invoices-id-void
  /api/stripe/integrations/{id}/invoices:
    get:
      tags:
      - Stripe
      summary: List Invoices by Instance
      description: 'Returns a paginated list of all Stripe Invoices for a Stripe integration
        instance, newest first.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: id
        in: path
        schema:
          type: integer
        required: true
        description: Stripe integration instance ID
        example: '7'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            text/plain:
              schema:
                type: string
                example: "{\"current_page\": 1, \"data\": [{\"id\": 42, \"integration_instance_id\"\
                  : 7, \"sales_order_id\": 1234, \"sales_order_number\": \"SO-2026-00100\"\
                  \x02 \"user_id\": 8, \"stripe_invoice_id\": \"in_1Oabc123\", \"\
                  stripe_customer_id\": \"cus_OabcDEF\", \"stripe_payment_intent_id\"\
                  : \"pi_3OabcDEF\", \"stripe_charge_id\": \"ch_3OabcDEF\", \"amount\"\
                  : 19999, \"amount_paid\": 19999, \"amount_refunded\": 0, \"currency\"\
                  : \"USD\", \"status\": \"paid\", \"customer_email\": \"buyer@example.com\"\
                  , \"hosted_invoice_url\": \"https://invoice.stripe.com/i/acct_1Oabc/test_YWNjdF8x\"\
                  , \"invoice_pdf\": \"https://pay.stripe.com/invoice/acct_1Oabc/invst_xxx/pdf\"\
                  , \"days_until_due\": 30, \"due_date\": \"2026-06-01T00:00:00.000000Z\"\
                  , \"finalized_at\": \"2026-05-01T07:30:00.000000Z\", \"paid_at\"\
                  : \"2026-05-01T08:00:00.000000Z\", \"voided_at\": null, \"last_refunded_at\"\
                  : null, \"metadata\": {\"sku9_sales_order_id\": 1234, \"sku9_user_id\"\
                  : 8}, \"created_at\": \"2026-05-01T07:30:00.000000Z\", \"updated_at\"\
                  : \"2026-05-01T08:00:00.000000Z\"}], \"per_page\": 25, \"total\"\
                  : 1, \"last_page\": 1}"
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-stripe-integrations-id-invoices
  /api/stripe/sales-orders/{salesOrderId}/invoices:
    get:
      tags:
      - Stripe
      summary: List Invoices for Sales Order
      description: 'Returns all Stripe Invoices linked to a sales order across all
        Stripe integration instances, newest first. Used by the sales order detail
        page to render the Stripe Invoices panel.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: salesOrderId
        in: path
        schema:
          type: integer
        required: true
        description: Sales order ID
        example: '1234'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            text/plain:
              schema:
                type: string
                example: "{\"data\": [{\"id\": 42, \"integration_instance_id\": 7,\
                  \ \"sales_order_id\": 1234, \"sales_order_number\": \"SO-2026-00100\"\
                  \x02 \"user_id\": 8, \"stripe_invoice_id\": \"in_1Oabc123\", \"\
                  stripe_customer_id\": \"cus_OabcDEF\", \"stripe_payment_intent_id\"\
                  : \"pi_3OabcDEF\", \"stripe_charge_id\": \"ch_3OabcDEF\", \"amount\"\
                  : 19999, \"amount_paid\": 19999, \"amount_refunded\": 0, \"currency\"\
                  : \"USD\", \"status\": \"paid\", \"customer_email\": \"buyer@example.com\"\
                  , \"hosted_invoice_url\": \"https://invoice.stripe.com/i/acct_1Oabc/test_YWNjdF8x\"\
                  , \"invoice_pdf\": \"https://pay.stripe.com/invoice/acct_1Oabc/invst_xxx/pdf\"\
                  , \"days_until_due\": 30, \"due_date\": \"2026-06-01T00:00:00.000000Z\"\
                  , \"finalized_at\": \"2026-05-01T07:30:00.000000Z\", \"paid_at\"\
                  : \"2026-05-01T08:00:00.000000Z\", \"voided_at\": null, \"last_refunded_at\"\
                  : null, \"metadata\": {\"sku9_sales_order_id\": 1234, \"sku9_user_id\"\
                  : 8}, \"created_at\": \"2026-05-01T07:30:00.000000Z\", \"updated_at\"\
                  : \"2026-05-01T08:00:00.000000Z\"}]}"
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-stripe-sales-orders-salesorderid-invoices
  /api/stripe/invoices/{id}/refunds:
    post:
      tags:
      - Stripe
      summary: Issue Refund
      description: 'Issues a partial or full refund against the charge backing a paid
        Stripe Invoice. Requires admin or power-user privileges. Throttled to 20 requests/minute.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Fields:

        - `amount_in_cents` (optional, integer, min 1) — refund amount; if omitted,
        refunds the full remaining refundable amount

        - `reason` (optional, enum) — one of `duplicate`, `fraudulent`, `requested_by_customer`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                amount_in_cents:
                  type: integer
                reason:
                  type: string
              example:
                amount_in_cents: 5000
                reason: requested_by_customer
      parameters:
      - name: id
        in: path
        schema:
          type: integer
        required: true
        description: Local SKU.io invoice ID
        example: '42'
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      refund_id:
                        type: string
                      amount:
                        type: integer
                      currency:
                        type: string
                      status:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    refund_id: re_3OabcDEF
                    amount: 5000
                    currency: usd
                    status: succeeded
                  message: Refund issued.
        '403':
          description: Forbidden
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: This action is unauthorized.
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Invoice not found.
        '429': *id001
        '401': *id002
        '422': *id005
      operationId: post-api-stripe-invoices-id-refunds
  /api/stripe/webhook-events:
    get:
      tags:
      - Stripe
      summary: List Webhook Events
      description: 'Returns a paginated list of received Stripe webhook events, newest
        first.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        stripe_event_id:
                          type: string
                        event_type:
                          type: string
                        account_id:
                          type: string
                        livemode:
                          type: boolean
                        related_object_id:
                          type: string
                        status:
                          type: string
                        attempts:
                          type: integer
                        last_error:
                          type: string
                          nullable: true
                        event_created_at:
                          type: string
                        processed_at:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  per_page:
                    type: integer
                  total:
                    type: integer
                  last_page:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 21
                    integration_instance_id: 7
                    stripe_event_id: evt_1Oxxxxxxx
                    event_type: checkout.session.completed
                    account_id: acct_1Oxxxxxxx
                    livemode: false
                    related_object_id: cs_test_a1B2C3
                    status: processed
                    attempts: 1
                    last_error: null
                    event_created_at: '2026-05-01T08:00:01.000000Z'
                    processed_at: '2026-05-01T08:00:02.000000Z'
                    created_at: '2026-05-01T08:00:01.000000Z'
                    updated_at: '2026-05-01T08:00:02.000000Z'
                  per_page: 25
                  total: 1
                  last_page: 1
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-stripe-webhook-events
  /api/stripe/webhook-events/{id}:
    get:
      tags:
      - Stripe
      summary: Show Webhook Event
      description: 'Returns a single webhook event. Pass `include_payload=1` to also
        receive the raw Stripe payload for debugging.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: id
        in: path
        schema:
          type: string
        required: true
        description: The record ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      stripe_event_id:
                        type: string
                      event_type:
                        type: string
                      account_id:
                        type: string
                      livemode:
                        type: boolean
                      related_object_id:
                        type: string
                      status:
                        type: string
                      attempts:
                        type: integer
                      last_error:
                        type: string
                        nullable: true
                      event_created_at:
                        type: string
                      processed_at:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      payload:
                        type: object
                        properties:
                          id:
                            type: string
                          type:
                            type: string
                          data:
                            type: object
                            properties:
                              object:
                                type: object
                                properties:
                                  id:
                                    type: string
                example:
                  data:
                    id: 21
                    integration_instance_id: 7
                    stripe_event_id: evt_1Oxxxxxxx
                    event_type: checkout.session.completed
                    account_id: acct_1Oxxxxxxx
                    livemode: false
                    related_object_id: cs_test_a1B2C3
                    status: processed
                    attempts: 1
                    last_error: null
                    event_created_at: '2026-05-01T08:00:01.000000Z'
                    processed_at: '2026-05-01T08:00:02.000000Z'
                    created_at: '2026-05-01T08:00:01.000000Z'
                    updated_at: '2026-05-01T08:00:02.000000Z'
                    payload:
                      id: evt_1Oxxxxxxx
                      type: checkout.session.completed
                      data:
                        object:
                          id: cs_test_a1B2C3
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-stripe-webhook-events-id
  /api/stripe/webhook-events/{id}/replay:
    post:
      tags:
      - Stripe
      summary: Replay Webhook Event
      description: 'Re-queues a previously received webhook event for processing.
        Useful when an event failed transiently or you''ve fixed a bug in the handler.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters:
      - name: id
        in: path
        schema:
          type: string
        required: true
        description: The record ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Webhook event re-queued for processing.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-stripe-webhook-events-id-replay
  /api/webhooks/stripe:
    post:
      tags:
      - Stripe
      summary: Platform Webhook
      description: 'Platform-level webhook endpoint. Receives events from the platform''s
        Stripe account (e.g. `account.application.deauthorized`).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Requires the `Stripe-Signature` header — requests without a valid signature
        return 400.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                id:
                  type: string
                type:
                  type: string
                data:
                  type: object
                  properties:
                    object:
                      type: object
                      properties:
                        id:
                          type: string
              example:
                id: evt_1Oxxxxxxx
                type: account.application.deauthorized
                data:
                  object:
                    id: acct_1Oxxxxxxx
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  received:
                    type: boolean
                example:
                  received: true
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-webhooks-stripe
  /api/webhooks/stripe/{integration_instance_id}:
    post:
      tags:
      - Stripe
      summary: Connect Account Webhook
      description: 'Per-Stripe-account webhook endpoint registered for each connected
        Stripe account during onboarding. Receives events for that specific connected
        account (e.g. `checkout.session.completed`, `charge.refunded`, `charge.dispute.created`).


        Requires the `Stripe-Signature` header. The integration instance ID in the
        URL must match the receiver registered with Stripe.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                id:
                  type: string
                type:
                  type: string
                data:
                  type: object
                  properties:
                    object:
                      type: object
                      properties:
                        id:
                          type: string
              example:
                id: evt_1Oxxxxxxx
                type: checkout.session.completed
                data:
                  object:
                    id: cs_test_a1B2C3
      parameters:
      - name: integration_instance_id
        in: path
        schema:
          type: string
        required: true
        description: The integration instance ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  received:
                    type: boolean
                example:
                  received: true
        '429': *id001
        '404': *id004
        '422': *id005
      security: []
      operationId: post-api-webhooks-stripe-integration-instance-id
  /api/google-calendar/integrations:
    get:
      tags:
      - Google Calendar
      summary: List Google Calendar Connections
      description: 'List the authenticated user''s Google Calendar connection. Connections
        are per-user — each user links their own Google account — so the list contains
        at most one entry (empty when the user has not connected).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        The connection itself is created by authorizing through the SKU.io web app
        (Integrations → Google Calendar); this API manages an existing connection.


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        google_email:
                          type: string
                        calendar_id:
                          type: string
                        is_authenticated:
                          type: boolean
                        is_auto_sync_enabled:
                          type: boolean
                        settings:
                          type: object
                          properties:
                            all_day_events:
                              type: boolean
                            event_time_local:
                              type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                example:
                  success: true
                  data:
                  - id: 3
                    name: Google Calendar
                    google_email: ops@acme.com
                    calendar_id: primary
                    is_authenticated: true
                    is_auto_sync_enabled: true
                    settings:
                      all_day_events: true
                      event_time_local: 09:00
                    created_at: '2026-05-30T12:00:00.000000Z'
                    updated_at: '2026-06-18T09:30:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-google-calendar-integrations
  /api/google-calendar/integrations/calendars:
    get:
      tags:
      - Google Calendar
      summary: List Google Calendars
      description: 'List the calendars available on the authenticated user''s connected
        Google account (fetched live from Google, all pages). Use a calendar''s `id`
        as the `calendar_id` when updating the connection settings to choose which
        calendar events sync to.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        404 when the user has no Google Calendar connection; 400 when the Google API
        call fails.


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: string
                        summary:
                          type: string
                        primary:
                          type: boolean
                        time_zone:
                          type: string
                example:
                  success: true
                  data:
                  - id: primary
                    summary: ops@acme.com
                    primary: true
                    time_zone: America/Chicago
                  - id: c_ops123@group.calendar.google.com
                    summary: Purchasing
                    primary: false
                    time_zone: America/Chicago
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  error:
                    type: string
                example:
                  success: false
                  error: Google Calendar integration not found for this user
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-google-calendar-integrations-calendars
  /api/google-calendar/integrations/test-connection:
    get:
      tags:
      - Google Calendar
      summary: Test Google Calendar Connection
      description: 'Make a minimal Google Calendar API call to confirm the authenticated
        user''s stored authorization still works. Returns the target calendar''s summary
        and time zone on success; a failed test returns 400 with the upstream message.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        404 when the user has no Google Calendar connection.


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      success:
                        type: boolean
                      message:
                        type: string
                      calendar_summary:
                        type: string
                      calendar_time_zone:
                        type: string
                example:
                  success: true
                  data:
                    success: true
                    message: Connection successful
                    calendar_summary: ops@acme.com
                    calendar_time_zone: America/Chicago
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      success:
                        type: boolean
                      message:
                        type: string
                example:
                  success: false
                  data:
                    success: false
                    message: 'Connection test failed: invalid_grant'
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  error:
                    type: string
                example:
                  success: false
                  error: Google Calendar integration not found for this user
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-google-calendar-integrations-test-connection
  /api/google-calendar/integrations/{id}:
    patch:
      tags:
      - Google Calendar
      summary: Update Google Calendar Settings
      description: 'Update the authenticated user''s Google Calendar connection settings.
        Only the caller''s own connection can be updated (404 otherwise).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Body fields (all optional):**

        - `calendar_id` (string, max 255) — which Google calendar events sync to (see
        List Google Calendars).

        - `all_day_events` (boolean) — create synced events as all-day events.

        - `event_time_local` (string, HH:MM) — local time of day for timed events
        when `all_day_events` is false.


        Returns the updated connection.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                calendar_id:
                  type: string
                all_day_events:
                  type: boolean
                event_time_local:
                  type: string
              example:
                calendar_id: c_ops123@group.calendar.google.com
                all_day_events: false
                event_time_local: 09:00
      parameters:
      - name: id
        in: path
        schema:
          type: integer
        required: true
        description: Google Calendar connection ID (must belong to the authenticated
          user)
        example: '3'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      google_email:
                        type: string
                      calendar_id:
                        type: string
                      is_authenticated:
                        type: boolean
                      is_auto_sync_enabled:
                        type: boolean
                      settings:
                        type: object
                        properties:
                          all_day_events:
                            type: boolean
                          event_time_local:
                            type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  success: true
                  data:
                    id: 3
                    name: Google Calendar
                    google_email: ops@acme.com
                    calendar_id: primary
                    is_authenticated: true
                    is_auto_sync_enabled: true
                    settings:
                      all_day_events: true
                      event_time_local: 09:00
                    created_at: '2026-05-30T12:00:00.000000Z'
                    updated_at: '2026-06-18T09:30:00.000000Z'
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  error:
                    type: string
                example:
                  success: false
                  error: Google Calendar integration not found for this user
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: patch-api-google-calendar-integrations-id
    delete:
      tags:
      - Google Calendar
      summary: Delete Google Calendar Connection
      description: 'Disconnect the authenticated user''s Google Calendar. The stored
        authorization is revoked and the connection removed, along with the user''s
        calendar sync subscriptions. Only the caller''s own connection can be deleted
        (404 otherwise).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: id
        in: path
        schema:
          type: integer
        required: true
        description: Google Calendar connection ID (must belong to the authenticated
          user)
        example: '3'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                example:
                  success: true
                  message: Google Calendar disconnected.
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  error:
                    type: string
                example:
                  success: false
                  error: Google Calendar integration not found for this user
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: delete-api-google-calendar-integrations-id
  /api/google-calendar/subscriptions/catalog:
    get:
      tags:
      - Google Calendar
      summary: List Calendar Sync Features
      description: 'The catalog of features that can sync to a user''s Google Calendar.
        Each entry''s `key` is the `feature_key` used when subscribing; `manage_route`
        is the in-app page where that feature''s data lives.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Currently available features: `po_cash_flow` (payment milestones from the
        purchase order cash-flow schedule) and `vendor_deposits` (vendor deposit due
        dates).


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        key:
                          type: string
                        label:
                          type: string
                        description:
                          type: string
                        manage_route:
                          type: string
                example:
                  success: true
                  data:
                  - key: po_cash_flow
                    label: Purchase Order Cash Flow
                    description: Payment milestones from the PO cash-flow schedule.
                    manage_route: /orders/purchase-orders/cash-flow-schedule
                  - key: vendor_deposits
                    label: Vendor Deposits
                    description: Vendor deposit due dates.
                    manage_route: /orders/vendor-deposits
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-google-calendar-subscriptions-catalog
  /api/google-calendar/subscriptions:
    get:
      tags:
      - Google Calendar
      summary: List Calendar Sync Subscriptions
      description: 'List the authenticated user''s calendar sync subscriptions — each
        one says "sync feature X to my Google Calendar".


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        feature_key:
                          type: string
                        feature_label:
                          type: string
                        manage_route:
                          type: string
                        is_enabled:
                          type: boolean
                        options:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                        updated_at:
                          type: string
                example:
                  success: true
                  data:
                  - id: 6
                    feature_key: po_cash_flow
                    feature_label: Purchase Order Cash Flow
                    manage_route: /orders/purchase-orders/cash-flow-schedule
                    is_enabled: true
                    options: null
                    created_at: '2026-06-01T10:00:00.000000Z'
                    updated_at: '2026-06-01T10:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-google-calendar-subscriptions
    post:
      tags:
      - Google Calendar
      summary: Create Calendar Sync Subscription
      description: 'Subscribe the authenticated user to a calendar sync feature so
        its events appear on their connected Google Calendar.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Body fields:**

        - `feature_key` (required, string) — one of the keys from List Calendar Sync
        Features (`po_cash_flow`, `vendor_deposits`).

        - `options` (optional, object) — feature-specific options.


        Returns the created (or re-enabled) subscription. 400 when subscribing fails
        (e.g. no Google Calendar connection).


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                feature_key:
                  type: string
                options:
                  type: string
                  nullable: true
              example:
                feature_key: po_cash_flow
                options: null
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      feature_key:
                        type: string
                      feature_label:
                        type: string
                      manage_route:
                        type: string
                      is_enabled:
                        type: boolean
                      options:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  success: true
                  data:
                    id: 6
                    feature_key: po_cash_flow
                    feature_label: Purchase Order Cash Flow
                    manage_route: /orders/purchase-orders/cash-flow-schedule
                    is_enabled: true
                    options: null
                    created_at: '2026-06-01T10:00:00.000000Z'
                    updated_at: '2026-06-01T10:00:00.000000Z'
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  error:
                    type: string
                  message:
                    type: string
                example:
                  success: false
                  error: Failed to subscribe to feature
                  message: Connect Google Calendar before subscribing to a sync feature.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-google-calendar-subscriptions
  /api/google-calendar/subscriptions/{featureKey}/sync-now:
    post:
      tags:
      - Google Calendar
      summary: Sync Calendar Feature Now
      description: 'Manually queue a sync of the authenticated user''s Google Calendar
        for the given feature — useful for immediate confirmation instead of waiting
        for the scheduled sync.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **This endpoint is asynchronous**: it queues a background sync and returns
        immediately; the calendar updates shortly after.


        404 for an unknown feature key; 400 when the user is not subscribed to the
        feature.


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: featureKey
        in: path
        schema:
          type: string
        required: true
        description: Feature key (po_cash_flow or vendor_deposits)
        example: po_cash_flow
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                example:
                  success: true
                  message: Sync queued.
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  error:
                    type: string
                example:
                  success: false
                  error: Not subscribed to this feature
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  error:
                    type: string
                example:
                  success: false
                  error: Unknown feature key
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-google-calendar-subscriptions-featurekey-sync-now
  /api/google-calendar/subscriptions/{featureKey}:
    delete:
      tags:
      - Google Calendar
      summary: Delete Calendar Sync Subscription
      description: 'Unsubscribe the authenticated user from a calendar sync feature.
        Events already created on the user''s Google Calendar for this feature are
        removed by the sync.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        404 for an unknown feature key.


        Authentication: Requires Bearer token.'
      parameters:
      - name: featureKey
        in: path
        schema:
          type: string
        required: true
        description: Feature key (po_cash_flow or vendor_deposits)
        example: po_cash_flow
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                example:
                  success: true
                  message: Unsubscribed.
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  error:
                    type: string
                example:
                  success: false
                  error: Unknown feature key
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: delete-api-google-calendar-subscriptions-featurekey
  /api/v2/google/connection:
    get:
      tags:
      - Google Sheets
      summary: Get Google Connection
      description: 'Return the authenticated user''s Google connection status. The
        connection is per-user and grants access only to sheets the app creates or
        the user picks (drive.file scope).


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      connected:
                        type: boolean
                      google_email:
                        type: string
                      scopes:
                        type: array
                        items:
                          type: string
                      status:
                        type: string
                example:
                  data:
                    connected: true
                    google_email: jane@acme.com
                    scopes:
                    - https://www.googleapis.com/auth/drive.file
                    status: connected
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-v2-google-connection
    delete:
      tags:
      - Google Sheets
      summary: Disconnect Google
      description: 'Revoke and remove the authenticated user''s Google connection.


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      connected:
                        type: boolean
                      google_email:
                        type: string
                        nullable: true
                      scopes:
                        type: array
                      status:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    connected: false
                    google_email: null
                    scopes: []
                    status: disconnected
                  message: Google disconnected.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: delete-api-v2-google-connection
  /api/v2/google/connection/initiate:
    post:
      tags:
      - Google Sheets
      summary: Connect Google
      description: 'Start the Google authorization flow. Returns a consent URL to
        open in the browser; after the user consents, the connection is stored server-side.
        Only the non-sensitive drive.file scope is requested.


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      url:
                        type: string
                example:
                  data:
                    url: https://accounts.google.com/o/oauth2/v2/auth?client_id=...&scope=https://www.googleapis.com/auth/drive.file&state=...
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-v2-google-connection-initiate
  /api/v2/google/sheets/export:
    post:
      tags:
      - Google Sheets
      summary: Export to Google Sheet
      description: 'Create a new Google Sheet (or refresh an existing linked sheet
        when sheet_link_id is provided) populated with the supplied rows. entity_type
        must be a supported import entity (e.g. products). Include an `id` column
        so edits pulled back are applied as updates; rows with a blank id are inserts.


        Row sets above the sync limit are written as a background job — the response
        returns tracked_job_log_id and no url until it completes.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                entity_type:
                  type: string
                rows:
                  type: array
                  items:
                    type: object
                    properties:
                      id:
                        type: integer
                      sku:
                        type: string
                      name:
                        type: string
                title:
                  type: string
                filter_signature:
                  type: string
                  nullable: true
                sheet_link_id:
                  type: string
                  nullable: true
              example:
                entity_type: products
                rows:
                - id: 5
                  sku: ABC-123
                  name: Blue Widget
                - id: ''
                  sku: NEW-001
                  name: New Product
                title: SKU Products
                filter_signature: null
                sheet_link_id: null
      parameters: []
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      sheet_link_id:
                        type: integer
                      spreadsheet_id:
                        type: string
                      url:
                        type: string
                      row_count:
                        type: integer
                      tracked_job_log_id:
                        type: string
                        nullable: true
                example:
                  data:
                    sheet_link_id: 12
                    spreadsheet_id: 1AbCdEfGhIjKlMnOpQrStUvWxYz0123456789ABCDEFG
                    url: https://docs.google.com/spreadsheets/d/1AbCdEfGhIjKlMnOpQrStUvWxYz0123456789ABCDEFG/edit
                    row_count: 2
                    tracked_job_log_id: null
        '202':
          description: Accepted
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      sheet_link_id:
                        type: string
                        nullable: true
                      spreadsheet_id:
                        type: string
                        nullable: true
                      url:
                        type: string
                        nullable: true
                      row_count:
                        type: integer
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    sheet_link_id: null
                    spreadsheet_id: null
                    url: null
                    row_count: 25000
                    tracked_job_log_id: 9876
                  message: Exporting to Google Sheets — track progress with the returned
                    tracked_job_log_id.
        '409':
          description: Conflict
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  code:
                    type: string
                example:
                  message: Google is not connected. Connect your Google account in
                    Settings.
                  code: google_not_connected
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-v2-google-sheets-export
  /api/v2/google/sheets/links:
    get:
      tags:
      - Google Sheets
      summary: List Linked Google Sheets
      description: 'List the authenticated user''s linked Google Sheets for an entity
        type.


        Authentication: Requires Bearer token.'
      parameters:
      - name: entity_type
        in: query
        schema:
          type: string
        description: Entity type to list linked sheets for (required).
        example: products
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        entity_type:
                          type: string
                        spreadsheet_id:
                          type: string
                        url:
                          type: string
                        data_sheet_name:
                          type: string
                        title:
                          type: string
                        column_mapping:
                          type: object
                          properties:
                            id:
                              type: string
                            SKU:
                              type: string
                            Name:
                              type: string
                        filter_signature:
                          type: string
                          nullable: true
                        row_count:
                          type: integer
                        is_stale:
                          type: boolean
                        created_by:
                          type: string
                        last_pulled_at:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                        updated_at:
                          type: string
                example:
                  data:
                  - id: 12
                    entity_type: products
                    spreadsheet_id: 1AbCdEfGhIjKlMnOpQrStUvWxYz0123456789ABCDEFG
                    url: https://docs.google.com/spreadsheets/d/1AbCdEfGhIjKlMnOpQrStUvWxYz0123456789ABCDEFG/edit
                    data_sheet_name: Data
                    title: SKU Products
                    column_mapping:
                      id: id
                      SKU: sku
                      Name: name
                    filter_signature: null
                    row_count: 2
                    is_stale: false
                    created_by: Jane
                    last_pulled_at: null
                    created_at: '2026-07-11T14:30:00.000000Z'
                    updated_at: '2026-07-11T14:30:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-v2-google-sheets-links
  /api/v2/google/sheets/{sheetLink}/pull:
    post:
      tags:
      - Google Sheets
      summary: Pull Changes From Google Sheet
      description: 'Read a linked sheet''s current rows and start validation of the
        changes. Rows are matched on the `id` column (blank id inserts a new record).
        The response returns a data_import_id whose validation results and execution
        are handled through the standard import endpoints.


        Returns total_rows 0 with a null data_import_id when the sheet has only a
        header row.


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: sheetLink
        in: path
        schema:
          type: integer
        required: true
        description: Linked sheet id (from List Linked Google Sheets).
        example: '12'
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      data_import_id:
                        type: integer
                      tracked_job_log_id:
                        type: integer
                      total_rows:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    data_import_id: 45
                    tracked_job_log_id: 9881
                    total_rows: 2
                  message: Sheet read; validation started.
        '410':
          description: Gone
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  code:
                    type: string
                example:
                  message: This Google Sheet no longer exists or is no longer accessible.
                    Create a new one.
                  code: sheet_unavailable
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  code:
                    type: string
                  data:
                    type: object
                    properties:
                      missing_headers:
                        type: array
                        items:
                          type: string
                      extra_headers:
                        type: array
                example:
                  message: The sheet columns no longer match the linked mapping. Reconcile
                    the columns before pulling.
                  code: header_drift
                  data:
                    missing_headers:
                    - SKU
                    extra_headers: []
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-v2-google-sheets-sheetlink-pull
  /api/v2/google/sheets/{sheetLink}:
    patch:
      tags:
      - Google Sheets
      summary: Rename Google Sheet
      description: 'Rename a linked Google Sheet. Renames the Google Sheet in your
        Drive and updates the stored label so the two stay in sync. Only the sheet''s
        owner can rename it.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                title:
                  type: string
              example:
                title: Q3 reorder planning
      parameters:
      - name: sheetLink
        in: path
        schema:
          type: integer
        required: true
        description: Linked sheet id (from List Linked Google Sheets).
        example: '12'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      entity_type:
                        type: string
                      spreadsheet_id:
                        type: string
                      url:
                        type: string
                      data_sheet_name:
                        type: string
                      title:
                        type: string
                      column_mapping:
                        type: object
                        properties:
                          id:
                            type: string
                          SKU:
                            type: string
                          Name:
                            type: string
                      filter_signature:
                        type: string
                        nullable: true
                      row_count:
                        type: integer
                      is_stale:
                        type: boolean
                      created_by:
                        type: string
                      last_pulled_at:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 12
                    entity_type: products
                    spreadsheet_id: 1ymf6PauZBgU0dWgLDWcZKUCBZ_bvPVVb1JOUWMTsM3A
                    url: https://docs.google.com/spreadsheets/d/1ymf6PauZBgU0dWgLDWcZKUCBZ_bvPVVb1JOUWMTsM3A/edit
                    data_sheet_name: Data
                    title: Q3 reorder planning
                    column_mapping:
                      id: id
                      SKU: sku
                      Name: name
                    filter_signature: null
                    row_count: 27
                    is_stale: false
                    created_by: Jane
                    last_pulled_at: '2026-07-13T08:19:50.000000Z'
                    created_at: '2026-07-13T08:10:00.000000Z'
                    updated_at: '2026-07-13T09:02:00.000000Z'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      title:
                        type: array
                        items:
                          type: string
                example:
                  message: The title field is required.
                  errors:
                    title:
                    - The title field is required.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: patch-api-v2-google-sheets-sheetlink
    delete:
      tags:
      - Google Sheets
      summary: Unlink Google Sheet
      description: 'Unlink a Google Sheet from SKU. This removes the link only — the
        Google Sheet itself stays untouched in your Google Drive. Only the sheet''s
        owner can unlink it.


        Authentication: Requires Bearer token.'
      parameters:
      - name: sheetLink
        in: path
        schema:
          type: integer
        required: true
        description: Linked sheet id (from List Linked Google Sheets).
        example: '12'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Sheet unlinked.
        '403':
          description: Forbidden
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: This action is unauthorized.
        '429': *id001
        '401': *id002
        '404': *id004
      operationId: delete-api-v2-google-sheets-sheetlink
  /api/airtable/authorize:
    get:
      tags:
      - Airtable
      summary: Get OAuth Authorize URL
      description: 'Build the Airtable authorization URL that starts the connect flow.
        Open the returned authorization_url in a browser so the account owner can
        grant access; Airtable then redirects back to SKU.io to finish the connection.
        Pass the optional instance_id query parameter to re-authorize an existing
        connection instead of creating a new one.


        Authentication: Requires Bearer token.'
      parameters:
      - name: instance_id
        in: query
        schema:
          type: integer
        example: '7'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      authorization_url:
                        type: string
                example:
                  data:
                    authorization_url: https://airtable.com/oauth2/v1/authorize?client_id=abc123&redirect_uri=https%3A%2F%2Facme.sku.io%2Fairtable%2Fauth%2Fcallback&response_type=code&scope=data.records%3Aread%20data.records%3Awrite%20schema.bases%3Aread%20schema.bases%3Awrite&state=acme.t0k3n&code_challenge=E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM&code_challenge_method=S256
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-airtable-authorize
  /api/airtable/integrations:
    get:
      tags:
      - Airtable
      summary: List Airtable Connections
      description: 'List the Airtable connections for the current account, including
        connection status, the granting Airtable account, granted scopes, and monthly
        API usage against the plan cap.


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        connection_status:
                          type: string
                        is_connected:
                          type: boolean
                        account_id:
                          type: string
                        account_email:
                          type: string
                        granted_scopes:
                          type: array
                          items:
                            type: string
                        is_automatic_sync_enabled:
                          type: boolean
                        api_usage:
                          type: object
                          properties:
                            used:
                              type: integer
                            cap:
                              type: integer
                            percent:
                              type: integer
                            near_cap:
                              type: boolean
                            over_cap:
                              type: boolean
                        created_at:
                          type: string
                        updated_at:
                          type: string
                example:
                  data:
                  - id: 7
                    name: Ops Hub
                    connection_status: connected
                    is_connected: true
                    account_id: usr8Yh2Qw9Lm4Zx0
                    account_email: jane@acme.com
                    granted_scopes:
                    - data.records:read
                    - data.records:write
                    - schema.bases:read
                    - schema.bases:write
                    is_automatic_sync_enabled: true
                    api_usage:
                      used: 1840
                      cap: 50000
                      percent: 4
                      near_cap: false
                      over_cap: false
                    created_at: '2026-07-01T09:15:00+00:00'
                    updated_at: '2026-07-22T08:30:00+00:00'
                  - id: 9
                    name: Analytics Base
                    connection_status: connected
                    is_connected: true
                    account_id: usr8Yh2Qw9Lm4Zx0
                    account_email: jane@acme.com
                    granted_scopes:
                    - data.records:read
                    - data.records:write
                    - schema.bases:read
                    - schema.bases:write
                    is_automatic_sync_enabled: true
                    api_usage:
                      used: 1840
                      cap: 50000
                      percent: 4
                      near_cap: false
                      over_cap: false
                    created_at: '2026-07-01T09:15:00+00:00'
                    updated_at: '2026-07-22T08:30:00+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-airtable-integrations
  /api/airtable/instances/{instance}/whoami:
    get:
      tags:
      - Airtable
      summary: Verify Connection
      description: 'Verify a connection by calling Airtable with the stored token
        and returning the connected Airtable account id, email, and the scopes granted
        to the connection.


        Authentication: Requires Bearer token.'
      parameters:
      - name: instance
        in: path
        schema:
          type: integer
        required: true
        description: Airtable connection id (from List Airtable Connections).
        example: '7'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      account_id:
                        type: string
                      account_email:
                        type: string
                      scopes:
                        type: array
                        items:
                          type: string
                example:
                  data:
                    account_id: usr8Yh2Qw9Lm4Zx0
                    account_email: jane@acme.com
                    scopes:
                    - data.records:read
                    - data.records:write
                    - schema.bases:read
                    - schema.bases:write
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-airtable-instances-instance-whoami
  /api/airtable/instances/{instance}:
    delete:
      tags:
      - Airtable
      summary: Disconnect Airtable
      description: 'Disconnect an Airtable connection. This revokes the stored token
        and removes every dataset mapping that belonged to the connection.


        Authentication: Requires Bearer token.'
      parameters:
      - name: instance
        in: path
        schema:
          type: integer
        required: true
        description: Airtable connection id (from List Airtable Connections).
        example: '7'
      responses:
        '204':
          description: No Content
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties: {}
                example: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-airtable-instances-instance
  /api/airtable/datasets:
    get:
      tags:
      - Airtable
      summary: List Syncable Datasets
      description: 'List the catalog of SKU.io datasets that can be synced to Airtable.
        Each dataset lists the exportable fields available to map (with the target
        cell type) and whether it accepts inbound changes back from Airtable.


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        dataset:
                          type: string
                        label:
                          type: string
                        supports_inbound:
                          type: boolean
                        fields:
                          type: array
                          items:
                            type: object
                            properties:
                              source:
                                type: string
                              label:
                                type: string
                              type:
                                type: string
                              key:
                                type: boolean
                example:
                  data:
                  - dataset: products
                    label: Products
                    supports_inbound: true
                    fields:
                    - source: sku_io_id
                      label: SKU.io ID
                      type: text
                      key: true
                    - source: name
                      label: Name
                      type: text
                    - source: barcode
                      label: Barcode
                      type: text
                    - source: average_cost
                      label: Average Cost
                      type: currency
                    - source: price
                      label: Price
                      type: currency
                    - source: brand.name
                      label: Brand
                      type: text
                    - source: gross_margin_pct
                      label: Gross Margin %
                      type: number
                    - source: on_hand
                      label: On Hand
                      type: number
                    - source: units_sold_90d
                      label: Units Sold (90d)
                      type: number
                    - source: days_of_cover
                      label: Days of Cover
                      type: number
                    - source: sell_through_pct
                      label: Sell-through % (90d)
                      type: number
                    - source: is_archived
                      label: Archived
                      type: checkbox
                    - source: updated_at
                      label: Updated At
                      type: datetime
                  - dataset: sales_orders
                    label: Sales Orders
                    supports_inbound: true
                    fields:
                    - source: sku_io_id
                      label: SKU.io ID
                      type: text
                      key: true
                    - source: order_status
                      label: Order Status
                      type: text
                    - source: order_date
                      label: Order Date
                      type: datetime
                    - source: customer_name
                      label: Customer Name
                      type: text
                    - source: customer_email
                      label: Customer Email
                      type: text
                    - source: customer_company
                      label: Customer Company
                      type: text
                    - source: customer_phone
                      label: Customer Phone
                      type: text
                    - source: customer_po_number
                      label: Customer PO
                      type: text
                    - source: memo_for_customer
                      label: Customer Memo
                      type: text
                    - source: is_archived
                      label: Archived
                      type: checkbox
                    - source: updated_at
                      label: Updated At
                      type: datetime
                  - dataset: suppliers
                    label: Suppliers
                    supports_inbound: true
                    fields:
                    - source: sku_io_id
                      label: SKU.io ID
                      type: text
                      key: true
                    - source: name
                      label: Name
                      type: text
                    - source: company_name
                      label: Company
                      type: text
                    - source: primary_contact_name
                      label: Contact Name
                      type: text
                    - source: email
                      label: Email
                      type: text
                    - source: messaging_phone
                      label: Phone
                      type: text
                    - source: website
                      label: Website
                      type: text
                    - source: is_archived
                      label: Archived
                      type: checkbox
                    - source: updated_at
                      label: Updated At
                      type: datetime
                  - dataset: inventory_levels
                    label: Inventory Levels
                    supports_inbound: false
                    fields:
                    - source: sku_io_id
                      label: SKU.io ID
                      type: text
                      key: true
                    - source: product.sku
                      label: SKU
                      type: text
                    - source: warehouse.name
                      label: Warehouse
                      type: text
                    - source: inventory_available
                      label: Available
                      type: number
                    - source: updated_at
                      label: Updated At
                      type: datetime
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-airtable-datasets
  /api/airtable/instances/{instance}/bases:
    get:
      tags:
      - Airtable
      summary: List Airtable Bases
      description: 'List the Airtable bases the connection can access, with the permission
        level granted for each base.


        Authentication: Requires Bearer token.'
      parameters:
      - name: instance
        in: path
        schema:
          type: integer
        required: true
        description: Airtable connection id (from List Airtable Connections).
        example: '7'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: string
                        name:
                          type: string
                        permissionLevel:
                          type: string
                example:
                  data:
                  - id: appXt3kQ9vB2mLpZ1
                    name: Ops Hub
                    permissionLevel: create
                  - id: appLm5nR8sT1uV4wY
                    name: Warehouse Tracker
                    permissionLevel: edit
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-airtable-instances-instance-bases
  /api/airtable/instances/{instance}/bases/{baseId}/tables:
    get:
      tags:
      - Airtable
      summary: List Base Tables
      description: 'List the tables in an Airtable base along with each table''s fields.
        Use the field ids to build a mapping''s key field and field map.


        Authentication: Requires Bearer token.'
      parameters:
      - name: instance
        in: path
        schema:
          type: integer
        required: true
        description: Airtable connection id (from List Airtable Connections).
        example: '7'
      - name: baseId
        in: path
        schema:
          type: string
        required: true
        description: Airtable base id (from List Airtable Bases).
        example: appXt3kQ9vB2mLpZ1
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: string
                        name:
                          type: string
                        primaryFieldId:
                          type: string
                        fields:
                          type: array
                          items:
                            type: object
                            properties:
                              id:
                                type: string
                              name:
                                type: string
                              type:
                                type: string
                example:
                  data:
                  - id: tbl9aRk2Pq7WnE5cX
                    name: Products
                    primaryFieldId: fldName0000000001
                    fields:
                    - id: fldName0000000001
                      name: Name
                      type: singleLineText
                    - id: fldSkuIoIdKey0001
                      name: SKU.io ID
                      type: singleLineText
                    - id: fldPrice000000001
                      name: Price
                      type: currency
                    - id: fldBrand000000001
                      name: Brand
                      type: singleLineText
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-airtable-instances-instance-bases-baseid-tables
  /api/airtable/instances/{instance}/mappings:
    get:
      tags:
      - Airtable
      summary: List Mappings
      description: 'List the dataset mappings configured on a connection, with their
        target base and table, sync schedule, last sync result, and error count.


        Authentication: Requires Bearer token.'
      parameters:
      - name: instance
        in: path
        schema:
          type: integer
        required: true
        description: Airtable connection id (from List Airtable Connections).
        example: '7'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        dataset:
                          type: string
                        dataset_label:
                          type: string
                        direction:
                          type: string
                        base_id:
                          type: string
                        table_id:
                          type: string
                        key_field_id:
                          type: string
                        field_map:
                          type: array
                          items:
                            type: object
                            properties:
                              source:
                                type: string
                              target_field_id:
                                type: string
                        filters:
                          type: string
                          nullable: true
                        delete_mode:
                          type: string
                        schedule:
                          type: string
                        realtime_enabled:
                          type: boolean
                        apply_mode:
                          type: string
                          nullable: true
                        auto_create:
                          type: boolean
                        webhook_active:
                          type: boolean
                        is_enabled:
                          type: boolean
                        error_count:
                          type: integer
                        last_synced_at:
                          type: string
                        last_result:
                          type: object
                          properties:
                            created:
                              type: integer
                            updated:
                              type: integer
                            deleted:
                              type: integer
                            skipped:
                              type: integer
                            finished_at:
                              type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 42
                    integration_instance_id: 7
                    dataset: products
                    dataset_label: Products
                    direction: outbound
                    base_id: appXt3kQ9vB2mLpZ1
                    table_id: tbl9aRk2Pq7WnE5cX
                    key_field_id: fldSkuIoIdKey0001
                    field_map:
                    - source: name
                      target_field_id: fldName0000000001
                    - source: price
                      target_field_id: fldPrice000000001
                    - source: brand.name
                      target_field_id: fldBrand000000001
                    filters: null
                    delete_mode: flag
                    schedule: hourly
                    realtime_enabled: true
                    apply_mode: null
                    auto_create: true
                    webhook_active: false
                    is_enabled: true
                    error_count: 0
                    last_synced_at: '2026-07-22T08:00:00+00:00'
                    last_result:
                      created: 4
                      updated: 120
                      deleted: 0
                      skipped: 2
                      finished_at: '2026-07-22T08:00:07+00:00'
                    created_at: '2026-07-10T12:00:00+00:00'
                    updated_at: '2026-07-22T08:00:07+00:00'
                  current_page: 1
                  first_page_url: '{{protocol}}://{{domain}}/api/airtable/instances/7/mappings?page=1'
                  from: 1
                  last_page: 1
                  per_page: 10
                  to: 1
                  total: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-airtable-instances-instance-mappings
    post:
      tags:
      - Airtable
      summary: Create Mapping
      description: 'Create a dataset mapping that syncs a SKU.io dataset to a table
        in an Airtable base.


        Body fields:

        - dataset (string, required): the SKU.io dataset to sync. One of products,
        inventory_levels, sales_orders, sales_order_lines, purchase_orders, purchase_order_lines,
        suppliers.

        - direction (string, optional, default outbound): outbound sends SKU.io data
        to Airtable; inbound reads changes back. Inbound is only supported for the
        products dataset.

        - base_id (string, required): the target Airtable base id.

        - table_id (string, required): the target table id within the base.

        - key_field_id (string, required): the Airtable field that stores the SKU.io
        id and is used as the merge key for upserts.

        - field_map (array, required, min 1): each entry maps a SKU.io source field
        to an Airtable target field. Each item has source (string) and target_field_id
        (string).

        - filters (object, optional): optional filter conditions restricting which
        records sync.

        - delete_mode (string, optional, default flag): how records removed in SKU.io
        are handled in Airtable. One of flag, delete, ignore.

        - schedule (string, optional, default hourly): automatic sync cadence. One
        of fifteen_minutes, hourly, daily, manual.

        - realtime_enabled (boolean, optional, default false): push changes as they
        happen.

        - apply_mode (string, optional): for inbound mappings, whether changes are
        queued for review or applied automatically. One of review, auto.

        - auto_create (boolean, optional, default false): when true, create missing
        Airtable records during sync instead of only updating existing rows.

        - is_enabled (boolean, optional, default true): whether the mapping is active.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                dataset:
                  type: string
                direction:
                  type: string
                base_id:
                  type: string
                table_id:
                  type: string
                key_field_id:
                  type: string
                field_map:
                  type: array
                  items:
                    type: object
                    properties:
                      source:
                        type: string
                      target_field_id:
                        type: string
                filters:
                  type: string
                  nullable: true
                delete_mode:
                  type: string
                schedule:
                  type: string
                realtime_enabled:
                  type: boolean
                apply_mode:
                  type: string
                  nullable: true
                auto_create:
                  type: boolean
                is_enabled:
                  type: boolean
              example:
                dataset: products
                direction: outbound
                base_id: appXt3kQ9vB2mLpZ1
                table_id: tbl9aRk2Pq7WnE5cX
                key_field_id: fldSkuIoIdKey0001
                field_map:
                - source: name
                  target_field_id: fldName0000000001
                - source: price
                  target_field_id: fldPrice000000001
                - source: brand.name
                  target_field_id: fldBrand000000001
                filters: null
                delete_mode: flag
                schedule: hourly
                realtime_enabled: true
                apply_mode: null
                auto_create: true
                is_enabled: true
      parameters:
      - name: instance
        in: path
        schema:
          type: integer
        required: true
        description: Airtable connection id (from List Airtable Connections).
        example: '7'
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: integer
                  integration_instance_id:
                    type: integer
                  dataset:
                    type: string
                  dataset_label:
                    type: string
                  direction:
                    type: string
                  base_id:
                    type: string
                  table_id:
                    type: string
                  key_field_id:
                    type: string
                  field_map:
                    type: array
                    items:
                      type: object
                      properties:
                        source:
                          type: string
                        target_field_id:
                          type: string
                  filters:
                    type: string
                    nullable: true
                  delete_mode:
                    type: string
                  schedule:
                    type: string
                  realtime_enabled:
                    type: boolean
                  apply_mode:
                    type: string
                    nullable: true
                  auto_create:
                    type: boolean
                  webhook_active:
                    type: boolean
                  is_enabled:
                    type: boolean
                  error_count:
                    type: integer
                  last_synced_at:
                    type: string
                  last_result:
                    type: object
                    properties:
                      created:
                        type: integer
                      updated:
                        type: integer
                      deleted:
                        type: integer
                      skipped:
                        type: integer
                      finished_at:
                        type: string
                  created_at:
                    type: string
                  updated_at:
                    type: string
                example:
                  id: 42
                  integration_instance_id: 7
                  dataset: products
                  dataset_label: Products
                  direction: outbound
                  base_id: appXt3kQ9vB2mLpZ1
                  table_id: tbl9aRk2Pq7WnE5cX
                  key_field_id: fldSkuIoIdKey0001
                  field_map:
                  - source: name
                    target_field_id: fldName0000000001
                  - source: price
                    target_field_id: fldPrice000000001
                  - source: brand.name
                    target_field_id: fldBrand000000001
                  filters: null
                  delete_mode: flag
                  schedule: hourly
                  realtime_enabled: true
                  apply_mode: null
                  auto_create: true
                  webhook_active: false
                  is_enabled: true
                  error_count: 0
                  last_synced_at: '2026-07-22T08:00:00+00:00'
                  last_result:
                    created: 4
                    updated: 120
                    deleted: 0
                    skipped: 2
                    finished_at: '2026-07-22T08:00:07+00:00'
                  created_at: '2026-07-10T12:00:00+00:00'
                  updated_at: '2026-07-22T08:00:07+00:00'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      key_field_id:
                        type: array
                        items:
                          type: string
                      field_map:
                        type: array
                        items:
                          type: string
                example:
                  message: Choose the Airtable field that stores the SKU.io ID — it
                    is the merge key for syncing. (and 1 more error)
                  errors:
                    key_field_id:
                    - Choose the Airtable field that stores the SKU.io ID — it is
                      the merge key for syncing.
                    field_map:
                    - Map at least one field before saving.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-airtable-instances-instance-mappings
  /api/airtable/instances/{instance}/mappings/{mapping}:
    patch:
      tags:
      - Airtable
      summary: Update Mapping
      description: 'Update an existing dataset mapping. Send only the fields you want
        to change; omitted fields keep their current value.


        Body fields (all optional): key_field_id (string), field_map (array of source
        / target_field_id entries), filters (object or null), delete_mode (flag, delete,
        ignore), schedule (fifteen_minutes, hourly, daily, manual), realtime_enabled
        (boolean), apply_mode (review, auto, or null), auto_create (boolean), is_enabled
        (boolean).


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                schedule:
                  type: string
                realtime_enabled:
                  type: boolean
                auto_create:
                  type: boolean
                is_enabled:
                  type: boolean
              example:
                schedule: daily
                realtime_enabled: false
                auto_create: false
                is_enabled: true
      parameters:
      - name: instance
        in: path
        schema:
          type: integer
        required: true
        description: Airtable connection id (from List Airtable Connections).
        example: '7'
      - name: mapping
        in: path
        schema:
          type: integer
        required: true
        description: Dataset mapping id (from List Mappings).
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: integer
                  integration_instance_id:
                    type: integer
                  dataset:
                    type: string
                  dataset_label:
                    type: string
                  direction:
                    type: string
                  base_id:
                    type: string
                  table_id:
                    type: string
                  key_field_id:
                    type: string
                  field_map:
                    type: array
                    items:
                      type: object
                      properties:
                        source:
                          type: string
                        target_field_id:
                          type: string
                  filters:
                    type: string
                    nullable: true
                  delete_mode:
                    type: string
                  schedule:
                    type: string
                  realtime_enabled:
                    type: boolean
                  apply_mode:
                    type: string
                    nullable: true
                  auto_create:
                    type: boolean
                  webhook_active:
                    type: boolean
                  is_enabled:
                    type: boolean
                  error_count:
                    type: integer
                  last_synced_at:
                    type: string
                  last_result:
                    type: object
                    properties:
                      created:
                        type: integer
                      updated:
                        type: integer
                      deleted:
                        type: integer
                      skipped:
                        type: integer
                      finished_at:
                        type: string
                  created_at:
                    type: string
                  updated_at:
                    type: string
                example:
                  id: 42
                  integration_instance_id: 7
                  dataset: products
                  dataset_label: Products
                  direction: outbound
                  base_id: appXt3kQ9vB2mLpZ1
                  table_id: tbl9aRk2Pq7WnE5cX
                  key_field_id: fldSkuIoIdKey0001
                  field_map:
                  - source: name
                    target_field_id: fldName0000000001
                  - source: price
                    target_field_id: fldPrice000000001
                  - source: brand.name
                    target_field_id: fldBrand000000001
                  filters: null
                  delete_mode: flag
                  schedule: daily
                  realtime_enabled: false
                  apply_mode: null
                  auto_create: false
                  webhook_active: false
                  is_enabled: true
                  error_count: 0
                  last_synced_at: '2026-07-22T08:00:00+00:00'
                  last_result:
                    created: 4
                    updated: 120
                    deleted: 0
                    skipped: 2
                    finished_at: '2026-07-22T08:00:07+00:00'
                  created_at: '2026-07-10T12:00:00+00:00'
                  updated_at: '2026-07-22T08:00:07+00:00'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      field_map:
                        type: array
                        items:
                          type: string
                      field_map.0.target_field_id:
                        type: array
                        items:
                          type: string
                example:
                  message: The field map field must have at least 1 items.
                  errors:
                    field_map:
                    - The field map field must have at least 1 items.
                    field_map.0.target_field_id:
                    - The field_map.0.target_field_id field is required when field_map
                      is present.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: patch-api-airtable-instances-instance-mappings-mapping
    delete:
      tags:
      - Airtable
      summary: Delete Mapping
      description: 'Delete a dataset mapping. This stops future syncs for the mapping;
        records already written to Airtable are left in place.


        Authentication: Requires Bearer token.'
      parameters:
      - name: instance
        in: path
        schema:
          type: integer
        required: true
        description: Airtable connection id (from List Airtable Connections).
        example: '7'
      - name: mapping
        in: path
        schema:
          type: integer
        required: true
        description: Dataset mapping id (from List Mappings).
        example: '42'
      responses:
        '204':
          description: No Content
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties: {}
                example: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-airtable-instances-instance-mappings-mapping
  /api/airtable/instances/{instance}/mappings/{mapping}/sync:
    post:
      tags:
      - Airtable
      summary: Sync Mapping
      description: 'Trigger a sync run for a mapping now. The sync runs in the background;
        the response returns a tracked_job_log_id you can use to follow its progress.


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: instance
        in: path
        schema:
          type: integer
        required: true
        description: Airtable connection id (from List Airtable Connections).
        example: '7'
      - name: mapping
        in: path
        schema:
          type: integer
        required: true
        description: Dataset mapping id (from List Mappings).
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                example:
                  data:
                    tracked_job_log_id: 98765
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-airtable-instances-instance-mappings-mapping-sync
  /api/airtable/instances/{instance}/provision-template:
    post:
      tags:
      - Airtable
      summary: Provision Template Table
      description: 'Provision a ready-made Airtable base for the connection. This
        creates a pre-built base with tables and mappings for common datasets and
        runs an initial backfill in the background.


        Body fields:

        - workspace_id (string, required): the Airtable workspace to create the base
        in.

        - base_name (string, optional, default "SKU.io Ops Hub"): the name for the
        new base.

        - order_window_days (integer, optional, default 90, range 1–3650): how many
        days of recent orders to backfill.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                workspace_id:
                  type: string
                base_name:
                  type: string
                order_window_days:
                  type: integer
              example:
                workspace_id: wspYq2Zt6Bn8Kx3Rd
                base_name: SKU.io Ops Hub
                order_window_days: 90
      parameters:
      - name: instance
        in: path
        schema:
          type: integer
        required: true
        description: Airtable connection id (from List Airtable Connections).
        example: '7'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                example:
                  data:
                    tracked_job_log_id: 98766
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      workspace_id:
                        type: array
                        items:
                          type: string
                example:
                  message: The workspace id field is required.
                  errors:
                    workspace_id:
                    - The workspace id field is required.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-airtable-instances-instance-provision-template
  /api/airtable/instances/{instance}/inbound-changes:
    get:
      tags:
      - Airtable
      summary: List Inbound Changes
      description: 'List the queued inbound changes proposed from Airtable and awaiting
        review. Each change targets a SKU.io record (product, sales order, or supplier):
        link_type/link_id identify it, link_reference and link_route present it for
        navigation, and proposed lists each mapped field''s old and new value. Apply
        or reject them from the review queue.


        Supports pagination (page, per_page — default 10), sort (id, status, created_at,
        updated_at; prefix - for DESC), and filter[status] (pending, applied, rejected,
        failed, unmatched).


        Authentication: Requires Bearer token.'
      parameters:
      - name: instance
        in: path
        schema:
          type: integer
        required: true
        description: Airtable connection id (from List Airtable Connections).
        example: '7'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        mapping_id:
                          type: integer
                        airtable_record_id:
                          type: string
                        link_type:
                          type: string
                        link_id:
                          type: integer
                        link_type_label:
                          type: string
                        link_reference:
                          type: string
                        link_route:
                          type: string
                        proposed:
                          type: object
                          properties:
                            barcode:
                              type: object
                              properties:
                                old:
                                  type: string
                                new:
                                  type: string
                            name:
                              type: object
                              properties:
                                old:
                                  type: string
                                new:
                                  type: string
                        status:
                          type: string
                        error:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 301
                    mapping_id: 42
                    airtable_record_id: recQw7Yh2Kp9Lm4Zx
                    link_type: App\Models\Product
                    link_id: 512
                    link_type_label: Product
                    link_reference: ABC-123
                    link_route: /products/512
                    proposed:
                      barcode:
                        old: '0000000000'
                        new: 0123456789012
                      name:
                        old: Blue Widget
                        new: Blue Widget (2026)
                    status: pending
                    error: null
                    created_at: '2026-07-22T07:45:00+00:00'
                    updated_at: '2026-07-22T07:45:00+00:00'
                  - id: 302
                    mapping_id: 43
                    airtable_record_id: recSalesOrderAB12
                    link_type: App\Models\SalesOrder
                    link_id: 88
                    link_type_label: Sales Order
                    link_reference: SO-1042
                    link_route: /orders/sales-orders/88
                    proposed:
                      customer_company:
                        old: Acme LLC
                        new: Acme Inc
                    status: pending
                    error: null
                    created_at: '2026-07-22T07:50:00+00:00'
                    updated_at: '2026-07-22T07:50:00+00:00'
                  current_page: 1
                  first_page_url: '{{protocol}}://{{domain}}/api/airtable/instances/7/inbound-changes?page=1'
                  from: 1
                  last_page: 1
                  per_page: 10
                  to: 2
                  total: 2
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-airtable-instances-instance-inbound-changes
  /api/airtable/instances/{instance}/inbound-changes/apply:
    post:
      tags:
      - Airtable
      summary: Apply Inbound Changes
      description: 'Apply queued inbound changes back into SKU.io. Send "all": true
        to apply every pending change for the connection, or "ids": [..] to apply
        specific changes. Changes are applied in the background; the response returns
        a tracked_job_log_id to follow progress.


        Body fields:

        - all (boolean, optional): apply every pending change when true.

        - ids (array of integers, optional): the specific change ids to apply when
        all is not set.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                all:
                  type: boolean
                ids:
                  type: array
                  items:
                    type: integer
              example:
                all: false
                ids:
                - 301
                - 302
      parameters:
      - name: instance
        in: path
        schema:
          type: integer
        required: true
        description: Airtable connection id (from List Airtable Connections).
        example: '7'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                example:
                  data:
                    tracked_job_log_id: 98767
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-airtable-instances-instance-inbound-changes-apply
  /api/airtable/instances/{instance}/inbound-changes/reject:
    post:
      tags:
      - Airtable
      summary: Reject Inbound Changes
      description: 'Reject queued inbound changes so they are not applied. Send "all":
        true to reject every pending change for the connection, or "ids": [..] to
        reject specific changes.


        Body fields:

        - all (boolean, optional): reject every pending change when true.

        - ids (array of integers, optional): the specific change ids to reject when
        all is not set.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                all:
                  type: boolean
                ids:
                  type: array
                  items:
                    type: integer
              example:
                all: false
                ids:
                - 303
      parameters:
      - name: instance
        in: path
        schema:
          type: integer
        required: true
        description: Airtable connection id (from List Airtable Connections).
        example: '7'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      rejected:
                        type: integer
                example:
                  data:
                    rejected: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-airtable-instances-instance-inbound-changes-reject
  /api/products/{id}:
    get:
      tags:
      - Products
      summary: Get Product
      description: 'Get a single product by ID with all related data.


        :::info[Required scope: `products:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Returns 404 if product not found.'
      parameters:
      - name: id
        in: path
        schema:
          type: integer
        required: true
        description: Product ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      sku:
                        type: string
                      name:
                        type: string
                      barcode:
                        type: string
                      mpn:
                        type: string
                      hts_code:
                        type: string
                      type:
                        type: string
                      is_lot_tracked:
                        type: boolean
                      lot_tracking_method:
                        type: string
                      shelf_life_days:
                        type: integer
                      near_expiry_threshold_days:
                        type: integer
                      min_remaining_shelf_life_days:
                        type: integer
                      expiry_aware_availability:
                        type: boolean
                      image_url:
                        type: string
                      has_inventory_movements:
                        type: boolean
                      brand:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      tags:
                        type: array
                        items:
                          type: string
                      is_variation:
                        type: boolean
                      weight:
                        type: string
                      weight_unit:
                        type: string
                      length:
                        type: string
                      width:
                        type: string
                      height:
                        type: string
                      dimension_unit:
                        type: string
                      case_quantity:
                        type: integer
                      case_weight:
                        type: string
                      case_weight_unit:
                        type: string
                      fba_prep_instructions:
                        type: string
                      price:
                        type: object
                        properties:
                          Default:
                            type: object
                            properties:
                              price:
                                type: number
                      average_cost:
                        type: object
                        properties:
                          value:
                            type: number
                          currency:
                            type: string
                      default_supplier:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      default_supplier_sku:
                        type: string
                      default_supplier_leadtime:
                        type: integer
                      default_supplier_moq:
                        type: integer
                      default_supplier_price:
                        type: number
                      min_stock_level:
                        type: integer
                      target_stock_days:
                        type: integer
                      inventory_total:
                        type: integer
                      inventory_available:
                        type: integer
                      inventory_available_to_sell:
                        type: integer
                      inventory_allocated:
                        type: integer
                      inventory_on_hold:
                        type: integer
                      inventory_incoming:
                        type: integer
                      category_main:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      attributes:
                        type: object
                        properties: {}
                      sales_nominal_code_id:
                        type: string
                        nullable: true
                      cogs_nominal_code_id:
                        type: string
                        nullable: true
                      default_tax_rate_id:
                        type: string
                        nullable: true
                      is_taxable:
                        type: boolean
                      archived_at:
                        type: string
                        nullable: true
                      stock_uom_id:
                        type: integer
                      stock_uom_code:
                        type: string
                      stock_uom_name:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                  status:
                    type: string
                example:
                  data:
                    id: 1
                    sku: SKU-001
                    name: Blue Widget
                    barcode: 0123456789012
                    mpn: BW-001
                    hts_code: 8471.30.0100
                    type: standard
                    is_lot_tracked: true
                    lot_tracking_method: fifo
                    shelf_life_days: 180
                    near_expiry_threshold_days: 60
                    min_remaining_shelf_life_days: 105
                    expiry_aware_availability: true
                    image_url: https://cdn.example.com/products/blue-widget.jpg
                    has_inventory_movements: true
                    brand:
                      id: 3
                      name: Acme Co
                    tags:
                    - new
                    - featured
                    is_variation: false
                    weight: '0.5'
                    weight_unit: kg
                    length: '10.0'
                    width: '5.0'
                    height: '3.0'
                    dimension_unit: cm
                    case_quantity: 12
                    case_weight: '6.0'
                    case_weight_unit: kg
                    fba_prep_instructions: Bubble wrap required
                    price:
                      Default:
                        price: 29.99
                    average_cost:
                      value: 12.5
                      currency: USD
                    default_supplier:
                      id: 5
                      name: Main Supplier
                    default_supplier_sku: MS-BW-001
                    default_supplier_leadtime: 14
                    default_supplier_moq: 100
                    default_supplier_price: 10.0
                    min_stock_level: 50
                    target_stock_days: 30
                    inventory_total: 150
                    inventory_available: 120
                    inventory_available_to_sell: 115
                    inventory_allocated: 30
                    inventory_on_hold: 0
                    inventory_incoming: 200
                    category_main:
                      id: 2
                      name: Widgets
                    attributes: {}
                    sales_nominal_code_id: null
                    cogs_nominal_code_id: null
                    default_tax_rate_id: null
                    is_taxable: false
                    archived_at: null
                    stock_uom_id: 1
                    stock_uom_code: EACH
                    stock_uom_name: Each
                    created_at: '2024-01-15T10:30:00.000000Z'
                    updated_at: '2024-06-01T08:00:00.000000Z'
                  status: success
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      id:
                        type: array
                        items:
                          type: string
                example:
                  message: Product not found
                  errors:
                    id:
                    - Product not found
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: products:read
      operationId: get-api-products-id
    put:
      tags:
      - Products
      summary: Update Product
      description: 'Update an existing product by ID. All fields are optional on update.


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Product type cannot be changed if inventory movements exist (exception: standard
        -> kit is allowed). Additionally, an inventory-bearing product (standard/kit/blemished/manufactured)
        cannot be converted to a non-inventory type (bundle/matrix) while it still
        carries any inventory ledger - a FIFO layer OR an inventory movement of any
        type (including stock_take, receipt, adjustment, transfer). This prevents
        orphaning stock layers and movements.


        For update (PUT), additional field available:

        - initial_inventory.warehouses[].id (required with initial_inventory)

        - initial_inventory.warehouses[].quantity (required)

        - initial_inventory.warehouses[0].unit_cost (required)

        - images[].id — required only when images[].operation is delete

        - images[].operation — nullable|in:update_create,delete


        **Optional field:** `mpn` (string, max 255, nullable) — manufacturer part
        number.


        **Optional field:** `hts_code` (string, max 255, nullable) — Harmonized Tariff
        Schedule code.


        Returns 422 if product type change is invalid.


        **Bundle / Kit components:** When the resulting product type is `bundle` or
        `kit`, `components[]` must be present and non-empty. This applies whether
        you are (a) changing the type from `standard` → `bundle|kit`, (b) updating
        an existing bundle/kit that currently has no components, or (c) sending an
        empty `components: []` payload (which would otherwise wipe components). Returns
        a 422 validation error on the `components` field in these cases. Updates that
        don''t touch `components` on a bundle/kit which already has components are
        unaffected. To convert a `standard` product that has no components yet, supply
        `components[]` in the same request as the `type` change — the components are
        saved as part of the same update, satisfying the requirement atomically.


        **Note (pricing tiers):** When sending `suppliers[].pricing[]` entries with
        `operation: updateOrCreate` (or omitted), `price` is **required** and must
        be a numeric value `>= 0` and `< 100000`. To remove a tier, send `operation:
        "delete"`. Sending `price: null` will return a `422` validation error on `suppliers.{i}.pricing.{j}.price`.


        **Lot tracking fields** (optional):

        - `is_lot_tracked` (boolean, nullable) — enable batch/lot tracking for this
        product.

        - `lot_tracking_method` (string, nullable) — required when `is_lot_tracked`
        is true. Allowed values: `fifo` (First-In, First-Out), `fefo` (First-Expiry,
        First-Out).


        **Stock unit of measure** (optional):

        - `stock_uom_id` (integer, nullable) — id of a row in `units_of_measure`.
        When omitted, the product is auto-assigned `EACH` as its stock UoM on create.
        Pick `KG`, `L`, etc. for bulk weight or volume products so quantities, purchase
        orders, sales orders, and stock takes use the correct unit from day one.


        Also accepts expiration_offset_months (integer 0-120, nullable) — the product''s
        default FBA-inbound shelf-life estimate in months; blank uses the app default
        (10). Responses include it too.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                sku:
                  type: string
                name:
                  type: string
                type:
                  type: string
                is_lot_tracked:
                  type: boolean
                lot_tracking_method:
                  type: string
                shelf_life_days:
                  type: integer
                near_expiry_threshold_days:
                  type: integer
                min_remaining_shelf_life_days:
                  type: integer
                expiry_aware_availability:
                  type: boolean
                barcode:
                  type: string
                mpn:
                  type: string
                hts_code:
                  type: string
                brand_name:
                  type: string
                weight:
                  type: number
                weight_unit:
                  type: string
                min_stock_level:
                  type: integer
                target_stock_days:
                  type: integer
                stock_uom_id:
                  type: string
                  nullable: true
                pricing:
                  type: array
                  items:
                    type: object
                    properties:
                      product_pricing_tier_name:
                        type: string
                      price:
                        type: number
                suppliers:
                  type: array
                  items:
                    type: object
                    properties:
                      supplier_id:
                        type: integer
                      is_default:
                        type: boolean
                      supplier_sku:
                        type: string
                      leadtime:
                        type: integer
                      minimum_order_quantity:
                        type: integer
                tags:
                  type: array
                  items:
                    type: string
                initial_inventory:
                  type: object
                  properties:
                    warehouses:
                      type: array
                      items:
                        type: object
                        properties:
                          id:
                            type: integer
                          quantity:
                            type: integer
                          unit_cost:
                            type: number
                shared_children_attributes:
                  type: array
              example:
                sku: SKU-001-UPDATED
                name: Updated Blue Widget
                type: standard
                is_lot_tracked: true
                lot_tracking_method: fifo
                shelf_life_days: 180
                near_expiry_threshold_days: 60
                min_remaining_shelf_life_days: 105
                expiry_aware_availability: true
                barcode: '1234567890124'
                mpn: MPN-12345
                hts_code: 8471.30.0100
                brand_name: Acme Co
                weight: 0.6
                weight_unit: kg
                min_stock_level: 60
                target_stock_days: 45
                stock_uom_id: null
                pricing:
                - product_pricing_tier_name: Default
                  price: 34.99
                suppliers:
                - supplier_id: 5
                  is_default: true
                  supplier_sku: MS-BW-001-V2
                  leadtime: 10
                  minimum_order_quantity: 50
                tags:
                - updated
                initial_inventory:
                  warehouses:
                  - id: 1
                    quantity: 100
                    unit_cost: 12.5
                shared_children_attributes: []
      parameters:
      - name: id
        in: path
        schema:
          type: integer
        required: true
        description: Product ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      sku:
                        type: string
                      name:
                        type: string
                      type:
                        type: string
                      is_lot_tracked:
                        type: boolean
                      lot_tracking_method:
                        type: string
                      shelf_life_days:
                        type: integer
                      near_expiry_threshold_days:
                        type: integer
                      min_remaining_shelf_life_days:
                        type: integer
                      expiry_aware_availability:
                        type: boolean
                      updated_at:
                        type: string
                  message:
                    type: string
                  status:
                    type: string
                example:
                  data:
                    id: 1
                    sku: SKU-001-UPDATED
                    name: Updated Blue Widget
                    type: standard
                    is_lot_tracked: true
                    lot_tracking_method: fifo
                    shelf_life_days: 180
                    near_expiry_threshold_days: 60
                    min_remaining_shelf_life_days: 105
                    expiry_aware_availability: true
                    updated_at: '2024-06-15T14:00:00.000000Z'
                  message: Product SKU-001-UPDATED updated successfully
                  status: success
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 422 Type Change Error
                  value:
                    message: Product has inventory movements. Cannot update product
                      type
                example-1:
                  summary: 422 Type Conversion Error (inventory ledger present)
                  value:
                    message: Product has inventory history (stock layers or movements).
                      Cannot convert it to a non-inventory product type.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: products:write
      operationId: put-api-products-id
    delete:
      tags:
      - Products
      summary: Delete Product
      description: 'Delete a product by ID. Deletion fails if the product (or, for
        a matrix parent, any of its variations) is still referenced by a RESTRICT
        foreign key: sales order lines, bundle sales order lines, purchase order lines,
        inventory movements, FIFO layers, inventory adjustments, assembly lines, warehouse
        transfer lines, return receipt lines, RMA lines, sales credit lines, inbound
        shipment lines, blemished products, or subscription editions.


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Returns 400 Bad Request with reason details if the product is in use.'
      parameters:
      - name: id
        in: path
        schema:
          type: integer
        required: true
        description: Product ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  status:
                    type: string
                example:
                  message: Product SKU-001 deleted successfully
                  status: success
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: array
                    items:
                      type: object
                      properties:
                        message:
                          type: string
                        code:
                          type: string
                        field:
                          type: string
                example:
                  message: Product SKU-001 could not be deleted
                  errors:
                  - message: Product is linked to sales orders
                    code: SalesOrderResourceLinked
                    field: salesOrderLines
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: products:write
      operationId: delete-api-products-id
  /api/products/by-sku:
    get:
      tags:
      - Products
      summary: Get Product by SKU
      description: 'Get a product by its exact SKU.


        :::info[Required scope: `products:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Returns 422 if sku parameter is missing. Returns 404 (ModelNotFoundException)
        if SKU not found.'
      parameters:
      - name: sku
        in: query
        schema:
          type: string
        description: Required. Exact SKU to look up.
        example: SKU-001
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      sku:
                        type: string
                      name:
                        type: string
                      type:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                  status:
                    type: string
                example:
                  data:
                    id: 1
                    sku: SKU-001
                    name: Blue Widget
                    type: standard
                    archived_at: null
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: products:read
      operationId: get-api-products-by-sku
  /api/products:
    post:
      tags:
      - Products
      summary: Create Product
      description: 'Create a new product.


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Required fields: sku (unique), type

        Product types: standard, bundle, kit, matrix

        Weight units: kg, lb, oz, g

        Dimension units: cm, in, mm, ft


        For bundle/kit products, `components[]` is **required** and must contain at
        least one component (each entry has `id` and `quantity`). Saving a bundle
        or kit with an empty `components` array (or without providing one when creating,
        or when changing type to bundle/kit) returns a 422 validation error on the
        `components` field.

        For matrix products (parent), include variations[] with sku and attributes.


        **Optional field:** `mpn` (string, max 255, nullable) — manufacturer part
        number.


        **Optional field:** `hts_code` (string, max 255, nullable) — Harmonized Tariff
        Schedule code.


        Returns 422 validation error if SKU already exists or other validation fails.


        **Note (pricing tiers):** When sending `suppliers[].pricing[]` entries with
        `operation: updateOrCreate` (or omitted), `price` is **required** and must
        be a numeric value `>= 0` and `< 100000`. To remove a tier, send `operation:
        "delete"`. Sending `price: null` will return a `422` validation error on `suppliers.{i}.pricing.{j}.price`.


        **Lot tracking fields** (optional):

        - `is_lot_tracked` (boolean, nullable) — enable batch/lot tracking for this
        product.

        - `lot_tracking_method` (string, nullable) — required when `is_lot_tracked`
        is true. Allowed values: `fifo` (First-In, First-Out), `fefo` (First-Expiry,
        First-Out).


        **Stock unit of measure** (optional):

        - `stock_uom_id` (integer, nullable) — id of a row in `units_of_measure`.
        When omitted, the product is auto-assigned `EACH` as its stock UoM on create.
        Pick `KG`, `L`, etc. for bulk weight or volume products so quantities, purchase
        orders, sales orders, and stock takes use the correct unit from day one.


        **Requires permission:** `products.create`


        Also accepts expiration_offset_months (integer 0-120, nullable) — the product''s
        default FBA-inbound shelf-life estimate in months; blank uses the app default
        (10). Responses include it too.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                sku:
                  type: string
                name:
                  type: string
                type:
                  type: string
                is_lot_tracked:
                  type: boolean
                lot_tracking_method:
                  type: string
                shelf_life_days:
                  type: integer
                near_expiry_threshold_days:
                  type: integer
                min_remaining_shelf_life_days:
                  type: integer
                expiry_aware_availability:
                  type: boolean
                barcode:
                  type: string
                mpn:
                  type: string
                hts_code:
                  type: string
                brand_name:
                  type: string
                weight:
                  type: number
                weight_unit:
                  type: string
                length:
                  type: integer
                width:
                  type: integer
                height:
                  type: integer
                dimension_unit:
                  type: string
                case_quantity:
                  type: integer
                case_weight:
                  type: integer
                case_weight_unit:
                  type: string
                case_length:
                  type: integer
                case_width:
                  type: integer
                case_height:
                  type: integer
                case_dimension_unit:
                  type: string
                fba_prep_instructions:
                  type: string
                target_stock_days:
                  type: integer
                min_stock_level:
                  type: integer
                proforma_landed_cost_percentage:
                  type: integer
                proforma_shipping_cost:
                  type: number
                stock_uom_id:
                  type: string
                  nullable: true
                sales_nominal_code_id:
                  type: string
                  nullable: true
                cogs_nominal_code_id:
                  type: string
                  nullable: true
                default_tax_rate_id:
                  type: string
                  nullable: true
                is_dropshippable:
                  type: boolean
                is_decoration_consumable:
                  type: boolean
                parent_id:
                  type: string
                  nullable: true
                tags:
                  type: array
                  items:
                    type: string
                tags_operation:
                  type: string
                pricing:
                  type: array
                  items:
                    type: object
                    properties:
                      product_pricing_tier_name:
                        type: string
                      price:
                        type: number
                suppliers:
                  type: array
                  items:
                    type: object
                    properties:
                      supplier_id:
                        type: integer
                      is_default:
                        type: boolean
                      supplier_sku:
                        type: string
                      leadtime:
                        type: integer
                      minimum_order_quantity:
                        type: integer
                      pricing:
                        type: array
                        items:
                          type: object
                          properties:
                            supplier_pricing_tier_name:
                              type: string
                            price:
                              type: integer
                categories:
                  type: array
                  items:
                    type: object
                    properties:
                      category_id:
                        type: integer
                      is_primary:
                        type: boolean
                attributes:
                  type: array
                  items:
                    type: object
                    properties:
                      name:
                        type: string
                      value:
                        type: string
                images:
                  type: array
                  items:
                    type: object
                    properties:
                      url:
                        type: string
                      name:
                        type: string
                      is_primary:
                        type: boolean
                      download:
                        type: boolean
                components:
                  type: array
                variations:
                  type: array
              example:
                sku: SKU-NEW-001
                name: New Product
                type: standard
                is_lot_tracked: true
                lot_tracking_method: fifo
                shelf_life_days: 180
                near_expiry_threshold_days: 60
                min_remaining_shelf_life_days: 105
                expiry_aware_availability: true
                barcode: '1234567890123'
                mpn: MPN-12345
                hts_code: 8471.30.0100
                brand_name: Acme Co
                weight: 0.5
                weight_unit: kg
                length: 10
                width: 5
                height: 3
                dimension_unit: cm
                case_quantity: 12
                case_weight: 6
                case_weight_unit: kg
                case_length: 30
                case_width: 20
                case_height: 15
                case_dimension_unit: cm
                fba_prep_instructions: Bubble wrap required
                target_stock_days: 30
                min_stock_level: 50
                proforma_landed_cost_percentage: 5
                proforma_shipping_cost: 2.5
                stock_uom_id: null
                sales_nominal_code_id: null
                cogs_nominal_code_id: null
                default_tax_rate_id: null
                is_dropshippable: false
                is_decoration_consumable: false
                parent_id: null
                tags:
                - new
                - featured
                tags_operation: set
                pricing:
                - product_pricing_tier_name: Default
                  price: 29.99
                suppliers:
                - supplier_id: 5
                  is_default: true
                  supplier_sku: MS-BW-001
                  leadtime: 14
                  minimum_order_quantity: 100
                  pricing:
                  - supplier_pricing_tier_name: Default
                    price: 10
                categories:
                - category_id: 2
                  is_primary: true
                attributes:
                - name: Color
                  value: Blue
                images:
                - url: https://example.com/images/blue-widget.jpg
                  name: Main Image
                  is_primary: true
                  download: false
                components: []
                variations: []
      parameters: []
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      sku:
                        type: string
                      name:
                        type: string
                      type:
                        type: string
                      is_lot_tracked:
                        type: boolean
                      lot_tracking_method:
                        type: string
                      shelf_life_days:
                        type: integer
                      near_expiry_threshold_days:
                        type: integer
                      min_remaining_shelf_life_days:
                        type: integer
                      expiry_aware_availability:
                        type: boolean
                      barcode:
                        type: string
                      hts_code:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                  message:
                    type: string
                  status:
                    type: string
                example:
                  data:
                    id: 42
                    sku: SKU-NEW-001
                    name: New Product
                    type: standard
                    is_lot_tracked: true
                    lot_tracking_method: fifo
                    shelf_life_days: 180
                    near_expiry_threshold_days: 60
                    min_remaining_shelf_life_days: 105
                    expiry_aware_availability: true
                    barcode: '1234567890123'
                    hts_code: 8471.30.0100
                    archived_at: null
                    created_at: '2024-06-15T12:00:00.000000Z'
                    updated_at: '2024-06-15T12:00:00.000000Z'
                  message: Product created successfully
                  status: success
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      sku:
                        type: array
                        items:
                          type: string
                      type:
                        type: array
                        items:
                          type: string
                example:
                  message: The sku has already been taken.
                  errors:
                    sku:
                    - The sku has already been taken.
                    type:
                    - The product type field is required.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: products:write
      operationId: post-api-products
    get:
      tags:
      - Products
      summary: List Products
      description: 'List all products. Supports searching, sorting, filtering, pagination,
        and column selection.


        Authentication: Requires Bearer token.


        Filter scopes available on the Product model:

        - filter[type]: standard | bundle | kit | matrix

        - filter[brand]: brand name string

        - filter[category]: category name or path

        - filter[tag]: tag name

        - filter[supplier]: supplier name or ID


        Sort fields: sku, name, barcode, type, created_at, updated_at, inventory_total,
        inventory_available, average_cost


        Inclusion columns: sku, id, name, barcode, type, image, image_url, brand,
        price, weight, weight_unit, length, width, height, dimension_unit, case_quantity,
        inventory_total, inventory_available, inventory_allocated, inventory_on_hold,
        inventory_in_transit, inventory_incoming, average_cost, default_supplier,
        default_supplier_sku, suppliers, tags, attributes, created_at, updated_at,
        archived_at


        **Stock UoM filters (added 2026-05-30):**

        - `filter[stock_uom_id]` — by uom_id (exact, comma-separated)

        - `filter[stock_uom_code]` — by UoM code (advanced text ops)

        - `filter[stock_uom_name]` — by UoM display name (advanced text ops)


        The `hts_code` (Harmonized Tariff Schedule code) column can be returned via
        `included[]=hts_code`. Filtering (`filter[hts_code]`) and sorting by `hts_code`
        are available on the `/api/v2/products` endpoint.'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        description: Page number (default 1)
        example: '1'
      - name: limit
        in: query
        schema:
          type: integer
        description: Items per page (default 10)
        example: '10'
      - name: search
        in: query
        schema:
          type: string
        description: Search by SKU, name, or barcode
      - name: sort
        in: query
        schema:
          type: string
        description: 'Sort field. Prefix with - for descending (e.g. -sku). Allowed:
          sku, name, barcode, type, created_at, updated_at, inventory_total, inventory_available,
          average_cost'
        example: sku
      - name: archived
        in: query
        schema:
          type: integer
        description: 0 = active only, 1 = archived only, 2 = all
        example: '0'
      - name: included[]
        in: query
        schema:
          type: string
        description: Columns to include in response. Repeat for multiple.
        example: sku
      - name: excluded[]
        in: query
        schema:
          type: string
        description: Columns to exclude. Cannot be used with included[].
      - name: filter[type]
        in: query
        schema:
          type: string
        description: 'Filter by product type: standard, bundle, kit, matrix'
      - name: filter[brand]
        in: query
        schema:
          type: string
        description: Filter by brand name
      - name: filter[category]
        in: query
        schema:
          type: string
        description: Filter by category
      - name: filter[tag]
        in: query
        schema:
          type: string
        description: Filter by tag
      - name: filter[supplier]
        in: query
        schema:
          type: string
        description: Filter by supplier name or ID
      - name: supplier_id
        in: query
        schema:
          type: string
        description: Filter variations shown in the response to those belonging to
          a specific supplier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        sku:
                          type: string
                        name:
                          type: string
                        barcode:
                          type: string
                        hts_code:
                          type: string
                        type:
                          type: string
                        image_url:
                          type: string
                        brand:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        price:
                          type: object
                          properties:
                            Default:
                              type: object
                              properties:
                                price:
                                  type: number
                        weight:
                          type: string
                        weight_unit:
                          type: string
                        inventory_total:
                          type: integer
                        inventory_available:
                          type: integer
                        inventory_available_to_sell:
                          type: integer
                        inventory_allocated:
                          type: integer
                        average_cost:
                          type: object
                          properties:
                            value:
                              type: number
                            currency:
                              type: string
                        inventory_avg_cost:
                          type: object
                          properties:
                            value:
                              type: number
                            currency:
                              type: string
                        archived_at:
                          type: string
                          nullable: true
                        stock_uom_id:
                          type: integer
                        stock_uom_code:
                          type: string
                        stock_uom_name:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  table_specifications:
                    type: object
                    properties:
                      columns:
                        type: array
                        items:
                          type: object
                          properties:
                            data_name:
                              type: string
                            label:
                              type: string
                            default_visible:
                              type: integer
                            sortable:
                              type: boolean
                  links:
                    type: object
                    properties:
                      first:
                        type: string
                      last:
                        type: string
                  meta:
                    type: object
                    properties:
                      current_page:
                        type: integer
                      last_page:
                        type: integer
                      per_page:
                        type: integer
                      total:
                        type: integer
                example:
                  data:
                  - id: 1
                    sku: SKU-001
                    name: Blue Widget
                    barcode: 0123456789012
                    hts_code: 8471.30.0100
                    type: standard
                    image_url: https://cdn.example.com/products/blue-widget.jpg
                    brand:
                      id: 3
                      name: Acme Co
                    price:
                      Default:
                        price: 29.99
                    weight: '0.5'
                    weight_unit: kg
                    inventory_total: 150
                    inventory_available: 120
                    inventory_available_to_sell: 115
                    inventory_allocated: 30
                    average_cost:
                      value: 12.5
                      currency: USD
                    inventory_avg_cost:
                      value: 11.85
                      currency: USD
                    archived_at: null
                    stock_uom_id: 1
                    stock_uom_code: EACH
                    stock_uom_name: Each
                    created_at: '2024-01-15T10:30:00.000000Z'
                    updated_at: '2024-06-01T08:00:00.000000Z'
                  table_specifications:
                    columns:
                    - data_name: sku
                      label: SKU
                      default_visible: 1
                      sortable: true
                  links:
                    first: https://sku2.test/api/products?page=1
                    last: https://sku2.test/api/products?page=10
                  meta:
                    current_page: 1
                    last_page: 10
                    per_page: 10
                    total: 98
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-products
    delete:
      tags:
      - Products
      summary: Bulk Delete Products
      description: 'Bulk delete multiple products. For large datasets, deletion is
        processed in the background via a queue.


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Body fields (one required):

        - ids (array): specific product IDs to delete

        - filters (object): filter criteria to select products for deletion


        **Requires permission:** `products.delete`'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 Success
                  value:
                    message: Products deleted successfully
                    status: success
                example-1:
                  summary: 200 Queued
                  value:
                    message: Added to the Queue, it will be process shortly
                    status: success
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: products:write
      operationId: delete-api-products
  /api/products/{product}/duplicate:
    post:
      tags:
      - Products
      summary: Duplicate Product
      description: 'Duplicate an existing product into a brand-new one with its own
        SKU.


        The new product copies the source''s identity-adjacent configuration - name,
        brand, type, dimensions, unit cost, financial line type, flags, attributes,
        categories, pricing tiers, suppliers (and their pricing), units of measure,
        tags, images, and kit/bundle components - but starts with zero inventory:
        no stock movements, FIFO layers, inventory cache, or channel listings. The
        barcode and inventory/velocity-derived figures (average cost, quantities sold,
        ABC/XYZ classification) are reset.


        A new unique `sku` is required. When `name` is omitted it defaults to the
        source name suffixed with " (copy)".


        Matrix (variation) products and variation children cannot be duplicated and
        return 422.


        Requires a Bearer token with the `products.create` permission.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                sku:
                  type: string
                name:
                  type: string
              example:
                sku: SKU-NEW-001-COPY
                name: New Product (copy)
      parameters:
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: ID of the product to duplicate
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      sku:
                        type: string
                      name:
                        type: string
                      type:
                        type: string
                      barcode:
                        type: string
                        nullable: true
                      brand_name:
                        type: string
                      weight:
                        type: number
                      weight_unit:
                        type: string
                      average_cost:
                        type: string
                        nullable: true
                      archived_at:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                  message:
                    type: string
                  status:
                    type: string
                example:
                  data:
                    id: 108
                    sku: SKU-NEW-001-COPY
                    name: New Product (copy)
                    type: standard
                    barcode: null
                    brand_name: Acme Co
                    weight: 0.5
                    weight_unit: kg
                    average_cost: null
                    archived_at: null
                    created_at: '2024-06-15T12:00:00.000000Z'
                    updated_at: '2024-06-15T12:00:00.000000Z'
                  message: The product 'SKU-NEW-001-COPY' was duplicated successfully
                  status: success
        '422':
          description: Unprocessable Content
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      sku:
                        type: array
                        items:
                          type: string
                example:
                  message: The sku has already been taken.
                  errors:
                    sku:
                    - The sku has already been taken.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-products-product-duplicate
  /api/products/constants:
    get:
      tags:
      - Products
      summary: Get Product Constants
      description: 'Returns enumeration constants used in product forms: product types,
        weight units, dimension units, attribute types, warehouse types, and inventory
        movement types.


        :::info[Required scope: `products:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      product_types:
                        type: array
                        items:
                          type: string
                      weight_units:
                        type: array
                        items:
                          type: string
                      dimension_units:
                        type: array
                        items:
                          type: string
                      attribute_types:
                        type: array
                        items:
                          type: string
                      warehouse_types:
                        type: array
                        items:
                          type: string
                      inventory_movement_type:
                        type: array
                        items:
                          type: string
                      inventory_movement_status:
                        type: array
                        items:
                          type: string
                  status:
                    type: string
                example:
                  data:
                    product_types:
                    - standard
                    - bundle
                    - kit
                    - matrix
                    weight_units:
                    - kg
                    - lb
                    - oz
                    - g
                    dimension_units:
                    - cm
                    - in
                    - mm
                    - ft
                    attribute_types:
                    - text
                    - number
                    - date
                    - boolean
                    warehouse_types:
                    - standard
                    - amazon_fba
                    - supplier
                    inventory_movement_type:
                    - purchase
                    - sale
                    - adjustment
                    - transfer
                    inventory_movement_status:
                    - available
                    - allocated
                    - on_hold
                    - in_transit
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: products:read
      operationId: get-api-products-constants
  /api/products/create:
    get:
      tags:
      - Products
      summary: Get Create Product Form
      description: 'Returns the data needed to pre-populate the create product form.


        :::info[Required scope: `products:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties: {}
                  status:
                    type: string
                example:
                  data: {}
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: products:read
      operationId: get-api-products-create
  /api/products/{product}/edit:
    get:
      tags:
      - Products
      summary: Get Edit Product Form
      description: 'Returns the product data pre-populated for the edit form.


        :::info[Required scope: `products:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: Product ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      sku:
                        type: string
                      name:
                        type: string
                  status:
                    type: string
                example:
                  data:
                    id: 1
                    sku: SKU-001
                    name: Blue Widget
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: products:read
      operationId: get-api-products-product-edit
  /api/products/search:
    get:
      tags:
      - Products
      summary: Search Products
      description: "Search products by SKU, name, or barcode. Results are ranked by\
        \ a 9-tier relevance scheme so typing a full SKU surfaces the exact product\
        \ first:\n  1. Exact SKU match\n  2. Exact barcode match\n  3. Exact name\
        \ match\n  4. SKU starts with the query\n  5. Barcode starts with the query\n\
        \  6. Name starts with the query\n  7. SKU contains the query (anywhere)\n\
        \  8. Name contains the query (anywhere)\n  9. Anything else (barcode contains,\
        \ etc.)\n\n:::info[Required scope: `products:read`]\nGrant this scope to your\
        \ token under [Settings → Developer → Personal Access Tokens](https://app.sku.io/settings/api).\n\
        :::\n\nOnly active (non-archived) products are returned.\n\nAuthentication:\
        \ Requires Bearer token.\n\nMinimum query length: 2 characters.\n\nOptional\
        \ `with` parameter (allowlist): pass `with=inventory` to include warehouse-aggregate\
        \ inventory totals (`inventory_available`, `inventory_allocated`, `inventory_on_hold`)\
        \ in each result.\n\nOptional `simple_assembleable=1` filter: restricts results\
        \ to products that can actually be assembled or disassembled via Manufacturing\
        \ Simple Mode (have an active default BOM with component lines, or legacy\
        \ kit components). Anything else would fail at submit, so the picker blocks\
        \ it.\n\n**Stock UoM fields:** When the product's `stockProductUom.unitOfMeasure`\
        \ relation is eager-loaded (this endpoint always loads it), each item additionally\
        \ exposes `stock_uom_id`, `stock_uom_code` (e.g. `KG`), and `stock_uom_name`.\
        \ The legacy nested `stock_uom` object is still emitted via `?with=stock_uom`."
      parameters:
      - name: q
        in: query
        schema:
          type: string
        description: Required. Search term (min 2 chars). Searches SKU, name, and
          barcode with fuzzy matching.
        example: blue
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        sku:
                          type: string
                        name:
                          type: string
                        barcode:
                          type: string
                        type:
                          type: string
                        stock_uom_id:
                          type: integer
                        stock_uom_code:
                          type: string
                        stock_uom_name:
                          type: string
                        inventory_available:
                          type: integer
                        inventory_allocated:
                          type: integer
                        inventory_on_hold:
                          type: integer
                  status:
                    type: string
                example:
                  data:
                  - id: 1
                    sku: SKU-001
                    name: Blue Widget
                    barcode: 0123456789012
                    type: standard
                    stock_uom_id: 1
                    stock_uom_code: EACH
                    stock_uom_name: Each
                    inventory_available: 42
                    inventory_allocated: 8
                    inventory_on_hold: 2
                  - id: 2
                    sku: SKU-002
                    name: Blue Widget Pro
                    barcode: 0123456789013
                    type: standard
                    stock_uom_id: 1
                    stock_uom_code: EACH
                    stock_uom_name: Each
                    inventory_available: 15
                    inventory_allocated: 0
                    inventory_on_hold: 0
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: products:read
      operationId: get-api-products-search
  /api/products/barcode-lookup:
    get:
      tags:
      - Products
      summary: Barcode Lookup
      description: 'Exact-match barcode or SKU lookup for barcode scanning. Prioritises
        barcode match first, then falls back to SKU match. Only active products are
        returned. Returns null in data if no match found.


        :::info[Required scope: `products:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: code
        in: query
        schema:
          type: integer
        description: Required. Barcode or SKU to look up (exact match only, no fuzzy
          matching).
        example: 0123456789012
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 Found
                  value:
                    data:
                      id: 1
                      sku: SKU-001
                      name: Blue Widget
                      barcode: 0123456789012
                example-1:
                  summary: 200 Not Found
                  value:
                    data: null
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: products:read
      operationId: get-api-products-barcode-lookup
  /api/products/is-deletable:
    post:
      tags:
      - Products
      summary: Check Product Deletability
      description: 'Check whether one or more products can be safely deleted. Returns
        deletability status with reasons and usage record samples for each product.


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Fields:

        - ids (required): array of product IDs (integers, must exist in DB)


        For each product, returns:

        - deletable: true if safe to delete

        - reason: human-readable reason if not deletable

        - usages: array of blocking usage types, each with: relation, label, count,
        message, and sample records


        Usage relations include: salesOrderLines, bundleSalesOrderLines, purchaseOrderLines,
        inventoryMovements, fifoLayers, inventoryAdjustments, inventoryAssemblyLines,
        warehouseTransferLines, returnReceiptLines, rmaLines, salesCreditLines, blemishedProducts,
        inboundShipmentLines, and subscriptionEditions (each is a RESTRICT foreign
        key, so any referencing row blocks deletion; product variations are checked
        too, so a matrix parent is reported not deletable when any of its variants
        is referenced). bundleSalesOrderLines appears when the product was sold as
        a bundle parent (referenced via sales_order_lines.bundle_id, a RESTRICT foreign
        key); such bundles are reported as not deletable so they can be archived instead.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1
                - 2
                - 3
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        sku:
                          type: string
                        deletable:
                          type: boolean
                        reason:
                          type: string
                        usages:
                          type: array
                          items:
                            type: object
                            properties:
                              relation:
                                type: string
                              label:
                                type: string
                              count:
                                type: integer
                              message:
                                type: string
                              records:
                                type: array
                                items:
                                  type: object
                                  properties:
                                    label:
                                      type: string
                                    detail:
                                      type: string
                  status:
                    type: string
                example:
                  data:
                  - id: 1
                    name: Blue Widget
                    sku: SKU-001
                    deletable: false
                    reason: There are 5 sales order lines associated with this product(SKU-001).
                    usages:
                    - relation: salesOrderLines
                      label: Sales Order Lines
                      count: 5
                      message: There are 5 sales order lines associated with this
                        product(SKU-001).
                      records:
                      - label: SO-1001
                        detail: 'Qty: 2'
                      - label: SO-1002
                        detail: 'Qty: 1'
                  - id: 2
                    name: Starter Bundle Kit
                    sku: BNDL-100
                    deletable: false
                    reason: There are 4 bundle sales order lines associated with this
                      product(BNDL-100).
                    usages:
                    - relation: bundleSalesOrderLines
                      label: Bundle Sales Order Lines
                      count: 4
                      message: There are 4 bundle sales order lines associated with
                        this product(BNDL-100).
                      records:
                      - label: SO-2001
                        detail: 'Qty: 1'
                      - label: SO-2002
                        detail: 'Qty: 3'
                  - id: 3
                    name: Red Widget
                    sku: SKU-002
                    deletable: true
                    reason: null
                    usages: []
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: products:write
      operationId: post-api-products-is-deletable
  /api/products/{id}/archive:
    put:
      tags:
      - Products
      summary: Archive Product
      description: 'Archive a product by ID. Sets archived_at timestamp.


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Returns a warning if the product is already archived.


        **Requires permission:** `products.archive`'
      requestBody:
        content: {}
      parameters:
      - name: id
        in: path
        schema:
          type: integer
        required: true
        description: Product ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  status:
                    type: string
                example:
                  message: Product SKU-001 archived successfully
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: products:write
      operationId: put-api-products-id-archive
  /api/products/{id}/unarchived:
    put:
      tags:
      - Products
      summary: Unarchive Product
      description: 'Unarchive a product by ID. Clears the archived_at timestamp.


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `products.archive`'
      requestBody:
        content: {}
      parameters:
      - name: id
        in: path
        schema:
          type: integer
        required: true
        description: Product ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  status:
                    type: string
                example:
                  message: Product SKU-001 unarchived successfully
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: products:write
      operationId: put-api-products-id-unarchived
  /api/products/archive:
    put:
      tags:
      - Products
      summary: Bulk Archive Products
      description: 'Bulk archive multiple products.


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Body fields:

        - ids (array): specific product IDs to archive

        - apply_to_all (boolean): if true, applies to all products matching the current
        filters instead of ids

        - filters (object): filter criteria used when apply_to_all is true


        **Requires permission:** `products.archive`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
                apply_to_all:
                  type: boolean
                filters:
                  type: object
                  properties: {}
              example:
                ids:
                - 1
                - 2
                - 3
                apply_to_all: false
                filters: {}
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  status:
                    type: string
                example:
                  message: Products archived successfully
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: products:write
      operationId: put-api-products-archive
  /api/products/unarchive:
    put:
      tags:
      - Products
      summary: Bulk Unarchive Products
      description: 'Bulk unarchive multiple products.


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Body fields:

        - ids (array): specific product IDs to unarchive

        - apply_to_all (boolean): if true, applies to all matching products

        - filters (object): filter criteria used when apply_to_all is true


        **Requires permission:** `products.archive`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
                apply_to_all:
                  type: boolean
                filters:
                  type: object
                  properties: {}
              example:
                ids:
                - 1
                - 2
                - 3
                apply_to_all: false
                filters: {}
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  status:
                    type: string
                example:
                  message: Products unarchived successfully
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: products:write
      operationId: put-api-products-unarchive
  /api/products/{productId}/inventory:
    get:
      tags:
      - Products
      summary: Get Product Inventory
      description: 'Get detailed inventory breakdown for a product across all warehouses.
        Includes FBA real-time data, Pan-EU rollup, supplier drop-ship inventory,
        and purchase order inbound quantities.


        :::info[Required scope: `products:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.

        Each warehouse row and the totals include `non_sellable` — physically-present
        stock in non-sellable bins (excluded from `available` but included in on-hand).'
      parameters:
      - name: no_fba
        in: query
        schema:
          type: boolean
        description: Exclude FBA warehouses from response (boolean)
        example: 'false'
      - name: no_suppliers
        in: query
        schema:
          type: boolean
        description: Exclude supplier warehouses from response (boolean)
        example: 'false'
      - name: legacy_mode
        in: query
        schema:
          type: boolean
        description: Use legacy inventory mode without Pan-EU FBA rollup (boolean)
        example: 'false'
      - name: include_mcf
        in: query
        schema:
          type: boolean
        description: Include MCF inventory (boolean)
        example: 'false'
      - name: productId
        in: path
        schema:
          type: integer
        required: true
        description: Product ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      total:
                        type: object
                        properties:
                          inbound:
                            type: boolean
                          stock:
                            type: boolean
                          allocated:
                            type: boolean
                          backorder_planned:
                            type: boolean
                          backorder_awaiting_receipt:
                            type: boolean
                          backorder:
                            type: boolean
                          on_hold:
                            type: boolean
                          available:
                            type: boolean
                          available_to_sell:
                            type: boolean
                          in_transit:
                            type: boolean
                          backordered:
                            type: boolean
                          consigned:
                            type: boolean
                          non_sellable:
                            type: integer
                      unit_cost:
                        type: number
                      warehouses:
                        type: object
                        properties:
                          Main Warehouse:
                            type: object
                            properties:
                              inbound:
                                type: boolean
                              stock:
                                type: boolean
                              allocated:
                                type: boolean
                              backorder_planned:
                                type: boolean
                              backorder_awaiting_receipt:
                                type: boolean
                              backorder:
                                type: boolean
                              on_hold:
                                type: boolean
                              available:
                                type: boolean
                              available_to_sell:
                                type: boolean
                              in_transit:
                                type: boolean
                              warehouse_id:
                                type: boolean
                              warehouse_name:
                                type: boolean
                              warehouse_type:
                                type: boolean
                              initial_inventory:
                                type: boolean
                              supplier:
                                type: boolean
                              listing_count:
                                type: boolean
                              country_code:
                                type: boolean
                              consigned:
                                type: boolean
                              non_sellable:
                                type: integer
                      bundle_data:
                        type: array
                      cache_updated_at:
                        type: string
                  status:
                    type: string
                example:
                  data:
                    total:
                      inbound: false
                      stock: false
                      allocated: false
                      backorder_planned: false
                      backorder_awaiting_receipt: false
                      backorder: false
                      on_hold: false
                      available: false
                      available_to_sell: false
                      in_transit: false
                      backordered: false
                      consigned: false
                      non_sellable: 15
                    unit_cost: 12.5
                    warehouses:
                      Main Warehouse:
                        inbound: false
                        stock: false
                        allocated: false
                        backorder_planned: false
                        backorder_awaiting_receipt: false
                        backorder: false
                        on_hold: false
                        available: false
                        available_to_sell: false
                        in_transit: false
                        warehouse_id: false
                        warehouse_name: false
                        warehouse_type: false
                        initial_inventory: false
                        supplier: false
                        listing_count: false
                        country_code: false
                        consigned: false
                        non_sellable: 15
                    bundle_data: []
                    cache_updated_at: '2024-06-15T12:00:00.000000Z'
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: products:read
      operationId: get-api-products-productid-inventory
  /api/products/{productId}/available-lots:
    get:
      tags:
      - Products
      summary: Get Available Lots (FEFO)
      description: 'Active FIFO layers available to CONSUME for a product in a given
        warehouse — only layers with remaining (unfulfilled) quantity are returned.


        :::info[Required scope: `products:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Layers are ordered by the product''s removal strategy: FEFO products list
        soonest-expiry first with undated lots last; FIFO products list by layer date.
        This drives the lot-override picker (LotConsumptionPanel) and its FEFO pre-fill
        on negative inventory events (fulfillment, transfer ship, decrease adjustment).


        Authentication: Requires Bearer token.


        Path params:

        - productId: Product ID


        Query params:

        - warehouse_id (REQUIRED, integer, exists:warehouses,id): warehouse to scope
        available lots to. Returns 422 if missing.


        Response (wrapped in {data}) — array of lots:

        - fifo_layer_id (int): FIFO layer ID to reference in a lot_allocation override

        - batch_number (string|null): lot/batch number

        - expiry_date (date|null, YYYY-MM-DD): lot expiry date

        - manufacture_date (date|null, YYYY-MM-DD): lot manufacture date

        - available_quantity (float): remaining quantity available to consume from
        this layer

        - fifo_layer_date (date|null, YYYY-MM-DD): the layer''s FIFO date

        - days_to_expiry (int|null): whole days until expiry (negative if already
        expired); null when undated

        - is_expired (bool): whether the lot''s expiry date is before today

        - avg_cost (float): average unit cost of the layer'
      parameters:
      - name: warehouse_id
        in: query
        schema:
          type: integer
        description: REQUIRED. Warehouse to list available lots for (integer, must
          exist in warehouses). The endpoint returns 422 if omitted.
        example: '1'
      - name: productId
        in: path
        schema:
          type: integer
        required: true
        description: Product ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        fifo_layer_id:
                          type: integer
                        batch_number:
                          type: string
                        expiry_date:
                          type: string
                        manufacture_date:
                          type: string
                        available_quantity:
                          type: number
                        fifo_layer_date:
                          type: string
                        days_to_expiry:
                          type: integer
                        is_expired:
                          type: boolean
                        avg_cost:
                          type: number
                example:
                  data:
                  - fifo_layer_id: 5012
                    batch_number: LOT-A
                    expiry_date: '2030-01-31'
                    manufacture_date: '2026-01-01'
                    available_quantity: 40.0
                    fifo_layer_date: '2026-01-10'
                    days_to_expiry: 1321
                    is_expired: false
                    avg_cost: 12.5
                  - fifo_layer_id: 5040
                    batch_number: null
                    expiry_date: null
                    manufacture_date: null
                    available_quantity: 15.0
                    fifo_layer_date: '2026-02-02'
                    days_to_expiry: null
                    is_expired: false
                    avg_cost: 11.75
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      warehouse_id:
                        type: array
                        items:
                          type: string
                example:
                  message: The warehouse id field is required.
                  errors:
                    warehouse_id:
                    - The warehouse id field is required.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: products:read
      operationId: get-api-products-productid-available-lots
  /api/products/{warehouseId}/{productId}/inventory-fba:
    get:
      tags:
      - Products
      summary: Get FBA Inventory
      description: 'Returns the Amazon FBA inventory listings for a product at a specific
        warehouse. Each row is an FBA-enabled product listing on the warehouse''s
        sales channel, with its real-time FBA inventory snapshot (available, reserved,
        in transit, total, inbound) and Amazon **condition** (e.g. `NewItem`, `UsedLikeNew`).
        Rows are sorted by available quantity descending. Listings are scoped to the
        warehouse''s marketplace (the warehouse `country_code`): a US FBA warehouse
        returns only US listings, never another marketplace''s listing (e.g. a Canadian
        one), mirroring how Amazon MCF fulfils from the destination''s marketplace.


        Note: Amazon MCF only fulfills New-condition inventory — listings with a non-New
        `condition` cannot be fulfilled via createFulfillmentOrder even when `available`
        is greater than 0.


        Authentication: Requires Bearer token. Rows come from two sources: (1) Amazon
        listings mapped to this product via product_listings, and (2) the FNSKU mapper
        — the seller SKU (MSKU) behind each SELLABLE FNSKU mapped to this product
        in the warehouse marketplace, with its FBA report stock. Source 2 lets a product
        whose marketplace listing is mapped to a different SKU.io product (a per-market
        "-CA-O" shadow listing) still surface its shippable seller SKU, so Amazon
        MCF submission resolves correctly. Mirrors ResolveFbaSellerSku.


        :::info[Required scope: `products:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: warehouseId
        in: path
        schema:
          type: integer
        required: true
        description: Warehouse ID (must be Amazon FBA type)
        example: '2'
      - name: productId
        in: path
        schema:
          type: integer
        required: true
        description: Product ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        integration_instance_id:
                          type: integer
                        product_listing_id:
                          type: integer
                        seller_sku:
                          type: string
                        asin:
                          type: string
                        condition:
                          type: string
                        available:
                          type: integer
                        reserved:
                          type: integer
                        in_transit:
                          type: integer
                        total:
                          type: integer
                        inbound:
                          type: integer
                  status:
                    type: string
                example:
                  data:
                  - integration_instance_id: 2
                    product_listing_id: 9380
                    seller_sku: BTS-AA-FBA-USED
                    asin: B07XYZ1234
                    condition: UsedLikeNew
                    available: 1
                    reserved: 0
                    in_transit: 0
                    total: 1
                    inbound: 0
                  - integration_instance_id: 2
                    product_listing_id: 9381
                    seller_sku: 2291988-FBA-1
                    asin: B07ABC5678
                    condition: NewItem
                    available: 13
                    reserved: 2
                    in_transit: 0
                    total: 15
                    inbound: 5
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: products:read
      operationId: get-api-products-warehouseid-productid-inventory-fba
  /api/products/{productId}/inventory/refresh:
    post:
      tags:
      - Products
      summary: Refresh Inventory Cache
      description: 'Synchronously refreshes the inventory cache for a specific product.
        This forces a recalculation of inventory totals and average cost.


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Returns 500 if the refresh fails.'
      requestBody:
        content: {}
      parameters:
      - name: productId
        in: path
        schema:
          type: integer
        required: true
        description: Product ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  status:
                    type: string
                example:
                  message: Inventory cache refreshed successfully
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: products:write
      operationId: post-api-products-productid-inventory-refresh
  /api/products/{product}/get-sales-channel-inventory:
    get:
      tags:
      - Products
      summary: Get Sales Channel Inventory
      description: 'Get inventory broken down by sales channel for a specific product.


        :::info[Required scope: `products:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: Product ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        sales_channel:
                          type: string
                        available:
                          type: integer
                        allocated:
                          type: integer
                  status:
                    type: string
                example:
                  data:
                  - sales_channel: Shopify Store
                    available: 80
                    allocated: 20
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: products:read
      operationId: get-api-products-product-get-sales-channel-inventory
  /api/products/{product}/last-purchase-price:
    get:
      tags:
      - Products
      summary: Get Last Purchase Price
      description: 'Get the most recent purchase price for a product from non-draft
        purchase orders.


        :::info[Required scope: `products:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Returns null in data if no purchase order lines exist with a positive amount.'
      parameters:
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: Product ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 Found
                  value:
                    data:
                      amount: 10.0
                      purchase_order_id: 55
                      purchase_order_date: '2024-05-15'
                example-1:
                  summary: 200 No Price
                  value:
                    data: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: products:read
      operationId: get-api-products-product-last-purchase-price
  /api/products/{productId}/inventory-movements:
    get:
      tags:
      - Products
      summary: Get Product Inventory Movements
      description: 'Get paginated inventory movements for a specific product.


        Authentication: Requires Bearer token.


        Response includes movements with type, quantity, warehouse, FIFO layer, and
        reference data.'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        description: Page number
        example: '1'
      - name: limit
        in: query
        schema:
          type: integer
        description: Items per page
        example: '10'
      - name: sort
        in: query
        schema:
          type: string
        description: Sort field. Prefix - for descending.
        example: -created_at
      - name: included[]
        in: query
        schema:
          type: string
        description: Columns to include
      - name: excluded[]
        in: query
        schema:
          type: string
        description: Columns to exclude
      - name: productId
        in: path
        schema:
          type: integer
        required: true
        description: Product ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        inventory_movement_date:
                          type: string
                        product_id:
                          type: integer
                        sku:
                          type: string
                        type:
                          type: object
                          properties:
                            name:
                              type: string
                            link_type:
                              type: string
                            link_id:
                              type: integer
                            parent_link_id:
                              type: integer
                            detail_link_id:
                              type: string
                              nullable: true
                            manufacturing_order:
                              type: string
                              nullable: true
                        inventory_status:
                          type: string
                        quantity:
                          type: integer
                        warehouse:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        layer:
                          type: object
                          properties:
                            fifo_layer_id:
                              type: integer
                            name:
                              type: string
                        reference:
                          type: string
                        created_at:
                          type: string
                  table_specifications:
                    type: object
                    properties: {}
                  meta:
                    type: object
                    properties:
                      current_page:
                        type: integer
                      last_page:
                        type: integer
                      per_page:
                        type: integer
                      total:
                        type: integer
                example:
                  data:
                  - id: 101
                    inventory_movement_date: '2024-06-01'
                    product_id: 1
                    sku: SKU-001
                    type:
                      name: purchase
                      link_type: App\Models\PurchaseOrderLine
                      link_id: 55
                      parent_link_id: 10
                      detail_link_id: null
                      manufacturing_order: null
                    inventory_status: available
                    quantity: 100
                    warehouse:
                      id: 1
                      name: Main Warehouse
                    layer:
                      fifo_layer_id: 3
                      name: Layer 2024-06-01
                    reference: PO-1001
                    created_at: '2024-06-01T10:00:00.000000Z'
                  table_specifications: {}
                  meta:
                    current_page: 1
                    last_page: 5
                    per_page: 10
                    total: 48
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-products-productid-inventory-movements
  /api/products/{productId}/fifo-layers:
    get:
      tags:
      - Products
      summary: Get Product FIFO Layers
      description: 'Get FIFO cost layers for a specific product.


        Authentication: Requires Bearer token.'
      parameters:
      - name: productId
        in: path
        schema:
          type: integer
        required: true
        description: Product ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        product_id:
                          type: integer
                        quantity:
                          type: integer
                        unit_cost:
                          type: number
                        created_at:
                          type: string
                example:
                  data:
                  - id: 3
                    product_id: 1
                    quantity: 100
                    unit_cost: 12.5
                    created_at: '2024-06-01T10:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-products-productid-fifo-layers
  /api/consignment/inventory:
    get:
      tags:
      - Products
      summary: List Consignment Inventory
      description: 'Consigned (supplier-owned) stock on hand that hasn''t sold yet,
        one row per cost layer, with unit cost, total value, and days-on-consignment
        aging, plus the supplier and purchase order it came from. Drives the return-unsold
        workflow.


        Authentication: Requires a Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        sku:
                          type: string
                        product_id:
                          type: integer
                        product_name:
                          type: string
                        supplier_id:
                          type: integer
                        supplier_name:
                          type: string
                        warehouse_id:
                          type: integer
                        warehouse_name:
                          type: string
                        purchase_order_id:
                          type: integer
                        purchase_order_number:
                          type: string
                        on_hand_quantity:
                          type: integer
                        unit_cost:
                          type: integer
                        total_value:
                          type: integer
                        days_on_consignment:
                          type: integer
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - id: 40122
                    sku: WIDGET-1
                    product_id: 881
                    product_name: Blue Widget
                    supplier_id: 44
                    supplier_name: Acme Wholesale
                    warehouse_id: 12
                    warehouse_name: Acme Consignment
                    purchase_order_id: 10432
                    purchase_order_number: PO-10432
                    on_hand_quantity: 40
                    unit_cost: 4
                    total_value: 160
                    days_on_consignment: 52
                  current_page: 1
                  last_page: 1
                  per_page: 15
                  total: 1
                  from: 1
                  to: 1
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-consignment-inventory
  /api/consignment/valuation-summary:
    get:
      tags:
      - Products
      summary: Get Consignment Valuation Summary
      description: 'Off-balance-sheet valuation memo for consigned (supplier-owned)
        stock on hand. It reports the total value of consigned inventory you hold
        and the equal received-not-billed obligation that would arise if it were grossed
        up onto the balance sheet, broken down by supplier. Because the asset and
        obligation always offset, the net balance-sheet impact is zero. This is a
        disclosure only — it is never posted to the general ledger and is not synced
        to any accounting integration.


        Authentication: Requires a Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      consigned_inventory_value:
                        type: integer
                      received_not_billed_obligation:
                        type: integer
                      net_balance_sheet_impact:
                        type: integer
                      total_on_hand_quantity:
                        type: integer
                      supplier_count:
                        type: integer
                      suppliers:
                        type: array
                        items:
                          type: object
                          properties:
                            supplier_id:
                              type: integer
                            supplier_name:
                              type: string
                            on_hand_quantity:
                              type: integer
                            total_value:
                              type: integer
                example:
                  data:
                    consigned_inventory_value: 12480
                    received_not_billed_obligation: 12480
                    net_balance_sheet_impact: 0
                    total_on_hand_quantity: 3120
                    supplier_count: 2
                    suppliers:
                    - supplier_id: 44
                      supplier_name: Acme Wholesale
                      on_hand_quantity: 2000
                      total_value: 8000
                    - supplier_id: 51
                      supplier_name: Globex Supply Co.
                      on_hand_quantity: 1120
                      total_value: 4480
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-consignment-valuation-summary
  /api/products/{productId}/attributes:
    get:
      tags:
      - Products
      summary: Get Product Attributes
      description: 'Get all available attributes for a product, including direct attributes
        and those inherited from category attribute groups.


        :::info[Required scope: `products:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: productId
        in: path
        schema:
          type: integer
        required: true
        description: Product ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      Color:
                        type: object
                        properties:
                          id:
                            type: integer
                          attribute_id:
                            type: integer
                          name:
                            type: string
                          value:
                            type: string
                          type:
                            type: string
                          attribute_group:
                            type: object
                            properties:
                              id:
                                type: integer
                              name:
                                type: string
                  status:
                    type: string
                example:
                  data:
                    Color:
                      id: 1
                      attribute_id: 5
                      name: Color
                      value: Blue
                      type: text
                      attribute_group:
                        id: 2
                        name: Product Details
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: products:read
      operationId: get-api-products-productid-attributes
    put:
      tags:
      - Products
      summary: Update Product Attributes
      description: 'Add or update attributes on a product. Syncs without detaching
        other existing attributes.


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Fields in attributes[]:

        - id (required without name): attribute ID

        - name (required without id): attribute name (max 255)

        - value (nullable): attribute value


        **Requires permission:** `products.manage_variants`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                attributes:
                  type: array
                  items:
                    type: object
                    properties:
                      id:
                        type: integer
                      value:
                        type: string
              example:
                attributes:
                - id: 5
                  value: Red
                - name: Material
                  value: Plastic
      parameters:
      - name: productId
        in: path
        schema:
          type: integer
        required: true
        description: Product ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  status:
                    type: string
                example:
                  message: Product attributes updated successfully
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: products:write
      operationId: put-api-products-productid-attributes
    delete:
      tags:
      - Products
      summary: Delete Product Attributes
      description: 'Remove specific attributes from a product by attribute IDs.


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Body fields:

        - attributes (required, array, min 1): array of attribute IDs to remove (must
        exist in attributes table)


        **Requires permission:** `products.manage_variants`'
      parameters:
      - name: productId
        in: path
        schema:
          type: integer
        required: true
        description: Product ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  status:
                    type: string
                example:
                  message: Product attributes 5,7,12 deleted successfully
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: products:write
      operationId: delete-api-products-productid-attributes
  /api/products/{productId}/attributes-grouped:
    get:
      tags:
      - Products
      summary: Get Product Attributes Grouped
      description: 'Get product attributes organised into grouped (by attribute group)
        and direct (ungrouped) sections.


        :::info[Required scope: `products:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: productId
        in: path
        schema:
          type: integer
        required: true
        description: Product ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      direct:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            value:
                              type: string
                      groups:
                        type: object
                        properties:
                          '2':
                            type: object
                            properties:
                              id:
                                type: integer
                              name:
                                type: string
                              attributes:
                                type: array
                                items:
                                  type: object
                                  properties:
                                    id:
                                      type: integer
                                    name:
                                      type: string
                                    value:
                                      type: string
                  status:
                    type: string
                example:
                  data:
                    direct:
                    - id: 1
                      name: Description
                      value: A blue widget
                    groups:
                      '2':
                        id: 2
                        name: Product Details
                        attributes:
                        - id: 2
                          name: Color
                          value: Blue
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: products:read
      operationId: get-api-products-productid-attributes-grouped
  /api/products/{productId}/assign-attribute-groups:
    put:
      tags:
      - Products
      summary: Assign Attribute Groups
      description: 'Sync attribute groups assigned to a product. This replaces all
        current attribute group assignments.


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Body fields:

        - attribute_groups_ids (required, array): array of attribute group IDs (must
        exist in attribute_groups table)'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                attribute_groups_ids:
                  type: array
                  items:
                    type: integer
              example:
                attribute_groups_ids:
                - 2
                - 5
      parameters:
      - name: productId
        in: path
        schema:
          type: integer
        required: true
        description: Product ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  status:
                    type: string
                example:
                  message: Attribute groups assigned successfully
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: products:write
      operationId: put-api-products-productid-assign-attribute-groups
  /api/products/attributes:
    get:
      tags:
      - Products
      summary: Get All Attributes for Products
      description: 'Get unique variant attributes across multiple products. Used by
        mapping modals.


        :::info[Required scope: `products:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Returns a deduplicated list of variant attributes across all provided product
        IDs.'
      parameters:
      - name: product_ids
        in: query
        schema:
          type: string
        description: Required. JSON-encoded array of product IDs
        example: '[1,2,3]'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        attribute_id:
                          type: integer
                        name:
                          type: string
                        value:
                          type: string
                  status:
                    type: string
                example:
                  data:
                  - id: 1
                    attribute_id: 5
                    name: Color
                    value: Blue
                  - id: 2
                    attribute_id: 6
                    name: Size
                    value: M
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: products:read
      operationId: get-api-products-attributes
  /api/products/{productId}/suppliers:
    get:
      tags:
      - Products
      summary: Get Product Suppliers
      description: 'Get all supplier relationships for a product, including pricing
        tiers per supplier.


        :::info[Required scope: `products:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: productId
        in: path
        schema:
          type: integer
        required: true
        description: Product ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        product_id:
                          type: integer
                        supplier_id:
                          type: integer
                        supplier_sku:
                          type: string
                        leadtime:
                          type: integer
                        minimum_order_quantity:
                          type: integer
                        is_default:
                          type: boolean
                        supplier:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        supplier_pricing_tiers:
                          type: array
                          items:
                            type: object
                            properties:
                              name:
                                type: string
                              price:
                                type: number
                              currency_code:
                                type: string
                  status:
                    type: string
                example:
                  data:
                  - id: 10
                    product_id: 1
                    supplier_id: 5
                    supplier_sku: MS-BW-001
                    leadtime: 14
                    minimum_order_quantity: 100
                    is_default: true
                    supplier:
                      id: 5
                      name: Main Supplier
                    supplier_pricing_tiers:
                    - name: Default
                      price: 10.0
                      currency_code: USD
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: products:read
      operationId: get-api-products-productid-suppliers
  /api/products/{productId}/set-default-supplier/{supplierId}:
    put:
      tags:
      - Products
      summary: Set Default Supplier
      description: 'Mark a supplier as the default supplier for a product. Clears
        the is_default flag from all other suppliers for this product.


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Both product_id and supplier_id must exist in the database.'
      requestBody:
        content: {}
      parameters:
      - name: productId
        in: path
        schema:
          type: integer
        required: true
        description: Product ID
        example: '1'
      - name: supplierId
        in: path
        schema:
          type: integer
        required: true
        description: Supplier ID
        example: '5'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  status:
                    type: string
                example:
                  message: Supplier 5 set as default for product 1
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: products:write
      operationId: put-api-products-productid-set-default-supplier-supplierid
  /api/products/{productId}/components:
    get:
      tags:
      - Products
      summary: Get Product Components
      description: 'Get all component products for a bundle or kit product.


        :::info[Required scope: `products:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: productId
        in: path
        schema:
          type: integer
        required: true
        description: Product ID (must be bundle or kit type)
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: array
                items:
                  type: object
                  properties:
                    id:
                      type: integer
                    sku:
                      type: string
                    name:
                      type: string
                    quantity:
                      type: integer
                example:
                - id: 3
                  sku: COMP-001
                  name: Component A
                  quantity: 2
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: products:read
      operationId: get-api-products-productid-components
  /api/products/{productId}/bundles:
    get:
      tags:
      - Products
      summary: Get Product Bundles
      description: 'Get all bundles that this product is a component of.


        :::info[Required scope: `products:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: productId
        in: path
        schema:
          type: integer
        required: true
        description: Product ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: array
                items:
                  type: object
                  properties:
                    id:
                      type: integer
                    sku:
                      type: string
                    name:
                      type: string
                    type:
                      type: string
                example:
                - id: 8
                  sku: BUNDLE-001
                  name: Starter Bundle
                  type: bundle
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: products:read
      operationId: get-api-products-productid-bundles
  /api/products/{productId}/potential-bundles:
    get:
      tags:
      - Products
      summary: Get Potential Bundles
      description: 'Calculate potential bundle quantities for a kit product based
        on current stock of its components per warehouse and inventory status.


        :::info[Required scope: `products:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Only valid for kit-type products. Throws 500 if product is not a kit.'
      parameters:
      - name: productId
        in: path
        schema:
          type: integer
        required: true
        description: Product ID (must be kit type)
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        sku:
                          type: string
                        name:
                          type: string
                        bundle_data:
                          type: array
                          items:
                            type: object
                            properties:
                              warehouse_id:
                                type: integer
                              inventory_available:
                                type: object
                                properties:
                                  quantity:
                                    type: integer
                                  max_bundle_quantity:
                                    type: integer
                              inventory_allocated:
                                type: object
                                properties:
                                  quantity:
                                    type: integer
                                  max_bundle_quantity:
                                    type: integer
                              inventory_on_hold:
                                type: object
                                properties:
                                  quantity:
                                    type: integer
                                  max_bundle_quantity:
                                    type: integer
                              inventory_in_transit:
                                type: object
                                properties:
                                  quantity:
                                    type: integer
                                  max_bundle_quantity:
                                    type: integer
                  status:
                    type: string
                example:
                  data:
                  - id: 3
                    sku: COMP-001
                    name: Component A
                    bundle_data:
                    - warehouse_id: 1
                      inventory_available:
                        quantity: 200
                        max_bundle_quantity: 100
                      inventory_allocated:
                        quantity: 30
                        max_bundle_quantity: 15
                      inventory_on_hold:
                        quantity: 10
                        max_bundle_quantity: 5
                      inventory_in_transit:
                        quantity: 0
                        max_bundle_quantity: 0
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: products:read
      operationId: get-api-products-productid-potential-bundles
  /api/products/{product}/dropship-status:
    get:
      tags:
      - Products
      summary: Get Product Drop-ship Status
      description: 'Return the drop-ship eligibility checklist for a product — whether
        a sales order line for this product will auto-route to a supplier''s drop-ship
        warehouse, and which gate conditions are currently met or failing.


        Optionally scope the check to a specific supplier with the `supplier_id` query
        parameter; omit it to evaluate against the product''s default supplier.


        A line auto-routes to a supplier''s drop-ship warehouse when the product is
        drop-shippable, drop-shipping is enabled, the supplier has a drop-ship warehouse
        ranked in the warehouse priority list, and its live stock covers the line
        — there is no per-supplier-product opt-in. The `gates` object reports each
        eligibility condition, and `missing` lists the labels of the gates that are
        not yet satisfied.


        Authentication: Requires Bearer token.'
      parameters:
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: Product ID
        example: '123'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  product_id:
                    type: integer
                  supplier_id:
                    type: integer
                  supplier_name:
                    type: string
                  eligible:
                    type: boolean
                  auto_routing_enabled:
                    type: boolean
                  gates:
                    type: object
                    properties:
                      supplier_product_link:
                        type: boolean
                      product_is_dropshippable:
                        type: boolean
                      supplier_warehouse_enabled:
                        type: boolean
                      supplier_feed_healthy:
                        type: boolean
                  missing:
                    type: array
                    items:
                      type: string
                example:
                  product_id: 123
                  supplier_id: 45
                  supplier_name: Acme Supply
                  eligible: false
                  auto_routing_enabled: true
                  gates:
                    supplier_product_link: true
                    product_is_dropshippable: true
                    supplier_warehouse_enabled: true
                    supplier_feed_healthy: false
                  missing:
                  - Supplier feed healthy
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-products-product-dropship-status
  /api/products/{product}/variations:
    get:
      tags:
      - Products
      summary: Get Product Variations
      description: 'Get all variation products for a matrix (parent) product.


        :::info[Required scope: `products:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Returns 400 if the product is not a matrix type.'
      parameters:
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: Product ID (must be matrix type)
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        sku:
                          type: string
                        name:
                          type: string
                        type:
                          type: string
                        is_variation:
                          type: boolean
                  status:
                    type: string
                example:
                  data:
                  - id: 5
                    sku: SKU-001-RED-S
                    name: Blue Widget - Red - Small
                    type: standard
                    is_variation: true
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: products:read
      operationId: get-api-products-product-variations
  /api/products/{product}/variations/attributes:
    get:
      tags:
      - Products
      summary: Get Variation Attributes
      description: 'Get unique variant attributes used across all variations of a
        matrix product.


        :::info[Required scope: `products:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Returns 400 if product is not a matrix type.'
      parameters:
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: Product ID (must be matrix type)
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        attribute_id:
                          type: integer
                        name:
                          type: string
                  status:
                    type: string
                example:
                  data:
                  - id: 1
                    attribute_id: 5
                    name: Color
                  - id: 2
                    attribute_id: 6
                    name: Size
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: products:read
      operationId: get-api-products-product-variations-attributes
  /api/products/{product}/images:
    get:
      tags:
      - Products
      summary: List Product Images
      description: 'Get all images for a product.


        :::info[Required scope: `products:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: Product ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        url:
                          type: string
                        name:
                          type: string
                        sort_order:
                          type: integer
                        is_primary:
                          type: boolean
                        resolvable:
                          type: boolean
                  status:
                    type: string
                example:
                  data:
                  - id: 1
                    url: https://cdn.example.com/products/blue-widget.jpg
                    name: Main Image
                    sort_order: 1
                    is_primary: true
                    resolvable: true
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: products:read
      operationId: get-api-products-product-images
    post:
      tags:
      - Products
      summary: Add Product Image
      description: 'Add a new image to a product. The `image` field accepts EITHER
        an uploaded file (multipart/form-data) OR a URL / base64 string (application/json).


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        **Mode 1 — File upload (multipart/form-data):**

        - image (required, file): image file uploaded from the device. Allowed types:
        jpg, jpeg, png, gif, webp. Max size: 10 MB (10240 KB).


        **Mode 2 — URL or base64 string (application/json):**

        - image (required, string): image URL or base64 encoded data URI.


        **Common optional fields (both modes):**

        - name (optional, max 255): image display name

        - sort_order (optional, integer): display order

        - is_primary (optional, boolean): set as the primary product image

        - download (optional, boolean): URL mode only — if true, downloads and stores
        the image from the URL

        - swatch_variant_attribute (optional, max 255): marks this image as the variant
        swatch for the named variant attribute (e.g. "color"). Sales channels that
        support swatches render it as the variant''s swatch image. Omit or send null
        for a normal gallery image.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                image:
                  type: string
                name:
                  type: string
                sort_order:
                  type: integer
                is_primary:
                  type: boolean
                swatch_variant_attribute:
                  type: string
                download:
                  type: boolean
              example:
                image: https://example.com/images/widget-red.jpg
                name: Red Variant Image
                sort_order: 2
                is_primary: false
                swatch_variant_attribute: color
                download: true
      parameters:
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: Product ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      url:
                        type: string
                      name:
                        type: string
                      sort_order:
                        type: integer
                      is_primary:
                        type: boolean
                      resolvable:
                        type: boolean
                  message:
                    type: string
                  status:
                    type: string
                example:
                  data:
                    id: 5
                    url: https://cdn.example.com/products/widget-red.jpg
                    name: Red Variant Image
                    sort_order: 2
                    is_primary: false
                    resolvable: true
                  message: Product image created successfully
                  status: success
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      image:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: object
                              properties:
                                image:
                                  type: string
                  status:
                    type: string
                example:
                  message: 'The image must be a file of type: jpg, jpeg, png, gif,
                    webp.'
                  errors:
                    image:
                    - message: 'The image must be a file of type: jpg, jpeg, png,
                        gif, webp.'
                      code: ImageMimes
                      data:
                        image: document.pdf
                  status: error
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: products:write
      operationId: post-api-products-product-images
  /api/products/{product}/bulk-images:
    post:
      tags:
      - Products
      summary: Bulk Update/Create Product Images
      description: 'Bulk update or create multiple images for a product at once.


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                images:
                  type: array
                  items:
                    type: object
                    properties:
                      url:
                        type: string
                      name:
                        type: string
                      is_primary:
                        type: boolean
                      download:
                        type: boolean
              example:
                images:
                - url: https://example.com/images/main.jpg
                  name: Main Image
                  is_primary: true
                  download: false
                - url: https://example.com/images/angle2.jpg
                  name: Side View
                  is_primary: false
                  download: false
      parameters:
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: Product ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        url:
                          type: string
                        is_primary:
                          type: boolean
                  message:
                    type: string
                  status:
                    type: string
                example:
                  data:
                  - id: 1
                    url: https://cdn.example.com/products/main.jpg
                    is_primary: true
                  - id: 2
                    url: https://cdn.example.com/products/angle2.jpg
                    is_primary: false
                  message: Product images updated
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: products:write
      operationId: post-api-products-product-bulk-images
  /api/product-images/broken:
    get:
      tags:
      - Products
      summary: List Broken Product Images
      description: 'List product images the on-demand image health check confirmed
        broken — rows where `image_checked_at` is set AND `resolvable` is false. Newest-checked
        first, with primary images surfaced to the top. Each row is a single image
        with its parent product for cross-linking.


        :::info[Required scope: `products:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Query parameters:

        - `page` — page number (default 1)

        - `per_page` — items per page (default 25)


        Backs the Broken Product Images report, where each image is re-loaded live
        in the browser; images that load are self-healed via `POST /api/product-images/mark-resolvable`,
        and genuinely dead ones are removed via `POST /api/product-images/bulk-delete`.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        url:
                          type: string
                        is_primary:
                          type: boolean
                        is_external:
                          type: boolean
                        image_checked_at:
                          type: string
                        product:
                          type: object
                          properties:
                            id:
                              type: integer
                            sku:
                              type: string
                            name:
                              type: string
                            reference:
                              type: string
                        product_link:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                  path:
                    type: string
                example:
                  data:
                  - id: 4821
                    url: https://images.example.com/widgets/blue-widget.jpg
                    is_primary: true
                    is_external: true
                    image_checked_at: '2026-06-09T18:30:00+00:00'
                    product:
                      id: 1
                      sku: SKU-001
                      name: Blue Widget
                      reference: SKU-001
                    product_link: /products/1
                  current_page: 1
                  last_page: 3
                  per_page: 25
                  total: 56
                  from: 1
                  to: 25
                  path: '{{protocol}}{{domain}}/api/product-images/broken'
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: products:read
      operationId: get-api-product-images-broken
  /api/product-images/bulk-delete:
    post:
      tags:
      - Products
      summary: Bulk Delete Product Images
      description: 'Delete the selected product images. Deletion runs through the
        model so its side effects fire: if a deleted image was a product''s primary
        image, that product is left without a primary image, and affected packing
        slips are re-queued.


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Request body:

        - `image_ids` (`array<int>`, required) — 1–500 existing product_image ids.


        Returns 422 if `image_ids` is empty, exceeds 500, or contains an id that does
        not exist.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                image_ids:
                  type: array
                  items:
                    type: integer
              example:
                image_ids:
                - 4821
                - 4822
                - 4830
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      deleted:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    deleted: 3
                  message: Deleted 3 images.
        '422':
          description: Unprocessable Content
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      image_ids:
                        type: array
                        items:
                          type: string
                example:
                  message: Select at least one image.
                  errors:
                    image_ids:
                    - Select at least one image.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: products:write
      operationId: post-api-product-images-bulk-delete
  /api/product-images/mark-resolvable:
    post:
      tags:
      - Products
      summary: Mark Product Images Resolvable
      description: 'Clear the broken flag on the selected images — the report''s in-browser
        load proved they resolve, so the server''s false positive is healed. Uses
        a mass update, so ProductImage save side effects (primary reset, packing-slip
        re-queue) do NOT fire and `image_checked_at` is preserved.


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Request body:

        - `image_ids` (`array<int>`, required) — 1–500 existing product_image ids.


        Returns 422 if `image_ids` is empty, exceeds 500, or contains an id that does
        not exist.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                image_ids:
                  type: array
                  items:
                    type: integer
              example:
                image_ids:
                - 4821
                - 4822
                - 4830
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      updated:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    updated: 3
                  message: Marked 3 images as OK.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: products:write
      operationId: post-api-product-images-mark-resolvable
  /api/product-images/{productImage}:
    put:
      tags:
      - Products
      summary: Update Product Image
      description: 'Updates a product image''s metadata and optionally replaces the
        image itself.


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Body fields (all optional on update):

        - image (string) — a new image as an external URL or a base64 data URI (data:image/...;base64,...).
        Omit to keep the current image and only update metadata.

        - name (string, max 255) — display name for the image

        - sort_order (integer) — position within the product''s image list

        - is_primary (boolean) — mark as the product''s primary image

        - download (boolean) — when true and image is an external URL, the file is
        downloaded and stored on SKU.io storage instead of hot-linking the URL


        If an external image URL cannot be resolved, the update still succeeds but
        the response includes a warning and the image is stored with resolvable: false.


        Authentication: Requires Bearer token.

        - swatch_variant_attribute (optional, max 255): marks this image as the variant
        swatch for the named variant attribute (e.g. "color"). Sales channels that
        support swatches render it as the variant''s swatch image. Omit or send null
        for a normal gallery image.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                image:
                  type: string
                name:
                  type: string
                sort_order:
                  type: integer
                is_primary:
                  type: boolean
                swatch_variant_attribute:
                  type: string
                download:
                  type: boolean
              example:
                image: https://cdn.example.com/images/widget-blue-front.jpg
                name: Front view
                sort_order: 1
                is_primary: true
                swatch_variant_attribute: color
                download: true
      parameters:
      - name: productImage
        in: path
        schema:
          type: integer
        required: true
        description: Product image ID
        example: '315'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      product_id:
                        type: integer
                      url:
                        type: string
                      name:
                        type: string
                      sort_order:
                        type: integer
                      is_primary:
                        type: boolean
                      resolvable:
                        type: boolean
                      image_checked_at:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  message: The product image '315' updated successfully
                  data:
                    id: 315
                    product_id: 42
                    url: https://example.sku.io/storage/images/widget-blue-front.jpg
                    name: Front view
                    sort_order: 1
                    is_primary: true
                    resolvable: true
                    image_checked_at: '2026-07-01T08:30:00.000000Z'
                    created_at: '2025-11-02T09:14:33.000000Z'
                    updated_at: '2026-07-06T10:05:12.000000Z'
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No query results for model.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      name:
                        type: array
                        items:
                          type: string
                example:
                  message: The name field must not be greater than 255 characters.
                  errors:
                    name:
                    - The name field must not be greater than 255 characters.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: products:write
      operationId: put-api-product-images-productimage
    delete:
      tags:
      - Products
      summary: Delete Product Image
      description: 'Deletes a product image. Destructive: if the image file is hosted
        on SKU.io storage, the stored file (and its thumbnail) is removed from the
        server as well; externally hosted URLs are simply detached from the product.


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: productImage
        in: path
        schema:
          type: integer
        required: true
        description: Product image ID
        example: '315'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: The product image 315 deleted successfully
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No query results for model.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: products:write
      operationId: delete-api-product-images-productimage
  /api/store-image:
    post:
      tags:
      - Products
      summary: Upload Image
      description: 'Uploads an image to SKU.io storage and returns its hosted URL.
        Use the returned URL anywhere an image URL is accepted — for example when
        creating or updating product images, or for store branding assets.


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        The image field accepts three input forms:

        - a multipart file upload (shown here)

        - an external image URL (the file is downloaded and stored)

        - a base64 data URI string (data:image/png;base64,...)


        Returns 400 when the image cannot be resolved (e.g. an unreachable URL or
        invalid data).


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                image:
                  type: string
                  description: Required. The image to upload. Accepts a multipart
                    file upload (must be an image MIME type), or alternatively a text
                    value containing an external image URL or a base64 data URI (data:image/...;base64,...).
                  format: binary
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      url:
                        type: string
                example:
                  message: The image uploaded successfully on the server
                  data:
                    url: https://example.sku.io/storage/tenant-assets/images/9f2c1a7b3d.jpg
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: array
                    items:
                      type: object
                      properties:
                        message:
                          type: string
                        code:
                          type: string
                        field:
                          type: string
                        data:
                          type: object
                          properties:
                            image:
                              type: string
                example:
                  message: The image failed to resolve
                  errors:
                  - message: The image failed to resolve
                    code: UnresolvableImage
                    field: image
                    data:
                      image: https://cdn.example.com/missing.jpg
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      image:
                        type: array
                        items:
                          type: string
                example:
                  message: The image field is required.
                  errors:
                    image:
                    - The image field is required.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: products:write
      operationId: post-api-store-image
  /api/delete-image:
    delete:
      tags:
      - Products
      summary: Delete Uploaded Image
      description: 'Removes a previously uploaded image (and its thumbnail) from SKU.io
        storage.


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Body fields:

        - url (required, string) — the hosted URL (or storage path) returned by Upload
        Image


        Destructive: the stored file is permanently deleted. Returns 400 when the
        file cannot be found at the given path.


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: The image removed successfully from the server
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: array
                    items:
                      type: object
                      properties:
                        message:
                          type: string
                        code:
                          type: string
                        field:
                          type: string
                        data:
                          type: object
                          properties:
                            url:
                              type: string
                example:
                  message: Image not found on the server, please check image path
                  errors:
                  - message: Image not found on the server, please check image path
                    code: NotFound
                    field: url
                    data:
                      url: https://example.sku.io/storage/tenant-assets/images/missing.jpg
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      url:
                        type: array
                        items:
                          type: string
                example:
                  message: The url field is required.
                  errors:
                    url:
                    - The url field is required.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: products:write
      operationId: delete-api-delete-image
  /api/products/blemished:
    post:
      tags:
      - Products
      summary: Create Blemished Product
      description: 'Create a blemished (damaged/used) product derived from an existing
        standard product.


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Body fields:

        - blemished_sku (required, unique): SKU for the new blemished product

        - derived_from_product_id (required): ID of the original standard product

        - condition (optional): condition description (e.g. ''Grade B - Minor scratches'')

        - reference (optional): reference number or note

        - adjust_inventory (optional, boolean, default false): create an inventory
        adjustment

        - adjust_inventory_for_original_product (optional, boolean): also adjust the
        original product

        - adjustment_type (optional, default ''increase''): increase or decrease

        - adjustment_data (optional): adjustment details when adjust_inventory is
        true'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                blemished_sku:
                  type: string
                derived_from_product_id:
                  type: integer
                condition:
                  type: string
                reference:
                  type: string
                adjust_inventory:
                  type: boolean
                adjust_inventory_for_original_product:
                  type: boolean
                adjustment_type:
                  type: string
                adjustment_data:
                  type: object
                  properties:
                    warehouse_id:
                      type: integer
                    quantity:
                      type: integer
              example:
                blemished_sku: SKU-001-B
                derived_from_product_id: 1
                condition: Grade B - Minor scratches
                reference: REF-2024-001
                adjust_inventory: true
                adjust_inventory_for_original_product: false
                adjustment_type: increase
                adjustment_data:
                  warehouse_id: 1
                  quantity: 10
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      sku:
                        type: string
                      name:
                        type: string
                      type:
                        type: string
                      blemished:
                        type: object
                        properties:
                          derived_product:
                            type: object
                            properties:
                              id:
                                type: integer
                              name:
                                type: string
                              sku:
                                type: string
                          condition:
                            type: string
                          reference:
                            type: string
                  message:
                    type: string
                  status:
                    type: string
                example:
                  data:
                    id: 50
                    sku: SKU-001-B
                    name: Blue Widget (Blemished)
                    type: standard
                    blemished:
                      derived_product:
                        id: 1
                        name: Blue Widget
                        sku: SKU-001
                      condition: Grade B - Minor scratches
                      reference: REF-2024-001
                  message: Product created successfully
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: products:write
      operationId: post-api-products-blemished
  /api/products/generate-sku-pattern/{product}:
    get:
      tags:
      - Products
      summary: Generate Blemished SKU Pattern
      description: 'Generate a blemished SKU based on the tenant''s blemished SKU
        pattern settings and the original product''s SKU.


        :::info[Required scope: `products:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: Product ID to generate blemished SKU pattern for
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      sku:
                        type: string
                      pattern:
                        type: string
                      pattern_enabled:
                        type: boolean
                  status:
                    type: string
                example:
                  data:
                    sku: SKU-001-BLEM
                    pattern: '{sku}-BLEM'
                    pattern_enabled: true
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: products:read
      operationId: get-api-products-generate-sku-pattern-product
  /api/products/import:
    post:
      tags:
      - Products
      summary: Import Products
      description: 'Execute the product import — creates products from the validated
        data. Should be called after validate.


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Body fields:

        - products (required, array, min 1): array of validated product objects to
        import


        Returns 422 if the import fails.


        **Requires permission:** `products.import`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                products:
                  type: array
                  items:
                    type: object
                    properties:
                      sku:
                        type: string
                      name:
                        type: string
                      type:
                        type: string
                      barcode:
                        type: string
              example:
                products:
                - sku: SKU-NEW-001
                  name: New Product
                  type: standard
                  barcode: '1234567890123'
      parameters: []
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  imported:
                    type: integer
                  failed:
                    type: integer
                  errors:
                    type: array
                example:
                  imported: 1
                  failed: 0
                  errors: []
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 'Import failed: Duplicate SKU found'
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: products:write
      operationId: post-api-products-import
  /api/products/import/preview:
    post:
      tags:
      - Products
      summary: Preview Import (Legacy CSV)
      description: 'Legacy endpoint for CSV import preview (delegates to ImportsData
        trait).


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `products.import`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties: {}
              example: {}
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties: {}
                  status:
                    type: string
                example:
                  data: {}
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: products:write
      operationId: post-api-products-import-preview
  /api/products/import/fields:
    get:
      tags:
      - Products
      summary: Get Import Fields
      description: 'Returns dynamic import fields including custom attributes for
        the column mapping UI.


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      attributes:
                        type: array
                        items:
                          type: object
                          properties:
                            key:
                              type: string
                            label:
                              type: string
                example:
                  data:
                    attributes:
                    - key: attribute_5
                      label: 'Attr: Color'
                    - key: attribute_6
                      label: 'Attr: Size'
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-products-import-fields
  /api/products/import/template:
    get:
      tags:
      - Products
      summary: Download Import Template
      description: 'Download an XLSX import template with headers, sample data, field
        guide, and reference data from the tenant''s account.


        Authentication: Requires Bearer token.


        Response: XLSX file download (application/vnd.openxmlformats-officedocument.spreadsheetml.sheet)'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
            Content-Disposition:
              schema:
                type: string
                example: attachment; filename="product-import-template.xlsx"
          content:
            text/plain:
              schema:
                type: string
                example: (binary XLSX file)
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-products-import-template
  /api/products/import/validate:
    post:
      tags:
      - Products
      summary: Validate Import
      description: 'Validate mapped import data and return a preview. No data is created
        — safe to call repeatedly for client-side validation before executing the
        actual import.


        Authentication: Requires Bearer token.


        Body fields:

        - rows (required, array, min 1): array of product row objects to validate'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                rows:
                  type: array
                  items:
                    type: object
                    properties:
                      sku:
                        type: string
                      name:
                        type: string
                      type:
                        type: string
                      barcode:
                        type: string
                      brand:
                        type: string
                      weight:
                        type: number
                      weight_unit:
                        type: string
              example:
                rows:
                - sku: SKU-NEW-001
                  name: New Product
                  type: standard
                  barcode: '1234567890123'
                  brand: Acme Co
                  weight: 0.5
                  weight_unit: kg
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  valid:
                    type: array
                    items:
                      type: object
                      properties:
                        row:
                          type: integer
                        sku:
                          type: string
                        status:
                          type: string
                  invalid:
                    type: array
                  total:
                    type: integer
                  valid_count:
                    type: integer
                  invalid_count:
                    type: integer
                example:
                  valid:
                  - row: 1
                    sku: SKU-NEW-001
                    status: valid
                  invalid: []
                  total: 1
                  valid_count: 1
                  invalid_count: 0
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-products-import-validate
  /api/products/merge/template:
    get:
      tags:
      - Products
      summary: Download Merge Template
      description: 'Download a CSV template for bulk product merging. Contains columns:
        old_sku, destination_sku.


        :::info[Required scope: `products:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Response: CSV file download.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: text/csv
            Content-Disposition:
              schema:
                type: string
                example: attachment; filename="product-merge-template.csv"
          content:
            text/plain:
              schema:
                type: string
                example: 'old_sku,destination_sku

                  EXAMPLE-OLD-SKU,EXAMPLE-NEW-SKU'
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: products:read
      operationId: get-api-products-merge-template
  /api/products/merge/upload:
    post:
      tags:
      - Products
      summary: Upload Merge CSV
      description: 'Upload a CSV file with product merge pairs. Validates the SKU
        pairs and creates a session (cached for 2 hours) for preview and execution.


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Content-Type: multipart/form-data


        Body fields:

        - file (required): CSV or TXT file with columns old_sku and destination_sku'
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                file:
                  type: string
                  description: 'Required. CSV or TXT file with columns: old_sku, destination_sku.
                    Accepted: csv, txt.'
                  format: binary
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  session_id:
                    type: string
                  pairs_count:
                    type: integer
                example:
                  session_id: 550e8400-e29b-41d4-a716-446655440000
                  pairs_count: 5
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      file:
                        type: array
                        items:
                          type: string
                example:
                  message: The file field is required.
                  errors:
                    file:
                    - The file field is required.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: products:write
      operationId: post-api-products-merge-upload
  /api/products/merge/create-session:
    post:
      tags:
      - Products
      summary: Create Merge Session (Single Pair)
      description: 'Create a merge session for a single SKU pair without uploading
        a CSV. Validates that both SKUs exist and are compatible.


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Body fields:

        - old_sku (required, string): source SKU to merge from

        - destination_sku (required, string): destination SKU to merge into


        Returns 422 if SKUs are the same, either SKU doesn''t exist, or types are
        incompatible.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                old_sku:
                  type: string
                destination_sku:
                  type: string
              example:
                old_sku: SKU-OLD-001
                destination_sku: SKU-NEW-001
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  session_id:
                    type: string
                  pairs_count:
                    type: integer
                example:
                  session_id: 550e8400-e29b-41d4-a716-446655440000
                  pairs_count: 1
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      old_sku:
                        type: array
                        items:
                          type: string
                example:
                  message: 'Source and destination SKUs cannot be the same: SKU-001'
                  errors:
                    old_sku:
                    - 'Source and destination SKUs cannot be the same: SKU-001'
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: products:write
      operationId: post-api-products-merge-create-session
  /api/products/merge/{session_id}/preview:
    get:
      tags:
      - Products
      summary: Get Merge Preview
      description: 'Get a preview of what will happen when the merge is executed.
        Shows data changes for each SKU pair.


        :::info[Required scope: `products:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Sessions expire after 2 hours. Returns 404 if the session is not found or
        expired.'
      parameters:
      - name: session_id
        in: path
        schema:
          type: string
        required: true
        description: Session ID from upload or create-session
        example: 550e8400-e29b-41d4-a716-446655440000
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  previews:
                    type: array
                    items:
                      type: object
                      properties:
                        old_sku:
                          type: string
                        destination_sku:
                          type: string
                        changes:
                          type: object
                          properties:
                            sales_order_lines:
                              type: integer
                            purchase_order_lines:
                              type: integer
                example:
                  previews:
                  - old_sku: SKU-OLD-001
                    destination_sku: SKU-NEW-001
                    changes:
                      sales_order_lines: 3
                      purchase_order_lines: 1
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Session not found or expired
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: products:read
      operationId: get-api-products-merge-session-id-preview
  /api/products/merge/{session_id}/execute:
    post:
      tags:
      - Products
      summary: Execute Merge
      description: 'Execute the product merge for all pairs in the session. Merges
        sales order lines, purchase order lines, and other references from the old
        SKU to the destination SKU. Clears the session cache after execution.


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Sessions expire after 2 hours. Returns 404 if session is not found or expired.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties: {}
              example: {}
      parameters:
      - name: session_id
        in: path
        schema:
          type: string
        required: true
        description: Session ID from upload or create-session
        example: 550e8400-e29b-41d4-a716-446655440000
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 Success
                  value:
                    success: true
                    merged_count: 5
                    errors: []
                example-1:
                  summary: 200 Partial Success
                  value:
                    success: false
                    merged_count: 4
                    errors:
                    - old_sku: SKU-FAIL
                      destination_sku: SKU-NEW
                      error: Product type mismatch
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Session not found or expired
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: products:write
      operationId: post-api-products-merge-session-id-execute
  /api/products/{product}/listings:
    get:
      tags:
      - Products
      summary: List Product Listings
      description: 'Get paginated product listings (channel listings) for a specific
        product. Refreshes inventory cache for all listings before returning.


        Authentication: Requires Bearer token.'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        description: Page number
        example: '1'
      - name: limit
        in: query
        schema:
          type: integer
        description: Items per page
        example: '10'
      - name: archived
        in: query
        schema:
          type: integer
        description: 0 = active, 1 = archived, 2 = all
        example: '0'
      - name: included[]
        in: query
        schema:
          type: string
        description: Columns to include
      - name: excluded[]
        in: query
        schema:
          type: string
        description: Columns to exclude
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: Product ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        product_id:
                          type: integer
                        sales_channel_listing_id:
                          type: string
                        sales_channel:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        master_of_price:
                          type: boolean
                        is_fba:
                          type: boolean
                  meta:
                    type: object
                    properties:
                      current_page:
                        type: integer
                      per_page:
                        type: integer
                      total:
                        type: integer
                example:
                  data:
                  - id: 20
                    product_id: 1
                    sales_channel_listing_id: amazon-asin-B001
                    sales_channel:
                      id: 3
                      name: Amazon US
                    master_of_price: true
                    is_fba: false
                  meta:
                    current_page: 1
                    per_page: 10
                    total: 3
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-products-product-listings
  /api/products/{product}/default-financial-line-type:
    patch:
      tags:
      - Products
      summary: Update Product Default Financial Line Type
      description: 'Sets or clears the default financial line type used when this
        product is added to financial documents.


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Body fields:

        - default_financial_line_type_id (nullable integer) — ID of an existing financial
        line type. It must have a revenue classification; non-revenue types are rejected
        with a 422. Pass null to clear the default.


        Returns the updated product including the resolved default_financial_line_type
        object (id, name, classification).


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                default_financial_line_type_id:
                  type: integer
              example:
                default_financial_line_type_id: 12
      parameters:
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: Product ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      sku:
                        type: string
                      name:
                        type: string
                      type:
                        type: string
                      barcode:
                        type: string
                      default_financial_line_type_id:
                        type: integer
                      default_financial_line_type:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          classification:
                            type: string
                      sales_nominal_code_id:
                        type: integer
                      is_taxable:
                        type: boolean
                      archived_at:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  message: Product WIDGET-BLUE updated successfully
                  data:
                    id: 42
                    sku: WIDGET-BLUE
                    name: Blue Widget
                    type: standard
                    barcode: 0123456789012
                    default_financial_line_type_id: 12
                    default_financial_line_type:
                      id: 12
                      name: Product Sales
                      classification: revenue
                    sales_nominal_code_id: 5
                    is_taxable: true
                    archived_at: null
                    created_at: '2025-11-02T09:14:33.000000Z'
                    updated_at: '2026-07-06T10:05:12.000000Z'
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No query results for model.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      default_financial_line_type_id:
                        type: array
                        items:
                          type: string
                example:
                  message: The selected financial line type must be a revenue type.
                  errors:
                    default_financial_line_type_id:
                    - The selected financial line type must be a revenue type.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: products:write
      operationId: patch-api-products-product-default-financial-line-type
  /api/v2/products:
    get:
      tags:
      - Products
      summary: List Products
      description: 'Get a paginated list of products using Spatie QueryBuilder.


        :::info[Required scope: `products:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Supports both simple query filters (filter[field]=value) and advanced grouped
        filters (filter_groups tree). Default: shows non-archived products sorted
        by -created_at.


        Allowed sorts: id, sku, name, type, barcode, mpn, hts_code, unit_cost, average_cost,
        supplier_price, weight, length, width, height, case_quantity, case_weight,
        daily_average_consumption, daily_average_consumption_net_returns, min_stock_level,
        total_quantity_sold, total_orders, archived_at, created_at, updated_at


        Default pagination: 10 per page.


        The response also includes `unfiltered_total`, the count of rows in the base
        scope before any user filters are applied — used by the frontend to show export
        totals.


        **Stock UoM filters (added 2026-05-30):**

        - `filter[stock_uom_id]` — by uom_id (exact, comma-separated)

        - `filter[stock_uom_code]` — by UoM code (advanced text ops)

        - `filter[stock_uom_name]` — by UoM display name (advanced text ops)


        The response includes `inventory_non_sellable` — physically-present stock
        in non-sellable bins. It is excluded from `inventory_available` but is part
        of On Hand (On Hand = Available + Allocated + On Hold + Non-Sellable).


        Also supports `hts_code` (Harmonized Tariff Schedule code) for filtering (`filter[hts_code]`)
        and sorting.'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        description: 'Page number (default: 1)'
        example: '1'
      - name: per_page
        in: query
        schema:
          type: integer
        description: 'Items per page (default: 10)'
        example: '10'
      - name: sort
        in: query
        schema:
          type: string
        description: 'Sort field. Prefix with - for descending. Allowed: id, sku,
          name, type, barcode, mpn, hts_code, unit_cost, average_cost, supplier_price,
          weight, length, width, height, case_quantity, case_weight, daily_average_consumption,
          daily_average_consumption_net_returns, min_stock_level, total_quantity_sold,
          total_orders, archived_at, created_at, updated_at'
        example: -created_at
      - name: filter[search]
        in: query
        schema:
          type: string
        description: Full-text search across ID (exact), SKU, name, barcode, MPN,
          and brand name
        example: widget
      - name: filter[type]
        in: query
        schema:
          type: string
        description: 'Exact product type: standard, bundle, kit, blemished, matrix'
        example: standard
      - name: filter[archived]
        in: query
        schema:
          type: integer
        description: 'Archived state: 0 or omit for active only, ''only'' for archived
          only, ''all'' for all'
        example: '0'
      - name: filter[brand_id]
        in: query
        schema:
          type: integer
        description: Filter by brand ID(s), comma-separated
        example: '1'
      - name: filter[default_supplier_id]
        in: query
        schema:
          type: integer
        description: Filter by default supplier ID(s), comma-separated
        example: '2'
      - name: filter[stock_status]
        in: query
        schema:
          type: string
        description: 'Stock status: in_stock, out_of_stock'
        example: in_stock
      - name: filter[has_backorder]
        in: query
        schema:
          type: boolean
        description: 'Filter by backorder presence: true or false'
        example: 'false'
      - name: filter[has_fba]
        in: query
        schema:
          type: boolean
        description: 'Filter by FBA listing presence: true or false'
        example: 'false'
      - name: filter[ids]
        in: query
        schema:
          type: string
        description: Comma-separated list of product IDs to include
        example: 1,2,3
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        sku:
                          type: string
                        name:
                          type: string
                        type:
                          type: string
                        barcode:
                          type: string
                        mpn:
                          type: string
                        hts_code:
                          type: string
                        unit_cost:
                          type: number
                        average_cost:
                          type: number
                        is_variation:
                          type: boolean
                        is_dropshippable:
                          type: boolean
                        is_lot_tracked:
                          type: boolean
                        lot_tracking_method:
                          type: string
                          nullable: true
                        shelf_life_days:
                          type: string
                          nullable: true
                        near_expiry_threshold_days:
                          type: string
                          nullable: true
                        min_remaining_shelf_life_days:
                          type: string
                          nullable: true
                        expiry_aware_availability:
                          type: boolean
                        archived_at:
                          type: string
                          nullable: true
                        stock_uom_id:
                          type: integer
                        stock_uom_code:
                          type: string
                        stock_uom_name:
                          type: string
                        image_url:
                          type: string
                        brand_id:
                          type: integer
                        brand_name:
                          type: string
                        default_supplier_id:
                          type: integer
                        default_supplier_name:
                          type: string
                        default_supplier_sku:
                          type: string
                        supplier_count:
                          type: integer
                        inventory_total:
                          type: integer
                        inventory_available:
                          type: integer
                        inventory_available_to_sell:
                          type: integer
                        inventory_allocated:
                          type: integer
                        inventory_backorder:
                          type: integer
                        inventory_on_hold:
                          type: integer
                        inventory_non_sellable:
                          type: integer
                        inventory_in_transit:
                          type: integer
                        inventory_consigned:
                          type: integer
                        inventory_incoming:
                          type: integer
                        inventory_stock_value:
                          type: number
                        inventory_avg_cost:
                          type: number
                        daily_average_consumption:
                          type: number
                        min_stock_level:
                          type: integer
                        weight:
                          type: number
                        weight_unit:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                        total_quantity_sold:
                          type: integer
                        total_orders:
                          type: integer
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  next_page_url:
                    type: string
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                  unfiltered_total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 42
                    sku: WDG-001
                    name: Blue Widget
                    type: standard
                    barcode: 0123456789012
                    mpn: BW-001
                    hts_code: 8471.30.0100
                    unit_cost: 5.5
                    average_cost: 5.75
                    is_variation: false
                    is_dropshippable: false
                    is_lot_tracked: false
                    lot_tracking_method: null
                    shelf_life_days: null
                    near_expiry_threshold_days: null
                    min_remaining_shelf_life_days: null
                    expiry_aware_availability: false
                    archived_at: null
                    stock_uom_id: 1
                    stock_uom_code: EACH
                    stock_uom_name: Each
                    image_url: https://example.com/images/widget.jpg
                    brand_id: 1
                    brand_name: Acme
                    default_supplier_id: 3
                    default_supplier_name: Global Supplies Ltd
                    default_supplier_sku: GS-WDG-001
                    supplier_count: 2
                    inventory_total: 500
                    inventory_available: 450
                    inventory_available_to_sell: 450
                    inventory_allocated: 50
                    inventory_backorder: 0
                    inventory_on_hold: 0
                    inventory_non_sellable: 0
                    inventory_in_transit: 100
                    inventory_consigned: 50
                    inventory_incoming: 200
                    inventory_stock_value: 2875.0
                    inventory_avg_cost: 5.75
                    daily_average_consumption: 5.2
                    min_stock_level: 100
                    weight: 0.5
                    weight_unit: kg
                    created_at: '2024-01-15T10:30:00.000000Z'
                    updated_at: '2024-06-01T14:20:00.000000Z'
                    total_quantity_sold: 1280
                    total_orders: 312
                  first_page_url: https://sku2.test/api/v2/products?page=1
                  from: 1
                  last_page: 50
                  last_page_url: https://sku2.test/api/v2/products?page=50
                  next_page_url: https://sku2.test/api/v2/products?page=2
                  path: https://sku2.test/api/v2/products
                  per_page: 10
                  prev_page_url: null
                  to: 10
                  total: 498
                  unfiltered_total: 1843
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: products:read
      operationId: get-api-v2-products
    post:
      tags:
      - Products
      summary: Search Products
      description: 'Returns the same paginated product catalog list as the GET version
        of this endpoint, but accepts filters as a JSON request body instead of the
        query string. Use this POST variant when the filter set is too large or too
        complex to fit in a URL (for example, filtering by a long list of SKUs or
        ids). The response includes an `unfiltered_total` alongside the standard paginator
        totals so clients can show both the filtered and total record counts.


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Provide advanced filters under `filter_groups`, a tree of conditions combined
        with a `conjunction` of `and` or `or`. Each condition names a `column`, an
        `operator`, and a `value`. A free-text `search` term matches against id, SKU,
        name, barcode, MPN, and brand.


        Text columns (`sku`, `name`, `barcode`, `mpn`, `hts_code`, `brand_name`, `supplier_name`,
        `supplier_sku`, `tag`, `category`, `stock_uom_code`, `stock_uom_name`, `component_skus`,
        `parent_product`) accept: is, is_not, contains, does_not_contain, starts_with,
        ends_with, is_empty, is_not_empty, is_one_of, is_not_one_of.

        Numeric columns (`id`, `unit_cost`, `average_cost`, `supplier_price`, `default_supplier_leadtime`,
        `default_supplier_moq`, `default_supplier_target_stock_days`) accept: is,
        is_not, greater_than, greater_than_or_equal, less_than, less_than_or_equal,
        between, is_empty, is_not_empty. Additional filters include `type`, `archived`,
        `brand_id`, `default_supplier_id`, `stock_uom_id`, `stock_status` (in_stock
        / out_of_stock), `has_backorder`, and `ids`.


        Sortable columns (via `sort`, prefix with `-` for descending): id, sku, name,
        type, barcode, mpn, hts_code, unit_cost, average_cost, supplier_price, weight,
        case_quantity, daily_average_consumption, min_stock_level, archived_at, created_at,
        updated_at, plus inventory snapshot sorts (inventory_available, inventory_available_to_sell,
        inventory_allocated, inventory_on_hold, inventory_in_transit, inventory_total,
        inventory_backorder, inventory_stock_value, inventory_incoming, total_quantity_sold,
        total_orders). Results default to `-created_at`.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                per_page:
                  type: integer
                page:
                  type: integer
                sort:
                  type: string
                filter_groups:
                  type: object
                  properties:
                    conjunction:
                      type: string
                    children:
                      type: array
                      items:
                        type: object
                        properties:
                          type:
                            type: string
                          condition:
                            type: object
                            properties:
                              column:
                                type: string
                              operator:
                                type: string
                              value:
                                type: string
              example:
                per_page: 25
                page: 1
                sort: -created_at
                filter_groups:
                  conjunction: and
                  children:
                  - type: condition
                    condition:
                      column: stock_status
                      operator: is
                      value: in_stock
                  - type: group
                    group:
                      conjunction: or
                      children:
                      - type: condition
                        condition:
                          column: brand_name
                          operator: is
                          value: Acme
                      - type: condition
                        condition:
                          column: sku
                          operator: starts_with
                          value: WIDGET
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        sku:
                          type: string
                        id:
                          type: integer
                        unit_cost:
                          type: number
                        image_url:
                          type: string
                        name:
                          type: string
                        brand:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        barcode:
                          type: string
                        mpn:
                          type: string
                        hts_code:
                          type: string
                        tags:
                          type: array
                          items:
                            type: string
                        type:
                          type: string
                        is_lot_tracked:
                          type: boolean
                        has_fba:
                          type: boolean
                        is_variation:
                          type: boolean
                        inventory:
                          type: object
                          properties:
                            inventory_available:
                              type: integer
                            inventory_allocated:
                              type: integer
                            inventory_total:
                              type: integer
                            inventory_stock_value:
                              type: integer
                  current_page:
                    type: integer
                  per_page:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                  last_page:
                    type: integer
                  total:
                    type: integer
                  unfiltered_total:
                    type: integer
                  next_page_url:
                    type: string
                  prev_page_url:
                    type: string
                    nullable: true
                example:
                  data:
                  - sku: WIDGET-BLUE-01
                    id: 3312
                    unit_cost: 13.75
                    image_url: https://cdn.example.com/products/3312.jpg
                    name: Blue Widget
                    brand:
                      id: 5
                      name: Acme
                    barcode: '8801234567890'
                    mpn: ACM-WB-01
                    hts_code: 8471.30.0100
                    tags:
                    - bestseller
                    type: standard
                    is_lot_tracked: false
                    has_fba: true
                    is_variation: false
                    inventory:
                      inventory_available: 240
                      inventory_allocated: 12
                      inventory_total: 252
                      inventory_stock_value: 3465
                  current_page: 1
                  per_page: 25
                  from: 1
                  to: 1
                  last_page: 58
                  total: 1442
                  unfiltered_total: 3901
                  next_page_url: https://api.example.com/api/v2/products?page=2
                  prev_page_url: null
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: products:write
      operationId: post-api-v2-products
  /api/v2/products/{product}:
    get:
      tags:
      - Products
      summary: Get Product
      description: 'Get a single product with default relations loaded (brand, primaryImage,
        primaryCategory, tags, defaultSupplierProduct.supplier, totalInventory).


        :::info[Required scope: `products:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Use the `with` query parameter to load additional relations.'
      parameters:
      - name: with
        in: query
        schema:
          type: string
        description: 'Comma-separated additional relations to load. Allowed: brand,
          images, tags, primaryCategory, otherCategories, supplierProducts.supplier,
          components, variations, productPricingTiers, salesNominalCode, cogsNominalCode,
          inventoryNominalCode, inventoryInTransitNominalCode, accruedPurchasesNominalCode,
          discountNominalCode, warehousesInventory.warehouse, productBlemished.originalProduct,
          productAttributeValues.attribute.attributeGroup, notes.user, parent, defaultSupplierProduct.supplier,
          totalInventory, purchaseOrderLines'
        example: brand,images,tags,supplierProducts.supplier,components,variations,productPricingTiers
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: Product ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      sku:
                        type: string
                      name:
                        type: string
                      type:
                        type: string
                      barcode:
                        type: string
                      mpn:
                        type: string
                      hts_code:
                        type: string
                      unit_cost:
                        type: number
                      average_cost:
                        type: number
                      is_variation:
                        type: boolean
                      is_dropshippable:
                        type: boolean
                      is_lot_tracked:
                        type: boolean
                      lot_tracking_method:
                        type: string
                      shelf_life_days:
                        type: integer
                      near_expiry_threshold_days:
                        type: integer
                      min_remaining_shelf_life_days:
                        type: integer
                      expiry_aware_availability:
                        type: boolean
                      archived_at:
                        type: string
                        nullable: true
                      stock_uom_id:
                        type: integer
                      stock_uom_code:
                        type: string
                      stock_uom_name:
                        type: string
                      image_url:
                        type: string
                      brand_id:
                        type: integer
                      brand_name:
                        type: string
                      default_supplier_id:
                        type: integer
                      default_supplier_name:
                        type: string
                      default_supplier_sku:
                        type: string
                      default_supplier_leadtime:
                        type: integer
                      default_supplier_moq:
                        type: integer
                      supplier_count:
                        type: integer
                      inventory_total:
                        type: integer
                      inventory_available:
                        type: integer
                      inventory_available_to_sell:
                        type: integer
                      inventory_allocated:
                        type: integer
                      inventory_on_hold:
                        type: integer
                      inventory_in_transit:
                        type: integer
                      inventory_consigned:
                        type: integer
                      inventory_stock_value:
                        type: number
                      inventory_avg_cost:
                        type: number
                      daily_average_consumption:
                        type: number
                      min_stock_level:
                        type: integer
                      weight:
                        type: number
                      weight_unit:
                        type: string
                      length:
                        type: number
                      width:
                        type: number
                      height:
                        type: number
                      dimension_unit:
                        type: string
                      is_taxable:
                        type: boolean
                      default_tax_rate_id:
                        type: integer
                      sales_nominal_code_id:
                        type: integer
                      cogs_nominal_code_id:
                        type: integer
                      parent_id:
                        type: string
                        nullable: true
                      has_fba:
                        type: boolean
                      last_rebuilt_cogs_at:
                        type: string
                      tags:
                        type: array
                        items:
                          type: string
                      images:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            url:
                              type: string
                            is_primary:
                              type: boolean
                            sort_order:
                              type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 42
                    sku: WDG-001
                    name: Blue Widget
                    type: standard
                    barcode: 0123456789012
                    mpn: BW-001
                    hts_code: 8471.30.0100
                    unit_cost: 5.5
                    average_cost: 5.75
                    is_variation: false
                    is_dropshippable: false
                    is_lot_tracked: true
                    lot_tracking_method: fifo
                    shelf_life_days: 365
                    near_expiry_threshold_days: 45
                    min_remaining_shelf_life_days: 30
                    expiry_aware_availability: true
                    archived_at: null
                    stock_uom_id: 1
                    stock_uom_code: EACH
                    stock_uom_name: Each
                    image_url: https://example.com/images/widget.jpg
                    brand_id: 1
                    brand_name: Acme
                    default_supplier_id: 3
                    default_supplier_name: Global Supplies Ltd
                    default_supplier_sku: GS-WDG-001
                    default_supplier_leadtime: 14
                    default_supplier_moq: 50
                    supplier_count: 2
                    inventory_total: 500
                    inventory_available: 450
                    inventory_available_to_sell: 450
                    inventory_allocated: 50
                    inventory_on_hold: 0
                    inventory_in_transit: 100
                    inventory_consigned: 50
                    inventory_stock_value: 2875.0
                    inventory_avg_cost: 5.75
                    daily_average_consumption: 5.2
                    min_stock_level: 100
                    weight: 0.5
                    weight_unit: kg
                    length: 10.0
                    width: 5.0
                    height: 3.0
                    dimension_unit: cm
                    is_taxable: true
                    default_tax_rate_id: 1
                    sales_nominal_code_id: 10
                    cogs_nominal_code_id: 11
                    parent_id: null
                    has_fba: false
                    last_rebuilt_cogs_at: '2024-05-20T08:00:00.000000Z'
                    tags:
                    - blue
                    - widget
                    images:
                    - id: 5
                      url: https://example.com/images/widget.jpg
                      is_primary: true
                      sort_order: 0
                    created_at: '2024-01-15T10:30:00.000000Z'
                    updated_at: '2024-06-01T14:20:00.000000Z'
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No query results for model [App\Models\Product] 42
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: products:read
      operationId: get-api-v2-products-product
  /api/v2/products/{product}/inventory:
    get:
      tags:
      - Products
      summary: Get Product Inventory
      description: 'Get inventory breakdown by warehouse for a product.


        :::info[Required scope: `products:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Includes FBA/AWD real-time data, Pan-European rollup, listing counts, inbound
        quantities, and backorder coverage (`backorder_planned` = unfulfilled demand
        without stock; `backorder_awaiting_receipt` = backordered demand covered by
        inbound POs). FBA/AWD warehouses show real-time data; standard warehouses
        use cached ProductInventory.

        Each warehouse row and the totals include `non_sellable` — physically-present
        stock in non-sellable bins (excluded from `available` but included in on-hand).'
      parameters:
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: Product ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      warehouses:
                        type: array
                        items:
                          type: object
                          properties:
                            warehouse_id:
                              type: boolean
                            warehouse_name:
                              type: boolean
                            warehouse_type:
                              type: boolean
                            total:
                              type: boolean
                            available:
                              type: boolean
                            allocated:
                              type: boolean
                            on_hold:
                              type: boolean
                            in_transit:
                              type: boolean
                            inbound:
                              type: boolean
                            backorder_planned:
                              type: boolean
                            backorder_awaiting_receipt:
                              type: boolean
                            consigned:
                              type: boolean
                            non_sellable:
                              type: integer
                            listing_count:
                              type: boolean
                            country_code:
                              type: boolean
                            fba_warehouse_id:
                              type: boolean
                      totals:
                        type: object
                        properties:
                          total:
                            type: boolean
                          available:
                            type: boolean
                          allocated:
                            type: boolean
                          on_hold:
                            type: boolean
                          in_transit:
                            type: boolean
                          inbound:
                            type: boolean
                          backorder_planned:
                            type: boolean
                          backorder_awaiting_receipt:
                            type: boolean
                          consigned:
                            type: boolean
                          non_sellable:
                            type: integer
                          incoming:
                            type: boolean
                          stock_value:
                            type: boolean
                          cache_updated_at:
                            type: boolean
                example:
                  data:
                    warehouses:
                    - warehouse_id: false
                      warehouse_name: false
                      warehouse_type: false
                      total: false
                      available: false
                      allocated: false
                      on_hold: false
                      in_transit: false
                      inbound: false
                      backorder_planned: false
                      backorder_awaiting_receipt: false
                      consigned: false
                      non_sellable: 15
                      listing_count: false
                      country_code: false
                      fba_warehouse_id: false
                    - warehouse_id: false
                      warehouse_name: false
                      warehouse_type: false
                      total: false
                      available: false
                      allocated: false
                      on_hold: false
                      in_transit: false
                      inbound: false
                      backorder_planned: false
                      backorder_awaiting_receipt: false
                      consigned: false
                      non_sellable: 0
                      listing_count: false
                      country_code: false
                      fba_warehouse_id: false
                    totals:
                      total: false
                      available: false
                      allocated: false
                      on_hold: false
                      in_transit: false
                      inbound: false
                      backorder_planned: false
                      backorder_awaiting_receipt: false
                      consigned: false
                      non_sellable: 15
                      incoming: false
                      stock_value: false
                      cache_updated_at: false
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: products:read
      operationId: get-api-v2-products-product-inventory
  /api/v2/products/{product}/suppliers:
    get:
      tags:
      - Products
      summary: Get Product Suppliers
      description: 'Get supplier products for a product, including pricing tiers and
        supplier inventory.


        :::info[Required scope: `products:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: Product ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        supplier_id:
                          type: integer
                        supplier_name:
                          type: string
                        default_pricing_tier_id:
                          type: integer
                        supplier_sku:
                          type: string
                        lead_time:
                          type: integer
                        minimum_order_quantity:
                          type: integer
                        target_stock_days:
                          type: integer
                        is_default:
                          type: boolean
                        pricing:
                          type: array
                          items:
                            type: object
                            properties:
                              tier_id:
                                type: integer
                              tier_name:
                                type: string
                              price:
                                type: number
                              currency_code:
                                type: string
                        inventories:
                          type: array
                          items:
                            type: object
                            properties:
                              id:
                                type: integer
                              warehouse_id:
                                type: integer
                              warehouse_name:
                                type: string
                              quantity:
                                type: integer
                              in_stock:
                                type: boolean
                              discontinued:
                                type: boolean
                              eta:
                                type: string
                                nullable: true
                              source:
                                type: string
                              updated_at:
                                type: string
                example:
                  data:
                  - id: 10
                    supplier_id: 3
                    supplier_name: Global Supplies Ltd
                    default_pricing_tier_id: 1
                    supplier_sku: GS-WDG-001
                    lead_time: 14
                    minimum_order_quantity: 50
                    target_stock_days: 30
                    is_default: true
                    pricing:
                    - tier_id: 1
                      tier_name: Standard
                      price: 4.5
                      currency_code: USD
                    inventories:
                    - id: 7
                      warehouse_id: 10
                      warehouse_name: Supplier Warehouse A
                      quantity: 2000
                      in_stock: true
                      discontinued: false
                      eta: null
                      source: manual
                      updated_at: '2024-05-15T09:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: products:read
      operationId: get-api-v2-products-product-suppliers
  /api/v2/products/{product}/pricing:
    get:
      tags:
      - Products
      summary: Get Product Pricing
      description: 'Get product pricing tiers.


        :::info[Required scope: `products:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: Product ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        tier_id:
                          type: integer
                        tier_name:
                          type: string
                        price:
                          type: number
                        currency_code:
                          type: string
                        is_default:
                          type: boolean
                example:
                  data:
                  - tier_id: 1
                    tier_name: Retail
                    price: 12.99
                    currency_code: USD
                    is_default: true
                  - tier_id: 2
                    tier_name: Wholesale
                    price: 8.99
                    currency_code: USD
                    is_default: false
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: products:read
      operationId: get-api-v2-products-product-pricing
    put:
      tags:
      - Products
      summary: Upsert Product Pricing
      description: 'Idempotently upsert a single pricing tier price for a product.


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Used to save a pricing tier''s master price without navigating to the product
        edit page. Returns the resolved tier row.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                tier_id:
                  type: integer
                price:
                  type: number
              example:
                tier_id: 1
                price: 12.99
      parameters:
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: Product ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tier_id:
                        type: integer
                      tier_name:
                        type: string
                      price:
                        type: number
                      currency_code:
                        type: string
                      is_default:
                        type: boolean
                example:
                  data:
                    tier_id: 1
                    tier_name: Retail
                    price: 12.99
                    currency_code: USD
                    is_default: true
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      tier_id:
                        type: array
                        items:
                          type: string
                      price:
                        type: array
                        items:
                          type: string
                example:
                  message: The given data was invalid.
                  errors:
                    tier_id:
                    - The selected tier id is invalid.
                    price:
                    - The price must be a number.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: products:write
      operationId: put-api-v2-products-product-pricing
  /api/v2/products/{product}/components:
    get:
      tags:
      - Products
      summary: Get Product Components
      description: 'Get components for a bundle or kit product.


        :::info[Required scope: `products:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: Product ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        sku:
                          type: string
                        name:
                          type: string
                        quantity:
                          type: integer
                        type:
                          type: string
                example:
                  data:
                  - id: 10
                    sku: COMP-A
                    name: Component A
                    quantity: 2
                    type: standard
                  - id: 11
                    sku: COMP-B
                    name: Component B
                    quantity: 1
                    type: standard
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: products:read
      operationId: get-api-v2-products-product-components
  /api/v2/products/{product}/parent-products:
    get:
      tags:
      - Products
      summary: Get Parent Products
      description: 'Get parent bundle/kit products that include this product as a
        component.


        :::info[Required scope: `products:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: Product ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        sku:
                          type: string
                        name:
                          type: string
                        type:
                          type: string
                        image_url:
                          type: string
                          nullable: true
                        quantity:
                          type: integer
                example:
                  data:
                  - id: 5
                    sku: BUNDLE-001
                    name: Widget Bundle
                    type: bundle
                    image_url: null
                    quantity: 2
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: products:read
      operationId: get-api-v2-products-product-parent-products
  /api/v2/products/{product}/bundle-potential:
    get:
      tags:
      - Products
      summary: Get Bundle Potential
      description: 'Get bundle assembly potential — how many units can be assembled
        from current component inventory.


        :::info[Required scope: `products:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Returns per-warehouse breakdown and bottleneck identification. Returns empty
        result for non-bundle/kit products.'
      parameters:
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: Product ID (must be bundle or kit type)
        example: '5'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      components:
                        type: array
                        items:
                          type: object
                          properties:
                            product_id:
                              type: integer
                            sku:
                              type: string
                            name:
                              type: string
                            required_quantity:
                              type: integer
                            available_inventory:
                              type: integer
                            max_assemblable:
                              type: integer
                            is_bottleneck:
                              type: boolean
                      max_assemblable:
                        type: integer
                      warehouses:
                        type: array
                        items:
                          type: object
                          properties:
                            warehouse_id:
                              type: integer
                            warehouse_name:
                              type: string
                            max_assemblable:
                              type: integer
                            components:
                              type: array
                example:
                  data:
                    components:
                    - product_id: 10
                      sku: COMP-A
                      name: Component A
                      required_quantity: 2
                      available_inventory: 450
                      max_assemblable: 225
                      is_bottleneck: false
                    - product_id: 11
                      sku: COMP-B
                      name: Component B
                      required_quantity: 1
                      available_inventory: 100
                      max_assemblable: 100
                      is_bottleneck: true
                    max_assemblable: 100
                    warehouses:
                    - warehouse_id: 1
                      warehouse_name: Main Warehouse
                      max_assemblable: 100
                      components: []
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: products:read
      operationId: get-api-v2-products-product-bundle-potential
  /api/v2/products/{product}/variations:
    get:
      tags:
      - Products
      summary: Get Product Variations
      description: 'Get variations of a matrix product.


        :::info[Required scope: `products:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: Product ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        sku:
                          type: string
                        name:
                          type: string
                        image_url:
                          type: string
                          nullable: true
                        attributes:
                          type: array
                          items:
                            type: object
                            properties:
                              name:
                                type: string
                              value:
                                type: string
                example:
                  data:
                  - id: 43
                    sku: WDG-001-RED
                    name: Blue Widget - Red
                    image_url: null
                    attributes:
                    - name: Color
                      value: Red
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: products:read
      operationId: get-api-v2-products-product-variations
  /api/v2/products/{product}/images:
    get:
      tags:
      - Products
      summary: Get Product Images
      description: 'Get all images for a product, sorted by sort_order.


        :::info[Required scope: `products:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Each image may carry `swatch_variant_attribute` (string, nullable): when set,
        the image is the variant swatch for the named attribute (e.g. "Color") on
        matrix variant children. Channels that support swatches (Walmart) emit it
        as that child''s swatch image.'
      parameters:
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: Product ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        url:
                          type: string
                        is_primary:
                          type: boolean
                        sort_order:
                          type: integer
                        swatch_variant_attribute:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                example:
                  data:
                  - id: 5
                    url: https://example.com/images/widget.jpg
                    is_primary: true
                    sort_order: 0
                    swatch_variant_attribute: Color
                    created_at: '2024-01-15T10:30:00Z'
                    updated_at: '2024-01-15T10:30:00Z'
                  - id: 6
                    url: https://example.com/images/widget-alt.jpg
                    is_primary: false
                    sort_order: 1
                    swatch_variant_attribute: null
                    created_at: '2024-01-15T10:31:00Z'
                    updated_at: '2024-01-15T10:31:00Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: products:read
      operationId: get-api-v2-products-product-images
  /api/v2/products/{product}/listings:
    get:
      tags:
      - Products
      summary: Get Product Listings
      description: 'Get paginated sales channel listings for a product.


        :::info[Required scope: `products:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        example: '1'
        description: Page number (default 1).
      - name: per_page
        in: query
        schema:
          type: integer
        example: '10'
        description: Results per page (default 10).
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: Product ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        listing_sku:
                          type: string
                        is_fba:
                          type: boolean
                        sales_channel_id:
                          type: integer
                        sales_channel_name:
                          type: string
                  total:
                    type: integer
                  per_page:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 100
                    listing_sku: WDG-001
                    is_fba: false
                    sales_channel_id: 1
                    sales_channel_name: Shopify US
                  total: 3
                  per_page: 10
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: products:read
      operationId: get-api-v2-products-product-listings
  /api/v2/products/{product}/listings/summary:
    get:
      tags:
      - Products
      summary: Get Product Listings Summary
      description: 'Get listing counts grouped by integration for a product.


        :::info[Required scope: `products:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: Product ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      total:
                        type: integer
                      integrations:
                        type: array
                        items:
                          type: object
                          properties:
                            integration_name:
                              type: string
                            integration_id:
                              type: integer
                            count:
                              type: integer
                example:
                  data:
                    total: 5
                    integrations:
                    - integration_name: Shopify
                      integration_id: 1
                      count: 3
                    - integration_name: Amazon
                      integration_id: 2
                      count: 2
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: products:read
      operationId: get-api-v2-products-product-listings-summary
  /api/v2/products/{product}/inventory-movements:
    get:
      tags:
      - Products
      summary: Get Product Inventory Movements
      description: 'Get paginated inventory movements for a product.


        :::info[Required scope: `products:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        example: '1'
        description: Page number (default 1).
      - name: per_page
        in: query
        schema:
          type: integer
        example: '15'
        description: Results per page (default 10).
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: Product ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        type:
                          type: string
                        inventory_status:
                          type: string
                        quantity:
                          type: integer
                        reference:
                          type: string
                        link_type:
                          type: string
                        link_id:
                          type: integer
                        parent_link_id:
                          type: integer
                        detail_link_id:
                          type: string
                          nullable: true
                        warehouse_id:
                          type: integer
                        warehouse_name:
                          type: string
                        unit_cost:
                          type: number
                        unit_cost_provisional:
                          type: boolean
                        layer:
                          type: object
                          properties:
                            fifo_layer_id:
                              type: integer
                            name:
                              type: string
                        inventory_movement_date:
                          type: string
                        created_at:
                          type: string
                  total:
                    type: integer
                  per_page:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 1001
                    type: sale
                    inventory_status: active
                    quantity: -2
                    reference: SO-0042
                    link_type: App\Models\SalesOrderLine
                    link_id: 55
                    parent_link_id: 22
                    detail_link_id: null
                    warehouse_id: 1
                    warehouse_name: Main Warehouse
                    unit_cost: 5.75
                    unit_cost_provisional: false
                    layer:
                      fifo_layer_id: 10
                      name: fifo
                    inventory_movement_date: '2024-06-01'
                    created_at: '2024-06-01T14:20:00Z'
                  total: 150
                  per_page: 15
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: products:read
      operationId: get-api-v2-products-product-inventory-movements
  /api/v2/products/{product}/sales:
    get:
      tags:
      - Products
      summary: List Product Sales
      description: 'List sales order lines for a product — one row per line with parent-order
        context (order number, date, sales channel, customer, order and fulfillment
        status) and per-line financials (unit price, line revenue, profit). Draft
        orders are excluded. Results are live order data.


        Authentication: Requires Bearer token.


        Filters:

        - filter[search] — searches order number and customer name

        - filter[sales_channel_id] — exact sales channel ID

        - filter[warehouse_id] — exact warehouse ID (line-level)

        - filter[order_status] / filter[fulfillment_status] / filter[order_number]
        / filter[customer_name] — text filters; bare param matches exactly, or suffix
        an operator, e.g. filter[order_status.is_one_of]=open,closed, filter[order_number.contains]=1234.
        Operators: contains, does_not_contain, is, is_not, is_one_of, is_not_one_of,
        starts_with, does_not_start_with, ends_with, does_not_end_with, is_empty,
        is_not_empty

        - filter[`order_date.<operator>`] — date filters. Operators: is, is_not, before,
        after, on_or_before, on_or_after, between, is_empty, is_not_empty, today,
        yesterday, past_week, past_month, past_year

        - filter[`quantity.<operator>`] / filter[`unit_price.<operator>`] — numeric
        filters. Operators: is, is_not, is_one_of, is_not_one_of, greater_than, less_than,
        greater_than_or_equal, less_than_or_equal, between, is_empty, is_not_empty

        - filter_groups — base64-encoded JSON tree for grouped AND/OR filter conditions,
        e.g. {"conjunction":"and","children":[{"type":"condition","condition":{"column":"quantity","operator":"greater_than","value":1}}]}


        Allowed sorts: id, order_date, order_number, order_status, fulfillment_status,
        customer_name, quantity, unit_price. Prefix with - for descending. Default:
        -order_date.


        Pagination: page, per_page (default 15).'
      parameters:
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: Product ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        sales_order_id:
                          type: integer
                        order_number:
                          type: string
                        order_date:
                          type: string
                        sales_channel_id:
                          type: integer
                        sales_channel_name:
                          type: string
                        customer_id:
                          type: integer
                        customer_name:
                          type: string
                        order_status:
                          type: string
                        fulfillment_status:
                          type: string
                        quantity:
                          type: integer
                        unit_price:
                          type: number
                        line_revenue:
                          type: number
                        profit:
                          type: number
                        warehouse_id:
                          type: integer
                        warehouse_name:
                          type: string
                  total:
                    type: integer
                  per_page:
                    type: integer
                  last_page:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 59881
                    sales_order_id: 295069
                    order_number: SO-10412
                    order_date: '2026-07-02T16:58:28.000000Z'
                    sales_channel_id: 30
                    sales_channel_name: TikTok Shop
                    customer_id: 818699
                    customer_name: Jane Cooper
                    order_status: closed
                    fulfillment_status: fulfilled
                    quantity: 1
                    unit_price: 149.99
                    line_revenue: 149.99
                    profit: 48.89
                    warehouse_id: 4
                    warehouse_name: Main Warehouse
                  total: 6
                  per_page: 15
                  last_page: 1
                  from: 1
                  to: 6
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-v2-products-product-sales
  /api/v2/products/{product}/fifo-layers:
    get:
      tags:
      - Products
      summary: Get Product FIFO Layers
      description: 'Get paginated FIFO cost layers for a product.


        :::info[Required scope: `products:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        example: '1'
        description: Page number (default 1).
      - name: per_page
        in: query
        schema:
          type: integer
        example: '15'
        description: Results per page (default 10).
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: Product ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        fifo_layer_date:
                          type: string
                        quantity:
                          type: integer
                        fulfilled_quantity:
                          type: integer
                        available_quantity:
                          type: integer
                        unit_cost:
                          type: number
                        total_cost:
                          type: number
                        warehouse_id:
                          type: integer
                        warehouse_name:
                          type: string
                        source_type:
                          type: string
                        source_reference:
                          type: string
                        link_type:
                          type: string
                        link_id:
                          type: integer
                        parent_link_id:
                          type: integer
                        detail_link_id:
                          type: string
                          nullable: true
                        condition:
                          type: string
                        is_consignment:
                          type: boolean
                        created_at:
                          type: string
                  total:
                    type: integer
                  per_page:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 10
                    fifo_layer_date: '2024-05-01'
                    quantity: 200
                    fulfilled_quantity: 50
                    available_quantity: 150
                    unit_cost: 5.5
                    total_cost: 1100.0
                    warehouse_id: 1
                    warehouse_name: Main Warehouse
                    source_type: Purchase Order
                    source_reference: PO-0015
                    link_type: App\Models\PurchaseOrderLine
                    link_id: 88
                    parent_link_id: 40
                    detail_link_id: null
                    condition: new
                    is_consignment: false
                    created_at: '2024-05-01T09:00:00Z'
                  total: 8
                  per_page: 15
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: products:read
      operationId: get-api-v2-products-product-fifo-layers
  /api/v2/products/{product}/lots-expiry:
    get:
      tags:
      - Products
      summary: Get Product Lots & Expiry
      description: 'Paginated lot/expiry breakdown scoped to a single product (the
        product detail "Lots & Expiry" tab).


        :::info[Required scope: `products:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Reuses the cross-warehouse expiry pipeline (internal FIFO layers + Amazon
        FBA layers), enriched with each lot''s review/disposition state. Each row
        is one batch/expiry FIFO layer with quantities, valuation, days-to-expiry,
        shelf-life remaining percentage, and review status.


        Authentication: Requires Bearer token.


        Pagination: page (default 1), per_page (default 25). Returns the standard
        Laravel paginator envelope (current_page, last_page, per_page, total, data).'
      parameters:
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: Product ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        fifo_layer_id:
                          type: integer
                        product_id:
                          type: integer
                        sku:
                          type: string
                        product_name:
                          type: string
                        brand_name:
                          type: string
                        supplier_name:
                          type: string
                        warehouse_id:
                          type: integer
                        warehouse_name:
                          type: string
                        bucket:
                          type: string
                        days_to_expiry:
                          type: integer
                        expiry_date:
                          type: string
                        manufacture_date:
                          type: string
                        batch_number:
                          type: string
                        shelf_life_remaining_pct:
                          type: number
                        link_type:
                          type: string
                        link_type_name:
                          type: string
                        link_id:
                          type: integer
                        quantity:
                          type: integer
                        avg_unit_cost:
                          type: number
                        total_value:
                          type: number
                        valuation_source:
                          type: string
                        is_fba:
                          type: boolean
                        review_status:
                          type: string
                        review_status_label:
                          type: string
                        review_notes:
                          type: string
                          nullable: true
                        reviewed_at:
                          type: string
                          nullable: true
                        reviewed_by_name:
                          type: string
                          nullable: true
                        inventory_hold_id:
                          type: string
                          nullable: true
                  from:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - fifo_layer_id: 9012
                    product_id: 42
                    sku: WDG-001
                    product_name: Blue Widget
                    brand_name: Acme
                    supplier_name: Global Supplies Ltd
                    warehouse_id: 1
                    warehouse_name: Main Warehouse
                    bucket: 0-30
                    days_to_expiry: 18
                    expiry_date: '2026-07-04T00:00:00.000000Z'
                    manufacture_date: '2026-01-04T00:00:00.000000Z'
                    batch_number: LOT-2026-0042
                    shelf_life_remaining_pct: 30.5
                    link_type: App\Models\PurchaseOrderLine
                    link_type_name: Purchase Order Line
                    link_id: 88
                    quantity: 150
                    avg_unit_cost: 5.5
                    total_value: 825.0
                    valuation_source: internal
                    is_fba: false
                    review_status: open
                    review_status_label: Open
                    review_notes: null
                    reviewed_at: null
                    reviewed_by_name: null
                    inventory_hold_id: null
                  - fifo_layer_id: null
                    product_id: 42
                    sku: WDG-001
                    product_name: Blue Widget
                    brand_name: Acme
                    supplier_name: null
                    warehouse_id: 87
                    warehouse_name: Amazon FBA (US)
                    bucket: 61-90
                    days_to_expiry: 74
                    expiry_date: '2026-08-29T00:00:00.000000Z'
                    manufacture_date: null
                    batch_number: FBA-LOT-7781
                    shelf_life_remaining_pct: null
                    link_type: null
                    link_type_name: ''
                    link_id: null
                    quantity: 60
                    avg_unit_cost: 5.75
                    total_value: 345.0
                    valuation_source: amazon
                    is_fba: true
                    review_status: null
                    review_status_label: null
                    review_notes: null
                    reviewed_at: null
                    reviewed_by_name: null
                    inventory_hold_id: null
                  from: 1
                  last_page: 1
                  per_page: 25
                  to: 2
                  total: 2
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: products:read
      operationId: get-api-v2-products-product-lots-expiry
  /api/v2/products/{product}/lots/{fifoLayer}/genealogy:
    get:
      tags:
      - Products
      summary: Get Product Lot Genealogy
      description: 'Read-only lot genealogy / traceability tree for a single FIFO
        layer (lot) of this product.


        :::info[Required scope: `products:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Returns two trees:

        - forward: downstream consumers (where the lot went — sales orders, manufacturing
        orders, transfers that consumed it).

        - backward: upstream ingredients (what was consumed to produce this lot, for
        manufactured lots). Purchased lots have an empty backward tree.


        Each node carries entity_type (''manufacturing_order'' | ''purchase_order''
        | ''sales_order'' | ''warehouse_transfer'' | ''fifo_layer''), reference, product
        info, batch_number, quantity, consumed_quantity (qty travelling along the
        parent->node edge), date, fifo_layer_id, and recursive children.


        Returns 404 if the FIFO layer does not belong to the product.


        Authentication: Requires Bearer token.'
      parameters:
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: Product ID
        example: '42'
      - name: fifoLayer
        in: path
        schema:
          type: integer
        required: true
        description: FIFO layer ID (the lot) to trace. Must belong to the product,
          otherwise 404.
        example: '9012'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      forward:
                        type: object
                        properties:
                          id:
                            type: string
                          entity_type:
                            type: string
                          reference:
                            type: string
                          product_id:
                            type: integer
                          product_name:
                            type: string
                          batch_number:
                            type: string
                          quantity:
                            type: integer
                          consumed_quantity:
                            type: string
                            nullable: true
                          date:
                            type: string
                          fifo_layer_id:
                            type: integer
                          manufacturing_order_id:
                            type: string
                            nullable: true
                          purchase_order_id:
                            type: integer
                          children:
                            type: array
                            items:
                              type: object
                              properties:
                                id:
                                  type: string
                                entity_type:
                                  type: string
                                reference:
                                  type: string
                                product_id:
                                  type: string
                                  nullable: true
                                product_name:
                                  type: string
                                  nullable: true
                                batch_number:
                                  type: string
                                  nullable: true
                                quantity:
                                  type: string
                                  nullable: true
                                consumed_quantity:
                                  type: integer
                                date:
                                  type: string
                                fifo_layer_id:
                                  type: string
                                  nullable: true
                                manufacturing_order_id:
                                  type: string
                                  nullable: true
                                purchase_order_id:
                                  type: string
                                  nullable: true
                                children:
                                  type: array
                      backward:
                        type: object
                        properties:
                          id:
                            type: string
                          entity_type:
                            type: string
                          reference:
                            type: string
                          product_id:
                            type: integer
                          product_name:
                            type: string
                          batch_number:
                            type: string
                          quantity:
                            type: integer
                          consumed_quantity:
                            type: string
                            nullable: true
                          date:
                            type: string
                          fifo_layer_id:
                            type: integer
                          manufacturing_order_id:
                            type: string
                            nullable: true
                          purchase_order_id:
                            type: integer
                          children:
                            type: array
                example:
                  data:
                    forward:
                      id: fifo-9012
                      entity_type: purchase_order
                      reference: PO-1234
                      product_id: 42
                      product_name: Blue Widget
                      batch_number: LOT-2026-0042
                      quantity: 200
                      consumed_quantity: null
                      date: '2026-01-04'
                      fifo_layer_id: 9012
                      manufacturing_order_id: null
                      purchase_order_id: 1234
                      children:
                      - id: terminal-App-Models-SalesOrderLine-55347
                        entity_type: sales_order
                        reference: SO-8842
                        product_id: null
                        product_name: null
                        batch_number: null
                        quantity: null
                        consumed_quantity: 50
                        date: '2026-02-12'
                        fifo_layer_id: null
                        manufacturing_order_id: null
                        purchase_order_id: null
                        children: []
                    backward:
                      id: fifo-9012
                      entity_type: purchase_order
                      reference: PO-1234
                      product_id: 42
                      product_name: Blue Widget
                      batch_number: LOT-2026-0042
                      quantity: 200
                      consumed_quantity: null
                      date: '2026-01-04'
                      fifo_layer_id: 9012
                      manufacturing_order_id: null
                      purchase_order_id: 1234
                      children: []
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Not Found
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: products:read
      operationId: get-api-v2-products-product-lots-fifolayer-genealogy
  /api/v2/products/{product}/activity-log:
    get:
      tags:
      - Products
      summary: Get Product Activity Log
      description: 'Get paginated activity log for a product (covers Product and SupplierProductPricing
        events).


        :::info[Required scope: `products:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        example: '1'
        description: Page number (default 1).
      - name: per_page
        in: query
        schema:
          type: integer
        description: 'Items per page (default: 15)'
        example: '15'
      - name: filter[search]
        in: query
        schema:
          type: string
        description: Search across causer name, properties, event, and subject type
        example: updated
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: Product ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        description:
                          type: string
                        event:
                          type: string
                        subject_type:
                          type: string
                        subject_id:
                          type: integer
                        properties:
                          type: object
                          properties:
                            attributes:
                              type: object
                              properties:
                                unit_cost:
                                  type: number
                            old:
                              type: object
                              properties:
                                unit_cost:
                                  type: number
                        causer_name:
                          type: string
                        created_at:
                          type: string
                  total:
                    type: integer
                  per_page:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 501
                    description: updated
                    event: updated
                    subject_type: Product
                    subject_id: 42
                    properties:
                      attributes:
                        unit_cost: 5.5
                      old:
                        unit_cost: 5.0
                    causer_name: John Smith
                    created_at: '2024-06-01T14:20:00Z'
                  total: 45
                  per_page: 15
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: products:read
      operationId: get-api-v2-products-product-activity-log
  /api/v2/products/{product}/notes:
    get:
      tags:
      - Products
      summary: Get Product Notes
      description: 'Get notes for a product, sorted by most recent first.


        :::info[Required scope: `products:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: Product ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        note:
                          type: string
                        created_at:
                          type: string
                        user:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                example:
                  data:
                  - id: 12
                    note: Check with supplier for Q3 pricing update
                    created_at: '2024-05-20T11:00:00Z'
                    user:
                      id: 2
                      name: Jane Doe
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: products:read
      operationId: get-api-v2-products-product-notes
  /api/v2/products/{product}/purchase-order-lines:
    get:
      tags:
      - Products
      summary: Get Product Purchase Order Lines
      description: 'Get purchase order lines for a product, filtered by status.


        :::info[Required scope: `products:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Excludes draft POs.'
      parameters:
      - name: status
        in: query
        schema:
          type: string
        description: 'Filter: ''inbound'' (unreceived_quantity > 0, default) or ''received''
          (received_quantity > 0)'
        example: inbound
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: Product ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        po_id:
                          type: integer
                        po_date:
                          type: string
                        po_number:
                          type: string
                        supplier_name:
                          type: string
                        quantity:
                          type: integer
                        received_quantity:
                          type: integer
                        unreceived_quantity:
                          type: integer
                example:
                  data:
                  - po_id: 88
                    po_date: '2024-05-10'
                    po_number: PO-0088
                    supplier_name: Global Supplies Ltd
                    quantity: 200
                    received_quantity: 0
                    unreceived_quantity: 200
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: products:read
      operationId: get-api-v2-products-product-purchase-order-lines
  /api/v2/products/{product}/inventory-tally:
    get:
      tags:
      - Products
      summary: Get Product Inventory Tally
      description: 'Get enriched inventory tally data for a product at a specific
        warehouse.


        :::info[Required scope: `products:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: warehouse_id
        in: query
        schema:
          type: integer
        description: Required. Warehouse ID to tally
        example: '1'
      - name: inventory_status
        in: query
        schema:
          type: string
        description: 'Optional. Inventory status: active (default) or in_transit'
        example: active
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: Product ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      total:
                        type: integer
                      available:
                        type: integer
                      allocated:
                        type: integer
                      movements:
                        type: array
                example:
                  data:
                    total: 300
                    available: 280
                    allocated: 20
                    movements: []
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      warehouse_id:
                        type: array
                        items:
                          type: string
                example:
                  message: The given data was invalid.
                  errors:
                    warehouse_id:
                    - The warehouse id field is required.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: products:read
      operationId: get-api-v2-products-product-inventory-tally
  /api/v2/products/{product}/warehouse-transfer-lines:
    get:
      tags:
      - Products
      summary: Get Product Warehouse Transfer Lines
      description: 'Get warehouse transfer lines for a product, showing in-transit
        or received quantities.


        :::info[Required scope: `products:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        For FBA/AWD destinations, quantity_received is derived from Amazon pending
        inbound data.'
      parameters:
      - name: status
        in: query
        schema:
          type: string
        description: 'Filter: ''in_transit'' (default) or ''received'''
        example: in_transit
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: Product ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        transfer_id:
                          type: integer
                        transfer_date:
                          type: string
                        warehouse_transfer_number:
                          type: string
                        from_warehouse:
                          type: string
                        to_warehouse:
                          type: string
                        quantity:
                          type: integer
                        quantity_received:
                          type: integer
                        quantity_unreceived:
                          type: integer
                example:
                  data:
                  - transfer_id: 20
                    transfer_date: '2024-05-28'
                    warehouse_transfer_number: WT-0020
                    from_warehouse: Main Warehouse
                    to_warehouse: FBA US
                    quantity: 100
                    quantity_received: 0
                    quantity_unreceived: 100
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: products:read
      operationId: get-api-v2-products-product-warehouse-transfer-lines
  /api/v2/products/{product}/holds:
    get:
      tags:
      - Products
      summary: Get Product Holds
      description: 'Get inventory holds for a product.


        :::info[Required scope: `inventory:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: Product ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        quantity:
                          type: integer
                        reason:
                          type: string
                        warehouse_id:
                          type: integer
                        created_at:
                          type: string
                example:
                  data:
                  - id: 3
                    quantity: 5
                    reason: Quality check
                    warehouse_id: 1
                    created_at: '2024-05-30T08:00:00Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: inventory:read
      operationId: get-api-v2-products-product-holds
  /api/v2/products/{product}/reservation-integrity:
    get:
      tags:
      - Products
      summary: Get Product Reservation Integrity
      description: 'Get reservation integrity issues for a product.


        Authentication: Requires Bearer token.'
      parameters:
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: Product ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      issues:
                        type: array
                      total_issues:
                        type: integer
                example:
                  data:
                    issues: []
                    total_issues: 0
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-v2-products-product-reservation-integrity
  /api/v2/products/{product}/active-reservations:
    get:
      tags:
      - Products
      summary: Get Product Active Reservations
      description: 'Get active (outstanding) inventory reservations for a product.


        Authentication: Requires Bearer token.'
      parameters:
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: Product ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        type:
                          type: string
                        quantity:
                          type: integer
                        reference:
                          type: string
                        warehouse_id:
                          type: integer
                example:
                  data:
                  - type: sales_order
                    quantity: 10
                    reference: SO-0042
                    warehouse_id: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-v2-products-product-active-reservations
  /api/v2/products/bulk-edit-metadata:
    get:
      tags:
      - Products
      summary: Get Bulk Edit Metadata
      description: 'Get dynamic field metadata for the bulk edit UI: attributes (with
        options), pricing tiers, supplier pricing tiers, and suppliers.


        :::info[Required scope: `products:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      attributes:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            type:
                              type: string
                            has_options:
                              type: boolean
                            options:
                              type: array
                              items:
                                type: string
                            group_name:
                              type: string
                      pricing_tiers:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            is_default:
                              type: boolean
                      supplier_pricing_tiers:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            is_default:
                              type: boolean
                            currency_code:
                              type: string
                      suppliers:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                example:
                  data:
                    attributes:
                    - id: 1
                      name: Color
                      type: text
                      has_options: true
                      options:
                      - Red
                      - Blue
                      - Green
                      group_name: Physical
                    pricing_tiers:
                    - id: 1
                      name: Retail
                      is_default: true
                    supplier_pricing_tiers:
                    - id: 1
                      name: Default
                      is_default: true
                      currency_code: USD
                    suppliers:
                    - id: 3
                      name: Global Supplies Ltd
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: products:read
      operationId: get-api-v2-products-bulk-edit-metadata
  /api/v2/products/bulk-edit-fetch:
    get:
      tags:
      - Products
      summary: Fetch Products for Bulk Edit
      description: 'Fetch products with all editable fields loaded for the bulk edit
        page.


        :::info[Required scope: `products:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Includes basic info, shipping dimensions, costing, accounting nominal codes,
        tax, attributes, pricing, suppliers, and supplier pricing (per supplier ×
        tier).'
      parameters:
      - name: ids
        in: query
        schema:
          type: string
        description: Required. Comma-separated product IDs to fetch for editing
        example: 42,43,44
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        sku:
                          type: string
                        name:
                          type: string
                        type:
                          type: string
                        barcode:
                          type: string
                        mpn:
                          type: string
                        hts_code:
                          type: string
                        unit_cost:
                          type: number
                        is_dropshippable:
                          type: boolean
                        brand_id:
                          type: integer
                        brand_name:
                          type: string
                        weight:
                          type: number
                        weight_unit:
                          type: string
                        attributes:
                          type: array
                          items:
                            type: object
                            properties:
                              attribute_id:
                                type: integer
                              attribute_name:
                                type: string
                              value:
                                type: string
                        pricing:
                          type: array
                          items:
                            type: object
                            properties:
                              tier_id:
                                type: integer
                              tier_name:
                                type: string
                              price:
                                type: number
                        suppliers:
                          type: array
                          items:
                            type: object
                            properties:
                              supplier_id:
                                type: integer
                              supplier_name:
                                type: string
                              is_default:
                                type: boolean
                        supplier_pricing:
                          type: array
                          items:
                            type: object
                            properties:
                              supplier_product_id:
                                type: integer
                              supplier_id:
                                type: integer
                              supplier_name:
                                type: string
                              tier_id:
                                type: integer
                              tier_name:
                                type: string
                              price:
                                type: number
                              currency_code:
                                type: string
                example:
                  data:
                  - id: 42
                    sku: WDG-001
                    name: Blue Widget
                    type: standard
                    barcode: 0123456789012
                    mpn: BW-001
                    hts_code: 8471.30.0100
                    unit_cost: 5.5
                    is_dropshippable: false
                    brand_id: 1
                    brand_name: Acme
                    weight: 0.5
                    weight_unit: kg
                    attributes:
                    - attribute_id: 1
                      attribute_name: Color
                      value: Blue
                    pricing:
                    - tier_id: 1
                      tier_name: Retail
                      price: 12.99
                    suppliers:
                    - supplier_id: 3
                      supplier_name: Global Supplies Ltd
                      is_default: true
                    supplier_pricing:
                    - supplier_product_id: 11
                      supplier_id: 3
                      supplier_name: Global Supplies Ltd
                      tier_id: 1
                      tier_name: Default
                      price: 4.5
                      currency_code: USD
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: products:read
      operationId: get-api-v2-products-bulk-edit-fetch
  /api/v2/products/bulk-edit:
    post:
      tags:
      - Products
      summary: Bulk Edit Products (Apply to All)
      description: "Apply the same set of changes to all selected products.\n\n:::info[Required\
        \ scope: `products:write`]\nGrant this scope to your token under [Settings\
        \ → Developer → Personal Access Tokens](https://app.sku.io/settings/api).\n\
        :::\n\nAuthentication: Requires Bearer token.\n\nFields:\n- product_ids (required,\
        \ array, max 500): Product IDs to update\n- changes (required, array): List\
        \ of changes, each with:\n  - field (required, string): Field name to change.\
        \ Supports scalar product fields (e.g. weight, weight_unit, unit_cost, brand_id),\
        \ 'pricing' (customer pricing tiers), 'supplier_pricing' (per-supplier pricing\
        \ tiers — applies to ALL suppliers of each product), 'attribute' (custom attributes),\
        \ and 'supplier' (link suppliers).\n  - operation (required, string): Operation\
        \ type. Scalars use 'set' / 'clear'. Numeric/pricing/supplier_pricing also\
        \ accept 'increase_by_amount', 'decrease_by_amount', 'increase_by_percent',\
        \ 'decrease_by_percent'.\n  - value (nullable): New value\n  - tier_id (nullable,\
        \ integer): Required for 'pricing' (references product_pricing_tiers) and\
        \ 'supplier_pricing' (references supplier_pricing_tiers). Validation routes\
        \ to the correct table based on the sibling 'field' value.\n  - attribute_id\
        \ (nullable, integer): Required for attribute field changes\n  - supplier_id\
        \ (nullable, integer): Required for supplier field changes\n\n**Requires permission:**\
        \ `products.update`"
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                product_ids:
                  type: array
                  items:
                    type: integer
                changes:
                  type: array
                  items:
                    type: object
                    properties:
                      field:
                        type: string
                      operation:
                        type: string
                      value:
                        type: number
              example:
                product_ids:
                - 42
                - 43
                - 44
                changes:
                - field: weight
                  operation: set
                  value: 0.6
                - field: weight_unit
                  operation: set
                  value: kg
                - field: pricing
                  operation: set
                  tier_id: 1
                  value: 14.99
                - field: supplier_pricing
                  operation: increase_by_percent
                  tier_id: 1
                  value: 5
                - field: attribute
                  operation: set
                  attribute_id: 1
                  value: Blue
                - field: supplier
                  operation: add
                  supplier_id: 7
                - field: supplier_sku
                  operation: set
                  supplier_id: 7
                  value: VENDOR-PART-123
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      updated:
                        type: integer
                      failed:
                        type: integer
                example:
                  data:
                    updated: 3
                    failed: 0
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      product_ids:
                        type: array
                        items:
                          type: string
                      changes.0.field:
                        type: array
                        items:
                          type: string
                example:
                  message: The given data was invalid.
                  errors:
                    product_ids:
                    - The product ids field is required.
                    changes.0.field:
                    - Each change must specify a field.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: products:write
      operationId: post-api-v2-products-bulk-edit
  /api/v2/products/bulk-edit-individual:
    post:
      tags:
      - Products
      summary: Bulk Edit Products (Individual)
      description: 'Apply individual per-product changes.


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Max 100 products per request. Each product''s changes object supports:

        - Basic: name, brand_id, is_dropshippable, barcode, mpn, hts_code

        - Shipping: weight, weight_unit, length, width, height, dimension_unit, case_quantity,
        case_weight, case_weight_unit, case_length, case_width, case_height, case_dimension_unit,
        fba_prep_instructions

        - Costing: unit_cost, proforma_shipping_cost, proforma_landed_cost_percentage,
        proforma_marketplace_cost_percentage

        - Accounting: sales_nominal_code_id, cogs_nominal_code_id, inventory_nominal_code_id,
        inventory_in_transit_nominal_code_id, accrued_purchases_nominal_code_id, discount_nominal_code_id

        - Tax: is_taxable, default_tax_rate_id

        - Taxonomy: primary_category_id, tags_add (array), tags_remove (array)

        - Inventory: min_stock_level

        - Pricing: pricing[].tier_id + pricing[].price

        - Attributes: attributes[].attribute_id + attributes[].value'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                products:
                  type: array
                  items:
                    type: object
                    properties:
                      id:
                        type: integer
                      changes:
                        type: object
                        properties:
                          name:
                            type: string
                          weight:
                            type: number
                          weight_unit:
                            type: string
                          unit_cost:
                            type: number
                          is_dropshippable:
                            type: boolean
                          min_stock_level:
                            type: integer
                          pricing:
                            type: array
                            items:
                              type: object
                              properties:
                                tier_id:
                                  type: integer
                                price:
                                  type: number
                          attributes:
                            type: array
                            items:
                              type: object
                              properties:
                                attribute_id:
                                  type: integer
                                value:
                                  type: string
                          supplier_skus:
                            type: array
                            items:
                              type: object
                              properties:
                                supplier_id:
                                  type: integer
                                supplier_sku:
                                  type: string
                          tags_add:
                            type: array
                            items:
                              type: string
                          tags_remove:
                            type: array
                            items:
                              type: string
              example:
                products:
                - id: 42
                  changes:
                    name: Blue Widget Pro
                    weight: 0.6
                    weight_unit: kg
                    unit_cost: 5.75
                    is_dropshippable: false
                    min_stock_level: 100
                    pricing:
                    - tier_id: 1
                      price: 13.99
                    attributes:
                    - attribute_id: 1
                      value: Blue
                    supplier_skus:
                    - supplier_id: 7
                      supplier_sku: VENDOR-PART-123
                    tags_add:
                    - new-tag
                    tags_remove:
                    - old-tag
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      updated:
                        type: integer
                      failed:
                        type: integer
                example:
                  data:
                    updated: 1
                    failed: 0
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: products:write
      operationId: post-api-v2-products-bulk-edit-individual
  /api/v2/products/bulk-edit-preview:
    post:
      tags:
      - Products
      summary: Preview Bulk Edit
      description: 'Preview bulk edit changes without applying them (dry run). Safe
        to call repeatedly.


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        For mode=''apply_to_all'': requires product_ids and changes.

        For mode=''individual'': requires products[].id and products[].changes.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                mode:
                  type: string
                product_ids:
                  type: array
                  items:
                    type: integer
                changes:
                  type: array
                  items:
                    type: object
                    properties:
                      field:
                        type: string
                      operation:
                        type: string
                      value:
                        type: number
              example:
                mode: apply_to_all
                product_ids:
                - 42
                - 43
                changes:
                - field: weight
                  operation: set
                  value: 0.6
                - field: supplier_pricing
                  operation: set
                  tier_id: 1
                  value: 4.75
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        product_id:
                          type: integer
                        sku:
                          type: string
                        changes:
                          type: array
                          items:
                            type: object
                            properties:
                              field:
                                type: string
                              field_label:
                                type: string
                              old_value:
                                type: number
                              new_value:
                                type: number
                example:
                  data:
                  - product_id: 42
                    sku: WDG-001
                    changes:
                    - field: weight
                      field_label: Weight
                      old_value: 0.5
                      new_value: 0.6
                    - field: supplier_pricing.1.3
                      field_label: 'Supplier Price: Global Supplies Ltd — Default'
                      old_value: 4.5
                      new_value: 4.75
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: products:write
      operationId: post-api-v2-products-bulk-edit-preview
  /api/v2/products/bundle-workshop:
    get:
      tags:
      - Products
      summary: List Bundle Workshop Products
      description: 'List all bundle/kit products with component counts and configuration
        status.


        :::info[Required scope: `products:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        example: '1'
        description: Page number (default 1).
      - name: per_page
        in: query
        schema:
          type: integer
        example: '10'
        description: Results per page (default 10).
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        sku:
                          type: string
                        name:
                          type: string
                        type:
                          type: string
                        image_url:
                          type: string
                          nullable: true
                        components_count:
                          type: integer
                        is_configured:
                          type: boolean
                  total:
                    type: integer
                  per_page:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 5
                    sku: BUNDLE-001
                    name: Widget Bundle
                    type: bundle
                    image_url: null
                    components_count: 2
                    is_configured: true
                  total: 12
                  per_page: 10
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: products:read
      operationId: get-api-v2-products-bundle-workshop
  /api/v2/products/bundle-workshop/auto-detect:
    get:
      tags:
      - Products
      summary: Auto-Detect Bundle Candidates
      description: 'Auto-detect standard products that may be bundles/kits based on
        naming patterns.


        :::info[Required scope: `products:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Returns products with detected_pattern, suggested_type, confidence, has_inventory_movements,
        and components_count (number of components already configured on the product
        — used by the conversion queue to know whether component configuration is
        required before converting to bundle/kit).'
      parameters:
      - name: filter[confidence]
        in: query
        schema:
          type: string
        description: 'Confidence filter: all, high, medium, low'
        example: high
      - name: filter[mode]
        in: query
        schema:
          type: string
        description: 'Mode: suggestions (pattern-matched only) or all (all standard
          products)'
        example: suggestions
      - name: page
        in: query
        schema:
          type: integer
        example: '1'
        description: Page number (default 1).
      - name: per_page
        in: query
        schema:
          type: integer
        example: '20'
        description: Results per page (default 10).
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        sku:
                          type: string
                        name:
                          type: string
                        type:
                          type: string
                        image_url:
                          type: string
                          nullable: true
                        detected_pattern:
                          type: string
                        suggested_type:
                          type: string
                        confidence:
                          type: string
                        has_inventory_movements:
                          type: boolean
                        components_count:
                          type: integer
                  total:
                    type: integer
                  per_page:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 100
                    sku: BUNDLE-KIT-001
                    name: Widget Bundle Kit
                    type: standard
                    image_url: null
                    detected_pattern: bundle_suffix
                    suggested_type: bundle
                    confidence: high
                    has_inventory_movements: false
                    components_count: 0
                  total: 8
                  per_page: 20
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: products:read
      operationId: get-api-v2-products-bundle-workshop-auto-detect
  /api/v2/products/bundle-workshop/batch-convert:
    post:
      tags:
      - Products
      summary: Batch Convert Products to Bundle/Kit
      description: "Batch convert standard products to bundle/kit types.\n\n:::info[Required\
        \ scope: `products:write`]\nGrant this scope to your token under [Settings\
        \ → Developer → Personal Access Tokens](https://app.sku.io/settings/api).\n\
        :::\n\nAuthentication: Requires Bearer token.\n\nFields:\n- products (required,\
        \ array, min 1): Products to convert\n  - id (required, integer): Product\
        \ ID\n  - type (required, string): Target type — bundle, kit, or standard\n\
        \  - components (optional, array): Components to save on the product BEFORE\
        \ converting. Only applies when type is bundle or kit. Allows converting a\
        \ product that currently has zero components in a single atomic call.\n  \
        \  - id (required, integer, must exist in products): Component product ID.\
        \ Components must be standard or kit products (a bundle cannot be a component).\n\
        \    - quantity (required, numeric, min 1): Quantity of this component per\
        \ parent unit.\n\n**Component handling:** When `components` is provided for\
        \ a bundle/kit target, they are saved first (via the bundle/kit component\
        \ setter for the target type), then the type conversion proceeds. If the component\
        \ save fails (e.g. a component is itself a bundle, a kit component references\
        \ itself, or a circular kit reference is detected), the item is skipped with\
        \ the validation message as `reason` and the product type is left unchanged.\n\
        \n**Skip rules — returned in `data.skipped[]`:**\n- Converting to `bundle`\
        \ when the source product has prior sale/assembly inventory movements (cannot\
        \ become a bundle once it has movement history).\n- Converting to `bundle`\
        \ or `kit` when the source product has zero components AND no `components`\
        \ were provided in the request (you must add components before promoting it).\n\
        - Provided `components` failed validation (invalid component type, self/circular\
        \ reference) — the validation message is returned as the skip reason.\n\n\
        The response payload includes `data.converted_count` for successful conversions\
        \ and `data.skipped[]` for entries that were skipped, each with `id`, `sku`,\
        \ and a human-readable `reason`."
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                products:
                  type: array
                  items:
                    type: object
                    properties:
                      id:
                        type: integer
                      type:
                        type: string
                      components:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            quantity:
                              type: integer
              example:
                products:
                - id: 100
                  type: bundle
                  components:
                  - id: 200
                    quantity: 2
                  - id: 201
                    quantity: 1
                - id: 101
                  type: kit
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      converted_count:
                        type: integer
                      skipped:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            sku:
                              type: string
                            reason:
                              type: string
                example:
                  data:
                    converted_count: 2
                    skipped:
                    - id: 102
                      sku: WIDGET-PACK
                      reason: No components — add components before converting to
                        bundle
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: products:write
      operationId: post-api-v2-products-bundle-workshop-batch-convert
  /api/v2/products/bundle-workshop/check-restrictions:
    post:
      tags:
      - Products
      summary: Check Bundle Restrictions
      description: 'Check which products have sale/assembly inventory movements that
        would restrict type changes.


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                product_ids:
                  type: array
                  items:
                    type: integer
              example:
                product_ids:
                - 42
                - 43
                - 44
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      '42':
                        type: object
                        properties:
                          has_restriction:
                            type: boolean
                          movement_count:
                            type: integer
                      '43':
                        type: object
                        properties:
                          has_restriction:
                            type: boolean
                          movement_count:
                            type: integer
                example:
                  data:
                    '42':
                      has_restriction: false
                      movement_count: 0
                    '43':
                      has_restriction: true
                      movement_count: 5
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: products:write
      operationId: post-api-v2-products-bundle-workshop-check-restrictions
  /api/v2/products/bundle-workshop/{product}/components:
    get:
      tags:
      - Products
      summary: Get Bundle Components
      description: 'Get components for a specific bundle/kit product in the Bundle
        Workshop.


        :::info[Required scope: `products:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: Bundle/Kit Product ID
        example: '5'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        sku:
                          type: string
                        name:
                          type: string
                        quantity:
                          type: integer
                example:
                  data:
                  - id: 10
                    sku: COMP-A
                    name: Component A
                    quantity: 2
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: products:read
      operationId: get-api-v2-products-bundle-workshop-product-components
    post:
      tags:
      - Products
      summary: Save Bundle Components
      description: "Save/sync components for a bundle/kit. Replaces all existing components.\n\
        \n:::info[Required scope: `products:write`]\nGrant this scope to your token\
        \ under [Settings → Developer → Personal Access Tokens](https://app.sku.io/settings/api).\n\
        :::\n\nAuthentication: Requires Bearer token.\n\nFields:\n- components (required,\
        \ array, **min 1 entry**): Component list. Empty arrays are rejected — a bundle/kit\
        \ must always have at least one component.\n  - id (required, integer): Component\
        \ product ID\n  - quantity (required, numeric, min 1): Quantity of this component\
        \ in the bundle\n\nReturns a 422 validation error if `components` is empty\
        \ or missing."
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                components:
                  type: array
                  items:
                    type: object
                    properties:
                      id:
                        type: integer
                      quantity:
                        type: integer
              example:
                components:
                - id: 10
                  quantity: 2
                - id: 11
                  quantity: 1
      parameters:
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: Bundle/Kit Product ID
        example: '5'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      components_count:
                        type: integer
                example:
                  data:
                    components_count: 2
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Cannot add bundle as its own component.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: products:write
      operationId: post-api-v2-products-bundle-workshop-product-components
  /api/v2/products/bundle-workshop/{product}/restricting-movements:
    get:
      tags:
      - Products
      summary: Get Restricting Movements
      description: 'Get paginated sale/assembly inventory movements that restrict
        type changes for a product.


        :::info[Required scope: `products:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        example: '1'
        description: Page number (default 1).
      - name: per_page
        in: query
        schema:
          type: integer
        description: 'Items per page (default: 15)'
        example: '15'
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: Product ID
        example: '5'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        type:
                          type: string
                        quantity:
                          type: integer
                        reference:
                          type: string
                        warehouse_name:
                          type: string
                        inventory_movement_date:
                          type: string
                  total:
                    type: integer
                  per_page:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 2001
                    type: assembly
                    quantity: -2
                    reference: ASM-0015
                    warehouse_name: Main Warehouse
                    inventory_movement_date: '2024-04-10'
                  total: 5
                  per_page: 15
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: products:read
      operationId: get-api-v2-products-bundle-workshop-product-restricting-movements
  /api/v2/products/bundle-workshop/{product}/type:
    put:
      tags:
      - Products
      summary: Update Bundle Type
      description: 'Update the type of an existing bundle/kit product (bundle ↔ kit
        ↔ standard).


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Only bundle or kit products can have their type changed via this endpoint.


        **Component requirement:** Converting to `bundle` or `kit` requires the product
        to already have at least one component. Returns a 422 with `Cannot convert
        to a bundle or kit without at least one component. Add components first.`
        when the source product has zero components.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                type:
                  type: string
              example:
                type: kit
      parameters:
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: Bundle/Kit Product ID
        example: '5'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      type:
                        type: string
                example:
                  data:
                    id: 5
                    type: kit
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Only bundle or kit products can have their type changed.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: products:write
      operationId: put-api-v2-products-bundle-workshop-product-type
  /api/v2/products/import/fields:
    get:
      tags:
      - Product Import
      summary: Get Import Fields
      description: 'Returns dynamic import fields (currently account-specific attributes)
        used by the column mapping UI.


        :::info[Required scope: `products:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Route: v2.products.import.fields


        Response shape: { data: { attributes: [{ key, label }] } }


        **Stock UoM (added 2026-05-30):** `stock_uom_code` is now a supported field.
        Provide a value matching an existing UoM code (e.g. EACH, KG, BOX). On create,
        it sets the product''s initial stock UoM; on update, it flips the stock UoM
        to the matching uom_id.'
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: products:read
      operationId: get-api-v2-products-import-fields
  /api/v2/products/import/template:
    get:
      tags:
      - Product Import
      summary: Download Import Template (XLSX)
      description: 'Downloads the multi-sheet XLSX import template, prefilled with
        sample rows and tenant reference data (brands, categories).


        :::info[Required scope: `products:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Route: v2.products.import.template


        update: the data sheet now includes nine new purple-headed image URL columns:

        - image_url_1 — Primary Image URL

        - image_url_2 .. image_url_9 — Additional gallery image URLs


        The guide sheet documents these columns. Sample rows include picsum.photos
        placeholder URLs for image_url_1, image_url_2, and image_url_3.


        Response: binary XLSX file (Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet).


        **Stock UoM (added 2026-05-30):** `stock_uom_code` is now a supported field.
        Provide a value matching an existing UoM code (e.g. EACH, KG, BOX). On create,
        it sets the product''s initial stock UoM; on update, it flips the stock UoM
        to the matching uom_id.'
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: products:read
      operationId: get-api-v2-products-import-template
  /api/v2/products/import/validate:
    post:
      tags:
      - Product Import
      summary: Validate Import
      description: "Validates mapped import rows and returns a structured preview.\
        \ No side effects — safe to call repeatedly.\n\n:::info[Required scope: `products:write`]\n\
        Grant this scope to your token under [Settings → Developer → Personal Access\
        \ Tokens](https://app.sku.io/settings/api).\n:::\n\nRoute: v2.products.import.validate\n\
        \nRequired body field:\n- rows: array (min 1) of row objects with mapped column\
        \ keys.\n\nadded image URL fields to the accepted row shape:\n- rows[].image_url_1\
        \ (string) — Primary image URL (http/https only, max 2048 chars)\n- rows[].image_url_2\
        \ .. rows[].image_url_9 (string) — Additional gallery image URLs\n\nValidation\
        \ rules for each image_url_N:\n- Must start with http:// or https://\n- Must\
        \ pass FILTER_VALIDATE_URL\n- Must be <= 2048 characters\n- Duplicate URLs\
        \ (case-insensitive) are skipped with a warning\n- If all image_url_* columns\
        \ are blank/unmapped, existing product images are left unchanged\n\nResponse\
        \ shape: { products: [...], summary: {...} }\n\nEach product entry includes\
        \ a new field:\n- _image_urls: array of { url, is_primary, sort_order, download\
        \ } | null\n  - null = no image_url_* columns mapped, OR all blank (existing\
        \ images preserved)\n  - Otherwise: ordered by image_url_1..9 position; image_url_1\
        \ becomes is_primary=true; download=true triggers async download/storage on\
        \ import.\n\nThe summary reports: total_products, total_new, total_updates,\
        \ total_errors, total_warnings.\n\n**Stock UoM (added 2026-05-30):** `stock_uom_code`\
        \ is now a supported field. Provide a value matching an existing UoM code\
        \ (e.g. EACH, KG, BOX). On create, it sets the product's initial stock UoM;\
        \ on update, it flips the stock UoM to the matching uom_id."
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                rows:
                  type: array
                  items:
                    type: object
                    properties:
                      sku:
                        type: string
                      name:
                        type: string
                      type:
                        type: string
                      barcode:
                        type: string
                      mpn:
                        type: string
                      hts_code:
                        type: string
                      brand:
                        type: string
                      category:
                        type: string
                      unit_cost:
                        type: number
                      weight:
                        type: number
                      weight_unit:
                        type: string
                      length:
                        type: integer
                      width:
                        type: integer
                      height:
                        type: integer
                      dimension_unit:
                        type: string
                      tags:
                        type: string
                      image_url_1:
                        type: string
                      image_url_2:
                        type: string
                      image_url_3:
                        type: string
                      image_url_4:
                        type: string
                      image_url_5:
                        type: string
                      image_url_6:
                        type: string
                      image_url_7:
                        type: string
                      image_url_8:
                        type: string
                      image_url_9:
                        type: string
              example:
                rows:
                - sku: SAMPLE-SKU-001
                  name: Sample Product One
                  type: standard
                  barcode: 012345678901
                  mpn: MFG-001
                  hts_code: 8471.30.0100
                  brand: Acme Co
                  category: Widgets
                  unit_cost: 9.99
                  weight: 0.5
                  weight_unit: kg
                  length: 10
                  width: 5
                  height: 3
                  dimension_unit: cm
                  tags: sample, import
                  image_url_1: https://picsum.photos/seed/sku-001-front/600/600
                  image_url_2: https://picsum.photos/seed/sku-001-back/600/600
                  image_url_3: https://picsum.photos/seed/sku-001-side/600/600
                  image_url_4: ''
                  image_url_5: ''
                  image_url_6: ''
                  image_url_7: ''
                  image_url_8: ''
                  image_url_9: ''
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: products:write
      operationId: post-api-v2-products-import-validate
  /api/v2/products/import:
    post:
      tags:
      - Product Import
      summary: Execute Import
      description: 'Imports run as a tracked job — a bulk import can exceed a ~100s
        edge-proxy limit (Cloudflare 524), so the rows are processed off the request
        cycle. Returns a tracked_job_log_id; progress and the created/updated/failed
        counts surface via the tracked job log endpoints. The request body is the
        validated rows from the import preview.


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                products:
                  type: array
                  items:
                    type: object
                    properties:
                      sku:
                        type: string
                      name:
                        type: string
                      type:
                        type: string
                      barcode:
                        type: string
                      mpn:
                        type: string
                      hts_code:
                        type: string
                      brand_id:
                        type: integer
                      category_id:
                        type: integer
                      unit_cost:
                        type: number
                      weight:
                        type: number
                      weight_unit:
                        type: string
                      length:
                        type: integer
                      width:
                        type: integer
                      height:
                        type: integer
                      dimension_unit:
                        type: string
                      tags:
                        type: string
                      _image_urls:
                        type: array
                        items:
                          type: object
                          properties:
                            url:
                              type: string
                            is_primary:
                              type: boolean
                            sort_order:
                              type: integer
                            download:
                              type: boolean
                      existing_product_id:
                        type: string
                        nullable: true
              example:
                products:
                - sku: SAMPLE-SKU-001
                  name: Sample Product One
                  type: standard
                  barcode: 012345678901
                  mpn: MFG-001
                  hts_code: 8471.30.0100
                  brand_id: 12
                  category_id: 7
                  unit_cost: 9.99
                  weight: 0.5
                  weight_unit: kg
                  length: 10
                  width: 5
                  height: 3
                  dimension_unit: cm
                  tags: sample, import
                  _image_urls:
                  - url: https://picsum.photos/seed/sku-001-front/600/600
                    is_primary: true
                    sort_order: 0
                    download: true
                  - url: https://picsum.photos/seed/sku-001-back/600/600
                    is_primary: false
                    sort_order: 1
                    download: true
                  - url: https://picsum.photos/seed/sku-001-side/600/600
                    is_primary: false
                    sort_order: 2
                    download: true
                  existing_product_id: null
      parameters: []
      responses:
        '202':
          description: Accepted
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 5123
                  message: Import queued — track progress in the job tray.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: products:write
      operationId: post-api-v2-products-import
  /api/v2/products/import-supplier-links/template:
    get:
      tags:
      - Products
      summary: Download Supplier Link Template
      description: 'Download the supplier link import template XLSX.


        :::info[Required scope: `products:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Response: XLSX file download.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
          content:
            text/plain:
              schema:
                type: string
                example: (binary XLSX file)
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: products:read
      operationId: get-api-v2-products-import-supplier-links-template
  /api/v2/products/import-supplier-links/validate:
    post:
      tags:
      - Products
      summary: Validate Supplier Link Import
      description: "Validate supplier link import data and return a preview.\n\n:::info[Required\
        \ scope: `products:write`]\nGrant this scope to your token under [Settings\
        \ → Developer → Personal Access Tokens](https://app.sku.io/settings/api).\n\
        :::\n\nAuthentication: Requires Bearer token.\n\nFields:\n- rows (required,\
        \ array, min 1): Rows to validate\n  - product_sku (present): Product SKU\n\
        \  - supplier_name (present): Supplier name"
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                rows:
                  type: array
                  items:
                    type: object
                    properties:
                      product_sku:
                        type: string
                      supplier_name:
                        type: string
              example:
                rows:
                - product_sku: WDG-001
                  supplier_name: Global Supplies Ltd
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  valid:
                    type: integer
                  invalid:
                    type: integer
                  rows:
                    type: array
                    items:
                      type: object
                      properties:
                        product_sku:
                          type: string
                        supplier_name:
                          type: string
                        valid:
                          type: boolean
                example:
                  valid: 1
                  invalid: 0
                  rows:
                  - product_sku: WDG-001
                    supplier_name: Global Supplies Ltd
                    valid: true
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: products:write
      operationId: post-api-v2-products-import-supplier-links-validate
  /api/v2/products/import-supplier-links:
    post:
      tags:
      - Products
      summary: Import Supplier Links
      description: 'Imports run as a tracked job — a bulk import can exceed a ~100s
        edge-proxy limit (Cloudflare 524), so the rows are processed off the request
        cycle. Returns a tracked_job_log_id; progress and the created/updated/failed
        counts surface via the tracked job log endpoints.


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                links:
                  type: array
                  items:
                    type: object
                    properties:
                      product_id:
                        type: integer
                      supplier_id:
                        type: integer
                      supplier_product_id:
                        type: string
                        nullable: true
              example:
                links:
                - product_id: 42
                  supplier_id: 3
                  supplier_product_id: null
      parameters: []
      responses:
        '202':
          description: Accepted
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 5123
                  message: Import queued — track progress in the job tray.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: products:write
      operationId: post-api-v2-products-import-supplier-links
  /api/v2/products/list/export:
    get:
      tags:
      - Products
      summary: Export Product List
      description: 'Export products as XLSX or CSV.


        :::info[Required scope: `products:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Scope options:

        - filtered: Uses current filter parameters (same as the products list)

        - all: All products (ignores filters)

        - current_page: First page of current filter results

        - selected: Specific product IDs (requires ids param)


        Content modes:

        - summary: One row per product (includes the product-level Default Supplier
        columns when requested)

        - suppliers: One row per product-supplier link. Emits the per-link supplier
        columns (Supplier Name, Supplier SKU, MOQ, Leadtime, Target Stock Days, Is
        Default, pricing tiers) and omits the duplicate product-level Default Supplier
        columns, so the file round-trips 1:1 with the supplier-links import template.


        Response (dual mode):

        - Small exports (≤ 1000 records, or scope=current_page): Returns the file
        directly as a binary download (XLSX or CSV).

        - Large exports (> 1000 records): Returns 200 application/json with `{ data:
        { tracked_job_log_id, queued: true }, message }`. The export is dispatched
        as a background job; track it via the tracked job log endpoints. Once complete,
        download via `GET /api/v2/products/list/export/download?file=<filename>` (the
        job''s `results.file` value).


        **Requires permission:** `products.export`'
      parameters:
      - name: format
        in: query
        schema:
          type: string
        description: 'Export format: xlsx (default) or csv'
        example: xlsx
      - name: scope
        in: query
        schema:
          type: string
        description: 'Export scope: filtered (default, uses active filters), all,
          current_page, selected'
        example: filtered
      - name: content_mode
        in: query
        schema:
          type: string
        description: 'Content mode: summary (default, one row per product) or suppliers
          (one row per product-supplier link; emits the per-link supplier columns
          and omits the duplicate product-level Default Supplier columns)'
        example: summary
      - name: columns
        in: query
        schema:
          type: string
        description: 'Comma-separated column keys to include. Omit for all columns.
          Available columns now include: stock_uom_code, stock_uom_name.'
        example: id,sku,name,type,inventory_total
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
          content:
            text/plain:
              schema:
                type: string
                example: (binary XLSX file)
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: products:read
      operationId: get-api-v2-products-list-export
  /api/v2/products/list/export/download:
    get:
      tags:
      - Products
      summary: Download Export File
      description: 'Download a completed products export file produced by a queued
        export tracked job.


        :::info[Required scope: `products:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Use this after `GET /api/v2/products/list/export` returned a queued JSON response.
        Poll the tracked job log endpoints for completion, then fetch the `results.file`
        value from the TrackedJobLog and pass it as the `file` query parameter.


        Response: File download (XLSX or CSV). Returns 404 if the file does not exist
        on the `model-exports` disk.


        **Requires permission:** `products.export`'
      parameters:
      - name: file
        in: query
        schema:
          type: string
        description: Filename returned by the queued export tracked job (`results.file`).
          Only basename is used server-side.
        example: products-export-2026-05-12-153045.xlsx
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
          content:
            text/plain:
              schema:
                type: string
                example: (binary XLSX file)
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Not Found
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: products:read
      operationId: get-api-v2-products-list-export-download
  /api/v2/products/lookup:
    get:
      tags:
      - Products
      summary: Lookup Products
      description: 'Lightweight paginated product lookup that returns only core identifying
        fields (id, sku, name, barcode, type, unit_cost, price, image_url) — much
        faster than the full List Products endpoint when you only need to resolve
        products by SKU, name, barcode, or id.


        :::info[Required scope: `products:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        When a search term is given, results are ranked exact-SKU match first, SKU
        prefix match second, then everything else; within each rank results are ordered
        by SKU. A fully-numeric term additionally matches the product id directly.
        Without a search term, all products are returned ordered by SKU.


        Archived products are excluded unless include_archived=true. Pass sellable_only=true
        to exclude non-sellable products (e.g. internal consumables).


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        sku:
                          type: string
                        name:
                          type: string
                        barcode:
                          type: string
                        type:
                          type: string
                        unit_cost:
                          type: number
                        price:
                          type: number
                        image_url:
                          type: string
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                    items:
                      type: object
                      properties:
                        url:
                          type: string
                          nullable: true
                        label:
                          type: string
                        active:
                          type: boolean
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 42
                    sku: WIDGET-BLUE
                    name: Blue Widget
                    barcode: 0123456789012
                    type: standard
                    unit_cost: 4.5
                    price: 4.5
                    image_url: https://example.sku.io/storage/images/widget-blue.jpg
                  - id: 87
                    sku: WIDGET-BLUE-2PK
                    name: Blue Widget - 2 Pack
                    barcode: 0123456789029
                    type: bundle
                    unit_cost: 9
                    price: 9
                    image_url: null
                  first_page_url: https://example.sku.io/api/v2/products/lookup?page=1
                  from: 1
                  last_page: 1
                  last_page_url: https://example.sku.io/api/v2/products/lookup?page=1
                  links:
                  - url: null
                    label: '&laquo; Previous'
                    active: false
                  - url: https://example.sku.io/api/v2/products/lookup?page=1
                    label: '1'
                    active: true
                  - url: null
                    label: Next &raquo;
                    active: false
                  next_page_url: null
                  path: https://example.sku.io/api/v2/products/lookup
                  per_page: 20
                  prev_page_url: null
                  to: 2
                  total: 2
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: products:read
      operationId: get-api-v2-products-lookup
  /api/product-brands:
    post:
      tags:
      - Organization
      summary: Create Product Brand
      description: 'Creates a new product brand.


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Validation:

        - `name` (required, max 255, unique across product_brands)'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
              example:
                name: Nike
      parameters: []
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                  message:
                    type: string
                example:
                  data:
                    id: 42
                    name: Nike
                    created_at: '2024-04-01T12:00:00.000000Z'
                    updated_at: '2024-04-01T12:00:00.000000Z'
                    archived_at: null
                  message: Product brand has been created successfully
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      name:
                        type: array
                        items:
                          type: string
                example:
                  message: The name has already been taken.
                  errors:
                    name:
                    - The name has already been taken.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: products:write
      operationId: post-api-product-brands
    get:
      tags:
      - Organization
      summary: List Product Brands
      description: 'Returns a paginated list of product brands.


        Authentication: Requires Bearer token.


        Supports search, sort, pagination, archived filter, and column inclusion/exclusion.


        Allowed sort fields: name, created_at, updated_at.'
      parameters:
      - name: search
        in: query
        schema:
          type: string
        description: General text search across searchable columns (name)
        example: nike
      - name: sort
        in: query
        schema:
          type: string
        description: 'Sort column. Prefix with - for descending (e.g. -name). Sortable:
          name, created_at, updated_at.'
        example: name
      - name: page
        in: query
        schema:
          type: integer
        description: 'Page number (default: 1)'
        example: '1'
      - name: limit
        in: query
        schema:
          type: integer
        description: 'Results per page (default: 25)'
        example: '25'
      - name: archived
        in: query
        schema:
          type: integer
        description: 0 = active only (default), 1 = archived only
        example: '0'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                        archived_at:
                          type: string
                          nullable: true
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - id: 1
                    name: Nike
                    created_at: '2024-01-15T10:00:00.000000Z'
                    updated_at: '2024-03-20T14:30:00.000000Z'
                    archived_at: null
                  - id: 2
                    name: Adidas
                    created_at: '2024-01-16T09:00:00.000000Z'
                    updated_at: '2024-03-21T11:00:00.000000Z'
                    archived_at: null
                  current_page: 1
                  last_page: 5
                  per_page: 25
                  total: 112
                  from: 1
                  to: 25
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-product-brands
    delete:
      tags:
      - Organization
      summary: Bulk Delete Product Brands
      description: 'Bulk deletes multiple product brands by ID.


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Validation:

        - `ids` (required, array of integers)'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 3 product brands have been deleted successfully
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: products:write
      operationId: delete-api-product-brands
  /api/product-brands/{id}:
    get:
      tags:
      - Organization
      summary: Get Product Brand
      description: 'Returns a single product brand by ID.


        :::info[Required scope: `products:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                example:
                  data:
                    id: 1
                    name: Nike
                    created_at: '2024-01-15T10:00:00.000000Z'
                    updated_at: '2024-03-20T14:30:00.000000Z'
                    archived_at: null
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No query results for model [App\Models\ProductBrand] 999
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: products:read
      operationId: get-api-product-brands-id
    put:
      tags:
      - Organization
      summary: Update Product Brand
      description: 'Updates a product brand''s name.


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Validation:

        - `name` (required, max 255, unique ignoring current record)'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
              example:
                name: Nike Inc.
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                  message:
                    type: string
                example:
                  data:
                    id: 1
                    name: Nike Inc.
                    created_at: '2024-01-15T10:00:00.000000Z'
                    updated_at: '2024-04-01T12:00:00.000000Z'
                    archived_at: null
                  message: Product brand Nike Inc. has been updated successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: products:write
      operationId: put-api-product-brands-id
    delete:
      tags:
      - Organization
      summary: Delete Product Brand
      description: 'Deletes a product brand. Fails if any products are still linked
        to the brand.


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Product brand Nike has been deleted successfully
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: array
                    items:
                      type: object
                      properties:
                        message:
                          type: string
                        code:
                          type: string
                        key:
                          type: string
                example:
                  message: Failed to delete product brand Nike
                  errors:
                  - message: Product brand(Nike) is currently used by 5 product(s)
                    code: ProductRESOURCE_LINKED
                    key: Products
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: products:write
      operationId: delete-api-product-brands-id
  /api/product-brands/{id}/archive:
    put:
      tags:
      - Organization
      summary: Archive Product Brand
      description: 'Archives a product brand. Sets archived_at timestamp. Returns
        a warning if already archived.


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      archived_at:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 1
                    name: Nike
                    created_at: '2024-01-15T10:00:00.000000Z'
                    updated_at: '2024-04-01T12:00:00.000000Z'
                    archived_at: '2024-04-01T12:00:00.000000Z'
                  message: Product brand Nike has been archived successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: products:write
      operationId: put-api-product-brands-id-archive
  /api/product-brands/{id}/unarchived:
    put:
      tags:
      - Organization
      summary: Unarchive Product Brand
      description: 'Unarchives a product brand. Clears archived_at. Returns a warning
        if already active.


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                  message:
                    type: string
                example:
                  data:
                    id: 1
                    name: Nike
                    created_at: '2024-01-15T10:00:00.000000Z'
                    updated_at: '2024-04-01T12:30:00.000000Z'
                    archived_at: null
                  message: Product brand Nike has been unarchived successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: products:write
      operationId: put-api-product-brands-id-unarchived
  /api/product-brands/archive:
    put:
      tags:
      - Organization
      summary: Bulk Archive Product Brands
      description: 'Bulk archives multiple product brands.


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 3
                - 4
                - 5
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 3 product brands have been archived successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: products:write
      operationId: put-api-product-brands-archive
  /api/product-brands/unarchive:
    put:
      tags:
      - Organization
      summary: Bulk Unarchive Product Brands
      description: 'Bulk unarchives multiple product brands.


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 3
                - 4
                - 5
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 3 product brands have been unarchived successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: products:write
      operationId: put-api-product-brands-unarchive
  /api/product-brands/deletable:
    post:
      tags:
      - Organization
      summary: Check Product Brands Deletable
      description: 'Checks whether each of the given product brand IDs can be safely
        deleted. A brand is not deletable if products are linked to it.


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Validation:

        - `ids` (required, array of integers, each must exist in product_brands table)

        - `ids.*` (integer)'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1
                - 2
                - 3
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        deletable:
                          type: boolean
                        reason:
                          type: object
                          properties:
                            Products:
                              type: string
                example:
                  data:
                  - id: 1
                    name: Nike
                    deletable: false
                    reason:
                      Products: Product brand(Nike) is currently used by 12 product(s)
                  - id: 2
                    name: Generic
                    deletable: true
                    reason: null
                  - id: 3
                    name: Unused Brand
                    deletable: true
                    reason: null
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: products:write
      operationId: post-api-product-brands-deletable
  /api/product-brands/search:
    get:
      tags:
      - Organization
      summary: Search Product Brands
      description: 'Simple search endpoint returning up to 50 product brands matching
        the name. Returns product brand object collection.


        :::info[Required scope: `products:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: search
        in: query
        schema:
          type: string
        description: Optional. Partial name match (LIKE %search%). Returns up to 50
          results ordered by name.
        example: nike
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                        archived_at:
                          type: string
                          nullable: true
                example:
                  data:
                  - id: 1
                    name: Nike
                    created_at: '2024-01-15T10:00:00.000000Z'
                    updated_at: '2024-03-20T14:30:00.000000Z'
                    archived_at: null
                  - id: 8
                    name: Nike Sport
                    created_at: '2024-02-01T09:00:00.000000Z'
                    updated_at: '2024-02-01T09:00:00.000000Z'
                    archived_at: null
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: products:read
      operationId: get-api-product-brands-search
  /api/product-brands/import/preview:
    post:
      tags:
      - Organization
      summary: Preview Product Brands Import
      description: 'Preview the result of importing product brands from a CSV/Excel
        file without committing the import.


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Content-Type: multipart/form-data'
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                file:
                  type: string
                  description: CSV or Excel file containing product brand data
                  format: binary
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      headers:
                        type: array
                        items:
                          type: string
                      rows:
                        type: array
                        items:
                          type: object
                          properties:
                            name:
                              type: string
                            status:
                              type: string
                      total:
                        type: integer
                      errors:
                        type: array
                example:
                  data:
                    headers:
                    - name
                    rows:
                    - name: New Brand A
                      status: create
                    - name: Nike
                      status: update
                    total: 2
                    errors: []
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: products:write
      operationId: post-api-product-brands-import-preview
  /api/product-brands/import:
    post:
      tags:
      - Organization
      summary: Import Product Brands
      description: 'Imports product brands from a CSV or Excel file. Each row must
        have a `name` column.


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Content-Type: multipart/form-data'
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                file:
                  type: string
                  description: CSV or Excel file containing product brand data with
                    a 'name' column
                  format: binary
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 'Import completed: 10 created, 2 updated, 0 errors'
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: products:write
      operationId: post-api-product-brands-import
  /api/v2/brands/{brand}:
    get:
      tags:
      - Organization
      summary: Get Brand Detail Summary
      description: 'Returns a single brand with lightweight aggregate stats for the
        Brand detail page header. Includes archived brands (a deep-link to an archived
        brand still resolves).


        Response fields: id, name, archived_at, created_at, updated_at, products_count
        (count of products assigned to the brand).


        Authentication: Requires Bearer token.'
      parameters:
      - name: brand
        in: path
        schema:
          type: integer
        required: true
        description: Brand ID (archived brands are resolvable)
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      products_count:
                        type: integer
                example:
                  data:
                    id: 1
                    name: Nike
                    archived_at: null
                    created_at: '2024-01-15T10:00:00.000000Z'
                    updated_at: '2024-03-20T14:30:00.000000Z'
                    products_count: 128
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No query results for model [App\Models\ProductBrand] 999
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-v2-brands-brand
  /api/v2/brands/{brand}/activity-log:
    get:
      tags:
      - Organization
      summary: Get Brand Activity Log
      description: 'Paginated, filterable activity log for a brand. Surfaces two signals:
        the brand''s own events (rename, archive, restore) and product brand-assignment
        changes (a product''s brand being set to or cleared from this brand).


        Each entry: id, description, event, subject_type (ProductBrand or Product),
        subject_id, properties (attributes/old change diff), causer_name, created_at.'
      parameters:
      - name: brand
        in: path
        schema:
          type: integer
        required: true
        description: Brand ID (archived brands are resolvable)
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        description:
                          type: string
                          nullable: true
                        event:
                          type: string
                        subject_type:
                          type: string
                        subject_id:
                          type: integer
                        properties:
                          type: object
                          properties:
                            attributes:
                              type: object
                              properties:
                                name:
                                  type: string
                            old:
                              type: object
                              properties:
                                name:
                                  type: string
                        causer_name:
                          type: string
                        created_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - id: 5012
                    description: null
                    event: updated
                    subject_type: ProductBrand
                    subject_id: 1
                    properties:
                      attributes:
                        name: Nike
                      old:
                        name: Nike Inc
                    causer_name: Jane Doe
                    created_at: '2024-03-20T14:30:00.000000Z'
                  - id: 5008
                    description: null
                    event: created
                    subject_type: Product
                    subject_id: 44
                    properties:
                      attributes:
                        brand_id: 1
                        sku: AIRMAX-90
                    causer_name: System
                    created_at: '2024-03-19T09:15:00.000000Z'
                  current_page: 1
                  last_page: 1
                  per_page: 15
                  total: 2
                  from: 1
                  to: 2
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-v2-brands-brand-activity-log
  /api/categories/{category}:
    get:
      tags:
      - Organization
      summary: Get Category
      description: 'Show a single product category with full detail including children,
        attribute groups, attributes, parent, and root info.


        :::info[Required scope: `products:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Response includes:

        - `products_count` — total products assigned to this category and all sub-categories

        - `products_ids` — first 10 product IDs assigned

        - `subcategories_count` — count of all subcategories

        - `attribute_groups` / `attributes` — linked attribute groups and attributes'
      parameters:
      - name: category
        in: path
        schema:
          type: integer
        required: true
        description: Category ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      parent_id:
                        type: string
                        nullable: true
                      parent_name:
                        type: string
                        nullable: true
                      category_tree:
                        type: string
                        nullable: true
                      is_leaf:
                        type: boolean
                      level:
                        type: integer
                      products_count:
                        type: integer
                      products_ids:
                        type: array
                        items:
                          type: integer
                      subcategories_count:
                        type: integer
                      attribute_groups_count:
                        type: integer
                      attribute_groups:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                      attributes_count:
                        type: integer
                      attributes:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            type:
                              type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                  status:
                    type: string
                example:
                  data:
                    id: 1
                    name: Electronics
                    parent_id: null
                    parent_name: null
                    category_tree: null
                    is_leaf: false
                    level: 0
                    products_count: 128
                    products_ids:
                    - 10
                    - 11
                    - 12
                    - 13
                    - 14
                    - 15
                    - 16
                    - 17
                    - 18
                    - 19
                    subcategories_count: 4
                    attribute_groups_count: 2
                    attribute_groups:
                    - id: 1
                      name: Technical Specs
                    attributes_count: 5
                    attributes:
                    - id: 3
                      name: Color
                      type: text
                    - id: 4
                      name: Weight
                      type: number
                    created_at: '2024-01-15T10:00:00.000000Z'
                    updated_at: '2024-01-20T08:30:00.000000Z'
                    archived_at: null
                  status: success
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No query results for model [App\Models\ProductCategory]
                    999
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: products:read
      operationId: get-api-categories-category
    put:
      tags:
      - Organization
      summary: Update Category
      description: 'Update an existing product category. Attribute groups and attributes
        are synced (replaced entirely if provided).


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Request body fields:

        - `name` (optional) — category name; must be unique within the same parent

        - `parent_id` (optional) — parent category ID

        - `attribute_groups` (optional) — array of attribute group IDs to sync

        - `attributes` (optional) — array of attribute IDs to sync


        **Requires permission:** `categories.update`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                parent_id:
                  type: integer
                attribute_groups:
                  type: array
                  items:
                    type: integer
                attributes:
                  type: array
                  items:
                    type: integer
              example:
                name: Gaming Laptops
                parent_id: 1
                attribute_groups:
                - 1
                attributes:
                - 3
      parameters:
      - name: category
        in: path
        schema:
          type: integer
        required: true
        description: Category ID
        example: '5'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      parent_id:
                        type: integer
                      parent_name:
                        type: string
                        nullable: true
                      is_leaf:
                        type: boolean
                      level:
                        type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                  message:
                    type: string
                  status:
                    type: string
                example:
                  data:
                    id: 5
                    name: Gaming Laptops
                    parent_id: 1
                    parent_name: null
                    is_leaf: true
                    level: 1
                    created_at: '2024-03-01T10:00:00.000000Z'
                    updated_at: '2024-03-02T09:15:00.000000Z'
                    archived_at: null
                  message: category Gaming Laptops was updated successfully
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: products:write
      operationId: put-api-categories-category
    delete:
      tags:
      - Organization
      summary: Delete Category
      description: 'Delete a product category. Only leaf categories (is_leaf = true)
        can be deleted.


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Returns 400 if the category is not a leaf node (has children).


        **Requires permission:** `categories.delete`'
      parameters:
      - name: category
        in: path
        schema:
          type: integer
        required: true
        description: Category ID
        example: '5'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  status:
                    type: string
                example:
                  message: category and its associations Gaming Laptops was deleted
                    successfully
                  status: success
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: array
                    items:
                      type: object
                      properties:
                        code:
                          type: string
                        field:
                          type: string
                        meta:
                          type: object
                          properties:
                            id:
                              type: integer
                  status:
                    type: string
                example:
                  message: Category deletion failed
                  errors:
                  - code: ProductCategoryNOT_LEAF
                    field: id
                    meta:
                      id: 1
                  status: error
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: products:write
      operationId: delete-api-categories-category
  /api/categories:
    post:
      tags:
      - Organization
      summary: Create Category
      description: 'Create a new product category.


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Request body fields:

        - `name` (required) — category name; must be unique within the same parent

        - `parent_id` (optional) — parent category ID; null creates a root category

        - `attribute_groups` (optional) — array of attribute group IDs to link

        - `attributes` (optional) — array of attribute IDs to link


        **Requires permission:** `categories.create`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                parent_id:
                  type: integer
                attribute_groups:
                  type: array
                  items:
                    type: integer
                attributes:
                  type: array
                  items:
                    type: integer
              example:
                name: Laptops
                parent_id: 1
                attribute_groups:
                - 1
                - 2
                attributes:
                - 3
                - 4
                - 5
      parameters: []
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      parent_id:
                        type: integer
                      parent_name:
                        type: string
                        nullable: true
                      is_leaf:
                        type: boolean
                      level:
                        type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                  message:
                    type: string
                  status:
                    type: string
                example:
                  data:
                    id: 5
                    name: Laptops
                    parent_id: 1
                    parent_name: null
                    is_leaf: true
                    level: 1
                    created_at: '2024-03-01T10:00:00.000000Z'
                    updated_at: '2024-03-01T10:00:00.000000Z'
                    archived_at: null
                  message: category was created successfully
                  status: success
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      name:
                        type: array
                        items:
                          type: string
                      parent_id:
                        type: array
                        items:
                          type: string
                example:
                  message: The given data was invalid.
                  errors:
                    name:
                    - The name field is required.
                    parent_id:
                    - The selected parent_id is invalid.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: products:write
      operationId: post-api-categories
    get:
      tags:
      - Organization
      summary: List Categories
      description: 'List product categories. Supports search, sort, pagination, and
        archiving filters.


        Authentication: Requires Bearer token.


        Query parameters:

        - `page` / `limit` — pagination

        - `search` — full-text search on name

        - `sort` — sortable columns: id, name, created_at, updated_at, archived_at

        - `archived` — 0 (active), 1 (archived)

        - `filter[name]` — filter by name

        - `included[]` / `excluded[]` — force-include or exclude specific IDs'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        description: 'Page number (default: 1)'
        example: '1'
      - name: limit
        in: query
        schema:
          type: integer
        description: 'Records per page (default: 15)'
        example: '15'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        parent_id:
                          type: string
                          nullable: true
                        parent_name:
                          type: string
                          nullable: true
                        is_leaf:
                          type: boolean
                        level:
                          type: integer
                        created_at:
                          type: string
                        updated_at:
                          type: string
                        archived_at:
                          type: string
                          nullable: true
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  status:
                    type: string
                example:
                  data:
                  - id: 1
                    name: Electronics
                    parent_id: null
                    parent_name: null
                    is_leaf: false
                    level: 0
                    created_at: '2024-01-15T10:00:00.000000Z'
                    updated_at: '2024-01-20T08:30:00.000000Z'
                    archived_at: null
                  - id: 2
                    name: Smartphones
                    parent_id: 1
                    parent_name: Electronics
                    is_leaf: true
                    level: 1
                    created_at: '2024-01-16T09:00:00.000000Z'
                    updated_at: '2024-01-21T12:00:00.000000Z'
                    archived_at: null
                  current_page: 1
                  last_page: 3
                  per_page: 15
                  total: 42
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-categories
    delete:
      tags:
      - Organization
      summary: Bulk Delete Categories
      description: 'Bulk delete multiple product categories by their IDs. Only leaf
        categories can be deleted.


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Request body:

        - `ids` (required) — array of category IDs to delete


        **Requires permission:** `categories.delete`'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  status:
                    type: string
                example:
                  message: 2 categories deleted successfully
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: products:write
      operationId: delete-api-categories
  /api/categories/tree:
    get:
      tags:
      - Organization
      summary: Get Category Tree
      description: 'Returns all categories as a nested tree structure for hierarchical
        display.


        :::info[Required scope: `products:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Each node includes: id, name, parent_id, is_leaf, subcategories_count, children[]'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        parent_id:
                          type: string
                          nullable: true
                        is_leaf:
                          type: boolean
                        subcategories_count:
                          type: integer
                        children:
                          type: array
                          items:
                            type: object
                            properties:
                              id:
                                type: integer
                              name:
                                type: string
                              parent_id:
                                type: integer
                              is_leaf:
                                type: boolean
                              subcategories_count:
                                type: integer
                              children:
                                type: array
                  status:
                    type: string
                example:
                  data:
                  - id: 1
                    name: Electronics
                    parent_id: null
                    is_leaf: false
                    subcategories_count: 2
                    children:
                    - id: 2
                      name: Smartphones
                      parent_id: 1
                      is_leaf: true
                      subcategories_count: 0
                      children: []
                    - id: 3
                      name: Laptops
                      parent_id: 1
                      is_leaf: true
                      subcategories_count: 0
                      children: []
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: products:read
      operationId: get-api-categories-tree
  /api/categories/for-manage:
    get:
      tags:
      - Organization
      summary: List Categories (Management View)
      description: 'Returns categories at a specific level for the product category
        assignment/manage UI. Includes counts for products, attributes, and attribute
        groups.


        :::info[Required scope: `products:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Query parameters:

        - `parent_id` (optional) — limit to children of this parent; omit for root-level
        categories'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        parent_id:
                          type: string
                          nullable: true
                        children_count:
                          type: integer
                        is_leaf:
                          type: boolean
                        level:
                          type: integer
                        created_at:
                          type: string
                        updated_at:
                          type: string
                        archived_at:
                          type: string
                          nullable: true
                  status:
                    type: string
                example:
                  data:
                  - id: 1
                    name: Electronics
                    parent_id: null
                    children_count: 3
                    is_leaf: false
                    level: 0
                    created_at: '2024-01-15T10:00:00.000000Z'
                    updated_at: '2024-01-20T08:30:00.000000Z'
                    archived_at: null
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: products:read
      operationId: get-api-categories-for-manage
  /api/categories/assign-category-to-product:
    post:
      tags:
      - Organization
      summary: Assign Category to Product
      description: 'Assign a category to a product and optionally set it as the primary
        category. Uses updateOrCreate so re-posting changes is_primary.


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Request body fields:

        - `category_id` (required) — must be a leaf category

        - `product_id` (required) — must exist in products table

        - `is_primary` (optional, boolean) — if true, unsets primary from all other
        categories for this product


        Returns 201 on creation, 200 on update.


        **Requires permission:** `categories.update`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                category_id:
                  type: integer
                product_id:
                  type: integer
                is_primary:
                  type: boolean
              example:
                category_id: 2
                product_id: 100
                is_primary: true
      parameters: []
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  status:
                    type: string
                example:
                  message: category was assigned to product, and set as primary category
                  status: success
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      category_id:
                        type: array
                        items:
                          type: string
                example:
                  message: The given data was invalid.
                  errors:
                    category_id:
                    - The selected category is not a leaf category.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: products:write
      operationId: post-api-categories-assign-category-to-product
  /api/categories/reassign-to-products:
    put:
      tags:
      - Organization
      summary: Reassign Category to Products
      description: 'Bulk reassign all products from one leaf category to another.
        Products already in the new category are detached from the old one.


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Request body fields:

        - `old_category_id` (required) — must be an existing leaf category

        - `new_category_id` (required) — must be an existing leaf category; different
        from old_category_id


        **Requires permission:** `categories.update`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                old_category_id:
                  type: integer
                new_category_id:
                  type: integer
              example:
                old_category_id: 3
                new_category_id: 4
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      affected_records_count:
                        type: integer
                  message:
                    type: string
                  status:
                    type: string
                example:
                  data:
                    affected_records_count: 47
                  message: Products have been reassigned to the new category.
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: products:write
      operationId: put-api-categories-reassign-to-products
  /api/categories/{productCategoryId}/archive:
    put:
      tags:
      - Organization
      summary: Archive Category
      description: 'Archive a single product category.


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `categories.archive`'
      requestBody:
        content: {}
      parameters:
      - name: productCategoryId
        in: path
        schema:
          type: integer
        required: true
        description: Category ID
        example: '5'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      archived_at:
                        type: string
                  message:
                    type: string
                  status:
                    type: string
                example:
                  data:
                    id: 5
                    name: Laptops
                    archived_at: '2024-03-10T11:00:00.000000Z'
                  message: category Laptops was archived successfully
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: products:write
      operationId: put-api-categories-productcategoryid-archive
  /api/categories/{productCategoryId}/unarchived:
    put:
      tags:
      - Organization
      summary: Unarchive Category
      description: 'Unarchive a single product category.


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `categories.archive`'
      requestBody:
        content: {}
      parameters:
      - name: productCategoryId
        in: path
        schema:
          type: integer
        required: true
        description: Category ID
        example: '5'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                  message:
                    type: string
                  status:
                    type: string
                example:
                  data:
                    id: 5
                    name: Laptops
                    archived_at: null
                  message: category Laptops was unarchived successfully
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: products:write
      operationId: put-api-categories-productcategoryid-unarchived
  /api/categories/archive:
    put:
      tags:
      - Organization
      summary: Bulk Archive Categories
      description: 'Bulk archive multiple product categories by their IDs.


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Request body:

        - `ids` (required) — array of category IDs to archive


        **Requires permission:** `categories.archive`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 5
                - 6
                - 7
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  status:
                    type: string
                example:
                  message: 3 categories archived successfully
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: products:write
      operationId: put-api-categories-archive
  /api/categories/unarchive:
    put:
      tags:
      - Organization
      summary: Bulk Unarchive Categories
      description: 'Bulk unarchive multiple product categories by their IDs.


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Request body:

        - `ids` (required) — array of category IDs to unarchive


        **Requires permission:** `categories.archive`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 5
                - 6
                - 7
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  status:
                    type: string
                example:
                  message: 3 categories unarchived successfully
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: products:write
      operationId: put-api-categories-unarchive
  /api/categories/deletable:
    post:
      tags:
      - Organization
      summary: Check Categories Deletable
      description: 'Check which categories can be deleted. Categories with children
        (is_leaf = false) cannot be deleted.


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Request body:

        - `ids` (required) — array of category IDs to check


        **Requires permission:** `categories.delete`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1
                - 2
                - 5
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        deletable:
                          type: boolean
                        reason:
                          type: object
                          properties:
                            productCategory:
                              type: string
                  status:
                    type: string
                example:
                  data:
                  - id: 1
                    name: Electronics
                    deletable: false
                    reason:
                      productCategory: Category cannot be deleted as it has sub-categories.
                  - id: 2
                    name: Smartphones
                    deletable: true
                    reason: null
                  - id: 5
                    name: Laptops
                    deletable: true
                    reason: null
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: products:write
      operationId: post-api-categories-deletable
  /api/categories/import/preview:
    post:
      tags:
      - Organization
      summary: Preview Categories Import
      description: 'Preview a category import file before committing. Returns parsed
        rows and any validation errors.


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Content-Type: multipart/form-data

        - `file` (required) — CSV or Excel file


        **Requires permission:** `categories.import`'
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                file:
                  type: string
                  description: CSV or Excel file with category data
                  format: binary
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      rows:
                        type: array
                        items:
                          type: object
                          properties:
                            name:
                              type: string
                            parent_id:
                              type: integer
                            valid:
                              type: boolean
                            errors:
                              type: array
                      total:
                        type: integer
                      valid:
                        type: integer
                      invalid:
                        type: integer
                  status:
                    type: string
                example:
                  data:
                    rows:
                    - name: Tablets
                      parent_id: 1
                      valid: true
                      errors: []
                    total: 1
                    valid: 1
                    invalid: 0
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: products:write
      operationId: post-api-categories-import-preview
  /api/categories/import:
    post:
      tags:
      - Organization
      summary: Import Categories
      description: 'Import categories from a CSV or Excel file.


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Content-Type: multipart/form-data

        - `file` (required) — CSV or Excel file


        **Requires permission:** `categories.import`'
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                file:
                  type: string
                  description: CSV or Excel file with category data
                  format: binary
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      imported:
                        type: integer
                      skipped:
                        type: integer
                      errors:
                        type: array
                  message:
                    type: string
                  status:
                    type: string
                example:
                  data:
                    imported: 5
                    skipped: 0
                    errors: []
                  message: Import completed successfully
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: products:write
      operationId: post-api-categories-import
  /api/attributes/{id}:
    get:
      tags:
      - Organization
      summary: Get Attribute
      description: 'Returns a single attribute with its group and option values.


        :::info[Required scope: `products:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      type:
                        type: string
                      attribute_group_id:
                        type: integer
                      attribute_group:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      display_options:
                        type: object
                        properties:
                          placeholder:
                            type: string
                      validation:
                        type: string
                        nullable: true
                      available_for_templates:
                        type: boolean
                      option_values:
                        type: array
                        items:
                          type: object
                          properties:
                            value:
                              type: string
                            sort_order:
                              type: integer
                      notes:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                example:
                  status: success
                  data:
                    id: 1
                    name: Color
                    type: string
                    attribute_group_id: 1
                    attribute_group:
                      id: 1
                      name: Physical Attributes
                    display_options:
                      placeholder: Enter color
                    validation: null
                    available_for_templates: true
                    option_values:
                    - value: Red
                      sort_order: 1
                    - value: Blue
                      sort_order: 2
                    notes: Primary product color
                    created_at: '2024-01-15T10:00:00.000000Z'
                    updated_at: '2024-06-01T14:30:00.000000Z'
                    archived_at: null
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                example:
                  status: error
                  message: Not Found
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: products:read
      operationId: get-api-attributes-id
    put:
      tags:
      - Organization
      summary: Update Attribute
      description: 'Updates an existing attribute. All fields are optional (PATCH
        semantics). Providing option_values syncs them — values not included will
        be deleted.


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Each entry in `option_values` may carry an optional variant SWATCH — `swatch_hex`
        (a hex colour, max 20) and/or `swatch_image_url` (an image URL, max 500).
        When the attribute is used as a variant axis (e.g. Color), channels that support
        swatches (Walmart) render this chip for every variant that selects the value.
        Send null to clear a swatch.


        Returns **422** with code `IsLinked` if the update would remove an option
        value that is still assigned to a product — the response lists the in-use
        values under `errors[].data.in_use`. Add those values back, or reassign/clear
        them on the affected products, before removing the option.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                type:
                  type: string
                option_values:
                  type: array
                  items:
                    type: object
                    properties:
                      value:
                        type: string
                      sort_order:
                        type: integer
                      swatch_hex:
                        type: string
                      swatch_image_url:
                        type: string
                        nullable: true
                available_for_templates:
                  type: boolean
                notes:
                  type: string
              example:
                name: Product Color
                type: string
                option_values:
                - value: Red
                  sort_order: 1
                  swatch_hex: '#FF0000'
                  swatch_image_url: null
                - value: Blue
                  sort_order: 2
                  swatch_hex: '#0000FF'
                  swatch_image_url: null
                - value: Green
                  sort_order: 3
                  swatch_hex: '#00A651'
                  swatch_image_url: https://cdn.example.com/swatches/green.jpg
                available_for_templates: true
                notes: Updated color attribute
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      type:
                        type: string
                      attribute_group_id:
                        type: integer
                      display_options:
                        type: string
                        nullable: true
                      option_values:
                        type: array
                        items:
                          type: object
                          properties:
                            value:
                              type: string
                            sort_order:
                              type: integer
                      notes:
                        type: string
                      updated_at:
                        type: string
                example:
                  status: success
                  message: attribute 'Product Color' updated successfully
                  data:
                    id: 1
                    name: Product Color
                    type: string
                    attribute_group_id: 1
                    display_options: null
                    option_values:
                    - value: Red
                      sort_order: 1
                    - value: Blue
                      sort_order: 2
                    - value: Green
                      sort_order: 3
                    notes: Updated color attribute
                    updated_at: '2024-06-15T14:00:00.000000Z'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: array
                    items:
                      type: object
                      properties:
                        message:
                          type: string
                        code:
                          type: string
                        key:
                          type: string
                        data:
                          type: object
                          properties:
                            in_use:
                              type: array
                              items:
                                type: string
                example:
                  message: 'These option values are still assigned to products and
                    cannot be removed: Red'
                  errors:
                  - message: 'These option values are still assigned to products and
                      cannot be removed: Red'
                    code: IsLinked
                    key: option_values
                    data:
                      in_use:
                      - Red
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: products:write
      operationId: put-api-attributes-id
    delete:
      tags:
      - Organization
      summary: Delete Attribute
      description: 'Deletes an attribute along with its values and product attribute
        assignments. Returns an error if the attribute is used by products unless
        ignore_relations=1.


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Query params:

        - ignore_relations (optional): 0 (default) = block if used, 1 = force delete'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      - name: ignore_relations
        in: query
        schema:
          type: integer
        description: Set to 1 to force delete even if used by products
        example: '0'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                example:
                  status: success
                  message: attribute 'Color' deleted successfully
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                example:
                  status: error
                  message: Unable to delete attribute 'Color' - it has related relations
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: products:write
      operationId: delete-api-attributes-id
  /api/attributes/grouped:
    get:
      tags:
      - Organization
      summary: Get Attributes Grouped
      description: 'Returns all attributes organized by their attribute group, plus
        a list of ungrouped attributes.


        :::info[Required scope: `products:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  grouped:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        sort_order:
                          type: integer
                        attributes:
                          type: array
                          items:
                            type: object
                            properties:
                              id:
                                type: integer
                              name:
                                type: string
                              type:
                                type: string
                              sort_order:
                                type: integer
                              attribute_id:
                                type: integer
                              display_options:
                                type: string
                                nullable: true
                              validation:
                                type: string
                                nullable: true
                  ungrouped:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                example:
                  status: success
                  grouped:
                  - id: 1
                    name: Physical Attributes
                    sort_order: 1
                    attributes:
                    - id: 1
                      name: Color
                      type: string
                      sort_order: 1
                      attribute_id: 1
                      display_options: null
                      validation: null
                  ungrouped:
                  - id: 10
                    name: Internal Notes
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: products:read
      operationId: get-api-attributes-grouped
  /api/attributes:
    post:
      tags:
      - Organization
      summary: Create Attribute
      description: "Creates a new attribute.\n\n:::info[Required scope: `products:write`]\n\
        Grant this scope to your token under [Settings → Developer → Personal Access\
        \ Tokens](https://app.sku.io/settings/api).\n:::\n\nAuthentication: Requires\
        \ Bearer token.\n\nFields:\n- name (required): Unique name, max 255 chars\n\
        - type (required): One of: string, longtext, date, datetime, numeric, integer,\
        \ checkbox\n- display_options (optional): JSON object with display configuration\n\
        - option_values (optional): Array of selectable options for dropdown-type\
        \ attributes\n  - option_values.*.value (optional): Option value string, max\
        \ 255 chars\n  - option_values.*.sort_order (optional): Sort order integer\n\
        - validation (optional): JSON validation rules\n- available_for_templates\
        \ (optional): Boolean — makes attribute available in email templates\n- attribute_group_id\
        \ (optional): ID of the group to assign this attribute to\n- notes (optional):\
        \ Internal notes, max 255 chars\n\n**Requires permission:** `attributes.create`\n\
        \nEach entry in `option_values` may carry an optional variant SWATCH — `swatch_hex`\
        \ (a hex colour, max 20) and/or `swatch_image_url` (an image URL, max 500).\
        \ When the attribute is used as a variant axis (e.g. Color), channels that\
        \ support swatches (Walmart) render this chip for every variant that selects\
        \ the value. Send null to clear a swatch."
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                type:
                  type: string
                display_options:
                  type: object
                  properties:
                    has_options:
                      type: boolean
                    type:
                      type: string
                    placeholder:
                      type: string
                option_values:
                  type: array
                  items:
                    type: object
                    properties:
                      value:
                        type: string
                      sort_order:
                        type: integer
                      swatch_hex:
                        type: string
                      swatch_image_url:
                        type: string
                validation:
                  type: string
                  nullable: true
                available_for_templates:
                  type: boolean
                attribute_group_id:
                  type: integer
                notes:
                  type: string
              example:
                name: Color
                type: string
                display_options:
                  has_options: true
                  type: Multi
                  placeholder: Enter color
                option_values:
                - value: Red
                  sort_order: 1
                  swatch_hex: '#FF0000'
                  swatch_image_url: https://cdn.example.com/swatches/red.jpg
                - value: Blue
                  sort_order: 2
                  swatch_hex: '#0000FF'
                  swatch_image_url: null
                validation: null
                available_for_templates: true
                attribute_group_id: 1
                notes: Primary product color
      parameters: []
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      type:
                        type: string
                      attribute_group_id:
                        type: integer
                      display_options:
                        type: object
                        properties:
                          placeholder:
                            type: string
                      validation:
                        type: string
                        nullable: true
                      available_for_templates:
                        type: boolean
                      option_values:
                        type: array
                        items:
                          type: object
                          properties:
                            value:
                              type: string
                            sort_order:
                              type: integer
                      notes:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                example:
                  status: success
                  message: attribute created successfully
                  data:
                    id: 15
                    name: Color
                    type: string
                    attribute_group_id: 1
                    display_options:
                      placeholder: Enter color
                    validation: null
                    available_for_templates: true
                    option_values:
                    - value: Red
                      sort_order: 1
                    - value: Blue
                      sort_order: 2
                    notes: Primary product color
                    created_at: '2024-06-15T12:00:00.000000Z'
                    updated_at: '2024-06-15T12:00:00.000000Z'
                    archived_at: null
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      name:
                        type: array
                        items:
                          type: string
                      type:
                        type: array
                        items:
                          type: string
                example:
                  message: The name has already been taken.
                  errors:
                    name:
                    - The name has already been taken.
                    type:
                    - The selected type is invalid.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: products:write
      operationId: post-api-attributes
    delete:
      tags:
      - Organization
      summary: Bulk Delete Attributes
      description: 'Bulk deletes multiple attributes by ID array or current list view
        filters.


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `attributes.delete`'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                example:
                  status: success
                  message: Attributes deleted successfully
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: products:write
      operationId: delete-api-attributes
    get:
      tags:
      - Organization
      summary: List Attributes
      description: 'Returns a paginated list of attributes.


        Authentication: Requires Bearer token.


        Sort fields: name, type, created_at, updated_at, archived_at'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        description: Page number
        example: '1'
      - name: limit
        in: query
        schema:
          type: integer
        description: Records per page
        example: '15'
      - name: sort
        in: query
        schema:
          type: string
        description: Sort field (prefix with - for descending)
        example: name
      - name: search
        in: query
        schema:
          type: string
        description: Search by attribute name
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        type:
                          type: string
                        attribute_group_id:
                          type: integer
                        notes:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                        updated_at:
                          type: string
                        archived_at:
                          type: string
                          nullable: true
                        display_options:
                          type: string
                          nullable: true
                        validation:
                          type: string
                          nullable: true
                        available_for_templates:
                          type: boolean
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  status: success
                  data:
                  - id: 1
                    name: Color
                    type: string
                    attribute_group_id: 1
                    notes: null
                    created_at: '2024-01-15T10:00:00.000000Z'
                    updated_at: '2024-06-01T14:30:00.000000Z'
                    archived_at: null
                    display_options: null
                    validation: null
                    available_for_templates: false
                  current_page: 1
                  last_page: 3
                  per_page: 15
                  total: 38
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-attributes
  /api/attributes/{id}/archive:
    put:
      tags:
      - Organization
      summary: Archive Attribute
      description: 'Archives a single attribute. Idempotent — returns a warning if
        already archived.


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      archived_at:
                        type: string
                example:
                  status: success
                  message: attribute 'Color' archived successfully
                  data:
                    id: 1
                    name: Color
                    archived_at: '2024-06-15T10:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: products:write
      operationId: put-api-attributes-id-archive
  /api/attributes/{id}/unarchived:
    put:
      tags:
      - Organization
      summary: Unarchive Attribute
      description: 'Unarchives a single attribute.


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                example:
                  status: success
                  message: attribute 'Color' unarchived successfully
                  data:
                    id: 1
                    name: Color
                    archived_at: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: products:write
      operationId: put-api-attributes-id-unarchived
  /api/attributes/archive:
    put:
      tags:
      - Organization
      summary: Bulk Archive Attributes
      description: 'Bulk archives multiple attributes by ID array or current list
        view filters.


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `attributes.archive`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1
                - 2
                - 3
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                example:
                  status: success
                  message: Attributes archived successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: products:write
      operationId: put-api-attributes-archive
  /api/attributes/unarchive:
    put:
      tags:
      - Organization
      summary: Bulk Unarchive Attributes
      description: 'Bulk unarchives multiple attributes by ID array or current list
        view filters.


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `attributes.archive`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1
                - 2
                - 3
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                example:
                  status: success
                  message: Attributes unarchived successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: products:write
      operationId: put-api-attributes-unarchive
  /api/attributes/deletable:
    post:
      tags:
      - Organization
      summary: Check Attributes Deletable
      description: 'Checks whether each provided attribute ID can be safely deleted.


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Fields:

        - ids (required): Array of attribute IDs to check (integers that exist in
        attributes table)


        **Requires permission:** `attributes.delete`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1
                - 2
                - 3
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        deletable:
                          type: boolean
                        reason:
                          type: string
                example:
                  status: success
                  data:
                  - id: 1
                    name: Color
                    deletable: false
                    reason: Used by 5 products
                  - id: 2
                    name: Size
                    deletable: true
                    reason: null
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: products:write
      operationId: post-api-attributes-deletable
  /api/attributes/import:
    post:
      tags:
      - Organization
      summary: Import Attributes
      description: 'Imports attributes from a CSV or Excel file.


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Content-Type: multipart/form-data


        **Requires permission:** `attributes.import`'
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                file:
                  type: string
                  description: CSV or Excel file containing attribute data
                  format: binary
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      imported:
                        type: integer
                      errors:
                        type: array
                example:
                  status: success
                  message: Import completed
                  data:
                    imported: 10
                    errors: []
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: products:write
      operationId: post-api-attributes-import
  /api/attributes/import/preview:
    post:
      tags:
      - Organization
      summary: Preview Attributes Import
      description: 'Previews attribute import data from a file without actually importing.


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Content-Type: multipart/form-data


        **Requires permission:** `attributes.import`'
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                file:
                  type: string
                  description: CSV or Excel file to preview
                  format: binary
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  data:
                    type: object
                    properties:
                      rows:
                        type: array
                        items:
                          type: object
                          properties:
                            name:
                              type: string
                            type:
                              type: string
                            valid:
                              type: boolean
                            errors:
                              type: array
                      total:
                        type: integer
                      valid:
                        type: integer
                      invalid:
                        type: integer
                example:
                  status: success
                  data:
                    rows:
                    - name: Material
                      type: string
                      valid: true
                      errors: []
                    total: 1
                    valid: 1
                    invalid: 0
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: products:write
      operationId: post-api-attributes-import-preview
  /api/attribute-groups/for-manage:
    get:
      tags:
      - Organization
      summary: List Attribute Groups (Management View)
      description: 'Returns all attribute groups ordered by sort_order, including
        nested attributes, product counts, and category counts. Used for the attribute
        group management page.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        sort_order:
                          type: integer
                        num_attributes:
                          type: integer
                        num_categories:
                          type: integer
                        num_products:
                          type: integer
                        attributes:
                          type: array
                          items:
                            type: object
                            properties:
                              id:
                                type: integer
                              name:
                                type: string
                              type:
                                type: string
                              sort_order:
                                type: integer
                              attribute_id:
                                type: integer
                              display_options:
                                type: string
                                nullable: true
                              validation:
                                type: string
                                nullable: true
                example:
                  status: success
                  data:
                  - id: 1
                    name: Physical Attributes
                    sort_order: 1
                    num_attributes: 2
                    num_categories: 1
                    num_products: 15
                    attributes:
                    - id: 1
                      name: Color
                      type: string
                      sort_order: 1
                      attribute_id: 1
                      display_options: null
                      validation: null
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: get-api-attribute-groups-for-manage
  /api/attribute-groups/{id}:
    get:
      tags:
      - Organization
      summary: Get Attribute Group
      description: 'Returns a single attribute group with full details including products,
        categories, and attributes.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      sort_order:
                        type: integer
                      products_count_directly:
                        type: integer
                      products_ids_directly:
                        type: array
                        items:
                          type: integer
                      products_count_through_categories:
                        type: integer
                      products_ids_through_categories:
                        type: array
                        items:
                          type: integer
                      attributes_count:
                        type: integer
                      attributes:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            type:
                              type: string
                            sort_order:
                              type: integer
                            attribute_id:
                              type: integer
                            display_options:
                              type: string
                              nullable: true
                            validation:
                              type: string
                              nullable: true
                      categories_count:
                        type: integer
                      categories:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                example:
                  status: success
                  data:
                    id: 1
                    name: Physical Attributes
                    sort_order: 1
                    products_count_directly: 10
                    products_ids_directly:
                    - 101
                    - 102
                    - 103
                    products_count_through_categories: 25
                    products_ids_through_categories:
                    - 104
                    - 105
                    - 106
                    attributes_count: 2
                    attributes:
                    - id: 1
                      name: Color
                      type: string
                      sort_order: 1
                      attribute_id: 1
                      display_options: null
                      validation: null
                    categories_count: 1
                    categories:
                    - id: 5
                      name: Apparel
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                example:
                  status: error
                  message: Not Found
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: get-api-attribute-groups-id
    put:
      tags:
      - Organization
      summary: Update Attribute Group
      description: 'Updates an existing attribute group. All fields are optional (PATCH
        semantics on PUT). Providing the attributes array syncs assigned attributes
        — attributes not included will be removed from the group.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                sort_order:
                  type: integer
                attributes:
                  type: array
                  items:
                    type: object
                    properties:
                      id:
                        type: integer
                      sort_order:
                        type: integer
              example:
                name: Updated Physical Attributes
                sort_order: 2
                attributes:
                - id: 1
                  sort_order: 1
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      sort_order:
                        type: integer
                      attributes_count:
                        type: integer
                      attributes:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            type:
                              type: string
                            sort_order:
                              type: integer
                            attribute_id:
                              type: integer
                            display_options:
                              type: string
                              nullable: true
                            validation:
                              type: string
                              nullable: true
                example:
                  status: success
                  message: Attribute group 'Updated Physical Attributes' updated successfully
                  data:
                    id: 1
                    name: Updated Physical Attributes
                    sort_order: 2
                    attributes_count: 1
                    attributes:
                    - id: 1
                      name: Color
                      type: string
                      sort_order: 1
                      attribute_id: 1
                      display_options: null
                      validation: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-session-only: true
      operationId: put-api-attribute-groups-id
    delete:
      tags:
      - Organization
      summary: Delete Attribute Group
      description: 'Deletes a single attribute group. Returns an error if the group
        is linked to categories or products.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                example:
                  status: success
                  message: Attribute group 'Physical Attributes' deleted successfully
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                  errors:
                    type: array
                    items:
                      type: object
                      properties:
                        message:
                          type: string
                        code:
                          type: string
                example:
                  status: error
                  message: Unable to delete attribute group 'Physical Attributes'
                  errors:
                  - message: This attribute group is linked to categories
                    code: CategoryResourceLinked
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-session-only: true
      operationId: delete-api-attribute-groups-id
  /api/attribute-groups:
    post:
      tags:
      - Organization
      summary: Create Attribute Group
      description: "Creates a new attribute group. Optionally assigns existing attributes\
        \ to the group.\n\n:::warning[Not yet available to API tokens]\nThis endpoint\
        \ currently requires session authentication; Personal Access Token scope support\
        \ is in progress.\n:::\n\nAuthentication: Requires Bearer token.\n\nFields:\n\
        - name (required): Unique name for the group, max 255 chars\n- sort_order\
        \ (optional): Integer sort position\n- attributes (optional): Array of attribute\
        \ objects to assign\n  - attributes.*.id (required): ID of an existing attribute\n\
        \  - attributes.*.sort_order (optional): Sort order within the group\n\nNote:\
        \ An attribute can only belong to one group — assigning it to a new group\
        \ removes it from the previous one.\n\n**Requires permission:** `attribute_groups.create`"
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                sort_order:
                  type: integer
                attributes:
                  type: array
                  items:
                    type: object
                    properties:
                      id:
                        type: integer
                      sort_order:
                        type: integer
              example:
                name: Physical Attributes
                sort_order: 1
                attributes:
                - id: 1
                  sort_order: 1
                - id: 2
                  sort_order: 2
      parameters: []
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      sort_order:
                        type: integer
                      attributes_count:
                        type: integer
                      attributes:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            type:
                              type: string
                            sort_order:
                              type: integer
                            attribute_id:
                              type: integer
                            display_options:
                              type: string
                              nullable: true
                            validation:
                              type: string
                              nullable: true
                example:
                  status: success
                  message: Attribute group created successfully
                  data:
                    id: 5
                    name: Physical Attributes
                    sort_order: 1
                    attributes_count: 2
                    attributes:
                    - id: 1
                      name: Color
                      type: string
                      sort_order: 1
                      attribute_id: 1
                      display_options: null
                      validation: null
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      name:
                        type: array
                        items:
                          type: string
                example:
                  message: The name has already been taken.
                  errors:
                    name:
                    - The name has already been taken.
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: post-api-attribute-groups
    delete:
      tags:
      - Organization
      summary: Bulk Delete Attribute Groups
      description: 'Bulk deletes multiple attribute groups by ID array or by current
        list view filters.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `attribute_groups.delete`'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                example:
                  status: success
                  message: Attribute groups deleted successfully
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: delete-api-attribute-groups
    get:
      tags:
      - Organization
      summary: List Attribute Groups
      description: 'Returns a paginated list of attribute groups. Supports search,
        sort, and archive filtering.


        Authentication: Requires Bearer token.


        Sort fields: name, sort_order, created_at, updated_at, archived_at'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        description: Page number
        example: '1'
      - name: limit
        in: query
        schema:
          type: integer
        description: Records per page
        example: '15'
      - name: sort
        in: query
        schema:
          type: string
        description: Sort field (prefix with - for descending, e.g. -name)
        example: name
      - name: search
        in: query
        schema:
          type: string
        description: Search by attribute group name
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        sort_order:
                          type: integer
                        num_attributes:
                          type: integer
                        num_categories:
                          type: integer
                        num_products:
                          type: integer
                        created_at:
                          type: string
                        updated_at:
                          type: string
                        archived_at:
                          type: string
                          nullable: true
                        attributes:
                          type: array
                          items:
                            type: object
                            properties:
                              id:
                                type: integer
                              name:
                                type: string
                              type:
                                type: string
                              sort_order:
                                type: integer
                              attribute_id:
                                type: integer
                              display_options:
                                type: string
                                nullable: true
                              validation:
                                type: string
                                nullable: true
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  status: success
                  data:
                  - id: 1
                    name: Physical Attributes
                    sort_order: 1
                    num_attributes: 5
                    num_categories: 3
                    num_products: 42
                    created_at: '2024-01-15T10:00:00.000000Z'
                    updated_at: '2024-06-01T14:30:00.000000Z'
                    archived_at: null
                    attributes:
                    - id: 1
                      name: Color
                      type: string
                      sort_order: 1
                      attribute_id: 1
                      display_options: null
                      validation: null
                    - id: 2
                      name: Weight
                      type: numeric
                      sort_order: 2
                      attribute_id: 2
                      display_options: null
                      validation: null
                  current_page: 1
                  last_page: 1
                  per_page: 15
                  total: 1
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-attribute-groups
  /api/attribute-groups/{id}/archive:
    put:
      tags:
      - Organization
      summary: Archive Attribute Group
      description: 'Archives a single attribute group by ID. Idempotent — returns
        a warning if already archived.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      archived_at:
                        type: string
                example:
                  status: success
                  message: Attribute group 'Physical Attributes' archived successfully
                  data:
                    id: 1
                    name: Physical Attributes
                    archived_at: '2024-06-15T10:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-session-only: true
      operationId: put-api-attribute-groups-id-archive
  /api/attribute-groups/{id}/unarchived:
    put:
      tags:
      - Organization
      summary: Unarchive Attribute Group
      description: 'Unarchives a single attribute group by ID.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                example:
                  status: success
                  message: Attribute group 'Physical Attributes' unarchived successfully
                  data:
                    id: 1
                    name: Physical Attributes
                    archived_at: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-session-only: true
      operationId: put-api-attribute-groups-id-unarchived
  /api/attribute-groups/archive:
    put:
      tags:
      - Organization
      summary: Bulk Archive Attribute Groups
      description: 'Bulk archives multiple attribute groups by ID array or by current
        list view filters.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `attribute_groups.archive`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1
                - 2
                - 3
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                example:
                  status: success
                  message: Attribute groups archived successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-session-only: true
      operationId: put-api-attribute-groups-archive
  /api/attribute-groups/unarchive:
    put:
      tags:
      - Organization
      summary: Bulk Unarchive Attribute Groups
      description: 'Bulk unarchives multiple attribute groups by ID array or by current
        list view filters.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `attribute_groups.archive`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1
                - 2
                - 3
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                example:
                  status: success
                  message: Attribute groups unarchived successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-session-only: true
      operationId: put-api-attribute-groups-unarchive
  /api/attribute-groups/deletable:
    post:
      tags:
      - Organization
      summary: Check Attribute Groups Deletable
      description: 'Checks whether each provided attribute group ID can be safely
        deleted (not linked to categories or products).


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.


        Fields:

        - ids (required): Array of attribute group IDs to check


        **Requires permission:** `attribute_groups.delete`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1
                - 2
                - 3
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        deletable:
                          type: boolean
                        reason:
                          type: string
                          nullable: true
                example:
                  status: success
                  data:
                  - id: 1
                    name: Physical Attributes
                    deletable: true
                    reason: null
                  - id: 2
                    name: Dimensions
                    deletable: false
                    reason: Linked to categories
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-session-only: true
      operationId: post-api-attribute-groups-deletable
  /api/attribute-groups/import:
    post:
      tags:
      - Organization
      summary: Import Attribute Groups
      description: 'Imports attribute groups from a CSV or Excel file.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.


        Content-Type: multipart/form-data


        **Requires permission:** `attribute_groups.import`'
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                file:
                  type: string
                  description: CSV or Excel file containing attribute group data
                  format: binary
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      imported:
                        type: integer
                      errors:
                        type: array
                example:
                  status: success
                  message: Import completed successfully
                  data:
                    imported: 5
                    errors: []
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-session-only: true
      operationId: post-api-attribute-groups-import
  /api/attribute-groups/import/preview:
    post:
      tags:
      - Organization
      summary: Preview Attribute Groups Import
      description: 'Previews attribute group import data from a file without actually
        importing. Returns rows with validation status.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.


        Content-Type: multipart/form-data


        **Requires permission:** `attribute_groups.import`'
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                file:
                  type: string
                  description: CSV or Excel file to preview
                  format: binary
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  data:
                    type: object
                    properties:
                      rows:
                        type: array
                        items:
                          type: object
                          properties:
                            name:
                              type: string
                            sort_order:
                              type: integer
                            valid:
                              type: boolean
                            errors:
                              type: array
                      total:
                        type: integer
                      valid:
                        type: integer
                      invalid:
                        type: integer
                example:
                  status: success
                  data:
                    rows:
                    - name: New Group
                      sort_order: 1
                      valid: true
                      errors: []
                    total: 1
                    valid: 1
                    invalid: 0
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-session-only: true
      operationId: post-api-attribute-groups-import-preview
  /api/product-pricing-tiers/{product_pricing_tier}:
    get:
      tags:
      - Pricing
      summary: Get Pricing Tier
      description: 'Show a single product pricing tier.


        :::info[Required scope: `products:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: product_pricing_tier
        in: path
        schema:
          type: integer
        required: true
        description: Pricing tier ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      pricing_type:
                        type: string
                      base_pricing_tier_id:
                        type: string
                        nullable: true
                      base_pricing_tier_name:
                        type: string
                        nullable: true
                      relative_basis:
                        type: string
                        nullable: true
                      base_supplier_pricing_tier_id:
                        type: string
                        nullable: true
                      base_supplier_pricing_tier_name:
                        type: string
                        nullable: true
                      base_attribute_id:
                        type: string
                        nullable: true
                      base_attribute_name:
                        type: string
                        nullable: true
                      attr_rate:
                        type: string
                        nullable: true
                      attr_offset:
                        type: string
                        nullable: true
                      adjustment_percentage:
                        type: string
                        nullable: true
                      adjustment_fixed_amount:
                        type: string
                        nullable: true
                      rounding_value:
                        type: string
                        nullable: true
                      currency_code:
                        type: string
                      is_default:
                        type: boolean
                      dependent_tier_count:
                        type: integer
                      chain_depth:
                        type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                  status:
                    type: string
                example:
                  data:
                    id: 1
                    name: Standard
                    pricing_type: absolute
                    base_pricing_tier_id: null
                    base_pricing_tier_name: null
                    relative_basis: null
                    base_supplier_pricing_tier_id: null
                    base_supplier_pricing_tier_name: null
                    base_attribute_id: null
                    base_attribute_name: null
                    attr_rate: null
                    attr_offset: null
                    adjustment_percentage: null
                    adjustment_fixed_amount: null
                    rounding_value: null
                    currency_code: USD
                    is_default: true
                    dependent_tier_count: 1
                    chain_depth: 0
                    created_at: '2024-01-01T00:00:00.000000Z'
                    updated_at: '2024-01-10T09:00:00.000000Z'
                    archived_at: null
                  status: success
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No query results for model [App\Models\ProductPricingTier]
                    999
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: products:read
      operationId: get-api-product-pricing-tiers-product-pricing-tier
    put:
      tags:
      - Pricing
      summary: Update Pricing Tier
      description: 'Update an existing product pricing tier. currency_code cannot
        be changed on update.


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Request body fields (all optional on update):

        - `name` (string, max:255, unique)

        - `pricing_type` — `absolute` or `relative`

        - `base_pricing_tier_id` (nullable integer) — required if pricing_type=relative

        - `adjustment_percentage` (nullable numeric, -99.9999 to 999.9999) — required
        if pricing_type=relative

        - `adjustment_fixed_amount` (nullable numeric)

        - `rounding_value` (nullable numeric, gt:0)


        **Relative tiers** (`pricing_type=relative`) require `relative_basis`, one
        of:

        - `pricing_tier` — derive from another tier''s price. Requires `base_pricing_tier_id`
        + `adjustment_percentage`.

        - `supplier_pricing_tier` — cost-plus from the product''s primary supplier
        cost. Optional `base_supplier_pricing_tier_id` (defaults to the default supplier
        tier) + `adjustment_percentage`.

        - `attribute` — derive from a numeric/integer product attribute: `value ×
        attr_rate + attr_offset`. Requires `base_attribute_id` + `attr_rate` (optional
        `attr_offset`).


        `rounding_value` and `adjustment_fixed_amount` apply to every basis. Supplier/pricing-tier
        bases inherit currency from their source; attribute basis uses `currency_code`.


        **Requires permission:** `pricing_tiers.update`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                pricing_type:
                  type: string
                relative_basis:
                  type: string
                base_pricing_tier_id:
                  type: integer
                adjustment_percentage:
                  type: integer
                rounding_value:
                  type: number
              example:
                name: Trade Wholesale
                pricing_type: relative
                relative_basis: pricing_tier
                base_pricing_tier_id: 1
                adjustment_percentage: -20
                rounding_value: 0.1
      parameters:
      - name: product_pricing_tier
        in: path
        schema:
          type: integer
        required: true
        description: Pricing tier ID
        example: '2'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      pricing_type:
                        type: string
                      base_pricing_tier_id:
                        type: integer
                      base_pricing_tier_name:
                        type: string
                      relative_basis:
                        type: string
                      base_supplier_pricing_tier_id:
                        type: string
                        nullable: true
                      base_supplier_pricing_tier_name:
                        type: string
                        nullable: true
                      base_attribute_id:
                        type: string
                        nullable: true
                      base_attribute_name:
                        type: string
                        nullable: true
                      attr_rate:
                        type: string
                        nullable: true
                      attr_offset:
                        type: string
                        nullable: true
                      adjustment_percentage:
                        type: string
                      adjustment_fixed_amount:
                        type: string
                        nullable: true
                      rounding_value:
                        type: string
                      currency_code:
                        type: string
                      is_default:
                        type: boolean
                      dependent_tier_count:
                        type: integer
                      chain_depth:
                        type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                  message:
                    type: string
                  status:
                    type: string
                example:
                  data:
                    id: 2
                    name: Trade Wholesale
                    pricing_type: relative
                    base_pricing_tier_id: 1
                    base_pricing_tier_name: Standard
                    relative_basis: pricing_tier
                    base_supplier_pricing_tier_id: null
                    base_supplier_pricing_tier_name: null
                    base_attribute_id: null
                    base_attribute_name: null
                    attr_rate: null
                    attr_offset: null
                    adjustment_percentage: '-20.0000'
                    adjustment_fixed_amount: null
                    rounding_value: '0.1000'
                    currency_code: USD
                    is_default: false
                    dependent_tier_count: 0
                    chain_depth: 1
                    created_at: '2024-03-01T10:00:00.000000Z'
                    updated_at: '2024-03-05T14:00:00.000000Z'
                    archived_at: null
                  message: product pricing tier Trade Wholesale was updated successfully
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: products:write
      operationId: put-api-product-pricing-tiers-product-pricing-tier
    delete:
      tags:
      - Pricing
      summary: Delete Pricing Tier
      description: 'Delete a product pricing tier. Fails if the tier is the default,
        is used by products, referenced in import mappings, or has active dependent
        tiers.


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `pricing_tiers.delete`'
      parameters:
      - name: product_pricing_tier
        in: path
        schema:
          type: integer
        required: true
        description: Pricing tier ID
        example: '2'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  status:
                    type: string
                example:
                  message: product pricing tier Trade Wholesale was deleted successfully
                  status: success
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: array
                    items:
                      type: object
                      properties:
                        code:
                          type: string
                        field:
                          type: string
                        meta:
                          type: object
                          properties:
                            product_pricing_tier_id:
                              type: integer
                  status:
                    type: string
                example:
                  message: Failed to delete product pricing tier Standard
                  errors:
                  - code: ProductRESOURCE_LINKED
                    field: products
                    meta:
                      product_pricing_tier_id: 1
                  status: error
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: products:write
      operationId: delete-api-product-pricing-tiers-product-pricing-tier
  /api/product-pricing-tiers:
    post:
      tags:
      - Pricing
      summary: Create Pricing Tier
      description: 'Create a new product pricing tier. Supports both absolute and
        relative pricing.


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Request body fields:

        - `name` (required, string, max:255) — unique name for the tier

        - `currency_code` (required) — must exist in currencies table (e.g. USD, EUR).
        Relative tiers inherit currency from their base tier.

        - `pricing_type` (required) — `absolute` or `relative`. Defaults to `absolute`
        if omitted.

        - `base_pricing_tier_id` (required if pricing_type=relative, nullable) — the
        base tier to derive pricing from; must not create a circular reference

        - `adjustment_percentage` (required if pricing_type=relative, nullable, numeric
        -99.9999 to 999.9999) — percentage adjustment relative to the base tier

        - `adjustment_fixed_amount` (optional, nullable, numeric) — fixed amount adjustment

        - `rounding_value` (optional, nullable, numeric, gt:0) — round the final price
        to the nearest multiple of this value


        Validation rules:

        - A tier cannot reference itself as a base tier

        - Circular references are prevented

        - The default tier cannot be set to relative pricing type


        **Relative tiers** (`pricing_type=relative`) require `relative_basis`, one
        of:

        - `pricing_tier` — derive from another tier''s price. Requires `base_pricing_tier_id`
        + `adjustment_percentage`.

        - `supplier_pricing_tier` — cost-plus from the product''s primary supplier
        cost. Optional `base_supplier_pricing_tier_id` (defaults to the default supplier
        tier) + `adjustment_percentage`.

        - `attribute` — derive from a numeric/integer product attribute: `value ×
        attr_rate + attr_offset`. Requires `base_attribute_id` + `attr_rate` (optional
        `attr_offset`).


        `rounding_value` and `adjustment_fixed_amount` apply to every basis. Supplier/pricing-tier
        bases inherit currency from their source; attribute basis uses `currency_code`.


        **Requires permission:** `pricing_tiers.create`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                currency_code:
                  type: string
                pricing_type:
                  type: string
                relative_basis:
                  type: string
                base_pricing_tier_id:
                  type: integer
                adjustment_percentage:
                  type: integer
                adjustment_fixed_amount:
                  type: string
                  nullable: true
                rounding_value:
                  type: number
              example:
                name: Wholesale
                currency_code: USD
                pricing_type: relative
                relative_basis: pricing_tier
                base_pricing_tier_id: 1
                adjustment_percentage: -15
                adjustment_fixed_amount: null
                rounding_value: 0.05
      parameters: []
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      pricing_type:
                        type: string
                      base_pricing_tier_id:
                        type: integer
                      base_pricing_tier_name:
                        type: string
                      relative_basis:
                        type: string
                      base_supplier_pricing_tier_id:
                        type: string
                        nullable: true
                      base_supplier_pricing_tier_name:
                        type: string
                        nullable: true
                      base_attribute_id:
                        type: string
                        nullable: true
                      base_attribute_name:
                        type: string
                        nullable: true
                      attr_rate:
                        type: string
                        nullable: true
                      attr_offset:
                        type: string
                        nullable: true
                      adjustment_percentage:
                        type: string
                      adjustment_fixed_amount:
                        type: string
                        nullable: true
                      rounding_value:
                        type: string
                      currency_code:
                        type: string
                      is_default:
                        type: boolean
                      dependent_tier_count:
                        type: integer
                      chain_depth:
                        type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                  message:
                    type: string
                  status:
                    type: string
                example:
                  data:
                    id: 2
                    name: Wholesale
                    pricing_type: relative
                    base_pricing_tier_id: 1
                    base_pricing_tier_name: Standard
                    relative_basis: pricing_tier
                    base_supplier_pricing_tier_id: null
                    base_supplier_pricing_tier_name: null
                    base_attribute_id: null
                    base_attribute_name: null
                    attr_rate: null
                    attr_offset: null
                    adjustment_percentage: '-15.0000'
                    adjustment_fixed_amount: null
                    rounding_value: '0.0500'
                    currency_code: USD
                    is_default: false
                    dependent_tier_count: 0
                    chain_depth: 1
                    created_at: '2024-03-01T10:00:00.000000Z'
                    updated_at: '2024-03-01T10:00:00.000000Z'
                    archived_at: null
                  message: product pricing tier was created successfully
                  status: success
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      name:
                        type: array
                        items:
                          type: string
                      base_pricing_tier_id:
                        type: array
                        items:
                          type: string
                example:
                  message: The given data was invalid.
                  errors:
                    name:
                    - The name has already been taken.
                    base_pricing_tier_id:
                    - A pricing tier cannot reference itself as a base tier.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: products:write
      operationId: post-api-product-pricing-tiers
    get:
      tags:
      - Pricing
      summary: List Pricing Tiers
      description: 'List product pricing tiers. Eager-loads the base pricing tier
        and counts dependent tiers.


        Authentication: Requires Bearer token.


        Query parameters:

        - `page` / `limit` — pagination

        - `search` — searches name and currency_code

        - `sort` — sortable columns: id, name, currency_code, is_default, pricing_type,
        created_at, updated_at, archived_at

        - `archived` — 0 (active only), 1 (archived only)

        - `filter[name]` / `filter[currency_code]` — column filters'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        description: 'Page number (default: 1)'
        example: '1'
      - name: limit
        in: query
        schema:
          type: integer
        description: 'Records per page (default: 15)'
        example: '15'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        pricing_type:
                          type: string
                        base_pricing_tier_id:
                          type: string
                          nullable: true
                        base_pricing_tier_name:
                          type: string
                          nullable: true
                        relative_basis:
                          type: string
                          nullable: true
                        base_supplier_pricing_tier_id:
                          type: string
                          nullable: true
                        base_supplier_pricing_tier_name:
                          type: string
                          nullable: true
                        base_attribute_id:
                          type: string
                          nullable: true
                        base_attribute_name:
                          type: string
                          nullable: true
                        attr_rate:
                          type: string
                          nullable: true
                        attr_offset:
                          type: string
                          nullable: true
                        adjustment_percentage:
                          type: string
                          nullable: true
                        adjustment_fixed_amount:
                          type: string
                          nullable: true
                        rounding_value:
                          type: string
                          nullable: true
                        currency_code:
                          type: string
                        is_default:
                          type: boolean
                        dependent_tier_count:
                          type: integer
                        chain_depth:
                          type: integer
                        created_at:
                          type: string
                        updated_at:
                          type: string
                        archived_at:
                          type: string
                          nullable: true
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  status:
                    type: string
                example:
                  data:
                  - id: 1
                    name: Standard
                    pricing_type: absolute
                    base_pricing_tier_id: null
                    base_pricing_tier_name: null
                    relative_basis: null
                    base_supplier_pricing_tier_id: null
                    base_supplier_pricing_tier_name: null
                    base_attribute_id: null
                    base_attribute_name: null
                    attr_rate: null
                    attr_offset: null
                    adjustment_percentage: null
                    adjustment_fixed_amount: null
                    rounding_value: null
                    currency_code: USD
                    is_default: true
                    dependent_tier_count: 1
                    chain_depth: 0
                    created_at: '2024-01-01T00:00:00.000000Z'
                    updated_at: '2024-01-10T09:00:00.000000Z'
                    archived_at: null
                  - id: 2
                    name: Wholesale
                    pricing_type: relative
                    base_pricing_tier_id: 1
                    base_pricing_tier_name: Standard
                    relative_basis: pricing_tier
                    base_supplier_pricing_tier_id: null
                    base_supplier_pricing_tier_name: null
                    base_attribute_id: null
                    base_attribute_name: null
                    attr_rate: null
                    attr_offset: null
                    adjustment_percentage: '-15.0000'
                    adjustment_fixed_amount: null
                    rounding_value: '0.0500'
                    currency_code: USD
                    is_default: false
                    dependent_tier_count: 0
                    chain_depth: 1
                    created_at: '2024-01-05T09:00:00.000000Z'
                    updated_at: '2024-02-01T11:00:00.000000Z'
                    archived_at: null
                  current_page: 1
                  last_page: 1
                  per_page: 15
                  total: 2
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-product-pricing-tiers
    delete:
      tags:
      - Pricing
      summary: Bulk Delete Pricing Tiers
      description: 'Bulk delete multiple pricing tiers by ID.


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Request body:

        - `ids` (required) — array of pricing tier IDs to delete


        **Requires permission:** `pricing_tiers.delete`'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  status:
                    type: string
                example:
                  message: 2 product pricing tiers deleted successfully
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: products:write
      operationId: delete-api-product-pricing-tiers
  /api/product-pricing-tiers/{productPricingTier}/default:
    put:
      tags:
      - Pricing
      summary: Set as Default Tier
      description: 'Set a pricing tier as the system default. Only absolute (non-relative)
        tiers that are not archived can be set as default. Unsetting the previous
        default is done automatically.


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Returns 400 if the tier is archived or is a relative pricing type.


        **Requires permission:** `pricing_tiers.update`'
      requestBody:
        content: {}
      parameters:
      - name: productPricingTier
        in: path
        schema:
          type: integer
        required: true
        description: Pricing tier ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      pricing_type:
                        type: string
                      is_default:
                        type: boolean
                      currency_code:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                  message:
                    type: string
                  status:
                    type: string
                example:
                  data:
                    id: 1
                    name: Standard
                    pricing_type: absolute
                    is_default: true
                    currency_code: USD
                    created_at: '2024-01-01T00:00:00.000000Z'
                    updated_at: '2024-03-10T11:00:00.000000Z'
                    archived_at: null
                  message: product pricing tier Standard was set as default successfully
                  status: success
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 400 Archived Tier
                  value:
                    errors:
                    - code: ProductPricingTierUNACCEPTABLE
                      field: id
                      meta:
                        id: 5
                    status: error
                example-1:
                  summary: 400 Relative Tier Cannot Be Default
                  value:
                    errors:
                    - code: ProductPricingTierUNACCEPTABLE
                      field: id
                      message: A relative pricing tier cannot be set as the default.
                      meta:
                        id: 2
                    status: error
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: products:write
      operationId: put-api-product-pricing-tiers-productpricingtier-default
  /api/product-pricing-tiers/{productPricingTier}/archive:
    put:
      tags:
      - Pricing
      summary: Archive Pricing Tier
      description: 'Archive a product pricing tier. Fails if the tier is the default
        tier or has active dependent tiers.


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `pricing_tiers.archive`'
      requestBody:
        content: {}
      parameters:
      - name: productPricingTier
        in: path
        schema:
          type: integer
        required: true
        description: Pricing tier ID
        example: '2'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  status:
                    type: string
                example:
                  message: product pricing tier Trade Wholesale was archived successfully
                  status: success
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: array
                    items:
                      type: object
                      properties:
                        code:
                          type: string
                        field:
                          type: string
                        message:
                          type: string
                        meta:
                          type: object
                          properties:
                            id:
                              type: integer
                  status:
                    type: string
                example:
                  errors:
                  - code: ProductPricingTierUNACCEPTABLE
                    field: id
                    message: Cannot archive the default pricing tier 'Standard'.
                    meta:
                      id: 1
                  status: error
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: products:write
      operationId: put-api-product-pricing-tiers-productpricingtier-archive
  /api/product-pricing-tiers/{productPricingTier}/unarchived:
    put:
      tags:
      - Pricing
      summary: Unarchive Pricing Tier
      description: 'Unarchive a product pricing tier.


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `pricing_tiers.archive`'
      requestBody:
        content: {}
      parameters:
      - name: productPricingTier
        in: path
        schema:
          type: integer
        required: true
        description: Pricing tier ID
        example: '2'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      pricing_type:
                        type: string
                      is_default:
                        type: boolean
                      currency_code:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                  message:
                    type: string
                  status:
                    type: string
                example:
                  data:
                    id: 2
                    name: Trade Wholesale
                    pricing_type: relative
                    is_default: false
                    currency_code: USD
                    archived_at: null
                  message: product pricing tier Trade Wholesale was unarchived successfully
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: products:write
      operationId: put-api-product-pricing-tiers-productpricingtier-unarchived
  /api/product-pricing-tiers/archive:
    put:
      tags:
      - Pricing
      summary: Bulk Archive Pricing Tiers
      description: 'Bulk archive multiple pricing tiers. Default tiers and tiers with
        active dependents are skipped with warnings.


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Request body:

        - `ids` (required) — array of pricing tier IDs to archive


        **Requires permission:** `pricing_tiers.archive`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 2
                - 3
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  status:
                    type: string
                example:
                  message: 2 product pricing tiers archived successfully
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: products:write
      operationId: put-api-product-pricing-tiers-archive
  /api/product-pricing-tiers/unarchive:
    put:
      tags:
      - Pricing
      summary: Bulk Unarchive Pricing Tiers
      description: 'Bulk unarchive multiple pricing tiers.


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Request body:

        - `ids` (required) — array of pricing tier IDs to unarchive


        **Requires permission:** `pricing_tiers.archive`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 2
                - 3
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  status:
                    type: string
                example:
                  message: 2 product pricing tiers unarchived successfully
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: products:write
      operationId: put-api-product-pricing-tiers-unarchive
  /api/product-pricing-tiers/deletable:
    post:
      tags:
      - Pricing
      summary: Check Pricing Tiers Deletable
      description: 'Check which pricing tiers can be deleted. Deletion is blocked
        if: tier is default, is used by products, referenced in import mappings, or
        has active dependent (relative) tiers.


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Request body:

        - `ids` (required, array) — pricing tier IDs to check; must exist in product_pricing_tiers
        table


        **Requires permission:** `pricing_tiers.delete`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1
                - 2
                - 3
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        deletable:
                          type: boolean
                        reason:
                          type: object
                          properties:
                            is_default:
                              type: string
                  status:
                    type: string
                example:
                  data:
                  - id: 1
                    name: Standard
                    deletable: false
                    reason:
                      is_default: Cannot delete the default pricing tier 'Standard'.
                  - id: 2
                    name: Wholesale
                    deletable: false
                    reason:
                      products: 5 products are currently using product pricing tier(Wholesale).
                  - id: 3
                    name: Clearance
                    deletable: true
                    reason: null
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: products:write
      operationId: post-api-product-pricing-tiers-deletable
  /api/product-pricing-tiers/archivable:
    post:
      tags:
      - Pricing
      summary: Check Pricing Tiers Archivable
      description: 'Check which pricing tiers can be archived. The default tier cannot
        be archived.


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Request body:

        - `ids` (required, array) — pricing tier IDs to check; must exist in product_pricing_tiers
        table


        **Requires permission:** `pricing_tiers.archive`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1
                - 2
                - 3
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        is_default:
                          type: boolean
                        archivable:
                          type: boolean
                        reason:
                          type: object
                          properties:
                            is_default:
                              type: string
                  status:
                    type: string
                example:
                  data:
                  - id: 1
                    name: Standard
                    is_default: true
                    archivable: false
                    reason:
                      is_default: Cannot archive the default pricing tier 'Standard'.
                  - id: 2
                    name: Wholesale
                    is_default: false
                    archivable: true
                    reason: null
                  - id: 3
                    name: Clearance
                    is_default: false
                    archivable: true
                    reason: null
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: products:write
      operationId: post-api-product-pricing-tiers-archivable
  /api/product-pricing-tiers/import/preview:
    post:
      tags:
      - Pricing
      summary: Preview Product Pricing Tier Import
      description: 'Preview a pricing tier import file before committing. Returns
        parsed rows and validation errors.


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Content-Type: multipart/form-data

        - `file` (required) — CSV or Excel file


        **Requires permission:** `pricing_tiers.import`'
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                file:
                  type: string
                  description: CSV or Excel file with pricing tier data
                  format: binary
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      rows:
                        type: array
                        items:
                          type: object
                          properties:
                            name:
                              type: string
                            currency_code:
                              type: string
                            pricing_type:
                              type: string
                            valid:
                              type: boolean
                            errors:
                              type: array
                      total:
                        type: integer
                      valid:
                        type: integer
                      invalid:
                        type: integer
                  status:
                    type: string
                example:
                  data:
                    rows:
                    - name: VIP Tier
                      currency_code: USD
                      pricing_type: absolute
                      valid: true
                      errors: []
                    total: 1
                    valid: 1
                    invalid: 0
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: products:write
      operationId: post-api-product-pricing-tiers-import-preview
  /api/product-pricing-tiers/import:
    post:
      tags:
      - Pricing
      summary: Import Pricing Tiers
      description: 'Import product pricing tiers from a CSV or Excel file.


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Content-Type: multipart/form-data

        - `file` (required) — CSV or Excel file


        **Requires permission:** `pricing_tiers.import`'
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                file:
                  type: string
                  description: CSV or Excel file with pricing tier data
                  format: binary
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      imported:
                        type: integer
                      skipped:
                        type: integer
                      errors:
                        type: array
                  message:
                    type: string
                  status:
                    type: string
                example:
                  data:
                    imported: 2
                    skipped: 0
                    errors: []
                  message: Import completed successfully
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: products:write
      operationId: post-api-product-pricing-tiers-import
  /api/custom-field-values:
    get:
      tags:
      - Custom Fields
      summary: List Custom Field Values
      description: 'Returns all custom field values. Each value links a custom field
        definition to a specific record (link_type + link_id).


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: array
                items:
                  type: object
                  properties:
                    id:
                      type: integer
                    custom_field_id:
                      type: integer
                    link_type:
                      type: string
                    link_id:
                      type: integer
                    value:
                      type: string
                    created_at:
                      type: string
                    updated_at:
                      type: string
                example:
                - id: 1
                  custom_field_id: 1
                  link_type: App\Models\PurchaseOrder
                  link_id: 45
                  value: Please ship with fragile label
                  created_at: '2024-03-10T14:00:00.000000Z'
                  updated_at: '2024-03-10T14:00:00.000000Z'
                - id: 2
                  custom_field_id: 2
                  link_type: App\Models\Supplier
                  link_id: 12
                  value: 5 stars
                  created_at: '2024-04-01T09:00:00.000000Z'
                  updated_at: '2024-04-01T09:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: get-api-custom-field-values
    post:
      tags:
      - Custom Fields
      summary: Create Custom Field Value
      description: 'Creates a new custom field value, attaching a custom field to
        a specific record. The link_type is automatically inferred from the custom
        field definition.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.


        Fields:

        - custom_field_id (required, integer, exists:custom_fields,id) — ID of the
        custom field definition

        - link_id (required, integer) — ID of the record to attach the value to

        - value (required) — The value to store'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                custom_field_id:
                  type: integer
                link_id:
                  type: integer
                value:
                  type: string
              example:
                custom_field_id: 1
                link_id: 45
                value: Please ship with fragile label
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: integer
                  custom_field_id:
                    type: integer
                  link_type:
                    type: string
                  link_id:
                    type: integer
                  value:
                    type: string
                  created_at:
                    type: string
                  updated_at:
                    type: string
                example:
                  id: 3
                  custom_field_id: 1
                  link_type: App\Models\PurchaseOrder
                  link_id: 45
                  value: Please ship with fragile label
                  created_at: '2024-06-01T10:00:00.000000Z'
                  updated_at: '2024-06-01T10:00:00.000000Z'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      custom_field_id:
                        type: array
                        items:
                          type: string
                      link_id:
                        type: array
                        items:
                          type: string
                      value:
                        type: array
                        items:
                          type: string
                example:
                  message: The custom field id field is required.
                  errors:
                    custom_field_id:
                    - The custom field id field is required.
                    link_id:
                    - The link id field is required.
                    value:
                    - The value field is required.
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: post-api-custom-field-values
  /api/custom-field-values/{custom_field_value}:
    get:
      tags:
      - Custom Fields
      summary: Get Custom Field Value
      description: 'Returns a single custom field value by ID.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: custom_field_value
        in: path
        schema:
          type: integer
        required: true
        description: Custom field value ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: integer
                  custom_field_id:
                    type: integer
                  link_type:
                    type: string
                  link_id:
                    type: integer
                  value:
                    type: string
                  created_at:
                    type: string
                  updated_at:
                    type: string
                example:
                  id: 1
                  custom_field_id: 1
                  link_type: App\Models\PurchaseOrder
                  link_id: 45
                  value: Please ship with fragile label
                  created_at: '2024-03-10T14:00:00.000000Z'
                  updated_at: '2024-03-10T14:00:00.000000Z'
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No query results for model [App\Models\CustomFieldValue]
                    999
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: get-api-custom-field-values-custom-field-value
    put:
      tags:
      - Custom Fields
      summary: Update Custom Field Value
      description: 'Updates the value of an existing custom field value. The custom_field_id,
        link_id, and link_type are preserved from the existing record.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.


        Fields:

        - value (required) — The new value to store'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                value:
                  type: string
              example:
                value: Handle with extreme care — fragile electronics
      parameters:
      - name: custom_field_value
        in: path
        schema:
          type: integer
        required: true
        description: Custom field value ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: integer
                  custom_field_id:
                    type: integer
                  link_type:
                    type: string
                  link_id:
                    type: integer
                  value:
                    type: string
                  created_at:
                    type: string
                  updated_at:
                    type: string
                example:
                  id: 1
                  custom_field_id: 1
                  link_type: App\Models\PurchaseOrder
                  link_id: 45
                  value: Handle with extreme care — fragile electronics
                  created_at: '2024-03-10T14:00:00.000000Z'
                  updated_at: '2024-06-01T12:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-session-only: true
      operationId: put-api-custom-field-values-custom-field-value
    delete:
      tags:
      - Custom Fields
      summary: Delete Custom Field Value
      description: 'Deletes a custom field value by ID.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: custom_field_value
        in: path
        schema:
          type: integer
        required: true
        description: Custom field value ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties: {}
                example: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-session-only: true
      operationId: delete-api-custom-field-values-custom-field-value
  /api/csv-templates:
    post:
      tags:
      - CSV Templates
      summary: Create CSV Template
      description: 'Creates a new CSV template for import/export operations.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token


        Request body:

        - name (string, required, max:255): Template name. Must be unique per model
        type.

        - model (string, required): The entity type this template applies to. Valid
        values: ''product'', ''sales_order'', ''product_brand'', ''supplier''

        - columns (array, required, min:1): Array of column mapping objects defining
        which fields to include


        **Requires permission:** `csv_templates.create`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                model:
                  type: string
                columns:
                  type: array
                  items:
                    type: object
                    properties:
                      column:
                        type: string
                      header:
                        type: string
              example:
                name: Standard Product Import
                model: product
                columns:
                - column: sku
                  header: SKU
                - column: name
                  header: Product Name
                - column: barcode
                  header: Barcode
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      template_type:
                        type: string
                      columns:
                        type: array
                        items:
                          type: object
                          properties:
                            column:
                              type: string
                            header:
                              type: string
                      used_count:
                        type: integer
                      last_import:
                        type: string
                        nullable: true
                      last_export:
                        type: string
                        nullable: true
                      archived_at:
                        type: string
                        nullable: true
                example:
                  message: csv template created successfully.
                  data:
                    id: 5
                    name: Standard Product Import
                    template_type: product
                    columns:
                    - column: sku
                      header: SKU
                    used_count: 0
                    last_import: null
                    last_export: null
                    archived_at: null
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      name:
                        type: array
                        items:
                          type: string
                example:
                  message: The name has already been taken.
                  errors:
                    name:
                    - The name has already been taken.
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: post-api-csv-templates
    get:
      tags:
      - CSV Templates
      summary: List CSV Templates
      description: 'Returns a paginated list of CSV import/export templates. Supports
        filtering by model type, pagination, and archive status.


        Authentication: Requires Bearer token


        Response fields:

        - id: Template ID

        - name: Template name (unique per model type)

        - template_type: The model type this template is for (e.g. ''product'', ''sales_order'')

        - columns: Array of column mappings

        - used_count: How many times this template has been used

        - last_import: Timestamp of last import using this template

        - last_export: Timestamp of last export using this template

        - archived_at: Archive timestamp (null if active)'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        description: 'Page number (default: 1)'
        example: '1'
      - name: limit
        in: query
        schema:
          type: integer
        description: 'Items per page (default: 15)'
        example: '15'
      - name: search
        in: query
        schema:
          type: string
        description: Search string to filter templates by name
      - name: archived
        in: query
        schema:
          type: integer
        description: 'Include archived: 0 = active only (default), 1 = archived only'
        example: '0'
      - name: sort
        in: query
        schema:
          type: string
        description: 'Sort field. Prefix with - for descending. Allowed: id, name,
          model, created_at, updated_at'
        example: name
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        template_type:
                          type: string
                        columns:
                          type: array
                          items:
                            type: object
                            properties:
                              column:
                                type: string
                              header:
                                type: string
                        used_count:
                          type: integer
                        last_import:
                          type: string
                        last_export:
                          type: string
                          nullable: true
                        create_at:
                          type: string
                        updated_at:
                          type: string
                        archived_at:
                          type: string
                          nullable: true
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 5
                    name: Standard Product Import
                    template_type: product
                    columns:
                    - column: sku
                      header: SKU
                    - column: name
                      header: Product Name
                    used_count: 12
                    last_import: '2024-01-10T09:00:00.000000Z'
                    last_export: null
                    create_at: '2024-01-01T00:00:00.000000Z'
                    updated_at: '2024-01-10T09:00:00.000000Z'
                    archived_at: null
                  last_page: 2
                  per_page: 15
                  total: 18
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-csv-templates
  /api/csv-templates/{csv_template}:
    get:
      tags:
      - CSV Templates
      summary: Get CSV Template
      description: 'Returns the details of a single CSV template.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token'
      parameters:
      - name: csv_template
        in: path
        schema:
          type: integer
        required: true
        description: CSV Template ID
        example: '5'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      template_type:
                        type: string
                      columns:
                        type: array
                        items:
                          type: object
                          properties:
                            column:
                              type: string
                            header:
                              type: string
                      used_count:
                        type: integer
                      last_import:
                        type: string
                      last_export:
                        type: string
                        nullable: true
                      archived_at:
                        type: string
                        nullable: true
                example:
                  data:
                    id: 5
                    name: Standard Product Import
                    template_type: product
                    columns:
                    - column: sku
                      header: SKU
                    - column: name
                      header: Product Name
                    used_count: 12
                    last_import: '2024-01-10T09:00:00.000000Z'
                    last_export: null
                    archived_at: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-session-only: true
      operationId: get-api-csv-templates-csv-template
    put:
      tags:
      - CSV Templates
      summary: Update CSV Template
      description: 'Updates an existing CSV template.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token


        Request body:

        - name (string, required, max:255): Template name. Must be unique per model
        type (ignoring the current template).

        - model (string, required): The entity type. Valid values: ''product'', ''sales_order'',
        ''product_brand'', ''supplier''

        - columns (array, required, min:1): Updated array of column mappings


        **Requires permission:** `csv_templates.update`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                model:
                  type: string
                columns:
                  type: array
                  items:
                    type: object
                    properties:
                      column:
                        type: string
                      header:
                        type: string
              example:
                name: Standard Product Import v2
                model: product
                columns:
                - column: sku
                  header: SKU
                - column: name
                  header: Product Name
                - column: weight
                  header: Weight
      parameters:
      - name: csv_template
        in: path
        schema:
          type: integer
        required: true
        description: CSV Template ID
        example: '5'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      template_type:
                        type: string
                      columns:
                        type: array
                        items:
                          type: object
                          properties:
                            column:
                              type: string
                            header:
                              type: string
                      archived_at:
                        type: string
                        nullable: true
                example:
                  message: csv template Standard Product Import v2 updated successfully.
                  data:
                    id: 5
                    name: Standard Product Import v2
                    template_type: product
                    columns:
                    - column: sku
                      header: SKU
                    - column: name
                      header: Product Name
                    - column: weight
                      header: Weight
                    archived_at: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-session-only: true
      operationId: put-api-csv-templates-csv-template
    delete:
      tags:
      - CSV Templates
      summary: Delete CSV Template
      description: 'Deletes the specified CSV template.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token


        **Requires permission:** `csv_templates.delete`'
      parameters:
      - name: csv_template
        in: path
        schema:
          type: integer
        required: true
        description: CSV Template ID
        example: '5'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: csv template Standard Product Import deleted successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-session-only: true
      operationId: delete-api-csv-templates-csv-template
  /api/csv-templates/{csvTemplate}/archive:
    put:
      tags:
      - CSV Templates
      summary: Archive CSV Template
      description: 'Archives the specified CSV template.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token (Power User access required)


        **Requires permission:** `csv_templates.archive`'
      requestBody:
        content: {}
      parameters:
      - name: csvTemplate
        in: path
        schema:
          type: integer
        required: true
        description: CSV Template ID
        example: '5'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      archived_at:
                        type: string
                example:
                  message: csv template Standard Product Import archived successfully.
                  data:
                    id: 5
                    archived_at: '2024-01-15T10:30:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-session-only: true
      operationId: put-api-csv-templates-csvtemplate-archive
  /api/csv-templates/{csvTemplate}/unarchived:
    put:
      tags:
      - CSV Templates
      summary: Unarchive CSV Template
      description: 'Restores (unarchives) the specified CSV template.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token (Power User access required)


        **Requires permission:** `csv_templates.archive`'
      requestBody:
        content: {}
      parameters:
      - name: csvTemplate
        in: path
        schema:
          type: integer
        required: true
        description: CSV Template ID
        example: '5'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      archived_at:
                        type: string
                        nullable: true
                example:
                  message: csv template Standard Product Import unarchived successfully.
                  data:
                    id: 5
                    archived_at: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-session-only: true
      operationId: put-api-csv-templates-csvtemplate-unarchived
  /api/csv-templates/{csvTemplate}/download:
    get:
      tags:
      - CSV Templates
      summary: Download Sample Template
      description: 'Returns the URL to the sample CSV file for this template. The
        sample file shows the expected column headers and example data.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token (Power User access required)


        Response: URL string (not a JSON object)'
      parameters:
      - name: csvTemplate
        in: path
        schema:
          type: integer
        required: true
        description: CSV Template ID
        example: '5'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            text/plain:
              schema:
                type: string
                example: '"https://sku2.test/storage/csv-samples/standard-product-import.csv"'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-session-only: true
      operationId: get-api-csv-templates-csvtemplate-download
  /api/csv-templates/{csvTemplate}/export:
    get:
      tags:
      - CSV Templates
      summary: Export Data Using Template
      description: 'Exports data using the specified CSV template. Returns a CSV file
        download with the columns defined in the template.


        Authentication: Requires Bearer token (Power User access required)


        Response: text/csv file download


        **Requires permission:** `csv_templates.export`'
      parameters:
      - name: archived
        in: query
        schema:
          type: integer
        description: 'Include archived records: 0 = active only (default), 1 = archived
          only'
        example: '0'
      - name: limit
        in: query
        schema:
          type: integer
        description: Maximum number of records to export (optional)
        example: '1000'
      - name: csvTemplate
        in: path
        schema:
          type: integer
        required: true
        description: CSV Template ID
        example: '5'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: text/csv
            Content-Disposition:
              schema:
                type: string
                example: attachment; filename=export.csv
          content:
            text/plain:
              schema:
                type: string
                example: 'SKU,Product Name,Barcode

                  SKU-001,Widget A,123456789

                  SKU-002,Widget B,987654321'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-csv-templates-csvtemplate-export
  /api/csv-templates/import:
    post:
      tags:
      - CSV Templates
      summary: Import Data Using Template
      description: 'Imports data from a CSV file using the specified template. Supports
        preview mode to validate the file before committing.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token (Power User access required)


        Request body (multipart/form-data):

        - file (file, required unless tmp_file): The CSV file to import

        - tmp_file (string, required unless file): Path to a previously uploaded temporary
        file

        - template_id (integer, required unless model): ID of the template to use

        - model (string, required unless template_id): Model type for auto-detecting
        the template. Values: product, sales_order, product_brand, supplier

        - preview (boolean, optional): If true, returns a 10-row preview without importing
        (default: false)


        **Requires permission:** `csv_templates.import`'
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                file:
                  type: string
                  description: CSV file to import (required unless tmp_file is provided)
                  format: binary
                template_id:
                  type: integer
                  description: Template ID to use for import (required unless model
                    is provided)
                  example: '5'
                model:
                  type: string
                  description: 'Model type for auto-detecting template (required unless
                    template_id is provided). Values: product, sales_order, product_brand,
                    supplier'
                  example: product
                preview:
                  type: boolean
                  description: If true, returns a preview of the first 10 rows without
                    importing
                  example: 'false'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 Success - Import
                  value:
                    data:
                      imported: 50
                      errors: []
                      selected_template:
                        id: 5
                        name: Standard Product Import
                    message: Import completed successfully.
                example-1:
                  summary: 200 Success - Preview
                  value:
                    data:
                      tmp_file: /tmp/sku/upload_abc123.csv
                      rows:
                      - sku: SKU-001
                        name: Widget A
                      - sku: SKU-002
                        name: Widget B
                      headers:
                      - SKU
                      - Product Name
                    message: Preview generated.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-session-only: true
      operationId: post-api-csv-templates-import
  /api/csv-templates/{model}/prepare:
    get:
      tags:
      - CSV Templates
      summary: Get Template Builder Columns
      description: 'Returns the available columns and related data for building or
        editing a CSV template for the specified model type.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token (Power User access required)


        For ''product'' model, also returns:

        - relations.productAttributes: Available product attribute types

        - relations.productPricingTiers: Available pricing tiers

        - relations.suppliers: All suppliers

        - relations.SupplierPricingTiers: Supplier-specific pricing tiers'
      parameters:
      - name: model
        in: path
        schema:
          type: string
        required: true
        description: 'Model type. Valid values: product, sales_order, product_brand,
          supplier'
        example: product
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 Success - Product
                  value:
                    data:
                      attributes:
                      - id
                      - sku
                      - name
                      - barcode
                      - type
                      - weight
                      - weight_unit
                      - brand
                      - tags
                      - image_url
                      - category
                      - length
                      - width
                      - height
                      - created_at
                      relations:
                        productAttributes:
                        - id: 1
                          name: Color
                        productPricingTiers:
                        - id: 1
                          name: Retail
                        suppliers:
                        - id: 1
                          name: ACME Corp
                        SupplierPricingTiers:
                        - id: 1
                          name: Standard
                example-1:
                  summary: 200 Success - Sales Order
                  value:
                    data:
                      attributes:
                      - sales_order_number
                      - sales_channel
                      - customer
                      - order_date
                      - ship_by
                      - deliver_by
                      - shipping_method
                      - warehouse_name
                      - items
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-session-only: true
      operationId: get-api-csv-templates-model-prepare
  /api/csv-templates/archive:
    put:
      tags:
      - CSV Templates
      summary: Bulk Archive CSV Templates
      description: 'Archives multiple CSV templates.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token (Power User access required)


        Request body:

        - ids (array, required unless apply_to_all): Array of template IDs to archive

        - apply_to_all (boolean, optional): If true, archives all templates matching
        the provided filters

        - filters (array, optional): Filter criteria when apply_to_all is true


        **Requires permission:** `csv_templates.archive`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 5
                - 6
                - 7
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 3 csv templates archived successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-session-only: true
      operationId: put-api-csv-templates-archive
  /api/csv-templates/unarchive:
    put:
      tags:
      - CSV Templates
      summary: Bulk Unarchive CSV Templates
      description: 'Restores (unarchives) multiple CSV templates.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token (Power User access required)


        Request body:

        - ids (array, required unless apply_to_all): Array of template IDs to unarchive

        - apply_to_all (boolean, optional): If true, unarchives all templates matching
        the provided filters

        - filters (array, optional): Filter criteria when apply_to_all is true


        **Requires permission:** `csv_templates.archive`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 5
                - 6
                - 7
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 3 csv templates unarchived successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-session-only: true
      operationId: put-api-csv-templates-unarchive
  /api/v2/listing-drafts:
    get:
      tags:
      - Product Listings
      summary: List Drafts
      description: 'Paginated listing drafts for the drafts list. Slim payload — the
        heavy `fields[]` array is only served by show/update/validate.


        Search covers draft ID, product name/SKU, and channel name (resolved through
        the channel''s integration instance). Advanced `filter_groups` trees support
        nested AND/OR groups over the columns listed on the parameter.


        Authentication: Requires Bearer token.

        Feature flag: requires `listing-publishing` to be enabled.'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        description: Page number.
        example: '1'
      - name: per_page
        in: query
        schema:
          type: integer
        description: Items per page (max 100, default 25).
        example: '25'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        product_id:
                          type: integer
                        sales_channel_id:
                          type: integer
                        sales_channel_category_id:
                          type: integer
                        sales_channel_product_template_id:
                          type: string
                          nullable: true
                        sales_channel_listing_profile_id:
                          type: string
                          nullable: true
                        product_listing_id:
                          type: string
                          nullable: true
                        purpose:
                          type: string
                        state:
                          type: string
                        scheduled_at:
                          type: string
                          nullable: true
                        image_urls:
                          type: array
                        validation_errors:
                          type: string
                          nullable: true
                        channel_errors:
                          type: string
                          nullable: true
                        published_at:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                        updated_at:
                          type: string
                        product:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            sku:
                              type: string
                        sales_channel:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            integration_name:
                              type: string
                        category:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            path:
                              type: string
                            external_id:
                              type: string
                        variation_theme:
                          type: string
                          nullable: true
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - id: 181
                    product_id: 99
                    sales_channel_id: 34
                    sales_channel_category_id: 26
                    sales_channel_product_template_id: null
                    sales_channel_listing_profile_id: null
                    product_listing_id: null
                    purpose: create
                    state: ready
                    scheduled_at: null
                    image_urls: []
                    validation_errors: null
                    channel_errors: null
                    published_at: null
                    created_at: '2026-07-06T05:16:00+00:00'
                    updated_at: '2026-07-06T07:19:00+00:00'
                    product:
                      id: 99
                      name: Tiny Threads Cardigan
                      sku: TT019
                    sales_channel:
                      id: 34
                      name: BigCommerce2
                      integration_name: BigCommerce
                    category:
                      id: 26
                      name: General (Baseline)
                      path: General (Baseline)
                      external_id: '23'
                    variation_theme: null
                  current_page: 1
                  last_page: 11
                  per_page: 25
                  total: 259
                  from: 1
                  to: 25
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-v2-listing-drafts
    post:
      tags:
      - Product Listings
      summary: Create Draft
      description: 'Create a listing draft.


        Fields:

        - `purpose` (required, `create` | `update`) — `create` builds a new-listing
        draft; `update` seeds a draft from an existing live listing.

        - `product_id` (required if purpose=create, integer) — product to list.

        - `sales_channel_id` (required if purpose=create, integer) — target channel.

        - `sales_channel_category_id` (nullable, integer) — channel category driving
        the field schema. A draft without a category records a `missing_category`
        validation error and stays in `draft` state — it can never reach `ready` until
        a category is set.

        - `sales_channel_product_template_id` (nullable, integer) — template pre-mapping
        category fields. Optional: a draft is fully publishable without one (fill
        fields via overrides).

        - `sales_channel_listing_profile_id` (nullable, integer) — channel listing
        profile.

        - `product_listing_id` (required if purpose=update, integer) — live listing
        to seed from.


        The draft is resolved + validated on creation; the response includes `fields[]`
        (schema + resolved value + provenance + raw `override`), `resolved_values`
        and `validation_errors`.


        Authentication: Requires Bearer token.

        Feature flag: requires `listing-publishing` to be enabled.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                purpose:
                  type: string
                product_id:
                  type: integer
                sales_channel_id:
                  type: integer
                sales_channel_category_id:
                  type: integer
                sales_channel_product_template_id:
                  type: string
                  nullable: true
                sales_channel_listing_profile_id:
                  type: string
                  nullable: true
              example:
                purpose: create
                product_id: 88
                sales_channel_id: 30
                sales_channel_category_id: 7
                sales_channel_product_template_id: null
                sales_channel_listing_profile_id: null
      parameters: []
      responses:
        '201':
          description: Created
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 201 Created
                  value:
                    id: 42
                    product_id: 88
                    sales_channel_id: 30
                    sales_channel_category_id: 7
                    sales_channel_product_template_id: null
                    sales_channel_listing_profile_id: null
                    product_listing_id: null
                    purpose: create
                    state: ready
                    scheduled_at: null
                    image_urls:
                    - https://cdn.example.com/img/beanie-1.jpg
                    validation_errors: null
                    channel_errors: null
                    published_at: null
                    created_at: '2026-07-06T12:00:00+00:00'
                    updated_at: '2026-07-06T12:05:00+00:00'
                    product:
                      id: 88
                      name: Tiny Threads Beanie
                      sku: TT008
                    sales_channel:
                      id: 30
                      name: eBay Store
                      integration_name: Ebay
                    category:
                      id: 7
                      name: Hoodies
                      path: QA / Hoodies
                      external_id: '155184'
                    template: null
                    listing_profile: null
                    variation_theme: null
                    variation_data: null
                    fields:
                    - name: Brand
                      label: Brand
                      schema:
                        type: text
                        usage: required
                        cardinality: 1
                        allowed_values: null
                        allows_custom_value: true
                        max_length: null
                        min_length: null
                        object_schema: null
                      value: Tiny Threads
                      provenance: override
                      has_override: true
                      override:
                        source_type: product_field
                        source_value: brand
                      errors: []
                    - name: Color
                      label: Color
                      schema:
                        type: text
                        usage: required
                        cardinality: 1
                        allowed_values: null
                        allows_custom_value: true
                        max_length: null
                        min_length: null
                        object_schema: null
                      value: Sage
                      provenance: template
                      has_override: false
                      override: null
                      errors: []
                    field_overrides:
                      Brand:
                        source_type: product_field
                        source_value: brand
                    resolved_values:
                      Brand:
                        value: Tiny Threads
                        provenance: override
                      Color:
                        value: Sage
                        provenance: template
                example-1:
                  summary: 201 Created (no category — missing_category error)
                  value:
                    id: 43
                    product_id: 88
                    sales_channel_id: 30
                    sales_channel_category_id: null
                    sales_channel_product_template_id: null
                    sales_channel_listing_profile_id: null
                    product_listing_id: null
                    purpose: create
                    state: draft
                    scheduled_at: null
                    image_urls:
                    - https://cdn.example.com/img/beanie-1.jpg
                    validation_errors:
                    - field: _global
                      code: missing_category
                      message: Pick a channel category before this draft can be validated.
                    channel_errors: null
                    published_at: null
                    created_at: '2026-07-06T12:00:00+00:00'
                    updated_at: '2026-07-06T12:05:00+00:00'
                    product:
                      id: 88
                      name: Tiny Threads Beanie
                      sku: TT008
                    sales_channel:
                      id: 30
                      name: eBay Store
                      integration_name: Ebay
                    category: null
                    template: null
                    listing_profile: null
                    variation_theme: null
                    variation_data: null
                    fields: []
                    field_overrides: null
                    resolved_values: null
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-v2-listing-drafts
  /api/v2/listing-drafts/mappable-product-fields:
    get:
      tags:
      - Product Listings
      summary: List Mappable Product Fields
      description: 'Product columns usable as a `product_field` mapping source in
        draft field_overrides and template field defaults. Served from the resolver
        whitelist (ListingValueResolver) so pickers never offer a column the resolver
        won''t read.


        `brand` resolves through the product''s brand relation (ProductBrand::name);
        `price` resolves through the default pricing tier accessor; all other values
        are direct product columns.


        Authentication: Requires Bearer token.

        Feature flag: requires `listing-publishing` to be enabled.


        Each item includes `type` — the column''s data type (`text` or `number`) —
        so the mapping picker can show what kind of value a column carries.'
      parameters: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        value:
                          type: string
                        label:
                          type: string
                        type:
                          type: string
                example:
                  data:
                  - value: name
                    label: Name
                    type: text
                  - value: sku
                    label: SKU
                    type: text
                  - value: barcode
                    label: Barcode (UPC / EAN)
                    type: text
                  - value: mpn
                    label: MPN
                    type: text
                  - value: brand
                    label: Brand
                    type: text
                  - value: price
                    label: Price (default tier)
                    type: number
                  - value: weight
                    label: Weight
                    type: number
                  - value: weight_unit
                    label: Weight unit
                    type: text
                  - value: length
                    label: Length
                    type: number
                  - value: width
                    label: Width
                    type: number
                  - value: height
                    label: Height
                    type: number
                  - value: dimension_unit
                    label: Dimension unit
                    type: text
                  - value: case_quantity
                    label: Case quantity
                    type: number
                  - value: fba_prep_instructions
                    label: FBA prep instructions
                    type: text
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-v2-listing-drafts-mappable-product-fields
  /api/v2/listing-drafts/{draft}:
    get:
      tags:
      - Product Listings
      summary: Get Draft
      description: 'Show a draft with the full per-field payload.


        Each `fields[]` row merges the cached category schema with the draft''s resolved
        value:

        - `value` — resolved value after the precedence chain (override > template
        > channel mapping > integration mapping > blank)

        - `provenance` — where the value came from (`override`, `template`, `channel_mapping`,
        `integration_mapping`, `blank`)

        - `has_override` — whether the draft overrides this field

        - `override` — the raw override: a literal value, or a mapped source object
        `{source_type, source_value}`

        - `errors` — validation/channel errors scoped to this field


        Authentication: Requires Bearer token.

        Feature flag: requires `listing-publishing` to be enabled.'
      parameters:
      - name: draft
        in: path
        schema:
          type: integer
        required: true
        description: Listing draft ID
        example: '42'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: integer
                  product_id:
                    type: integer
                  sales_channel_id:
                    type: integer
                  sales_channel_category_id:
                    type: integer
                  sales_channel_product_template_id:
                    type: string
                    nullable: true
                  sales_channel_listing_profile_id:
                    type: string
                    nullable: true
                  product_listing_id:
                    type: string
                    nullable: true
                  purpose:
                    type: string
                  state:
                    type: string
                  scheduled_at:
                    type: string
                    nullable: true
                  image_urls:
                    type: array
                    items:
                      type: string
                  validation_errors:
                    type: string
                    nullable: true
                  channel_errors:
                    type: string
                    nullable: true
                  published_at:
                    type: string
                    nullable: true
                  created_at:
                    type: string
                  updated_at:
                    type: string
                  product:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      sku:
                        type: string
                  sales_channel:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      integration_name:
                        type: string
                  category:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      path:
                        type: string
                      external_id:
                        type: string
                  template:
                    type: string
                    nullable: true
                  listing_profile:
                    type: string
                    nullable: true
                  variation_theme:
                    type: string
                    nullable: true
                  variation_data:
                    type: string
                    nullable: true
                  fields:
                    type: array
                    items:
                      type: object
                      properties:
                        name:
                          type: string
                        label:
                          type: string
                        schema:
                          type: object
                          properties:
                            type:
                              type: string
                            usage:
                              type: string
                            cardinality:
                              type: integer
                            allowed_values:
                              type: string
                              nullable: true
                            allows_custom_value:
                              type: boolean
                            max_length:
                              type: string
                              nullable: true
                            min_length:
                              type: string
                              nullable: true
                            object_schema:
                              type: string
                              nullable: true
                        value:
                          type: string
                        provenance:
                          type: string
                        has_override:
                          type: boolean
                        override:
                          type: object
                          properties:
                            source_type:
                              type: string
                            source_value:
                              type: string
                        errors:
                          type: array
                  field_overrides:
                    type: object
                    properties:
                      Brand:
                        type: object
                        properties:
                          source_type:
                            type: string
                          source_value:
                            type: string
                  resolved_values:
                    type: object
                    properties:
                      Brand:
                        type: object
                        properties:
                          value:
                            type: string
                          provenance:
                            type: string
                      Color:
                        type: object
                        properties:
                          value:
                            type: string
                          provenance:
                            type: string
                example:
                  id: 42
                  product_id: 88
                  sales_channel_id: 30
                  sales_channel_category_id: 7
                  sales_channel_product_template_id: null
                  sales_channel_listing_profile_id: null
                  product_listing_id: null
                  purpose: create
                  state: ready
                  scheduled_at: null
                  image_urls:
                  - https://cdn.example.com/img/beanie-1.jpg
                  validation_errors: null
                  channel_errors: null
                  published_at: null
                  created_at: '2026-07-06T12:00:00+00:00'
                  updated_at: '2026-07-06T12:05:00+00:00'
                  product:
                    id: 88
                    name: Tiny Threads Beanie
                    sku: TT008
                  sales_channel:
                    id: 30
                    name: eBay Store
                    integration_name: Ebay
                  category:
                    id: 7
                    name: Hoodies
                    path: QA / Hoodies
                    external_id: '155184'
                  template: null
                  listing_profile: null
                  variation_theme: null
                  variation_data: null
                  fields:
                  - name: Brand
                    label: Brand
                    schema:
                      type: text
                      usage: required
                      cardinality: 1
                      allowed_values: null
                      allows_custom_value: true
                      max_length: null
                      min_length: null
                      object_schema: null
                    value: Tiny Threads
                    provenance: override
                    has_override: true
                    override:
                      source_type: product_field
                      source_value: brand
                    errors: []
                  - name: Color
                    label: Color
                    schema:
                      type: text
                      usage: required
                      cardinality: 1
                      allowed_values: null
                      allows_custom_value: true
                      max_length: null
                      min_length: null
                      object_schema: null
                    value: Sage
                    provenance: template
                    has_override: false
                    override: null
                    errors: []
                  field_overrides:
                    Brand:
                      source_type: product_field
                      source_value: brand
                  resolved_values:
                    Brand:
                      value: Tiny Threads
                      provenance: override
                    Color:
                      value: Sage
                      provenance: template
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-v2-listing-drafts-draft
    put:
      tags:
      - Product Listings
      summary: Update Draft (overrides, images, structure)
      description: 'Update a draft — saves `field_overrides`, `image_urls`, and structural
        changes (`sales_channel_category_id`, `sales_channel_product_template_id`,
        `sales_channel_listing_profile_id`), then re-resolves and re-validates. The
        draft transitions to `ready` when no validation errors remain.


        `field_overrides` values come in two shapes:

        - **Literal value** (string / number / bool / array for multiselect) — used
        verbatim, provenance `override`.

        - **Mapped source** — an object `{"source_type": ..., "source_value": ...}`
        that re-resolves from product data on every validate/publish. `source_type`
        must be one of `product_field` (whitelisted product columns — see GET /api/v2/listing-drafts/mappable-product-fields),
        `product_attribute` (an Attribute id), `static` (literal string), or `expression`
        (mustache tokens, e.g. `{{product.sku}} - {{product.name}}`). A mapped override
        that resolves to null stays null (no fall-through to template/mapping values)
        so required-field validation can flag it.


        Passing an invalid `source_type`, or a `source_value` that is not a scalar,
        returns 422.


        Fields:

        - `field_overrides` (nullable, object) — map of field name to literal value
        or mapped source (see above).

        - `sales_channel_category_id` (nullable, integer)

        - `sales_channel_product_template_id` (nullable, integer)

        - `sales_channel_listing_profile_id` (nullable, integer)

        - `image_urls` (nullable, array of strings)


        Authentication: Requires Bearer token.

        Feature flag: requires `listing-publishing` to be enabled.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                field_overrides:
                  type: object
                  properties:
                    Brand:
                      type: object
                      properties:
                        source_type:
                          type: string
                        source_value:
                          type: string
                    Color:
                      type: string
                    Title:
                      type: object
                      properties:
                        source_type:
                          type: string
                        source_value:
                          type: string
                image_urls:
                  type: array
                  items:
                    type: string
              example:
                field_overrides:
                  Brand:
                    source_type: product_field
                    source_value: brand
                  Color: Sage
                  Title:
                    source_type: expression
                    source_value: '{{product.sku}} - {{product.name}}'
                image_urls:
                - https://cdn.example.com/img/beanie-1.jpg
      parameters:
      - name: draft
        in: path
        schema:
          type: integer
        required: true
        description: Listing draft ID
        example: '42'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: integer
                  product_id:
                    type: integer
                  sales_channel_id:
                    type: integer
                  sales_channel_category_id:
                    type: integer
                  sales_channel_product_template_id:
                    type: string
                    nullable: true
                  sales_channel_listing_profile_id:
                    type: string
                    nullable: true
                  product_listing_id:
                    type: string
                    nullable: true
                  purpose:
                    type: string
                  state:
                    type: string
                  scheduled_at:
                    type: string
                    nullable: true
                  image_urls:
                    type: array
                    items:
                      type: string
                  validation_errors:
                    type: string
                    nullable: true
                  channel_errors:
                    type: string
                    nullable: true
                  published_at:
                    type: string
                    nullable: true
                  created_at:
                    type: string
                  updated_at:
                    type: string
                  product:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      sku:
                        type: string
                  sales_channel:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      integration_name:
                        type: string
                  category:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      path:
                        type: string
                      external_id:
                        type: string
                  template:
                    type: string
                    nullable: true
                  listing_profile:
                    type: string
                    nullable: true
                  variation_theme:
                    type: string
                    nullable: true
                  variation_data:
                    type: string
                    nullable: true
                  fields:
                    type: array
                    items:
                      type: object
                      properties:
                        name:
                          type: string
                        label:
                          type: string
                        schema:
                          type: object
                          properties:
                            type:
                              type: string
                            usage:
                              type: string
                            cardinality:
                              type: integer
                            allowed_values:
                              type: string
                              nullable: true
                            allows_custom_value:
                              type: boolean
                            max_length:
                              type: string
                              nullable: true
                            min_length:
                              type: string
                              nullable: true
                            object_schema:
                              type: string
                              nullable: true
                        value:
                          type: string
                        provenance:
                          type: string
                        has_override:
                          type: boolean
                        override:
                          type: object
                          properties:
                            source_type:
                              type: string
                            source_value:
                              type: string
                        errors:
                          type: array
                  field_overrides:
                    type: object
                    properties:
                      Brand:
                        type: object
                        properties:
                          source_type:
                            type: string
                          source_value:
                            type: string
                  resolved_values:
                    type: object
                    properties:
                      Brand:
                        type: object
                        properties:
                          value:
                            type: string
                          provenance:
                            type: string
                      Color:
                        type: object
                        properties:
                          value:
                            type: string
                          provenance:
                            type: string
                example:
                  id: 42
                  product_id: 88
                  sales_channel_id: 30
                  sales_channel_category_id: 7
                  sales_channel_product_template_id: null
                  sales_channel_listing_profile_id: null
                  product_listing_id: null
                  purpose: create
                  state: ready
                  scheduled_at: null
                  image_urls:
                  - https://cdn.example.com/img/beanie-1.jpg
                  validation_errors: null
                  channel_errors: null
                  published_at: null
                  created_at: '2026-07-06T12:00:00+00:00'
                  updated_at: '2026-07-06T12:05:00+00:00'
                  product:
                    id: 88
                    name: Tiny Threads Beanie
                    sku: TT008
                  sales_channel:
                    id: 30
                    name: eBay Store
                    integration_name: Ebay
                  category:
                    id: 7
                    name: Hoodies
                    path: QA / Hoodies
                    external_id: '155184'
                  template: null
                  listing_profile: null
                  variation_theme: null
                  variation_data: null
                  fields:
                  - name: Brand
                    label: Brand
                    schema:
                      type: text
                      usage: required
                      cardinality: 1
                      allowed_values: null
                      allows_custom_value: true
                      max_length: null
                      min_length: null
                      object_schema: null
                    value: Tiny Threads
                    provenance: override
                    has_override: true
                    override:
                      source_type: product_field
                      source_value: brand
                    errors: []
                  - name: Color
                    label: Color
                    schema:
                      type: text
                      usage: required
                      cardinality: 1
                      allowed_values: null
                      allows_custom_value: true
                      max_length: null
                      min_length: null
                      object_schema: null
                    value: Sage
                    provenance: template
                    has_override: false
                    override: null
                    errors: []
                  field_overrides:
                    Brand:
                      source_type: product_field
                      source_value: brand
                  resolved_values:
                    Brand:
                      value: Tiny Threads
                      provenance: override
                    Color:
                      value: Sage
                      provenance: template
        '422':
          description: Unprocessable Content
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      field_overrides.Brand:
                        type: array
                        items:
                          type: string
                example:
                  message: The field_overrides.Brand mapping has an invalid source_type.
                  errors:
                    field_overrides.Brand:
                    - The field_overrides.Brand mapping has an invalid source_type.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: put-api-v2-listing-drafts-draft
  /api/v2/listing-drafts/{draft}/validate:
    post:
      tags:
      - Product Listings
      summary: Validate Draft
      description: 'Re-resolve the draft''s values against current product data +
        mappings and re-run validation. Mapped overrides (`{source_type, source_value}`)
        are re-evaluated against the product on every call. State transitions to `ready`
        when validation passes, back to `draft` when errors appear. A draft without
        a category records a `missing_category` validation error.


        Authentication: Requires Bearer token.

        Feature flag: requires `listing-publishing` to be enabled.'
      requestBody:
        content: {}
      parameters:
      - name: draft
        in: path
        schema:
          type: integer
        required: true
        description: Listing draft ID
        example: '42'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: integer
                  product_id:
                    type: integer
                  sales_channel_id:
                    type: integer
                  sales_channel_category_id:
                    type: integer
                  sales_channel_product_template_id:
                    type: string
                    nullable: true
                  sales_channel_listing_profile_id:
                    type: string
                    nullable: true
                  product_listing_id:
                    type: string
                    nullable: true
                  purpose:
                    type: string
                  state:
                    type: string
                  scheduled_at:
                    type: string
                    nullable: true
                  image_urls:
                    type: array
                    items:
                      type: string
                  validation_errors:
                    type: string
                    nullable: true
                  channel_errors:
                    type: string
                    nullable: true
                  published_at:
                    type: string
                    nullable: true
                  created_at:
                    type: string
                  updated_at:
                    type: string
                  product:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      sku:
                        type: string
                  sales_channel:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      integration_name:
                        type: string
                  category:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      path:
                        type: string
                      external_id:
                        type: string
                  template:
                    type: string
                    nullable: true
                  listing_profile:
                    type: string
                    nullable: true
                  variation_theme:
                    type: string
                    nullable: true
                  variation_data:
                    type: string
                    nullable: true
                  fields:
                    type: array
                    items:
                      type: object
                      properties:
                        name:
                          type: string
                        label:
                          type: string
                        schema:
                          type: object
                          properties:
                            type:
                              type: string
                            usage:
                              type: string
                            cardinality:
                              type: integer
                            allowed_values:
                              type: string
                              nullable: true
                            allows_custom_value:
                              type: boolean
                            max_length:
                              type: string
                              nullable: true
                            min_length:
                              type: string
                              nullable: true
                            object_schema:
                              type: string
                              nullable: true
                        value:
                          type: string
                        provenance:
                          type: string
                        has_override:
                          type: boolean
                        override:
                          type: object
                          properties:
                            source_type:
                              type: string
                            source_value:
                              type: string
                        errors:
                          type: array
                  field_overrides:
                    type: object
                    properties:
                      Brand:
                        type: object
                        properties:
                          source_type:
                            type: string
                          source_value:
                            type: string
                  resolved_values:
                    type: object
                    properties:
                      Brand:
                        type: object
                        properties:
                          value:
                            type: string
                          provenance:
                            type: string
                      Color:
                        type: object
                        properties:
                          value:
                            type: string
                          provenance:
                            type: string
                example:
                  id: 42
                  product_id: 88
                  sales_channel_id: 30
                  sales_channel_category_id: 7
                  sales_channel_product_template_id: null
                  sales_channel_listing_profile_id: null
                  product_listing_id: null
                  purpose: create
                  state: ready
                  scheduled_at: null
                  image_urls:
                  - https://cdn.example.com/img/beanie-1.jpg
                  validation_errors: null
                  channel_errors: null
                  published_at: null
                  created_at: '2026-07-06T12:00:00+00:00'
                  updated_at: '2026-07-06T12:05:00+00:00'
                  product:
                    id: 88
                    name: Tiny Threads Beanie
                    sku: TT008
                  sales_channel:
                    id: 30
                    name: eBay Store
                    integration_name: Ebay
                  category:
                    id: 7
                    name: Hoodies
                    path: QA / Hoodies
                    external_id: '155184'
                  template: null
                  listing_profile: null
                  variation_theme: null
                  variation_data: null
                  fields:
                  - name: Brand
                    label: Brand
                    schema:
                      type: text
                      usage: required
                      cardinality: 1
                      allowed_values: null
                      allows_custom_value: true
                      max_length: null
                      min_length: null
                      object_schema: null
                    value: Tiny Threads
                    provenance: override
                    has_override: true
                    override:
                      source_type: product_field
                      source_value: brand
                    errors: []
                  - name: Color
                    label: Color
                    schema:
                      type: text
                      usage: required
                      cardinality: 1
                      allowed_values: null
                      allows_custom_value: true
                      max_length: null
                      min_length: null
                      object_schema: null
                    value: Sage
                    provenance: template
                    has_override: false
                    override: null
                    errors: []
                  field_overrides:
                    Brand:
                      source_type: product_field
                      source_value: brand
                  resolved_values:
                    Brand:
                      value: Tiny Threads
                      provenance: override
                    Color:
                      value: Sage
                      provenance: template
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-v2-listing-drafts-draft-validate
  /api/v2/listing-drafts/{draft}/preview-against-product:
    post:
      tags:
      - Product Listings
      summary: Preview Draft Against Product
      description: 'Resolve this draft''s mappings (its template + field overrides)
        against a DIFFERENT product, returning the value each channel field would
        receive for that product — with no persistence. Useful for a "preview against
        another product" control: mapped fields (`product_field` / `product_attribute`
        / `expression`) re-evaluate against the given product, while typed literal
        values stay as-is.


        Request body:

        - `product_id` (integer, required) — the product to resolve against; must
        exist.


        Response: `data.product` echoes the previewed product, and `data.values` is
        keyed by channel field name, each with the resolved `value` and its `provenance`
        (override / template / channel_mapping / integration_mapping / channel_default
        / blank).


        Authentication: Requires Bearer token.

        Feature flag: requires `listing-publishing` to be enabled.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                product_id:
                  type: integer
              example:
                product_id: 87
      parameters:
      - name: draft
        in: path
        schema:
          type: integer
        required: true
        description: Listing draft ID
        example: '42'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      product:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          sku:
                            type: string
                      values:
                        type: object
                        properties:
                          Brand:
                            type: object
                            properties:
                              value:
                                type: string
                              provenance:
                                type: string
                          Color:
                            type: object
                            properties:
                              value:
                                type: string
                              provenance:
                                type: string
                          Size:
                            type: object
                            properties:
                              value:
                                type: string
                                nullable: true
                              provenance:
                                type: string
                example:
                  data:
                    product:
                      id: 87
                      name: Blue Widget - 2 Pack
                      sku: WIDGET-BLUE-2PK
                    values:
                      Brand:
                        value: Acme
                        provenance: override
                      Color:
                        value: Blue
                        provenance: template
                      Size:
                        value: null
                        provenance: blank
        '422':
          description: Unprocessable Content
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      product_id:
                        type: array
                        items:
                          type: string
                example:
                  message: The selected product id is invalid.
                  errors:
                    product_id:
                    - The selected product id is invalid.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-v2-listing-drafts-draft-preview-against-product
  /api/product-listings/{productListing}/get-inventory:
    get:
      tags:
      - Product Listings
      summary: Get Inventory for Product Listing
      description: 'Returns the available inventory for a product listing across all
        warehouses / sales channel inventory locations.


        :::info[Required scope: `products:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: productListing
        in: path
        schema:
          type: integer
        required: true
        description: Product listing ID
        example: '1'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      available:
                        type: integer
                      on_hand:
                        type: integer
                      allocated:
                        type: integer
                      warehouses:
                        type: array
                        items:
                          type: object
                          properties:
                            warehouse_id:
                              type: integer
                            warehouse_name:
                              type: string
                            available:
                              type: integer
                example:
                  data:
                    available: 150
                    on_hand: 200
                    allocated: 50
                    warehouses:
                    - warehouse_id: 1
                      warehouse_name: Main Warehouse
                      available: 100
                    - warehouse_id: 2
                      warehouse_name: East Warehouse
                      available: 50
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: products:read
      operationId: get-api-product-listings-productlisting-get-inventory
  /api/product-listings/{productListing}/link-offering:
    post:
      tags:
      - Product Listings
      summary: Link to Subscription Offering
      description: 'Links a product listing to a subscription offering. Used for subscription-based
        sales channels.


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                subscription_offering_id:
                  type: integer
              example:
                subscription_offering_id: 3
      parameters:
      - name: productListing
        in: path
        schema:
          type: integer
        required: true
        description: Product listing ID
        example: '1'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      product_id:
                        type: integer
                      sales_channel_id:
                        type: integer
                      subscription_offering:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                example:
                  message: Successfully updated Product Listing 1
                  data:
                    id: 1
                    product_id: 42
                    sales_channel_id: 5
                    subscription_offering:
                      id: 3
                      name: Monthly Plan
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: products:write
      operationId: post-api-product-listings-productlisting-link-offering
  /api/product-listings/{productListing}/unlink-offering:
    post:
      tags:
      - Product Listings
      summary: Unlink from Subscription Offering
      description: 'Unlinks a product listing from a subscription offering.


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                product_id:
                  type: integer
              example:
                product_id: 42
      parameters:
      - name: productListing
        in: path
        schema:
          type: integer
        required: true
        description: Product listing ID
        example: '1'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      product_id:
                        type: integer
                      sales_channel_id:
                        type: integer
                      subscription_offering:
                        type: string
                        nullable: true
                example:
                  message: Successfully updated Product Listing 1
                  data:
                    id: 1
                    product_id: 42
                    sales_channel_id: 5
                    subscription_offering: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: products:write
      operationId: post-api-product-listings-productlisting-unlink-offering
  /api/product-listings/{product_listing}:
    get:
      tags:
      - Product Listings
      summary: Show Product Listing
      description: 'Returns a single product listing with its sales channel, integration,
        pricing tier, inventory cache, and document relations loaded. The integration-specific
        resource class is used based on the sales channel.


        :::info[Required scope: `products:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: product_listing
        in: path
        schema:
          type: integer
        required: true
        description: Product listing ID
        example: '1'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: integer
                  product_id:
                    type: integer
                  sales_channel_id:
                    type: integer
                  sales_channel_listing_id:
                    type: string
                  listing_sku:
                    type: string
                  title:
                    type: string
                  master_of_price:
                    type: boolean
                  master_of_stock:
                    type: boolean
                  product_pricing_tier_id:
                    type: string
                    nullable: true
                  sales_channel:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      integration_instance:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          integration:
                            type: object
                            properties:
                              name:
                                type: string
                  inventory_cache:
                    type: object
                    properties:
                      available_quantity:
                        type: integer
                example:
                  id: 1
                  product_id: 42
                  sales_channel_id: 5
                  sales_channel_listing_id: '7823456789012'
                  listing_sku: PROD-001
                  title: Premium Widget
                  master_of_price: true
                  master_of_stock: true
                  product_pricing_tier_id: null
                  sales_channel:
                    id: 5
                    name: Shopify Store
                    integration_instance:
                      id: 2
                      name: My Shopify
                      integration:
                        name: shopify
                  inventory_cache:
                    available_quantity: 150
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: products:read
      operationId: get-api-product-listings-product-listing
    put:
      tags:
      - Product Listings
      summary: Update Product Listing
      description: 'Updates a product listing. If master_of_price or product_pricing_tier_id
        change, the price is pushed to the sales channel. If inventoryLocations is
        provided, inventory is synced to the channel.


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                master_of_price:
                  type: boolean
                master_of_stock:
                  type: boolean
                product_pricing_tier_id:
                  type: integer
                inventoryLocations:
                  type: array
                  items:
                    type: integer
              example:
                master_of_price: true
                master_of_stock: false
                product_pricing_tier_id: 2
                inventoryLocations:
                - 1
                - 2
      parameters:
      - name: product_listing
        in: path
        schema:
          type: integer
        required: true
        description: Product listing ID
        example: '1'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      product_id:
                        type: integer
                      sales_channel_id:
                        type: integer
                      sales_channel_listing_id:
                        type: string
                      listing_sku:
                        type: string
                      master_of_price:
                        type: boolean
                      master_of_stock:
                        type: boolean
                      product_pricing_tier_id:
                        type: integer
                example:
                  message: Successfully updated Product Listing 7823456789012
                  data:
                    id: 1
                    product_id: 42
                    sales_channel_id: 5
                    sales_channel_listing_id: '7823456789012'
                    listing_sku: PROD-001
                    master_of_price: true
                    master_of_stock: false
                    product_pricing_tier_id: 2
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: products:write
      operationId: put-api-product-listings-product-listing
  /api/v2/products/{product}/publish-readiness:
    get:
      tags:
      - Product Listings
      summary: Get Publish-Readiness Snapshot
      description: 'Per-product, multi-channel publish readiness snapshot. Returns
        one entry per publish-capable, connected sales channel, grouped by bucket
        (live / ready / warn / idle / publishing / scheduled / draft) so the publish
        dialog can render confidence groups without orchestrating N parallel calls.


        Read-only: does NOT speculatively create drafts. Channels with no draft and
        no live listing land in `idle` and surface recommended next actions (pick
        a template, create one, etc.).


        Bucket resolution:

        - `live` — a non-archived `ProductListing` exists for this product on the
        channel

        - `ready` — open draft in state `ready`

        - `scheduled` — open draft in state `scheduled`

        - `publishing` — open draft in state `publishing` or `validating`

        - `warn` — open draft in state `error`, OR `draft` with validation errors

        - `draft` — open draft in state `draft` with no validation errors

        - `idle` — no open draft and no live listing


        Authentication: Requires Bearer token.

        Feature flag: requires `listing-publishing` to be enabled.


        **`quantity_to_push`** (int|null, per channel entry) — the stock a publish
        to this channel would seed right now, computed through the same SalesChannelInventoryCalculator
        rules the standing inventory sync uses (max/min/buffer, locations, bundles).
        `null` when quantity seeding is gated off (listing-publishing `push_quantity_on_publish`
        setting disabled, SKU.io not master of stock for the instance, no inventory
        rules configured) or the bucket cannot publish (`live` / `publishing`).'
      parameters:
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: Product ID
        example: '1'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        channel:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            integration_name:
                              type: string
                            integration_instance_id:
                              type: integer
                        bucket:
                          type: string
                        existing_listing:
                          type: string
                          nullable: true
                        draft:
                          type: object
                          properties:
                            id:
                              type: integer
                            state:
                              type: string
                            sales_channel_category_id:
                              type: integer
                            sales_channel_product_template_id:
                              type: integer
                            sales_channel_listing_profile_id:
                              type: integer
                            scheduled_at:
                              type: string
                              nullable: true
                            validation_errors_count:
                              type: integer
                            missing_required:
                              type: array
                            template:
                              type: object
                              properties:
                                id:
                                  type: integer
                                name:
                                  type: string
                            category:
                              type: object
                              properties:
                                id:
                                  type: integer
                                name:
                                  type: string
                                path:
                                  type: string
                            updated_at:
                              type: string
                        available_templates_count:
                          type: integer
                        issues_count:
                          type: integer
                        quantity_to_push:
                          type: integer
                example:
                  data:
                  - channel:
                      id: 12
                      name: My Shopify Store
                      integration_name: Shopify
                      integration_instance_id: 3
                    bucket: ready
                    existing_listing: null
                    draft:
                      id: 88
                      state: ready
                      sales_channel_category_id: 41
                      sales_channel_product_template_id: 5
                      sales_channel_listing_profile_id: 2
                      scheduled_at: null
                      validation_errors_count: 0
                      missing_required: []
                      template:
                        id: 5
                        name: Hoodies — Standard
                      category:
                        id: 41
                        name: Hoodies
                        path: Apparel / Hoodies
                      updated_at: '2026-06-22T14:31:22+00:00'
                    available_templates_count: 3
                    issues_count: 0
                    quantity_to_push: 42
                  - channel:
                      id: 7
                      name: My eBay Store
                      integration_name: Ebay
                      integration_instance_id: 1
                    bucket: warn
                    existing_listing: null
                    draft:
                      id: 92
                      state: draft
                      sales_channel_category_id: 318
                      sales_channel_product_template_id: 11
                      sales_channel_listing_profile_id: null
                      scheduled_at: null
                      validation_errors_count: 3
                      missing_required:
                      - field: Brand
                        label: 'Item Specifics: Brand'
                      - field: Condition
                        label: Item Condition
                      - field: Color
                        label: Color
                      template:
                        id: 11
                        name: eBay Hoodie — Default
                      category:
                        id: 318
                        name: Hoodies
                        path: Clothing / Men / Hoodies
                      updated_at: '2026-06-22T14:18:04+00:00'
                    available_templates_count: 2
                    issues_count: 3
                    quantity_to_push: 42
                  - channel:
                      id: 22
                      name: Walmart US
                      integration_name: Walmart
                      integration_instance_id: 5
                    bucket: idle
                    existing_listing: null
                    draft: null
                    available_templates_count: 0
                    issues_count: 0
                    quantity_to_push: 42
                  - channel:
                      id: 4
                      name: Etsy
                      integration_name: Etsy
                      integration_instance_id: 2
                    bucket: live
                    existing_listing:
                      id: 9412
                      sales_channel_listing_id: '1394820392'
                      listing_sku: AC-HOODIE-BLK-M
                      updated_at: '2026-06-22T14:27:11+00:00'
                    draft: null
                    available_templates_count: 0
                    issues_count: 0
                    quantity_to_push: null
        '403':
          description: Forbidden
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Listing publishing is disabled for this tenant.
        '429': *id001
        '401': *id002
        '404': *id004
      operationId: get-api-v2-products-product-publish-readiness
  /api/v2/listings/coverage:
    get:
      tags:
      - Product Listings
      summary: Get Catalog Coverage Matrix
      description: 'Catalog-wide publish coverage matrix. Returns a paginated list
        of products with per-channel publish state (bucket) for each publish-capable
        connected channel. Returns catalog-wide publish coverage per product across
        channels.


        **One row per product**, with `channels[]` listing all publish-capable channels
        and their current bucket (`live` / `ready` / `warn` / `idle` / `scheduled`
        / `publishing` / `draft`). The `channel_buckets` map is a convenience for
        matrix cell rendering (channel_id → bucket string).


        `totals` aggregates bucket counts across the ENTIRE catalog (every product
        × publish-capable channel) — this is what the summary cards above the matrix
        display. `page_totals` is the same aggregation scoped to only the products
        on the current page (retained for page-level tallies).


        Authentication: Requires Bearer token.

        Feature flag: requires `listing-publishing` to be enabled. `channel_totals`
        breaks the same catalog-wide counts down per channel — each entry lists the
        channel (channel_id, name, integration_name), its total product count, and
        a count in each status bucket.'
      parameters: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        product:
                          type: object
                          properties:
                            id:
                              type: integer
                            sku:
                              type: string
                            name:
                              type: string
                            brand:
                              type: string
                            primary_image_url:
                              type: string
                            product_type:
                              type: string
                            is_bundle:
                              type: boolean
                            bundle_component_count:
                              type: integer
                        channels:
                          type: array
                          items:
                            type: object
                            properties:
                              channel:
                                type: object
                                properties:
                                  id:
                                    type: integer
                                  name:
                                    type: string
                                  integration_name:
                                    type: string
                                  integration_instance_id:
                                    type: integer
                              bucket:
                                type: string
                              existing_listing:
                                type: object
                                properties:
                                  id:
                                    type: integer
                                  sales_channel_listing_id:
                                    type: string
                                  listing_sku:
                                    type: string
                                  updated_at:
                                    type: string
                              draft:
                                type: string
                                nullable: true
                              available_templates_count:
                                type: integer
                              issues_count:
                                type: integer
                        channel_buckets:
                          type: object
                          properties:
                            '3':
                              type: string
                            '25':
                              type: string
                            '26':
                              type: string
                            '30':
                              type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                  first_page_url:
                    type: string
                  last_page_url:
                    type: string
                  next_page_url:
                    type: string
                  prev_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  totals:
                    type: object
                    properties:
                      live:
                        type: integer
                      ready:
                        type: integer
                      warn:
                        type: integer
                      idle:
                        type: integer
                      scheduled:
                        type: integer
                      publishing:
                        type: integer
                      draft:
                        type: integer
                  page_totals:
                    type: object
                    properties:
                      live:
                        type: integer
                      ready:
                        type: integer
                      warn:
                        type: integer
                      idle:
                        type: integer
                      scheduled:
                        type: integer
                      publishing:
                        type: integer
                      draft:
                        type: integer
                  channel_totals:
                    type: array
                    items:
                      type: object
                      properties:
                        channel_id:
                          type: integer
                        name:
                          type: string
                        integration_name:
                          type: string
                        total:
                          type: integer
                        live:
                          type: integer
                        ready:
                          type: integer
                        removed:
                          type: integer
                        warn:
                          type: integer
                        idle:
                          type: integer
                        scheduled:
                          type: integer
                        publishing:
                          type: integer
                        draft:
                          type: integer
                example:
                  data:
                  - product:
                      id: 4
                      sku: BB004
                      name: Baby Bumble Hoodie
                      brand: Baby Bumble
                      primary_image_url: https://cdn.example.com/img/beanie-1.jpg
                      product_type: bundle
                      is_bundle: true
                      bundle_component_count: 3
                    channels:
                    - channel:
                        id: 3
                        name: My Shopify Store
                        integration_name: Shopify
                        integration_instance_id: 1
                      bucket: live
                      existing_listing:
                        id: 9412
                        sales_channel_listing_id: abc123
                        listing_sku: BB004
                        updated_at: '2026-06-22T14:27:11+00:00'
                      draft: null
                      available_templates_count: 2
                      issues_count: 0
                    - channel:
                        id: 25
                        name: Amazon
                        integration_name: Amazon
                        integration_instance_id: 3
                      bucket: ready
                      existing_listing: null
                      draft:
                        id: 88
                        state: ready
                        sales_channel_category_id: 41
                        sales_channel_product_template_id: 5
                        sales_channel_listing_profile_id: null
                        scheduled_at: null
                        validation_errors_count: 0
                        missing_required: []
                        template:
                          id: 5
                          name: Amazon Hoodie — FBA
                        category:
                          id: 41
                          name: Hoodies
                          path: Apparel / Hoodies
                        updated_at: '2026-06-22T14:31:22+00:00'
                      available_templates_count: 4
                      issues_count: 0
                    - channel:
                        id: 30
                        name: eBay Store
                        integration_name: Ebay
                        integration_instance_id: 1
                      bucket: warn
                      existing_listing: null
                      draft:
                        id: 92
                        state: draft
                        sales_channel_category_id: 318
                        sales_channel_product_template_id: 11
                        sales_channel_listing_profile_id: null
                        scheduled_at: null
                        validation_errors_count: 3
                        missing_required:
                        - field: Brand
                          label: Brand
                        - field: Color
                          label: Color
                        - field: Item_Condition
                          label: Item Condition
                        template:
                          id: 11
                          name: eBay Hoodie — Default
                        category:
                          id: 318
                          name: Hoodies
                          path: Clothing / Men / Hoodies
                        updated_at: '2026-06-22T14:18:04+00:00'
                      available_templates_count: 2
                      issues_count: 3
                    - channel:
                        id: 26
                        name: Walmart US
                        integration_name: Walmart
                        integration_instance_id: 5
                      bucket: idle
                      existing_listing: null
                      draft: null
                      available_templates_count: 0
                      issues_count: 0
                    channel_buckets:
                      '3': live
                      '25': ready
                      '26': idle
                      '30': warn
                  current_page: 1
                  last_page: 11
                  per_page: 20
                  total: 218
                  from: 1
                  to: 20
                  first_page_url: https://example.test/api/v2/listings/coverage?page=1
                  last_page_url: https://example.test/api/v2/listings/coverage?page=11
                  next_page_url: https://example.test/api/v2/listings/coverage?page=2
                  prev_page_url: null
                  path: https://example.test/api/v2/listings/coverage
                  totals:
                    live: 130
                    ready: 18
                    warn: 22
                    idle: 46
                    scheduled: 2
                    publishing: 0
                    draft: 0
                  page_totals:
                    live: 41
                    ready: 6
                    warn: 8
                    idle: 25
                    scheduled: 0
                    publishing: 0
                    draft: 0
                  channel_totals:
                  - channel_id: 3
                    name: My Shopify Store
                    integration_name: Shopify
                    total: 109
                    live: 78
                    ready: 9
                    removed: 0
                    warn: 11
                    idle: 10
                    scheduled: 1
                    publishing: 0
                    draft: 0
                  - channel_id: 5
                    name: My eBay Store
                    integration_name: eBay
                    total: 109
                    live: 41
                    ready: 6
                    removed: 0
                    warn: 8
                    idle: 53
                    scheduled: 1
                    publishing: 0
                    draft: 0
        '403':
          description: Forbidden
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Listing publishing is disabled for this tenant.
        '429': *id001
        '401': *id002
      operationId: get-api-v2-listings-coverage
  /api/v2/products/channel-lifecycle/channels:
    get:
      tags:
      - Product Listings
      summary: List Channels for Products
      description: 'List the sales channels the given products are currently listed
        on, with how many of the selected products are listed vs not listed on each
        channel, and whether the channel supports bulk archive / recover / delete.


        Use this to build a channel picker before running a bulk channel action. Pass
        the product ids you want to act on as a repeated `product_ids[]` query parameter.


        `supports_archive` is true when the channel can deactivate a listing; `supports_lifecycle`
        is true when it can also recover (reactivate/restore) and permanently delete
        a listing. TikTok Shop is the first channel to support the full lifecycle.


        Authentication: Requires Bearer token.'
      parameters:
      - name: product_ids[]
        in: query
        schema:
          type: integer
        description: Product id to include (repeat for each product). Required.
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      total_selected:
                        type: integer
                      channels:
                        type: array
                        items:
                          type: object
                          properties:
                            sales_channel_id:
                              type: integer
                            integration_instance_id:
                              type: integer
                            name:
                              type: string
                            integration_name:
                              type: string
                            integration_image_url:
                              type: string
                            listed_count:
                              type: integer
                            not_listed_count:
                              type: integer
                            supports_archive:
                              type: boolean
                            supports_lifecycle:
                              type: boolean
                example:
                  data:
                    total_selected: 2
                    channels:
                    - sales_channel_id: 5
                      integration_instance_id: 12
                      name: TikTok Shop — US
                      integration_name: TikTok Shop
                      integration_image_url: https://cdn.sku.io/integrations/tiktok-shop.png
                      listed_count: 2
                      not_listed_count: 0
                      supports_archive: true
                      supports_lifecycle: true
                    - sales_channel_id: 3
                      integration_instance_id: 7
                      name: Shopify — US
                      integration_name: Shopify
                      integration_image_url: https://cdn.sku.io/integrations/shopify.png
                      listed_count: 1
                      not_listed_count: 1
                      supports_archive: true
                      supports_lifecycle: false
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-v2-products-channel-lifecycle-channels
  /api/v2/products/channel-lifecycle/eligibility:
    get:
      tags:
      - Product Listings
      summary: Get Channel Action Eligibility
      description: 'Return the per-state breakdown of the selected products on a single
        sales channel plus, for each action, how many products are eligible and whether
        the channel supports it.


        `breakdown` counts the selected products by their state on the channel: `live`,
        `pending`, `archived`, `missing`, `unknown`, and `not_listed`. Each entry
        in `actions` reports the action (`publish`, `archive`, `recover`, `delete`),
        its `eligible_count`, whether it is `destructive`, whether it runs as a bulk
        background action here (`dispatchable`), and whether the channel `supported`
        it.


        Only archive, recover and delete are dispatchable; publish is handled by the
        bulk publish flow.


        Authentication: Requires Bearer token.'
      parameters:
      - name: sales_channel_id
        in: query
        schema:
          type: integer
        description: The sales channel to evaluate against. Required.
        example: '5'
      - name: product_ids[]
        in: query
        schema:
          type: integer
        description: Product id to include (repeat for each product). Required.
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      total_selected:
                        type: integer
                      breakdown:
                        type: object
                        properties:
                          live:
                            type: integer
                          pending:
                            type: integer
                          archived:
                            type: integer
                          missing:
                            type: integer
                          unknown:
                            type: integer
                          not_listed:
                            type: integer
                      actions:
                        type: array
                        items:
                          type: object
                          properties:
                            action:
                              type: string
                            label:
                              type: string
                            eligible_count:
                              type: integer
                            destructive:
                              type: boolean
                            dispatchable:
                              type: boolean
                            supported:
                              type: boolean
                example:
                  data:
                    total_selected: 60
                    breakdown:
                      live: 42
                      pending: 0
                      archived: 6
                      missing: 0
                      unknown: 0
                      not_listed: 12
                    actions:
                    - action: publish
                      label: Publish
                      eligible_count: 12
                      destructive: false
                      dispatchable: false
                      supported: true
                    - action: archive
                      label: Archive
                      eligible_count: 42
                      destructive: false
                      dispatchable: true
                      supported: true
                    - action: recover
                      label: Recover
                      eligible_count: 6
                      destructive: false
                      dispatchable: true
                      supported: true
                    - action: delete
                      label: Delete
                      eligible_count: 48
                      destructive: true
                      dispatchable: true
                      supported: true
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-v2-products-channel-lifecycle-eligibility
  /api/v2/products/channel-lifecycle/dispatch:
    post:
      tags:
      - Product Listings
      summary: Run Bulk Channel Action
      description: 'Run a bulk channel action (archive, recover or delete) against
        the eligible listings of the selected products on a sales channel. The action
        runs in the background and the response returns a `tracked_job_log_id` you
        can poll for progress and a per-product success/failure summary.


        Only `archive`, `recover` and `delete` are accepted here — publishing new
        listings uses the bulk publish flow. Products with no eligible listing for
        the chosen action are skipped; the request returns 422 when none of the selected
        products are eligible.


        - `archive` deactivates the listing on the channel (reversible).

        - `recover` reactivates an archived listing or restores a deleted one.

        - `delete` permanently removes the listing from the channel.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                sales_channel_id:
                  type: integer
                action:
                  type: string
                product_ids:
                  type: array
                  items:
                    type: integer
              example:
                sales_channel_id: 5
                action: archive
                product_ids:
                - 1
                - 2
                - 3
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 9174
                  message: Bulk Archive started — track progress with the tracked
                    job log id.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: None of the selected products are eligible for Archive
                    on this channel.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-v2-products-channel-lifecycle-dispatch
  /api/inventory-adjustments/{inventory_adjustment}:
    get:
      tags:
      - Adjustments & Transfers
      summary: Get Inventory Adjustment
      description: 'Retrieve a single inventory adjustment by ID. Loads fifoLayers
        and required list view relations.


        :::info[Required scope: `inventory:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: inventory_adjustment
        in: path
        schema:
          type: integer
        required: true
        description: Inventory adjustment ID
        example: '101'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      adjustment_date:
                        type: string
                      product_id:
                        type: integer
                      sku:
                        type: string
                      product_name:
                        type: string
                      is_lot_tracked:
                        type: boolean
                      lot_tracking_method:
                        type: string
                      shelf_life_days:
                        type: integer
                      near_expiry_threshold_days:
                        type: integer
                      min_remaining_shelf_life_days:
                        type: integer
                      product_average_cost:
                        type: number
                      quantity:
                        type: integer
                      warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      notes:
                        type: string
                      reason:
                        type: string
                        nullable: true
                      is_correction:
                        type: boolean
                      type:
                        type: object
                        properties:
                          link_type:
                            type: string
                            nullable: true
                          link_id:
                            type: string
                            nullable: true
                          parent_link_type:
                            type: string
                            nullable: true
                          parent_link_id:
                            type: string
                            nullable: true
                      reference:
                        type: string
                        nullable: true
                      unit_cost:
                        type: number
                      lots:
                        type: array
                        items:
                          type: object
                          properties:
                            fifo_layer_id:
                              type: integer
                            batch_number:
                              type: string
                            expiry_date:
                              type: string
                            manufacture_date:
                              type: string
                            lot_notes:
                              type: string
                            quantity:
                              type: integer
                      archived_at:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 101
                    adjustment_date: '2024-03-15'
                    product_id: 42
                    sku: SKU-ABC-123
                    product_name: Blue Widget 500ml
                    is_lot_tracked: true
                    lot_tracking_method: fifo
                    shelf_life_days: 180
                    near_expiry_threshold_days: 60
                    min_remaining_shelf_life_days: 105
                    product_average_cost: 12.5
                    quantity: 50
                    warehouse:
                      id: 1
                      name: Main Warehouse
                    notes: Cycle count correction
                    reason: null
                    is_correction: false
                    type:
                      link_type: null
                      link_id: null
                      parent_link_type: null
                      parent_link_id: null
                    reference: null
                    unit_cost: 12.5
                    lots:
                    - fifo_layer_id: 9012
                      batch_number: LOT-2026-0042
                      expiry_date: '2026-07-04'
                      manufacture_date: '2026-01-04'
                      lot_notes: Received from PO-1234
                      quantity: 50
                    archived_at: null
                    created_at: '2024-03-15T14:23:00Z'
                    updated_at: '2024-03-15T14:23:00Z'
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No query results for model [App\Models\InventoryAdjustment]
                    9999
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: inventory:read
      operationId: get-api-inventory-adjustments-inventory-adjustment
    put:
      tags:
      - Adjustments & Transfers
      summary: Update Inventory Adjustment
      description: 'Update an existing inventory adjustment.


        :::info[Required scope: `inventory:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Fields:

        - adjustment_date (optional): Date of adjustment in Y-m-d format

        - warehouse_id (optional): ID of the target warehouse

        - quantity (required): Adjustment quantity (numeric, < 1,000,000, decimals
        supported e.g. 0.5)

        - adjustment_type (optional): One of: increase, decrease

        - unit_cost (optional): Cost per unit (>= 0)

        - notes (optional): Free-text notes

        - warehouse_location_id (optional): Specific location within the warehouse

        - condition (optional): Item condition

        - integration_unique_id (optional): External reference ID


        **Requires permission:** `inventory.adjust`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                adjustment_date:
                  type: string
                warehouse_id:
                  type: integer
                quantity:
                  type: integer
                adjustment_type:
                  type: string
                unit_cost:
                  type: integer
                notes:
                  type: string
                warehouse_location_id:
                  type: string
                  nullable: true
              example:
                adjustment_date: '2024-03-16'
                warehouse_id: 1
                quantity: 75
                adjustment_type: increase
                unit_cost: 13
                notes: 'Updated: corrected quantity'
                warehouse_location_id: null
      parameters:
      - name: inventory_adjustment
        in: path
        schema:
          type: integer
        required: true
        description: Inventory adjustment ID
        example: '101'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      adjustment_date:
                        type: string
                      product_id:
                        type: integer
                      sku:
                        type: string
                      product_name:
                        type: string
                      quantity:
                        type: integer
                      warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      notes:
                        type: string
                      unit_cost:
                        type: number
                      archived_at:
                        type: string
                        nullable: true
                      updated_at:
                        type: string
                example:
                  message: Inventory has been adjusted
                  data:
                    id: 101
                    adjustment_date: '2024-03-16'
                    product_id: 42
                    sku: SKU-ABC-123
                    product_name: Blue Widget 500ml
                    quantity: 75
                    warehouse:
                      id: 1
                      name: Main Warehouse
                    notes: 'Updated: corrected quantity'
                    unit_cost: 13.0
                    archived_at: null
                    updated_at: '2024-03-16T09:00:00Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: inventory:write
      operationId: put-api-inventory-adjustments-inventory-adjustment
    delete:
      tags:
      - Adjustments & Transfers
      summary: Delete Inventory Adjustment
      description: 'Delete an inventory adjustment. Reverses the inventory movement.
        Will fail if doing so would result in negative fulfilled quantities.


        :::info[Required scope: `inventory:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `inventory.adjust`'
      parameters:
      - name: inventory_adjustment
        in: path
        schema:
          type: integer
        required: true
        description: Inventory adjustment ID
        example: '101'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: inventory adjustment 101 has been successfully deleted
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: array
                    items:
                      type: object
                      properties:
                        message:
                          type: string
                        code:
                          type: string
                example:
                  message: Failed to delete inventory adjustment 101
                  errors:
                  - message: The fulfilled quantity would not be covered by existing
                      FIFO layers
                    code: FulfillmentLinked
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: inventory:write
      operationId: delete-api-inventory-adjustments-inventory-adjustment
  /api/inventory-adjustments:
    post:
      tags:
      - Adjustments & Transfers
      summary: Create Inventory Adjustment
      description: 'Create a new inventory adjustment. Supports increase, decrease,
        and set adjustment types.


        :::info[Required scope: `inventory:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Fields:

        - adjustment_date (required): Date of adjustment in Y-m-d format

        - product_id (required): ID of the product to adjust (not bundles/matrix products)

        - warehouse_id (required): ID of the target warehouse (must have a default
        location)

        - quantity (required): Adjustment quantity (numeric, < 1,000,000, decimals
        supported e.g. 0.5). Must be non-zero for increase/decrease

        - adjustment_type (required): One of: increase, decrease, set. Default: increase

        - unit_cost (optional/required for increase/set): Cost per unit (must be >=
        0). Required if product has no average cost

        - notes (optional): Free-text notes

        - warehouse_location_id (optional): Specific location within the warehouse

        - condition (optional): Item condition description

        - integration_unique_id (optional): External reference ID


        Errors: 400 if insufficient stock (for decrease) or protected inventory conflict.


        **Requires permission:** `inventory.adjust`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                adjustment_date:
                  type: string
                product_id:
                  type: integer
                warehouse_id:
                  type: integer
                quantity:
                  type: integer
                adjustment_type:
                  type: string
                unit_cost:
                  type: number
                notes:
                  type: string
                warehouse_location_id:
                  type: string
                  nullable: true
                condition:
                  type: string
                  nullable: true
                integration_unique_id:
                  type: string
                  nullable: true
                lots:
                  type: array
                  items:
                    type: object
                    properties:
                      batch_number:
                        type: string
                      manufacture_date:
                        type: string
                      expiry_date:
                        type: string
                      quantity:
                        type: integer
                      lot_notes:
                        type: string
              example:
                adjustment_date: '2024-03-15'
                product_id: 42
                warehouse_id: 1
                quantity: 50
                adjustment_type: increase
                unit_cost: 12.5
                notes: Cycle count correction
                warehouse_location_id: null
                condition: null
                integration_unique_id: null
                lots:
                - batch_number: LOT-2026-0042
                  manufacture_date: '2026-01-04'
                  expiry_date: '2026-07-04'
                  quantity: 50
                  lot_notes: Received from PO-1234
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      adjustment_date:
                        type: string
                      product_id:
                        type: integer
                      sku:
                        type: string
                      product_name:
                        type: string
                      is_lot_tracked:
                        type: boolean
                      lot_tracking_method:
                        type: string
                      shelf_life_days:
                        type: integer
                      near_expiry_threshold_days:
                        type: integer
                      min_remaining_shelf_life_days:
                        type: integer
                      product_average_cost:
                        type: number
                      quantity:
                        type: integer
                      warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      notes:
                        type: string
                      reason:
                        type: string
                        nullable: true
                      is_correction:
                        type: boolean
                      unit_cost:
                        type: number
                      lots:
                        type: array
                        items:
                          type: object
                          properties:
                            fifo_layer_id:
                              type: integer
                            batch_number:
                              type: string
                            expiry_date:
                              type: string
                            manufacture_date:
                              type: string
                            lot_notes:
                              type: string
                            quantity:
                              type: integer
                      archived_at:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  message: Inventory has been adjusted
                  data:
                    id: 102
                    adjustment_date: '2024-03-15'
                    product_id: 42
                    sku: SKU-ABC-123
                    product_name: Blue Widget 500ml
                    is_lot_tracked: true
                    lot_tracking_method: fifo
                    shelf_life_days: 180
                    near_expiry_threshold_days: 60
                    min_remaining_shelf_life_days: 105
                    product_average_cost: 12.5
                    quantity: 50
                    warehouse:
                      id: 1
                      name: Main Warehouse
                    notes: Cycle count correction
                    reason: null
                    is_correction: false
                    unit_cost: 12.5
                    lots:
                    - fifo_layer_id: 9012
                      batch_number: LOT-2026-0042
                      expiry_date: '2026-07-04'
                      manufacture_date: '2026-01-04'
                      lot_notes: Received from PO-1234
                      quantity: 50
                    archived_at: null
                    created_at: '2024-03-15T14:30:00Z'
                    updated_at: '2024-03-15T14:30:00Z'
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: array
                    items:
                      type: object
                      properties:
                        message:
                          type: string
                        code:
                          type: string
                        field:
                          type: string
                example:
                  errors:
                  - message: Product SKU-ABC-123 does not have enough FIFO layers
                    code: NO_ENOUGH_QUANTITY
                    field: product_id
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      product_id:
                        type: array
                        items:
                          type: string
                      quantity:
                        type: array
                        items:
                          type: string
                example:
                  message: The given data was invalid.
                  errors:
                    product_id:
                    - The product id field is required.
                    quantity:
                    - The quantity must be non-zero for increase/decrease adjustments.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: inventory:write
      operationId: post-api-inventory-adjustments
    delete:
      tags:
      - Adjustments & Transfers
      summary: Bulk Delete Inventory Adjustments
      description: 'Bulk delete multiple inventory adjustments by ID, or delete all
        matching current filters.


        :::info[Required scope: `inventory:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Body: { ids: [integer array] } — specific IDs to delete. Omit ids to delete
        all matching current filters.


        **Requires permission:** `inventory.adjust`'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 3 inventory adjustments deleted successfully
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: inventory:write
      operationId: delete-api-inventory-adjustments
    get:
      tags:
      - Adjustments & Transfers
      summary: List Inventory Adjustments
      description: 'List all inventory adjustments. Supports filtering, sorting, search
        and pagination.


        Authentication: Requires Bearer token.


        Sort fields: id, adjustment_date, quantity, unit_cost, created_at, updated_at.


        table filters: archived (0/1), search, filter[warehouse_id], filter[product_id].'
      parameters:
      - name: archived
        in: query
        schema:
          type: integer
        description: 'Filter by archived status: 0 (active) or 1 (archived). Default:
          0'
        example: '0'
      - name: search
        in: query
        schema:
          type: string
        description: Search across product SKU, product name, notes
      - name: sort
        in: query
        schema:
          type: string
        description: 'Sort field. Prefix with - for descending. Allowed: id, adjustment_date,
          quantity, unit_cost, created_at, updated_at'
        example: -adjustment_date
      - name: page
        in: query
        schema:
          type: integer
        description: Page number for pagination
        example: '1'
      - name: limit
        in: query
        schema:
          type: integer
        description: Number of records per page
        example: '25'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        adjustment_date:
                          type: string
                        product_id:
                          type: integer
                        sku:
                          type: string
                        product_name:
                          type: string
                        product_average_cost:
                          type: number
                        quantity:
                          type: integer
                        warehouse:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        notes:
                          type: string
                        reason:
                          type: string
                          nullable: true
                        is_correction:
                          type: boolean
                        type:
                          type: string
                          nullable: true
                        reference:
                          type: string
                          nullable: true
                        unit_cost:
                          type: number
                        archived_at:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - id: 101
                    adjustment_date: '2024-03-15'
                    product_id: 42
                    sku: SKU-ABC-123
                    product_name: Blue Widget 500ml
                    product_average_cost: 12.5
                    quantity: 50
                    warehouse:
                      id: 1
                      name: Main Warehouse
                    notes: Cycle count correction
                    reason: null
                    is_correction: false
                    type: null
                    reference: null
                    unit_cost: 12.5
                    archived_at: null
                    created_at: '2024-03-15T14:23:00Z'
                    updated_at: '2024-03-15T14:23:00Z'
                  current_page: 1
                  last_page: 5
                  per_page: 25
                  total: 112
                  from: 1
                  to: 25
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-inventory-adjustments
  /api/inventory-adjustments/archive:
    put:
      tags:
      - Adjustments & Transfers
      summary: Bulk Archive Inventory Adjustments
      description: 'Bulk archive multiple inventory adjustments.


        :::info[Required scope: `inventory:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `inventory.adjust`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 101
                - 102
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 2 inventory adjustments archived successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: inventory:write
      operationId: put-api-inventory-adjustments-archive
  /api/inventory-adjustments/unarchive:
    put:
      tags:
      - Adjustments & Transfers
      summary: Bulk Unarchive Inventory Adjustments
      description: 'Bulk unarchive multiple inventory adjustments.


        :::info[Required scope: `inventory:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `inventory.adjust`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 101
                - 102
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 2 inventory adjustments unarchived successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: inventory:write
      operationId: put-api-inventory-adjustments-unarchive
  /api/inventory-adjustments/{adjustment}/archive:
    put:
      tags:
      - Adjustments & Transfers
      summary: Archive Inventory Adjustment
      description: 'Archive a single inventory adjustment.


        :::info[Required scope: `inventory:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `inventory.adjust`'
      requestBody:
        content: {}
      parameters:
      - name: adjustment
        in: path
        schema:
          type: integer
        required: true
        description: Inventory adjustment ID
        example: '101'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      archived_at:
                        type: string
                example:
                  message: inventory adjustment 101 has been archived
                  data:
                    id: 101
                    archived_at: '2024-03-16T10:00:00Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: inventory:write
      operationId: put-api-inventory-adjustments-adjustment-archive
  /api/inventory-adjustments/{adjustment}/unarchived:
    put:
      tags:
      - Adjustments & Transfers
      summary: Unarchive Inventory Adjustment
      description: 'Unarchive a single inventory adjustment.


        :::info[Required scope: `inventory:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `inventory.adjust`'
      requestBody:
        content: {}
      parameters:
      - name: adjustment
        in: path
        schema:
          type: integer
        required: true
        description: Inventory adjustment ID
        example: '101'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      archived_at:
                        type: string
                        nullable: true
                example:
                  message: inventory adjustment 101 has been unarchived
                  data:
                    id: 101
                    archived_at: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: inventory:write
      operationId: put-api-inventory-adjustments-adjustment-unarchived
  /api/inventory-adjustments/deletable:
    post:
      tags:
      - Adjustments & Transfers
      summary: Check Inventory Adjustments Deletable
      description: 'Check which inventory adjustments can be deleted. Returns a deletability
        status for each requested ID.


        :::info[Required scope: `inventory:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Body:

        - ids (required): Array of integer IDs to check


        **Requires permission:** `inventory.adjust`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 101
                - 102
                - 103
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        deletable:
                          type: boolean
                        reason:
                          type: string
                          nullable: true
                example:
                  data:
                  - id: 101
                    deletable: true
                    reason: null
                  - id: 102
                    deletable: false
                    reason:
                      fulfilledQuantity: The fulfilled quantity would not be covered
                  - id: 103
                    deletable: true
                    reason: null
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: inventory:write
      operationId: post-api-inventory-adjustments-deletable
  /api/inventory-adjustments/{inventoryAdjustment}/activity-log:
    get:
      tags:
      - Adjustments & Transfers
      summary: Get Adjustment Activity Log
      description: 'Get paginated activity log for a specific inventory adjustment.
        Includes who made the change and what changed.


        :::info[Required scope: `inventory:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Query parameters:

        - per_page: Number of entries per page (default: 15)

        - filter[search]: Search by causer name, event, or properties

        - page: Page number for pagination'
      parameters:
      - name: per_page
        in: query
        schema:
          type: integer
        description: 'Number of activity log entries per page. Default: 15'
        example: '15'
      - name: inventoryAdjustment
        in: path
        schema:
          type: integer
        required: true
        description: Inventory adjustment ID
        example: '101'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        description:
                          type: string
                        event:
                          type: string
                        subject_type:
                          type: string
                        subject_id:
                          type: integer
                        properties:
                          type: object
                          properties:
                            old:
                              type: object
                              properties:
                                quantity:
                                  type: integer
                            attributes:
                              type: object
                              properties:
                                quantity:
                                  type: integer
                        causer_name:
                          type: string
                        created_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 5001
                    description: updated
                    event: updated
                    subject_type: InventoryAdjustment
                    subject_id: 101
                    properties:
                      old:
                        quantity: 50
                      attributes:
                        quantity: 75
                    causer_name: Jane Smith
                    created_at: '2024-03-16T09:00:00Z'
                  current_page: 1
                  last_page: 1
                  per_page: 15
                  total: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: inventory:read
      operationId: get-api-inventory-adjustments-inventoryadjustment-activity-log
  /api/inventory/fulfillment-debt-report:
    get:
      tags:
      - Inventory
      summary: Get Fulfillment Debt Report
      description: 'Returns a paginated list of fulfillment debt lines — sales order
        lines where fulfilled quantity is less than what was originally ordered.

        Authentication: Requires Bearer token.


        :::info[Required scope: `inventory:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        description: Page number
        example: '1'
      - name: per_page
        in: query
        schema:
          type: integer
        description: Items per page
        example: '25'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        sales_order_id:
                          type: integer
                        order_number:
                          type: string
                        order_date:
                          type: string
                        order_status:
                          type: string
                        fulfillment_status:
                          type: string
                        integration_instance_name:
                          type: string
                        product_id:
                          type: integer
                        sku:
                          type: string
                        product_title:
                          type: string
                        warehouse_id:
                          type: integer
                        warehouse_name:
                          type: string
                        line_quantity:
                          type: integer
                        canceled_quantity:
                          type: integer
                        externally_fulfilled_quantity:
                          type: integer
                        processable_quantity:
                          type: integer
                        fulfilled_quantity:
                          type: integer
                        allocated_quantity:
                          type: number
                        reserved_quantity:
                          type: number
                        debt_quantity:
                          type: integer
                        created_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 500
                    sales_order_id: 12
                    order_number: SO-2024-0042
                    order_date: '2024-01-10T00:00:00Z'
                    order_status: open
                    fulfillment_status: partial
                    integration_instance_name: Shopify Store
                    product_id: 42
                    sku: WIDGET-001
                    product_title: Blue Widget
                    warehouse_id: 1
                    warehouse_name: Main Warehouse
                    line_quantity: 10
                    canceled_quantity: 0
                    externally_fulfilled_quantity: 0
                    processable_quantity: 10
                    fulfilled_quantity: 6
                    allocated_quantity: 4.0
                    reserved_quantity: 4.0
                    debt_quantity: 4
                    created_at: '2024-01-10T08:00:00Z'
                  current_page: 1
                  last_page: 2
                  per_page: 25
                  total: 38
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: inventory:read
      operationId: get-api-inventory-fulfillment-debt-report
  /api/inventory/fulfillment-debt-report/summary:
    get:
      tags:
      - Inventory
      summary: Get Fulfillment Debt Summary
      description: 'Returns aggregated summary totals for the fulfillment debt report
        header cards.

        Authentication: Requires Bearer token.


        :::info[Required scope: `inventory:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      total_debt_quantity:
                        type: integer
                      affected_orders:
                        type: integer
                      affected_products:
                        type: integer
                      total_debt_value:
                        type: number
                example:
                  data:
                    total_debt_quantity: 142
                    affected_orders: 38
                    affected_products: 25
                    total_debt_value: 5230.0
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: inventory:read
      operationId: get-api-inventory-fulfillment-debt-report-summary
  /api/inventory/fulfillment-debt-report/create-stock-take:
    post:
      tags:
      - Inventory
      summary: Create Catch-Up Stock Takes
      description: 'Creates adjustment stock takes in DRAFT status to catch up fulfillment
        debt.

        Authentication: Requires Bearer token.


        :::info[Required scope: `inventory:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Fields:

        - warehouse_id (nullable): Specific warehouse to create stock takes for. If
        omitted, creates for all warehouses.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                warehouse_id:
                  type: integer
              example:
                warehouse_id: 1
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      stock_takes:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            warehouse_id:
                              type: integer
                            warehouse_name:
                              type: string
                            item_count:
                              type: integer
                            status:
                              type: string
                      message:
                        type: string
                example:
                  data:
                    stock_takes:
                    - id: 55
                      warehouse_id: 1
                      warehouse_name: Main Warehouse
                      item_count: 12
                      status: draft
                    message: 1 adjustment stock take(s) created in DRAFT status. Review
                      and finalize to apply.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: inventory:write
      operationId: post-api-inventory-fulfillment-debt-report-create-stock-take
  /api/v2/inventory/holds:
    get:
      tags:
      - Inventory
      summary: List Inventory Holds
      description: 'Returns paginated inventory holds (reservations). By default shows
        active holds (not released, not expired).


        :::info[Required scope: `inventory:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Status filter (resolved from filter_groups, filter[status], or top-level status
        param):

        - active: Not released and not expired (default)

        - partially_released: Has released_quantity > 0 but not fully released yet

        - released: Fully released holds

        - expired: Expired holds

        - expiring_soon: Expiring within the next 7 days

        - all: All holds regardless of status


        Available sorts: id, quantity, released_quantity, created_at, expires_at,
        released_at (default: -created_at)'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        description: 'Page number (default: 1)'
        example: '1'
      - name: per_page
        in: query
        schema:
          type: integer
        description: 'Items per page (default: 10)'
        example: '10'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        product_id:
                          type: integer
                        product:
                          type: object
                          properties:
                            id:
                              type: integer
                            sku:
                              type: string
                            name:
                              type: string
                        warehouse_id:
                          type: integer
                        warehouse:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        quantity:
                          type: integer
                        released_quantity:
                          type: integer
                        reason:
                          type: string
                        reason_label:
                          type: string
                        notes:
                          type: string
                        expires_at:
                          type: string
                        released_at:
                          type: string
                          nullable: true
                        released_by:
                          type: string
                          nullable: true
                        release_reason:
                          type: string
                          nullable: true
                        created_by:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - id: 1
                    product_id: 42
                    product:
                      id: 42
                      sku: WIDGET-001
                      name: Premium Widget
                    warehouse_id: 1
                    warehouse:
                      id: 1
                      name: Main Warehouse
                    quantity: 50
                    released_quantity: 0
                    reason: quality_hold
                    reason_label: Quality Hold
                    notes: Pending QA inspection
                    expires_at: '2024-02-01T00:00:00.000000Z'
                    released_at: null
                    released_by: null
                    release_reason: null
                    created_by:
                      id: 5
                      name: Jane Smith
                    created_at: '2024-01-15T10:00:00.000000Z'
                    updated_at: '2024-01-15T10:00:00.000000Z'
                  current_page: 1
                  last_page: 1
                  per_page: 10
                  total: 1
                  from: 1
                  to: 1
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: inventory:read
      operationId: get-api-v2-inventory-holds
    post:
      tags:
      - Inventory
      summary: Create Inventory Hold
      description: 'Creates a single inventory hold (reservation) for a product in
        a specific warehouse. Deducts from available inventory.


        :::info[Required scope: `inventory:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Request Body:

        - product_id (required, integer): Product to hold

        - warehouse_id (required, integer): Warehouse where inventory is held

        - quantity (required, numeric, min 0.0001): Quantity to hold

        - reason (required, string, max 255): Reason for the hold

        - notes (optional, string): Additional notes

        - expires_at (optional, date, must be future): Expiration date for the hold


        **Requires permission:** `inventory.adjust`


        `notes` is **required** when `reason` is `other`; optional otherwise.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                product_id:
                  type: integer
                warehouse_id:
                  type: integer
                quantity:
                  type: integer
                reason:
                  type: string
                notes:
                  type: string
                expires_at:
                  type: string
              example:
                product_id: 42
                warehouse_id: 1
                quantity: 50
                reason: quality_hold
                notes: Pending QA inspection
                expires_at: '2024-02-01T00:00:00Z'
      parameters: []
      responses:
        '201':
          description: Created
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      product_id:
                        type: integer
                      product:
                        type: object
                        properties:
                          id:
                            type: integer
                          sku:
                            type: string
                          name:
                            type: string
                      warehouse_id:
                        type: integer
                      warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      quantity:
                        type: integer
                      released_quantity:
                        type: integer
                      reason:
                        type: string
                      reason_label:
                        type: string
                      notes:
                        type: string
                      expires_at:
                        type: string
                      released_at:
                        type: string
                        nullable: true
                      created_by:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 5
                    product_id: 42
                    product:
                      id: 42
                      sku: WIDGET-001
                      name: Premium Widget
                    warehouse_id: 1
                    warehouse:
                      id: 1
                      name: Main Warehouse
                    quantity: 50
                    released_quantity: 0
                    reason: quality_hold
                    reason_label: Quality Hold
                    notes: Pending QA inspection
                    expires_at: '2024-02-01T00:00:00.000000Z'
                    released_at: null
                    created_by:
                      id: 5
                      name: Jane Smith
                    created_at: '2024-01-20T10:00:00.000000Z'
                    updated_at: '2024-01-20T10:00:00.000000Z'
                  message: Inventory reservation created successfully.
        '422':
          description: Unprocessable Entity
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: 'Insufficient stock: only 150 units available, but 9999 were
                    requested.'
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: inventory:write
      operationId: post-api-v2-inventory-holds
  /api/v2/inventory/holds/bulk:
    post:
      tags:
      - Inventory
      summary: Bulk Create Inventory Holds
      description: "Creates inventory holds for multiple products in the same warehouse\
        \ in a single request. Up to 100 items per request.\n\n:::info[Required scope:\
        \ `inventory:write`]\nGrant this scope to your token under [Settings → Developer\
        \ → Personal Access Tokens](https://app.sku.io/settings/api).\n:::\n\nAuthentication:\
        \ Requires Bearer token.\n\nRequest Body:\n- warehouse_id (required, integer):\
        \ Warehouse where all items are held\n- reason (required, string, max 255):\
        \ Reason applied to all holds\n- notes (optional, string): Notes applied to\
        \ all holds\n- expires_at (optional, date, must be future): Expiration applied\
        \ to all holds\n- items (required, array, 1-100): Array of items to hold\n\
        \  - items.*.product_id (required, integer): Product ID\n  - items.*.quantity\
        \ (required, numeric, min 0.0001): Quantity to hold\n\n**Requires permission:**\
        \ `inventory.adjust`\n\n`notes` is **required** when `reason` is `other`;\
        \ optional otherwise."
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                warehouse_id:
                  type: integer
                reason:
                  type: string
                notes:
                  type: string
                expires_at:
                  type: string
                items:
                  type: array
                  items:
                    type: object
                    properties:
                      product_id:
                        type: integer
                      quantity:
                        type: integer
              example:
                warehouse_id: 1
                reason: quality_hold
                notes: Batch QA hold
                expires_at: '2024-03-01T00:00:00Z'
                items:
                - product_id: 42
                  quantity: 10
                - product_id: 43
                  quantity: 5
                - product_id: 44
                  quantity: 20
      parameters: []
      responses:
        '201':
          description: Created
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        product_id:
                          type: integer
                        warehouse_id:
                          type: integer
                        quantity:
                          type: integer
                        reason:
                          type: string
                        created_at:
                          type: string
                  errors:
                    type: array
                  message:
                    type: string
                example:
                  data:
                  - id: 6
                    product_id: 42
                    warehouse_id: 1
                    quantity: 10
                    reason: quality_hold
                    created_at: '2024-01-20T10:00:00.000000Z'
                  errors: []
                  message: 1 reservation(s) created.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: inventory:write
      operationId: post-api-v2-inventory-holds-bulk
  /api/v2/inventory/holds/{reservation}:
    get:
      tags:
      - Inventory
      summary: Get Inventory Hold
      description: 'Returns a single inventory hold with full product, warehouse,
        creator, and releaser details.


        :::info[Required scope: `inventory:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: reservation
        in: path
        schema:
          type: integer
        required: true
        description: Inventory hold ID
        example: '1'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      product_id:
                        type: integer
                      product:
                        type: object
                        properties:
                          id:
                            type: integer
                          sku:
                            type: string
                          name:
                            type: string
                      warehouse_id:
                        type: integer
                      warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      quantity:
                        type: integer
                      released_quantity:
                        type: integer
                      reason:
                        type: string
                      reason_label:
                        type: string
                      notes:
                        type: string
                      expires_at:
                        type: string
                      released_at:
                        type: string
                        nullable: true
                      released_by:
                        type: string
                        nullable: true
                      release_reason:
                        type: string
                        nullable: true
                      created_by:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 1
                    product_id: 42
                    product:
                      id: 42
                      sku: WIDGET-001
                      name: Premium Widget
                    warehouse_id: 1
                    warehouse:
                      id: 1
                      name: Main Warehouse
                    quantity: 30
                    released_quantity: 20
                    reason: quality_hold
                    reason_label: Quality Hold
                    notes: Pending QA inspection
                    expires_at: '2024-02-01T00:00:00.000000Z'
                    released_at: null
                    released_by: null
                    release_reason: null
                    created_by:
                      id: 5
                      name: Jane Smith
                    created_at: '2024-01-15T10:00:00.000000Z'
                    updated_at: '2024-01-15T10:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: inventory:read
      operationId: get-api-v2-inventory-holds-reservation
    put:
      tags:
      - Inventory
      summary: Update Inventory Hold
      description: 'Updates an inventory hold''s quantity, notes, or expiration date.


        :::info[Required scope: `inventory:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Request Body:

        - quantity (sometimes, numeric, min 0.0001): New quantity

        - notes (nullable, string): Updated notes

        - expires_at (nullable, date, must be future): New expiration date


        **Requires permission:** `inventory.adjust`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                quantity:
                  type: integer
                notes:
                  type: string
                expires_at:
                  type: string
              example:
                quantity: 30
                notes: Updated notes
                expires_at: '2024-03-01T00:00:00Z'
      parameters:
      - name: reservation
        in: path
        schema:
          type: integer
        required: true
        description: Inventory hold ID
        example: '1'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      product_id:
                        type: integer
                      quantity:
                        type: integer
                      reason:
                        type: string
                      notes:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 1
                    product_id: 42
                    quantity: 30
                    reason: quality_hold
                    notes: Updated notes
                  message: Inventory reservation updated successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: inventory:write
      operationId: put-api-v2-inventory-holds-reservation
    delete:
      tags:
      - Inventory
      summary: Delete Inventory Hold
      description: 'Permanently deletes an inventory hold and returns the quantity
        to available inventory.


        :::info[Required scope: `inventory:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `inventory.adjust`'
      parameters:
      - name: reservation
        in: path
        schema:
          type: integer
        required: true
        description: Inventory hold ID
        example: '1'
      responses:
        '204':
          description: No Content
          content:
            text/plain:
              schema:
                type: string
                example: ''
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: inventory:write
      operationId: delete-api-v2-inventory-holds-reservation
  /api/v2/inventory/holds/{reservation}/release:
    post:
      tags:
      - Inventory
      summary: Release Inventory Hold
      description: 'Releases inventory from a hold. Supports both partial and full
        release.


        :::info[Required scope: `inventory:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Partial release (quantity provided AND less than current held quantity):

        - The hold''s `quantity` is reduced by the released amount

        - `released_quantity` accumulates the cumulative total released across all
        release events

        - `released_at` remains null — the hold is still active


        Full release (quantity omitted, null, 0, or equal to current held quantity):

        - `released_at`, `released_by`, and `release_reason` are populated

        - The remaining `quantity` is added to `released_quantity` so it reflects
        the cumulative total released


        Authentication: Requires Bearer token.


        Request Body:

        - quantity (nullable, numeric, min 0.0001, max=current held quantity): Quantity
        to release. Omit, send null, or send 0 to fully release. Cannot exceed the
        current held quantity (returns 422)

        - release_reason (nullable, string, max 500): Reason for the release


        **Requires permission:** `inventory.adjust`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                quantity:
                  type: integer
                release_reason:
                  type: string
              example:
                quantity: 20
                release_reason: QA inspection passed for partial batch
      parameters:
      - name: reservation
        in: path
        schema:
          type: integer
        required: true
        description: Inventory hold ID
        example: '1'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 Success
                  value:
                    data:
                      id: 1
                      quantity: 30
                      released_quantity: 20
                      released_at: null
                      released_by: null
                      release_reason: QA passed for partial batch
                    message: Inventory reservation released successfully.
                example-1:
                  summary: 200 Full Release
                  value:
                    data:
                      id: 1
                      quantity: 30
                      released_quantity: 50
                      released_at: '2024-01-20T11:00:00.000000Z'
                      released_by:
                        id: 5
                        name: Jane Smith
                      release_reason: QA inspection passed
                    message: Inventory reservation released successfully.
        '422':
          description: Unprocessable Entity
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      quantity:
                        type: array
                        items:
                          type: string
                example:
                  message: The release quantity cannot exceed the held quantity.
                  errors:
                    quantity:
                    - The release quantity cannot exceed the held quantity.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: inventory:write
      operationId: post-api-v2-inventory-holds-reservation-release
  /api/v2/inventory/holds/bulk-release:
    post:
      tags:
      - Inventory
      summary: Bulk Release Inventory Holds
      description: 'Releases multiple inventory holds at once.


        :::info[Required scope: `inventory:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Request Body:

        - ids (required, array): Array of inventory hold IDs to release

        - ids.* (integer): Must exist in inventory_holds table

        - release_reason (nullable, string, max 500): Reason applied to all released
        holds


        **Requires permission:** `inventory.adjust`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
                release_reason:
                  type: string
              example:
                ids:
                - 1
                - 2
                - 3
                release_reason: Batch QA pass
      parameters: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  released:
                    type: integer
                  skipped:
                    type: integer
                example:
                  message: 3 hold(s) released successfully.
                  released: 3
                  skipped: 0
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: inventory:write
      operationId: post-api-v2-inventory-holds-bulk-release
  /api/v2/inventory/holds/bulk-delete:
    post:
      tags:
      - Inventory
      summary: Bulk Delete Inventory Holds
      description: 'Permanently deletes multiple inventory holds.


        :::info[Required scope: `inventory:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Request Body:

        - ids (required, array): Array of inventory hold IDs to delete

        - ids.* (integer): Must exist in inventory_holds table


        **Requires permission:** `inventory.adjust`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 4
                - 5
                - 6
      parameters: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  deleted:
                    type: integer
                example:
                  message: 2 hold(s) deleted successfully.
                  deleted: 2
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: inventory:write
      operationId: post-api-v2-inventory-holds-bulk-delete
  /api/v2/inventory/holds/export:
    get:
      tags:
      - Inventory
      summary: Export Inventory Holds
      description: 'Exports inventory holds as XLSX or CSV file. Columns include:
        ID, SKU, Product Name, Warehouse, Quantity, Reason, Notes, Created By, Created
        At, Expires At, Released At, Archived At.


        :::info[Required scope: `inventory:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Response: File download (binary), not JSON.


        **Requires permission:** `inventory.export`'
      parameters:
      - name: format
        in: query
        schema:
          type: string
        description: 'Export format: xlsx or csv (default: xlsx)'
        example: xlsx
      - name: scope
        in: query
        schema:
          type: string
        description: 'Export scope: filtered (default) or selected'
        example: filtered
      responses:
        '200':
          description: OK
          content:
            text/plain:
              schema:
                type: string
                example: '[Binary XLSX file download]'
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: inventory:read
      operationId: get-api-v2-inventory-holds-export
  /api/v2/inventory/holds/reasons:
    get:
      tags:
      - Inventory
      summary: Get Hold Reasons
      description: 'Returns all distinct non-null reasons used across inventory holds,
        sorted alphabetically. Useful for populating filter dropdowns.


        :::info[Required scope: `inventory:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: string
                example:
                  data:
                  - damaged
                  - other
                  - quality_hold
                  - reserved_for_event
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: inventory:read
      operationId: get-api-v2-inventory-holds-reasons
  /api/v2/inventory/holds/summary:
    get:
      tags:
      - Inventory
      summary: Get Holds Summary
      description: 'Returns aggregated summary statistics for inventory holds.


        :::info[Required scope: `inventory:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      total_active:
                        type: integer
                      total_quantity_held:
                        type: integer
                      expiring_soon:
                        type: integer
                      expired:
                        type: integer
                example:
                  data:
                    total_active: 24
                    total_quantity_held: 1250
                    expiring_soon: 3
                    expired: 1
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: inventory:read
      operationId: get-api-v2-inventory-holds-summary
  /api/v2/inventory/holds/warehouse-availability:
    post:
      tags:
      - Inventory
      summary: Check Warehouse Availability
      description: 'Returns the available inventory for a batch of products in a specific
        warehouse. Used by the Reserve Stock modal browse drawer.


        :::info[Required scope: `inventory:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Request Body:

        - product_ids (required, array, max 100): Product IDs to check availability
        for

        - product_ids.* (integer): Product ID

        - warehouse_id (required, integer): Warehouse to check availability in'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                product_ids:
                  type: array
                  items:
                    type: integer
                warehouse_id:
                  type: integer
              example:
                product_ids:
                - 42
                - 43
                - 44
                warehouse_id: 1
      parameters: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      '42':
                        type: object
                        properties:
                          available:
                            type: integer
                      '43':
                        type: object
                        properties:
                          available:
                            type: integer
                example:
                  data:
                    '42':
                      available: 150
                    '43':
                      available: 0
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: inventory:write
      operationId: post-api-v2-inventory-holds-warehouse-availability
  /api/v2/inventory/location-quantities:
    get:
      tags:
      - Inventory
      summary: List Location Quantities
      description: 'Paginated per-(product, warehouse, location) on-hand balances
        from the incrementally-maintained inventory_location_quantities cache (stock
        by location).


        Authentication: Requires Bearer token.

        Scope: inventory (read/write).

        Requires the tenant to have warehouse locations enabled.


        Filters (Spatie QueryBuilder `filter[...]`):

        - warehouse_id (exact)

        - warehouse_location_id (exact)

        - product_id (exact)

        - location_type (exact or comma-separated; one of: staging, primary_pick,
        reserve, storage, shipping, returns, quarantine, damaged)

        - search (product sku/name + location code)


        Available sorts: id, quantity, product_id, warehouse_id, warehouse_location_id,
        updated_at (default: -quantity).

        per_page is clamped to a max of 100 (default 10).'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        description: 'Page number (default: 1)'
        example: '1'
      - name: per_page
        in: query
        schema:
          type: integer
        description: 'Items per page (default: 10, max: 100)'
        example: '10'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        product:
                          type: object
                          properties:
                            id:
                              type: integer
                            sku:
                              type: string
                            name:
                              type: string
                        warehouse:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        location:
                          type: object
                          properties:
                            id:
                              type: integer
                            code:
                              type: string
                            name:
                              type: string
                            type:
                              type: string
                            type_label:
                              type: string
                        quantity:
                          type: integer
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - id: 501
                    product:
                      id: 42
                      sku: WIDGET-001
                      name: Premium Widget
                    warehouse:
                      id: 1
                      name: Main Warehouse
                    location:
                      id: 12
                      code: A1-B2-S3-BIN4
                      name: Aisle 1 Bay 2 Shelf 3 Bin 4
                      type: storage
                      type_label: Storage
                    quantity: 42
                  current_page: 1
                  last_page: 1
                  per_page: 10
                  total: 1
                  from: 1
                  to: 1
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-v2-inventory-location-quantities
  /api/v2/inventory/location-quantities/export:
    get:
      tags:
      - Inventory
      summary: Export Location Quantities
      description: 'Export the filtered per-location balances as a CSV or XLSX file
        download (columns: SKU, Product Name, Warehouse, Location Code, Location Name,
        Location Type, Quantity). Applies the same filter pipeline as the index endpoint.
        Returns a binary file, NOT JSON.


        The export must be scoped to a warehouse or a product: supply filter[warehouse_id]
        or filter[product_id] (either one satisfies the requirement). A request with
        neither returns 422 Unprocessable Entity.


        Authentication: Requires Bearer token.

        Scope: inventory (read/write).

        Additional permission required: `inventory.export`.


        Query params:

        - filter[warehouse_id] (required unless filter[product_id] given)

        - filter[product_id] (required unless filter[warehouse_id] given)

        - format (optional: csv | xlsx, default csv)

        - plus any other filter[...] accepted by the index endpoint


        **Requires permission:** `inventory.export`'
      parameters:
      - name: filter[warehouse_id]
        in: query
        schema:
          type: integer
        description: Warehouse ID to export. Required unless filter[product_id] is
          supplied — the export must be scoped to a warehouse or a product.
        example: '1'
      responses:
        '200':
          description: OK
          content:
            text/plain:
              schema:
                type: string
                example: '[Binary CSV file download: location-quantities-YYYY-MM-DD-HH-mm-ss.csv]'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      filter.warehouse_id:
                        type: array
                        items:
                          type: string
                      filter.product_id:
                        type: array
                        items:
                          type: string
                example:
                  message: Scope the export with filter[warehouse_id] or filter[product_id].
                  errors:
                    filter.warehouse_id:
                    - Scope the export with filter[warehouse_id] or filter[product_id].
                    filter.product_id:
                    - Scope the export with filter[warehouse_id] or filter[product_id].
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-v2-inventory-location-quantities-export
  /api/v2/inventory-allocations:
    get:
      tags:
      - Adjustments & Transfers
      summary: List Allocations
      description: 'Returns a paginated list of inventory allocations.


        :::info[Required scope: `inventory:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        **Simple filters** (`filter[status]`): Sentinel values control the list scope:

        - `active` (default) — pending + released allocations

        - `all` — every status

        - `pending`, `released`, `cancelled`, `fulfilled` — specific status


        **Advanced filters** (`filter_groups`): Tree-based GroupedFilterSupport filters
        on id, quantity, priority, status, warehouse_id, supplier_id, created_at,
        fulfilled_at, cancelled_at, product_sku, product_name. The `filter[search]`
        parameter is a cross-column search.


        **Sort options**: id, quantity, priority, status, created_at. Default: `-created_at`.


        The response also includes `unfiltered_total`, the count of rows in the base
        scope before any user filters are applied — used by the frontend to show export
        totals.'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        example: '1'
        description: Page number (default 1).
      - name: per_page
        in: query
        schema:
          type: integer
        example: '10'
        description: Results per page (default 10).
      - name: filter[search]
        in: query
        schema:
          type: string
        description: Search across id, sku, product name, and source reference
      - name: filter[warehouse_id]
        in: query
        schema:
          type: string
        description: Exact match on warehouse ID
      - name: filter[supplier_id]
        in: query
        schema:
          type: string
        description: Exact match on supplier ID
      - name: filter[product_id]
        in: query
        schema:
          type: string
        description: Exact match on product ID
      - name: filter[status]
        in: query
        schema:
          type: string
        description: 'Sentinel: all | active (default) | pending | released | cancelled
          | fulfilled'
        example: active
      - name: filter[id]
        in: query
        schema:
          type: string
        description: Numeric filter on id
      - name: filter[quantity]
        in: query
        schema:
          type: string
        description: Numeric filter on quantity
      - name: filter[priority]
        in: query
        schema:
          type: string
        description: Numeric filter on priority
      - name: filter[created_at]
        in: query
        schema:
          type: string
        description: Datetime filter on created_at
      - name: filter[fulfilled_at]
        in: query
        schema:
          type: string
        description: Datetime filter on fulfilled_at
      - name: filter[cancelled_at]
        in: query
        schema:
          type: string
        description: Datetime filter on cancelled_at
      - name: filter[product_sku]
        in: query
        schema:
          type: string
        description: Text filter on product SKU
      - name: filter[product_name]
        in: query
        schema:
          type: string
        description: Text filter on product name
      - name: filter_groups[conjunction]
        in: query
        schema:
          type: string
        description: 'Advanced filter tree conjunction: and | or. Use with filter_groups[children][]
          for grouped conditions.'
        example: and
      - name: sort
        in: query
        schema:
          type: string
        description: 'Sort field. Prefix with - for descending. Options: id, quantity,
          priority, status, created_at'
        example: -created_at
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        product_id:
                          type: integer
                        product:
                          type: object
                          properties:
                            id:
                              type: integer
                            sku:
                              type: string
                            name:
                              type: string
                        warehouse_id:
                          type: integer
                        warehouse:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        link_id:
                          type: integer
                        link_type:
                          type: string
                        link_type_label:
                          type: string
                        link_route:
                          type: string
                        link_reference:
                          type: string
                        date:
                          type: string
                        quantity:
                          type: integer
                        status:
                          type: string
                        status_label:
                          type: string
                        priority:
                          type: integer
                        supplier_id:
                          type: integer
                        supplier:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        purchase_order_line_id:
                          type: string
                          nullable: true
                        is_tight_coverage:
                          type: boolean
                        release_source_id:
                          type: string
                          nullable: true
                        release_source_type:
                          type: string
                          nullable: true
                        fulfilled_at:
                          type: string
                          nullable: true
                        cancelled_at:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  unfiltered_total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - id: 10045
                    product_id: 812
                    product:
                      id: 812
                      sku: WIDGET-BLU
                      name: Blue Widget
                    warehouse_id: 3
                    warehouse:
                      id: 3
                      name: East Coast DC
                    link_id: 55347
                    link_type: App\Models\SalesOrderLine
                    link_type_label: Sales Order Line
                    link_route: /sales-orders/9821
                    link_reference: SO-9821
                    date: '2025-04-10'
                    quantity: 5
                    status: pending
                    status_label: Pending
                    priority: 1
                    supplier_id: 14
                    supplier:
                      id: 14
                      name: Acme Corp
                    purchase_order_line_id: null
                    is_tight_coverage: false
                    release_source_id: null
                    release_source_type: null
                    fulfilled_at: null
                    cancelled_at: null
                    created_at: '2025-04-10T08:22:11.000000Z'
                    updated_at: '2025-04-10T08:22:11.000000Z'
                  current_page: 1
                  last_page: 12
                  per_page: 10
                  total: 118
                  unfiltered_total: 947
                  from: 1
                  to: 10
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: inventory:read
      operationId: get-api-v2-inventory-allocations
  /api/v2/inventory-allocations/{allocation}:
    get:
      tags:
      - Adjustments & Transfers
      summary: Get Allocation
      description: 'Returns a single inventory allocation by ID.


        :::info[Required scope: `inventory:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        warehouse_location_id and the nested warehouse_location object reflect the
        bin this allocation is pinned to (null when not pinned). warehouse.locations_enabled
        indicates whether the warehouse uses bin locations.'
      parameters:
      - name: allocation
        in: path
        schema:
          type: integer
        required: true
        description: Allocation ID
        example: '10045'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: integer
                  product_id:
                    type: integer
                  product:
                    type: object
                    properties:
                      id:
                        type: integer
                      sku:
                        type: string
                      name:
                        type: string
                  warehouse_id:
                    type: integer
                  warehouse:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      locations_enabled:
                        type: boolean
                  warehouse_location_id:
                    type: integer
                  warehouse_location:
                    type: object
                    properties:
                      id:
                        type: integer
                      code:
                        type: string
                      name:
                        type: string
                  link_id:
                    type: integer
                  link_type:
                    type: string
                  link_type_label:
                    type: string
                  link_route:
                    type: string
                  link_reference:
                    type: string
                  date:
                    type: string
                  quantity:
                    type: integer
                  status:
                    type: string
                  status_label:
                    type: string
                  priority:
                    type: integer
                  supplier_id:
                    type: integer
                  supplier:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                  purchase_order_line_id:
                    type: string
                    nullable: true
                  is_tight_coverage:
                    type: boolean
                  release_source_id:
                    type: string
                    nullable: true
                  release_source_type:
                    type: string
                    nullable: true
                  fulfilled_at:
                    type: string
                    nullable: true
                  cancelled_at:
                    type: string
                    nullable: true
                  created_at:
                    type: string
                  updated_at:
                    type: string
                example:
                  id: 10045
                  product_id: 812
                  product:
                    id: 812
                    sku: WIDGET-BLU
                    name: Blue Widget
                  warehouse_id: 3
                  warehouse:
                    id: 3
                    name: East Coast DC
                    locations_enabled: true
                  warehouse_location_id: 402
                  warehouse_location:
                    id: 402
                    code: ST-09
                    name: Reserve Aisle 9
                  link_id: 55347
                  link_type: App\Models\SalesOrderLine
                  link_type_label: Sales Order Line
                  link_route: /sales-orders/9821
                  link_reference: SO-9821
                  date: '2025-04-10'
                  quantity: 5
                  status: pending
                  status_label: Pending
                  priority: 1
                  supplier_id: 14
                  supplier:
                    id: 14
                    name: Acme Corp
                  purchase_order_line_id: null
                  is_tight_coverage: false
                  release_source_id: null
                  release_source_type: null
                  fulfilled_at: null
                  cancelled_at: null
                  created_at: '2025-04-10T08:22:11.000000Z'
                  updated_at: '2025-04-10T08:22:11.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: inventory:read
      operationId: get-api-v2-inventory-allocations-allocation
  /api/v2/inventory-allocations/{allocation}/reorder:
    post:
      tags:
      - Adjustments & Transfers
      summary: Reorder Allocation
      description: 'Reorders an allocation relative to another.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        **Body**:

        - `reorder_type` — `above` | `below` | `top` | `bottom`

        - `options.above_id` — ID of the allocation to place this one above (used
        when reorder_type is `above`)'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                reorder_type:
                  type: string
                options:
                  type: object
                  properties:
                    above_id:
                      type: integer
              example:
                reorder_type: above
                options:
                  above_id: 10040
      parameters:
      - name: allocation
        in: path
        schema:
          type: integer
        required: true
        description: Allocation ID
        example: '10045'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Allocation reordered successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: orders:write
      operationId: post-api-v2-inventory-allocations-allocation-reorder
  /api/v2/inventory-allocations/{allocation}/reassign-coverage:
    post:
      tags:
      - Adjustments & Transfers
      summary: Reassign Coverage
      description: 'Manually (re)assigns a single allocation''s PO-line coverage.
        Binding a PO line transitions the allocation to `AwaitingReceipt` and pins
        it as tight coverage (so a later automatic rebalance won''t move it).


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        **Body**:

        - `purchase_order_line_id` (required, nullable integer) — the PO line to cover
        this allocation with. Pass `null` to clear coverage and revert the allocation
        to `Planned`.


        Returns `422` when the PO line belongs to a different product, or the PO is
        draft/closed/cancelled/voided, or the line is already fully received.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                purchase_order_line_id:
                  type: integer
              example:
                purchase_order_line_id: 5567
      parameters:
      - name: allocation
        in: path
        schema:
          type: integer
        required: true
        description: Allocation ID
        example: '10045'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      priority:
                        type: integer
                      backorder_date:
                        type: string
                      backordered_quantity:
                        type: integer
                      quantity:
                        type: integer
                      status:
                        type: string
                      status_label:
                        type: string
                      is_tight_coverage:
                        type: boolean
                      sales_order:
                        type: object
                        properties:
                          id:
                            type: integer
                          number:
                            type: string
                          order_date:
                            type: string
                      sku:
                        type: object
                        properties:
                          id:
                            type: integer
                          sku:
                            type: string
                          name:
                            type: string
                      supplier:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      coverage:
                        type: object
                        properties:
                          purchase_order_line_id:
                            type: integer
                          purchase_order_id:
                            type: integer
                          purchase_order_number:
                            type: string
                          covered_quantity:
                            type: integer
                          is_tight:
                            type: boolean
                      scheduled_at:
                        type: string
                      created_at:
                        type: string
                example:
                  data:
                    id: 10045
                    priority: 3
                    backorder_date: '2026-05-10T14:22:00.000000Z'
                    backordered_quantity: 8
                    quantity: 8
                    status: awaiting_receipt
                    status_label: Awaiting Receipt
                    is_tight_coverage: true
                    sales_order:
                      id: 33021
                      number: SO-033021
                      order_date: '2026-05-08'
                    sku:
                      id: 812
                      sku: WIDGET-BLU
                      name: Blue Widget
                    supplier:
                      id: 47
                      name: Acme Supplies
                    coverage:
                      purchase_order_line_id: 5567
                      purchase_order_id: 902
                      purchase_order_number: PO-000902
                      covered_quantity: 8
                      is_tight: true
                    scheduled_at: '2026-05-20'
                    created_at: '2026-05-10T14:22:00.000000Z'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: Purchase order line 5567 is for a different product.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:write
      operationId: post-api-v2-inventory-allocations-allocation-reassign-coverage
  /api/v2/inventory-allocations/{allocation}/move-targets:
    get:
      tags:
      - Adjustments & Transfers
      summary: Get Move Targets
      description: 'Lists the candidate destination sales order lines that on-hand
        (`allocated`) stock from this allocation can be moved to.


        :::info[Required scope: `orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Returns the backordered lines (status `planned` / `awaiting_receipt`) waiting
        on the **same product and warehouse pool** as the source allocation, excluding
        the source''s own line. Each entry includes how much of that line is still
        backordered, so the caller can cap the move quantity.


        Returns an empty list when the allocation is not `allocated`, is not linked
        to a sales order line, or there are no other backordered lines in the pool.'
      parameters:
      - name: allocation
        in: path
        schema:
          type: integer
        required: true
        description: Allocation ID (must be an on-hand `allocated` allocation linked
          to a sales order line)
        example: '10045'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        sales_order_line_id:
                          type: integer
                        sales_order_id:
                          type: integer
                        sales_order_number:
                          type: string
                        customer_id:
                          type: integer
                        customer_name:
                          type: string
                        order_date:
                          type: string
                        backordered_quantity:
                          type: integer
                example:
                  data:
                  - sales_order_line_id: 55512
                    sales_order_id: 33099
                    sales_order_number: SO-033099
                    customer_id: 33099
                    customer_name: Acme Retail
                    order_date: '2026-05-12'
                    backordered_quantity: 4
                  - sales_order_line_id: 55540
                    sales_order_id: 33104
                    sales_order_number: SO-033104
                    customer_id: 33104
                    customer_name: Blue Mountain Co
                    order_date: '2026-05-13'
                    backordered_quantity: 2
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:read
      operationId: get-api-v2-inventory-allocations-allocation-move-targets
  /api/v2/inventory-allocations/{allocation}/move:
    post:
      tags:
      - Adjustments & Transfers
      summary: Move To Line
      description: 'Moves on-hand (`allocated`) stock from this allocation to a backordered
        line in the same product + warehouse pool — a **conserved swap**.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        The moved quantity releases the destination line''s backorder (`planned` /
        `awaiting_receipt` → `allocated`), carrying the source allocation''s FIFO
        `release_source` reference. The source''s `allocated` row is reduced by the
        same quantity (or cancelled if fully consumed), and the source''s demand is
        recreated as a `planned` backorder. Total on-hand commitment, total demand,
        and FIFO cost layering are all preserved.


        **Body**:

        - `destination_sales_order_line_id` (required, integer) — the backordered
        sales order line to move stock to. Must exist and be in the same product +
        warehouse pool. Get valid targets from `GET /move-targets`.

        - `quantity` (required, numeric, > 0) — how much on-hand stock to move. Must
        not exceed the source''s movable on-hand quantity (allocated minus any stock
        committed to open fulfillments) nor the destination line''s backordered quantity.


        Returns `422` when the source is not `allocated`, the destination is a different
        product/warehouse or the same line, the quantity exceeds the movable on-hand
        stock (e.g. committed to an open fulfillment) or the destination''s backorder,
        or the destination has no matching backorder to release.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                destination_sales_order_line_id:
                  type: integer
                quantity:
                  type: integer
              example:
                destination_sales_order_line_id: 55512
                quantity: 4
      parameters:
      - name: allocation
        in: path
        schema:
          type: integer
        required: true
        description: Source allocation ID (must be an on-hand `allocated` allocation
          linked to a sales order line)
        example: '10045'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      priority:
                        type: integer
                      backorder_date:
                        type: string
                        nullable: true
                      backordered_quantity:
                        type: integer
                      quantity:
                        type: integer
                      status:
                        type: string
                      status_label:
                        type: string
                      is_tight_coverage:
                        type: boolean
                      sales_order:
                        type: object
                        properties:
                          id:
                            type: integer
                          number:
                            type: string
                          order_date:
                            type: string
                      sku:
                        type: object
                        properties:
                          id:
                            type: integer
                          sku:
                            type: string
                          name:
                            type: string
                      supplier:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      coverage:
                        type: string
                        nullable: true
                      scheduled_at:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                example:
                  data:
                    id: 10072
                    priority: 2
                    backorder_date: null
                    backordered_quantity: 0
                    quantity: 4
                    status: allocated
                    status_label: Allocated
                    is_tight_coverage: false
                    sales_order:
                      id: 33099
                      number: SO-033099
                      order_date: '2026-05-12'
                    sku:
                      id: 812
                      sku: WIDGET-BLU
                      name: Blue Widget
                    supplier:
                      id: 47
                      name: Acme Supplies
                    coverage: null
                    scheduled_at: null
                    created_at: '2026-06-15T09:14:00.000000Z'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: Cannot move more than the available on-hand quantity. 3 units
                    are committed to an open fulfillment.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:write
      operationId: post-api-v2-inventory-allocations-allocation-move
  /api/v2/inventory-allocations/pull-stock-donors:
    get:
      tags:
      - Adjustments & Transfers
      summary: List Pull-Stock Donors
      description: 'Lists the sales order lines a backordered line can pull on-hand
        stock from. Returns other sales orders holding **soft** allocations (`allocated`,
        not yet committed to a printed shipping label) of the same product in the
        same warehouse pool, excluding the backordered line''s own sales order.


        Each donor entry reports `movable_quantity` (soft on-hand that can be pulled)
        and `priority` (lower number = higher priority), ordered least-urgent first
        so the safest donors appear at the top.


        Query:

        - `destination_sales_order_line_id` (required, integer) — the backordered
        sales order line that would receive the stock.


        Returns an empty list when no other order in the pool holds soft-allocated
        stock.'
      parameters:
      - name: destination_sales_order_line_id
        in: query
        schema:
          type: integer
        description: Required. The backordered sales order line that would receive
          the pulled stock.
        example: '55600'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        sales_order_line_id:
                          type: integer
                        sales_order_id:
                          type: integer
                        sales_order_number:
                          type: string
                        customer_id:
                          type: integer
                        customer_name:
                          type: string
                        order_date:
                          type: string
                        priority:
                          type: integer
                        movable_quantity:
                          type: integer
                example:
                  data:
                  - sales_order_line_id: 55540
                    sales_order_id: 33104
                    sales_order_number: SO-033104
                    customer_id: 44011
                    customer_name: Blue Mountain Co
                    order_date: '2026-05-13'
                    priority: 8
                    movable_quantity: 5
                  - sales_order_line_id: 55512
                    sales_order_id: 33099
                    sales_order_number: SO-033099
                    customer_id: 44011
                    customer_name: Acme Retail
                    order_date: '2026-05-12'
                    priority: 3
                    movable_quantity: 2
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-v2-inventory-allocations-pull-stock-donors
  /api/v2/inventory-allocations/pull-stock:
    post:
      tags:
      - Adjustments & Transfers
      summary: Pull Stock To Line
      description: 'Pulls soft on-hand stock from one or more donor sales order lines
        onto a backordered line, atomically. Each donor''s soft allocation is backordered
        by the pulled quantity and the freed on-hand is allocated to the destination
        line — a **conserved swap** that preserves total demand and FIFO cost layering
        across every affected order. All pulls succeed or roll back together.


        **Body**:

        - `destination_sales_order_line_id` (required, integer) — the backordered
        line that receives the stock.

        - `pulls` (required, array, min 1) — the donors to pull from.

        - `pulls[].sales_order_line_id` (required, integer) — a donor sales order
        line holding soft allocations of the same product + warehouse. Get valid donors
        from `GET /pull-stock-donors`.

        - `pulls[].quantity` (required, numeric, > 0) — how much soft on-hand to pull
        from that donor.


        Returns `422` when a donor no longer holds enough soft-allocated stock, a
        donor is the same line as the destination, or the destination has no matching
        backorder to receive the pull.


        On success returns the total `pulled_quantity` and the refreshed donor list.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                destination_sales_order_line_id:
                  type: integer
                pulls:
                  type: array
                  items:
                    type: object
                    properties:
                      sales_order_line_id:
                        type: integer
                      quantity:
                        type: integer
              example:
                destination_sales_order_line_id: 55600
                pulls:
                - sales_order_line_id: 55540
                  quantity: 2
                - sales_order_line_id: 55512
                  quantity: 1
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      pulled_quantity:
                        type: integer
                      donors:
                        type: array
                        items:
                          type: object
                          properties:
                            sales_order_line_id:
                              type: integer
                            sales_order_id:
                              type: integer
                            sales_order_number:
                              type: string
                            customer_id:
                              type: integer
                            customer_name:
                              type: string
                            order_date:
                              type: string
                            priority:
                              type: integer
                            movable_quantity:
                              type: integer
                example:
                  data:
                    pulled_quantity: 3
                    donors:
                    - sales_order_line_id: 55540
                      sales_order_id: 33104
                      sales_order_number: SO-033104
                      customer_id: 44011
                      customer_name: Blue Mountain Co
                      order_date: '2026-05-13'
                      priority: 8
                      movable_quantity: 3
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: One of the selected orders no longer holds enough soft-allocated
                    stock to pull. Please refresh and try again.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-v2-inventory-allocations-pull-stock
  /api/v2/inventory-allocations/{inventoryAllocation}/pin-bin:
    put:
      tags:
      - Adjustments & Transfers
      summary: Reserve Allocation to Bin
      description: 'Hard-reserve an allocation''s stock to a specific bin so it''s
        held there for its order and picked from there.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                warehouse_location_id:
                  type: integer
              example:
                warehouse_location_id: 16
      parameters:
      - name: inventoryAllocation
        in: path
        schema:
          type: string
        required: true
        description: The inventory allocation ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      warehouse_location_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    id: 221
                    warehouse_location_id: 16
                  message: Stock reserved to the bin.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: Bin ST-02 holds 3 but the reservation needs 5.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: put-api-v2-inventory-allocations-inventoryallocation-pin-bin
    delete:
      tags:
      - Adjustments & Transfers
      summary: Clear Bin Reservation
      description: 'Clear an allocation''s hard bin reservation.


        Authentication: Requires Bearer token.'
      parameters:
      - name: inventoryAllocation
        in: path
        schema:
          type: string
        required: true
        description: The inventory allocation ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      warehouse_location_id:
                        type: string
                        nullable: true
                  message:
                    type: string
                example:
                  data:
                    id: 221
                    warehouse_location_id: null
                  message: Bin reservation cleared.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-v2-inventory-allocations-inventoryallocation-pin-bin
  /api/v2/inventory-allocations/backorders:
    get:
      tags:
      - Adjustments & Transfers
      summary: List Backorders
      description: 'Returns a paginated backorder queue showing allocations that are
        awaiting stock.


        :::info[Required scope: `orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        **Supports GET and POST** — POST can be used to send large filter payloads
        in the request body.


        **Sort options**: id, priority, quantity, created_at, updated_at, backorder_date,
        backordered_quantity, released_quantity, sku, product_name, supplier, order_date,
        sales_order_number, eta. Default: `priority`.


        Each backorder row also carries `in_transit_stock` (inbound stock in motion
        across warehouses), alongside `other_warehouse_stock`. Both are populated
        in the CSV/XLSX export.'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        example: '1'
        description: Page number (default 1).
      - name: per_page
        in: query
        schema:
          type: integer
        example: '10'
        description: Results per page (default 10).
      - name: filter[search]
        in: query
        schema:
          type: string
        description: Search across id, sku, product name, supplier name, sales order
          number, PO number
      - name: filter[status]
        in: query
        schema:
          type: string
        description: 'Backorder status: pending | released | partial | cancelled'
      - name: filter[supplier_id]
        in: query
        schema:
          type: string
        description: Filter by supplier ID
      - name: filter[covered_by_po]
        in: query
        schema:
          type: string
        description: true | false — filter by whether the backorder is covered by
          a PO
      - name: filter[eta_state]
        in: query
        schema:
          type: string
        description: on_time | late | unknown
      - name: filter[sku]
        in: query
        schema:
          type: string
        description: Text filter on product SKU
      - name: filter[product_name]
        in: query
        schema:
          type: string
        description: Text filter on product name
      - name: filter[supplier_name]
        in: query
        schema:
          type: string
        description: Text filter on supplier name
      - name: filter[quantity]
        in: query
        schema:
          type: string
        description: Numeric filter on backorder quantity
      - name: filter[priority]
        in: query
        schema:
          type: string
        description: Numeric filter on priority
      - name: filter[created_at]
        in: query
        schema:
          type: string
        description: Datetime filter on created_at
      - name: sort
        in: query
        schema:
          type: string
        description: 'Sort field. Options: id, priority, quantity, created_at, updated_at,
          backorder_date, backordered_quantity, released_quantity, sku, product_name,
          supplier, order_date, sales_order_number, eta. Default: priority'
        example: priority
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        priority:
                          type: integer
                        backorder_date:
                          type: string
                        order_date:
                          type: string
                        sku:
                          type: object
                          properties:
                            id:
                              type: integer
                            sku:
                              type: string
                        product_name:
                          type: string
                        backordered_quantity:
                          type: integer
                        released_quantity:
                          type: integer
                        quantity:
                          type: integer
                        status:
                          type: string
                        status_label:
                          type: string
                        supplier:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        sales_order_number:
                          type: object
                          properties:
                            sales_order_line_id:
                              type: integer
                            sales_order_id:
                              type: integer
                            sales_order_number:
                              type: string
                        covered_by_po:
                          type: boolean
                        is_tight_coverage:
                          type: boolean
                        purchase_order_line_id:
                          type: string
                          nullable: true
                        purchase_order:
                          type: string
                          nullable: true
                        eta:
                          type: string
                          nullable: true
                        eta_state:
                          type: string
                        eta_source:
                          type: string
                          nullable: true
                        has_split_coverage:
                          type: boolean
                        other_warehouse_stock:
                          type: object
                          properties:
                            total:
                              type: integer
                            warehouses:
                              type: array
                        in_transit_stock:
                          type: object
                          properties:
                            total:
                              type: integer
                            warehouses:
                              type: array
                        scheduled_at:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - id: 10045
                    priority: 1
                    backorder_date: '2025-04-10'
                    order_date: '2025-04-08'
                    sku:
                      id: 812
                      sku: WIDGET-BLU
                    product_name: Blue Widget
                    backordered_quantity: 5
                    released_quantity: 0
                    quantity: 5
                    status: pending
                    status_label: Pending
                    supplier:
                      id: 14
                      name: Acme Corp
                    sales_order_number:
                      sales_order_line_id: 55347
                      sales_order_id: 9821
                      sales_order_number: SO-9821
                    covered_by_po: false
                    is_tight_coverage: false
                    purchase_order_line_id: null
                    purchase_order: null
                    eta: null
                    eta_state: unknown
                    eta_source: null
                    has_split_coverage: false
                    other_warehouse_stock:
                      total: 0
                      warehouses: []
                    in_transit_stock:
                      total: 0
                      warehouses: []
                    scheduled_at: null
                    created_at: '2025-04-10T08:22:11.000000Z'
                    updated_at: '2025-04-10T08:22:11.000000Z'
                  current_page: 1
                  last_page: 5
                  per_page: 10
                  total: 47
                  from: 1
                  to: 10
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: orders:read
      operationId: get-api-v2-inventory-allocations-backorders
    post:
      tags:
      - Adjustments & Transfers
      summary: Search Backorders
      description: 'Returns the same paginated list of backorders as the GET version
        of this endpoint, but accepts filters as a JSON request body instead of the
        query string. Use this POST variant when the filter set is too large or too
        complex to fit in a URL.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        A `status` scope selects which backorders are returned: `active` (default;
        outstanding backorders awaiting stock or receipt), `released` (backorders
        that have since been allocated or fulfilled), `released_fulfilled`, `released_submitted`,
        `released_unfulfilled`, or `all`.


        Provide advanced filters under `filter_groups`, a tree of conditions combined
        with a `conjunction` of `and` or `or`. Each condition names a `column`, an
        `operator`, and a `value`. A free-text `search` term matches against allocation
        id, SKU, product name, supplier, sales order number, and purchase order number.


        Text columns (`sku`, `product_name`, `supplier_name`) accept: is, is_not,
        contains, does_not_contain, starts_with, ends_with, is_empty, is_not_empty,
        is_one_of, is_not_one_of.

        Numeric and date columns (`id`, `quantity`, `priority`, `backordered_quantity`,
        `released_quantity`, `created_at`, `updated_at`, `backorder_date`, `order_date`)
        accept: is, is_not, greater_than, greater_than_or_equal, less_than, less_than_or_equal,
        between, is_empty, is_not_empty. Boolean filters `covered_by_po` and `has_other_wh_stock`
        accept `is` with true/false; `eta_state` accepts `is` with `has_eta`, `late_eta`,
        or `missing_eta`; `supplier_id` accepts a numeric id or `none`.


        Sortable columns (via `sort`, prefix with `-` for descending): id, priority,
        quantity, created_at, updated_at, backorder_date, backordered_quantity, released_quantity,
        sku, product_name, supplier, order_date, sales_order_number, eta. Results
        default to `priority`.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                status:
                  type: string
                per_page:
                  type: integer
                page:
                  type: integer
                sort:
                  type: string
                filter_groups:
                  type: object
                  properties:
                    conjunction:
                      type: string
                    children:
                      type: array
                      items:
                        type: object
                        properties:
                          type:
                            type: string
                          condition:
                            type: object
                            properties:
                              column:
                                type: string
                              operator:
                                type: string
                              value:
                                type: boolean
              example:
                status: active
                per_page: 25
                page: 1
                sort: priority
                filter_groups:
                  conjunction: and
                  children:
                  - type: condition
                    condition:
                      column: covered_by_po
                      operator: is
                      value: false
                  - type: condition
                    condition:
                      column: product_name
                      operator: contains
                      value: Widget
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        priority:
                          type: integer
                        backorder_date:
                          type: string
                        order_date:
                          type: string
                        sku:
                          type: object
                          properties:
                            id:
                              type: integer
                            sku:
                              type: string
                        product_name:
                          type: string
                        backordered_quantity:
                          type: integer
                        released_quantity:
                          type: integer
                        quantity:
                          type: integer
                        status:
                          type: string
                        status_label:
                          type: string
                        supplier:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        sales_order_number:
                          type: object
                          properties:
                            sales_order_line_id:
                              type: integer
                            sales_order_id:
                              type: integer
                            sales_order_number:
                              type: string
                        covered_by_po:
                          type: boolean
                        is_tight_coverage:
                          type: boolean
                        purchase_order_line_id:
                          type: string
                          nullable: true
                        purchase_order:
                          type: string
                          nullable: true
                        eta:
                          type: string
                          nullable: true
                        eta_state:
                          type: string
                        eta_source:
                          type: string
                          nullable: true
                        has_split_coverage:
                          type: boolean
                        other_warehouse_stock:
                          type: array
                        scheduled_at:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  per_page:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                  last_page:
                    type: integer
                  total:
                    type: integer
                  next_page_url:
                    type: string
                  prev_page_url:
                    type: string
                    nullable: true
                example:
                  data:
                  - id: 77120
                    priority: 1
                    backorder_date: '2026-06-25T11:03:00.000000Z'
                    order_date: '2026-06-24'
                    sku:
                      id: 3312
                      sku: WIDGET-BLUE-01
                    product_name: Blue Widget
                    backordered_quantity: 12
                    released_quantity: 0
                    quantity: 12
                    status: planned
                    status_label: Planned
                    supplier:
                      id: 44
                      name: Acme Supply Co
                    sales_order_number:
                      sales_order_line_id: 88231
                      sales_order_id: 6021
                      sales_order_number: SO-6021
                    covered_by_po: false
                    is_tight_coverage: false
                    purchase_order_line_id: null
                    purchase_order: null
                    eta: null
                    eta_state: missing_no_po
                    eta_source: null
                    has_split_coverage: false
                    other_warehouse_stock: []
                    scheduled_at: '2026-07-10'
                    created_at: '2026-06-25T11:03:00.000000Z'
                    updated_at: '2026-06-25T11:03:00.000000Z'
                  current_page: 1
                  per_page: 25
                  from: 1
                  to: 1
                  last_page: 3
                  total: 61
                  next_page_url: https://api.example.com/api/v2/inventory-allocations/backorders?page=2
                  prev_page_url: null
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: orders:write
      operationId: post-api-v2-inventory-allocations-backorders
  /api/v2/inventory-allocations/backorders/export:
    get:
      tags:
      - Adjustments & Transfers
      summary: Export Backorders
      description: 'Downloads the backorder queue as an XLSX or CSV file.


        :::info[Required scope: `orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Uses the same status scope, search, and grouped filter pipeline as `List Backorders`,
        so the export always matches what the user sees in the UI for the active status
        tab.


        **Scopes:**

        - `all` — export every backorder in the current status tab, ignoring filters/search/sort

        - `filtered` (default) — honor all active filters, search, and sort

        - `current_page` — just the page currently rendered by the list view

        - `selected` — the IDs passed via the `ids` query param (comma-separated)


        **Columns:**

        Pass `columns` as a comma-separated list of keys to limit the export to the
        visible list view columns (in request order). Omit `columns` to export every
        available column.


        **Response:**

        Returns a binary download — `application/vnd.openxmlformats-officedocument.spreadsheetml.sheet`
        for xlsx, `text/csv` for csv. Filename pattern: `backorders-YYYY-MM-DD-HH-MM-SS.{format}`.


        Each backorder row also carries `in_transit_stock` (inbound stock in motion
        across warehouses), alongside `other_warehouse_stock`. Both are populated
        in the CSV/XLSX export.'
      parameters:
      - name: format
        in: query
        schema:
          type: string
        description: 'Export file format: xlsx (default) or csv'
        example: xlsx
      - name: scope
        in: query
        schema:
          type: string
        description: 'Which records to export: all (ignores filters, keeps status
          tab) | filtered (default, honors active filters/search) | current_page (just
          the page the user is viewing) | selected (requires ids param)'
        example: filtered
      - name: filter[status]
        in: query
        schema:
          type: string
        description: 'Status tab. Preserved even when scope=all. Values: active |
          pending | released | partial | cancelled'
        example: active
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
            Content-Disposition:
              schema:
                type: string
                example: attachment; filename="backorders-2026-05-14-09-31-22.xlsx"
          content:
            text/plain:
              schema:
                type: string
                example: <binary xlsx contents>
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: orders:read
      operationId: get-api-v2-inventory-allocations-backorders-export
  /api/v2/inventory-allocations/summary:
    get:
      tags:
      - Adjustments & Transfers
      summary: Get Summary
      description: 'Returns summary statistics for inventory allocations — total counts
        by status, total quantities, coverage metrics.


        :::info[Required scope: `inventory:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      pending_count:
                        type: integer
                      released_count:
                        type: integer
                      fulfilled_count:
                        type: integer
                      cancelled_count:
                        type: integer
                      pending_quantity:
                        type: integer
                      released_quantity:
                        type: integer
                      tight_coverage_count:
                        type: integer
                example:
                  data:
                    pending_count: 34
                    released_count: 12
                    fulfilled_count: 201
                    cancelled_count: 5
                    pending_quantity: 340
                    released_quantity: 87
                    tight_coverage_count: 8
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: inventory:read
      operationId: get-api-v2-inventory-allocations-summary
  /api/v2/inventory-allocations/breakdown:
    get:
      tags:
      - Adjustments & Transfers
      summary: Get Breakdown
      description: 'Returns a breakdown of allocations grouped by relevant dimensions
        (warehouse, supplier, status) for dashboard widgets.


        :::info[Required scope: `orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      by_status:
                        type: array
                        items:
                          type: object
                          properties:
                            status:
                              type: string
                            count:
                              type: integer
                            quantity:
                              type: integer
                      by_warehouse:
                        type: array
                        items:
                          type: object
                          properties:
                            warehouse_id:
                              type: integer
                            warehouse_name:
                              type: string
                            count:
                              type: integer
                      by_supplier:
                        type: array
                        items:
                          type: object
                          properties:
                            supplier_id:
                              type: integer
                            supplier_name:
                              type: string
                            count:
                              type: integer
                example:
                  data:
                    by_status:
                    - status: pending
                      count: 34
                      quantity: 340
                    - status: released
                      count: 12
                      quantity: 87
                    by_warehouse:
                    - warehouse_id: 3
                      warehouse_name: East Coast DC
                      count: 28
                    by_supplier:
                    - supplier_id: 14
                      supplier_name: Acme Corp
                      count: 20
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: orders:read
      operationId: get-api-v2-inventory-allocations-breakdown
  /api/v2/inventory-allocations/product/{productId}/analysis:
    get:
      tags:
      - Adjustments & Transfers
      summary: Get Product Analysis
      description: 'Returns allocation analysis for a specific product — current allocations,
        coverage status, and demand history.


        :::info[Required scope: `orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: productId
        in: path
        schema:
          type: integer
        required: true
        description: Product ID
        example: '812'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      product:
                        type: object
                        properties:
                          id:
                            type: integer
                          sku:
                            type: string
                          name:
                            type: string
                      active_allocations:
                        type: integer
                      total_allocated_quantity:
                        type: integer
                      total_stock:
                        type: integer
                      available_after_allocations:
                        type: integer
                      tight_coverage:
                        type: boolean
                example:
                  data:
                    product:
                      id: 812
                      sku: WIDGET-BLU
                      name: Blue Widget
                    active_allocations: 3
                    total_allocated_quantity: 15
                    total_stock: 20
                    available_after_allocations: 5
                    tight_coverage: false
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:read
      operationId: get-api-v2-inventory-allocations-product-productid-analysis
  /api/v2/inventory-allocations/supplier/{supplierId}/analysis:
    get:
      tags:
      - Adjustments & Transfers
      summary: Get Supplier Analysis
      description: 'Returns allocation analysis for a specific supplier — coverage
        metrics, pending PO quantities, backorder exposure.


        :::info[Required scope: `orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: supplierId
        in: path
        schema:
          type: integer
        required: true
        description: Supplier ID
        example: '14'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      supplier:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      pending_backorders:
                        type: integer
                      total_backordered_quantity:
                        type: integer
                      po_covered_quantity:
                        type: integer
                      uncovered_quantity:
                        type: integer
                example:
                  data:
                    supplier:
                      id: 14
                      name: Acme Corp
                    pending_backorders: 8
                    total_backordered_quantity: 42
                    po_covered_quantity: 30
                    uncovered_quantity: 12
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:read
      operationId: get-api-v2-inventory-allocations-supplier-supplierid-analysis
  /api/v2/inventory-allocations/product/{productId}/coverage-options:
    get:
      tags:
      - Adjustments & Transfers
      summary: List Coverage Options
      description: 'Lists the open PO lines a product''s allocation can be manually
        covered by — used to populate the ''Change PO Coverage'' picker.


        :::info[Required scope: `orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Returns non-draft / non-closed / non-cancelled / non-voided PO lines with
        unreceived quantity remaining, sorted by earliest resolved ETA first (lines
        with no resolvable ETA sort last, by creation order). `resolved_eta` is the
        inbound-shipment expected arrival date, falling back to the PO header''s estimated
        delivery date.'
      parameters:
      - name: productId
        in: path
        schema:
          type: integer
        required: true
        description: Product ID
        example: '812'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        purchase_order_line_id:
                          type: integer
                        purchase_order_id:
                          type: integer
                        purchase_order_number:
                          type: string
                        quantity:
                          type: integer
                        received_quantity:
                          type: integer
                        unreceived_quantity:
                          type: integer
                        resolved_eta:
                          type: string
                example:
                  data:
                  - purchase_order_line_id: 5567
                    purchase_order_id: 902
                    purchase_order_number: PO-000902
                    quantity: 100
                    received_quantity: 20
                    unreceived_quantity: 80
                    resolved_eta: '2026-05-28'
                  - purchase_order_line_id: 5612
                    purchase_order_id: 915
                    purchase_order_number: PO-000915
                    quantity: 50
                    received_quantity: 0
                    unreceived_quantity: 50
                    resolved_eta: '2026-06-10'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:read
      operationId: get-api-v2-inventory-allocations-product-productid-coverage-options
  /api/v2/inventory-allocations/suppliers:
    get:
      tags:
      - Adjustments & Transfers
      summary: List Allocation Suppliers
      description: 'Returns a list of suppliers that have active inventory allocations
        — used to populate supplier filter dropdowns.


        :::info[Required scope: `orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                example:
                  data:
                  - id: 14
                    name: Acme Corp
                  - id: 22
                    name: Global Supply Ltd
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: orders:read
      operationId: get-api-v2-inventory-allocations-suppliers
  /api/v2/inventory-allocations/search-suppliers:
    get:
      tags:
      - Adjustments & Transfers
      summary: Search Allocation Suppliers
      description: 'Searches suppliers by name for autocomplete dropdowns. Returns
        suppliers that match the query string.


        :::info[Required scope: `orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: query
        in: query
        schema:
          type: string
        description: Supplier name search string
        example: acme
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                example:
                  data:
                  - id: 14
                    name: Acme Corp
                  - id: 31
                    name: Acme International
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: orders:read
      operationId: get-api-v2-inventory-allocations-search-suppliers
  /api/v2/inventory-allocations/export:
    get:
      tags:
      - Adjustments & Transfers
      summary: Export Allocations
      description: 'Downloads an export of inventory allocations.


        :::info[Required scope: `inventory:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        **Query Parameters**:

        - `format` — `xlsx` (default)

        - `scope` — `filtered` (apply current filters), `selected` (specific IDs),
        `all`

        - `ids` — Required when `scope=selected`. Comma-separated allocation IDs.


        Returns a binary file download response.'
      parameters:
      - name: format
        in: query
        schema:
          type: string
        description: 'Export format: xlsx (default)'
        example: xlsx
      - name: scope
        in: query
        schema:
          type: string
        description: 'Export scope: filtered | selected | all'
        example: filtered
      - name: ids
        in: query
        schema:
          type: string
        description: Comma-separated allocation IDs when scope=selected
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
            Content-Disposition:
              schema:
                type: string
                example: attachment; filename="inventory-allocations.xlsx"
          content:
            text/plain:
              schema:
                type: string
                example: (binary XLSX file)
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: inventory:read
      operationId: get-api-v2-inventory-allocations-export
  /api/v2/inventory-allocations/sync-coverages:
    post:
      tags:
      - Adjustments & Transfers
      summary: Sync Coverages
      description: 'Dispatches a background job to sync allocation coverages. Returns
        a `tracked_job_log_id` for monitoring progress via the tracked job log endpoints.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties: {}
              example: {}
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 4821
                  message: Sync coverages job started.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: orders:write
      operationId: post-api-v2-inventory-allocations-sync-coverages
  /api/v2/inventory-allocations/rebalance-coverages:
    post:
      tags:
      - Adjustments & Transfers
      summary: Rebalance Coverages
      description: 'Dispatches a background job that rebalances allocation coverages
        — it tears down every non-tight `AwaitingReceipt` coverage and rebuilds it
        from scratch using the current resolved PO ETAs (inbound-shipment expected
        arrival, falling back to the PO header''s estimated delivery date).


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Manually pinned (tight) coverage is never touched. Returns a `tracked_job_log_id`
        for monitoring progress via the tracked job log endpoints.


        Use this after PO ETAs change so existing PO-line ↔ allocation bindings reflect
        earliest-ETA-first ordering.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties: {}
              example: {}
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 4822
                  message: Coverage rebalance job has been queued
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: orders:write
      operationId: post-api-v2-inventory-allocations-rebalance-coverages
  /api/v2/inventory-allocations/release-allocations:
    post:
      tags:
      - Adjustments & Transfers
      summary: Release Allocations
      description: 'Dispatches a background job to release eligible allocations to
        fulfillment. Returns a `tracked_job_log_id` for monitoring progress via the
        tracked job log endpoints.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties: {}
              example: {}
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 4822
                  message: Release allocations job started.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: orders:write
      operationId: post-api-v2-inventory-allocations-release-allocations
  /api/v2/inventory-allocations/reset-priorities:
    post:
      tags:
      - Adjustments & Transfers
      summary: Reset Priorities
      description: 'Dispatches a background job to reset allocation priorities using
        the specified method.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        **Body**:

        - `method` (required) — Priority reset method: `fifo` | `lifo` | custom

        - `overwrite_tight_coverages` (boolean) — Whether to reassign tight coverage
        allocations

        - `resync_coverages` (boolean) — Whether to resync coverages after reset


        Returns a `tracked_job_log_id`.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                method:
                  type: string
                overwrite_tight_coverages:
                  type: boolean
                resync_coverages:
                  type: boolean
              example:
                method: fifo
                overwrite_tight_coverages: false
                resync_coverages: true
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 4823
                  message: Reset priorities job started.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: orders:write
      operationId: post-api-v2-inventory-allocations-reset-priorities
  /api/v2/inventory-allocations/compact-priorities:
    post:
      tags:
      - Adjustments & Transfers
      summary: Compact Priorities
      description: 'Dispatches a background job to compact allocation priority numbers
        — fills in gaps from deleted/cancelled allocations so priorities are sequential.
        Returns a `tracked_job_log_id`.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties: {}
              example: {}
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 4825
                  message: Compact priorities job started.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: orders:write
      operationId: post-api-v2-inventory-allocations-compact-priorities
  /api/v2/inventory-allocations/evaluate-releases:
    post:
      tags:
      - Adjustments & Transfers
      summary: Evaluate Releases
      description: 'Dispatches a background job to evaluate which allocations are
        ready for release.


        **Body**:

        - `dispatch_fulfillments` (boolean) — If `true`, automatically dispatch fulfillments
        for ready allocations. If `false`, only evaluate and mark.


        Returns a `tracked_job_log_id`.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                dispatch_fulfillments:
                  type: boolean
              example:
                dispatch_fulfillments: false
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 4824
                  message: Evaluate releases job started.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-v2-inventory-allocations-evaluate-releases
  /api/v2/inventory-allocations/check-release-availability:
    post:
      tags:
      - Adjustments & Transfers
      summary: Check Release Availability
      description: 'Checks whether the specified allocations have sufficient stock
        to be released. Returns availability status per allocation.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        **Body**:

        - `allocation_ids` — Array of allocation IDs to check'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                allocation_ids:
                  type: array
                  items:
                    type: integer
              example:
                allocation_ids:
                - 10045
                - 10046
                - 10047
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        allocation_id:
                          type: integer
                        available:
                          type: boolean
                        stock:
                          type: integer
                        required:
                          type: integer
                example:
                  data:
                  - allocation_id: 10045
                    available: true
                    stock: 20
                    required: 5
                  - allocation_id: 10046
                    available: false
                    stock: 2
                    required: 10
                  - allocation_id: 10047
                    available: true
                    stock: 8
                    required: 3
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: orders:write
      operationId: post-api-v2-inventory-allocations-check-release-availability
  /api/v2/inventory-allocations/release-selected:
    post:
      tags:
      - Adjustments & Transfers
      summary: Release Selected Backorders
      description: 'Immediately releases the specified allocations to fulfillment.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        **Body**:

        - `allocation_ids` — Array of allocation IDs to release'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                allocation_ids:
                  type: array
                  items:
                    type: integer
              example:
                allocation_ids:
                - 10045
                - 10047
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  released_count:
                    type: integer
                example:
                  message: 2 allocations released successfully.
                  released_count: 2
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: orders:write
      operationId: post-api-v2-inventory-allocations-release-selected
  /api/v2/inventory-allocations/submit-fulfillments:
    post:
      tags:
      - Adjustments & Transfers
      summary: Submit Fulfillments
      description: 'Submits fulfillments for the specified released allocations.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        **Body**:

        - `allocation_ids` — Array of allocation IDs to submit fulfillments for'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                allocation_ids:
                  type: array
                  items:
                    type: integer
              example:
                allocation_ids:
                - 10045
                - 10047
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Fulfillments submitted for 2 allocations.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: orders:write
      operationId: post-api-v2-inventory-allocations-submit-fulfillments
  /api/v2/inventory-allocations/delete-fulfillments:
    post:
      tags:
      - Adjustments & Transfers
      summary: Delete Fulfillments
      description: 'Deletes pending fulfillments for the specified allocations, reverting
        them to released status.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        **Body**:

        - `allocation_ids` — Array of allocation IDs whose fulfillments should be
        deleted'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                allocation_ids:
                  type: array
                  items:
                    type: integer
              example:
                allocation_ids:
                - 10045
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Fulfillments deleted for 1 allocation.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: orders:write
      operationId: post-api-v2-inventory-allocations-delete-fulfillments
  /api/v2/inventory-allocations/unreserve:
    post:
      tags:
      - Adjustments & Transfers
      summary: Unreserve Allocations
      description: 'Cancels (unreserves) the specified allocations.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        **Body**:

        - `allocation_ids` — Array of allocation IDs to cancel

        - `disable_auto_release` (boolean) — If `true`, disables automatic re-release
        for the linked source document after cancellation'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                allocation_ids:
                  type: array
                  items:
                    type: integer
                disable_auto_release:
                  type: boolean
              example:
                allocation_ids:
                - 10045
                - 10046
                disable_auto_release: false
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 2 allocations cancelled.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: orders:write
      operationId: post-api-v2-inventory-allocations-unreserve
  /api/v2/inventory-allocations/switch-supplier-options:
    post:
      tags:
      - Adjustments & Transfers
      summary: Switch Supplier Options
      description: 'Returns the per-allocation supplier picker payload used by the
        Allocation Pipeline Change Supplier dialog. Only allocations in `planned`
        or `awaiting_receipt` status are eligible. For each eligible allocation, returns
        the list of suppliers configured for that product (via `supplier_products`),
        excluding archived suppliers.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        **Body**:

        - `ids` (required, array, min 1) — Array of inventory allocation IDs.

        - `ids.*` (integer) — Each ID must be an integer.


        **Notes**:

        - Allocations whose status is not `planned` or `awaiting_receipt` are silently
        filtered out (they are not eligible for supplier change).

        - Each row''s `suppliers` list is sorted with the default supplier first,
        then alphabetically by name.

        - Use the returned `current_supplier.id` to highlight the existing selection
        in the UI.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 10045
                - 10046
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        product_id:
                          type: integer
                        sku:
                          type: string
                        product_name:
                          type: string
                        current_supplier:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        suppliers:
                          type: array
                          items:
                            type: object
                            properties:
                              id:
                                type: integer
                              name:
                                type: string
                              is_default:
                                type: boolean
                example:
                  data:
                  - id: 10045
                    product_id: 8821
                    sku: SPN-STD-SPIRAL-BLK
                    product_name: Spiral Notebook - Black
                    current_supplier:
                      id: 14
                      name: HomeLife
                    suppliers:
                    - id: 14
                      name: HomeLife
                      is_default: true
                    - id: 27
                      name: A Bar Above
                      is_default: false
                  - id: 10046
                    product_id: 9102
                    sku: WGT-001
                    product_name: Widget 001
                    current_supplier: null
                    suppliers:
                    - id: 31
                      name: Acme Supply Co.
                      is_default: true
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      ids:
                        type: array
                        items:
                          type: string
                example:
                  message: The ids field is required.
                  errors:
                    ids:
                    - The ids field is required.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: orders:write
      operationId: post-api-v2-inventory-allocations-switch-supplier-options
  /api/v2/inventory-allocations/switch-suppliers:
    post:
      tags:
      - Adjustments & Transfers
      summary: Switch Suppliers
      description: 'Bulk updates the supplier on one or more inventory allocations.
        Each assignment is validated against `supplier_products` so the chosen supplier
        must already be configured for the allocation''s product. Allocations not
        in `planned` or `awaiting_receipt` status are skipped.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        **Body**:

        - `assignments` (required, array, min 1) — List of allocation/supplier pairs
        to apply.

        - `assignments.*.allocation_id` (required, integer, exists in `inventory_allocations`)
        — ID of the allocation to update.

        - `assignments.*.supplier_id` (required, integer, exists in `suppliers`) —
        ID of the supplier to assign.


        **Behavior**:

        - Assignments where the new supplier matches the current supplier are counted
        as `skipped` (no-op).

        - Assignments referencing an allocation that is no longer in `planned`/`awaiting_receipt`
        are counted as `skipped`.

        - Assignments where the supplier is not configured for the product return
        per-row errors and do NOT update the allocation.

        - The endpoint is best-effort per row; partial success is normal (e.g., 3
        updated, 1 skipped, 1 error).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                assignments:
                  type: array
                  items:
                    type: object
                    properties:
                      allocation_id:
                        type: integer
                      supplier_id:
                        type: integer
              example:
                assignments:
                - allocation_id: 10045
                  supplier_id: 27
                - allocation_id: 10046
                  supplier_id: 31
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 OK
                  value:
                    message: Updated supplier on 2 allocation(s).
                    data:
                      updated: 2
                      skipped: 0
                      errors: []
                example-1:
                  summary: 200 OK - Partial
                  value:
                    message: Updated supplier on 1 allocation(s).
                    data:
                      updated: 1
                      skipped: 1
                      errors:
                      - id: 10046
                        error: Supplier is not configured for this product.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      assignments:
                        type: array
                        items:
                          type: string
                example:
                  message: The assignments field is required.
                  errors:
                    assignments:
                    - The assignments field is required.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: orders:write
      operationId: post-api-v2-inventory-allocations-switch-suppliers
  /api/warehouses/transfers:
    post:
      tags:
      - Adjustments & Transfers
      summary: Create Warehouse Transfer
      description: 'Creates a warehouse transfer (in draft status) moving stock between
        two warehouses.


        :::info[Required scope: `warehouses:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Fields: from_warehouse_id and to_warehouse_id (required, must differ), transfer_date,
        eta (must not be before transfer_date), products (array of {product_id, quantity,
        quantity_cancelled, description, sales_channel_unique_id}), shipping_method_id,
        shipment (object with shipment_date, tracking_number, cost - creates an initial
        shipment), shipment_id (required when the destination is an Amazon FBA warehouse
        - the Amazon inbound shipment ID), order_id and custom_field_values (array
        of {custom_field_id, value}).


        Returns 400 when a product does not have enough available stock in the source
        warehouse.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                transfer_date:
                  type: string
                eta:
                  type: string
                from_warehouse_id:
                  type: integer
                to_warehouse_id:
                  type: integer
                shipping_method_id:
                  type: integer
                products:
                  type: array
                  items:
                    type: object
                    properties:
                      product_id:
                        type: integer
                      quantity:
                        type: integer
              example:
                transfer_date: '2026-06-01'
                eta: '2026-06-15'
                from_warehouse_id: 2
                to_warehouse_id: 5
                shipping_method_id: 3
                products:
                - product_id: 101
                  quantity: 100
                - product_id: 102
                  quantity: 50
      parameters: []
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      transfer_type:
                        type: string
                      warehouse_transfer_number:
                        type: string
                      transfer_date:
                        type: string
                      from_warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          type:
                            type: string
                          integration_instance_id:
                            type: string
                            nullable: true
                      to_warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          type:
                            type: string
                      status:
                        type: string
                      shipment_status:
                        type: string
                      shipment_id:
                        type: string
                        nullable: true
                      receipt_status:
                        type: string
                      fully_shipped_at:
                        type: string
                        nullable: true
                      fully_received_at:
                        type: string
                        nullable: true
                      eta:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                      line_item_count:
                        type: integer
                      first_line_sku:
                        type: string
                      asn_last_sent_at:
                        type: string
                        nullable: true
                example:
                  message: warehouse transfer created successfully.
                  data:
                    id: 512
                    transfer_type: standard
                    warehouse_transfer_number: WT-000512
                    transfer_date: '2026-06-01T00:00:00.000000Z'
                    from_warehouse:
                      id: 2
                      name: Main Warehouse
                      type: direct
                      integration_instance_id: null
                    to_warehouse:
                      id: 5
                      name: West Coast 3PL
                      type: 3pl
                    status: open
                    shipment_status: unshipped
                    shipment_id: null
                    receipt_status: unreceived
                    fully_shipped_at: null
                    fully_received_at: null
                    eta: '2026-06-15'
                    created_at: '2026-06-01T10:00:00.000000Z'
                    updated_at: '2026-06-02T08:30:00.000000Z'
                    archived_at: null
                    line_item_count: 1
                    first_line_sku: WIDGET-001
                    asn_last_sent_at: null
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      product:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: object
                              properties:
                                product_id:
                                  type: integer
                example:
                  message: warehouse transfer could not be created.
                  errors:
                    product:
                    - message: Not enough available quantity for SKU WIDGET-001.
                      code: Product406
                      data:
                        product_id: 101
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: warehouses:write
      operationId: post-api-warehouses-transfers
    delete:
      tags:
      - Adjustments & Transfers
      summary: Bulk Delete Warehouse Transfers
      description: 'Deletes multiple warehouse transfers, reversing their inventory
        movements. Provide either ids (array of transfer IDs) or apply_to_all=true
        with an optional filters object.


        :::info[Required scope: `warehouses:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Returns 400 when received stock from a transfer has already been consumed
        downstream.


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      totalCount:
                        type: integer
                      failCount:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    totalCount: 2
                    failCount: 0
                  message: 2 records processed successfully.
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      product:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: object
                              properties:
                                product_id:
                                  type: integer
                example:
                  message: warehouse transfers could not be deleted.
                  errors:
                    product:
                    - message: Stock received by this transfer has already been used
                        for SKU WIDGET-001.
                      code: Product406
                      data:
                        product_id: 101
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: warehouses:write
      operationId: delete-api-warehouses-transfers
  /api/warehouses/transfers/{transfer}:
    put:
      tags:
      - Adjustments & Transfers
      summary: Update Warehouse Transfer
      description: 'Updates a warehouse transfer. Accepts the same fields as Create
        Warehouse Transfer (all optional) plus tags (array of tag names to sync).
        The products array replaces the transfer''s line items; include existing line
        ids to keep them.


        :::info[Required scope: `warehouses:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Transfers to an Amazon FBA warehouse can only be edited while in draft status.
        Returns 422 when editing a line that has already been shipped or when stock
        is insufficient.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                eta:
                  type: string
                products:
                  type: array
                  items:
                    type: object
                    properties:
                      id:
                        type: integer
                      product_id:
                        type: integer
                      quantity:
                        type: integer
                tags:
                  type: array
                  items:
                    type: string
              example:
                eta: '2026-06-20'
                products:
                - id: 9001
                  product_id: 101
                  quantity: 120
                tags:
                - restock
      parameters:
      - name: transfer
        in: path
        schema:
          type: integer
        required: true
        description: Warehouse transfer ID
        example: '512'
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      transfer_type:
                        type: string
                      warehouse_transfer_number:
                        type: string
                      transfer_date:
                        type: string
                      from_warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          type:
                            type: string
                          integration_instance_id:
                            type: string
                            nullable: true
                      to_warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          type:
                            type: string
                      status:
                        type: string
                      shipment_status:
                        type: string
                      shipment_id:
                        type: string
                        nullable: true
                      receipt_status:
                        type: string
                      fully_shipped_at:
                        type: string
                        nullable: true
                      fully_received_at:
                        type: string
                        nullable: true
                      eta:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                      line_item_count:
                        type: integer
                      first_line_sku:
                        type: string
                      asn_last_sent_at:
                        type: string
                        nullable: true
                      shipment_percent:
                        type: integer
                      receipt_percent:
                        type: integer
                      items:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            quantity:
                              type: number
                            product_id:
                              type: integer
                            product:
                              type: object
                              properties:
                                id:
                                  type: integer
                                sku:
                                  type: string
                                name:
                                  type: string
                                is_lot_tracked:
                                  type: boolean
                                lot_tracking_method:
                                  type: string
                                  nullable: true
                                shelf_life_days:
                                  type: string
                                  nullable: true
                                near_expiry_threshold_days:
                                  type: string
                                  nullable: true
                                min_remaining_shelf_life_days:
                                  type: string
                                  nullable: true
                            sku:
                              type: string
                            barcode:
                              type: string
                            sales_channel_unique_id:
                              type: string
                              nullable: true
                            name:
                              type: string
                            image_url:
                              type: string
                              nullable: true
                            quantity_cancelled:
                              type: integer
                            quantity_received:
                              type: integer
                            quantity_shipped:
                              type: integer
                      tags:
                        type: array
                        items:
                          type: string
                      total_quantity:
                        type: integer
                example:
                  message: warehouse transfer updated successfully.
                  data:
                    id: 512
                    transfer_type: standard
                    warehouse_transfer_number: WT-000512
                    transfer_date: '2026-06-01T00:00:00.000000Z'
                    from_warehouse:
                      id: 2
                      name: Main Warehouse
                      type: direct
                      integration_instance_id: null
                    to_warehouse:
                      id: 5
                      name: West Coast 3PL
                      type: 3pl
                    status: open
                    shipment_status: unshipped
                    shipment_id: null
                    receipt_status: unreceived
                    fully_shipped_at: null
                    fully_received_at: null
                    eta: '2026-06-15'
                    created_at: '2026-06-01T10:00:00.000000Z'
                    updated_at: '2026-06-02T08:30:00.000000Z'
                    archived_at: null
                    line_item_count: 1
                    first_line_sku: WIDGET-001
                    asn_last_sent_at: null
                    shipment_percent: 0
                    receipt_percent: 0
                    items:
                    - id: 9001
                      quantity: 100.0
                      product_id: 101
                      product:
                        id: 101
                        sku: WIDGET-001
                        name: Widget
                        is_lot_tracked: false
                        lot_tracking_method: null
                        shelf_life_days: null
                        near_expiry_threshold_days: null
                        min_remaining_shelf_life_days: null
                      sku: WIDGET-001
                      barcode: 0123456789012
                      sales_channel_unique_id: null
                      name: Widget
                      image_url: null
                      quantity_cancelled: 0
                      quantity_received: 0
                      quantity_shipped: 0
                    tags:
                    - restock
                    total_quantity: 100
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Cannot edit a line that has already been shipped.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: warehouses:write
      operationId: put-api-warehouses-transfers-transfer
    delete:
      tags:
      - Adjustments & Transfers
      summary: Delete Warehouse Transfer
      description: 'Deletes a warehouse transfer and reverses its inventory movements.
        Deletion fails when received stock from this transfer has already been consumed
        downstream (sold, transferred again, or adjusted).


        :::info[Required scope: `warehouses:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: transfer
        in: path
        schema:
          type: integer
        required: true
        description: Warehouse transfer ID
        example: '512'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: warehouse transfer 512 deleted successfully.
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      product:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: object
                              properties:
                                product_id:
                                  type: integer
                example:
                  message: warehouse transfer could not be deleted.
                  errors:
                    product:
                    - message: Stock received by this transfer has already been used
                        for SKU WIDGET-001.
                      code: Product406
                      data:
                        product_id: 101
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: warehouses:write
      operationId: delete-api-warehouses-transfers-transfer
  /api/warehouses/transfers/{transfer}/duplicate:
    post:
      tags:
      - Adjustments & Transfers
      summary: Duplicate Warehouse Transfer
      description: 'Creates a new draft warehouse transfer copying the source transfer''s
        warehouses and line items.


        :::info[Required scope: `warehouses:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: transfer
        in: path
        schema:
          type: integer
        required: true
        description: Warehouse transfer ID to duplicate
        example: '512'
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      transfer_type:
                        type: string
                      warehouse_transfer_number:
                        type: string
                      transfer_date:
                        type: string
                      from_warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          type:
                            type: string
                          integration_instance_id:
                            type: string
                            nullable: true
                      to_warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          type:
                            type: string
                      status:
                        type: string
                      shipment_status:
                        type: string
                      shipment_id:
                        type: string
                        nullable: true
                      receipt_status:
                        type: string
                      fully_shipped_at:
                        type: string
                        nullable: true
                      fully_received_at:
                        type: string
                        nullable: true
                      eta:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                      line_item_count:
                        type: integer
                      first_line_sku:
                        type: string
                      asn_last_sent_at:
                        type: string
                        nullable: true
                example:
                  message: warehouse transfer created successfully.
                  data:
                    id: 512
                    transfer_type: standard
                    warehouse_transfer_number: WT-000512
                    transfer_date: '2026-06-01T00:00:00.000000Z'
                    from_warehouse:
                      id: 2
                      name: Main Warehouse
                      type: direct
                      integration_instance_id: null
                    to_warehouse:
                      id: 5
                      name: West Coast 3PL
                      type: 3pl
                    status: open
                    shipment_status: unshipped
                    shipment_id: null
                    receipt_status: unreceived
                    fully_shipped_at: null
                    fully_received_at: null
                    eta: '2026-06-15'
                    created_at: '2026-06-01T10:00:00.000000Z'
                    updated_at: '2026-06-02T08:30:00.000000Z'
                    archived_at: null
                    line_item_count: 1
                    first_line_sku: WIDGET-001
                    asn_last_sent_at: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: warehouses:write
      operationId: post-api-warehouses-transfers-transfer-duplicate
  /api/v2/warehouse-transfers:
    get:
      tags:
      - Adjustments & Transfers
      summary: List Warehouse Transfers
      description: 'Returns a paginated list of warehouse transfers.


        :::info[Required scope: `warehouses:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        **Supports GET and POST** — POST can be used to send large filter payloads
        in the request body.


        **Filters** (via Spatie QueryBuilder + GroupedFilterSupport):

        - `filter[search]` — Cross-column search on id, transfer_number, from/to warehouse
        name, item SKU, item FNSKU

        - `filter[archived]` — Boolean (true|false) — archived transfers

        - `filter[transfer_type]` — Transfer type text filter: `standard`, `fba_inbound`,
        `awd`

        - `filter[has_blemished]` — Boolean text filter

        - `filter[has_inbound_plan]` — Boolean text filter (FBA)

        - `filter[include_deleted]` — Include soft-deleted records

        - `filter_groups` — Tree-based advanced filters (GroupedFilterSupport)


        **Sort options**: id, warehouse_transfer_number, transfer_date, transfer_status,
        shipment_status, receipt_status, created_at, updated_at, eta, archived_at,
        asn_last_sent_at, status, from_warehouse_name, to_warehouse_name, from_warehouse,
        to_warehouse. Default: `-transfer_date`.


        The response also includes `unfiltered_total`, the count of rows in the base
        scope before any user filters are applied — used by the frontend to show export
        totals.'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        example: '1'
        description: Page number (default 1).
      - name: per_page
        in: query
        schema:
          type: integer
        example: '10'
        description: Results per page (default 10).
      - name: filter[search]
        in: query
        schema:
          type: string
        description: 'Cross-column search: id, transfer_number, from_warehouse name,
          to_warehouse name, item SKU, item FNSKU'
      - name: filter[archived]
        in: query
        schema:
          type: string
        description: true | false — filter archived transfers
      - name: filter[transfer_type]
        in: query
        schema:
          type: string
        description: 'Text filter on transfer_type: standard | fba_inbound | awd'
      - name: filter[has_blemished]
        in: query
        schema:
          type: string
        description: Text filter — true | false
      - name: filter[has_inbound_plan]
        in: query
        schema:
          type: string
        description: Text filter — true | false (FBA inbound plan link)
      - name: filter[include_deleted]
        in: query
        schema:
          type: string
        description: true — include soft-deleted transfers
      - name: filter_groups[conjunction]
        in: query
        schema:
          type: string
        description: 'Advanced filter tree conjunction: and | or. Use with filter_groups[children][]
          for grouped conditions.'
        example: and
      - name: sort
        in: query
        schema:
          type: string
        description: 'Sort field. Prefix with - for descending. Options: id, warehouse_transfer_number,
          transfer_date, transfer_status, shipment_status, receipt_status, created_at,
          updated_at, eta, archived_at, asn_last_sent_at, status, from_warehouse_name,
          to_warehouse_name, from_warehouse, to_warehouse. Default: -transfer_date'
        example: -transfer_date
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        transfer_type:
                          type: string
                        warehouse_transfer_number:
                          type: string
                        transfer_date:
                          type: string
                        from_warehouse:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        to_warehouse:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        status:
                          type: string
                        shipment_status:
                          type: string
                        shipment_percent:
                          type: integer
                        receipt_status:
                          type: string
                        receipt_percent:
                          type: integer
                        shipping_method:
                          type: string
                        fully_shipped_at:
                          type: string
                        fully_received_at:
                          type: string
                          nullable: true
                        items:
                          type: integer
                        eta:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                        archived_at:
                          type: string
                          nullable: true
                        tags:
                          type: array
                        line_item_count:
                          type: integer
                        total_quantity:
                          type: integer
                        notes:
                          type: string
                          nullable: true
                        adjustments:
                          type: array
                        shipments:
                          type: array
                        financial_lines:
                          type: array
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  unfiltered_total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - id: 501
                    transfer_type: standard
                    warehouse_transfer_number: WT-501
                    transfer_date: '2025-04-10'
                    from_warehouse:
                      id: 1
                      name: Main Warehouse
                    to_warehouse:
                      id: 3
                      name: East Coast DC
                    status: in_transit
                    shipment_status: shipped
                    shipment_percent: 100
                    receipt_status: partial
                    receipt_percent: 60
                    shipping_method: Ground
                    fully_shipped_at: '2025-04-11T14:00:00.000000Z'
                    fully_received_at: null
                    items: 3
                    eta: '2025-04-15'
                    created_at: '2025-04-10T08:00:00.000000Z'
                    updated_at: '2025-04-11T14:05:00.000000Z'
                    archived_at: null
                    tags: []
                    line_item_count: 3
                    total_quantity: 150
                    notes: null
                    adjustments: []
                    shipments: []
                    financial_lines: []
                  current_page: 1
                  last_page: 8
                  per_page: 10
                  total: 78
                  unfiltered_total: 412
                  from: 1
                  to: 10
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: warehouses:read
      operationId: get-api-v2-warehouse-transfers
    post:
      tags:
      - Adjustments & Transfers
      summary: Search Warehouse Transfers
      description: 'Returns the same paginated list of warehouse transfers as the
        GET version of this endpoint, but accepts filters as a JSON request body instead
        of the query string. Use this POST variant when the filter set is too large
        or too complex to fit in a URL. The response includes an `unfiltered_total`
        alongside the standard paginator totals so clients can show both the filtered
        and total record counts.


        :::info[Required scope: `warehouses:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Provide advanced filters under `filter_groups`, a tree of conditions combined
        with a `conjunction` of `and` or `or`. Each condition names a `column`, an
        `operator`, and a `value`. A free-text `search` term matches against transfer
        id, transfer number, source and destination warehouses, item SKU, and item
        FNSKU.


        Text and status columns (`transfer_status`, `shipment_status`, `receipt_status`,
        `from_warehouse`, `to_warehouse`) accept: is, is_not, contains, does_not_contain,
        starts_with, ends_with, is_empty, is_not_empty, is_one_of, is_not_one_of.

        Numeric and date columns (`id`, `transfer_date`, `created_at`, `updated_at`)
        accept: is, is_not, greater_than, greater_than_or_equal, less_than, less_than_or_equal,
        between, is_empty, is_not_empty. The `transfer_type` filter accepts `standard`,
        `fba_inbound`, `awd_inbound`, or `awd_fba_replenishment`; `has_blemished`,
        `has_inbound_plan`, `archived`, and `include_deleted` are boolean toggles.
        Custom field filters are also supported.


        Sortable columns (via `sort`, prefix with `-` for descending): id, warehouse_transfer_number,
        transfer_date, transfer_status, shipment_status, receipt_status, created_at,
        updated_at, eta, archived_at, asn_last_sent_at, from_warehouse_name, to_warehouse_name.
        Results default to `-transfer_date`.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                per_page:
                  type: integer
                page:
                  type: integer
                sort:
                  type: string
                filter_groups:
                  type: object
                  properties:
                    conjunction:
                      type: string
                    children:
                      type: array
                      items:
                        type: object
                        properties:
                          type:
                            type: string
                          condition:
                            type: object
                            properties:
                              column:
                                type: string
                              operator:
                                type: string
                              value:
                                type: string
              example:
                per_page: 25
                page: 1
                sort: -transfer_date
                filter_groups:
                  conjunction: and
                  children:
                  - type: condition
                    condition:
                      column: transfer_type
                      operator: is
                      value: fba_inbound
                  - type: condition
                    condition:
                      column: shipment_status
                      operator: is_not
                      value: shipped
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        transfer_type:
                          type: string
                        warehouse_transfer_number:
                          type: string
                        transfer_date:
                          type: string
                        from_warehouse:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            type:
                              type: string
                            integration_instance_id:
                              type: string
                              nullable: true
                        to_warehouse:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            type:
                              type: string
                        status:
                          type: string
                        shipment_status:
                          type: string
                        shipment_id:
                          type: integer
                        receipt_status:
                          type: string
                        fully_shipped_at:
                          type: string
                          nullable: true
                        fully_received_at:
                          type: string
                          nullable: true
                        eta:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                        archived_at:
                          type: string
                          nullable: true
                  current_page:
                    type: integer
                  per_page:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                  last_page:
                    type: integer
                  total:
                    type: integer
                  unfiltered_total:
                    type: integer
                  next_page_url:
                    type: string
                  prev_page_url:
                    type: string
                    nullable: true
                example:
                  data:
                  - id: 3021
                    transfer_type: fba_inbound
                    warehouse_transfer_number: WT-3021
                    transfer_date: '2026-06-27T00:00:00.000000Z'
                    from_warehouse:
                      id: 2
                      name: Main Warehouse
                      type: standard
                      integration_instance_id: null
                    to_warehouse:
                      id: 9
                      name: Amazon FBA - US
                      type: amazon_fba
                    status: in_progress
                    shipment_status: partially_shipped
                    shipment_id: 1201
                    receipt_status: pending
                    fully_shipped_at: null
                    fully_received_at: null
                    eta: '2026-07-05'
                    created_at: '2026-06-27T13:00:00.000000Z'
                    updated_at: '2026-06-28T08:22:00.000000Z'
                    archived_at: null
                  current_page: 1
                  per_page: 25
                  from: 1
                  to: 1
                  last_page: 5
                  total: 118
                  unfiltered_total: 342
                  next_page_url: https://api.example.com/api/v2/warehouse-transfers?page=2
                  prev_page_url: null
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: warehouses:write
      operationId: post-api-v2-warehouse-transfers
  /api/v2/warehouse-transfers/{warehouseTransfer}:
    get:
      tags:
      - Adjustments & Transfers
      summary: Get Warehouse Transfer
      description: 'Returns the full detail view of a warehouse transfer.


        :::info[Required scope: `warehouses:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Eager-loads: from_warehouse, to_warehouse, tags, adjustments, shipments (with
        lines and receipts), financial_lines, and COGS data. Also preloads current
        stock levels for both warehouses.'
      parameters:
      - name: warehouseTransfer
        in: path
        schema:
          type: integer
        required: true
        description: Warehouse Transfer ID
        example: '501'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: integer
                  transfer_type:
                    type: string
                  warehouse_transfer_number:
                    type: string
                  transfer_date:
                    type: string
                  from_warehouse:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                  to_warehouse:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                  status:
                    type: string
                  shipment_status:
                    type: string
                  shipment_percent:
                    type: integer
                  receipt_status:
                    type: string
                  receipt_percent:
                    type: integer
                  shipping_method:
                    type: string
                  fully_shipped_at:
                    type: string
                  fully_received_at:
                    type: string
                    nullable: true
                  items:
                    type: integer
                  eta:
                    type: string
                  created_at:
                    type: string
                  updated_at:
                    type: string
                  archived_at:
                    type: string
                    nullable: true
                  tags:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                  line_item_count:
                    type: integer
                  total_quantity:
                    type: integer
                  notes:
                    type: string
                  adjustments:
                    type: array
                  shipments:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        shipped_at:
                          type: string
                        tracking_number:
                          type: string
                        line_count:
                          type: integer
                        receipts:
                          type: array
                  financial_lines:
                    type: array
                example:
                  id: 501
                  transfer_type: standard
                  warehouse_transfer_number: WT-501
                  transfer_date: '2025-04-10'
                  from_warehouse:
                    id: 1
                    name: Main Warehouse
                  to_warehouse:
                    id: 3
                    name: East Coast DC
                  status: in_transit
                  shipment_status: shipped
                  shipment_percent: 100
                  receipt_status: partial
                  receipt_percent: 60
                  shipping_method: Ground
                  fully_shipped_at: '2025-04-11T14:00:00.000000Z'
                  fully_received_at: null
                  items: 3
                  eta: '2025-04-15'
                  created_at: '2025-04-10T08:00:00.000000Z'
                  updated_at: '2025-04-11T14:05:00.000000Z'
                  archived_at: null
                  tags:
                  - id: 5
                    name: urgent
                  line_item_count: 3
                  total_quantity: 150
                  notes: Rush transfer for East Coast restock
                  adjustments: []
                  shipments:
                  - id: 201
                    shipped_at: '2025-04-11T14:00:00.000000Z'
                    tracking_number: 1Z999AA1234567890
                    line_count: 3
                    receipts: []
                  financial_lines: []
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: warehouses:read
      operationId: get-api-v2-warehouse-transfers-warehousetransfer
  /api/v2/warehouse-transfers/{warehouseTransfer}/tab-counts:
    get:
      tags:
      - Adjustments & Transfers
      summary: Get Tab Counts
      description: 'Returns badge counts for all detail page tabs in a single request
        — line items, shipments, receipts, inventory movements, FIFO layers, allocations,
        activity log. Used to populate tab badges without loading each tab''s full
        data.


        :::info[Required scope: `warehouses:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: warehouseTransfer
        in: path
        schema:
          type: integer
        required: true
        description: Warehouse Transfer ID
        example: '501'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      line_items:
                        type: integer
                      shipments:
                        type: integer
                      receipts:
                        type: integer
                      inventory_movements:
                        type: integer
                      fifo_layers:
                        type: integer
                      allocations:
                        type: integer
                      activity_log:
                        type: integer
                example:
                  data:
                    line_items: 3
                    shipments: 1
                    receipts: 1
                    inventory_movements: 45
                    fifo_layers: 3
                    allocations: 2
                    activity_log: 12
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: warehouses:read
      operationId: get-api-v2-warehouse-transfers-warehousetransfer-tab-counts
  /api/v2/warehouse-transfers/{warehouseTransfer}/browse-products:
    get:
      tags:
      - Adjustments & Transfers
      summary: Browse Products
      description: 'Searches products that can be added to this warehouse transfer.
        Scoped to the transfer''s `from_warehouse`.


        :::info[Required scope: `warehouses:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        **Query Parameters**:

        - `query` — Product name or SKU search

        - `in_stock_only` — Restrict to products with stock in the source warehouse

        - `limit` — Max results (default: 25)'
      parameters:
      - name: query
        in: query
        schema:
          type: string
        description: Product search string (name or SKU)
        example: widget
      - name: in_stock_only
        in: query
        schema:
          type: boolean
        description: true — only return products with available stock in the from_warehouse
        example: 'true'
      - name: limit
        in: query
        schema:
          type: integer
        description: 'Maximum number of results (default: 25)'
        example: '25'
      - name: warehouseTransfer
        in: path
        schema:
          type: integer
        required: true
        description: Warehouse Transfer ID
        example: '501'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        sku:
                          type: string
                        name:
                          type: string
                        stock:
                          type: integer
                        available_stock:
                          type: integer
                example:
                  data:
                  - id: 812
                    sku: WIDGET-BLU
                    name: Blue Widget
                    stock: 45
                    available_stock: 38
                  - id: 813
                    sku: WIDGET-RED
                    name: Red Widget
                    stock: 20
                    available_stock: 20
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: warehouses:read
      operationId: get-api-v2-warehouse-transfers-warehousetransfer-browse-products
  /api/v2/warehouse-transfers/{warehouseTransfer}/line-items:
    get:
      tags:
      - Adjustments & Transfers
      summary: Get Line Items
      description: 'Returns the line items for a warehouse transfer, including product
        details, quantities, shipped/received quantities, and COGS values.


        :::info[Required scope: `warehouses:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: warehouseTransfer
        in: path
        schema:
          type: integer
        required: true
        description: Warehouse Transfer ID
        example: '501'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        product_id:
                          type: integer
                        product:
                          type: object
                          properties:
                            id:
                              type: integer
                            sku:
                              type: string
                            name:
                              type: string
                        quantity:
                          type: integer
                        shipped_quantity:
                          type: integer
                        received_quantity:
                          type: integer
                        unit_cost:
                          type: string
                        total_cost:
                          type: string
                        notes:
                          type: string
                          nullable: true
                example:
                  data:
                  - id: 3001
                    product_id: 812
                    product:
                      id: 812
                      sku: WIDGET-BLU
                      name: Blue Widget
                    quantity: 50
                    shipped_quantity: 50
                    received_quantity: 30
                    unit_cost: '12.50'
                    total_cost: '625.00'
                    notes: null
                  - id: 3002
                    product_id: 813
                    product:
                      id: 813
                      sku: WIDGET-RED
                      name: Red Widget
                    quantity: 100
                    shipped_quantity: 100
                    received_quantity: 60
                    unit_cost: '9.75'
                    total_cost: '975.00'
                    notes: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: warehouses:read
      operationId: get-api-v2-warehouse-transfers-warehousetransfer-line-items
  /api/v2/warehouse-transfers/{warehouseTransfer}/inventory-movements:
    get:
      tags:
      - Adjustments & Transfers
      summary: Get Inventory Movements
      description: 'Returns paginated inventory movements generated by this warehouse
        transfer (both ship-out and receive-in movements).


        :::info[Required scope: `warehouses:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        example: '1'
        description: Page number (default 1).
      - name: per_page
        in: query
        schema:
          type: integer
        example: '25'
        description: Results per page (default 10).
      - name: warehouseTransfer
        in: path
        schema:
          type: integer
        required: true
        description: Warehouse Transfer ID
        example: '501'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        type:
                          type: string
                        type_label:
                          type: string
                        product_id:
                          type: integer
                        product:
                          type: object
                          properties:
                            id:
                              type: integer
                            sku:
                              type: string
                        warehouse_id:
                          type: integer
                        warehouse:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        quantity:
                          type: integer
                        date:
                          type: string
                        created_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 88001
                    type: warehouse_transfer_ship
                    type_label: WT Ship
                    product_id: 812
                    product:
                      id: 812
                      sku: WIDGET-BLU
                    warehouse_id: 1
                    warehouse:
                      id: 1
                      name: Main Warehouse
                    quantity: -50
                    date: '2025-04-11'
                    created_at: '2025-04-11T14:00:00.000000Z'
                  - id: 88002
                    type: warehouse_transfer_receive
                    type_label: WT Receive
                    product_id: 812
                    product:
                      id: 812
                      sku: WIDGET-BLU
                    warehouse_id: 3
                    warehouse:
                      id: 3
                      name: East Coast DC
                    quantity: 30
                    date: '2025-04-13'
                    created_at: '2025-04-13T09:30:00.000000Z'
                  current_page: 1
                  last_page: 2
                  per_page: 25
                  total: 45
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: warehouses:read
      operationId: get-api-v2-warehouse-transfers-warehousetransfer-inventory-movements
  /api/v2/warehouse-transfers/{warehouseTransfer}/fifo-layers:
    get:
      tags:
      - Adjustments & Transfers
      summary: Get FIFO Layers
      description: 'Returns the FIFO inventory layers for this warehouse transfer
        (paginated).


        :::info[Required scope: `warehouses:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        **Two layer types depending on the transfer''s destination:**

        - **Standard transfers** (destination is a regular warehouse) return regular
        `FifoLayer` rows produced when the transfer was received. The `origin` object
        carries the polymorphic receipt-line link.

        - **Amazon inbound transfers** (destination is an Amazon FBA/AWD warehouse
        — i.e. FBA inbound, AWD inbound, or AWD→FBA replenishment) don''t produce
        regular `FifoLayer` rows; inventory enters Amazon and is tracked by `AmazonFifoLayer`.
        For these, the corresponding Amazon FIFO layers are returned in the same shape,
        each flagged with `is_amazon: true`, exposing `source_label` / `source_reference`
        (the Amazon source: ledger / discrepancy / initial inventory) in place of
        a receipt `origin`, plus a `detail_route` to the Amazon FIFO layer detail
        page. The Amazon layers are linked indirectly via the transfer''s Amazon inbound
        shipment(s) (`AmazonNewFbaInboundShipment.sku_link`).


        **Query Parameters**:

        - `per_page` — Items per page (default: 15)

        - `filter[search]` — Search by product SKU or name'
      parameters:
      - name: per_page
        in: query
        schema:
          type: integer
        example: '25'
        description: Results per page (default 10).
      - name: filter[search]
        in: query
        schema:
          type: string
        description: Search FIFO layers by product SKU or name
      - name: warehouseTransfer
        in: path
        schema:
          type: integer
        required: true
        description: Warehouse Transfer ID
        example: '501'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 OK — Standard transfer (regular FIFO layers)
                  value:
                    data:
                    - id: 7701
                      is_amazon: false
                      product_id: 812
                      fifo_layer_date: '2025-04-13T09:30:00.000000Z'
                      sku: WIDGET-BLU
                      product_name: Blue Widget
                      original_quantity: 30
                      fulfilled_quantity: 2
                      available_quantity: 28
                      avg_cost: '12.5000'
                      total_cost: '375.0000'
                      origin:
                        link_type: App\Models\WarehouseTransferShipmentReceiptLine
                        link_id: 44012
                        name: Warehouse Transfer Receipt Line
                        parent_link_id: 9120
                        detail_link_id: 501
                        reference: WT-501
                        parent_reference: WT-501
                        manufacturing_order: null
                      warehouse:
                        id: 3
                        name: East Coast DC
                      created_at: '2025-04-13T09:30:00.000000Z'
                    current_page: 1
                    last_page: 1
                    per_page: 15
                    total: 3
                example-1:
                  summary: 200 OK — Amazon inbound transfer (Amazon FIFO layers)
                  value:
                    data:
                    - id: 90431
                      is_amazon: true
                      fifo_layer_date: '2025-05-02T14:10:00.000000Z'
                      product_id: 812
                      sku: WIDGET-BLU
                      product_name: Blue Widget
                      original_quantity: 120
                      fulfilled_quantity: 45
                      available_quantity: 75
                      avg_cost: 12.5
                      total_cost: 1500.0
                      origin: null
                      source_label: Ledger
                      source_reference: AMZ-LEDGER-558123
                      detail_route: /integrations/amazon/fba/inventory-and-valuation/fifo-layers/90431
                      created_at: '2025-05-02T14:10:00.000000Z'
                    current_page: 1
                    last_page: 1
                    per_page: 15
                    total: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: warehouses:read
      operationId: get-api-v2-warehouse-transfers-warehousetransfer-fifo-layers
  /api/cogs/sku-health/{productId}/cost-composition:
    get:
      tags:
      - Adjustments & Transfers
      summary: Get Product Cost Composition
      description: 'Returns the per-component cost composition of a product''s weighted-average
        unit cost — how much each consumed component (and any landed-cost or labor
        category) contributes to the average unit cost. Useful for manufactured or
        assembled goods to see what makes up the final cost, not just the blended
        number.


        Aggregated across the product''s active warehouse FIFO layers, prorated by
        each layer''s remaining quantity, so the composition ties out to the weighted-average
        cost. Amazon FBA inventory is excluded (separate WAC ledger). Layers with
        no categorized breakdown fall into an "Uncategorized" bucket.


        Authentication: Requires Bearer token.'
      parameters:
      - name: productId
        in: path
        schema:
          type: integer
        required: true
        description: Product ID
        example: '101'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      components:
                        type: array
                        items:
                          type: object
                          properties:
                            category:
                              type: string
                            total:
                              type: integer
                            per_unit:
                              type: integer
                            pct:
                              type: integer
                      total_available:
                        type: integer
                      avg_cost:
                        type: integer
                example:
                  data:
                    components:
                    - category: Helmet Shell
                      total: 400
                      per_unit: 40
                      pct: 80
                    - category: Carry Pouch
                      total: 60
                      per_unit: 6
                      pct: 12
                    - category: Sticker Pack
                      total: 40
                      per_unit: 4
                      pct: 8
                    total_available: 10
                    avg_cost: 50
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-cogs-sku-health-productid-cost-composition
  /api/v2/warehouse-transfers/{warehouseTransfer}/allocations:
    get:
      tags:
      - Adjustments & Transfers
      summary: Get Allocations
      description: 'Returns inventory allocations linked to this warehouse transfer.


        :::info[Required scope: `warehouses:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        **Query Parameters**:

        - `filter[status]` — `all` | `active` | `pending` | `released` | `cancelled`
        | `fulfilled`

        - `filter[warehouse_id]` — Filter by warehouse

        - `filter[search]` — Search by product SKU or name

        - `per_page` — Items per page'
      parameters:
      - name: filter[status]
        in: query
        schema:
          type: string
        description: 'Allocation status filter: all | active | pending | released
          | cancelled | fulfilled'
        example: all
      - name: filter[warehouse_id]
        in: query
        schema:
          type: string
        description: Filter by destination warehouse ID
      - name: filter[search]
        in: query
        schema:
          type: string
        description: Search by product SKU or name
      - name: per_page
        in: query
        schema:
          type: integer
        example: '25'
        description: Results per page (default 10).
      - name: warehouseTransfer
        in: path
        schema:
          type: integer
        required: true
        description: Warehouse Transfer ID
        example: '501'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        product_id:
                          type: integer
                        product:
                          type: object
                          properties:
                            id:
                              type: integer
                            sku:
                              type: string
                            name:
                              type: string
                        warehouse_id:
                          type: integer
                        warehouse:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        quantity:
                          type: integer
                        status:
                          type: string
                        status_label:
                          type: string
                        priority:
                          type: integer
                        created_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 10045
                    product_id: 812
                    product:
                      id: 812
                      sku: WIDGET-BLU
                      name: Blue Widget
                    warehouse_id: 3
                    warehouse:
                      id: 3
                      name: East Coast DC
                    quantity: 5
                    status: pending
                    status_label: Pending
                    priority: 1
                    created_at: '2025-04-10T08:22:11.000000Z'
                  current_page: 1
                  last_page: 1
                  per_page: 25
                  total: 2
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: warehouses:read
      operationId: get-api-v2-warehouse-transfers-warehousetransfer-allocations
  /api/v2/warehouse-transfers/{warehouseTransfer}/generate-accounting-transactions:
    post:
      tags:
      - Adjustments & Transfers
      summary: Generate Accounting Transactions
      description: 'Generates or regenerates accounting transactions (financial lines)
        for this warehouse transfer based on the current COGS data.


        :::info[Required scope: `warehouses:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties: {}
              example: {}
      parameters:
      - name: warehouseTransfer
        in: path
        schema:
          type: integer
        required: true
        description: Warehouse Transfer ID
        example: '501'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  financial_lines_count:
                    type: integer
                example:
                  message: Accounting transactions generated successfully.
                  financial_lines_count: 6
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: warehouses:write
      operationId: post-api-v2-warehouse-transfers-warehousetransfer-generate-accounting-transactions
  /api/warehouses/transfers/{transfer}/receiving-discrepancy:
    post:
      tags:
      - Adjustments & Transfers
      summary: Create Receiving Discrepancy
      description: 'Creates a receiving-discrepancy accounting transaction for a warehouse
        transfer, recording the financial gain/loss from the difference between expected
        and received quantities.


        :::info[Required scope: `warehouses:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Request body:

        - `transaction_date` (optional, date) — date to record the transaction on;
        defaults to now when omitted.


        Note: Receiving discrepancies cannot be created for Amazon-to-Amazon transfers
        (e.g. AWD→FBA) — Amazon reconciles those transfers automatically, so the endpoint
        returns 400.


        **Requires permission:** `warehouse_transfers.receive`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                transaction_date:
                  type: string
              example:
                transaction_date: '2026-05-15'
      parameters:
      - name: transfer
        in: path
        schema:
          type: integer
        required: true
        description: Warehouse Transfer ID
        example: '501'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Successfully closed with receiving discrepancy
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 400 Amazon-to-Amazon Transfer
                  value:
                    errors:
                      warehouse_transfer_id:
                      - message: Receiving discrepancies cannot be created for Amazon-to-Amazon
                          transfers. Amazon reconciles these transfers automatically.
                        code: ReceivingDiscrepancyNotAllowedForAmazonTransfer
                example-1:
                  summary: 400 Discrepancy Already Exists
                  value:
                    errors:
                      purchase_order_id:
                      - message: A receiving discrepancy already exists for this transfer.
                        code: ReceivingDiscrepancyAlreadyExists
                example-2:
                  summary: 400 Missing Nominal Code Mapping
                  value:
                    errors:
                      nominal_code_id:
                      - message: A nominal code mapping is required to record receiving
                          discrepancies.
                        code: ReceivingDiscrepancyMissingNominalCodeMapping
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      transaction_date:
                        type: array
                        items:
                          type: string
                example:
                  message: The transaction date field must be a valid date.
                  errors:
                    transaction_date:
                    - The transaction date field must be a valid date.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: warehouses:write
      operationId: post-api-warehouses-transfers-transfer-receiving-discrepancy
  /api/v2/warehouse-transfers/{warehouseTransfer}/activity-log:
    get:
      tags:
      - Adjustments & Transfers
      summary: Get Transfer Activity Log
      description: 'Returns paginated activity log entries for a warehouse transfer.


        :::info[Required scope: `warehouses:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: per_page
        in: query
        schema:
          type: integer
        example: '25'
        description: Results per page (default 10).
      - name: filter[search]
        in: query
        schema:
          type: string
        description: Search activity log entries
      - name: warehouseTransfer
        in: path
        schema:
          type: integer
        required: true
        description: Warehouse Transfer ID
        example: '501'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        event:
                          type: string
                        description:
                          type: string
                        causer:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        created_at:
                          type: string
                        properties:
                          type: object
                          properties: {}
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 9901
                    event: created
                    description: Warehouse transfer WT-501 created
                    causer:
                      id: 1
                      name: Jane Smith
                    created_at: '2025-04-10T08:00:00.000000Z'
                    properties: {}
                  - id: 9902
                    event: updated
                    description: Status changed to in_transit
                    causer:
                      id: 1
                      name: Jane Smith
                    created_at: '2025-04-11T14:05:00.000000Z'
                    properties:
                      old:
                        status: pending
                      new:
                        status: in_transit
                  current_page: 1
                  last_page: 1
                  per_page: 25
                  total: 12
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: warehouses:read
      operationId: get-api-v2-warehouse-transfers-warehousetransfer-activity-log
  /api/warehouses/transfers/import-lines/template:
    get:
      tags:
      - Adjustments & Transfers
      summary: Download Lines Import Template
      description: 'Downloads a multi-sheet XLSX template for the warehouse transfer
        lines bulk import.


        :::info[Required scope: `warehouses:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        **Response**: A binary `.xlsx` file (zip-based Office Open XML).

        - `Content-Type`: `application/vnd.openxmlformats-officedocument.spreadsheetml.sheet`

        - `Content-Disposition`: `attachment; filename="warehouse-transfer-lines-import-template-YYYY-MM-DD.xlsx"`


        **Sheets:**

        1. **Import Here** — the row-data sheet with two required columns (`sku`,
        `quantity`) plus 3 example rows. Header row is frozen; columns are autofiltered;
        the SKU column has a comment explaining required fields.

        2. **Field Guide** — reference sheet describing each column (Required, Description,
        Valid Values, Example).


        No query parameters or request body. Used by the "Import Lines from CSV" workflow
        on the warehouse transfer detail page (the resulting filled-out file is then
        POSTed to `/api/warehouses/transfers/import-lines`).


        **Requires permission:** `warehouse_transfers.import`'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
            Content-Disposition:
              schema:
                type: string
                example: attachment; filename="warehouse-transfer-lines-import-template-2026-05-07.xlsx"
          content:
            text/plain:
              schema:
                type: string
                example: <binary XLSX file — zip archive starting with PK\x03\x04
                  signature>
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: warehouses:read
      operationId: get-api-warehouses-transfers-import-lines-template
  /api/warehouses/transfers/import-lines:
    post:
      tags:
      - Adjustments & Transfers
      summary: Import Warehouse Transfer Lines
      description: 'Imports line items into an existing warehouse transfer from CSV
        data. Provide either file (a stored upload reference) or csvString (inline
        CSV content). The CSV must contain a sku column; quantity is optional and
        defaults to 1. Rows with the same SKU are merged and quantities summed.


        :::info[Required scope: `warehouses:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Fields: warehouse_transfer_id (required), file or csvString (one required),
        replace (boolean - when true, replaces all existing lines instead of adding),
        separator (default ",") and escape (default ''"'').


        Returns 400 when the CSV contains SKUs that do not match any product. Download
        a template from GET /api/warehouses/transfers/import-lines/template.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                warehouse_transfer_id:
                  type: integer
                csvString:
                  type: string
                replace:
                  type: boolean
                separator:
                  type: string
              example:
                warehouse_transfer_id: 512
                csvString: 'sku,quantity

                  WIDGET-001,100

                  WIDGET-002,50'
                replace: false
                separator: ','
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: warehouse transfer lines imported successfully.
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      unknown_skus:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: array
                              items:
                                type: string
                example:
                  message: The CSV contains unknown products
                  errors:
                    unknown_skus:
                    - message: The CSV contains unknown products
                      code: Product404
                      data:
                      - UNKNOWN-SKU-1
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: warehouses:write
      operationId: post-api-warehouses-transfers-import-lines
  /api/v2/warehouse-transfers/export:
    get:
      tags:
      - Adjustments & Transfers
      summary: Export Warehouse Transfers
      description: 'Download warehouse transfers as an XLSX or CSV file. Requires
        export permission for warehouse transfers.


        :::info[Required scope: `warehouses:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Export controls:

        - `format` — xlsx (default) or csv.

        - `content_mode` — summary (default, one row per transfer) or line_items (one
        row per transfer line, with the transfer columns repeated and line columns
        appended: Line ID, Item SKU, Item Name, Item Description, Item Qty, Cancelled
        Qty, Item FNSKU).

        - `scope` — filtered (default: respects active filters/search), all (ignores
        filters), current_page (only the current page of the list), or selected (only
        the IDs passed in `ids`).

        - `ids` — comma-separated transfer IDs; required when scope=selected.

        - `columns` — comma-separated column keys to restrict/reorder transfer-level
        columns. Available keys: id, warehouse_transfer_number, transfer_date, from_warehouse,
        to_warehouse, transfer_type, status, shipment_status, receipt_status, shipping_method,
        shipment_id, line_item_count, eta, fully_shipped_at, fully_received_at, tags,
        created_at, updated_at (plus any custom-field columns defined for transfers).


        Filters (same set as List Warehouse Transfers; applied when scope is filtered
        or current_page):

        - `filter[search]` — matches transfer ID, transfer number, from/to warehouse
        name, item SKU, and item FNSKU.

        - `filter[archived]` — archived visibility: omit for non-archived only, `only`
        for archived only, `all` for everything.

        - `filter[include_deleted]` — `include` adds deleted transfers, `only` returns
        just deleted ones.

        - `filter[transfer_status.{op}]`, `filter[shipment_status.{op}]`, `filter[receipt_status.{op}]`
        — text operators; receipt_status also accepts the special value received_for_less.

        - `filter[transfer_type.{op}]` — values: standard, fba_inbound, awd_inbound,
        awd_fba_replenishment; operators: is, is_not, is_one_of, is_not_one_of.

        - `filter[has_blemished.is]=1` / `filter[has_inbound_plan.is]=1` — flag filters
        (is / is_not).

        - `filter[id.{op}]` — numeric operators.

        - `filter[from_warehouse.{op}]`, `filter[to_warehouse.{op}]` — warehouse ID,
        text operators.

        - `filter[transfer_date.{op}]`, `filter[created_at.{op}]`, `filter[updated_at.{op}]`
        — date operators.


        Text operators: contains, does_not_contain, is, is_not, is_one_of, is_not_one_of,
        starts_with, does_not_start_with, ends_with, does_not_end_with, is_empty,
        is_not_empty. Numeric operators: is, is_not, is_one_of, is_not_one_of, greater_than,
        less_than, greater_than_or_equal, less_than_or_equal, between, is_empty, is_not_empty.
        Date operators: is, is_not, before, after, on_or_before, on_or_after, between,
        is_empty, is_not_empty, today, yesterday, tomorrow, past_week, past_month,
        past_year, next_week, next_month, next_year, days_ago, days_from_now, past_days,
        next_days.


        `filter_groups` — base64-encoded JSON tree for nested AND/OR filter groups
        over the same columns.


        Sorting: `sort` with optional `-` prefix for descending. Allowed sorts: id,
        warehouse_transfer_number, transfer_date, transfer_status, shipment_status,
        receipt_status, created_at, updated_at, eta, archived_at, asn_last_sent_at,
        status, from_warehouse_name, to_warehouse_name, from_warehouse, to_warehouse.
        Default: -transfer_date.


        Response: binary file download (Content-Type application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
        for xlsx, text/csv for csv).


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
            Content-Disposition:
              schema:
                type: string
                example: attachment; filename=warehouse-transfers-2026-07-06-12-30-00.xlsx
          content:
            text/plain:
              schema:
                type: string
                example: (binary XLSX file download — one row per warehouse transfer,
                  or per line item when content_mode=line_items)
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: warehouses:read
      operationId: get-api-v2-warehouse-transfers-export
  /api/v2/warehouse-transfers/filter-options:
    get:
      tags:
      - Adjustments & Transfers
      summary: Get Warehouse Transfer Filter Options
      description: 'Returns the list of warehouses available for filtering warehouse
        transfers, as id/name pairs (Amazon FBA, virtual, and supplier warehouses
        are excluded, and archived warehouses are omitted). Use it to populate the
        warehouse filter dropdowns on the transfers list.


        :::info[Required scope: `warehouses:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      warehouses:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                example:
                  data:
                    warehouses:
                    - id: 1
                      name: Main Warehouse
                    - id: 2
                      name: East Coast DC
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: warehouses:read
      operationId: get-api-v2-warehouse-transfers-filter-options
  /api/warehouses/transfers/{transfer}/shipments:
    post:
      tags:
      - Adjustments & Transfers
      summary: Create Shipment
      description: "Creates a shipment for an already-open traditional (non-Amazon\
        \ FBA) warehouse transfer. This is the explicit second step of the split lifecycle:\
        \ open the transfer first (allocations only), then ship.\n\n:::info[Required\
        \ scope: `warehouses:write`]\nGrant this scope to your token under [Settings\
        \ → Developer → Personal Access Tokens](https://app.sku.io/settings/api).\n\
        :::\n\n**Effects:**\n- Deducts source warehouse stock\n- Creates `-active`\
        \ and `+in_transit` inventory movements\n- Fulfils the line-level allocations\
        \ created during open (Allocated → Fulfilled)\n\n**Request body (all fields\
        \ optional unless noted):**\n- `shipment_date` (date) — defaults to today\
        \ if omitted\n- `shipping_method_id` (integer) — must exist in `shipping_methods`\n\
        - `tracking_number` (string, max 255)\n- `cost` (numeric, >= 0, < 100000)\n\
        - `lines` (array, min 1 when present) — if omitted, all remaining open line\
        \ quantities are shipped\n  - `lines[].warehouse_transfer_line_id` (integer,\
        \ required_with:lines) — must belong to the transfer\n  - `lines[].quantity`\
        \ (numeric, required_with:lines, min 0.0001)\n\n**Responses:**\n- `201 Created`\
        \ — warehouse transfer object with updated shipments\n- `422 Unprocessable\
        \ Entity` (`WarehouseTransferIsNotOpen`) — transfer is not in open status\n\
        - `422 Unprocessable Entity` (`WarehouseTransferLineIsUnacceptable`) — a transfer\
        \ line's requested quantity exceeds its allocated sum (allocations out of\
        \ sync, e.g. stuck Fulfilled rows); the message includes the product SKU and\
        \ the allocated quantity\n- `422 Unprocessable Entity` — transfer is an Amazon\
        \ FBA transfer (use the Amazon-specific flow instead)\n- `400 Bad Request`\
        \ (`ProductIsUnacceptable`) — not enough stock at the source warehouse for\
        \ one of the requested lines\n\n**Requires permission:** `warehouse_transfers.ship`\n\
        Form Request: `App\\Http\\Requests\\CreateWarehouseTransferShipmentRequest`\n\
        Route name: `warehouses.transfers.shipments.store`\n\nSource bin: each line\
        \ may optionally set `warehouse_location_id` — the source-warehouse bin the\
        \ line's dispatch should draw stock from. It must be an active (non-deprecated)\
        \ bin in the transfer's source warehouse. When omitted, pickable source bins\
        \ are walked automatically."
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                shipment_date:
                  type: string
                shipping_method_id:
                  type: integer
                tracking_number:
                  type: string
                cost:
                  type: number
                lines:
                  type: array
                  items:
                    type: object
                    properties:
                      warehouse_transfer_line_id:
                        type: integer
                      quantity:
                        type: integer
                      warehouse_location_id:
                        type: integer
              example:
                shipment_date: '2026-06-12'
                shipping_method_id: 3
                tracking_number: 1Z999AA10123456784
                cost: 25.5
                lines:
                - warehouse_transfer_line_id: 87499
                  quantity: 150
                  warehouse_location_id: 15
      parameters:
      - name: transfer
        in: path
        schema:
          type: integer
        required: true
        description: Warehouse transfer ID (must be in open status)
        example: '38207'
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      warehouse_transfer_number:
                        type: string
                      transfer_status:
                        type: string
                      shipment_status:
                        type: string
                      from_warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      to_warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      transfer_date:
                        type: string
                      shipments:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            tracking_number:
                              type: string
                            shipped_at:
                              type: string
                            lines:
                              type: array
                              items:
                                type: object
                                properties:
                                  id:
                                    type: integer
                                  warehouse_transfer_line_id:
                                    type: integer
                                  quantity:
                                    type: integer
                  message:
                    type: string
                example:
                  data:
                    id: 38207
                    warehouse_transfer_number: WH-38207
                    transfer_status: open
                    shipment_status: shipped
                    from_warehouse:
                      id: 7
                      name: Main Warehouse
                    to_warehouse:
                      id: 8
                      name: Overflow Warehouse
                    transfer_date: '2026-06-12'
                    shipments:
                    - id: 901
                      tracking_number: 1Z999AA10123456784
                      shipped_at: '2026-06-12T16:00:00.000000Z'
                      lines:
                      - id: 4001
                        warehouse_transfer_line_id: 87499
                        quantity: 150
                  message: The warehouse transfer shipment created successfully
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: object
                    properties:
                      product:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: object
                              properties:
                                product_id:
                                  type: integer
                example:
                  errors:
                    product:
                    - message: There is no quantity available for the product with
                        SKU RC-SERUM-30ML
                      code: ProductIsUnacceptable
                      data:
                        product_id: 812
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 422 — transfer not open
                  value:
                    errors:
                      transfer_id:
                      - message: 'Warehouse transfer #38207 is not in open status'
                        code: WarehouseTransferIsNotOpen
                        data:
                          transfer_id: 38207
                example-1:
                  summary: 422 — transfer line not allocated
                  value:
                    errors:
                      warehouse_transfer_line:
                      - message: Cannot ship 150 units of product (RC-SERUM-30ML)
                          — only 0 units are allocated to this transfer line. The
                          transfer's inventory allocations are out of sync; re-open
                          the transfer or contact support.
                        code: WarehouseTransferLineIsUnacceptable
                        data:
                          warehouse_transfer_line_id: 87499
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: warehouses:write
      operationId: post-api-warehouses-transfers-transfer-shipments
  /api/v2/warehouse-transfers/shipments/{shipment}:
    get:
      tags:
      - Adjustments & Transfers
      summary: Get Shipment Detail
      description: 'Returns the detail view of a specific warehouse transfer shipment,
        including shipment lines and any associated receipts.


        :::info[Required scope: `warehouses:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: shipment
        in: path
        schema:
          type: integer
        required: true
        description: Shipment ID
        example: '201'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: integer
                  warehouse_transfer_id:
                    type: integer
                  shipped_at:
                    type: string
                  tracking_number:
                    type: string
                  carrier:
                    type: string
                  notes:
                    type: string
                    nullable: true
                  lines:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        warehouse_transfer_line_id:
                          type: integer
                        product_id:
                          type: integer
                        product:
                          type: object
                          properties:
                            id:
                              type: integer
                            sku:
                              type: string
                            name:
                              type: string
                        quantity:
                          type: integer
                  receipts:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        received_at:
                          type: string
                        received_by:
                          type: string
                  created_at:
                    type: string
                  updated_at:
                    type: string
                example:
                  id: 201
                  warehouse_transfer_id: 501
                  shipped_at: '2025-04-11T14:00:00.000000Z'
                  tracking_number: 1Z999AA1234567890
                  carrier: UPS
                  notes: null
                  lines:
                  - id: 4001
                    warehouse_transfer_line_id: 3001
                    product_id: 812
                    product:
                      id: 812
                      sku: WIDGET-BLU
                      name: Blue Widget
                    quantity: 50
                  receipts:
                  - id: 301
                    received_at: '2025-04-13T09:30:00.000000Z'
                    received_by: John Doe
                  created_at: '2025-04-11T14:00:00.000000Z'
                  updated_at: '2025-04-13T09:30:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: warehouses:read
      operationId: get-api-v2-warehouse-transfers-shipments-shipment
  /api/v2/warehouse-transfers/shipments/{shipment}/lines/{line}/quantity-preview:
    get:
      tags:
      - Adjustments & Transfers
      summary: Preview Shipment Line Quantity Change
      description: 'Preview the inventory implications of changing a warehouse transfer
        shipment line''s quantity, without persisting any change.


        :::info[Required scope: `warehouses:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Returns:

        - `current_quantity`, `new_quantity`, `delta`

        - `requires_confirmation` — true whenever delta != 0

        - `can_update` — false when either block applies

        - `blocks.below_received` — true if the requested quantity is below the total
        already received against this line; adjust receipts first

        - `blocks.above_transfer_line` — true if the requested quantity exceeds the
        parent warehouse transfer line quantity (the WT line caps the shipment, not
        source on-hand stock)

        - `implications.shipment_quantity` / `transfer_quantity` / `received_quantity`
        / `in_transit_quantity` — current vs after-update values. The parent warehouse
        transfer line quantity is ALWAYS unchanged (BBP invariant: the WT line is
        the canonical record of original intent).'
      parameters:
      - name: quantity
        in: query
        schema:
          type: integer
        description: Target shipment line quantity (integer, >= 0). Required.
        example: '12'
      - name: shipment
        in: path
        schema:
          type: integer
        required: true
        description: Warehouse transfer shipment ID
        example: '201'
      - name: line
        in: path
        schema:
          type: integer
        required: true
        description: Warehouse transfer shipment line ID
        example: '4001'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      shipment_id:
                        type: integer
                      line_id:
                        type: integer
                      current_quantity:
                        type: integer
                      new_quantity:
                        type: integer
                      delta:
                        type: integer
                      requires_confirmation:
                        type: boolean
                      can_update:
                        type: boolean
                      blocks:
                        type: object
                        properties:
                          below_received:
                            type: boolean
                          above_transfer_line:
                            type: boolean
                      implications:
                        type: object
                        properties:
                          shipment_quantity:
                            type: object
                            properties:
                              label:
                                type: string
                              current:
                                type: integer
                              after_update:
                                type: integer
                          transfer_quantity:
                            type: object
                            properties:
                              label:
                                type: string
                              current:
                                type: integer
                              after_update:
                                type: integer
                          received_quantity:
                            type: object
                            properties:
                              label:
                                type: string
                              current:
                                type: integer
                              after_update:
                                type: integer
                          in_transit_quantity:
                            type: object
                            properties:
                              label:
                                type: string
                              current:
                                type: integer
                              after_update:
                                type: integer
                example:
                  data:
                    shipment_id: 201
                    line_id: 4001
                    current_quantity: 10
                    new_quantity: 8
                    delta: -2
                    requires_confirmation: true
                    can_update: true
                    blocks:
                      below_received: false
                      above_transfer_line: false
                    implications:
                      shipment_quantity:
                        label: Warehouse transfer shipment line quantity
                        current: 10
                        after_update: 8
                      transfer_quantity:
                        label: Warehouse transfer line quantity (unchanged)
                        current: 10
                        after_update: 10
                      received_quantity:
                        label: Already received against this line
                        current: 0
                        after_update: 0
                      in_transit_quantity:
                        label: In-transit at destination after edit
                        current: 10
                        after_update: 8
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Shipment line does not belong to this warehouse transfer
                    shipment.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: warehouses:read
      operationId: get-api-v2-warehouse-transfers-shipments-shipment-lines-line-quantity-preview
  /api/v2/warehouse-transfers/shipments/{shipment}/lines/{line}:
    patch:
      tags:
      - Adjustments & Transfers
      summary: Update Shipment Line Quantity
      description: 'Update a warehouse transfer shipment line''s quantity in place,
        scaling its inventory movements at the source (active negative) and destination
        (in-transit positive) accordingly.


        :::info[Required scope: `warehouses:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Request body:

        - `quantity` (integer, required, >= 0) — new shipment line quantity. Capped
        by the parent warehouse transfer line quantity.

        - `confirmed_implications` (boolean, optional) — must be `true` when the change
        is non-zero; otherwise the endpoint returns 409 with the preview payload so
        the caller can confirm.


        Behavior:

        - Increase: pulls `delta` additional units from source on-hand FIFO and places
        them in-transit toward the destination.

        - Decrease: returns `abs(delta)` units to source on-hand and removes them
        from in-transit at the destination.

        - The parent warehouse transfer line quantity is NEVER mutated by this endpoint
        — it preserves the original transfer intent (BBP invariant).


        Errors:

        - `409 Conflict` — non-zero delta without `confirmed_implications: true`;
        the preview is returned in `data` so callers can render and confirm.

        - `422 Unprocessable Entity` with `data.blocks.below_received: true` — requested
        quantity is below the total already received against this line; adjust receipts
        first.

        - `422 Unprocessable Entity` with `data.blocks.above_transfer_line: true`
        — requested quantity exceeds the parent warehouse transfer line quantity.

        - `422 Unprocessable Entity` from `InsufficientStockException` thrown by the
        inventory manager if FIFO consumption cannot satisfy the delta at the moment
        of save (race / concurrency safety net).


        **Requires permission:** `warehouse_transfers.ship`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                quantity:
                  type: integer
                confirmed_implications:
                  type: boolean
              example:
                quantity: 12
                confirmed_implications: true
      parameters:
      - name: shipment
        in: path
        schema:
          type: integer
        required: true
        description: Warehouse transfer shipment ID
        example: '201'
      - name: line
        in: path
        schema:
          type: integer
        required: true
        description: Warehouse transfer shipment line ID
        example: '4001'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      warehouse_transfer:
                        type: object
                        properties:
                          id:
                            type: integer
                          warehouse_transfer_number:
                            type: string
                      from_warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      to_warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      shipping_method:
                        type: string
                        nullable: true
                      tracking_number:
                        type: string
                      shipped_at:
                        type: string
                      fully_received_at:
                        type: string
                        nullable: true
                      auto_generated_at_receipt:
                        type: boolean
                      summary:
                        type: object
                        properties:
                          total_lines:
                            type: integer
                          total_shipped:
                            type: integer
                          total_received:
                            type: integer
                          total_receipts:
                            type: integer
                      lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            product:
                              type: object
                              properties:
                                id:
                                  type: integer
                                sku:
                                  type: string
                                name:
                                  type: string
                                image_url:
                                  type: string
                                  nullable: true
                            description:
                              type: string
                              nullable: true
                            quantity:
                              type: integer
                            received_quantity:
                              type: integer
                      receipts:
                        type: array
                  message:
                    type: string
                example:
                  data:
                    id: 201
                    warehouse_transfer:
                      id: 501
                      warehouse_transfer_number: WT-0501
                    from_warehouse:
                      id: 7
                      name: Main Warehouse
                    to_warehouse:
                      id: 8
                      name: Overflow Warehouse
                    shipping_method: null
                    tracking_number: 1Z999AA1234567890
                    shipped_at: '2025-04-11T14:00:00.000000Z'
                    fully_received_at: null
                    auto_generated_at_receipt: false
                    summary:
                      total_lines: 1
                      total_shipped: 12
                      total_received: 0
                      total_receipts: 0
                    lines:
                    - id: 4001
                      product:
                        id: 812
                        sku: WIDGET-BLU
                        name: Blue Widget
                        image_url: null
                      description: null
                      quantity: 12
                      received_quantity: 0
                    receipts: []
                  message: Shipment line quantity updated successfully.
        '409':
          description: Conflict
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      shipment_id:
                        type: integer
                      line_id:
                        type: integer
                      current_quantity:
                        type: integer
                      new_quantity:
                        type: integer
                      delta:
                        type: integer
                      requires_confirmation:
                        type: boolean
                      can_update:
                        type: boolean
                      blocks:
                        type: object
                        properties:
                          below_received:
                            type: boolean
                          above_transfer_line:
                            type: boolean
                      caps:
                        type: object
                        properties:
                          transfer_line_quantity:
                            type: integer
                          received_total:
                            type: integer
                      implications:
                        type: object
                        properties:
                          shipment_quantity:
                            type: object
                            properties:
                              current:
                                type: integer
                              after_update:
                                type: integer
                          transfer_quantity:
                            type: object
                            properties:
                              current:
                                type: integer
                              after_update:
                                type: integer
                          received_quantity:
                            type: object
                            properties:
                              current:
                                type: integer
                              after_update:
                                type: integer
                          in_transit_quantity:
                            type: object
                            properties:
                              current:
                                type: integer
                              after_update:
                                type: integer
                example:
                  message: Confirm the shipment quantity implications before saving.
                  data:
                    shipment_id: 201
                    line_id: 4001
                    current_quantity: 10
                    new_quantity: 8
                    delta: -2
                    requires_confirmation: true
                    can_update: true
                    blocks:
                      below_received: false
                      above_transfer_line: false
                    caps:
                      transfer_line_quantity: 10
                      received_total: 0
                    implications:
                      shipment_quantity:
                        current: 10
                        after_update: 8
                      transfer_quantity:
                        current: 10
                        after_update: 10
                      received_quantity:
                        current: 0
                        after_update: 0
                      in_transit_quantity:
                        current: 10
                        after_update: 8
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 422 — below received
                  value:
                    message: Shipment quantity cannot be set below the total already
                      received against this line.
                    data:
                      blocks:
                        below_received: true
                        above_transfer_line: false
                example-1:
                  summary: 422 — above transfer line
                  value:
                    message: Shipment quantity cannot exceed the parent warehouse
                      transfer line quantity.
                    data:
                      blocks:
                        below_received: false
                        above_transfer_line: true
                      caps:
                        transfer_line_quantity: 10
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: warehouses:write
      operationId: patch-api-v2-warehouse-transfers-shipments-shipment-lines-line
  /api/v2/warehouse-transfers/shipments/{shipment}/activity-log:
    get:
      tags:
      - Adjustments & Transfers
      summary: Get Shipment Activity Log
      description: 'Returns paginated activity log entries for a specific shipment.


        :::info[Required scope: `warehouses:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: per_page
        in: query
        schema:
          type: integer
        example: '25'
        description: Results per page (default 10).
      - name: filter[search]
        in: query
        schema:
          type: string
        description: Search activity log entries
      - name: shipment
        in: path
        schema:
          type: integer
        required: true
        description: Shipment ID
        example: '201'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        event:
                          type: string
                        description:
                          type: string
                        causer:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        created_at:
                          type: string
                        properties:
                          type: object
                          properties: {}
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 9910
                    event: created
                    description: Shipment created with tracking 1Z999AA1234567890
                    causer:
                      id: 1
                      name: Jane Smith
                    created_at: '2025-04-11T14:00:00.000000Z'
                    properties: {}
                  current_page: 1
                  last_page: 1
                  per_page: 25
                  total: 3
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: warehouses:read
      operationId: get-api-v2-warehouse-transfers-shipments-shipment-activity-log
  /api/v2/warehouse-transfers/shipments/{shipment}/inventory-movements:
    get:
      tags:
      - Adjustments & Transfers
      summary: Get Shipment Inventory Movements
      description: 'Returns paginated inventory movements scoped to the given warehouse
        transfer shipment. Movements are linked to the shipment''s `WarehouseTransferShipmentLine`
        records (negative inventory events — stock leaving the source warehouse).
        Includes movement type, quantity, FIFO layer link, unit/total cost, and product/warehouse
        references for each movement. Used by the Movements tab on the shipment detail
        page.


        :::info[Required scope: `warehouses:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        description: Page number (default 1)
        example: '1'
      - name: per_page
        in: query
        schema:
          type: integer
        description: Items per page (default 25)
        example: '25'
      - name: shipment
        in: path
        schema:
          type: integer
        required: true
        description: Shipment ID
        example: '201'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        type:
                          type: string
                        inventory_status:
                          type: string
                        quantity:
                          type: integer
                        reference:
                          type: string
                        link_type:
                          type: string
                        link_id:
                          type: integer
                        parent_link_id:
                          type: integer
                        detail_link_id:
                          type: string
                          nullable: true
                        product_id:
                          type: integer
                        product_sku:
                          type: string
                        product_name:
                          type: string
                        warehouse_id:
                          type: integer
                        warehouse_name:
                          type: string
                        unit_cost:
                          type: number
                        unit_cost_provisional:
                          type: boolean
                        total_cost:
                          type: number
                        layer:
                          type: object
                          properties:
                            name:
                              type: string
                            layer_type:
                              type: string
                            layer_id:
                              type: integer
                        inventory_movement_date:
                          type: string
                        created_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - id: 87553
                    type: transfer
                    inventory_status: available
                    quantity: -10
                    reference: WT-2025-0042
                    link_type: App\Models\WarehouseTransferShipmentLine
                    link_id: 4012
                    parent_link_id: 201
                    detail_link_id: null
                    product_id: 812
                    product_sku: WIDGET-BLU
                    product_name: Blue Widget
                    warehouse_id: 8
                    warehouse_name: Source Warehouse
                    unit_cost: 4.5
                    unit_cost_provisional: false
                    total_cost: 45.0
                    layer:
                      name: 'FIFO Layer #43850'
                      layer_type: App\Models\FifoLayer
                      layer_id: 43850
                    inventory_movement_date: '2025-04-11T14:00:00.000000Z'
                    created_at: '2025-04-11T14:00:01.000000Z'
                  current_page: 1
                  last_page: 1
                  per_page: 25
                  total: 1
                  from: 1
                  to: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: warehouses:read
      operationId: get-api-v2-warehouse-transfers-shipments-shipment-inventory-movements
  /api/warehouses/transfers/{transfer}/shipments/{shipment}:
    delete:
      tags:
      - Adjustments & Transfers
      summary: Delete Warehouse Transfer Shipment
      description: 'Deletes a shipment from the warehouse transfer, reversing its
        stock deduction at the source warehouse and returning the shipped quantities
        to available stock. Returns the updated transfer.


        :::info[Required scope: `warehouses:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: transfer
        in: path
        schema:
          type: integer
        required: true
        description: Warehouse transfer ID
        example: '512'
      - name: shipment
        in: path
        schema:
          type: integer
        required: true
        description: Shipment ID
        example: '204'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      transfer_type:
                        type: string
                      warehouse_transfer_number:
                        type: string
                      transfer_date:
                        type: string
                      from_warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          type:
                            type: string
                          integration_instance_id:
                            type: string
                            nullable: true
                      to_warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          type:
                            type: string
                      status:
                        type: string
                      shipment_status:
                        type: string
                      shipment_id:
                        type: string
                        nullable: true
                      receipt_status:
                        type: string
                      fully_shipped_at:
                        type: string
                        nullable: true
                      fully_received_at:
                        type: string
                        nullable: true
                      eta:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                      line_item_count:
                        type: integer
                      first_line_sku:
                        type: string
                      asn_last_sent_at:
                        type: string
                        nullable: true
                example:
                  message: warehouse transfer shipment 204 deleted successfully.
                  data:
                    id: 512
                    transfer_type: standard
                    warehouse_transfer_number: WT-000512
                    transfer_date: '2026-06-01T00:00:00.000000Z'
                    from_warehouse:
                      id: 2
                      name: Main Warehouse
                      type: direct
                      integration_instance_id: null
                    to_warehouse:
                      id: 5
                      name: West Coast 3PL
                      type: 3pl
                    status: open
                    shipment_status: unshipped
                    shipment_id: null
                    receipt_status: unreceived
                    fully_shipped_at: null
                    fully_received_at: null
                    eta: '2026-06-15'
                    created_at: '2026-06-01T10:00:00.000000Z'
                    updated_at: '2026-06-02T08:30:00.000000Z'
                    archived_at: null
                    line_item_count: 1
                    first_line_sku: WIDGET-001
                    asn_last_sent_at: null
        '500':
          description: Internal Server Error
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Shipment could not be deleted.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: warehouses:write
      operationId: delete-api-warehouses-transfers-transfer-shipments-shipment
  /api/warehouses/transfers/{transfer}/receipts:
    get:
      tags:
      - Adjustments & Transfers
      summary: List Warehouse Transfer Receipts
      description: 'Returns all shipment receipts recorded against the warehouse transfer,
        including receipt lines with received quantities and the units still pending
        per shipment line.


        :::info[Required scope: `warehouses:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: transfer
        in: path
        schema:
          type: integer
        required: true
        description: Warehouse transfer ID
        example: '512'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        received_at:
                          type: string
                        user:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        receipt_lines:
                          type: array
                          items:
                            type: object
                            properties:
                              id:
                                type: integer
                              product_id:
                                type: integer
                              product_name:
                                type: string
                              product_sku:
                                type: string
                              quantity:
                                type: integer
                              units_pending:
                                type: integer
                              warehouse_transfer_line_id:
                                type: integer
                example:
                  data:
                  - id: 31
                    received_at: '2026-06-10T09:00:00.000000Z'
                    user:
                      id: 4
                      name: Jane Smith
                    receipt_lines:
                    - id: 74
                      product_id: 101
                      product_name: Widget
                      product_sku: WIDGET-001
                      quantity: 60
                      units_pending: 40
                      warehouse_transfer_line_id: 9001
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: warehouses:read
      operationId: get-api-warehouses-transfers-transfer-receipts
  /api/v2/warehouse-transfers/receipts/{receipt}:
    get:
      tags:
      - Adjustments & Transfers
      summary: Get Receipt Detail
      description: 'Returns the detail view of a specific warehouse transfer receipt,
        including receipt lines. Automatically detects lines that generated blemished
        inventory adjustments.


        :::info[Required scope: `warehouses:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: receipt
        in: path
        schema:
          type: integer
        required: true
        description: Receipt ID
        example: '301'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: integer
                  warehouse_transfer_id:
                    type: integer
                  shipment_id:
                    type: integer
                  received_at:
                    type: string
                  received_by:
                    type: string
                  notes:
                    type: string
                    nullable: true
                  lines:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        warehouse_transfer_line_id:
                          type: integer
                        product_id:
                          type: integer
                        product:
                          type: object
                          properties:
                            id:
                              type: integer
                            sku:
                              type: string
                            name:
                              type: string
                        quantity:
                          type: integer
                        blemished_quantity:
                          type: integer
                        has_blemished_adjustment:
                          type: boolean
                  created_at:
                    type: string
                  updated_at:
                    type: string
                example:
                  id: 301
                  warehouse_transfer_id: 501
                  shipment_id: 201
                  received_at: '2025-04-13T09:30:00.000000Z'
                  received_by: John Doe
                  notes: null
                  lines:
                  - id: 5001
                    warehouse_transfer_line_id: 3001
                    product_id: 812
                    product:
                      id: 812
                      sku: WIDGET-BLU
                      name: Blue Widget
                    quantity: 28
                    blemished_quantity: 2
                    has_blemished_adjustment: true
                  - id: 5002
                    warehouse_transfer_line_id: 3002
                    product_id: 813
                    product:
                      id: 813
                      sku: WIDGET-RED
                      name: Red Widget
                    quantity: 60
                    blemished_quantity: 0
                    has_blemished_adjustment: false
                  created_at: '2025-04-13T09:30:00.000000Z'
                  updated_at: '2025-04-13T09:30:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: warehouses:read
      operationId: get-api-v2-warehouse-transfers-receipts-receipt
  /api/v2/warehouse-transfers/receipts/{receipt}/lines/{line}/quantity-preview:
    get:
      tags:
      - Adjustments & Transfers
      summary: Preview Receipt Line Quantity Change
      description: 'Preview the implications of changing a warehouse transfer receipt
        line quantity without persisting any changes.


        :::info[Required scope: `warehouses:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Returns:

        - `delta` — change vs. current quantity

        - `requires_confirmation` — true if the user must confirm before saving

        - `can_update` — false when blocking conditions exist

        - `blocks.above_shipped` — true if the new quantity exceeds the parent shipment
        line''s shipped quantity (minus other receipts against the same shipment line)

        - `blocks.above_transfer_line` — true if the new quantity exceeds the parent
        warehouse transfer line quantity (minus other receipts against the same shipment
        line)

        - `caps.shipped_quantity` — shipment line shipped quantity

        - `caps.transfer_line_quantity` — warehouse transfer line quantity

        - `caps.other_receipts_total` — total received on the same shipment line via
        other receipts (excluding the line being edited)

        - `caps.max_quantity` — minimum of `shipped - other_receipts_total` and `transfer_line
        - other_receipts_total`

        - `implications.shipment_quantity` — shipment line quantity is NOT mutated
        by a receipt edit

        - `implications.transfer_quantity` — warehouse transfer line quantity is NOT
        mutated by a receipt edit

        - `implications.in_transit_quantity` — recomputed in-transit at destination
        after edit

        - `inventory` — FIFO usage / redistribution preview (when decreasing)'
      parameters:
      - name: quantity
        in: query
        schema:
          type: integer
        description: Desired receipt line quantity (integer ≥ 0)
        example: '8'
      - name: receipt
        in: path
        schema:
          type: integer
        required: true
        description: Warehouse transfer receipt ID
        example: '301'
      - name: line
        in: path
        schema:
          type: integer
        required: true
        description: Warehouse transfer receipt line ID
        example: '5001'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 OK — decrease preview
                  value:
                    data:
                      receipt_type: warehouse_transfer
                      line_id: 5001
                      current_quantity: 10
                      new_quantity: 8
                      delta: -2
                      requires_confirmation: true
                      can_update: true
                      blocks:
                        above_shipped: false
                        above_transfer_line: false
                      caps:
                        shipped_quantity: 10
                        transfer_line_quantity: 10
                        other_receipts_total: 0
                        max_quantity: 10
                      implications:
                        shipment_quantity:
                          label: Warehouse transfer shipment line quantity (unchanged)
                          current: 10
                          after_update: 10
                          total_received_after_edit: 8
                        transfer_quantity:
                          label: Warehouse transfer line quantity (unchanged)
                          current: 10
                          after_update: 10
                        in_transit_quantity:
                          label: In-transit quantity at destination after edit
                          current: 0
                          after_update: 2
                      inventory:
                        fifo_layer:
                          id: 9001
                          product_id: 812
                          warehouse_id: 8
                          original_quantity: 10
                          fulfilled_quantity: 0
                          available_quantity: 10
                        decrease_quantity: 2
                        available_without_reassignment: 10
                        usage_quantity_to_redistribute: 0
                        requires_redistribution: false
                        can_redistribute: true
                        blocks_update: false
                        alternative_available_quantity: 0
                        alternative_shortage_quantity: 0
                        usages: []
                        alternative_layers: []
                example-1:
                  summary: 200 OK — above shipped block
                  value:
                    data:
                      receipt_type: warehouse_transfer
                      line_id: 5001
                      current_quantity: 6
                      new_quantity: 7
                      delta: 1
                      requires_confirmation: true
                      can_update: false
                      blocks:
                        above_shipped: true
                        above_transfer_line: false
                      caps:
                        shipped_quantity: 10
                        transfer_line_quantity: 12
                        other_receipts_total: 4
                        max_quantity: 6
                      implications:
                        shipment_quantity:
                          label: Warehouse transfer shipment line quantity (unchanged)
                          current: 10
                          after_update: 10
                          total_received_after_edit: 11
                        transfer_quantity:
                          label: Warehouse transfer line quantity (unchanged)
                          current: 12
                          after_update: 12
                        in_transit_quantity:
                          label: In-transit quantity at destination after edit
                          current: 0
                          after_update: 0
                      inventory:
                        fifo_layer: null
                        decrease_quantity: 0
                        available_without_reassignment: 0
                        usage_quantity_to_redistribute: 0
                        requires_redistribution: false
                        can_redistribute: false
                        blocks_update: false
                        alternative_available_quantity: 0
                        alternative_shortage_quantity: 0
                        usages: []
                        alternative_layers: []
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: warehouses:read
      operationId: get-api-v2-warehouse-transfers-receipts-receipt-lines-line-quantity-preview
  /api/v2/warehouse-transfers/receipts/{receipt}/lines/{line}:
    patch:
      tags:
      - Adjustments & Transfers
      summary: Update Receipt Line Quantity
      description: 'Update a warehouse transfer receipt line''s quantity. The shipment
        line and warehouse transfer line are NOT mutated by this edit — they remain
        canonical intent.


        :::info[Required scope: `warehouses:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Body fields:

        - `quantity` (required, integer ≥ 0) — new receipt line quantity

        - `confirmed_implications` (optional, boolean) — required when the preview
        reports `requires_confirmation: true`

        - `redistribute_usages` (optional, boolean) — required when reducing quantity
        causes FIFO usage redistribution


        Returns 409 with the preview payload when confirmation is required and not
        yet provided.


        Returns 422 with `blocks.above_shipped: true` when the new quantity exceeds
        the shipment line shipped quantity (minus other receipts), and `blocks.above_transfer_line:
        true` when it exceeds the warehouse transfer line quantity. The cap subtracts
        the totals of OTHER receipt lines on the same shipment line, so concurrent
        partial receipts each get their fair share.


        **Requires permission:** `warehouse_transfers.receive`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                quantity:
                  type: integer
                confirmed_implications:
                  type: boolean
                redistribute_usages:
                  type: boolean
              example:
                quantity: 8
                confirmed_implications: true
                redistribute_usages: false
      parameters:
      - name: receipt
        in: path
        schema:
          type: integer
        required: true
        description: Warehouse transfer receipt ID
        example: '301'
      - name: line
        in: path
        schema:
          type: integer
        required: true
        description: Warehouse transfer receipt line ID
        example: '5001'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      warehouse_transfer_id:
                        type: integer
                      shipment_id:
                        type: integer
                      received_at:
                        type: string
                      received_by:
                        type: string
                      notes:
                        type: string
                        nullable: true
                      lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            warehouse_transfer_line_id:
                              type: integer
                            product_id:
                              type: integer
                            product:
                              type: object
                              properties:
                                id:
                                  type: integer
                                sku:
                                  type: string
                                name:
                                  type: string
                            quantity:
                              type: integer
                            blemished_quantity:
                              type: integer
                            has_blemished_adjustment:
                              type: boolean
                  message:
                    type: string
                example:
                  data:
                    id: 301
                    warehouse_transfer_id: 501
                    shipment_id: 201
                    received_at: '2025-04-13T09:30:00.000000Z'
                    received_by: John Doe
                    notes: null
                    lines:
                    - id: 5001
                      warehouse_transfer_line_id: 3001
                      product_id: 812
                      product:
                        id: 812
                        sku: WIDGET-BLU
                        name: Blue Widget
                      quantity: 8
                      blemished_quantity: 0
                      has_blemished_adjustment: false
                  message: Receipt line quantity updated successfully.
        '409':
          description: Conflict
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      receipt_type:
                        type: string
                      line_id:
                        type: integer
                      current_quantity:
                        type: integer
                      new_quantity:
                        type: integer
                      delta:
                        type: integer
                      requires_confirmation:
                        type: boolean
                      can_update:
                        type: boolean
                      blocks:
                        type: object
                        properties:
                          above_shipped:
                            type: boolean
                          above_transfer_line:
                            type: boolean
                      caps:
                        type: object
                        properties:
                          shipped_quantity:
                            type: integer
                          transfer_line_quantity:
                            type: integer
                          other_receipts_total:
                            type: integer
                          max_quantity:
                            type: integer
                      implications:
                        type: object
                        properties:
                          shipment_quantity:
                            type: object
                            properties:
                              current:
                                type: integer
                              after_update:
                                type: integer
                              total_received_after_edit:
                                type: integer
                          transfer_quantity:
                            type: object
                            properties:
                              current:
                                type: integer
                              after_update:
                                type: integer
                          in_transit_quantity:
                            type: object
                            properties:
                              current:
                                type: integer
                              after_update:
                                type: integer
                example:
                  message: Confirm the receipt quantity implications before saving.
                  data:
                    receipt_type: warehouse_transfer
                    line_id: 5001
                    current_quantity: 10
                    new_quantity: 8
                    delta: -2
                    requires_confirmation: true
                    can_update: true
                    blocks:
                      above_shipped: false
                      above_transfer_line: false
                    caps:
                      shipped_quantity: 10
                      transfer_line_quantity: 10
                      other_receipts_total: 0
                      max_quantity: 10
                    implications:
                      shipment_quantity:
                        current: 10
                        after_update: 10
                        total_received_after_edit: 8
                      transfer_quantity:
                        current: 10
                        after_update: 10
                      in_transit_quantity:
                        current: 0
                        after_update: 2
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 422 — above shipped
                  value:
                    message: Receipt quantity cannot exceed the shipment line shipped
                      quantity (minus other receipts against the same shipment line).
                    data:
                      blocks:
                        above_shipped: true
                        above_transfer_line: false
                      caps:
                        shipped_quantity: 10
                        transfer_line_quantity: 12
                        other_receipts_total: 4
                        max_quantity: 6
                example-1:
                  summary: 422 — above transfer line
                  value:
                    message: Receipt quantity cannot exceed the warehouse transfer
                      line quantity (minus other receipts against the same shipment
                      line).
                    data:
                      blocks:
                        above_shipped: false
                        above_transfer_line: true
                      caps:
                        shipped_quantity: 12
                        transfer_line_quantity: 10
                        other_receipts_total: 0
                        max_quantity: 10
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: warehouses:write
      operationId: patch-api-v2-warehouse-transfers-receipts-receipt-lines-line
  /api/v2/warehouse-transfers/receipts/{receipt}/activity-log:
    get:
      tags:
      - Adjustments & Transfers
      summary: Get Receipt Activity Log
      description: 'Returns paginated activity log entries for a specific receipt.


        :::info[Required scope: `warehouses:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: per_page
        in: query
        schema:
          type: integer
        example: '25'
        description: Results per page (default 10).
      - name: filter[search]
        in: query
        schema:
          type: string
        description: Search activity log entries
      - name: receipt
        in: path
        schema:
          type: integer
        required: true
        description: Receipt ID
        example: '301'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        event:
                          type: string
                        description:
                          type: string
                        causer:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        created_at:
                          type: string
                        properties:
                          type: object
                          properties: {}
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 9920
                    event: created
                    description: Receipt recorded — 90 units across 2 products
                    causer:
                      id: 2
                      name: John Doe
                    created_at: '2025-04-13T09:30:00.000000Z'
                    properties: {}
                  current_page: 1
                  last_page: 1
                  per_page: 25
                  total: 2
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: warehouses:read
      operationId: get-api-v2-warehouse-transfers-receipts-receipt-activity-log
  /api/v2/warehouse-transfers/receipts/{receipt}/inventory-movements:
    get:
      tags:
      - Adjustments & Transfers
      summary: Get Receipt Inventory Movements
      description: 'Returns paginated inventory movements scoped to the given warehouse
        transfer receipt. Includes movement type, quantity, FIFO layer link, unit/total
        cost, and product/warehouse references for each movement. Used by the Movements
        tab on the receipt detail page.


        :::info[Required scope: `warehouses:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        description: Page number (default 1)
        example: '1'
      - name: per_page
        in: query
        schema:
          type: integer
        description: Items per page (default 25)
        example: '25'
      - name: receipt
        in: path
        schema:
          type: integer
        required: true
        description: Receipt ID
        example: '301'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        type:
                          type: string
                        inventory_status:
                          type: string
                        quantity:
                          type: integer
                        reference:
                          type: string
                        link_type:
                          type: string
                        link_id:
                          type: integer
                        parent_link_id:
                          type: integer
                        detail_link_id:
                          type: string
                          nullable: true
                        product_id:
                          type: integer
                        product_sku:
                          type: string
                        product_name:
                          type: string
                        warehouse_id:
                          type: integer
                        warehouse_name:
                          type: string
                        unit_cost:
                          type: number
                        unit_cost_provisional:
                          type: boolean
                        total_cost:
                          type: number
                        layer:
                          type: object
                          properties:
                            name:
                              type: string
                            layer_type:
                              type: string
                            layer_id:
                              type: integer
                        inventory_movement_date:
                          type: string
                        created_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - id: 88012
                    type: receipt
                    inventory_status: available
                    quantity: 28
                    reference: WT-2025-0042
                    link_type: App\Models\WarehouseTransferShipmentReceiptLine
                    link_id: 5001
                    parent_link_id: 301
                    detail_link_id: null
                    product_id: 812
                    product_sku: WIDGET-BLU
                    product_name: Blue Widget
                    warehouse_id: 12
                    warehouse_name: Main Warehouse
                    unit_cost: 4.5
                    unit_cost_provisional: false
                    total_cost: 126.0
                    layer:
                      name: 'FIFO Layer #44021'
                      layer_type: App\Models\FifoLayer
                      layer_id: 44021
                    inventory_movement_date: '2025-04-13T09:30:00.000000Z'
                    created_at: '2025-04-13T09:30:01.000000Z'
                  current_page: 1
                  last_page: 1
                  per_page: 25
                  total: 2
                  from: 1
                  to: 2
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: warehouses:read
      operationId: get-api-v2-warehouse-transfers-receipts-receipt-inventory-movements
  /api/v2/warehouse-transfers/receipts/{receipt}/fifo-layers:
    get:
      tags:
      - Adjustments & Transfers
      summary: Get Receipt FIFO Layers
      description: 'Returns paginated FIFO layers created by the given warehouse transfer
        receipt. Each layer includes original/available quantity, average unit cost,
        total cost, polymorphic source link, and product/warehouse references. Used
        by the FIFO Layers tab on the receipt detail page.


        :::info[Required scope: `warehouses:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        description: Page number (default 1)
        example: '1'
      - name: per_page
        in: query
        schema:
          type: integer
        description: Items per page (default 25)
        example: '25'
      - name: receipt
        in: path
        schema:
          type: integer
        required: true
        description: Receipt ID
        example: '301'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        fifo_layer_date:
                          type: string
                        quantity:
                          type: integer
                        fulfilled_quantity:
                          type: integer
                        available_quantity:
                          type: integer
                        unit_cost:
                          type: number
                        total_cost:
                          type: number
                        product_id:
                          type: integer
                        product_sku:
                          type: string
                        product_name:
                          type: string
                        warehouse_id:
                          type: integer
                        warehouse_name:
                          type: string
                        source_type:
                          type: string
                        source_reference:
                          type: string
                        link_type:
                          type: string
                        link_id:
                          type: integer
                        parent_link_id:
                          type: integer
                        detail_link_id:
                          type: string
                          nullable: true
                        condition:
                          type: string
                        created_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - id: 44021
                    fifo_layer_date: '2025-04-13T09:30:00.000000Z'
                    quantity: 28
                    fulfilled_quantity: 0
                    available_quantity: 28
                    unit_cost: 4.5
                    total_cost: 126.0
                    product_id: 812
                    product_sku: WIDGET-BLU
                    product_name: Blue Widget
                    warehouse_id: 12
                    warehouse_name: Main Warehouse
                    source_type: Warehouse Transfer Receipt Line
                    source_reference: WT-2025-0042
                    link_type: App\Models\WarehouseTransferShipmentReceiptLine
                    link_id: 5001
                    parent_link_id: 301
                    detail_link_id: null
                    condition: new
                    created_at: '2025-04-13T09:30:01.000000Z'
                  current_page: 1
                  last_page: 1
                  per_page: 25
                  total: 2
                  from: 1
                  to: 2
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: warehouses:read
      operationId: get-api-v2-warehouse-transfers-receipts-receipt-fifo-layers
  /api/warehouses/transfers/{transfer}/receive:
    post:
      tags:
      - Adjustments & Transfers
      summary: Receive Warehouse Transfer Shipment
      description: 'Records a receipt against a shipped warehouse transfer, adding
        the received quantities to stock at the destination warehouse.


        :::info[Required scope: `warehouses:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Fields: products (required array of {id: warehouse transfer line ID, quantity,
        shipment_line_id}), shipment_id (the shipment being received), receipt_date
        (defaults to now), blemished (array of {product_id, sku, quantity, condition,
        reference} - received units in damaged condition are booked in as a new blemished
        product with the given SKU), condition and integration_unique_id.


        The transfer must be open, and received quantities cannot exceed shipped quantities.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                shipment_id:
                  type: integer
                receipt_date:
                  type: string
                products:
                  type: array
                  items:
                    type: object
                    properties:
                      id:
                        type: integer
                      quantity:
                        type: integer
                      shipment_line_id:
                        type: integer
                blemished:
                  type: array
              example:
                shipment_id: 204
                receipt_date: '2026-06-10 09:00:00'
                products:
                - id: 9001
                  quantity: 60
                  shipment_line_id: 3301
                blemished: []
      parameters:
      - name: transfer
        in: path
        schema:
          type: integer
        required: true
        description: Warehouse transfer ID
        example: '512'
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      transfer_type:
                        type: string
                      warehouse_transfer_number:
                        type: string
                      transfer_date:
                        type: string
                      from_warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          type:
                            type: string
                          integration_instance_id:
                            type: string
                            nullable: true
                      to_warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          type:
                            type: string
                      status:
                        type: string
                      shipment_status:
                        type: string
                      shipment_id:
                        type: string
                        nullable: true
                      receipt_status:
                        type: string
                      fully_shipped_at:
                        type: string
                        nullable: true
                      fully_received_at:
                        type: string
                        nullable: true
                      eta:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                      line_item_count:
                        type: integer
                      first_line_sku:
                        type: string
                      asn_last_sent_at:
                        type: string
                        nullable: true
                example:
                  message: warehouse transfer shipment receipt created successfully.
                  data:
                    id: 512
                    transfer_type: standard
                    warehouse_transfer_number: WT-000512
                    transfer_date: '2026-06-01T00:00:00.000000Z'
                    from_warehouse:
                      id: 2
                      name: Main Warehouse
                      type: direct
                      integration_instance_id: null
                    to_warehouse:
                      id: 5
                      name: West Coast 3PL
                      type: 3pl
                    status: open
                    shipment_status: unshipped
                    shipment_id: null
                    receipt_status: unreceived
                    fully_shipped_at: null
                    fully_received_at: null
                    eta: '2026-06-15'
                    created_at: '2026-06-01T10:00:00.000000Z'
                    updated_at: '2026-06-02T08:30:00.000000Z'
                    archived_at: null
                    line_item_count: 1
                    first_line_sku: WIDGET-001
                    asn_last_sent_at: null
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      transfer_id:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: object
                              properties:
                                transfer_id:
                                  type: integer
                example:
                  message: warehouse transfer is not open.
                  errors:
                    transfer_id:
                    - message: Warehouse transfer 512 is not open.
                      code: WarehouseTransfer424
                      data:
                        transfer_id: 512
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: warehouses:write
      operationId: post-api-warehouses-transfers-transfer-receive
  /api/warehouses/transfers/{transfer}/receipts/{receipt}:
    put:
      tags:
      - Adjustments & Transfers
      summary: Update Warehouse Transfer Receipt
      description: 'Updates a previously recorded receipt, adjusting received quantities.


        :::info[Required scope: `warehouses:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Fields: receipt_date (date, not in the future), products (required array of
        {id: product ID, quantity}) and blemished (array of {product_id, sku, quantity,
        condition, reference}).


        Total received per product cannot exceed the total shipped quantity, and the
        transfer must be open.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                receipt_date:
                  type: string
                products:
                  type: array
                  items:
                    type: object
                    properties:
                      id:
                        type: integer
                      quantity:
                        type: integer
              example:
                receipt_date: '2026-06-10 09:00:00'
                products:
                - id: 101
                  quantity: 80
      parameters:
      - name: transfer
        in: path
        schema:
          type: integer
        required: true
        description: Warehouse transfer ID
        example: '512'
      - name: receipt
        in: path
        schema:
          type: integer
        required: true
        description: Receipt ID
        example: '31'
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: warehouse transfer shipment receipt updated successfully.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      products.0:
                        type: array
                        items:
                          type: string
                example:
                  message: The given data was invalid.
                  errors:
                    products.0:
                    - Receipt quantity for product must not exceed total quantity
                      shipped for product.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: warehouses:write
      operationId: put-api-warehouses-transfers-transfer-receipts-receipt
    delete:
      tags:
      - Adjustments & Transfers
      summary: Delete Warehouse Transfer Receipt
      description: 'Deletes a receipt from the warehouse transfer, removing the received
        stock from the destination warehouse.


        :::info[Required scope: `warehouses:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Returns 422 when the received stock has already been consumed downstream;
        the response lists the blocking lines. Returns 400 when the transfer is not
        open.


        Authentication: Requires Bearer token.'
      parameters:
      - name: transfer
        in: path
        schema:
          type: integer
        required: true
        description: Warehouse transfer ID
        example: '512'
      - name: receipt
        in: path
        schema:
          type: integer
        required: true
        description: Receipt ID
        example: '31'
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      transfer_type:
                        type: string
                      warehouse_transfer_number:
                        type: string
                      transfer_date:
                        type: string
                      from_warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          type:
                            type: string
                          integration_instance_id:
                            type: string
                            nullable: true
                      to_warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          type:
                            type: string
                      status:
                        type: string
                      shipment_status:
                        type: string
                      shipment_id:
                        type: string
                        nullable: true
                      receipt_status:
                        type: string
                      fully_shipped_at:
                        type: string
                        nullable: true
                      fully_received_at:
                        type: string
                        nullable: true
                      eta:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                      line_item_count:
                        type: integer
                      first_line_sku:
                        type: string
                      asn_last_sent_at:
                        type: string
                        nullable: true
                example:
                  message: warehouse transfer shipment receipt 31 deleted successfully.
                  data:
                    id: 512
                    transfer_type: standard
                    warehouse_transfer_number: WT-000512
                    transfer_date: '2026-06-01T00:00:00.000000Z'
                    from_warehouse:
                      id: 2
                      name: Main Warehouse
                      type: direct
                      integration_instance_id: null
                    to_warehouse:
                      id: 5
                      name: West Coast 3PL
                      type: 3pl
                    status: open
                    shipment_status: unshipped
                    shipment_id: null
                    receipt_status: unreceived
                    fully_shipped_at: null
                    fully_received_at: null
                    eta: '2026-06-15'
                    created_at: '2026-06-01T10:00:00.000000Z'
                    updated_at: '2026-06-02T08:30:00.000000Z'
                    archived_at: null
                    line_item_count: 1
                    first_line_sku: WIDGET-001
                    asn_last_sent_at: null
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      blocking_lines:
                        type: array
                        items:
                          type: object
                          properties:
                            product_id:
                              type: integer
                            sku:
                              type: string
                            consumed_quantity:
                              type: integer
                example:
                  message: Receipt stock has downstream consumption.
                  data:
                    blocking_lines:
                    - product_id: 101
                      sku: WIDGET-001
                      consumed_quantity: 20
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: warehouses:write
      operationId: delete-api-warehouses-transfers-transfer-receipts-receipt
  /api/warehouses/transfers/{transfer}/open:
    put:
      tags:
      - Adjustments & Transfers
      summary: Open Warehouse Transfer
      description: 'Opens a draft warehouse transfer, making it active. Opening validates
        that the transfer has line items and allocates stock at the source warehouse.


        :::info[Required scope: `warehouses:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Optionally accepts the same fields as Update Warehouse Transfer to apply changes
        while opening, plus force_shipment (boolean) to immediately create a shipment
        for the full quantities.


        Returns 400 when the transfer is already open, has no products, or stock is
        insufficient.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                force_shipment:
                  type: boolean
              example:
                force_shipment: false
      parameters:
      - name: transfer
        in: path
        schema:
          type: integer
        required: true
        description: Warehouse transfer ID
        example: '512'
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      transfer_type:
                        type: string
                      warehouse_transfer_number:
                        type: string
                      transfer_date:
                        type: string
                      from_warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          type:
                            type: string
                          integration_instance_id:
                            type: string
                            nullable: true
                      to_warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          type:
                            type: string
                      status:
                        type: string
                      shipment_status:
                        type: string
                      shipment_id:
                        type: string
                        nullable: true
                      receipt_status:
                        type: string
                      fully_shipped_at:
                        type: string
                        nullable: true
                      fully_received_at:
                        type: string
                        nullable: true
                      eta:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                      line_item_count:
                        type: integer
                      first_line_sku:
                        type: string
                      asn_last_sent_at:
                        type: string
                        nullable: true
                example:
                  message: warehouse transfer opened successfully.
                  data:
                    id: 512
                    transfer_type: standard
                    warehouse_transfer_number: WT-000512
                    transfer_date: '2026-06-01T00:00:00.000000Z'
                    from_warehouse:
                      id: 2
                      name: Main Warehouse
                      type: direct
                      integration_instance_id: null
                    to_warehouse:
                      id: 5
                      name: West Coast 3PL
                      type: 3pl
                    status: open
                    shipment_status: unshipped
                    shipment_id: null
                    receipt_status: unreceived
                    fully_shipped_at: null
                    fully_received_at: null
                    eta: '2026-06-15'
                    created_at: '2026-06-01T10:00:00.000000Z'
                    updated_at: '2026-06-02T08:30:00.000000Z'
                    archived_at: null
                    line_item_count: 1
                    first_line_sku: WIDGET-001
                    asn_last_sent_at: null
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      transfer_id:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: object
                              properties:
                                transfer_id:
                                  type: integer
                example:
                  message: warehouse transfer could not be opened.
                  errors:
                    transfer_id:
                    - message: Warehouse transfer 512 is already open.
                      code: WarehouseTransfer423
                      data:
                        transfer_id: 512
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: warehouses:write
      operationId: put-api-warehouses-transfers-transfer-open
  /api/warehouses/transfers/{transfer}/draft:
    put:
      tags:
      - Adjustments & Transfers
      summary: Revert Warehouse Transfer to Draft
      description: 'Reverts an open warehouse transfer back to draft status, releasing
        allocated stock.


        :::info[Required scope: `warehouses:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Returns 400 when stock received by this transfer has already been consumed
        downstream, or when an Amazon FBA transfer still has shipments or pending
        inbound records (delete the shipments first).


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: transfer
        in: path
        schema:
          type: integer
        required: true
        description: Warehouse transfer ID
        example: '512'
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      transfer_type:
                        type: string
                      warehouse_transfer_number:
                        type: string
                      transfer_date:
                        type: string
                      from_warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          type:
                            type: string
                          integration_instance_id:
                            type: string
                            nullable: true
                      to_warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          type:
                            type: string
                      status:
                        type: string
                      shipment_status:
                        type: string
                      shipment_id:
                        type: string
                        nullable: true
                      receipt_status:
                        type: string
                      fully_shipped_at:
                        type: string
                        nullable: true
                      fully_received_at:
                        type: string
                        nullable: true
                      eta:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                      line_item_count:
                        type: integer
                      first_line_sku:
                        type: string
                      asn_last_sent_at:
                        type: string
                        nullable: true
                example:
                  message: warehouse transfer reverted to draft successfully.
                  data:
                    id: 512
                    transfer_type: standard
                    warehouse_transfer_number: WT-000512
                    transfer_date: '2026-06-01T00:00:00.000000Z'
                    from_warehouse:
                      id: 2
                      name: Main Warehouse
                      type: direct
                      integration_instance_id: null
                    to_warehouse:
                      id: 5
                      name: West Coast 3PL
                      type: 3pl
                    status: open
                    shipment_status: unshipped
                    shipment_id: null
                    receipt_status: unreceived
                    fully_shipped_at: null
                    fully_received_at: null
                    eta: '2026-06-15'
                    created_at: '2026-06-01T10:00:00.000000Z'
                    updated_at: '2026-06-02T08:30:00.000000Z'
                    archived_at: null
                    line_item_count: 1
                    first_line_sku: WIDGET-001
                    asn_last_sent_at: null
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      warehouse transfer:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: array
                example:
                  message: warehouse transfer could not be reverted.
                  errors:
                    warehouse transfer:
                    - message: 'Cannot revert: a stock layer created by this transfer
                        has been used (SKU WIDGET-001).'
                      code: WarehouseTransfer406
                      data: []
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: warehouses:write
      operationId: put-api-warehouses-transfers-transfer-draft
  /api/warehouses/transfers/{transfer}/close-draft:
    put:
      tags:
      - Adjustments & Transfers
      summary: Close Warehouse Transfer Draft
      description: 'Closes a draft warehouse transfer, marking it closed without moving
        any stock.


        :::info[Required scope: `warehouses:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: transfer
        in: path
        schema:
          type: integer
        required: true
        description: Warehouse transfer ID
        example: '512'
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      transfer_type:
                        type: string
                      warehouse_transfer_number:
                        type: string
                      transfer_date:
                        type: string
                      from_warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          type:
                            type: string
                          integration_instance_id:
                            type: string
                            nullable: true
                      to_warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          type:
                            type: string
                      status:
                        type: string
                      shipment_status:
                        type: string
                      shipment_id:
                        type: string
                        nullable: true
                      receipt_status:
                        type: string
                      fully_shipped_at:
                        type: string
                        nullable: true
                      fully_received_at:
                        type: string
                        nullable: true
                      eta:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                      line_item_count:
                        type: integer
                      first_line_sku:
                        type: string
                      asn_last_sent_at:
                        type: string
                        nullable: true
                example:
                  message: warehouse transfer closed successfully.
                  data:
                    id: 512
                    transfer_type: standard
                    warehouse_transfer_number: WT-000512
                    transfer_date: '2026-06-01T00:00:00.000000Z'
                    from_warehouse:
                      id: 2
                      name: Main Warehouse
                      type: direct
                      integration_instance_id: null
                    to_warehouse:
                      id: 5
                      name: West Coast 3PL
                      type: 3pl
                    status: open
                    shipment_status: unshipped
                    shipment_id: null
                    receipt_status: unreceived
                    fully_shipped_at: null
                    fully_received_at: null
                    eta: '2026-06-15'
                    created_at: '2026-06-01T10:00:00.000000Z'
                    updated_at: '2026-06-02T08:30:00.000000Z'
                    archived_at: null
                    line_item_count: 1
                    first_line_sku: WIDGET-001
                    asn_last_sent_at: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: warehouses:write
      operationId: put-api-warehouses-transfers-transfer-close-draft
  /api/warehouses/transfers/{transfer}/mark-as-shipped:
    put:
      tags:
      - Adjustments & Transfers
      summary: Mark Warehouse Transfer as Shipped
      description: 'Marks an Amazon FBA inbound warehouse transfer as shipped, recording
        the shipment with Amazon inbound processing (including shortage handling and
        status updates).


        :::info[Required scope: `warehouses:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Only valid for transfers whose destination is an Amazon FBA warehouse with
        a linked Amazon inbound shipment. Fields: shipment_date (Y-m-d, not in the
        future) and tracking_number (both optional).


        Returns 422 when the transfer is not an FBA transfer or has already been marked
        as shipped.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                shipment_date:
                  type: string
                tracking_number:
                  type: string
              example:
                shipment_date: '2026-06-05'
                tracking_number: 1Z999AA10123456784
      parameters:
      - name: transfer
        in: path
        schema:
          type: integer
        required: true
        description: Warehouse transfer ID
        example: '512'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      transfer_type:
                        type: string
                      warehouse_transfer_number:
                        type: string
                      transfer_date:
                        type: string
                      from_warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          type:
                            type: string
                          integration_instance_id:
                            type: string
                            nullable: true
                      to_warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          type:
                            type: string
                      status:
                        type: string
                      shipment_status:
                        type: string
                      shipment_id:
                        type: string
                        nullable: true
                      receipt_status:
                        type: string
                      fully_shipped_at:
                        type: string
                        nullable: true
                      fully_received_at:
                        type: string
                        nullable: true
                      eta:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                      line_item_count:
                        type: integer
                      first_line_sku:
                        type: string
                      asn_last_sent_at:
                        type: string
                        nullable: true
                example:
                  message: Warehouse transfer marked as shipped successfully.
                  data:
                    id: 512
                    transfer_type: standard
                    warehouse_transfer_number: WT-000512
                    transfer_date: '2026-06-01T00:00:00.000000Z'
                    from_warehouse:
                      id: 2
                      name: Main Warehouse
                      type: direct
                      integration_instance_id: null
                    to_warehouse:
                      id: 5
                      name: West Coast 3PL
                      type: 3pl
                    status: open
                    shipment_status: unshipped
                    shipment_id: null
                    receipt_status: unreceived
                    fully_shipped_at: null
                    fully_received_at: null
                    eta: '2026-06-15'
                    created_at: '2026-06-01T10:00:00.000000Z'
                    updated_at: '2026-06-02T08:30:00.000000Z'
                    archived_at: null
                    line_item_count: 1
                    first_line_sku: WIDGET-001
                    asn_last_sent_at: null
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: This action is only available for Amazon FBA warehouse
                    transfers.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: warehouses:write
      operationId: put-api-warehouses-transfers-transfer-mark-as-shipped
  /api/warehouses/transfers/{transfer}/update-shipment:
    put:
      tags:
      - Adjustments & Transfers
      summary: Update Warehouse Transfer Shipment Details
      description: 'Updates the shipped date and tracking number of an Amazon FBA
        warehouse transfer after it has been shipped.


        :::info[Required scope: `warehouses:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Fields: shipment_date (Y-m-d, not in the future) and tracking_number (both
        optional).


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                shipment_date:
                  type: string
                tracking_number:
                  type: string
              example:
                shipment_date: '2026-06-06'
                tracking_number: 1Z999AA10123456784
      parameters:
      - name: transfer
        in: path
        schema:
          type: integer
        required: true
        description: Warehouse transfer ID
        example: '512'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      transfer_type:
                        type: string
                      warehouse_transfer_number:
                        type: string
                      transfer_date:
                        type: string
                      from_warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          type:
                            type: string
                          integration_instance_id:
                            type: string
                            nullable: true
                      to_warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          type:
                            type: string
                      status:
                        type: string
                      shipment_status:
                        type: string
                      shipment_id:
                        type: string
                        nullable: true
                      receipt_status:
                        type: string
                      fully_shipped_at:
                        type: string
                        nullable: true
                      fully_received_at:
                        type: string
                        nullable: true
                      eta:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                      line_item_count:
                        type: integer
                      first_line_sku:
                        type: string
                      asn_last_sent_at:
                        type: string
                        nullable: true
                example:
                  message: Warehouse transfer shipment details updated successfully.
                  data:
                    id: 512
                    transfer_type: standard
                    warehouse_transfer_number: WT-000512
                    transfer_date: '2026-06-01T00:00:00.000000Z'
                    from_warehouse:
                      id: 2
                      name: Main Warehouse
                      type: direct
                      integration_instance_id: null
                    to_warehouse:
                      id: 5
                      name: West Coast 3PL
                      type: 3pl
                    status: open
                    shipment_status: unshipped
                    shipment_id: null
                    receipt_status: unreceived
                    fully_shipped_at: null
                    fully_received_at: null
                    eta: '2026-06-15'
                    created_at: '2026-06-01T10:00:00.000000Z'
                    updated_at: '2026-06-02T08:30:00.000000Z'
                    archived_at: null
                    line_item_count: 1
                    first_line_sku: WIDGET-001
                    asn_last_sent_at: null
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No Amazon inbound shipment found for this warehouse transfer.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: warehouses:write
      operationId: put-api-warehouses-transfers-transfer-update-shipment
  /api/warehouses/transfers/{transfer}/asn:
    post:
      tags:
      - Adjustments & Transfers
      summary: Send Warehouse Transfer ASN
      description: 'Sends (or resends) an Advance Shipment Notice email for the transfer
        to its destination third-party logistics (3PL) warehouse.


        :::info[Required scope: `warehouses:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        The destination warehouse must be of type 3pl and have an email address on
        its address record; otherwise a 422 is returned.


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: transfer
        in: path
        schema:
          type: integer
        required: true
        description: Warehouse transfer ID
        example: '512'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: ASN email sent successfully.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Warehouse should be 3PL
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: warehouses:write
      operationId: post-api-warehouses-transfers-transfer-asn
  /api/warehouses/transfers/{transfer}/archive:
    put:
      tags:
      - Adjustments & Transfers
      summary: Archive Warehouse Transfer
      description: 'Archives a warehouse transfer, hiding it from active listings.


        :::info[Required scope: `warehouses:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: transfer
        in: path
        schema:
          type: integer
        required: true
        description: Warehouse transfer ID
        example: '512'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      transfer_type:
                        type: string
                      warehouse_transfer_number:
                        type: string
                      transfer_date:
                        type: string
                      from_warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          type:
                            type: string
                          integration_instance_id:
                            type: string
                            nullable: true
                      to_warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          type:
                            type: string
                      status:
                        type: string
                      shipment_status:
                        type: string
                      shipment_id:
                        type: string
                        nullable: true
                      receipt_status:
                        type: string
                      fully_shipped_at:
                        type: string
                        nullable: true
                      fully_received_at:
                        type: string
                        nullable: true
                      eta:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                      line_item_count:
                        type: integer
                      first_line_sku:
                        type: string
                      asn_last_sent_at:
                        type: string
                        nullable: true
                example:
                  message: warehouse transfer 512 archived successfully.
                  data:
                    id: 512
                    transfer_type: standard
                    warehouse_transfer_number: WT-000512
                    transfer_date: '2026-06-01T00:00:00.000000Z'
                    from_warehouse:
                      id: 2
                      name: Main Warehouse
                      type: direct
                      integration_instance_id: null
                    to_warehouse:
                      id: 5
                      name: West Coast 3PL
                      type: 3pl
                    status: open
                    shipment_status: unshipped
                    shipment_id: null
                    receipt_status: unreceived
                    fully_shipped_at: null
                    fully_received_at: null
                    eta: '2026-06-15'
                    created_at: '2026-06-01T10:00:00.000000Z'
                    updated_at: '2026-06-02T08:30:00.000000Z'
                    archived_at: null
                    line_item_count: 1
                    first_line_sku: WIDGET-001
                    asn_last_sent_at: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: warehouses:write
      operationId: put-api-warehouses-transfers-transfer-archive
  /api/warehouses/transfers/{transfer}/unarchived:
    put:
      tags:
      - Adjustments & Transfers
      summary: Unarchive Warehouse Transfer
      description: 'Restores an archived warehouse transfer to active status.


        :::info[Required scope: `warehouses:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: transfer
        in: path
        schema:
          type: integer
        required: true
        description: Warehouse transfer ID
        example: '512'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      transfer_type:
                        type: string
                      warehouse_transfer_number:
                        type: string
                      transfer_date:
                        type: string
                      from_warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          type:
                            type: string
                          integration_instance_id:
                            type: string
                            nullable: true
                      to_warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          type:
                            type: string
                      status:
                        type: string
                      shipment_status:
                        type: string
                      shipment_id:
                        type: string
                        nullable: true
                      receipt_status:
                        type: string
                      fully_shipped_at:
                        type: string
                        nullable: true
                      fully_received_at:
                        type: string
                        nullable: true
                      eta:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                      line_item_count:
                        type: integer
                      first_line_sku:
                        type: string
                      asn_last_sent_at:
                        type: string
                        nullable: true
                example:
                  message: warehouse transfer 512 unarchived successfully.
                  data:
                    id: 512
                    transfer_type: standard
                    warehouse_transfer_number: WT-000512
                    transfer_date: '2026-06-01T00:00:00.000000Z'
                    from_warehouse:
                      id: 2
                      name: Main Warehouse
                      type: direct
                      integration_instance_id: null
                    to_warehouse:
                      id: 5
                      name: West Coast 3PL
                      type: 3pl
                    status: open
                    shipment_status: unshipped
                    shipment_id: null
                    receipt_status: unreceived
                    fully_shipped_at: null
                    fully_received_at: null
                    eta: '2026-06-15'
                    created_at: '2026-06-01T10:00:00.000000Z'
                    updated_at: '2026-06-02T08:30:00.000000Z'
                    archived_at: null
                    line_item_count: 1
                    first_line_sku: WIDGET-001
                    asn_last_sent_at: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: warehouses:write
      operationId: put-api-warehouses-transfers-transfer-unarchived
  /api/warehouses/transfers/archive:
    put:
      tags:
      - Adjustments & Transfers
      summary: Bulk Archive Warehouse Transfers
      description: 'Archives multiple warehouse transfers. Provide either ids (array
        of transfer IDs) or apply_to_all=true with an optional filters object to target
        all transfers matching the current listing filters.


        :::info[Required scope: `warehouses:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 512
                - 513
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      totalCount:
                        type: integer
                      failCount:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    totalCount: 2
                    failCount: 0
                  message: 2 records processed successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: warehouses:write
      operationId: put-api-warehouses-transfers-archive
  /api/warehouses/transfers/unarchive:
    put:
      tags:
      - Adjustments & Transfers
      summary: Bulk Unarchive Warehouse Transfers
      description: 'Restores multiple archived warehouse transfers. Provide either
        ids (array of transfer IDs) or apply_to_all=true with an optional filters
        object.


        :::info[Required scope: `warehouses:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 512
                - 513
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      totalCount:
                        type: integer
                      failCount:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    totalCount: 2
                    failCount: 0
                  message: 2 records processed successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: warehouses:write
      operationId: put-api-warehouses-transfers-unarchive
  /api/warehouses/transfers/deletable:
    post:
      tags:
      - Adjustments & Transfers
      summary: Check Warehouse Transfers Deletable
      description: 'Checks whether the given warehouse transfers can be deleted. Each
        result includes deletable (boolean) and reason (why deletion is blocked, or
        null). A transfer is not deletable when stock it received has already been
        consumed downstream.


        :::info[Required scope: `warehouses:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 512
                - 513
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        deletable:
                          type: boolean
                        reason:
                          type: string
                          nullable: true
                example:
                  data:
                  - id: 512
                    deletable: true
                    reason: null
                  - id: 513
                    deletable: false
                    reason: Received stock has been consumed by later movements
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: warehouses:write
      operationId: post-api-warehouses-transfers-deletable
  /api/warehouses/transfers/{transfer}/notes:
    get:
      tags:
      - Adjustments & Transfers
      summary: List Warehouse Transfer Notes
      description: 'Returns the transfer''s notes with their authors, newest first,
        paginated.


        :::info[Required scope: `warehouses:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: transfer
        in: path
        schema:
          type: integer
        required: true
        description: Warehouse transfer ID
        example: '512'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        note:
                          type: string
                        is_pinned:
                          type: boolean
                        notable_type:
                          type: string
                        notable_id:
                          type: integer
                        user_id:
                          type: integer
                        user:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 15
                    note: Carrier pickup confirmed for Friday.
                    is_pinned: false
                    notable_type: App\Models\WarehouseTransfer
                    notable_id: 512
                    user_id: 4
                    user:
                      id: 4
                      name: Jane Smith
                    created_at: '2026-06-03T15:20:00.000000Z'
                    updated_at: '2026-06-03T15:20:00.000000Z'
                  first_page_url: https://example.sku.io/api/warehouses/transfers/512/notes?page=1
                  from: 1
                  last_page: 1
                  last_page_url: https://example.sku.io/api/warehouses/transfers/512/notes?page=1
                  links: []
                  next_page_url: null
                  path: https://example.sku.io/api/warehouses/transfers/512/notes
                  per_page: 15
                  prev_page_url: null
                  to: 1
                  total: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: warehouses:read
      operationId: get-api-warehouses-transfers-transfer-notes
    post:
      tags:
      - Adjustments & Transfers
      summary: Add Warehouse Transfer Note
      description: 'Adds a note to the warehouse transfer. Fields: note (required).


        :::info[Required scope: `warehouses:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                note:
                  type: string
              example:
                note: Carrier pickup confirmed for Friday.
      parameters:
      - name: transfer
        in: path
        schema:
          type: integer
        required: true
        description: Warehouse transfer ID
        example: '512'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      note:
                        type: string
                      is_pinned:
                        type: boolean
                      notable_type:
                        type: string
                      notable_id:
                        type: integer
                      user_id:
                        type: integer
                      user:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  message: note created successfully.
                  data:
                    id: 15
                    note: Carrier pickup confirmed for Friday.
                    is_pinned: false
                    notable_type: App\Models\WarehouseTransfer
                    notable_id: 512
                    user_id: 4
                    user:
                      id: 4
                      name: Jane Smith
                    created_at: '2026-06-03T15:20:00.000000Z'
                    updated_at: '2026-06-03T15:20:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: warehouses:write
      operationId: post-api-warehouses-transfers-transfer-notes
  /api/warehouses/transfers/{transfer}/notes/{noteId}/toggle-pin:
    put:
      tags:
      - Adjustments & Transfers
      summary: Toggle Warehouse Transfer Note Pin
      description: 'Pins or unpins a note on the warehouse transfer. Pinned notes
        surface at the top of the notes list.


        :::info[Required scope: `warehouses:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: transfer
        in: path
        schema:
          type: integer
        required: true
        description: Warehouse transfer ID
        example: '512'
      - name: noteId
        in: path
        schema:
          type: integer
        required: true
        description: Note ID
        example: '15'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      note:
                        type: string
                      is_pinned:
                        type: boolean
                      notable_type:
                        type: string
                      notable_id:
                        type: integer
                      user_id:
                        type: integer
                      user:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  message: Note pinned
                  data:
                    id: 15
                    note: Carrier pickup confirmed for Friday.
                    is_pinned: true
                    notable_type: App\Models\WarehouseTransfer
                    notable_id: 512
                    user_id: 4
                    user:
                      id: 4
                      name: Jane Smith
                    created_at: '2026-06-03T15:20:00.000000Z'
                    updated_at: '2026-06-03T15:20:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: warehouses:write
      operationId: put-api-warehouses-transfers-transfer-notes-noteid-toggle-pin
  /api/warehouses/transfers/{transfer}/notes/{noteId}:
    delete:
      tags:
      - Adjustments & Transfers
      summary: Delete Warehouse Transfer Note
      description: 'Deletes a note from the warehouse transfer.


        :::info[Required scope: `warehouses:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: transfer
        in: path
        schema:
          type: integer
        required: true
        description: Warehouse transfer ID
        example: '512'
      - name: noteId
        in: path
        schema:
          type: integer
        required: true
        description: Note ID
        example: '15'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: note 15 deleted successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: warehouses:write
      operationId: delete-api-warehouses-transfers-transfer-notes-noteid
  /api/warehouses/transfers/{transfer}/bills:
    post:
      tags:
      - Adjustments & Transfers
      summary: Create Warehouse Transfer Bill
      description: 'Creates a supplier bill linked to the warehouse transfer, capturing
        third-party costs such as freight.


        :::info[Required scope: `warehouses:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Fields: supplier_id (required), invoice_number (required, unique), invoice_date
        (required), currency_id, currency_rate, lines (array of {description, quantity,
        amount, nominal_code_id, tax_rate_id, cost_category_id}), allocations (array
        of {warehouse_transfer_line_id, allocation_amount, proration_strategy} - must
        not exceed the bill total) and proration_strategy (required - how unallocated
        cost is distributed: straight_line, front_loaded, back_loaded, revenue_based,
        cost_based, weight_based, volume_based, quantity_based, specific_line, manual).


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                supplier_id:
                  type: integer
                invoice_number:
                  type: string
                invoice_date:
                  type: string
                currency_id:
                  type: integer
                currency_rate:
                  type: integer
                proration_strategy:
                  type: string
                lines:
                  type: array
                  items:
                    type: object
                    properties:
                      description:
                        type: string
                      quantity:
                        type: integer
                      amount:
                        type: integer
                      nominal_code_id:
                        type: integer
                allocations:
                  type: array
                  items:
                    type: object
                    properties:
                      warehouse_transfer_line_id:
                        type: integer
                      allocation_amount:
                        type: integer
              example:
                supplier_id: 3
                invoice_number: INV-2026-0142
                invoice_date: '2026-06-05'
                currency_id: 1
                currency_rate: 1
                proration_strategy: quantity_based
                lines:
                - description: Ocean freight
                  quantity: 1
                  amount: 350
                  nominal_code_id: 15
                allocations:
                - warehouse_transfer_line_id: 9001
                  allocation_amount: 350
      parameters:
      - name: transfer
        in: path
        schema:
          type: integer
        required: true
        description: Warehouse transfer ID
        example: '512'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      supplier_id:
                        type: integer
                      invoice_number:
                        type: string
                      invoice_date:
                        type: string
                      link_type:
                        type: string
                      link_id:
                        type: integer
                      currency_id:
                        type: integer
                      currency_rate:
                        type: number
                      proration_strategy:
                        type: string
                      total:
                        type: number
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 77
                    supplier_id: 3
                    invoice_number: INV-2026-0142
                    invoice_date: '2026-06-05'
                    link_type: App\Models\WarehouseTransfer
                    link_id: 512
                    currency_id: 1
                    currency_rate: 1.0
                    proration_strategy: quantity_based
                    total: 350.0
                    created_at: '2026-06-05T12:00:00.000000Z'
                    updated_at: '2026-06-05T12:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: warehouses:write
      operationId: post-api-warehouses-transfers-transfer-bills
  /api/warehouses/transfers/{transfer}/bills/{bill}:
    get:
      tags:
      - Adjustments & Transfers
      summary: Get Warehouse Transfer Bill
      description: 'Returns a bill linked to the warehouse transfer. Responds 404
        when the bill does not belong to this transfer.


        :::info[Required scope: `warehouses:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: transfer
        in: path
        schema:
          type: integer
        required: true
        description: Warehouse transfer ID
        example: '512'
      - name: bill
        in: path
        schema:
          type: integer
        required: true
        description: Bill ID
        example: '77'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      supplier_id:
                        type: integer
                      invoice_number:
                        type: string
                      invoice_date:
                        type: string
                      link_type:
                        type: string
                      link_id:
                        type: integer
                      currency_id:
                        type: integer
                      currency_rate:
                        type: number
                      proration_strategy:
                        type: string
                      total:
                        type: number
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 77
                    supplier_id: 3
                    invoice_number: INV-2026-0142
                    invoice_date: '2026-06-05'
                    link_type: App\Models\WarehouseTransfer
                    link_id: 512
                    currency_id: 1
                    currency_rate: 1.0
                    proration_strategy: quantity_based
                    total: 350.0
                    created_at: '2026-06-05T12:00:00.000000Z'
                    updated_at: '2026-06-05T12:00:00.000000Z'
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Bill not found for this warehouse transfer
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: warehouses:read
      operationId: get-api-warehouses-transfers-transfer-bills-bill
    patch:
      tags:
      - Adjustments & Transfers
      summary: Update Warehouse Transfer Bill
      description: 'Updates a bill linked to the warehouse transfer.


        :::info[Required scope: `warehouses:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Fields: invoice_number (required), invoice_date (required), supplier_id (required),
        currency_id, currency_rate, proration_strategy and allocations (array of {warehouse_transfer_line_id,
        allocation_amount, proration_strategy} - must not exceed the bill total).
        Responds 404 when the bill does not belong to this transfer.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                supplier_id:
                  type: integer
                invoice_number:
                  type: string
                invoice_date:
                  type: string
                currency_id:
                  type: integer
                currency_rate:
                  type: integer
                proration_strategy:
                  type: string
                allocations:
                  type: array
                  items:
                    type: object
                    properties:
                      warehouse_transfer_line_id:
                        type: integer
                      allocation_amount:
                        type: integer
              example:
                supplier_id: 3
                invoice_number: INV-2026-0142
                invoice_date: '2026-06-05'
                currency_id: 1
                currency_rate: 1
                proration_strategy: quantity_based
                allocations:
                - warehouse_transfer_line_id: 9001
                  allocation_amount: 350
      parameters:
      - name: transfer
        in: path
        schema:
          type: integer
        required: true
        description: Warehouse transfer ID
        example: '512'
      - name: bill
        in: path
        schema:
          type: integer
        required: true
        description: Bill ID
        example: '77'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      supplier_id:
                        type: integer
                      invoice_number:
                        type: string
                      invoice_date:
                        type: string
                      link_type:
                        type: string
                      link_id:
                        type: integer
                      currency_id:
                        type: integer
                      currency_rate:
                        type: number
                      proration_strategy:
                        type: string
                      total:
                        type: number
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 77
                    supplier_id: 3
                    invoice_number: INV-2026-0142
                    invoice_date: '2026-06-05'
                    link_type: App\Models\WarehouseTransfer
                    link_id: 512
                    currency_id: 1
                    currency_rate: 1.0
                    proration_strategy: quantity_based
                    total: 350.0
                    created_at: '2026-06-05T12:00:00.000000Z'
                    updated_at: '2026-06-05T12:00:00.000000Z'
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Bill not found for this warehouse transfer
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: warehouses:write
      operationId: patch-api-warehouses-transfers-transfer-bills-bill
  /api/v2/location-transfers:
    get:
      tags:
      - Adjustments & Transfers
      summary: List Location Transfers
      description: 'Paginated history of location transfers (put-aways and relocations).


        Authentication: Requires Bearer token.


        Search: filter[search] matches transfer number, notes, warehouse name, and
        performing user''s name; narrow with search_columns.


        Operator-aware filters: filter[number], filter[notes] (text), filter[id] (numeric),
        filter[completed_at], filter[created_at] (datetime). Each supports a bare
        implicit-is form (filter[number]=LT-000012) and an operator form (filter[number.contains]=LT).
        Text operators: is, is_not, contains, does_not_contain, starts_with, does_not_start_with,
        ends_with, does_not_end_with, is_one_of, is_not_one_of, is_empty, is_not_empty.
        Numeric operators: is, is_not, greater_than, less_than, greater_than_or_equal,
        less_than_or_equal, between, is_one_of, is_not_one_of, is_empty, is_not_empty.
        Datetime operators: is, is_not, before, after, on_or_before, on_or_after,
        between, is_empty, is_not_empty.


        Exact filters: filter[warehouse_id], filter[reason] (put_away | relocation),
        filter[product_id] (matches transfers containing a line for the product),
        filter[performed_by_user_id], filter[date_from] / filter[date_to] (date range
        on completion date, Y-m-d).


        filter_groups accepts a base64-encoded JSON tree of AND/OR advanced filter
        groups and takes precedence over individual filter params.


        Allowed sorts: id, number, reason, completed_at, created_at (default -completed_at).


        Each row includes the warehouse, the performing user, and a lines_count. Line
        detail is returned by the single-transfer endpoint.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        number:
                          type: string
                        warehouse_id:
                          type: integer
                        warehouse:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        reason:
                          type: string
                        reason_label:
                          type: string
                        notes:
                          type: string
                        performed_by:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        completed_at:
                          type: string
                        lines_count:
                          type: integer
                        created_at:
                          type: string
                  current_page:
                    type: integer
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 12
                    number: LT-000012
                    warehouse_id: 1
                    warehouse:
                      id: 1
                      name: Main Warehouse
                    reason: put_away
                    reason_label: Put Away
                    notes: Morning put-away from receiving dock
                    performed_by:
                      id: 5
                      name: Jane Smith
                    completed_at: '2026-07-07T15:04:12.000000Z'
                    lines_count: 2
                    created_at: '2026-07-07T15:04:12.000000Z'
                  current_page: 1
                  first_page_url: '{{protocol}}{{domain}}/api/v2/location-transfers?page=1'
                  from: 1
                  last_page: 1
                  last_page_url: '{{protocol}}{{domain}}/api/v2/location-transfers?page=1'
                  links: []
                  next_page_url: null
                  path: '{{protocol}}{{domain}}/api/v2/location-transfers'
                  per_page: 10
                  prev_page_url: null
                  to: 1
                  total: 1
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-v2-location-transfers
    post:
      tags:
      - Adjustments & Transfers
      summary: Create Location Transfer
      description: 'Execute a location transfer atomically: the document is created,
        completed, and paired reclassification inventory movements are written per
        line (-quantity at the from-location, +quantity at the to-location) in a single
        transaction. Location transfers never affect costing or warehouse-level availability.


        Authentication: Requires Bearer token.


        Rules:

        - warehouse_id (required, integer): warehouse with locations enabled — returns
        422 otherwise

        - reason (required, string): put_away or relocation

        - notes (optional, string)

        - lines (required, array, min 1)

        - lines[].product_id (required, integer)

        - lines[].from_warehouse_location_id (required, integer): must belong to the
        warehouse

        - lines[].to_warehouse_location_id (required, integer): must belong to the
        warehouse, differ from the from-location, and not be deprecated

        - lines[].quantity (required, number, > 0): the from-location balance must
        cover the total requested quantity across all lines drawing from the same
        product and location — returns 422 naming the available quantity otherwise


        **Requires permission:** `inventory.transfer`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                warehouse_id:
                  type: integer
                reason:
                  type: string
                notes:
                  type: string
                lines:
                  type: array
                  items:
                    type: object
                    properties:
                      product_id:
                        type: integer
                      from_warehouse_location_id:
                        type: integer
                      to_warehouse_location_id:
                        type: integer
                      quantity:
                        type: integer
              example:
                warehouse_id: 1
                reason: put_away
                notes: Morning put-away from receiving dock
                lines:
                - product_id: 42
                  from_warehouse_location_id: 7
                  to_warehouse_location_id: 15
                  quantity: 100
                - product_id: 58
                  from_warehouse_location_id: 7
                  to_warehouse_location_id: 18
                  quantity: 24
      parameters: []
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      number:
                        type: string
                      warehouse_id:
                        type: integer
                      warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      reason:
                        type: string
                      reason_label:
                        type: string
                      notes:
                        type: string
                      performed_by:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      completed_at:
                        type: string
                      lines_count:
                        type: integer
                      lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            product_id:
                              type: integer
                            product:
                              type: object
                              properties:
                                id:
                                  type: integer
                                sku:
                                  type: string
                                name:
                                  type: string
                            from_location:
                              type: object
                              properties:
                                id:
                                  type: integer
                                code:
                                  type: string
                                name:
                                  type: string
                                type:
                                  type: string
                                type_label:
                                  type: string
                            to_location:
                              type: object
                              properties:
                                id:
                                  type: integer
                                code:
                                  type: string
                                name:
                                  type: string
                                  nullable: true
                                type:
                                  type: string
                                type_label:
                                  type: string
                            quantity:
                              type: integer
                      created_at:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 12
                    number: LT-000012
                    warehouse_id: 1
                    warehouse:
                      id: 1
                      name: Main Warehouse
                    reason: put_away
                    reason_label: Put Away
                    notes: Morning put-away from receiving dock
                    performed_by:
                      id: 5
                      name: Jane Smith
                    completed_at: '2026-07-07T15:04:12.000000Z'
                    lines_count: 2
                    lines:
                    - id: 31
                      product_id: 42
                      product:
                        id: 42
                        sku: SKU-ABC-123
                        name: Blue Widget 500ml
                      from_location:
                        id: 7
                        code: RECEIVING
                        name: Receiving
                        type: staging
                        type_label: Staging
                      to_location:
                        id: 15
                        code: A-01-2-B
                        name: null
                        type: storage
                        type_label: Storage
                      quantity: 100
                    - id: 32
                      product_id: 58
                      product:
                        id: 58
                        sku: SKU-DEF-456
                        name: Red Widget 250ml
                      from_location:
                        id: 7
                        code: RECEIVING
                        name: Receiving
                        type: staging
                        type_label: Staging
                      to_location:
                        id: 18
                        code: A-02-1-A
                        name: null
                        type: storage
                        type_label: Storage
                      quantity: 24
                    created_at: '2026-07-07T15:04:12.000000Z'
                  message: Location transfer LT-000012 completed.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 422 Insufficient Stock
                  value:
                    message: 'Insufficient stock for product SKU-ABC-123 at location
                      RECEIVING: requested 100, available 40.'
                example-1:
                  summary: 422 Validation Error
                  value:
                    message: At least one transfer line is required.
                    errors:
                      lines:
                      - At least one transfer line is required.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-v2-location-transfers
  /api/v2/location-transfers/{locationTransfer}:
    get:
      tags:
      - Adjustments & Transfers
      summary: Get Location Transfer
      description: 'Retrieve a single location transfer with its lines. Each line
        includes the product and the from/to locations.


        Authentication: Requires Bearer token.'
      parameters:
      - name: locationTransfer
        in: path
        schema:
          type: integer
        required: true
        description: Location transfer ID
        example: '12'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      number:
                        type: string
                      warehouse_id:
                        type: integer
                      warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      reason:
                        type: string
                      reason_label:
                        type: string
                      notes:
                        type: string
                      performed_by:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      completed_at:
                        type: string
                      lines_count:
                        type: integer
                      lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            product_id:
                              type: integer
                            product:
                              type: object
                              properties:
                                id:
                                  type: integer
                                sku:
                                  type: string
                                name:
                                  type: string
                            from_location:
                              type: object
                              properties:
                                id:
                                  type: integer
                                code:
                                  type: string
                                name:
                                  type: string
                                type:
                                  type: string
                                type_label:
                                  type: string
                            to_location:
                              type: object
                              properties:
                                id:
                                  type: integer
                                code:
                                  type: string
                                name:
                                  type: string
                                  nullable: true
                                type:
                                  type: string
                                type_label:
                                  type: string
                            quantity:
                              type: integer
                      created_at:
                        type: string
                example:
                  data:
                    id: 12
                    number: LT-000012
                    warehouse_id: 1
                    warehouse:
                      id: 1
                      name: Main Warehouse
                    reason: put_away
                    reason_label: Put Away
                    notes: Morning put-away from receiving dock
                    performed_by:
                      id: 5
                      name: Jane Smith
                    completed_at: '2026-07-07T15:04:12.000000Z'
                    lines_count: 2
                    lines:
                    - id: 31
                      product_id: 42
                      product:
                        id: 42
                        sku: SKU-ABC-123
                        name: Blue Widget 500ml
                      from_location:
                        id: 7
                        code: RECEIVING
                        name: Receiving
                        type: staging
                        type_label: Staging
                      to_location:
                        id: 15
                        code: A-01-2-B
                        name: null
                        type: storage
                        type_label: Storage
                      quantity: 100
                    - id: 32
                      product_id: 58
                      product:
                        id: 58
                        sku: SKU-DEF-456
                        name: Red Widget 250ml
                      from_location:
                        id: 7
                        code: RECEIVING
                        name: Receiving
                        type: staging
                        type_label: Staging
                      to_location:
                        id: 18
                        code: A-02-1-A
                        name: null
                        type: storage
                        type_label: Storage
                      quantity: 24
                    created_at: '2026-07-07T15:04:12.000000Z'
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No query results for model [App\Models\LocationTransfer]
                    9999
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-v2-location-transfers-locationtransfer
  /api/v2/put-away/queue:
    get:
      tags:
      - Adjustments & Transfers
      summary: Get Put-Away Queue
      description: 'Paginated put-away queue: stock with a positive balance sitting
        in put-away-from locations (staging, returns, quarantine, damaged) — plus
        the Unassigned location when include_unassigned is truthy (default). Each
        row is decorated with the product''s suggested destination bin (its preferred
        default storage location for the warehouse, when one is set and not deprecated).


        Authentication: Requires Bearer token.


        Search: filter[search] matches product SKU, product name, and location code;
        narrow with search_columns.


        Operator-aware filters: filter[sku], filter[name], filter[location_code] (text)
        and filter[quantity] (numeric). Each supports a bare implicit-is form and
        an operator form (filter[quantity.greater_than]=50). Text operators: is, is_not,
        contains, does_not_contain, starts_with, does_not_start_with, ends_with, does_not_end_with,
        is_one_of, is_not_one_of, is_empty, is_not_empty. Numeric operators: is, is_not,
        greater_than, less_than, greater_than_or_equal, less_than_or_equal, between,
        is_one_of, is_not_one_of, is_empty, is_not_empty.


        filter[warehouse_id] filters to one warehouse (exact match). include_unassigned
        toggles the Unassigned location. filter_groups accepts a base64-encoded JSON
        tree of AND/OR advanced filter groups and takes precedence over individual
        filter params.


        Allowed sorts: product (SKU), location (code), quantity. Default order: location
        code, then product SKU.


        Create a location transfer with reason put_away to work rows off the queue.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        product_id:
                          type: integer
                        product:
                          type: object
                          properties:
                            id:
                              type: integer
                            sku:
                              type: string
                            name:
                              type: string
                        warehouse_id:
                          type: integer
                        warehouse_location_id:
                          type: integer
                        location:
                          type: object
                          properties:
                            id:
                              type: integer
                            code:
                              type: string
                            name:
                              type: string
                            type:
                              type: string
                            type_label:
                              type: string
                        quantity:
                          type: integer
                        suggested_location:
                          type: object
                          properties:
                            id:
                              type: integer
                            code:
                              type: string
                  current_page:
                    type: integer
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - product_id: 42
                    product:
                      id: 42
                      sku: SKU-ABC-123
                      name: Blue Widget 500ml
                    warehouse_id: 1
                    warehouse_location_id: 7
                    location:
                      id: 7
                      code: RECEIVING
                      name: Receiving
                      type: staging
                      type_label: Staging
                    quantity: 100
                    suggested_location:
                      id: 15
                      code: A-01-2-B
                  - product_id: 77
                    product:
                      id: 77
                      sku: SKU-GHI-789
                      name: Green Gadget XL
                    warehouse_id: 1
                    warehouse_location_id: 2
                    location:
                      id: 2
                      code: UNASSIGNED
                      name: Unassigned
                      type: storage
                      type_label: Storage
                    quantity: 950
                    suggested_location: null
                  current_page: 1
                  first_page_url: '{{protocol}}{{domain}}/api/v2/put-away/queue?page=1'
                  from: 1
                  last_page: 1
                  last_page_url: '{{protocol}}{{domain}}/api/v2/put-away/queue?page=1'
                  links: []
                  next_page_url: null
                  path: '{{protocol}}{{domain}}/api/v2/put-away/queue'
                  per_page: 10
                  prev_page_url: null
                  to: 2
                  total: 2
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      warehouse_id:
                        type: array
                        items:
                          type: string
                example:
                  message: A warehouse is required to load the put-away queue.
                  errors:
                    warehouse_id:
                    - A warehouse is required to load the put-away queue.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-v2-put-away-queue
  /api/warehouses:
    post:
      tags:
      - Warehouses
      summary: Create Warehouse
      description: 'Creates a new warehouse.


        :::info[Required scope: `warehouses:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Required fields: name (unique, max 255), type (one of: direct, 3pl, supplier,
        amazon_fba, virtual, amazon_awd, walmart_wfs).


        Optional fields: subtype (only "decorator" may be set here; integration-managed
        subtypes are assigned automatically), address_name, company, email, phone,
        fax, address1, address2, address3, city, province, province_code, zip, country,
        country_code, supplier_id (links a supplier-owned warehouse), order_fulfillment,
        dropship_enabled, direct_returns, customer_returns, auto_routing_enabled,
        auto_dispatch_enabled, partial_dispatch_enabled, is_default, default_location
        (object with aisle, bay, shelf, bin), nominal_code_id, transfer_destination_warehouse_id.


        The warehouse name must be unique (per supplier for supplier warehouses).


        Authentication: Requires Bearer token.


        Also accepts (3PL warehouses): fba_inbound_reminders_enabled (boolean) and
        fba_inbound_reminder_days (array of positive integer day-offsets, e.g. [3,7,14])
        — controls automatic FBA-inbound turnaround reminders to this 3PL.


        WFS inbound-reminder settings (opt-in turnaround nudges for WFS inbound shipments
        sourced from this 3PL/warehouse):

        - wfs_inbound_reminders_enabled (boolean, optional): enable per-warehouse
        WFS inbound turnaround reminders.

        - wfs_inbound_reminder_days (int[], optional, nullable, each 1–365): days-after-send
        cadence to remind on (default [3, 7, 14] when reminders are enabled and none
        provided).


        `negative_bin_policy` (optional; one of `block`, `warn`, `allow`; default
        `warn`) controls how the warehouse reacts when an outbound movement would
        drive a specific bin''s on-hand below zero: `block` rejects the movement,
        `warn` permits it but flags the shortfall, and `allow` permits it silently.
        The warehouse''s default catch-all location is always exempt.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                type:
                  type: string
                company:
                  type: string
                email:
                  type: string
                phone:
                  type: string
                address1:
                  type: string
                address2:
                  type: string
                  nullable: true
                city:
                  type: string
                province:
                  type: string
                province_code:
                  type: string
                zip:
                  type: string
                country:
                  type: string
                country_code:
                  type: string
                order_fulfillment:
                  type: string
                dropship_enabled:
                  type: boolean
                direct_returns:
                  type: boolean
                customer_returns:
                  type: boolean
                auto_routing_enabled:
                  type: boolean
                auto_dispatch_enabled:
                  type: boolean
                partial_dispatch_enabled:
                  type: boolean
                negative_bin_policy:
                  type: string
                default_location:
                  type: object
                  properties:
                    aisle:
                      type: string
                    bay:
                      type: string
                      nullable: true
                    shelf:
                      type: string
                      nullable: true
                    bin:
                      type: string
                      nullable: true
                nominal_code_id:
                  type: string
                  nullable: true
                transfer_destination_warehouse_id:
                  type: string
                  nullable: true
                wfs_inbound_reminders_enabled:
                  type: boolean
                wfs_inbound_reminder_days:
                  type: array
                  items:
                    type: integer
                exclude_from_planning:
                  type: boolean
              example:
                name: Main Warehouse
                type: direct
                company: Acme Corp
                email: warehouse@example.com
                phone: +1 555 0100
                address1: 100 Commerce Way
                address2: null
                city: Austin
                province: Texas
                province_code: TX
                zip: '78701'
                country: United States
                country_code: US
                order_fulfillment: manual
                dropship_enabled: false
                direct_returns: false
                customer_returns: true
                auto_routing_enabled: true
                auto_dispatch_enabled: false
                partial_dispatch_enabled: false
                negative_bin_policy: warn
                default_location:
                  aisle: Default
                  bay: null
                  shelf: null
                  bin: null
                nominal_code_id: null
                transfer_destination_warehouse_id: null
                wfs_inbound_reminders_enabled: true
                wfs_inbound_reminder_days:
                - 3
                - 7
                - 14
                exclude_from_planning: false
      parameters: []
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      name:
                        type: string
                      display_name:
                        type: string
                      id:
                        type: integer
                      type:
                        type: string
                      subtype:
                        type: string
                        nullable: true
                      supplier_id:
                        type: string
                        nullable: true
                      contractor_supplier_id:
                        type: string
                        nullable: true
                      dropship_enabled:
                        type: boolean
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                      address_name:
                        type: string
                      order_fulfillment:
                        type: string
                      address_id:
                        type: integer
                      label:
                        type: string
                        nullable: true
                      email:
                        type: string
                      phone:
                        type: string
                      fax:
                        type: string
                        nullable: true
                      company:
                        type: string
                      address1:
                        type: string
                      address2:
                        type: string
                        nullable: true
                      address3:
                        type: string
                        nullable: true
                      city:
                        type: string
                      province:
                        type: string
                      province_code:
                        type: string
                      zip:
                        type: string
                      country:
                        type: string
                      country_code:
                        type: string
                      address_redacted:
                        type: boolean
                      warehouse_locations:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            warehouse_id:
                              type: integer
                            aisle:
                              type: string
                            bay:
                              type: string
                              nullable: true
                            shelf:
                              type: string
                              nullable: true
                            bin:
                              type: string
                              nullable: true
                            is_default:
                              type: boolean
                      shipping_automated:
                        type: string
                        nullable: true
                      is_archivable:
                        type: boolean
                      archive_blocked_reason:
                        type: string
                        nullable: true
                      auto_routing_enabled:
                        type: boolean
                      auto_dispatch_enabled:
                        type: boolean
                      partial_dispatch_enabled:
                        type: boolean
                      negative_bin_policy:
                        type: string
                      integration_instance_id:
                        type: string
                        nullable: true
                      nominal_code_id:
                        type: string
                        nullable: true
                      transfer_destination_warehouse_id:
                        type: string
                        nullable: true
                      is_amazon_fba_warehouse:
                        type: boolean
                      externally_managed:
                        type: boolean
                example:
                  message: warehouse created successfully.
                  data:
                    name: Main Warehouse
                    display_name: Main Warehouse
                    id: 12
                    type: direct
                    subtype: null
                    supplier_id: null
                    contractor_supplier_id: null
                    dropship_enabled: false
                    created_at: '2026-01-10T09:00:00.000000Z'
                    updated_at: '2026-06-01T14:30:00.000000Z'
                    archived_at: null
                    address_name: Main Warehouse
                    order_fulfillment: manual
                    address_id: 301
                    label: null
                    email: warehouse@example.com
                    phone: +1 555 0100
                    fax: null
                    company: Acme Corp
                    address1: 100 Commerce Way
                    address2: null
                    address3: null
                    city: Austin
                    province: Texas
                    province_code: TX
                    zip: '78701'
                    country: United States
                    country_code: US
                    address_redacted: false
                    warehouse_locations:
                    - id: 55
                      warehouse_id: 12
                      aisle: Default
                      bay: null
                      shelf: null
                      bin: null
                      is_default: true
                    shipping_automated: null
                    is_archivable: true
                    archive_blocked_reason: null
                    auto_routing_enabled: true
                    auto_dispatch_enabled: false
                    partial_dispatch_enabled: false
                    negative_bin_policy: warn
                    integration_instance_id: null
                    nominal_code_id: null
                    transfer_destination_warehouse_id: null
                    is_amazon_fba_warehouse: false
                    externally_managed: false
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      name:
                        type: array
                        items:
                          type: string
                example:
                  message: The given data was invalid.
                  errors:
                    name:
                    - Warehouse name should be unique.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: warehouses:write
      operationId: post-api-warehouses
    delete:
      tags:
      - Warehouses
      summary: Bulk Delete Warehouses
      description: 'Deletes multiple warehouses. Provide either ids (array of warehouse
        IDs) or apply_to_all=true with an optional filters object. Warehouses referenced
        by other records are skipped and counted in failCount. Use Check Warehouses
        Deletable first to verify which records can be removed.


        :::info[Required scope: `warehouses:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      totalCount:
                        type: integer
                      failCount:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    totalCount: 3
                    failCount: 0
                  message: 3 records processed successfully.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: warehouses:write
      operationId: delete-api-warehouses
  /api/warehouses/{warehouse}:
    put:
      tags:
      - Warehouses
      summary: Update Warehouse
      description: 'Updates an existing warehouse. Accepts the same fields as Create
        Warehouse; all fields are optional on update.


        :::info[Required scope: `warehouses:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Address fields (address1, city, zip, country_code, etc.) update the warehouse''s
        address record. Setting is_default on a supplier warehouse makes it that supplier''s
        default warehouse. Toggling auto_routing_enabled adds or removes the warehouse
        from the automatic order-routing priority list.


        Returns 400 when disabling dropshipping on a warehouse that still has open
        dropship orders.


        Authentication: Requires Bearer token.


        Also accepts (3PL warehouses): fba_inbound_reminders_enabled (boolean) and
        fba_inbound_reminder_days (array of positive integer day-offsets, e.g. [3,7,14])
        — controls automatic FBA-inbound turnaround reminders to this 3PL.


        WFS inbound-reminder settings (opt-in turnaround nudges for WFS inbound shipments
        sourced from this 3PL/warehouse):

        - wfs_inbound_reminders_enabled (boolean, optional): enable per-warehouse
        WFS inbound turnaround reminders.

        - wfs_inbound_reminder_days (int[], optional, nullable, each 1–365): days-after-send
        cadence to remind on (default [3, 7, 14] when reminders are enabled and none
        provided).


        `negative_bin_policy` (optional; one of `block`, `warn`, `allow`; default
        `warn`) controls how the warehouse reacts when an outbound movement would
        drive a specific bin''s on-hand below zero: `block` rejects the movement,
        `warn` permits it but flags the shortfall, and `allow` permits it silently.
        The warehouse''s default catch-all location is always exempt.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                auto_routing_enabled:
                  type: boolean
                order_fulfillment:
                  type: string
                wfs_inbound_reminders_enabled:
                  type: boolean
                wfs_inbound_reminder_days:
                  type: array
                  items:
                    type: integer
                negative_bin_policy:
                  type: string
                exclude_from_planning:
                  type: boolean
              example:
                name: Main Warehouse East
                auto_routing_enabled: false
                order_fulfillment: manual
                wfs_inbound_reminders_enabled: true
                wfs_inbound_reminder_days:
                - 3
                - 7
                - 14
                negative_bin_policy: block
                exclude_from_planning: false
      parameters:
      - name: warehouse
        in: path
        schema:
          type: integer
        required: true
        description: Warehouse ID
        example: '12'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      name:
                        type: string
                      display_name:
                        type: string
                      id:
                        type: integer
                      type:
                        type: string
                      subtype:
                        type: string
                        nullable: true
                      supplier_id:
                        type: string
                        nullable: true
                      contractor_supplier_id:
                        type: string
                        nullable: true
                      dropship_enabled:
                        type: boolean
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                      address_name:
                        type: string
                      order_fulfillment:
                        type: string
                      address_id:
                        type: integer
                      label:
                        type: string
                        nullable: true
                      email:
                        type: string
                      phone:
                        type: string
                      fax:
                        type: string
                        nullable: true
                      company:
                        type: string
                      address1:
                        type: string
                      address2:
                        type: string
                        nullable: true
                      address3:
                        type: string
                        nullable: true
                      city:
                        type: string
                      province:
                        type: string
                      province_code:
                        type: string
                      zip:
                        type: string
                      country:
                        type: string
                      country_code:
                        type: string
                      address_redacted:
                        type: boolean
                      warehouse_locations:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            warehouse_id:
                              type: integer
                            aisle:
                              type: string
                            bay:
                              type: string
                              nullable: true
                            shelf:
                              type: string
                              nullable: true
                            bin:
                              type: string
                              nullable: true
                            is_default:
                              type: boolean
                      shipping_automated:
                        type: string
                        nullable: true
                      is_archivable:
                        type: boolean
                      archive_blocked_reason:
                        type: string
                        nullable: true
                      auto_routing_enabled:
                        type: boolean
                      auto_dispatch_enabled:
                        type: boolean
                      partial_dispatch_enabled:
                        type: boolean
                      negative_bin_policy:
                        type: string
                      integration_instance_id:
                        type: string
                        nullable: true
                      nominal_code_id:
                        type: string
                        nullable: true
                      transfer_destination_warehouse_id:
                        type: string
                        nullable: true
                      is_amazon_fba_warehouse:
                        type: boolean
                      externally_managed:
                        type: boolean
                example:
                  message: warehouse Main Warehouse East updated successfully.
                  data:
                    name: Main Warehouse
                    display_name: Main Warehouse
                    id: 12
                    type: direct
                    subtype: null
                    supplier_id: null
                    contractor_supplier_id: null
                    dropship_enabled: false
                    created_at: '2026-01-10T09:00:00.000000Z'
                    updated_at: '2026-06-01T14:30:00.000000Z'
                    archived_at: null
                    address_name: Main Warehouse
                    order_fulfillment: manual
                    address_id: 301
                    label: null
                    email: warehouse@example.com
                    phone: +1 555 0100
                    fax: null
                    company: Acme Corp
                    address1: 100 Commerce Way
                    address2: null
                    address3: null
                    city: Austin
                    province: Texas
                    province_code: TX
                    zip: '78701'
                    country: United States
                    country_code: US
                    address_redacted: false
                    warehouse_locations:
                    - id: 55
                      warehouse_id: 12
                      aisle: Default
                      bay: null
                      shelf: null
                      bin: null
                      is_default: true
                    shipping_automated: null
                    is_archivable: true
                    archive_blocked_reason: null
                    auto_routing_enabled: true
                    auto_dispatch_enabled: false
                    partial_dispatch_enabled: false
                    negative_bin_policy: block
                    integration_instance_id: null
                    nominal_code_id: null
                    transfer_destination_warehouse_id: null
                    is_amazon_fba_warehouse: false
                    externally_managed: false
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      id:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: object
                              properties:
                                id:
                                  type: integer
                example:
                  message: warehouse update failed.
                  errors:
                    id:
                    - message: Dropship warehouse has open orders.
                      code: UpdateWarehouse406
                      data:
                        id: 12
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: warehouses:write
      operationId: put-api-warehouses-warehouse
    delete:
      tags:
      - Warehouses
      summary: Delete Warehouse
      description: 'Deletes a warehouse. A warehouse that is referenced by inventory,
        orders, or other records cannot be deleted; the response lists the linked
        record types blocking deletion. Use Check Warehouses Deletable first to verify
        deletability.


        :::info[Required scope: `warehouses:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: warehouse
        in: path
        schema:
          type: integer
        required: true
        description: Warehouse ID
        example: '12'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: warehouse Main Warehouse deleted successfully.
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      products:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: object
                              properties:
                                warehouse_id:
                                  type: integer
                example:
                  message: warehouse Main Warehouse could not be deleted.
                  errors:
                    products:
                    - message: Warehouse has inventory records.
                      code: Product409
                      data:
                        warehouse_id: 12
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: warehouses:write
      operationId: delete-api-warehouses-warehouse
  /api/warehouses/{warehouse}/archive:
    put:
      tags:
      - Warehouses
      summary: Archive Warehouse
      description: 'Archives a warehouse, hiding it from active listings. Integration-managed
        warehouses (e.g. Amazon FBA) and warehouses that still hold available stock
        cannot be archived.


        :::info[Required scope: `warehouses:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: warehouse
        in: path
        schema:
          type: integer
        required: true
        description: Warehouse ID
        example: '12'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      name:
                        type: string
                      display_name:
                        type: string
                      id:
                        type: integer
                      type:
                        type: string
                      subtype:
                        type: string
                        nullable: true
                      supplier_id:
                        type: string
                        nullable: true
                      contractor_supplier_id:
                        type: string
                        nullable: true
                      dropship_enabled:
                        type: boolean
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                      address_name:
                        type: string
                      order_fulfillment:
                        type: string
                      address_id:
                        type: integer
                      label:
                        type: string
                        nullable: true
                      email:
                        type: string
                      phone:
                        type: string
                      fax:
                        type: string
                        nullable: true
                      company:
                        type: string
                      address1:
                        type: string
                      address2:
                        type: string
                        nullable: true
                      address3:
                        type: string
                        nullable: true
                      city:
                        type: string
                      province:
                        type: string
                      province_code:
                        type: string
                      zip:
                        type: string
                      country:
                        type: string
                      country_code:
                        type: string
                      address_redacted:
                        type: boolean
                      warehouse_locations:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            warehouse_id:
                              type: integer
                            aisle:
                              type: string
                            bay:
                              type: string
                              nullable: true
                            shelf:
                              type: string
                              nullable: true
                            bin:
                              type: string
                              nullable: true
                            is_default:
                              type: boolean
                      shipping_automated:
                        type: string
                        nullable: true
                      is_archivable:
                        type: boolean
                      archive_blocked_reason:
                        type: string
                        nullable: true
                      auto_routing_enabled:
                        type: boolean
                      auto_dispatch_enabled:
                        type: boolean
                      partial_dispatch_enabled:
                        type: boolean
                      integration_instance_id:
                        type: string
                        nullable: true
                      nominal_code_id:
                        type: string
                        nullable: true
                      transfer_destination_warehouse_id:
                        type: string
                        nullable: true
                      is_amazon_fba_warehouse:
                        type: boolean
                      externally_managed:
                        type: boolean
                example:
                  message: warehouse Main Warehouse archived successfully.
                  data:
                    name: Main Warehouse
                    display_name: Main Warehouse
                    id: 12
                    type: direct
                    subtype: null
                    supplier_id: null
                    contractor_supplier_id: null
                    dropship_enabled: false
                    created_at: '2026-01-10T09:00:00.000000Z'
                    updated_at: '2026-06-01T14:30:00.000000Z'
                    archived_at: null
                    address_name: Main Warehouse
                    order_fulfillment: manual
                    address_id: 301
                    label: null
                    email: warehouse@example.com
                    phone: +1 555 0100
                    fax: null
                    company: Acme Corp
                    address1: 100 Commerce Way
                    address2: null
                    address3: null
                    city: Austin
                    province: Texas
                    province_code: TX
                    zip: '78701'
                    country: United States
                    country_code: US
                    address_redacted: false
                    warehouse_locations:
                    - id: 55
                      warehouse_id: 12
                      aisle: Default
                      bay: null
                      shelf: null
                      bin: null
                      is_default: true
                    shipping_automated: null
                    is_archivable: true
                    archive_blocked_reason: null
                    auto_routing_enabled: true
                    auto_dispatch_enabled: false
                    partial_dispatch_enabled: false
                    integration_instance_id: null
                    nominal_code_id: null
                    transfer_destination_warehouse_id: null
                    is_amazon_fba_warehouse: false
                    externally_managed: false
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      id:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: object
                              properties:
                                id:
                                  type: integer
                example:
                  message: warehouse could not be archived.
                  errors:
                    id:
                    - message: Integration warehouses cannot be archived.
                      code: ArchiveWarehouse406
                      data:
                        id: 12
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: warehouses:write
      operationId: put-api-warehouses-warehouse-archive
  /api/warehouses/{warehouse}/unarchived:
    put:
      tags:
      - Warehouses
      summary: Unarchive Warehouse
      description: 'Restores an archived warehouse to active status. Integration-managed
        warehouses (e.g. Amazon FBA) cannot be modified through this endpoint.


        :::info[Required scope: `warehouses:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: warehouse
        in: path
        schema:
          type: integer
        required: true
        description: Warehouse ID
        example: '12'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      name:
                        type: string
                      display_name:
                        type: string
                      id:
                        type: integer
                      type:
                        type: string
                      subtype:
                        type: string
                        nullable: true
                      supplier_id:
                        type: string
                        nullable: true
                      contractor_supplier_id:
                        type: string
                        nullable: true
                      dropship_enabled:
                        type: boolean
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                      address_name:
                        type: string
                      order_fulfillment:
                        type: string
                      address_id:
                        type: integer
                      label:
                        type: string
                        nullable: true
                      email:
                        type: string
                      phone:
                        type: string
                      fax:
                        type: string
                        nullable: true
                      company:
                        type: string
                      address1:
                        type: string
                      address2:
                        type: string
                        nullable: true
                      address3:
                        type: string
                        nullable: true
                      city:
                        type: string
                      province:
                        type: string
                      province_code:
                        type: string
                      zip:
                        type: string
                      country:
                        type: string
                      country_code:
                        type: string
                      address_redacted:
                        type: boolean
                      warehouse_locations:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            warehouse_id:
                              type: integer
                            aisle:
                              type: string
                            bay:
                              type: string
                              nullable: true
                            shelf:
                              type: string
                              nullable: true
                            bin:
                              type: string
                              nullable: true
                            is_default:
                              type: boolean
                      shipping_automated:
                        type: string
                        nullable: true
                      is_archivable:
                        type: boolean
                      archive_blocked_reason:
                        type: string
                        nullable: true
                      auto_routing_enabled:
                        type: boolean
                      auto_dispatch_enabled:
                        type: boolean
                      partial_dispatch_enabled:
                        type: boolean
                      integration_instance_id:
                        type: string
                        nullable: true
                      nominal_code_id:
                        type: string
                        nullable: true
                      transfer_destination_warehouse_id:
                        type: string
                        nullable: true
                      is_amazon_fba_warehouse:
                        type: boolean
                      externally_managed:
                        type: boolean
                example:
                  message: warehouse Main Warehouse unarchived successfully.
                  data:
                    name: Main Warehouse
                    display_name: Main Warehouse
                    id: 12
                    type: direct
                    subtype: null
                    supplier_id: null
                    contractor_supplier_id: null
                    dropship_enabled: false
                    created_at: '2026-01-10T09:00:00.000000Z'
                    updated_at: '2026-06-01T14:30:00.000000Z'
                    archived_at: null
                    address_name: Main Warehouse
                    order_fulfillment: manual
                    address_id: 301
                    label: null
                    email: warehouse@example.com
                    phone: +1 555 0100
                    fax: null
                    company: Acme Corp
                    address1: 100 Commerce Way
                    address2: null
                    address3: null
                    city: Austin
                    province: Texas
                    province_code: TX
                    zip: '78701'
                    country: United States
                    country_code: US
                    address_redacted: false
                    warehouse_locations:
                    - id: 55
                      warehouse_id: 12
                      aisle: Default
                      bay: null
                      shelf: null
                      bin: null
                      is_default: true
                    shipping_automated: null
                    is_archivable: true
                    archive_blocked_reason: null
                    auto_routing_enabled: true
                    auto_dispatch_enabled: false
                    partial_dispatch_enabled: false
                    integration_instance_id: null
                    nominal_code_id: null
                    transfer_destination_warehouse_id: null
                    is_amazon_fba_warehouse: false
                    externally_managed: false
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: warehouses:write
      operationId: put-api-warehouses-warehouse-unarchived
  /api/warehouses/archive:
    put:
      tags:
      - Warehouses
      summary: Bulk Archive Warehouses
      description: 'Archives multiple warehouses. Provide either ids (array of warehouse
        IDs) or apply_to_all=true with an optional filters object to target all warehouses
        matching the current listing filters.


        :::info[Required scope: `warehouses:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Warehouses that cannot be archived (integration-managed, or holding stock)
        are skipped and counted in failCount, with a per-record warning in the response.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 12
                - 13
                - 14
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      totalCount:
                        type: integer
                      failCount:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    totalCount: 3
                    failCount: 0
                  message: 3 records processed successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: warehouses:write
      operationId: put-api-warehouses-archive
  /api/warehouses/unarchive:
    put:
      tags:
      - Warehouses
      summary: Bulk Unarchive Warehouses
      description: 'Restores multiple archived warehouses. Provide either ids (array
        of warehouse IDs) or apply_to_all=true with an optional filters object.


        :::info[Required scope: `warehouses:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 12
                - 13
                - 14
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      totalCount:
                        type: integer
                      failCount:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    totalCount: 3
                    failCount: 0
                  message: 3 records processed successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: warehouses:write
      operationId: put-api-warehouses-unarchive
  /api/warehouses/deletable:
    post:
      tags:
      - Warehouses
      summary: Check Warehouses Deletable
      description: 'Checks whether the given warehouses can be deleted. Provide ids
        (array of warehouse IDs), or scope="all" to check every warehouse matching
        the current listing filters.


        :::info[Required scope: `warehouses:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Each result includes deletable (boolean), reason (why deletion is blocked,
        or null) and reason_details (linked record breakdown, or null).


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 12
                - 13
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        deletable:
                          type: boolean
                        reason:
                          type: string
                        reason_details:
                          type: array
                          items:
                            type: object
                            properties:
                              type:
                                type: string
                              count:
                                type: integer
                example:
                  data:
                  - id: 12
                    name: Main Warehouse
                    deletable: false
                    reason: Warehouse is in use
                    reason_details:
                    - type: purchase_orders
                      count: 4
                  - id: 13
                    name: Overflow Warehouse
                    deletable: true
                    reason: null
                    reason_details: null
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: warehouses:write
      operationId: post-api-warehouses-deletable
  /api/warehouses/is-archivable:
    post:
      tags:
      - Warehouses
      summary: Check Warehouses Archivable
      description: 'Checks whether the given warehouses can be archived. Each result
        includes archivable (boolean) and reason (why archiving is blocked, or null).
        Integration-managed warehouses and warehouses holding stock are not archivable.


        :::info[Required scope: `warehouses:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 12
                - 13
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        archivable:
                          type: boolean
                        reason:
                          type: string
                example:
                  data:
                  - id: 12
                    name: Main Warehouse
                    archivable: false
                    reason: Warehouse has stock available
                  - id: 13
                    name: Overflow Warehouse
                    archivable: true
                    reason: null
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: warehouses:write
      operationId: post-api-warehouses-is-archivable
  /api/warehouses/import/preview:
    post:
      tags:
      - Warehouses
      summary: Preview Warehouse Import
      description: 'Parses an uploaded CSV file and returns a preview before importing:
        parsed records, detected file headers, the list of importable fields, unmatched
        columns (difference), missing required columns (required_difference) and columns
        that cannot be imported (not_importable).


        :::info[Required scope: `warehouses:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Required fields: original_name (the file''s original name), stored_name (the
        stored upload reference returned by the file upload). Optional: mapping (array
        of {file_field, expected_field} pairs to map CSV columns to warehouse fields),
        separator, escape, meta, task_id.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                original_name:
                  type: string
                stored_name:
                  type: string
                separator:
                  type: string
                escape:
                  type: string
                mapping:
                  type: array
                  items:
                    type: object
                    properties:
                      file_field:
                        type: string
                      expected_field:
                        type: string
              example:
                original_name: warehouses.csv
                stored_name: uploads/abc123-warehouses.csv
                separator: ','
                escape: '"'
                mapping:
                - file_field: Warehouse Name
                  expected_field: name
                - file_field: Type
                  expected_field: type
                - file_field: City
                  expected_field: city
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      records:
                        type: array
                        items:
                          type: object
                          properties:
                            name:
                              type: string
                            type:
                              type: string
                            city:
                              type: string
                      file_headers:
                        type: array
                        items:
                          type: string
                      importable_fields:
                        type: array
                        items:
                          type: string
                      difference:
                        type: array
                      required_difference:
                        type: array
                      not_importable:
                        type: array
                      task_id:
                        type: string
                        nullable: true
                example:
                  data:
                    records:
                    - name: Main Warehouse
                      type: direct
                      city: Austin
                    file_headers:
                    - Warehouse Name
                    - Type
                    - City
                    importable_fields:
                    - name
                    - type
                    - city
                    - province
                    - country_code
                    - zip
                    difference: []
                    required_difference: []
                    not_importable: []
                    task_id: null
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: warehouses:write
      operationId: post-api-warehouses-import-preview
  /api/warehouses/import:
    post:
      tags:
      - Warehouses
      summary: Import Warehouses
      description: 'Imports warehouses from an uploaded CSV file. Accepts the same
        payload as Preview Warehouse Import. If required columns are missing, the
        preview payload is returned instead so the mapping can be corrected. Large
        files are processed in the background and the response indicates the import
        will complete shortly.


        :::info[Required scope: `warehouses:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                original_name:
                  type: string
                stored_name:
                  type: string
                separator:
                  type: string
                escape:
                  type: string
                mapping:
                  type: array
                  items:
                    type: object
                    properties:
                      file_field:
                        type: string
                      expected_field:
                        type: string
              example:
                original_name: warehouses.csv
                stored_name: uploads/abc123-warehouses.csv
                separator: ','
                escape: '"'
                mapping:
                - file_field: Warehouse Name
                  expected_field: name
                - file_field: Type
                  expected_field: type
                - file_field: City
                  expected_field: city
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: string
                example:
                  data: Data import was successful.
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      ImportData:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: array
                example:
                  message: CSV Import has invalid syntax
                  errors:
                    ImportData:
                    - message: 'CSV Import has invalid syntax: unexpected character.'
                      code: '406'
                      data: []
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: warehouses:write
      operationId: post-api-warehouses-import
  /api/v2/warehouses/export:
    get:
      tags:
      - Warehouses
      summary: Export Warehouses
      description: 'Exports warehouses matching the current filters as a CSV or XLSX
        file download.


        :::info[Required scope: `warehouses:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Columns: Sr No., id, name, type, city, province, province_code, country, country_code,
        zip, created_at, updated_at. Archived warehouses are excluded unless filter[archived]
        is provided (values: only, all).


        Column filters accept operator suffixes in the form filter[column.operator],
        e.g. filter[name.contains]=main or filter[created_at.between]=2026-01-01,2026-06-30.
        Text operators: is, is_not, contains, does_not_contain, starts_with, ends_with,
        is_empty, is_not_empty, is_one_of. Numeric operators: is, is_not, greater_than,
        greater_than_or_equal, less_than, less_than_or_equal, between, is_empty, is_not_empty.
        Date operators: is, is_not, on_or_before, on_or_after, between, is_empty,
        is_not_empty.


        Authentication: Requires Bearer token.


        Optional. When `include_contacts=1`, the export flattens to one row per contact
        with the parent columns repeated (parent-only row when a record has no contacts),
        appending Contact ID/Name/Email/Phone/Role/Title/Primary/Notes columns.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: text/csv
          content:
            text/plain:
              schema:
                type: string
                example: 'Sr No.,id,name,type,city,province,province_code,country,country_code,zip,created_at,updated_at

                  1,12,Main Warehouse,direct,Austin,Texas,TX,United States,US,78701,2026-01-10T09:00:00.000000Z,2026-06-01T14:30:00.000000Z

                  '
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: warehouses:read
      operationId: get-api-v2-warehouses-export
  /api/warehouses/fulfillment-dispatch-settings:
    get:
      tags:
      - Warehouses
      summary: List Fulfillment Dispatch Settings
      description: 'Returns the fulfillment dispatch configuration for every non-supplier
        warehouse: the fulfillment channel (order_fulfillment), whether fulfillments
        are automatically dispatched to the connected shipping provider (auto_dispatch_enabled)
        and whether partial dispatch is allowed (partial_dispatch_enabled).


        :::info[Required scope: `warehouses:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        The response also includes shippingProviders (the available order_fulfillment
        values: "manual" plus the names of connected shipping-provider integrations)
        and shippingProviderDispatchEnabled (whether real provider dispatch is on
        for this account) and shippingProviderDispatchEditable (whether that setting
        can be toggled here — true outside production, where dispatch is a per-account
        opt-in; false in production, where it is always on).


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        order_fulfillment:
                          type: string
                        auto_dispatch_enabled:
                          type: boolean
                        partial_dispatch_enabled:
                          type: boolean
                        type:
                          type: string
                        integration_instance_id:
                          type: string
                          nullable: true
                        integration_name:
                          type: string
                          nullable: true
                        integration_sub_type:
                          type: string
                          nullable: true
                  shippingProviders:
                    type: array
                    items:
                      type: string
                  shippingProviderDispatchEnabled:
                    type: boolean
                  shippingProviderDispatchEditable:
                    type: boolean
                example:
                  data:
                  - id: 12
                    name: Main Warehouse
                    order_fulfillment: manual
                    auto_dispatch_enabled: false
                    partial_dispatch_enabled: false
                    type: direct
                    integration_instance_id: null
                    integration_name: null
                    integration_sub_type: null
                  - id: 5
                    name: West Coast 3PL
                    order_fulfillment: shipstation
                    auto_dispatch_enabled: true
                    partial_dispatch_enabled: true
                    type: 3pl
                    integration_instance_id: 9
                    integration_name: ShipStation
                    integration_sub_type: shipping_provider
                  shippingProviders:
                  - manual
                  - shipstation
                  shippingProviderDispatchEnabled: true
                  shippingProviderDispatchEditable: false
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: warehouses:read
      operationId: get-api-warehouses-fulfillment-dispatch-settings
  /api/warehouses/bulk-update:
    patch:
      tags:
      - Warehouses
      summary: Bulk Update Warehouse Dispatch Settings
      description: 'Updates fulfillment dispatch settings for multiple warehouses
        in one request.


        :::info[Required scope: `warehouses:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Each entry requires id, auto_dispatch_enabled and partial_dispatch_enabled;
        order_fulfillment (the fulfillment channel, "manual" or a connected shipping-provider
        name) is optional.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                warehouses:
                  type: array
                  items:
                    type: object
                    properties:
                      id:
                        type: integer
                      auto_dispatch_enabled:
                        type: boolean
                      partial_dispatch_enabled:
                        type: boolean
                      order_fulfillment:
                        type: string
              example:
                warehouses:
                - id: 12
                  auto_dispatch_enabled: true
                  partial_dispatch_enabled: false
                  order_fulfillment: shipstation
                - id: 5
                  auto_dispatch_enabled: true
                  partial_dispatch_enabled: true
                  order_fulfillment: shipstation
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Success
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: warehouses:write
      operationId: patch-api-warehouses-bulk-update
  /api/v2/product-warehouse-locations:
    get:
      tags:
      - Warehouses
      summary: List Product Warehouse Locations
      description: 'Paginated preferred-location (bin) assignments for products, with
        the location, warehouse and product relations loaded for display. Filter by
        product_id + warehouse_id to fetch a single product''s ordered bin list.


        Authentication: Requires Bearer token.

        Scope: warehouses (read/write).


        Available sorts: id, created_at, is_default, priority (default: -is_default,
        then priority, then id — i.e. resolution order).'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        description: 'Page number (default: 1)'
        example: '1'
      - name: per_page
        in: query
        schema:
          type: integer
        description: 'Items per page (default: 10)'
        example: '10'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        product_id:
                          type: integer
                        warehouse_id:
                          type: integer
                        warehouse_location_id:
                          type: integer
                        is_default:
                          type: boolean
                        priority:
                          type: integer
                        warehouse_name:
                          type: string
                        product:
                          type: object
                          properties:
                            id:
                              type: integer
                            sku:
                              type: string
                            name:
                              type: string
                        warehouse_location:
                          type: object
                          properties:
                            id:
                              type: integer
                            code:
                              type: string
                            name:
                              type: string
                            type:
                              type: string
                            type_label:
                              type: string
                            display_name:
                              type: string
                            deprecated_at:
                              type: string
                              nullable: true
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - id: 7
                    product_id: 42
                    warehouse_id: 1
                    warehouse_location_id: 12
                    is_default: true
                    priority: 0
                    warehouse_name: Main Warehouse
                    product:
                      id: 42
                      sku: WIDGET-001
                      name: Premium Widget
                    warehouse_location:
                      id: 12
                      code: A1-B2-S3-BIN4
                      name: Aisle 1 Bay 2 Shelf 3 Bin 4
                      type: storage
                      type_label: Storage
                      display_name: A1-B2-S3-BIN4 — Aisle 1 Bay 2 Shelf 3 Bin 4
                      deprecated_at: null
                    created_at: '2026-01-15T10:00:00.000000Z'
                    updated_at: '2026-01-15T10:00:00.000000Z'
                  current_page: 1
                  last_page: 1
                  per_page: 10
                  total: 1
                  from: 1
                  to: 1
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-v2-product-warehouse-locations
    post:
      tags:
      - Warehouses
      summary: Create Product Warehouse Location
      description: 'Assign a preferred storage bin to a product in a warehouse. The
        location must be an active put-away destination. The first assignment for
        a product+warehouse automatically becomes the default; new assignments append
        to the end of the ordered list unless `priority` is given.


        Body fields:

        - product_id (required) — product to assign.

        - warehouse_id (required) — warehouse the bin lives in.

        - warehouse_location_id (required) — the bin; must belong to the warehouse
        and be a put-away destination.

        - is_default (optional, boolean) — mark as the product+warehouse default.

        - priority (optional, integer ≥ 0) — explicit position in the ordered list;
        omitted assignments append to the end.


        Authentication: Requires Bearer token.

        Scope: warehouses (read/write). Requires the warehouses.manage_locations permission.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                product_id:
                  type: integer
                warehouse_id:
                  type: integer
                warehouse_location_id:
                  type: integer
                is_default:
                  type: boolean
                priority:
                  type: integer
              example:
                product_id: 42
                warehouse_id: 1
                warehouse_location_id: 12
                is_default: true
                priority: 2
      parameters: []
      responses:
        '201':
          description: Created
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      product_id:
                        type: integer
                      warehouse_id:
                        type: integer
                      warehouse_location_id:
                        type: integer
                      is_default:
                        type: boolean
                      priority:
                        type: integer
                      warehouse_name:
                        type: string
                      product:
                        type: object
                        properties:
                          id:
                            type: integer
                          sku:
                            type: string
                          name:
                            type: string
                      warehouse_location:
                        type: object
                        properties:
                          id:
                            type: integer
                          code:
                            type: string
                          name:
                            type: string
                          type:
                            type: string
                          type_label:
                            type: string
                          display_name:
                            type: string
                          deprecated_at:
                            type: string
                            nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 7
                    product_id: 42
                    warehouse_id: 1
                    warehouse_location_id: 12
                    is_default: true
                    priority: 0
                    warehouse_name: Main Warehouse
                    product:
                      id: 42
                      sku: WIDGET-001
                      name: Premium Widget
                    warehouse_location:
                      id: 12
                      code: A1-B2-S3-BIN4
                      name: Aisle 1 Bay 2 Shelf 3 Bin 4
                      type: storage
                      type_label: Storage
                      display_name: A1-B2-S3-BIN4 — Aisle 1 Bay 2 Shelf 3 Bin 4
                      deprecated_at: null
                    created_at: '2026-01-15T10:00:00.000000Z'
                    updated_at: '2026-01-15T10:00:00.000000Z'
                  message: Preferred location assigned.
        '422':
          description: Unprocessable Content
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      warehouse_location_id:
                        type: array
                        items:
                          type: string
                example:
                  message: The preferred location must be able to receive put-away
                    stock.
                  errors:
                    warehouse_location_id:
                    - The preferred location must be able to receive put-away stock.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-v2-product-warehouse-locations
  /api/v2/product-warehouse-locations/{productWarehouseLocation}:
    put:
      tags:
      - Warehouses
      summary: Update Product Warehouse Location
      description: 'Update a preferred-bin assignment. All fields optional (`sometimes`).


        Authentication: Requires Bearer token.

        Scope: warehouses (read/write).


        Body fields (all optional):

        - warehouse_location_id (integer, exists, must be a put-away destination (is_putaway_destination
        enabled), unique per product+warehouse)

        - is_default (boolean)


        **Requires permission:** `warehouses.manage_locations`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                warehouse_location_id:
                  type: integer
                is_default:
                  type: boolean
                priority:
                  type: integer
              example:
                warehouse_location_id: 13
                is_default: true
                priority: 1
      parameters:
      - name: productWarehouseLocation
        in: path
        schema:
          type: integer
        required: true
        description: Product warehouse location (preferred bin) ID
        example: '7'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      product_id:
                        type: integer
                      warehouse_id:
                        type: integer
                      warehouse_location_id:
                        type: integer
                      is_default:
                        type: boolean
                      priority:
                        type: integer
                      warehouse_name:
                        type: string
                      product:
                        type: object
                        properties:
                          id:
                            type: integer
                          sku:
                            type: string
                          name:
                            type: string
                      warehouse_location:
                        type: object
                        properties:
                          id:
                            type: integer
                          code:
                            type: string
                          name:
                            type: string
                          type:
                            type: string
                          type_label:
                            type: string
                          display_name:
                            type: string
                          deprecated_at:
                            type: string
                            nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 7
                    product_id: 42
                    warehouse_id: 1
                    warehouse_location_id: 12
                    is_default: true
                    priority: 0
                    warehouse_name: Main Warehouse
                    product:
                      id: 42
                      sku: WIDGET-001
                      name: Premium Widget
                    warehouse_location:
                      id: 12
                      code: A1-B2-S3-BIN4
                      name: Aisle 1 Bay 2 Shelf 3 Bin 4
                      type: storage
                      type_label: Storage
                      display_name: A1-B2-S3-BIN4 — Aisle 1 Bay 2 Shelf 3 Bin 4
                      deprecated_at: null
                    created_at: '2026-01-15T10:00:00.000000Z'
                    updated_at: '2026-01-15T10:00:00.000000Z'
                  message: Preferred location updated.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-v2-product-warehouse-locations-productwarehouselocation
    delete:
      tags:
      - Warehouses
      summary: Delete Product Warehouse Location
      description: 'Remove a preferred-bin assignment.


        Authentication: Requires Bearer token.

        Scope: warehouses (read/write).


        **Requires permission:** `warehouses.manage_locations`'
      parameters:
      - name: productWarehouseLocation
        in: path
        schema:
          type: integer
        required: true
        description: Product warehouse location (preferred bin) ID
        example: '7'
      responses:
        '204':
          description: No Content
          content:
            text/plain:
              schema:
                type: string
                example: ''
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-v2-product-warehouse-locations-productwarehouselocation
  /api/v2/product-warehouse-locations/{productWarehouseLocation}/set-default:
    put:
      tags:
      - Warehouses
      summary: Set Default Preferred Bin
      description: 'Promote a preferred-bin assignment to the product+warehouse default.
        The swap is atomic — the previous default for the same product+warehouse is
        unset.


        Authentication: Requires Bearer token.

        Scope: warehouses (read/write).


        **Requires permission:** `warehouses.manage_locations`'
      requestBody:
        content: {}
      parameters:
      - name: productWarehouseLocation
        in: path
        schema:
          type: integer
        required: true
        description: Product warehouse location (preferred bin) ID
        example: '7'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      product_id:
                        type: integer
                      warehouse_id:
                        type: integer
                      warehouse_location_id:
                        type: integer
                      is_default:
                        type: boolean
                      priority:
                        type: integer
                      warehouse_name:
                        type: string
                      product:
                        type: object
                        properties:
                          id:
                            type: integer
                          sku:
                            type: string
                          name:
                            type: string
                      warehouse_location:
                        type: object
                        properties:
                          id:
                            type: integer
                          code:
                            type: string
                          name:
                            type: string
                          type:
                            type: string
                          type_label:
                            type: string
                          display_name:
                            type: string
                          deprecated_at:
                            type: string
                            nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 7
                    product_id: 42
                    warehouse_id: 1
                    warehouse_location_id: 12
                    is_default: true
                    priority: 0
                    warehouse_name: Main Warehouse
                    product:
                      id: 42
                      sku: WIDGET-001
                      name: Premium Widget
                    warehouse_location:
                      id: 12
                      code: A1-B2-S3-BIN4
                      name: Aisle 1 Bay 2 Shelf 3 Bin 4
                      type: storage
                      type_label: Storage
                      display_name: A1-B2-S3-BIN4 — Aisle 1 Bay 2 Shelf 3 Bin 4
                      deprecated_at: null
                    created_at: '2026-01-15T10:00:00.000000Z'
                    updated_at: '2026-01-15T10:00:00.000000Z'
                  message: Default preferred location updated.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-v2-product-warehouse-locations-productwarehouselocation-set-default
  /api/v2/product-warehouse-locations/reorder:
    put:
      tags:
      - Warehouses
      summary: Reorder Preferred Bins
      description: 'Reorder a product''s preferred bins in a warehouse to match the
        given id order (top to bottom) and return the fresh ordered list. Priorities
        are rewritten 0-based and the new top bin becomes the default, so the ordered
        list matches the resolution order used by put-away and receiving.


        Body fields:

        - product_id (required) — product whose bins are reordered.

        - warehouse_id (required) — warehouse the bins live in.

        - ids (required, array of integers) — assignment ids in the desired order;
        must be exactly the product+warehouse''s current assignments.


        Authentication: Requires Bearer token.

        Scope: warehouses (read/write). Requires the warehouses.manage_locations permission.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                product_id:
                  type: integer
                warehouse_id:
                  type: integer
                ids:
                  type: array
                  items:
                    type: integer
              example:
                product_id: 42
                warehouse_id: 1
                ids:
                - 9
                - 7
                - 8
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        product_id:
                          type: integer
                        warehouse_id:
                          type: integer
                        warehouse_location_id:
                          type: integer
                        is_default:
                          type: boolean
                        priority:
                          type: integer
                        warehouse_name:
                          type: string
                        product:
                          type: object
                          properties:
                            id:
                              type: integer
                            sku:
                              type: string
                            name:
                              type: string
                        warehouse_location:
                          type: object
                          properties:
                            id:
                              type: integer
                            code:
                              type: string
                            name:
                              type: string
                              nullable: true
                            type:
                              type: string
                            type_label:
                              type: string
                            display_name:
                              type: string
                            deprecated_at:
                              type: string
                              nullable: true
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  message:
                    type: string
                example:
                  data:
                  - id: 9
                    product_id: 42
                    warehouse_id: 1
                    warehouse_location_id: 15
                    is_default: true
                    priority: 0
                    warehouse_name: Main Warehouse
                    product:
                      id: 42
                      sku: WIDGET-001
                      name: Premium Widget
                    warehouse_location:
                      id: 15
                      code: C1-B1-S1-BIN1
                      name: null
                      type: storage
                      type_label: Storage
                      display_name: C1-B1-S1-BIN1
                      deprecated_at: null
                    created_at: '2026-01-15T10:00:00.000000Z'
                    updated_at: '2026-01-15T10:00:00.000000Z'
                  - id: 7
                    product_id: 42
                    warehouse_id: 1
                    warehouse_location_id: 12
                    is_default: false
                    priority: 1
                    warehouse_name: Main Warehouse
                    product:
                      id: 42
                      sku: WIDGET-001
                      name: Premium Widget
                    warehouse_location:
                      id: 12
                      code: A1-B2-S3-BIN4
                      name: null
                      type: storage
                      type_label: Storage
                      display_name: A1-B2-S3-BIN4
                      deprecated_at: null
                    created_at: '2026-01-15T10:00:00.000000Z'
                    updated_at: '2026-01-15T10:00:00.000000Z'
                  - id: 8
                    product_id: 42
                    warehouse_id: 1
                    warehouse_location_id: 13
                    is_default: false
                    priority: 2
                    warehouse_name: Main Warehouse
                    product:
                      id: 42
                      sku: WIDGET-001
                      name: Premium Widget
                    warehouse_location:
                      id: 13
                      code: B1-B1-S1-BIN1
                      name: null
                      type: storage
                      type_label: Storage
                      display_name: B1-B1-S1-BIN1
                      deprecated_at: null
                    created_at: '2026-01-15T10:00:00.000000Z'
                    updated_at: '2026-01-15T10:00:00.000000Z'
                  message: Preferred bins reordered.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: The provided ids do not match the preferred bins for this
                    product and warehouse.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: put-api-v2-product-warehouse-locations-reorder
  /api/v2/lpns:
    get:
      tags:
      - Warehouses
      summary: List LPNs
      description: 'Paginated pallets/totes (LPNs) with their bin and content count.


        Authentication: Requires Bearer token.

        Filters: filter[status] (open|closed), filter[warehouse_id], filter[warehouse_location_id],
        filter[search] (number or barcode). Sorts: id, number, status, created_at.
        Pagination: page, per_page (default 10).'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        number:
                          type: string
                        barcode:
                          type: string
                        warehouse_id:
                          type: integer
                        warehouse:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        warehouse_location_id:
                          type: integer
                        location:
                          type: object
                          properties:
                            id:
                              type: integer
                            code:
                              type: string
                            name:
                              type: string
                        status:
                          type: string
                        status_label:
                          type: string
                        notes:
                          type: string
                          nullable: true
                        contents_count:
                          type: integer
                        created_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 3
                    number: LPN-000003
                    barcode: PLT-123
                    warehouse_id: 1
                    warehouse:
                      id: 1
                      name: Main Warehouse
                    warehouse_location_id: 15
                    location:
                      id: 15
                      code: ST-01
                      name: Storage 1
                    status: open
                    status_label: Open
                    notes: null
                    contents_count: 1
                    created_at: '2026-07-10T09:00:00.000000Z'
                  current_page: 1
                  last_page: 1
                  per_page: 10
                  total: 1
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-v2-lpns
    post:
      tags:
      - Warehouses
      summary: Create LPN
      description: 'Create an open LPN (pallet/tote), optionally placed in a bin.


        Authentication: Requires Bearer token. Only on warehouses with locations enabled.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                warehouse_id:
                  type: integer
                warehouse_location_id:
                  type: integer
                barcode:
                  type: string
                notes:
                  type: string
              example:
                warehouse_id: 1
                warehouse_location_id: 15
                barcode: PLT-123
                notes: Pallet A
      parameters: []
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      number:
                        type: string
                      barcode:
                        type: string
                      warehouse_id:
                        type: integer
                      warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      warehouse_location_id:
                        type: integer
                      location:
                        type: object
                        properties:
                          id:
                            type: integer
                          code:
                            type: string
                          name:
                            type: string
                      status:
                        type: string
                      status_label:
                        type: string
                      notes:
                        type: string
                        nullable: true
                      contents_count:
                        type: integer
                      contents:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            product_id:
                              type: integer
                            sku:
                              type: string
                            name:
                              type: string
                            quantity:
                              type: integer
                      created_at:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 3
                    number: LPN-000003
                    barcode: PLT-123
                    warehouse_id: 1
                    warehouse:
                      id: 1
                      name: Main Warehouse
                    warehouse_location_id: 15
                    location:
                      id: 15
                      code: ST-01
                      name: Storage 1
                    status: open
                    status_label: Open
                    notes: null
                    contents_count: 1
                    contents:
                    - id: 8
                      product_id: 42
                      sku: WIDGET-1
                      name: Blue Widget
                      quantity: 20
                    created_at: '2026-07-10T09:00:00.000000Z'
                  message: LPN created.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-v2-lpns
  /api/v2/lpns/{warehouseLpn}:
    get:
      tags:
      - Warehouses
      summary: Get LPN
      description: 'A single LPN with its full content manifest.


        Authentication: Requires Bearer token.'
      parameters:
      - name: warehouseLpn
        in: path
        schema:
          type: string
        required: true
        description: The warehouse lpn ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      number:
                        type: string
                      barcode:
                        type: string
                      warehouse_id:
                        type: integer
                      warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      warehouse_location_id:
                        type: integer
                      location:
                        type: object
                        properties:
                          id:
                            type: integer
                          code:
                            type: string
                          name:
                            type: string
                      status:
                        type: string
                      status_label:
                        type: string
                      notes:
                        type: string
                        nullable: true
                      contents_count:
                        type: integer
                      contents:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            product_id:
                              type: integer
                            sku:
                              type: string
                            name:
                              type: string
                            quantity:
                              type: integer
                      created_at:
                        type: string
                example:
                  data:
                    id: 3
                    number: LPN-000003
                    barcode: PLT-123
                    warehouse_id: 1
                    warehouse:
                      id: 1
                      name: Main Warehouse
                    warehouse_location_id: 15
                    location:
                      id: 15
                      code: ST-01
                      name: Storage 1
                    status: open
                    status_label: Open
                    notes: null
                    contents_count: 1
                    contents:
                    - id: 8
                      product_id: 42
                      sku: WIDGET-1
                      name: Blue Widget
                      quantity: 20
                    created_at: '2026-07-10T09:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-v2-lpns-warehouselpn
  /api/v2/lpns/{warehouseLpn}/contents:
    post:
      tags:
      - Warehouses
      summary: Add Stock to LPN
      description: 'Nest stock onto an open LPN. The LPN''s bin must physically hold
        at least the resulting quantity of the product.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                product_id:
                  type: integer
                quantity:
                  type: integer
              example:
                product_id: 42
                quantity: 20
      parameters:
      - name: warehouseLpn
        in: path
        schema:
          type: string
        required: true
        description: The warehouse lpn ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      number:
                        type: string
                      barcode:
                        type: string
                      warehouse_id:
                        type: integer
                      warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      warehouse_location_id:
                        type: integer
                      location:
                        type: object
                        properties:
                          id:
                            type: integer
                          code:
                            type: string
                          name:
                            type: string
                      status:
                        type: string
                      status_label:
                        type: string
                      notes:
                        type: string
                        nullable: true
                      contents_count:
                        type: integer
                      contents:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            product_id:
                              type: integer
                            sku:
                              type: string
                            name:
                              type: string
                            quantity:
                              type: integer
                      created_at:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 3
                    number: LPN-000003
                    barcode: PLT-123
                    warehouse_id: 1
                    warehouse:
                      id: 1
                      name: Main Warehouse
                    warehouse_location_id: 15
                    location:
                      id: 15
                      code: ST-01
                      name: Storage 1
                    status: open
                    status_label: Open
                    notes: null
                    contents_count: 1
                    contents:
                    - id: 8
                      product_id: 42
                      sku: WIDGET-1
                      name: Blue Widget
                      quantity: 20
                    created_at: '2026-07-10T09:00:00.000000Z'
                  message: Stock added to the LPN.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: The LPN's bin holds 10 of this product but 20 would be on
                    the pallet.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-v2-lpns-warehouselpn-contents
  /api/v2/lpns/{warehouseLpn}/contents/bulk:
    post:
      tags:
      - Warehouses
      summary: Bulk Import Stock to LPN
      description: 'Nest many products onto an open LPN in one call. Each item is
        matched by SKU (or barcode) or product id, aggregated per product, and checked
        against the on-hand quantity in the LPN''s bin. Returns a per-row report (status:
        ok, insufficient, not_found, invalid) plus a summary. Set dry_run=true to
        validate without persisting; dry_run=false nests every valid product in a
        single transaction and returns the updated LPN. Items referencing the same
        product are combined.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                dry_run:
                  type: boolean
                items:
                  type: array
                  items:
                    type: object
                    properties:
                      sku:
                        type: string
                      quantity:
                        type: integer
              example:
                dry_run: false
                items:
                - sku: WIDGET-1
                  quantity: 20
                - sku: WIDGET-2
                  quantity: 5
                - product_id: 99
                  quantity: 12
      parameters:
      - name: warehouseLpn
        in: path
        schema:
          type: string
        required: true
        description: The warehouse lpn ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 Validate (dry_run)
                  value:
                    results:
                    - row: 1
                      input: WIDGET-1
                      quantity: 20
                      product_id: 42
                      sku: WIDGET-1
                      name: Blue Widget
                      status: ok
                      message: null
                    - row: 2
                      input: WIDGET-2
                      quantity: 5
                      product_id: 43
                      sku: WIDGET-2
                      name: Red Widget
                      status: insufficient
                      message: The bin holds 2 of this product — not enough to nest
                        5.
                    - row: 3
                      input: NOPE-1
                      quantity: 1
                      product_id: null
                      sku: null
                      name: null
                      status: not_found
                      message: No product matches this SKU or barcode.
                    summary:
                      ok: 1
                      not_found: 1
                      insufficient: 1
                      invalid: 0
                      units: 20
                    lpn: null
                    message: Validated import.
                example-1:
                  summary: 200 Imported
                  value:
                    results:
                    - row: 1
                      input: WIDGET-1
                      quantity: 20
                      product_id: 42
                      sku: WIDGET-1
                      name: Blue Widget
                      status: ok
                      message: null
                    summary:
                      ok: 1
                      not_found: 0
                      insufficient: 0
                      invalid: 0
                      units: 20
                    lpn:
                      id: 3
                      number: LPN-000003
                      barcode: PLT-123
                      warehouse_id: 1
                      warehouse:
                        id: 1
                        name: Main Warehouse
                      warehouse_location_id: 15
                      location:
                        id: 15
                        code: ST-01
                        name: Storage 1
                      status: open
                      status_label: Open
                      notes: null
                      contents_count: 1
                      contents:
                      - id: 8
                        product_id: 42
                        sku: WIDGET-1
                        name: Blue Widget
                        quantity: 20
                      created_at: '2026-07-10T09:00:00.000000Z'
                    message: 1 product(s) nested onto the LPN.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: Place the LPN in a bin before importing stock onto it.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-v2-lpns-warehouselpn-contents-bulk
  /api/v2/lpns/{warehouseLpn}/move:
    put:
      tags:
      - Warehouses
      summary: Move LPN
      description: 'Move the whole LPN to another bin — relocating every content line''s
        stock in one transfer.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                warehouse_location_id:
                  type: integer
              example:
                warehouse_location_id: 16
      parameters:
      - name: warehouseLpn
        in: path
        schema:
          type: string
        required: true
        description: The warehouse lpn ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      number:
                        type: string
                      barcode:
                        type: string
                      warehouse_id:
                        type: integer
                      warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      warehouse_location_id:
                        type: integer
                      location:
                        type: object
                        properties:
                          id:
                            type: integer
                          code:
                            type: string
                          name:
                            type: string
                      status:
                        type: string
                      status_label:
                        type: string
                      notes:
                        type: string
                        nullable: true
                      contents_count:
                        type: integer
                      contents:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            product_id:
                              type: integer
                            sku:
                              type: string
                            name:
                              type: string
                            quantity:
                              type: integer
                      created_at:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 3
                    number: LPN-000003
                    barcode: PLT-123
                    warehouse_id: 1
                    warehouse:
                      id: 1
                      name: Main Warehouse
                    warehouse_location_id: 16
                    location:
                      id: 16
                      code: ST-02
                      name: Storage 2
                    status: open
                    status_label: Open
                    notes: null
                    contents_count: 1
                    contents:
                    - id: 8
                      product_id: 42
                      sku: WIDGET-1
                      name: Blue Widget
                      quantity: 20
                    created_at: '2026-07-10T09:00:00.000000Z'
                  message: LPN moved.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-v2-lpns-warehouselpn-move
  /api/v2/lpns/{warehouseLpn}/close:
    put:
      tags:
      - Warehouses
      summary: Close LPN
      description: 'Close an LPN — it can no longer take stock or move.


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: warehouseLpn
        in: path
        schema:
          type: string
        required: true
        description: The warehouse lpn ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      number:
                        type: string
                      barcode:
                        type: string
                      warehouse_id:
                        type: integer
                      warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      warehouse_location_id:
                        type: integer
                      location:
                        type: object
                        properties:
                          id:
                            type: integer
                          code:
                            type: string
                          name:
                            type: string
                      status:
                        type: string
                      status_label:
                        type: string
                      notes:
                        type: string
                        nullable: true
                      contents_count:
                        type: integer
                      contents:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            product_id:
                              type: integer
                            sku:
                              type: string
                            name:
                              type: string
                            quantity:
                              type: integer
                      created_at:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 3
                    number: LPN-000003
                    barcode: PLT-123
                    warehouse_id: 1
                    warehouse:
                      id: 1
                      name: Main Warehouse
                    warehouse_location_id: 15
                    location:
                      id: 15
                      code: ST-01
                      name: Storage 1
                    status: closed
                    status_label: Closed
                    notes: null
                    contents_count: 1
                    contents:
                    - id: 8
                      product_id: 42
                      sku: WIDGET-1
                      name: Blue Widget
                      quantity: 20
                    created_at: '2026-07-10T09:00:00.000000Z'
                  message: LPN closed.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-v2-lpns-warehouselpn-close
  /api/v2/warehouse-locations:
    get:
      tags:
      - Warehouses
      summary: List Warehouse Locations
      description: 'Paginated warehouse locations (bins) with the cached per-location
        on-hand units (`on_hand`). Deprecated locations are hidden unless `include_deprecated`
        (top-level or inside `filter[]`) is truthy.


        Authentication: Requires Bearer token.

        Scope: warehouses (read/write).

        Requires the tenant to have warehouse locations enabled (`warehouse.locations`
        middleware).


        Location types: staging, primary_pick, reserve, storage, shipping, returns,
        quarantine, damaged.

        Available sorts: code (default), type, created_at (prefix with - for descending).'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        description: 'Page number (default: 1)'
        example: '1'
      - name: per_page
        in: query
        schema:
          type: integer
        description: 'Items per page (default: 10)'
        example: '10'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        warehouse_id:
                          type: integer
                        warehouse_name:
                          type: string
                        name:
                          type: string
                        code:
                          type: string
                        zone:
                          type: string
                        aisle:
                          type: string
                        bay:
                          type: string
                        shelf:
                          type: string
                        bin:
                          type: string
                        type:
                          type: string
                        type_label:
                          type: string
                        is_receivable:
                          type: boolean
                        is_pickable:
                          type: boolean
                        is_putaway_source:
                          type: boolean
                        is_putaway_destination:
                          type: boolean
                        barcode:
                          type: string
                        sort_order:
                          type: integer
                        is_default:
                          type: boolean
                        deprecated_at:
                          type: string
                          nullable: true
                        display_name:
                          type: string
                        on_hand:
                          type: integer
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - id: 12
                    warehouse_id: 1
                    warehouse_name: Main Warehouse
                    name: Aisle 1 Bay 2 Shelf 3 Bin 4
                    code: A1-B2-S3-BIN4
                    zone: A
                    aisle: '1'
                    bay: '2'
                    shelf: '3'
                    bin: '4'
                    type: storage
                    type_label: Storage
                    is_receivable: true
                    is_pickable: true
                    is_putaway_source: false
                    is_putaway_destination: true
                    barcode: LOC-A1-B2-S3-BIN4
                    sort_order: 100
                    is_default: false
                    deprecated_at: null
                    display_name: A1-B2-S3-BIN4 — Aisle 1 Bay 2 Shelf 3 Bin 4
                    on_hand: 42
                    created_at: '2026-01-15T10:00:00.000000Z'
                    updated_at: '2026-01-15T10:00:00.000000Z'
                  current_page: 1
                  last_page: 1
                  per_page: 10
                  total: 1
                  from: 1
                  to: 1
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-v2-warehouse-locations
    post:
      tags:
      - Warehouses
      summary: Create Warehouse Location
      description: "Create a single warehouse location (bin). Provide either an explicit\
        \ `code` or at least one of the segment fields (`zone`, `aisle`, `bay`, `shelf`,\
        \ `bin`) from which a code is derived.\n\nAuthentication: Requires Bearer\
        \ token.\nScope: warehouses (read/write).\n\nBody fields:\n- warehouse_id\
        \ (required, integer, exists) — parent warehouse\n- code (string max 64, required_without_all:zone,aisle,bay,shelf,bin)\n\
        - name (nullable, string max 255)\n- zone (nullable, string max 32)\n- aisle\
        \ / bay / shelf / bin (nullable, string max 255)\n- type (required, enum:\
        \ staging, primary_pick, reserve, storage, shipping, returns, quarantine,\
        \ damaged)\n- is_receivable (optional, boolean) — bin can receive stock on\
        \ inbound receipts\n- is_pickable (optional, boolean) — bin is eligible for\
        \ order picking\n- is_putaway_source (optional, boolean) — stock can be drawn\
        \ from this bin during put-away\n- is_putaway_destination (optional, boolean)\
        \ — stock can be put away into this bin\n  When a capability flag is omitted\
        \ it is seeded from the location `type` defaults; once set, receiving, picking\
        \ and put-away routing follow the flags, not the type.\n- barcode (nullable,\
        \ string max 64)\n- sort_order (nullable, integer min 0)\n- is_default (boolean)\n\
        \nReturns 201 with the created location; 422 if the tenant does not have locations\
        \ enabled or the code/barcode conflicts.\n\n**Requires permission:** `warehouses.manage_locations`"
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                warehouse_id:
                  type: integer
                code:
                  type: string
                name:
                  type: string
                zone:
                  type: string
                aisle:
                  type: string
                bay:
                  type: string
                shelf:
                  type: string
                bin:
                  type: string
                type:
                  type: string
                is_receivable:
                  type: boolean
                is_pickable:
                  type: boolean
                is_putaway_source:
                  type: boolean
                is_putaway_destination:
                  type: boolean
                barcode:
                  type: string
                sort_order:
                  type: integer
                is_default:
                  type: boolean
                is_sellable:
                  type: boolean
                capacity_qty:
                  type: integer
                abc_class:
                  type: string
              example:
                warehouse_id: 1
                code: A1-B2-S3-BIN4
                name: Aisle 1 Bay 2 Shelf 3 Bin 4
                zone: A
                aisle: '1'
                bay: '2'
                shelf: '3'
                bin: '4'
                type: storage
                is_receivable: true
                is_pickable: true
                is_putaway_source: false
                is_putaway_destination: true
                barcode: LOC-A1-B2-S3-BIN4
                sort_order: 100
                is_default: false
                is_sellable: true
                capacity_qty: 100
                abc_class: A
      parameters: []
      responses:
        '201':
          description: Created
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      warehouse_id:
                        type: integer
                      warehouse_name:
                        type: string
                      name:
                        type: string
                      code:
                        type: string
                      zone:
                        type: string
                      aisle:
                        type: string
                      bay:
                        type: string
                      shelf:
                        type: string
                      bin:
                        type: string
                      type:
                        type: string
                      type_label:
                        type: string
                      is_receivable:
                        type: boolean
                      is_pickable:
                        type: boolean
                      is_putaway_source:
                        type: boolean
                      is_putaway_destination:
                        type: boolean
                      barcode:
                        type: string
                      sort_order:
                        type: integer
                      is_default:
                        type: boolean
                      deprecated_at:
                        type: string
                        nullable: true
                      display_name:
                        type: string
                      on_hand:
                        type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 12
                    warehouse_id: 1
                    warehouse_name: Main Warehouse
                    name: Aisle 1 Bay 2 Shelf 3 Bin 4
                    code: A1-B2-S3-BIN4
                    zone: A
                    aisle: '1'
                    bay: '2'
                    shelf: '3'
                    bin: '4'
                    type: storage
                    type_label: Storage
                    is_receivable: true
                    is_pickable: true
                    is_putaway_source: false
                    is_putaway_destination: true
                    barcode: LOC-A1-B2-S3-BIN4
                    sort_order: 100
                    is_default: false
                    deprecated_at: null
                    display_name: A1-B2-S3-BIN4 — Aisle 1 Bay 2 Shelf 3 Bin 4
                    on_hand: 42
                    created_at: '2026-01-15T10:00:00.000000Z'
                    updated_at: '2026-01-15T10:00:00.000000Z'
                  message: Location created successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-v2-warehouse-locations
  /api/v2/warehouse-locations/bulk-generate:
    post:
      tags:
      - Warehouses
      summary: Bulk Generate Warehouse Locations
      description: "Generate a range of locations from segment patterns. With `preview:\
        \ true` the response returns `{codes_sample, total, conflicts}` without persisting;\
        \ otherwise the non-conflicting codes are inserted and the response returns\
        \ `{created, skipped_codes}`.\n\nAuthentication: Requires Bearer token.\n\
        Scope: warehouses (read/write).\n\nBody fields:\n- warehouse_id (required,\
        \ integer, exists)\n- type (required, enum: staging, primary_pick, reserve,\
        \ storage, shipping, returns, quarantine, damaged)\n- Generated bins seed\
        \ their capability flags (is_receivable, is_pickable, is_putaway_source, is_putaway_destination)\
        \ from the chosen `type`; adjust per bin afterwards via Update.\n- zone (nullable,\
        \ string max 32)\n- segments (required array, 1-6 items). Each segment:\n\
        \    - kind (required, one of: literal | letters | numbers)\n    - value (required\
        \ when kind=literal, string max 32)\n    - from / to (required unless kind=literal)\
        \ — range bounds\n    - pad (boolean) — zero/left pad range values to equal\
        \ width\n- preview (boolean) — dry-run without persisting\n\n**Requires permission:**\
        \ `warehouses.manage_locations`"
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                warehouse_id:
                  type: integer
                type:
                  type: string
                zone:
                  type: string
                segments:
                  type: array
                  items:
                    type: object
                    properties:
                      kind:
                        type: string
                      value:
                        type: string
                preview:
                  type: boolean
              example:
                warehouse_id: 1
                type: storage
                zone: A
                segments:
                - kind: literal
                  value: A
                - kind: numbers
                  from: 1
                  to: 10
                  pad: true
                - kind: letters
                  from: A
                  to: C
                preview: true
      parameters: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 Preview
                  value:
                    data:
                      codes_sample:
                      - A-01-A
                      - A-01-B
                      - A-01-C
                      - A-02-A
                      total: 30
                      conflicts:
                      - A-01-A
                example-1:
                  summary: 200 Generated
                  value:
                    data:
                      created: 29
                      skipped_codes:
                      - A-01-A
                    message: Generated 29 location(s), skipped 1 existing code(s).
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-v2-warehouse-locations-bulk-generate
  /api/v2/warehouse-locations/import:
    post:
      tags:
      - Warehouses
      summary: Import Warehouse Locations
      description: 'CSV import of locations, upserting by the (warehouse, code) natural
        key. Small files run synchronously and return `{created, updated, skipped}`;
        large files are queued and return `{queued: true, tracked_job_log_id}` for
        the job list.


        Authentication: Requires Bearer token.

        Scope: warehouses (read/write).


        Body (multipart/form-data):

        - warehouse_id (required, integer, exists)

        - file (required, CSV/TXT upload, max 10 MB)


        **Requires permission:** `warehouses.manage_locations`'
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                warehouse_id:
                  type: integer
                  description: Required. Target warehouse ID.
                  example: '1'
                file:
                  type: string
                  description: Required. CSV/TXT file (max 10 MB). Upserts by (warehouse,
                    code).
                  format: binary
      parameters: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 Imported
                  value:
                    data:
                      queued: false
                      created: 12
                      updated: 3
                      skipped: []
                    message: Imported 12 new, updated 3.
                example-1:
                  summary: 200 Queued
                  value:
                    data:
                      queued: true
                      tracked_job_log_id: 8842
                    message: Import started — track progress in the job tray.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-v2-warehouse-locations-import
  /api/v2/warehouse-locations/labels:
    post:
      tags:
      - Warehouses
      summary: Generate Location Labels
      description: 'Generate a printable labels PDF (Code-128 barcode + code + type)
        for the selected locations. Returns a PDF/HTML label sheet as a binary download,
        NOT JSON.


        Authentication: Requires Bearer token.

        Scope: warehouses (read/write).


        Body fields:

        - ids (required array, 1-500 items) — warehouse_location IDs to print'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 12
                - 13
                - 14
      parameters: []
      responses:
        '200':
          description: OK
          content:
            text/plain:
              schema:
                type: string
                example: '[Binary PDF label sheet download]'
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-v2-warehouse-locations-labels
  /api/v2/warehouse-locations/{warehouseLocation}:
    get:
      tags:
      - Warehouses
      summary: Get Warehouse Location
      description: 'Single warehouse location with its warehouse and the cached on-hand
        summary (`on_hand`).


        Authentication: Requires Bearer token.

        Scope: warehouses (read/write).'
      parameters:
      - name: warehouseLocation
        in: path
        schema:
          type: integer
        required: true
        description: Warehouse location ID
        example: '12'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      warehouse_id:
                        type: integer
                      warehouse_name:
                        type: string
                      name:
                        type: string
                      code:
                        type: string
                      zone:
                        type: string
                      aisle:
                        type: string
                      bay:
                        type: string
                      shelf:
                        type: string
                      bin:
                        type: string
                      type:
                        type: string
                      type_label:
                        type: string
                      is_receivable:
                        type: boolean
                      is_pickable:
                        type: boolean
                      is_putaway_source:
                        type: boolean
                      is_putaway_destination:
                        type: boolean
                      barcode:
                        type: string
                      sort_order:
                        type: integer
                      is_default:
                        type: boolean
                      deprecated_at:
                        type: string
                        nullable: true
                      display_name:
                        type: string
                      on_hand:
                        type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 12
                    warehouse_id: 1
                    warehouse_name: Main Warehouse
                    name: Aisle 1 Bay 2 Shelf 3 Bin 4
                    code: A1-B2-S3-BIN4
                    zone: A
                    aisle: '1'
                    bay: '2'
                    shelf: '3'
                    bin: '4'
                    type: storage
                    type_label: Storage
                    is_receivable: true
                    is_pickable: true
                    is_putaway_source: false
                    is_putaway_destination: true
                    barcode: LOC-A1-B2-S3-BIN4
                    sort_order: 100
                    is_default: false
                    deprecated_at: null
                    display_name: A1-B2-S3-BIN4 — Aisle 1 Bay 2 Shelf 3 Bin 4
                    on_hand: 42
                    created_at: '2026-01-15T10:00:00.000000Z'
                    updated_at: '2026-01-15T10:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-v2-warehouse-locations-warehouselocation
    put:
      tags:
      - Warehouses
      summary: Update Warehouse Location
      description: "Update a warehouse location. All fields are optional (`sometimes`);\
        \ only provided fields are changed.\n\nAuthentication: Requires Bearer token.\n\
        Scope: warehouses (read/write).\n\nBody fields (all optional):\n- code (nullable,\
        \ string max 64)\n- name (nullable, string max 255)\n- zone (nullable, string\
        \ max 32)\n- aisle / bay / shelf / bin (nullable, string max 255)\n- type\
        \ (enum: staging, primary_pick, reserve, storage, shipping, returns, quarantine,\
        \ damaged)\n- is_receivable (optional, boolean) — bin can receive stock on\
        \ inbound receipts\n- is_pickable (optional, boolean) — bin is eligible for\
        \ order picking\n- is_putaway_source (optional, boolean) — stock can be drawn\
        \ from this bin during put-away\n- is_putaway_destination (optional, boolean)\
        \ — stock can be put away into this bin\n  When a capability flag is omitted\
        \ it is seeded from the location `type` defaults; once set, receiving, picking\
        \ and put-away routing follow the flags, not the type.\n- barcode (nullable,\
        \ string max 64)\n- sort_order (nullable, integer min 0)\n- is_default (boolean)\n\
        \n**Requires permission:** `warehouses.manage_locations`"
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                sort_order:
                  type: integer
                is_pickable:
                  type: boolean
                is_default:
                  type: boolean
                is_sellable:
                  type: boolean
                capacity_qty:
                  type: integer
                abc_class:
                  type: string
              example:
                name: Aisle 1 Bay 2 Shelf 3 Bin 4 (renamed)
                sort_order: 120
                is_pickable: false
                is_default: true
                is_sellable: true
                capacity_qty: 100
                abc_class: A
      parameters:
      - name: warehouseLocation
        in: path
        schema:
          type: integer
        required: true
        description: Warehouse location ID
        example: '12'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      warehouse_id:
                        type: integer
                      warehouse_name:
                        type: string
                      name:
                        type: string
                      code:
                        type: string
                      zone:
                        type: string
                      aisle:
                        type: string
                      bay:
                        type: string
                      shelf:
                        type: string
                      bin:
                        type: string
                      type:
                        type: string
                      type_label:
                        type: string
                      is_receivable:
                        type: boolean
                      is_pickable:
                        type: boolean
                      is_putaway_source:
                        type: boolean
                      is_putaway_destination:
                        type: boolean
                      barcode:
                        type: string
                      sort_order:
                        type: integer
                      is_default:
                        type: boolean
                      deprecated_at:
                        type: string
                        nullable: true
                      display_name:
                        type: string
                      on_hand:
                        type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 12
                    warehouse_id: 1
                    warehouse_name: Main Warehouse
                    name: Aisle 1 Bay 2 Shelf 3 Bin 4
                    code: A1-B2-S3-BIN4
                    zone: A
                    aisle: '1'
                    bay: '2'
                    shelf: '3'
                    bin: '4'
                    type: storage
                    type_label: Storage
                    is_receivable: true
                    is_pickable: true
                    is_putaway_source: false
                    is_putaway_destination: true
                    barcode: LOC-A1-B2-S3-BIN4
                    sort_order: 100
                    is_default: false
                    deprecated_at: null
                    display_name: A1-B2-S3-BIN4 — Aisle 1 Bay 2 Shelf 3 Bin 4
                    on_hand: 42
                    created_at: '2026-01-15T10:00:00.000000Z'
                    updated_at: '2026-01-15T10:00:00.000000Z'
                  message: Location updated successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-v2-warehouse-locations-warehouselocation
    delete:
      tags:
      - Warehouses
      summary: Delete Warehouse Location
      description: 'Hard delete a warehouse location. Only allowed when the location
        has never been referenced by an inventory movement; otherwise a 422 is returned
        suggesting deprecation instead.


        Authentication: Requires Bearer token.

        Scope: warehouses (read/write).


        **Requires permission:** `warehouses.manage_locations`'
      parameters:
      - name: warehouseLocation
        in: path
        schema:
          type: integer
        required: true
        description: Warehouse location ID
        example: '12'
      responses:
        '204':
          description: No Content
          content:
            text/plain:
              schema:
                type: string
                example: ''
        '422':
          description: Unprocessable Entity
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: This location has inventory history and cannot be deleted.
                    Deprecate it instead.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-v2-warehouse-locations-warehouselocation
  /api/v2/warehouse-locations/{warehouseLocation}/deprecate:
    post:
      tags:
      - Warehouses
      summary: Deprecate Warehouse Location
      description: 'Deprecate (soft-retire) a location so it is hidden from pickers
        and datatables but retains its history. Returns 422 if it is the last active
        storage location in the warehouse.


        Authentication: Requires Bearer token.

        Scope: warehouses (read/write).


        **Requires permission:** `warehouses.manage_locations`'
      requestBody:
        content: {}
      parameters:
      - name: warehouseLocation
        in: path
        schema:
          type: integer
        required: true
        description: Warehouse location ID
        example: '12'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      warehouse_id:
                        type: integer
                      warehouse_name:
                        type: string
                      name:
                        type: string
                      code:
                        type: string
                      zone:
                        type: string
                      aisle:
                        type: string
                      bay:
                        type: string
                      shelf:
                        type: string
                      bin:
                        type: string
                      type:
                        type: string
                      type_label:
                        type: string
                      barcode:
                        type: string
                      sort_order:
                        type: integer
                      is_default:
                        type: boolean
                      deprecated_at:
                        type: string
                      display_name:
                        type: string
                      on_hand:
                        type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 12
                    warehouse_id: 1
                    warehouse_name: Main Warehouse
                    name: Aisle 1 Bay 2 Shelf 3 Bin 4
                    code: A1-B2-S3-BIN4
                    zone: A
                    aisle: '1'
                    bay: '2'
                    shelf: '3'
                    bin: '4'
                    type: storage
                    type_label: Storage
                    barcode: LOC-A1-B2-S3-BIN4
                    sort_order: 100
                    is_default: false
                    deprecated_at: '2026-01-20T12:00:00.000000Z'
                    display_name: A1-B2-S3-BIN4 — Aisle 1 Bay 2 Shelf 3 Bin 4
                    on_hand: 42
                    created_at: '2026-01-15T10:00:00.000000Z'
                    updated_at: '2026-01-15T10:00:00.000000Z'
                  message: Location deprecated.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-v2-warehouse-locations-warehouselocation-deprecate
  /api/v2/warehouse-locations/{warehouseLocation}/restore:
    post:
      tags:
      - Warehouses
      summary: Restore Warehouse Location
      description: 'Restore a previously deprecated location (clears `deprecated_at`).


        Authentication: Requires Bearer token.

        Scope: warehouses (read/write).


        **Requires permission:** `warehouses.manage_locations`'
      requestBody:
        content: {}
      parameters:
      - name: warehouseLocation
        in: path
        schema:
          type: integer
        required: true
        description: Warehouse location ID
        example: '12'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      warehouse_id:
                        type: integer
                      warehouse_name:
                        type: string
                      name:
                        type: string
                      code:
                        type: string
                      zone:
                        type: string
                      aisle:
                        type: string
                      bay:
                        type: string
                      shelf:
                        type: string
                      bin:
                        type: string
                      type:
                        type: string
                      type_label:
                        type: string
                      barcode:
                        type: string
                      sort_order:
                        type: integer
                      is_default:
                        type: boolean
                      deprecated_at:
                        type: string
                        nullable: true
                      display_name:
                        type: string
                      on_hand:
                        type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 12
                    warehouse_id: 1
                    warehouse_name: Main Warehouse
                    name: Aisle 1 Bay 2 Shelf 3 Bin 4
                    code: A1-B2-S3-BIN4
                    zone: A
                    aisle: '1'
                    bay: '2'
                    shelf: '3'
                    bin: '4'
                    type: storage
                    type_label: Storage
                    barcode: LOC-A1-B2-S3-BIN4
                    sort_order: 100
                    is_default: false
                    deprecated_at: null
                    display_name: A1-B2-S3-BIN4 — Aisle 1 Bay 2 Shelf 3 Bin 4
                    on_hand: 42
                    created_at: '2026-01-15T10:00:00.000000Z'
                    updated_at: '2026-01-15T10:00:00.000000Z'
                  message: Location restored.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-v2-warehouse-locations-warehouselocation-restore
  /api/lookup/warehouse-locations:
    get:
      tags:
      - Warehouses
      summary: Lookup Warehouse Locations
      description: 'Decorated location options for select/autocomplete components.
        Returns active (non-deprecated) locations of a warehouse in pick-path order
        (sort_order nulls-last, then code). Returns an empty list when the warehouse
        does not have locations enabled.


        When `product_id` is supplied each option is decorated with the live `available_quantity`
        from the location-quantity cache and a `display_text` ("CODE (Type) — N units").


        Authentication: Requires Bearer token.


        Query params:

        - warehouse_id (required, integer, exists)

        - capability (optional: receivable | pickable | put-away-to | put-away-from)
        — filters types via the capability matrix

        - type / type[] (optional, comma-separated or array) — explicit type filter,
        intersected with capability

        - search (optional, string max 255) — matches code, name or barcode

        - product_id (optional, integer, exists) — decorate options with available_quantity
        + display_text

        - limit (optional, integer 1-500, default 50)'
      parameters:
      - name: warehouse_id
        in: query
        schema:
          type: integer
        description: Required. Warehouse to list locations for.
        example: '1'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        code:
                          type: string
                        name:
                          type: string
                        type:
                          type: string
                        type_label:
                          type: string
                        display_name:
                          type: string
                        barcode:
                          type: string
                        is_default:
                          type: boolean
                        available_quantity:
                          type: integer
                        display_text:
                          type: string
                example:
                  data:
                  - id: 12
                    code: A1-B2-S3-BIN4
                    name: Aisle 1 Bay 2 Shelf 3 Bin 4
                    type: storage
                    type_label: Storage
                    display_name: A1-B2-S3-BIN4 — Aisle 1 Bay 2 Shelf 3 Bin 4
                    barcode: LOC-A1-B2-S3-BIN4
                    is_default: false
                    available_quantity: 42
                    display_text: A1-B2-S3-BIN4 (Storage) — 42 units
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-lookup-warehouse-locations
  /api/v2/warehouse-locations/slotting-suggestions:
    get:
      tags:
      - Warehouses
      summary: Get Slotting Suggestions
      description: 'Velocity-aware slotting suggestions for a warehouse: stock whose
        bin doesn''t match its ABC sales-velocity class, or that overfills a bin''s
        capacity. Read-only — proposes moves, never makes them.


        Authentication: Requires Bearer token.'
      parameters:
      - name: warehouse_id
        in: query
        schema:
          type: integer
        description: Warehouse to analyse (required).
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        product_id:
                          type: integer
                        sku:
                          type: string
                        product_name:
                          type: string
                        abc_classification:
                          type: string
                        warehouse_location_id:
                          type: integer
                        bin_code:
                          type: string
                        bin_type:
                          type: string
                        quantity:
                          type: integer
                        kind:
                          type: string
                        severity:
                          type: string
                        message:
                          type: string
                example:
                  data:
                  - product_id: 42
                    sku: WIDGET-1
                    product_name: Blue Widget
                    abc_classification: A
                    warehouse_location_id: 15
                    bin_code: ST-01
                    bin_type: storage
                    quantity: 80
                    kind: promote_to_pick_face
                    severity: info
                    message: Fast mover (class A) is not on a Primary Pick face —
                      move it forward to speed picking.
                  - product_id: 57
                    sku: SLOW-9
                    product_name: Slow Mover
                    abc_classification: C
                    warehouse_location_id: 9
                    bin_code: PP-02
                    bin_type: primary_pick
                    quantity: 4
                    kind: demote_from_pick_face
                    severity: info
                    message: Slow mover (class C) is on a Primary Pick face — free
                      the face for a faster mover.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-v2-warehouse-locations-slotting-suggestions
  /api/stock-takes/list:
    get:
      tags:
      - Stock Takes
      summary: List Stock Takes
      description: 'Get paginated stock takes with filtering, sorting and search.
        Uses Spatie QueryBuilder + GroupedFilterSupport.


        :::info[Required scope: `inventory:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Filter columns available: id, status, mode, warehouse (ID), is_initial_count,
        variance_direction, notes, date_count, created_at, updated_at, value_change.


        Archived filter: none=non-archived only (default), only=archived only, all=all
        records.


        Allowed sorts: id, date_count, status, value_change, variance_direction, created_at,
        updated_at. Default sort: -id.


        **Requires permission:** `inventory.count`'
      parameters:
      - name: filter[status]
        in: query
        schema:
          type: string
        description: 'Optional. Filter by status: draft, open, closed.'
        example: open
      - name: filter[mode]
        in: query
        schema:
          type: string
        description: 'Optional. Filter by mode: full_count, adjustment.'
        example: full_count
      - name: filter[warehouse]
        in: query
        schema:
          type: integer
        description: Optional. Filter by warehouse ID.
        example: '1'
      - name: filter[archived]
        in: query
        schema:
          type: string
        description: 'Optional. archived filter: none (default, non-archived only),
          only (archived only), all (all records).'
        example: none
      - name: filter[variance_direction]
        in: query
        schema:
          type: string
        description: 'Optional. Filter by variance direction: positive, negative,
          neutral.'
        example: positive
      - name: filter[is_initial_count]
        in: query
        schema:
          type: string
        description: Optional. Filter by initial count (1 or 0).
      - name: filter[date_count]
        in: query
        schema:
          type: string
        description: Optional. Filter by count date.
      - name: filter[value_change]
        in: query
        schema:
          type: string
        description: Optional. Filter by value change amount.
      - name: filter[notes]
        in: query
        schema:
          type: string
        description: Optional. Filter by notes (partial match).
      - name: filter[id]
        in: query
        schema:
          type: string
        description: Optional. Filter by ID.
      - name: search
        in: query
        schema:
          type: string
        description: Optional. Search by ID, notes, or warehouse name.
      - name: sort
        in: query
        schema:
          type: string
        description: 'Optional. Sort field (prefix - for descending). Allowed: id,
          date_count, status, value_change, variance_direction, created_at, updated_at.'
        example: -id
      - name: per_page
        in: query
        schema:
          type: integer
        description: Optional. Items per page (default 10).
        example: '10'
      - name: page
        in: query
        schema:
          type: integer
        description: Optional. Page number.
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        date_count:
                          type: string
                        is_initial_count:
                          type: boolean
                        condition:
                          type: string
                          nullable: true
                        warehouse:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            type:
                              type: string
                            country_code:
                              type: string
                        mode:
                          type: string
                        status:
                          type: string
                        value_change:
                          type: string
                          nullable: true
                        variance_direction:
                          type: string
                          nullable: true
                        notes:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                        archived_at:
                          type: string
                          nullable: true
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 42
                    date_count: '2024-10-10T00:00:00+00:00'
                    is_initial_count: false
                    condition: null
                    warehouse:
                      id: 2
                      name: Main Warehouse
                      type: standard
                      country_code: US
                    mode: full_count
                    status: open
                    value_change: null
                    variance_direction: null
                    notes: Q4 annual count
                    created_at: '2024-10-08T09:00:00+00:00'
                    updated_at: '2024-10-10T14:00:00+00:00'
                    archived_at: null
                  current_page: 1
                  last_page: 3
                  per_page: 10
                  total: 28
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: inventory:read
      operationId: get-api-stock-takes-list
    post:
      tags:
      - Stock Takes
      summary: Search Stock Takes
      description: 'Returns the same paginated list of stock takes as the GET version
        of this endpoint, but accepts filters as a JSON request body instead of the
        query string. Use this POST variant when the filter set is too large or too
        complex to fit in a URL.


        :::info[Required scope: `inventory:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Provide advanced filters under `filter_groups`, a tree of conditions combined
        with a `conjunction` of `and` or `or`. Each condition names a `column`, an
        `operator`, and a `value`. A free-text `search` term matches against the stock
        take id, notes, and warehouse name.


        Text columns (`status`, `mode`, `variance_direction`, `notes`, `warehouse`)
        accept: is, is_not, contains, does_not_contain, starts_with, ends_with, is_empty,
        is_not_empty, is_one_of, is_not_one_of.

        Numeric, boolean and date columns (`id`, `value_change`, `is_initial_count`,
        `date_count`, `created_at`, `updated_at`, `archived`) accept: is, is_not,
        greater_than, greater_than_or_equal, less_than, less_than_or_equal, between,
        is_empty, is_not_empty.


        Sortable columns (via `sort`, prefix with `-` for descending): id, date_count,
        status, value_change, variance_direction, created_at, updated_at. Results
        default to `-id`.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                per_page:
                  type: integer
                page:
                  type: integer
                sort:
                  type: string
                search:
                  type: string
                filter_groups:
                  type: object
                  properties:
                    conjunction:
                      type: string
                    children:
                      type: array
                      items:
                        type: object
                        properties:
                          type:
                            type: string
                          condition:
                            type: object
                            properties:
                              column:
                                type: string
                              operator:
                                type: string
                              value:
                                type: string
              example:
                per_page: 25
                page: 1
                sort: -date_count
                search: ''
                filter_groups:
                  conjunction: and
                  children:
                  - type: condition
                    condition:
                      column: status
                      operator: is
                      value: completed
                  - type: condition
                    condition:
                      column: variance_direction
                      operator: is
                      value: negative
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        date_count:
                          type: string
                        is_initial_count:
                          type: boolean
                        condition:
                          type: string
                        warehouse:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            type:
                              type: string
                            country_code:
                              type: string
                        mode:
                          type: string
                        status:
                          type: string
                        value_change:
                          type: number
                        variance_direction:
                          type: string
                        notes:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                        archived_at:
                          type: string
                          nullable: true
                  current_page:
                    type: integer
                  per_page:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                  last_page:
                    type: integer
                  total:
                    type: integer
                  next_page_url:
                    type: string
                  prev_page_url:
                    type: string
                    nullable: true
                example:
                  data:
                  - id: 812
                    date_count: '2026-06-28'
                    is_initial_count: false
                    condition: new
                    warehouse:
                      id: 2
                      name: Main Warehouse
                      type: standard
                      country_code: US
                    mode: full
                    status: completed
                    value_change: -184.5
                    variance_direction: negative
                    notes: Quarterly cycle count
                    created_at: '2026-06-28T09:12:00.000000Z'
                    updated_at: '2026-06-28T15:41:00.000000Z'
                    archived_at: null
                  current_page: 1
                  per_page: 25
                  from: 1
                  to: 1
                  last_page: 4
                  total: 92
                  next_page_url: https://api.example.com/api/stock-takes/list?page=2
                  prev_page_url: null
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: inventory:write
      operationId: post-api-stock-takes-list
  /api/stock-takes/{stock_take}:
    get:
      tags:
      - Stock Takes
      summary: Get Stock Take
      description: 'Get a single stock take with full details including items, warehouse,
        parent and child stock takes.


        :::info[Required scope: `inventory:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Loads: warehouse, stockTakeItems (with inventoryMovements.fifoLayer for closed
        takes), parentStockTake, childStockTakes.


        Response includes `deletable` (boolean) and `delete_blocked_reasons` (string[]):
        a draft/open stock take is always deletable; a closed stock take is deletable
        only when none of its FIFO cost layers have been consumed (otherwise `deletable`
        is false and `delete_blocked_reasons` lists the blocking stock take items).


        The stock take exposes `is_blind`. For a blind count, items that have not
        yet been counted return null `snapshot_inventory` / `snapshot_available` /
        `snapshot_reserved` / `snapshot_committed_to_fulfillment` until they are counted.
        Each item also exposes its `variance_reason` (root-cause code, or null).'
      parameters:
      - name: stock_take
        in: path
        schema:
          type: integer
        required: true
        description: Stock take ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      date_count:
                        type: string
                      is_initial_count:
                        type: boolean
                      is_blind:
                        type: boolean
                      condition:
                        type: string
                        nullable: true
                      warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          type:
                            type: string
                          country_code:
                            type: string
                      mode:
                        type: string
                      status:
                        type: string
                      deletable:
                        type: boolean
                      delete_blocked_reasons:
                        type: array
                      value_change:
                        type: string
                        nullable: true
                      variance_direction:
                        type: string
                        nullable: true
                      notes:
                        type: string
                      parent_stock_take:
                        type: string
                        nullable: true
                      child_stock_takes:
                        type: array
                      items:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            item_product_id:
                              type: integer
                            item_sku:
                              type: string
                            item_name:
                              type: string
                            warehouse_id:
                              type: integer
                            snapshot_inventory:
                              type: integer
                            qty_counted:
                              type: integer
                            variance_reason:
                              type: string
                            unit_cost:
                              type: number
                            is_lot_tracked:
                              type: boolean
                            lot_tracking_method:
                              type: string
                            shelf_life_days:
                              type: integer
                            near_expiry_threshold_days:
                              type: integer
                            min_remaining_shelf_life_days:
                              type: integer
                            lot_allocation:
                              type: array
                              items:
                                type: object
                                properties:
                                  fifo_layer_id:
                                    type: integer
                                  quantity:
                                    type: integer
                            lots:
                              type: array
                              items:
                                type: object
                                properties:
                                  fifo_layer_id:
                                    type: integer
                                  batch_number:
                                    type: string
                                  expiry_date:
                                    type: string
                                  manufacture_date:
                                    type: string
                                  lot_notes:
                                    type: string
                                    nullable: true
                                  quantity:
                                    type: integer
                      during_count_movement_count:
                        type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                example:
                  data:
                    id: 42
                    date_count: '2024-10-10T00:00:00+00:00'
                    is_initial_count: false
                    is_blind: false
                    condition: null
                    warehouse:
                      id: 2
                      name: Main Warehouse
                      type: standard
                      country_code: US
                    mode: full_count
                    status: open
                    deletable: true
                    delete_blocked_reasons: []
                    value_change: null
                    variance_direction: null
                    notes: Q4 annual count
                    parent_stock_take: null
                    child_stock_takes: []
                    items:
                    - id: 101
                      item_product_id: 55
                      item_sku: PROD-55
                      item_name: Widget
                      warehouse_id: 2
                      snapshot_inventory: 100
                      qty_counted: 98
                      variance_reason: shrinkage
                      unit_cost: 12.5
                      is_lot_tracked: true
                      lot_tracking_method: fefo
                      shelf_life_days: 365
                      near_expiry_threshold_days: 30
                      min_remaining_shelf_life_days: 90
                      lot_allocation:
                      - fifo_layer_id: 7101
                        quantity: 2
                      lots:
                      - fifo_layer_id: 7101
                        batch_number: LOT-2026-0042
                        expiry_date: '2026-07-04'
                        manufacture_date: '2026-01-04'
                        lot_notes: null
                        quantity: 50
                    during_count_movement_count: 3
                    created_at: '2024-10-08T09:00:00+00:00'
                    updated_at: '2024-10-10T14:00:00+00:00'
                    archived_at: null
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No query results for model [App\Models\StockTake] 999
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: inventory:read
      operationId: get-api-stock-takes-stock-take
    put:
      tags:
      - Stock Takes
      summary: Update Stock Take
      description: 'Update a stock take and its line items. Handles adding, updating,
        and removing items.


        :::info[Required scope: `inventory:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        items: each item accepts product_id (required, must exist), qty_counted (numeric,
        min 0), unit_cost (optional numeric, min 0 — an explicit 0 is valid and preserved),
        to_delete (boolean, removes the line).


        items[].lots (array, optional): lot/batch rows for newly found (POSITIVE variance)
        stock on a lot-tracked product — each row becomes its own FIFO layer. For
        lot-tracked products every supplied lot must carry batch_number and expiry_date.
        Fields: batch_number, expiry_date, manufacture_date, quantity, lot_notes.


        items[].lot_allocation (array, optional): per-item FEFO override for a NEGATIVE
        variance (a consume — counted qty lower than the system snapshot) on a lot-tracked
        product. When supplied, the named FIFO layers are drawn down at finalize instead
        of automatic FEFO/FIFO; when omitted the consume falls back to automatic FEFO
        exactly as before. Each row is `{ fifo_layer_id (integer, must exist in fifo_layers),
        quantity (numeric, > 0) }`, and the allocation quantities must sum to abs(variance)
        (the snapshot − counted shortfall). The tenant setting `inventory.lot_override_policy`
        (off | warn | enforce) governs the override — under enforce an allocation
        selecting expired or non-FEFO (out-of-order) layers is rejected.


        date_count (date, optional): re-dating a finalized (closed) stock take moves
        its initial positive inventory movement and FIFO cost-layer date; on the next
        accounting sync this also re-dates the journal entry (TxnDate). Initial counts
        cannot be re-dated.


        reallocate_usages (boolean, optional): when true AND the date changed, dispatches
        a tracked FIFO reallocation that replays historical consumption against the
        re-ordered layers so each past usage consumes the correct layers in FIFO order,
        recomputes COGS, and propagates it to documents and accounting. When dispatched,
        the response includes `reallocation_tracked_job_id` to follow via the tracked
        job log endpoints. Preview the impact first via the reallocation-preview endpoint.


        Returns 400 if: the stock take is closed and the request attempts to change
        quantities; an adjustment-mode item cannot be modified; the new (or current)
        date_count falls on or before the accounting lock date; or the reallocation
        would change COGS on a consumption dated inside a locked accounting period.


        Response includes `deletable` (boolean) and `delete_blocked_reasons` (string[]).


        **Requires permission:** `inventory.count`


        Each item may carry `variance_reason` — a root-cause code for the count variance.
        One of: receiving_error, picking_error, damage, mislabel, shrinkage, unknown.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                notes:
                  type: string
                date_count:
                  type: string
                reallocate_usages:
                  type: boolean
                items:
                  type: array
                  items:
                    type: object
                    properties:
                      product_id:
                        type: integer
                      qty_counted:
                        type: integer
                      snapshot_inventory:
                        type: integer
                      unit_cost:
                        type: number
                      lots:
                        type: array
                        items:
                          type: object
                          properties:
                            batch_number:
                              type: string
                            manufacture_date:
                              type: string
                            expiry_date:
                              type: string
                            quantity:
                              type: integer
                            lot_notes:
                              type: string
              example:
                notes: Updated notes for Q4 count
                date_count: '2024-10-11'
                reallocate_usages: true
                items:
                - product_id: 55
                  qty_counted: 99
                  snapshot_inventory: 100
                  unit_cost: 12.5
                  lots:
                  - batch_number: LOT-2026-0042
                    manufacture_date: '2026-01-04'
                    expiry_date: '2026-07-04'
                    quantity: 98
                    lot_notes: Newly found lot
                - product_id: 56
                  qty_counted: 25
                  snapshot_inventory: 25
                - product_id: 57
                  qty_counted: 40
                  snapshot_inventory: 45
                  lot_allocation:
                  - fifo_layer_id: 7101
                    quantity: 3
                  - fifo_layer_id: 7102
                    quantity: 2
                  variance_reason: damage
      parameters:
      - name: stock_take
        in: path
        schema:
          type: integer
        required: true
        description: Stock take ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 Success
                  value:
                    data:
                      id: 42
                      notes: Updated notes for Q4 count
                      status: draft
                      deletable: true
                      delete_blocked_reasons: []
                      items:
                      - id: 103
                        item_product_id: 57
                        item_sku: PROD-57
                        warehouse_id: 2
                        snapshot_inventory: 45
                        qty_counted: 40
                        variance_reason: damage
                        is_lot_tracked: true
                        lot_tracking_method: fefo
                        lot_allocation:
                        - fifo_layer_id: 7101
                          quantity: 3
                        - fifo_layer_id: 7102
                          quantity: 2
                      updated_at: '2024-10-09T11:00:00+00:00'
                example-1:
                  summary: 200 Success (reallocation dispatched)
                  value:
                    data:
                      id: 42
                      status: closed
                      date_count: '2024-04-11T00:00:00+00:00'
                      deletable: false
                      delete_blocked_reasons:
                      - 'Stock Take Item: SKU-123 has 1 used fifo layer(s) and cannot
                        be deleted.'
                      reallocation_tracked_job_id: 9876
                      updated_at: '2024-10-09T11:00:00+00:00'
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: array
                    items:
                      type: object
                      properties:
                        message:
                          type: string
                        source:
                          type: string
                        field:
                          type: string
                        meta:
                          type: object
                          properties:
                            id:
                              type: integer
                example:
                  errors:
                  - message: 'Cannot reallocate: this would change COGS in a locked
                      accounting period. Sales Order Line SO-1041 (dated 2024-03-12)
                      is within the locked accounting period.'
                    source: StockTake
                    field: id
                    meta:
                      id: 42
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: inventory:write
      operationId: put-api-stock-takes-stock-take
    delete:
      tags:
      - Stock Takes
      summary: Delete Stock Take
      description: 'Delete a single stock take.


        :::info[Required scope: `inventory:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Returns 400 if the stock take has linked inventory adjustments or FIFO layers
        that prevent deletion.


        **Requires permission:** `inventory.count`'
      parameters:
      - name: stock_take
        in: path
        schema:
          type: integer
        required: true
        description: Stock take ID
        example: '43'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: stock take 43 deleted successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: inventory:write
      operationId: delete-api-stock-takes-stock-take
  /api/stock-takes/search-products:
    get:
      tags:
      - Stock Takes
      summary: Search Products
      description: 'Search products for adding to a stock take. Returns standard and
        kit products only (excludes archived).


        :::info[Required scope: `inventory:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Results are ordered by exact SKU match, then SKU prefix, then barcode, then
        name.


        If warehouse_id is provided, inventory levels for that warehouse are included.'
      parameters:
      - name: q
        in: query
        schema:
          type: string
        description: Optional. Search term (matches SKU, name, barcode).
        example: PROD
      - name: warehouse_id
        in: query
        schema:
          type: integer
        description: Optional. Warehouse ID to load inventory data for.
        example: '2'
      - name: in_stock_only
        in: query
        schema:
          type: integer
        description: Optional. 0=all products, 1=only products with stock in warehouse.
        example: '0'
      - name: limit
        in: query
        schema:
          type: integer
        description: Optional. Max results (1-50, default 50).
        example: '50'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        sku:
                          type: string
                        name:
                          type: string
                        barcode:
                          type: string
                        type:
                          type: string
                        unit_cost:
                          type: number
                        inventory_available:
                          type: integer
                        inventory_allocated:
                          type: integer
                        inventory_on_hold:
                          type: integer
                        inventory_total:
                          type: integer
                example:
                  data:
                  - id: 55
                    sku: PROD-001
                    name: Widget A
                    barcode: '123456789'
                    type: standard
                    unit_cost: 12.5
                    inventory_available: 95
                    inventory_allocated: 5
                    inventory_on_hold: 0
                    inventory_total: 100
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: inventory:read
      operationId: get-api-stock-takes-search-products
  /api/stock-takes/resolve-skus:
    post:
      tags:
      - Stock Takes
      summary: Resolve SKUs
      description: 'Bulk resolve a list of SKUs or barcodes to products in a single
        query. Used for importing large stock count sheets.


        :::info[Required scope: `inventory:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Matches against both SKU and barcode columns (case-insensitive). Deduplicates
        results.


        Max 5000 SKUs per request.


        Returns found, not_found, and skipped (wrong product type) arrays.


        **Requires permission:** `inventory.count`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                skus:
                  type: array
                  items:
                    type: string
              example:
                skus:
                - PROD-001
                - PROD-002
                - '123456789'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  found:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        sku:
                          type: string
                        name:
                          type: string
                        barcode:
                          type: string
                        type:
                          type: string
                        unit_cost:
                          type: number
                        case_quantity:
                          type: integer
                        input_sku:
                          type: string
                        is_lot_tracked:
                          type: boolean
                        lot_tracking_method:
                          type: string
                        shelf_life_days:
                          type: integer
                        near_expiry_threshold_days:
                          type: integer
                        min_remaining_shelf_life_days:
                          type: integer
                  not_found:
                    type: array
                    items:
                      type: string
                  skipped:
                    type: array
                example:
                  found:
                  - id: 55
                    sku: PROD-001
                    name: Widget A
                    barcode: '111111111'
                    type: standard
                    unit_cost: 12.5
                    case_quantity: 12
                    input_sku: PROD-001
                    is_lot_tracked: true
                    lot_tracking_method: fifo
                    shelf_life_days: 180
                    near_expiry_threshold_days: 60
                    min_remaining_shelf_life_days: 105
                  not_found:
                  - PROD-999
                  skipped: []
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: inventory:write
      operationId: post-api-stock-takes-resolve-skus
  /api/stock-takes:
    post:
      tags:
      - Stock Takes
      summary: Create Stock Take
      description: 'Create a new stock take.


        :::info[Required scope: `inventory:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        status: defaults to draft if not provided.


        date_count: defaults to today if not provided.


        mode: full_count (default) or adjustment.


        is_initial_count: marks this as the first ever count for the warehouse.


        condition: optional condition label (e.g., ''new'', ''used'').


        items: optional array of stock take line items. Can be added later. Each item:
        product_id (required, must exist), qty_counted (numeric, min 0), unit_cost
        (optional numeric, min 0 — an explicit 0 is valid and preserved, it does not
        fall back to the existing cost).


        warehouse_id must be a standard (non-virtual) warehouse.


        Response includes `deletable` (boolean) and `delete_blocked_reasons` (string[]):
        a draft/open stock take is always deletable; a closed stock take is deletable
        only when none of its FIFO cost layers have been consumed (otherwise `deletable`
        is false and `delete_blocked_reasons` lists the blocking stock take items).


        **Requires permission:** `inventory.count`


        `is_blind` (optional boolean, default false): a blind cycle count hides the
        system on-hand for items that have not yet been counted — their `snapshot_inventory`,
        `snapshot_available`, `snapshot_reserved`, and `snapshot_committed_to_fulfillment`
        are returned as null so the counter records what they find without anchoring
        to the expected quantity; once an item is counted the snapshots are revealed
        for variance review.


        Each item may also carry `variance_reason` — a root-cause code for why the
        counted quantity differs from the system on-hand. One of: receiving_error,
        picking_error, damage, mislabel, shrinkage, unknown.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                warehouse_id:
                  type: integer
                status:
                  type: string
                date_count:
                  type: string
                mode:
                  type: string
                is_initial_count:
                  type: boolean
                is_blind:
                  type: boolean
                condition:
                  type: string
                  nullable: true
                notes:
                  type: string
                items:
                  type: array
                  items:
                    type: object
                    properties:
                      product_id:
                        type: integer
                      qty_counted:
                        type: integer
                      snapshot_inventory:
                        type: integer
                      unit_cost:
                        type: number
                      lots:
                        type: array
                        items:
                          type: object
                          properties:
                            batch_number:
                              type: string
                            manufacture_date:
                              type: string
                            expiry_date:
                              type: string
                            quantity:
                              type: integer
                            lot_notes:
                              type: string
                      variance_reason:
                        type: string
              example:
                warehouse_id: 2
                status: draft
                date_count: '2024-10-10'
                mode: full_count
                is_initial_count: false
                is_blind: false
                condition: null
                notes: Q4 annual count
                items:
                - product_id: 55
                  qty_counted: 98
                  snapshot_inventory: 100
                  unit_cost: 12.5
                  lots:
                  - batch_number: LOT-2026-0042
                    manufacture_date: '2026-01-04'
                    expiry_date: '2026-07-04'
                    quantity: 98
                    lot_notes: Newly found lot
                  variance_reason: shrinkage
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      date_count:
                        type: string
                      is_blind:
                        type: boolean
                      warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      mode:
                        type: string
                      status:
                        type: string
                      deletable:
                        type: boolean
                      delete_blocked_reasons:
                        type: array
                      notes:
                        type: string
                      items:
                        type: array
                      created_at:
                        type: string
                example:
                  data:
                    id: 43
                    date_count: '2024-10-10T00:00:00+00:00'
                    is_blind: false
                    warehouse:
                      id: 2
                      name: Main Warehouse
                    mode: full_count
                    status: draft
                    deletable: true
                    delete_blocked_reasons: []
                    notes: Q4 annual count
                    items: []
                    created_at: '2024-10-08T09:00:00+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: inventory:write
      operationId: post-api-stock-takes
    delete:
      tags:
      - Stock Takes
      summary: Bulk Delete Stock Takes
      description: 'Bulk delete multiple stock takes.


        :::info[Required scope: `inventory:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        ids: required unless apply_to_all is true.


        **Requires permission:** `inventory.count`'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  deleted_count:
                    type: integer
                example:
                  message: Bulk delete completed
                  deleted_count: 2
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: inventory:write
      operationId: delete-api-stock-takes
  /api/stock-takes/bulk-insert:
    post:
      tags:
      - Stock Takes
      summary: Create Stock Take from Products
      description: 'Create a new stock take and bulk-insert product IDs as line items
        in one operation.


        :::info[Required scope: `inventory:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        ids: array of product IDs to add. Required unless filters is provided.


        filters: alternatively provide list view filters to select products dynamically.


        mode: full_count (default) or adjustment.


        is_initial_count: optional boolean; forces full_count and flags the take as
        the warehouse''s initial count.


        Unit cost: for adjustment mode, each item''s unit_cost is pre-seeded from
        the product''s best-available cost at the warehouse (FIFO / weighted-average
        / catalog unit cost, via GetBestAvailableCogs) so the Unit Cost column opens
        with a basis rather than blank; null when no cost exists. Overridable per
        row, and negative adjustments ignore it (cost is taken from consumed FIFO
        layers at finalization). Full counts are not seeded here — they capture cost
        at count initiation.


        Returns the new stock_take_id.


        **Requires permission:** `inventory.count`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
                warehouse_id:
                  type: integer
                mode:
                  type: string
                is_initial_count:
                  type: boolean
              example:
                ids:
                - 55
                - 56
                - 57
                warehouse_id: 2
                mode: full_count
                is_initial_count: false
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  stock_take_id:
                    type: integer
                example:
                  message: stock take 44 created successfully
                  stock_take_id: 44
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: inventory:write
      operationId: post-api-stock-takes-bulk-insert
  /api/stock-takes/check-initial-uniqueness:
    post:
      tags:
      - Stock Takes
      summary: Check Initial Uniqueness
      description: 'Check if an initial stock take already exists for a warehouse
        + condition combination.


        :::info[Required scope: `inventory:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `inventory.count`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                warehouse_id:
                  type: integer
                condition:
                  type: string
                  nullable: true
              example:
                warehouse_id: 2
                condition: null
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  exists:
                    type: boolean
                  stock_take_id:
                    type: integer
                example:
                  exists: true
                  stock_take_id: 10
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: inventory:write
      operationId: post-api-stock-takes-check-initial-uniqueness
  /api/stock-takes/{stockTake}/initiate:
    post:
      tags:
      - Stock Takes
      summary: Initiate Count
      description: 'Transition a stock take from Draft to Open status. Takes an inventory
        snapshot for all items.


        :::info[Required scope: `inventory:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        exclude_product_ids: optional array of product IDs to remove before initiating.


        is_integrity_fix: if true, marks as integrity fix count.


        date_count: optional retroactive count date (Y-m-d, app timezone, must be
        today or earlier). Use it when the physical count was performed earlier than
        it is being entered - the resulting inventory movements, FIFO layers and accounting
        journal are dated to it (so a historical ''as of'' inventory valuation reflects
        the count), while the snapshot cutoff for reconciling movements made during
        the count stays at the real initiate moment. Omit to date the count as of
        now.


        Returns 400 if stock take is in adjustment mode (use finalize-adjustment instead),
        if all items are excluded, or if date_count falls within a locked accounting
        period. Returns 422 if date_count is in the future.


        **Requires permission:** `inventory.count`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                exclude_product_ids:
                  type: array
                is_integrity_fix:
                  type: boolean
                date_count:
                  type: string
              example:
                exclude_product_ids: []
                is_integrity_fix: false
                date_count: '2026-06-29'
      parameters:
      - name: stockTake
        in: path
        schema:
          type: integer
        required: true
        description: Stock take ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      status:
                        type: string
                      date_count:
                        type: string
                      items:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            product_id:
                              type: integer
                            snapshot_inventory:
                              type: integer
                            qty_counted:
                              type: integer
                example:
                  data:
                    id: 42
                    status: open
                    date_count: '2024-10-10T09:00:00+00:00'
                    items:
                    - id: 101
                      product_id: 55
                      snapshot_inventory: 100
                      qty_counted: 100
        '422':
          description: Unprocessable Content
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      date_count:
                        type: array
                        items:
                          type: string
                example:
                  message: The date count field must be a date before or equal to
                    today.
                  errors:
                    date_count:
                    - The date count field must be a date before or equal to today.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: inventory:write
      operationId: post-api-stock-takes-stocktake-initiate
  /api/stock-takes/{stockTake}/re-snapshot:
    post:
      tags:
      - Stock Takes
      summary: Re-Snapshot Inventory
      description: 'Re-take inventory snapshot for an open stock take. Updates all
        items'' snapshot_inventory to current levels.


        :::info[Required scope: `inventory:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `inventory.count`'
      requestBody:
        content: {}
      parameters:
      - name: stockTake
        in: path
        schema:
          type: integer
        required: true
        description: Stock take ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      status:
                        type: string
                example:
                  data:
                    id: 42
                    status: open
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: inventory:write
      operationId: post-api-stock-takes-stocktake-re-snapshot
  /api/stock-takes/{stockTake}/zero-out:
    post:
      tags:
      - Stock Takes
      summary: Zero Out Counted Quantities
      description: 'Set all counted quantities to zero (or to allocated quantities).
        Only works for open, non-adjustment stock takes.


        :::info[Required scope: `inventory:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        mode values:

        - zero_all: set all items to 0

        - keep_submitted: keep quantities allocated to submitted fulfillments

        - keep_all_allocated: keep quantities reserved for all fulfillments


        **Requires permission:** `inventory.count`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                mode:
                  type: string
              example:
                mode: zero_all
      parameters:
      - name: stockTake
        in: path
        schema:
          type: integer
        required: true
        description: Stock take ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      status:
                        type: string
                      items:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            qty_counted:
                              type: integer
                example:
                  data:
                    id: 42
                    status: open
                    items:
                    - id: 101
                      qty_counted: 0
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: inventory:write
      operationId: post-api-stock-takes-stocktake-zero-out
  /api/stock-takes/{stockTake}/finalize:
    post:
      tags:
      - Stock Takes
      summary: Finalize Stock Take
      description: 'Finalize an open stock take. Creates inventory adjustments for
        all variances and transitions to Closed status.


        :::info[Required scope: `inventory:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Returns 400 if protected inventory conflicts exist, insufficient stock, or
        stock take is not open.


        **Requires permission:** `inventory.count`'
      requestBody:
        content: {}
      parameters:
      - name: stockTake
        in: path
        schema:
          type: integer
        required: true
        description: Stock take ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      status:
                        type: string
                      value_change:
                        type: number
                      variance_direction:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 42
                    status: closed
                    value_change: -125.0
                    variance_direction: negative
                    updated_at: '2024-10-10T16:00:00+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: inventory:write
      operationId: post-api-stock-takes-stocktake-finalize
  /api/stock-takes/{stockTake}/finalize-adjustment:
    post:
      tags:
      - Stock Takes
      summary: Finalize Adjustment
      description: 'Finalize an adjustment mode stock take (goes directly from Draft
        to Closed, bypassing Open status).


        :::info[Required scope: `inventory:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Returns 400 if stock take is not in adjustment mode.


        **Requires permission:** `inventory.count`'
      requestBody:
        content: {}
      parameters:
      - name: stockTake
        in: path
        schema:
          type: integer
        required: true
        description: Stock take ID (must be adjustment mode)
        example: '43'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      status:
                        type: string
                      mode:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 43
                    status: closed
                    mode: adjustment
                    updated_at: '2024-10-10T16:00:00+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: inventory:write
      operationId: post-api-stock-takes-stocktake-finalize-adjustment
  /api/stock-takes/{stockTake}/revert-to-draft:
    post:
      tags:
      - Stock Takes
      summary: Revert to Draft
      description: 'Revert an open stock take back to draft status.


        :::info[Required scope: `inventory:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `inventory.count`'
      requestBody:
        content: {}
      parameters:
      - name: stockTake
        in: path
        schema:
          type: integer
        required: true
        description: Stock take ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      status:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 42
                    status: draft
                    updated_at: '2024-10-09T12:00:00+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: inventory:write
      operationId: post-api-stock-takes-stocktake-revert-to-draft
  /api/stock-takes/{stockTake}/reverse:
    post:
      tags:
      - Stock Takes
      summary: Reverse Stock Take
      description: 'Reverse a closed stock take, undoing all inventory adjustments.


        :::info[Required scope: `inventory:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Returns 400 if reversal is not possible (e.g., FIFO layers already consumed).


        **Requires permission:** `inventory.count`'
      requestBody:
        content: {}
      parameters:
      - name: stockTake
        in: path
        schema:
          type: integer
        required: true
        description: Stock take ID (must be closed)
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      status:
                        type: string
                example:
                  message: Stock take reversed successfully.
                  data:
                    id: 42
                    status: closed
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: inventory:write
      operationId: post-api-stock-takes-stocktake-reverse
  /api/stock-takes/{stockTake}/reconciliation-preview:
    get:
      tags:
      - Stock Takes
      summary: Get Reconciliation Preview
      description: 'Get a preview of what reconciliation will do, including items
        with conflicts and open fulfillments.


        :::info[Required scope: `inventory:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: stockTake
        in: path
        schema:
          type: integer
        required: true
        description: Stock take ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  has_conflicts:
                    type: boolean
                  items:
                    type: array
                    items:
                      type: object
                      properties:
                        stock_take_item_id:
                          type: integer
                        product_sku:
                          type: string
                        variance:
                          type: integer
                        open_fulfillments:
                          type: array
                          items:
                            type: object
                            properties:
                              fulfillment_id:
                                type: integer
                              quantity:
                                type: integer
                example:
                  has_conflicts: true
                  items:
                  - stock_take_item_id: 101
                    product_sku: PROD-001
                    variance: -2
                    open_fulfillments:
                    - fulfillment_id: 500
                      quantity: 3
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: inventory:read
      operationId: get-api-stock-takes-stocktake-reconciliation-preview
  /api/stock-takes/{stockTake}/reconcile:
    post:
      tags:
      - Stock Takes
      summary: Execute Reconciliation
      description: 'Execute reconciliation for an open stock take, handling fulfillment
        conflicts and applying adjustments.


        :::info[Required scope: `inventory:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        fulfillment_ids_to_cancel: optional array of fulfillment IDs to cancel before
        reconciling.


        proceed_despite_failures: if true, continue even if some items fail.


        item_actions: per-item action overrides.


        Returns 400 if protected inventory conflicts exist or insufficient inventory.


        **Requires permission:** `inventory.count`


        downgraded_allocations: open Allocated reservations that were downgraded to
        Planned because the counted reduction exceeded the pool''s unallocated stock
        (reconciliation treats the 3PL count as authoritative). Each entry is also
        written to the reconciliation logs with action `allocation_downgraded`.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                fulfillment_ids_to_cancel:
                  type: array
                  items:
                    type: integer
                proceed_despite_failures:
                  type: boolean
                item_actions:
                  type: array
                  items:
                    type: object
                    properties:
                      stock_take_item_id:
                        type: integer
                      action:
                        type: string
              example:
                fulfillment_ids_to_cancel:
                - 500
                proceed_despite_failures: false
                item_actions:
                - stock_take_item_id: 101
                  action: adjust
      parameters:
      - name: stockTake
        in: path
        schema:
          type: integer
        required: true
        description: Stock take ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  stock_take_finalized:
                    type: boolean
                  cancelled_fulfillments:
                    type: array
                    items:
                      type: object
                      properties:
                        fulfillment_id:
                          type: integer
                        sales_order_reference:
                          type: string
                  failed_cancellations:
                    type: array
                  finalization_error:
                    type: string
                    nullable: true
                  total_value_change:
                    type: number
                  adjusted_items:
                    type: array
                    items:
                      type: object
                      properties:
                        stock_take_item_id:
                          type: integer
                        product_sku:
                          type: string
                        old_qty_counted:
                          type: integer
                        new_qty_counted:
                          type: integer
                  removed_items:
                    type: array
                  backordered_items:
                    type: array
                    items:
                      type: object
                      properties:
                        product_id:
                          type: integer
                        product_sku:
                          type: string
                        backordered_lines:
                          type: integer
                  downgraded_allocations:
                    type: array
                    items:
                      type: object
                      properties:
                        allocation_id:
                          type: integer
                        product_id:
                          type: integer
                        quantity:
                          type: integer
                        link_type:
                          type: string
                        link_id:
                          type: integer
                example:
                  success: true
                  stock_take_finalized: true
                  cancelled_fulfillments:
                  - fulfillment_id: 500
                    sales_order_reference: SO-1042
                  failed_cancellations: []
                  finalization_error: null
                  total_value_change: -125.5
                  adjusted_items:
                  - stock_take_item_id: 101
                    product_sku: WIDGET-1
                    old_qty_counted: 10
                    new_qty_counted: 8
                  removed_items: []
                  backordered_items:
                  - product_id: 55
                    product_sku: WIDGET-1
                    backordered_lines: 2
                  downgraded_allocations:
                  - allocation_id: 9912
                    product_id: 55
                    quantity: 6
                    link_type: App\Models\SalesOrderLine
                    link_id: 33412
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: inventory:write
      operationId: post-api-stock-takes-stocktake-reconcile
  /api/stock-takes/{stockTake}/reconciliation-logs:
    get:
      tags:
      - Stock Takes
      summary: Get Reconciliation Logs
      description: 'Get reconciliation log entries for a stock take.


        :::info[Required scope: `inventory:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: stockTake
        in: path
        schema:
          type: integer
        required: true
        description: Stock take ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: array
                items:
                  type: object
                  properties:
                    id:
                      type: integer
                    stock_take_id:
                      type: integer
                    stock_take_item_id:
                      type: integer
                    action:
                      type: string
                    qty_adjusted:
                      type: integer
                    created_at:
                      type: string
                example:
                - id: 1
                  stock_take_id: 42
                  stock_take_item_id: 101
                  action: adjusted
                  qty_adjusted: -2
                  created_at: '2024-10-10T16:00:00+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: inventory:read
      operationId: get-api-stock-takes-stocktake-reconciliation-logs
  /api/stock-takes/{stockTake}/cancel-fulfillment:
    post:
      tags:
      - Stock Takes
      summary: Cancel Fulfillment
      description: 'Cancel a single fulfillment as part of reconciliation preparation.
        Called line-by-line before executeReconciliation.


        :::info[Required scope: `inventory:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Returns 200 with success true/false, or 422 if cancellation fails.


        **Requires permission:** `inventory.count`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                fulfillment_id:
                  type: integer
              example:
                fulfillment_id: 500
      parameters:
      - name: stockTake
        in: path
        schema:
          type: integer
        required: true
        description: Stock take ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  fulfillment_id:
                    type: integer
                  message:
                    type: string
                example:
                  success: true
                  fulfillment_id: 500
                  message: Fulfillment cancelled successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: inventory:write
      operationId: post-api-stock-takes-stocktake-cancel-fulfillment
  /api/stock-takes/{stockTake}/adjustment-preview:
    get:
      tags:
      - Stock Takes
      summary: Preview Adjustment Feasibility
      description: 'Get a feasibility preview for each item before finalizing an adjustment
        mode stock take.


        :::info[Required scope: `inventory:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Returns 400 if not an adjustment mode stock take.'
      parameters:
      - name: stockTake
        in: path
        schema:
          type: integer
        required: true
        description: Stock take ID (must be adjustment mode)
        example: '43'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  items:
                    type: array
                    items:
                      type: object
                      properties:
                        stock_take_item_id:
                          type: integer
                        product_sku:
                          type: string
                        adjustment_qty:
                          type: integer
                        available_qty:
                          type: integer
                        feasible:
                          type: boolean
                example:
                  items:
                  - stock_take_item_id: 201
                    product_sku: PROD-005
                    adjustment_qty: -5
                    available_qty: 20
                    feasible: true
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: inventory:read
      operationId: get-api-stock-takes-stocktake-adjustment-preview
  /api/stock-takes/{stockTake}/reverse-analysis:
    get:
      tags:
      - Stock Takes
      summary: Analyze Reversibility
      description: 'Analyze whether a closed stock take can be reversed. Shows which
        items have consumed FIFO layers.


        :::info[Required scope: `inventory:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: stockTake
        in: path
        schema:
          type: integer
        required: true
        description: Stock take ID (must be closed)
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  can_reverse:
                    type: boolean
                  blocking_items:
                    type: array
                  reversible_items:
                    type: array
                    items:
                      type: object
                      properties:
                        stock_take_item_id:
                          type: integer
                        product_sku:
                          type: string
                example:
                  can_reverse: true
                  blocking_items: []
                  reversible_items:
                  - stock_take_item_id: 101
                    product_sku: PROD-001
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: inventory:read
      operationId: get-api-stock-takes-stocktake-reverse-analysis
  /api/stock-takes/{stockTake}/compensating-adjustment:
    post:
      tags:
      - Stock Takes
      summary: Create Compensating Adjustment
      description: 'Create a compensating adjustment stock take for a closed stock
        take whose FIFO layers have been consumed.


        :::info[Required scope: `inventory:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        items: optional array of item quantity overrides. If omitted, uses original
        variance quantities.


        Returns 400 if compensating adjustment cannot be created.


        **Requires permission:** `inventory.count`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                items:
                  type: array
                  items:
                    type: object
                    properties:
                      stock_take_item_id:
                        type: integer
                      adjustment_qty:
                        type: integer
              example:
                items:
                - stock_take_item_id: 101
                  adjustment_qty: -2
      parameters:
      - name: stockTake
        in: path
        schema:
          type: integer
        required: true
        description: Stock take ID (must be closed)
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      mode:
                        type: string
                      status:
                        type: string
                example:
                  message: Compensating adjustment created successfully.
                  data:
                    id: 45
                    mode: adjustment
                    status: draft
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: inventory:write
      operationId: post-api-stock-takes-stocktake-compensating-adjustment
  /api/stock-takes/{stockTake}/cost-correction-preview:
    post:
      tags:
      - Stock Takes
      summary: Preview Cost Correction
      description: 'Preview the impact of applying cost corrections to a closed stock
        take''s FIFO layers.


        :::info[Required scope: `inventory:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `inventory.count`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                items:
                  type: array
                  items:
                    type: object
                    properties:
                      stock_take_item_id:
                        type: integer
                      new_unit_cost:
                        type: integer
              example:
                items:
                - stock_take_item_id: 101
                  new_unit_cost: 13
      parameters:
      - name: stockTake
        in: path
        schema:
          type: integer
        required: true
        description: Stock take ID (must be closed)
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  items:
                    type: array
                    items:
                      type: object
                      properties:
                        stock_take_item_id:
                          type: integer
                        product_sku:
                          type: string
                        old_unit_cost:
                          type: number
                        new_unit_cost:
                          type: number
                        cost_difference:
                          type: number
                        affected_layers:
                          type: integer
                example:
                  items:
                  - stock_take_item_id: 101
                    product_sku: PROD-001
                    old_unit_cost: 12.5
                    new_unit_cost: 13.0
                    cost_difference: 0.5
                    affected_layers: 3
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: inventory:write
      operationId: post-api-stock-takes-stocktake-cost-correction-preview
  /api/stock-takes/{stockTake}/reallocation-preview:
    post:
      tags:
      - Stock Takes
      summary: Preview FIFO Reallocation
      description: 'Dry-run the FIFO reallocation that re-dating this stock take to
        the proposed date would cause, without writing anything. Returns the impact
        summary: how many outbound usages would be reassigned to different cost layers,
        the net COGS delta, a per-product breakdown, and whether the change would
        touch a locked accounting period (in which case the actual re-date is blocked).


        :::info[Required scope: `inventory:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Body: date_count (date, required) — the proposed new count date.


        **Requires permission:** `inventory.count`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                date_count:
                  type: string
              example:
                date_count: '2024-04-11'
      parameters:
      - name: stockTake
        in: path
        schema:
          type: integer
        required: true
        description: Stock take ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 Success
                  value:
                    data:
                      date_count: '2024-04-11'
                      locked_period_blocked: false
                      locked_period_reasons: []
                      total_reassigned_usages: 37
                      net_cogs_delta: 1284.5
                      products:
                      - product_id: 55
                        sku: ABC-123
                        warehouse_id: 1
                        reassigned_usages: 22
                        cogs_delta: 812.0
                        has_fba_layers: false
                example-1:
                  summary: 200 Blocked (locked period)
                  value:
                    data:
                      date_count: '2024-04-11'
                      locked_period_blocked: true
                      locked_period_reasons:
                      - Sales Order Line SO-1041 (dated 2024-03-12) is within the
                        locked accounting period.
                      total_reassigned_usages: 3
                      net_cogs_delta: -45.0
                      products: []
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      date_count:
                        type: array
                        items:
                          type: string
                example:
                  message: A proposed count date is required to preview the reallocation.
                  errors:
                    date_count:
                    - A proposed count date is required to preview the reallocation.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: inventory:write
      operationId: post-api-stock-takes-stocktake-reallocation-preview
  /api/stock-takes/{stockTake}/apply-cost-correction:
    post:
      tags:
      - Stock Takes
      summary: Apply Cost Correction
      description: 'Apply cost corrections to a closed stock take''s FIFO layers.


        :::info[Required scope: `inventory:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `inventory.count`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                items:
                  type: array
                  items:
                    type: object
                    properties:
                      stock_take_item_id:
                        type: integer
                      new_unit_cost:
                        type: integer
              example:
                items:
                - stock_take_item_id: 101
                  new_unit_cost: 13
      parameters:
      - name: stockTake
        in: path
        schema:
          type: integer
        required: true
        description: Stock take ID (must be closed)
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      status:
                        type: string
                example:
                  message: Cost corrections applied successfully.
                  data:
                    id: 42
                    status: closed
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: inventory:write
      operationId: post-api-stock-takes-stocktake-apply-cost-correction
  /api/stock-takes/{stockTake}/fifo-layers:
    get:
      tags:
      - Stock Takes
      summary: Get FIFO Layers
      description: 'Get FIFO inventory layers connected to this stock take''s items.


        :::info[Required scope: `inventory:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: stockTake
        in: path
        schema:
          type: integer
        required: true
        description: Stock take ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        product_id:
                          type: integer
                        warehouse_id:
                          type: integer
                        quantity:
                          type: integer
                        unit_cost:
                          type: number
                        link_type:
                          type: string
                        link_id:
                          type: integer
                        created_at:
                          type: string
                example:
                  data:
                  - id: 300
                    product_id: 55
                    warehouse_id: 2
                    quantity: 98
                    unit_cost: 12.5
                    link_type: App\Models\StockTakeItem
                    link_id: 101
                    created_at: '2024-10-10T16:00:00+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: inventory:read
      operationId: get-api-stock-takes-stocktake-fifo-layers
  /api/stock-takes/{stockTake}/inventory-movements:
    get:
      tags:
      - Stock Takes
      summary: Get Inventory Movements
      description: 'Get all inventory movements linked to this stock take.


        :::info[Required scope: `inventory:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: stockTake
        in: path
        schema:
          type: integer
        required: true
        description: Stock take ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        product_id:
                          type: integer
                        warehouse_id:
                          type: integer
                        quantity:
                          type: integer
                        movement_type:
                          type: string
                        link_type:
                          type: string
                        link_id:
                          type: integer
                        created_at:
                          type: string
                example:
                  data:
                  - id: 2001
                    product_id: 55
                    warehouse_id: 2
                    quantity: -2
                    movement_type: stock_take_adjustment
                    link_type: App\Models\StockTakeItem
                    link_id: 101
                    created_at: '2024-10-10T16:00:00+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: inventory:read
      operationId: get-api-stock-takes-stocktake-inventory-movements
  /api/stock-takes/{stockTake}/during-count-movements:
    get:
      tags:
      - Stock Takes
      summary: Get During-Count Movements
      description: 'Get inventory movements that occurred during the stock take counting
        period (after snapshot was taken), excluding movements belonging to this stock
        take itself.


        :::info[Required scope: `inventory:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: stockTake
        in: path
        schema:
          type: integer
        required: true
        description: Stock take ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        product_id:
                          type: integer
                        warehouse_id:
                          type: integer
                        quantity:
                          type: integer
                        movement_type:
                          type: string
                        created_at:
                          type: string
                example:
                  data:
                  - id: 2005
                    product_id: 55
                    warehouse_id: 2
                    quantity: 10
                    movement_type: purchase_order_receipt
                    created_at: '2024-10-10T12:00:00+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: inventory:read
      operationId: get-api-stock-takes-stocktake-during-count-movements
  /api/stock-takes/product-cost-options:
    get:
      tags:
      - Stock Takes
      summary: Get Product Cost Options
      description: 'Get cost options for a product in a warehouse. Returns the best
        available COGS (derived from FIFO cost history) and the product''s default
        unit cost. Both values are per stock unit and returned with up to 4 decimal
        places of precision — products stocked in small units (oz, g, ml) routinely
        have per-unit costs below $0.01.


        :::info[Required scope: `inventory:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: product_id
        in: query
        schema:
          type: integer
        description: Required. Product ID.
        example: '55'
      - name: warehouse_id
        in: query
        schema:
          type: integer
        description: Required. Warehouse ID.
        example: '2'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  best_available_cogs:
                    type: object
                    properties:
                      value:
                        type: number
                      source:
                        type: string
                      available:
                        type: boolean
                  unit_cost:
                    type: object
                    properties:
                      value:
                        type: number
                      available:
                        type: boolean
                example:
                  best_available_cogs:
                    value: 0.2344
                    source: oldest_active_fifo
                    available: true
                  unit_cost:
                    value: 0.23
                    available: true
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: inventory:read
      operationId: get-api-stock-takes-product-cost-options
  /api/stock-takes/inventory-start-date:
    get:
      tags:
      - Stock Takes
      summary: Get Inventory Start Date
      description: 'Get the inventory start date from application settings. Used to
        validate initial count dates.


        :::info[Required scope: `inventory:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  inventory_start_date:
                    type: string
                example:
                  inventory_start_date: '2024-01-01'
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: inventory:read
      operationId: get-api-stock-takes-inventory-start-date
  /api/stock-takes/{stockTake}/import-lines:
    post:
      tags:
      - Stock Takes
      summary: Import Lines from CSV
      description: 'Import stock take lines from a previously uploaded CSV file. The
        CSV must have columns: sku or id (product identifier), and optionally qty_counted,
        snapshot_inventory, unit_cost.


        :::info[Required scope: `inventory:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        file: path to an already uploaded file (not a direct upload).


        Products matched by SKU or barcode. Duplicate products are summed. Unmatched
        SKUs generate warnings.


        Returns parsed line items (not yet saved — save via the update endpoint).


        **Requires permission:** `inventory.count`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                file:
                  type: string
                separator:
                  type: string
                escape:
                  type: string
              example:
                file: uploads/stock_take_lines_20241010.csv
                separator: ','
                escape: '"'
      parameters:
      - name: stockTake
        in: path
        schema:
          type: integer
        required: true
        description: Stock take ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        product_id:
                          type: integer
                        sku:
                          type: string
                        name:
                          type: string
                        qty_counted:
                          type: integer
                        snapshot_inventory:
                          type: integer
                        unit_cost:
                          type: string
                          nullable: true
                  warnings:
                    type: array
                    items:
                      type: object
                      properties:
                        code:
                          type: string
                        message:
                          type: string
                example:
                  data:
                  - product_id: 55
                    sku: PROD-001
                    name: Widget A
                    qty_counted: 98
                    snapshot_inventory: 0
                    unit_cost: null
                  warnings:
                  - code: HAS_UNMAPPED_PRODUCTS
                    message: 2 of SKUs did not match any product
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: inventory:write
      operationId: post-api-stock-takes-stocktake-import-lines
  /api/stock-takes/{stockTake}/archive:
    put:
      tags:
      - Stock Takes
      summary: Archive Stock Take
      description: 'Archive a single stock take.


        :::info[Required scope: `inventory:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `inventory.count`'
      requestBody:
        content: {}
      parameters:
      - name: stockTake
        in: path
        schema:
          type: integer
        required: true
        description: Stock take ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      archived_at:
                        type: string
                example:
                  message: stock take 42 archived successfully
                  data:
                    id: 42
                    archived_at: '2024-10-15T09:00:00+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: inventory:write
      operationId: put-api-stock-takes-stocktake-archive
  /api/stock-takes/{stockTake}/unarchived:
    put:
      tags:
      - Stock Takes
      summary: Unarchive Stock Take
      description: 'Unarchive a single stock take.


        :::info[Required scope: `inventory:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `inventory.count`'
      requestBody:
        content: {}
      parameters:
      - name: stockTake
        in: path
        schema:
          type: integer
        required: true
        description: Stock take ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      archived_at:
                        type: string
                        nullable: true
                example:
                  message: stock take 42 unarchived successfully
                  data:
                    id: 42
                    archived_at: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: inventory:write
      operationId: put-api-stock-takes-stocktake-unarchived
  /api/stock-takes/archive:
    put:
      tags:
      - Stock Takes
      summary: Bulk Archive Stock Takes
      description: 'Bulk archive multiple stock takes.


        :::info[Required scope: `inventory:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        ids: array of stock take IDs. Required unless apply_to_all is true.


        apply_to_all: if true, archives all stock takes matching filters.


        filters: optional filter conditions when apply_to_all is true.


        **Requires permission:** `inventory.count`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
                apply_to_all:
                  type: boolean
                filters:
                  type: object
                  properties: {}
              example:
                ids:
                - 40
                - 41
                - 42
                apply_to_all: false
                filters: {}
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  archived_count:
                    type: integer
                example:
                  message: Bulk archive completed
                  archived_count: 3
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: inventory:write
      operationId: put-api-stock-takes-archive
  /api/stock-takes/unarchive:
    put:
      tags:
      - Stock Takes
      summary: Bulk Unarchive Stock Takes
      description: 'Bulk unarchive multiple stock takes.


        :::info[Required scope: `inventory:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `inventory.count`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
                apply_to_all:
                  type: boolean
                filters:
                  type: object
                  properties: {}
              example:
                ids:
                - 40
                - 41
                apply_to_all: false
                filters: {}
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Bulk unarchive completed
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: inventory:write
      operationId: put-api-stock-takes-unarchive
  /api/stock-takes/deletable:
    post:
      tags:
      - Stock Takes
      summary: Check Deletable Stock Takes
      description: 'Check whether stock takes can be deleted. Returns deletable status
        and reason for each.


        :::info[Required scope: `inventory:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `inventory.count`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 42
                - 43
                - 44
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        deletable:
                          type: boolean
                        reason:
                          type: string
                example:
                  data:
                  - id: 42
                    deletable: false
                    reason: Stock take has linked inventory movements
                  - id: 43
                    deletable: true
                    reason: null
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: inventory:write
      operationId: post-api-stock-takes-deletable
  /api/assemblies:
    get:
      tags:
      - Assemblies
      summary: List Assemblies
      description: 'Returns a paginated list of inventory assemblies. Supports pagination,
        search, and archive filtering.


        :::info[Required scope: `inventory:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token


        Response fields:

        - id: Assembly ID

        - warehouse: Warehouse details {id, name}

        - action_date: Date of the assembly/disassembly action

        - action: ''assemble'' or ''disassemble''

        - items: Assembly lines with product details

        - created_at: Creation timestamp

        - archived_at: Archive timestamp (null if not archived)'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        description: 'Page number (default: 1)'
        example: '1'
      - name: per_page
        in: query
        schema:
          type: integer
        description: 'Items per page (default: 15)'
        example: '15'
      - name: search
        in: query
        schema:
          type: string
        description: Search string to filter assemblies
      - name: archived
        in: query
        schema:
          type: integer
        description: 'Include archived records: 0 = active only (default), 1 = archived
          only'
        example: '0'
      - name: sort
        in: query
        schema:
          type: string
        description: 'Sort field. Prefix with - for descending. Allowed: id, action_date,
          created_at, updated_at'
        example: id
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        warehouse:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        action_date:
                          type: string
                        action:
                          type: string
                        items:
                          type: array
                          items:
                            type: object
                            properties:
                              id:
                                type: integer
                              product_id:
                                type: integer
                              quantity:
                                type: integer
                              product_type:
                                type: string
                        created_at:
                          type: string
                        archived_at:
                          type: string
                          nullable: true
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 42
                    warehouse:
                      id: 1
                      name: Main Warehouse
                    action_date: '2024-01-15'
                    action: assemble
                    items:
                    - id: 10
                      product_id: 100
                      quantity: 5
                      product_type: kit
                    created_at: '2024-01-15T10:30:00.000000Z'
                    archived_at: null
                  last_page: 4
                  per_page: 15
                  total: 57
                  from: 1
                  to: 15
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: inventory:read
      operationId: get-api-assemblies
    post:
      tags:
      - Assemblies
      summary: Create Assembly
      description: 'Creates a new inventory assembly or disassembly record, adjusting
        inventory accordingly.


        :::info[Required scope: `inventory:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token


        Request body:

        - action_date (date, required): Date of the assembly/disassembly action (e.g.
        ''2024-01-15'')

        - product_id (integer, required): ID of the kit product to assemble/disassemble

        - warehouse_id (integer, required): ID of the warehouse where the action takes
        place. Warehouse must have a default location unless warehouse_location_id
        is provided.

        - warehouse_location_id (integer, optional): ID of the warehouse location.
        If omitted, uses the warehouse''s default location.

        - quantity (numeric, required): Quantity to assemble or disassemble. Must
        be non-zero.

        - action (string, required): Type of action — ''assemble'' (build kits from
        components) or ''disassemble'' (break kits into components)

        - component_lot_allocations (array, optional, ASSEMBLE only): FEFO suggest-with-override
        for lot-tracked components. Each entry is `{ product_id, lot_allocation: [{
        fifo_layer_id, quantity }] }`. Omit to consume components by automatic FEFO/FIFO.
        When supplied, the allocation for each component must reconcile to that component''s
        total consumption (its per-kit quantity × assembly quantity), reference active
        FIFO layers of that component product + the selected warehouse, and respect
        the tenant''s lot-override policy (under `enforce`, expired or later-expiry
        FEFO picks are hard-blocked). Validation errors are returned per row, e.g.
        `component_lot_allocations.0.lot_allocation.1.fifo_layer_id`.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                action_date:
                  type: string
                product_id:
                  type: integer
                warehouse_id:
                  type: integer
                warehouse_location_id:
                  type: string
                  nullable: true
                quantity:
                  type: integer
                action:
                  type: string
                component_lot_allocations:
                  type: array
                  items:
                    type: object
                    properties:
                      product_id:
                        type: integer
                      lot_allocation:
                        type: array
                        items:
                          type: object
                          properties:
                            fifo_layer_id:
                              type: integer
                            quantity:
                              type: integer
              example:
                action_date: '2024-01-15'
                product_id: 100
                warehouse_id: 1
                warehouse_location_id: null
                quantity: 5
                action: assemble
                component_lot_allocations:
                - product_id: 201
                  lot_allocation:
                  - fifo_layer_id: 901
                    quantity: 8
                  - fifo_layer_id: 902
                    quantity: 2
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      action_date:
                        type: string
                      action:
                        type: string
                      items:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            product_id:
                              type: integer
                            quantity:
                              type: integer
                            product_type:
                              type: string
                      created_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                example:
                  message: Inventory assembled successfully.
                  data:
                    id: 42
                    warehouse:
                      id: 1
                      name: Main Warehouse
                    action_date: '2024-01-15'
                    action: assemble
                    items:
                    - id: 10
                      product_id: 100
                      quantity: 5
                      product_type: kit
                    created_at: '2024-01-15T10:30:00.000000Z'
                    archived_at: null
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      product:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            product_id:
                              type: integer
                example:
                  message: Cannot complete assembly — insufficient component stock.
                  errors:
                    product:
                    - message: Insufficient stock for SKU-001
                      code: ProductUnacceptable
                      product_id: 100
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      product_id:
                        type: array
                        items:
                          type: string
                      warehouse_id:
                        type: array
                        items:
                          type: string
                example:
                  message: The product id field is required.
                  errors:
                    product_id:
                    - The product id field is required.
                    warehouse_id:
                    - The warehouse id field is required.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: inventory:write
      operationId: post-api-assemblies
    delete:
      tags:
      - Assemblies
      summary: Bulk Delete Assemblies
      description: 'Deletes multiple inventory assemblies and reverses their inventory
        movements.


        :::info[Required scope: `inventory:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token


        Request body:

        - ids (array, required unless apply_to_all is true): Array of assembly IDs
        to delete

        - apply_to_all (boolean, optional): If true, deletes all assemblies matching
        the provided filters

        - filters (array, optional): Filter criteria when apply_to_all is true'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 3 inventory assemblies deleted successfully.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: inventory:write
      operationId: delete-api-assemblies
  /api/assemblies/{assembly}:
    get:
      tags:
      - Assemblies
      summary: Get Assembly
      description: 'Returns the full details of a single inventory assembly, including
        assembly lines, inventory movements, and FIFO layer data.


        :::info[Required scope: `inventory:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token


        Response includes:

        - id, warehouse, action_date, action

        - items: Assembly lines with product details and primary image

        - inventory_impact: Grouped movements per line with FIFO layer data

        - created_at, updated_at, archived_at'
      parameters:
      - name: assembly
        in: path
        schema:
          type: integer
        required: true
        description: Assembly ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      action_date:
                        type: string
                      action:
                        type: string
                      items:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            product_id:
                              type: integer
                            quantity:
                              type: integer
                            product_type:
                              type: string
                      inventory_impact:
                        type: array
                        items:
                          type: object
                          properties:
                            line_id:
                              type: integer
                            product_id:
                              type: integer
                            product:
                              type: object
                              properties:
                                sku:
                                  type: string
                                name:
                                  type: string
                            quantity:
                              type: integer
                            product_type:
                              type: string
                            movements:
                              type: array
                              items:
                                type: object
                                properties:
                                  id:
                                    type: integer
                                  product_id:
                                    type: integer
                                  warehouse_id:
                                    type: integer
                                  warehouse:
                                    type: object
                                    properties:
                                      name:
                                        type: string
                                  quantity_delta:
                                    type: integer
                                  quantity_delta_reserved:
                                    type: integer
                                  movement_date:
                                    type: string
                                  inventory_status:
                                    type: string
                                  layer:
                                    type: object
                                    properties:
                                      id:
                                        type: integer
                                      fifo_layer_date:
                                        type: string
                                      original_quantity:
                                        type: integer
                                      fulfilled_quantity:
                                        type: integer
                                      available_quantity:
                                        type: integer
                                      avg_cost:
                                        type: number
                                      total_cost:
                                        type: number
                                      link_type:
                                        type: string
                                      link_reference:
                                        type: string
                                      product:
                                        type: object
                                        properties:
                                          sku:
                                            type: string
                                          name:
                                            type: string
                                      warehouse:
                                        type: object
                                        properties:
                                          name:
                                            type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                example:
                  data:
                    id: 42
                    warehouse:
                      id: 1
                      name: Main Warehouse
                    action_date: '2024-01-15'
                    action: assemble
                    items:
                    - id: 10
                      product_id: 100
                      quantity: 5
                      product_type: kit
                    inventory_impact:
                    - line_id: 10
                      product_id: 100
                      product:
                        sku: KIT-001
                        name: Starter Kit
                      quantity: 5
                      product_type: kit
                      movements:
                      - id: 201
                        product_id: 100
                        warehouse_id: 1
                        warehouse:
                          name: Main Warehouse
                        quantity_delta: 5
                        quantity_delta_reserved: 0
                        movement_date: '2024-01-15'
                        inventory_status: on_hand
                        layer:
                          id: 55
                          fifo_layer_date: '2024-01-15'
                          original_quantity: 5
                          fulfilled_quantity: 0
                          available_quantity: 5
                          avg_cost: 12.5
                          total_cost: 62.5
                          link_type: assembly
                          link_reference: '42'
                          product:
                            sku: KIT-001
                            name: Starter Kit
                          warehouse:
                            name: Main Warehouse
                    created_at: '2024-01-15T10:30:00.000000Z'
                    updated_at: '2024-01-15T10:30:00.000000Z'
                    archived_at: null
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No query results for model [App\Models\InventoryAssembly]
                    99
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: inventory:read
      operationId: get-api-assemblies-assembly
    delete:
      tags:
      - Assemblies
      summary: Delete Assembly
      description: 'Deletes the specified inventory assembly and reverses its inventory
        movements.


        :::info[Required scope: `inventory:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token


        Note: Deletion reverses the inventory impact of the assembly (FIFO layers
        are unwound).'
      parameters:
      - name: assembly
        in: path
        schema:
          type: integer
        required: true
        description: Assembly ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: inventory assembly 42 deleted successfully.
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      product:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            product_id:
                              type: integer
                example:
                  message: Cannot delete assembly — FIFO layer has been used.
                  errors:
                    product:
                    - message: FIFO layer is in use for SKU-001
                      code: ProductUnacceptable
                      product_id: 100
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: inventory:write
      operationId: delete-api-assemblies-assembly
  /api/assemblies/deletable:
    post:
      tags:
      - Assemblies
      summary: Check Assemblies Deletable
      description: 'Checks whether the specified assemblies can be deleted. All inventory
        assemblies are deletable (deletion reverses inventory movements).


        :::info[Required scope: `inventory:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token


        Request body:

        - ids (array, required): Array of assembly IDs to check (min 1)'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 42
                - 43
                - 44
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        deletable:
                          type: boolean
                        reason:
                          type: string
                          nullable: true
                example:
                  data:
                  - id: 42
                    deletable: true
                    reason: null
                  - id: 43
                    deletable: true
                    reason: null
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: inventory:write
      operationId: post-api-assemblies-deletable
  /api/assemblies/{assembly}/archive:
    put:
      tags:
      - Assemblies
      summary: Archive Assembly
      description: 'Archives the specified inventory assembly by setting its archived_at
        timestamp.


        :::info[Required scope: `inventory:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token'
      requestBody:
        content: {}
      parameters:
      - name: assembly
        in: path
        schema:
          type: integer
        required: true
        description: Assembly ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      archived_at:
                        type: string
                example:
                  message: inventory assembly 42 archived successfully.
                  data:
                    id: 42
                    archived_at: '2024-01-15T10:30:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: inventory:write
      operationId: put-api-assemblies-assembly-archive
  /api/assemblies/{assembly}/unarchived:
    put:
      tags:
      - Assemblies
      summary: Unarchive Assembly
      description: 'Restores (unarchives) the specified inventory assembly by clearing
        its archived_at timestamp.


        :::info[Required scope: `inventory:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token'
      requestBody:
        content: {}
      parameters:
      - name: assembly
        in: path
        schema:
          type: integer
        required: true
        description: Assembly ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      archived_at:
                        type: string
                        nullable: true
                example:
                  message: inventory assembly 42 unarchived successfully.
                  data:
                    id: 42
                    archived_at: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: inventory:write
      operationId: put-api-assemblies-assembly-unarchived
  /api/assemblies/archive:
    put:
      tags:
      - Assemblies
      summary: Bulk Archive Assemblies
      description: 'Archives multiple inventory assemblies.


        :::info[Required scope: `inventory:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token


        Request body:

        - ids (array, required unless apply_to_all is true): Array of assembly IDs
        to archive

        - apply_to_all (boolean, optional): If true, archives all assemblies matching
        the provided filters

        - filters (array, optional): Filter criteria when apply_to_all is true'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 42
                - 43
                - 44
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 3 inventory assemblies archived successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: inventory:write
      operationId: put-api-assemblies-archive
  /api/assemblies/unarchive:
    put:
      tags:
      - Assemblies
      summary: Bulk Unarchive Assemblies
      description: 'Restores (unarchives) multiple inventory assemblies.


        :::info[Required scope: `inventory:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token


        Request body:

        - ids (array, required unless apply_to_all is true): Array of assembly IDs
        to unarchive

        - apply_to_all (boolean, optional): If true, unarchives all assemblies matching
        the provided filters

        - filters (array, optional): Filter criteria when apply_to_all is true'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 42
                - 43
                - 44
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 3 inventory assemblies unarchived successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: inventory:write
      operationId: put-api-assemblies-unarchive
  /api/assemblies/browse-kits:
    get:
      tags:
      - Assemblies
      summary: List Kit Products
      description: 'Returns a paginated list of kit products with inventory availability
        data for the assembly form. Shows how many kits can currently be assembled
        based on available component stock.


        :::info[Required scope: `inventory:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token


        Response fields per kit:

        - id: Product ID

        - sku: Product SKU

        - name: Product name

        - qty_on_hand: Current assembled kit quantity in the warehouse

        - qty_possible: Maximum number of kits that can be assembled from available
        component stock'
      parameters:
      - name: warehouse_id
        in: query
        schema:
          type: integer
        description: Warehouse ID to calculate inventory quantities for (optional).
          If omitted, qty_on_hand and qty_possible will be 0.
        example: '1'
      - name: query
        in: query
        schema:
          type: string
        description: Search string to filter kit products by SKU or name
        example: starter
      - name: limit
        in: query
        schema:
          type: integer
        description: 'Items per page (default: 15)'
        example: '15'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        sku:
                          type: string
                        name:
                          type: string
                        qty_on_hand:
                          type: integer
                        qty_possible:
                          type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 100
                    sku: KIT-001
                    name: Starter Kit
                    qty_on_hand: 12
                    qty_possible: 8
                  last_page: 2
                  per_page: 15
                  total: 18
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: inventory:read
      operationId: get-api-assemblies-browse-kits
  /api/assemblies/inventory-data:
    get:
      tags:
      - Assemblies
      summary: Get Kit & Component Availability
      description: 'Returns inventory availability data for a kit product and its
        components across all warehouses. Used in the assembly form to show per-warehouse
        stock levels.


        :::info[Required scope: `inventory:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token


        Response:

        - kit_inventory: Map of warehouse_id => {warehouse_id, warehouse_name, quantity}
        for the kit product

        - component_inventory: Map of warehouse_id => {product_id: available_qty}
        for each component'
      parameters:
      - name: product_id
        in: query
        schema:
          type: integer
        description: Kit product ID (required). Returns inventory data for this kit
          and all its component products.
        example: '100'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      kit_inventory:
                        type: object
                        properties:
                          '1':
                            type: object
                            properties:
                              warehouse_id:
                                type: integer
                              warehouse_name:
                                type: string
                              quantity:
                                type: integer
                          '2':
                            type: object
                            properties:
                              warehouse_id:
                                type: integer
                              warehouse_name:
                                type: string
                              quantity:
                                type: integer
                      component_inventory:
                        type: object
                        properties:
                          '1':
                            type: object
                            properties:
                              '101':
                                type: integer
                              '102':
                                type: integer
                          '2':
                            type: object
                            properties:
                              '101':
                                type: integer
                              '102':
                                type: integer
                example:
                  data:
                    kit_inventory:
                      '1':
                        warehouse_id: 1
                        warehouse_name: Main Warehouse
                        quantity: 12
                      '2':
                        warehouse_id: 2
                        warehouse_name: East Warehouse
                        quantity: 5
                    component_inventory:
                      '1':
                        '101': 50
                        '102': 30
                      '2':
                        '101': 20
                        '102': 10
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      product_id:
                        type: array
                        items:
                          type: string
                example:
                  message: The product id field is required.
                  errors:
                    product_id:
                    - The product id field is required.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: inventory:read
      operationId: get-api-assemblies-inventory-data
  /api/initial-inventory/import:
    post:
      tags:
      - Initial Inventory
      summary: Import Initial Inventory (CSV)
      description: 'Imports initial inventory records from a CSV file using the DataImport
        system.

        Authentication: Requires Bearer token.

        Content-Type: multipart/form-data


        :::info[Required scope: `inventory:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        The import first runs a preview/validation pass. If there are required field
        differences, the preview response is returned. Otherwise, the import is executed
        and records are created.'
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                file:
                  type: string
                  description: 'CSV file containing initial inventory records. Headers:
                    product_sku, warehouse_name, quantity, unit_cost, date'
                  format: binary
                import_type:
                  type: string
                  description: Import type identifier
                  example: initial_inventory
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 Success — Import Complete
                  value:
                    data:
                      imported: 42
                      failed: 0
                      errors: []
                    message: Import completed successfully.
                    status: success
                example-1:
                  summary: 200 Preview — Validation Required
                  value:
                    data:
                      preview: true
                      rows:
                      - product_sku: WIDGET-001
                        quantity: 200
                        unit_cost: 10.0
                        status: valid
                      errors: []
                      warnings: []
                    status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: inventory:write
      operationId: post-api-initial-inventory-import
  /api/initial-inventory:
    get:
      tags:
      - Initial Inventory
      summary: List Initial Inventory
      description: 'Returns a paginated list of initial inventory records (FIFO layers
        representing opening stock).

        Authentication: Requires Bearer token.

        Uses standard list query parameters for filtering, sorting, and pagination.


        :::info[Required scope: `inventory:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        description: Page number
        example: '1'
      - name: limit
        in: query
        schema:
          type: integer
        description: Items per page
        example: '25'
      - name: sort
        in: query
        schema:
          type: string
        description: Sort field. Prefix with - for descending (e.g. -id)
        example: id
      - name: search
        in: query
        schema:
          type: string
        description: Search across SKU, product name
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        product_id:
                          type: integer
                        sku:
                          type: string
                        product_name:
                          type: string
                        warehouse_id:
                          type: integer
                        warehouse_name:
                          type: string
                        quantity:
                          type: integer
                        unit_cost:
                          type: number
                        fifo_layer_date:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 1
                    product_id: 42
                    sku: WIDGET-001
                    product_name: Blue Widget
                    warehouse_id: 1
                    warehouse_name: Main Warehouse
                    quantity: 200
                    unit_cost: 10.0
                    fifo_layer_date: '2023-01-01'
                    created_at: '2023-01-01T00:00:00Z'
                    updated_at: '2023-01-01T00:00:00Z'
                  current_page: 1
                  last_page: 2
                  per_page: 25
                  total: 42
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: inventory:read
      operationId: get-api-initial-inventory
    post:
      tags:
      - Initial Inventory
      summary: Create Initial Inventory
      description: 'Creates an initial inventory record (opening stock FIFO layer)
        for a product in a warehouse.

        Authentication: Requires Bearer token.


        :::info[Required scope: `inventory:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                product_id:
                  type: integer
                warehouse_id:
                  type: integer
                quantity:
                  type: integer
                unit_cost:
                  type: integer
                fifo_layer_date:
                  type: string
              example:
                product_id: 42
                warehouse_id: 1
                quantity: 200
                unit_cost: 10
                fifo_layer_date: '2023-01-01'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      product_id:
                        type: integer
                      warehouse_id:
                        type: integer
                      quantity:
                        type: integer
                      unit_cost:
                        type: number
                      fifo_layer_date:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                  status:
                    type: string
                example:
                  data:
                    id: 5
                    product_id: 42
                    warehouse_id: 1
                    quantity: 200
                    unit_cost: 10.0
                    fifo_layer_date: '2023-01-01'
                    created_at: '2024-01-15T10:00:00Z'
                    updated_at: '2024-01-15T10:00:00Z'
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: inventory:write
      operationId: post-api-initial-inventory
  /api/initial-inventory/{id}:
    get:
      tags:
      - Initial Inventory
      summary: Get Initial Inventory
      description: 'Returns a single initial inventory record.

        Authentication: Requires Bearer token.


        :::info[Required scope: `inventory:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: id
        in: path
        schema:
          type: integer
        required: true
        description: Initial inventory record ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      product_id:
                        type: integer
                      sku:
                        type: string
                      product_name:
                        type: string
                      warehouse_id:
                        type: integer
                      warehouse_name:
                        type: string
                      quantity:
                        type: integer
                      unit_cost:
                        type: number
                      fifo_layer_date:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                  status:
                    type: string
                example:
                  data:
                    id: 1
                    product_id: 42
                    sku: WIDGET-001
                    product_name: Blue Widget
                    warehouse_id: 1
                    warehouse_name: Main Warehouse
                    quantity: 200
                    unit_cost: 10.0
                    fifo_layer_date: '2023-01-01'
                    created_at: '2023-01-01T00:00:00Z'
                    updated_at: '2023-01-01T00:00:00Z'
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: inventory:read
      operationId: get-api-initial-inventory-id
    put:
      tags:
      - Initial Inventory
      summary: Update Initial Inventory
      description: 'Updates an existing initial inventory record.

        Authentication: Requires Bearer token.


        :::info[Required scope: `inventory:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                quantity:
                  type: integer
                unit_cost:
                  type: integer
              example:
                quantity: 250
                unit_cost: 11
      parameters:
      - name: id
        in: path
        schema:
          type: integer
        required: true
        description: Initial inventory record ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      quantity:
                        type: integer
                      unit_cost:
                        type: number
                      updated_at:
                        type: string
                  status:
                    type: string
                example:
                  data:
                    id: 1
                    quantity: 250
                    unit_cost: 11.0
                    updated_at: '2024-01-16T09:00:00Z'
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: inventory:write
      operationId: put-api-initial-inventory-id
    delete:
      tags:
      - Initial Inventory
      summary: Delete Initial Inventory
      description: 'Deletes an initial inventory record and reverses its associated
        FIFO layers.

        Authentication: Requires Bearer token.


        :::info[Required scope: `inventory:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: id
        in: path
        schema:
          type: integer
        required: true
        description: Initial inventory record ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  status:
                    type: string
                example:
                  message: Initial inventory record deleted successfully.
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: inventory:write
      operationId: delete-api-initial-inventory-id
  /api/cost-entries:
    get:
      tags:
      - Costing
      summary: List Cost Entries
      description: 'Returns a paginated list of cost entries, newest cost date first
        by default.


        :::info[Required scope: `purchase-orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Allowed sorts: id, description, reference_number, status, cost_date, amount,
        amount_in_tenant_currency, created_at, updated_at, supplier_name, cost_entry_type_name,
        allocations_total, unallocated_total. Prefix with - for descending.


        filter[search] matches description, reference number, ID, supplier name and
        cost entry type name. filter[source.is]=bill returns only entries created
        from bills; filter[source.is_not]=bill returns manual entries. filter[has_amortization.is]=true/false
        filters by presence of an amortization schedule.


        Column filters accept operator suffixes in the form filter[column.operator],
        e.g. filter[name.contains]=main or filter[created_at.between]=2026-01-01,2026-06-30.
        Text operators: is, is_not, contains, does_not_contain, starts_with, ends_with,
        is_empty, is_not_empty, is_one_of. Numeric operators: is, is_not, greater_than,
        greater_than_or_equal, less_than, less_than_or_equal, between, is_empty, is_not_empty.
        Date operators: is, is_not, on_or_before, on_or_after, between, is_empty,
        is_not_empty.


        The response includes an unfiltered_total field with the total number of cost
        entries regardless of filters.


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        supplier_id:
                          type: integer
                        supplier_name:
                          type: string
                        reference_number:
                          type: string
                        description:
                          type: string
                        cost_date:
                          type: string
                        amount:
                          type: number
                        amount_in_tenant_currency:
                          type: number
                        currency_id:
                          type: integer
                        currency_code:
                          type: string
                        currency_rate:
                          type: number
                        nominal_code_id:
                          type: integer
                        nominal_code_name:
                          type: string
                        cost_entry_type_id:
                          type: integer
                        cost_entry_type:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        status:
                          type: string
                        bill_id:
                          type: string
                          nullable: true
                        bill_line_id:
                          type: string
                          nullable: true
                        source_type:
                          type: string
                        source_description:
                          type: string
                          nullable: true
                        source_link_type:
                          type: string
                          nullable: true
                        source_id:
                          type: string
                          nullable: true
                        source_label:
                          type: string
                          nullable: true
                        source_period:
                          type: string
                          nullable: true
                        reconciliation:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                        updated_at:
                          type: string
                        totals:
                          type: object
                          properties:
                            allocated:
                              type: number
                            unallocated:
                              type: number
                            is_fully_allocated:
                              type: boolean
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                  unfiltered_total:
                    type: integer
                example:
                  data:
                  - id: 42
                    supplier_id: 3
                    supplier_name: Global Freight Co
                    reference_number: FRT-2026-0142
                    description: June ocean freight
                    cost_date: '2026-06-01'
                    amount: 2500.0
                    amount_in_tenant_currency: 2500.0
                    currency_id: 1
                    currency_code: USD
                    currency_rate: 1.0
                    nominal_code_id: 15
                    nominal_code_name: Freight & Duty
                    cost_entry_type_id: 2
                    cost_entry_type:
                      id: 2
                      name: Freight
                    status: pending_allocation
                    bill_id: null
                    bill_line_id: null
                    source_type: manual
                    source_description: null
                    source_link_type: null
                    source_id: null
                    source_label: null
                    source_period: null
                    reconciliation: null
                    created_at: '2026-06-01T10:00:00.000000Z'
                    updated_at: '2026-06-01T10:00:00.000000Z'
                    totals:
                      allocated: 1000.0
                      unallocated: 1500.0
                      is_fully_allocated: false
                  current_page: 1
                  last_page: 1
                  per_page: 15
                  total: 1
                  from: 1
                  to: 1
                  unfiltered_total: 128
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: purchase-orders:read
      operationId: get-api-cost-entries
    post:
      tags:
      - Costing
      summary: Create Cost Entry
      description: 'Creates a cost entry.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Required fields: description, cost_date (Y-m-d), amount (in the entry''s currency)
        and amount_in_tenant_currency.


        Optional fields: cost_entry_type_id, status (draft, pending_allocation, partially_allocated
        or allocated; default draft), supplier_id, reference_number, currency_id,
        currency_rate, nominal_code_id, bill_id and bill_line_id (link the entry to
        a bill), source_type, source_id and source_period (identify an originating
        document and the period the cost applies to).


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                description:
                  type: string
                cost_date:
                  type: string
                amount:
                  type: integer
                amount_in_tenant_currency:
                  type: integer
                cost_entry_type_id:
                  type: integer
                status:
                  type: string
                supplier_id:
                  type: integer
                reference_number:
                  type: string
                currency_id:
                  type: integer
                currency_rate:
                  type: integer
                nominal_code_id:
                  type: integer
              example:
                description: June ocean freight
                cost_date: '2026-06-01'
                amount: 2500
                amount_in_tenant_currency: 2500
                cost_entry_type_id: 2
                status: pending_allocation
                supplier_id: 3
                reference_number: FRT-2026-0142
                currency_id: 1
                currency_rate: 1
                nominal_code_id: 15
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      supplier_id:
                        type: integer
                      supplier_name:
                        type: string
                      reference_number:
                        type: string
                      description:
                        type: string
                      cost_date:
                        type: string
                      amount:
                        type: number
                      amount_in_tenant_currency:
                        type: number
                      currency_id:
                        type: integer
                      currency_code:
                        type: string
                      currency_rate:
                        type: number
                      nominal_code_id:
                        type: integer
                      nominal_code_name:
                        type: string
                      cost_entry_type_id:
                        type: integer
                      cost_entry_type:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      status:
                        type: string
                      bill_id:
                        type: string
                        nullable: true
                      bill_line_id:
                        type: string
                        nullable: true
                      source_type:
                        type: string
                      source_description:
                        type: string
                        nullable: true
                      source_link_type:
                        type: string
                        nullable: true
                      source_id:
                        type: string
                        nullable: true
                      source_label:
                        type: string
                        nullable: true
                      source_period:
                        type: string
                        nullable: true
                      reconciliation:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      totals:
                        type: object
                        properties:
                          allocated:
                            type: number
                          unallocated:
                            type: number
                          is_fully_allocated:
                            type: boolean
                example:
                  data:
                    id: 42
                    supplier_id: 3
                    supplier_name: Global Freight Co
                    reference_number: FRT-2026-0142
                    description: June ocean freight
                    cost_date: '2026-06-01'
                    amount: 2500.0
                    amount_in_tenant_currency: 2500.0
                    currency_id: 1
                    currency_code: USD
                    currency_rate: 1.0
                    nominal_code_id: 15
                    nominal_code_name: Freight & Duty
                    cost_entry_type_id: 2
                    cost_entry_type:
                      id: 2
                      name: Freight
                    status: pending_allocation
                    bill_id: null
                    bill_line_id: null
                    source_type: manual
                    source_description: null
                    source_link_type: null
                    source_id: null
                    source_label: null
                    source_period: null
                    reconciliation: null
                    created_at: '2026-06-01T10:00:00.000000Z'
                    updated_at: '2026-06-01T10:00:00.000000Z'
                    totals:
                      allocated: 1000.0
                      unallocated: 1500.0
                      is_fully_allocated: false
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      cost_date:
                        type: array
                        items:
                          type: string
                example:
                  message: The given data was invalid.
                  errors:
                    cost_date:
                    - The cost date field is required.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: purchase-orders:write
      operationId: post-api-cost-entries
  /api/cost-entries/{costEntry}:
    get:
      tags:
      - Costing
      summary: Get Cost Entry
      description: 'Returns a cost entry with its allocations and amortization schedule
        (including periods and the resolved allocation target).


        :::info[Required scope: `purchase-orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        The totals object reports the allocated amount, the remaining unallocated
        amount and whether the entry is fully allocated. For entries auto-generated
        from a source document, source_type is "source" and the source_* fields identify
        the origin record; manual entries have source_type "manual". The reconciliation
        field holds settlement reconciliation results ({actual_amount, variance, variance_pct,
        settlement_report_ids, reconciled_at}) or null.


        Authentication: Requires Bearer token.'
      parameters:
      - name: costEntry
        in: path
        schema:
          type: integer
        required: true
        description: Cost entry ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      supplier_id:
                        type: integer
                      supplier_name:
                        type: string
                      reference_number:
                        type: string
                      description:
                        type: string
                      cost_date:
                        type: string
                      amount:
                        type: number
                      amount_in_tenant_currency:
                        type: number
                      currency_id:
                        type: integer
                      currency_code:
                        type: string
                      currency_rate:
                        type: number
                      nominal_code_id:
                        type: integer
                      nominal_code_name:
                        type: string
                      cost_entry_type_id:
                        type: integer
                      cost_entry_type:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      status:
                        type: string
                      bill_id:
                        type: string
                        nullable: true
                      bill_line_id:
                        type: string
                        nullable: true
                      source_type:
                        type: string
                      source_description:
                        type: string
                        nullable: true
                      source_link_type:
                        type: string
                        nullable: true
                      source_id:
                        type: string
                        nullable: true
                      source_label:
                        type: string
                        nullable: true
                      source_period:
                        type: string
                        nullable: true
                      reconciliation:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      totals:
                        type: object
                        properties:
                          allocated:
                            type: number
                          unallocated:
                            type: number
                          is_fully_allocated:
                            type: boolean
                      allocations:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            cost_entry_id:
                              type: integer
                            allocatable_type:
                              type: string
                            allocatable_type_label:
                              type: string
                            allocatable_id:
                              type: integer
                            allocatable:
                              type: object
                              properties:
                                id:
                                  type: integer
                                name:
                                  type: string
                                sku:
                                  type: string
                            allocation_date:
                              type: string
                            period_start:
                              type: string
                            period_end:
                              type: string
                            amount:
                              type: number
                            amount_in_tenant_currency:
                              type: number
                            proration_strategy:
                              type: string
                            proration_weight:
                              type: string
                              nullable: true
                            amortization_period_id:
                              type: string
                              nullable: true
                            is_amortized:
                              type: boolean
                            created_at:
                              type: string
                            updated_at:
                              type: string
                      amortization_schedule:
                        type: object
                        properties:
                          id:
                            type: integer
                          cost_entry_id:
                            type: integer
                          start_date:
                            type: string
                          end_date:
                            type: string
                          total_periods:
                            type: integer
                          frequency:
                            type: string
                          method:
                            type: string
                          total_amount:
                            type: number
                          amount_per_period:
                            type: number
                          is_fully_processed:
                            type: boolean
                          pending_periods_count:
                            type: integer
                          processed_periods_count:
                            type: integer
                          allocation_config:
                            type: object
                            properties:
                              allocatable_type:
                                type: string
                              allocatable_id:
                                type: integer
                              allocatable_name:
                                type: string
                              proration_strategy:
                                type: string
                          created_at:
                            type: string
                          updated_at:
                            type: string
                          periods:
                            type: array
                            items:
                              type: object
                              properties:
                                id:
                                  type: integer
                                period_number:
                                  type: integer
                                period_start:
                                  type: string
                                period_end:
                                  type: string
                                amount:
                                  type: number
                                is_processed:
                                  type: boolean
                example:
                  data:
                    id: 42
                    supplier_id: 3
                    supplier_name: Global Freight Co
                    reference_number: FRT-2026-0142
                    description: June ocean freight
                    cost_date: '2026-06-01'
                    amount: 2500.0
                    amount_in_tenant_currency: 2500.0
                    currency_id: 1
                    currency_code: USD
                    currency_rate: 1.0
                    nominal_code_id: 15
                    nominal_code_name: Freight & Duty
                    cost_entry_type_id: 2
                    cost_entry_type:
                      id: 2
                      name: Freight
                    status: pending_allocation
                    bill_id: null
                    bill_line_id: null
                    source_type: manual
                    source_description: null
                    source_link_type: null
                    source_id: null
                    source_label: null
                    source_period: null
                    reconciliation: null
                    created_at: '2026-06-01T10:00:00.000000Z'
                    updated_at: '2026-06-01T10:00:00.000000Z'
                    totals:
                      allocated: 1000.0
                      unallocated: 1500.0
                      is_fully_allocated: false
                    allocations:
                    - id: 88
                      cost_entry_id: 42
                      allocatable_type: App\Models\Product
                      allocatable_type_label: Product
                      allocatable_id: 101
                      allocatable:
                        id: 101
                        name: Widget
                        sku: WIDGET-001
                      allocation_date: '2026-06-01'
                      period_start: '2026-06-01'
                      period_end: '2026-06-30'
                      amount: 1000.0
                      amount_in_tenant_currency: 1000.0
                      proration_strategy: specific_line
                      proration_weight: null
                      amortization_period_id: null
                      is_amortized: false
                      created_at: '2026-06-01T10:05:00.000000Z'
                      updated_at: '2026-06-01T10:05:00.000000Z'
                    amortization_schedule:
                      id: 7
                      cost_entry_id: 42
                      start_date: '2026-07-01'
                      end_date: '2027-06-30'
                      total_periods: 12
                      frequency: monthly
                      method: straight_line
                      total_amount: 2500.0
                      amount_per_period: 208.33
                      is_fully_processed: false
                      pending_periods_count: 12
                      processed_periods_count: 0
                      allocation_config:
                        allocatable_type: product
                        allocatable_id: 101
                        allocatable_name: Widget
                        proration_strategy: specific_line
                      created_at: '2026-06-01T10:10:00.000000Z'
                      updated_at: '2026-06-01T10:10:00.000000Z'
                      periods:
                      - id: 601
                        period_number: 1
                        period_start: '2026-07-01'
                        period_end: '2026-07-31'
                        amount: 208.33
                        is_processed: false
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:read
      operationId: get-api-cost-entries-costentry
    put:
      tags:
      - Costing
      summary: Update Cost Entry
      description: 'Updates a cost entry. All fields are optional; only provided fields
        are changed.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Fields: description, cost_date, amount, amount_in_tenant_currency, cost_entry_type_id,
        status (draft, pending_allocation, partially_allocated, allocated), supplier_id,
        reference_number, currency_id, currency_rate and nominal_code_id.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                description:
                  type: string
                amount:
                  type: integer
                amount_in_tenant_currency:
                  type: integer
              example:
                description: June ocean freight (revised)
                amount: 2650
                amount_in_tenant_currency: 2650
      parameters:
      - name: costEntry
        in: path
        schema:
          type: integer
        required: true
        description: Cost entry ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      supplier_id:
                        type: integer
                      supplier_name:
                        type: string
                      reference_number:
                        type: string
                      description:
                        type: string
                      cost_date:
                        type: string
                      amount:
                        type: number
                      amount_in_tenant_currency:
                        type: number
                      currency_id:
                        type: integer
                      currency_code:
                        type: string
                      currency_rate:
                        type: number
                      nominal_code_id:
                        type: integer
                      nominal_code_name:
                        type: string
                      cost_entry_type_id:
                        type: integer
                      cost_entry_type:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      status:
                        type: string
                      bill_id:
                        type: string
                        nullable: true
                      bill_line_id:
                        type: string
                        nullable: true
                      source_type:
                        type: string
                      source_description:
                        type: string
                        nullable: true
                      source_link_type:
                        type: string
                        nullable: true
                      source_id:
                        type: string
                        nullable: true
                      source_label:
                        type: string
                        nullable: true
                      source_period:
                        type: string
                        nullable: true
                      reconciliation:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      totals:
                        type: object
                        properties:
                          allocated:
                            type: number
                          unallocated:
                            type: number
                          is_fully_allocated:
                            type: boolean
                example:
                  data:
                    id: 42
                    supplier_id: 3
                    supplier_name: Global Freight Co
                    reference_number: FRT-2026-0142
                    description: June ocean freight
                    cost_date: '2026-06-01'
                    amount: 2500.0
                    amount_in_tenant_currency: 2500.0
                    currency_id: 1
                    currency_code: USD
                    currency_rate: 1.0
                    nominal_code_id: 15
                    nominal_code_name: Freight & Duty
                    cost_entry_type_id: 2
                    cost_entry_type:
                      id: 2
                      name: Freight
                    status: pending_allocation
                    bill_id: null
                    bill_line_id: null
                    source_type: manual
                    source_description: null
                    source_link_type: null
                    source_id: null
                    source_label: null
                    source_period: null
                    reconciliation: null
                    created_at: '2026-06-01T10:00:00.000000Z'
                    updated_at: '2026-06-01T10:00:00.000000Z'
                    totals:
                      allocated: 1000.0
                      unallocated: 1500.0
                      is_fully_allocated: false
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: purchase-orders:write
      operationId: put-api-cost-entries-costentry
    delete:
      tags:
      - Costing
      summary: Delete Cost Entry
      description: 'Deletes a cost entry and its allocations.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: costEntry
        in: path
        schema:
          type: integer
        required: true
        description: Cost entry ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Cost entry deleted successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:write
      operationId: delete-api-cost-entries-costentry
  /api/cost-entries/{costEntry}/allocations:
    get:
      tags:
      - Costing
      summary: List Cost Entry Allocations
      description: 'Returns all allocations recorded against the cost entry, including
        the allocated target (product, brand, supplier, sales channel or sales order
        line) and any amortization linkage.


        :::info[Required scope: `purchase-orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: costEntry
        in: path
        schema:
          type: integer
        required: true
        description: Cost entry ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        cost_entry_id:
                          type: integer
                        allocatable_type:
                          type: string
                        allocatable_type_label:
                          type: string
                        allocatable_id:
                          type: integer
                        allocatable:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            sku:
                              type: string
                        allocation_date:
                          type: string
                        period_start:
                          type: string
                        period_end:
                          type: string
                        amount:
                          type: number
                        amount_in_tenant_currency:
                          type: number
                        proration_strategy:
                          type: string
                        proration_weight:
                          type: string
                          nullable: true
                        amortization_period_id:
                          type: string
                          nullable: true
                        is_amortized:
                          type: boolean
                        created_at:
                          type: string
                        updated_at:
                          type: string
                example:
                  data:
                  - id: 88
                    cost_entry_id: 42
                    allocatable_type: App\Models\Product
                    allocatable_type_label: Product
                    allocatable_id: 101
                    allocatable:
                      id: 101
                      name: Widget
                      sku: WIDGET-001
                    allocation_date: '2026-06-01'
                    period_start: '2026-06-01'
                    period_end: '2026-06-30'
                    amount: 1000.0
                    amount_in_tenant_currency: 1000.0
                    proration_strategy: specific_line
                    proration_weight: null
                    amortization_period_id: null
                    is_amortized: false
                    created_at: '2026-06-01T10:05:00.000000Z'
                    updated_at: '2026-06-01T10:05:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:read
      operationId: get-api-cost-entries-costentry-allocations
    delete:
      tags:
      - Costing
      summary: Delete Cost Entry Allocations
      description: 'Deletes all allocations for the cost entry, returning its full
        amount to unallocated.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: costEntry
        in: path
        schema:
          type: integer
        required: true
        description: Cost entry ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Deleted 3 allocations
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:write
      operationId: delete-api-cost-entries-costentry-allocations
  /api/cost-entries/{costEntry}/amortization-schedule:
    post:
      tags:
      - Costing
      summary: Create Amortization Schedule
      description: 'Creates an amortization schedule for a cost entry, spreading its
        amount across future periods. Each period, when processed, allocates its share
        to the configured target. A cost entry can have only one schedule.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Required fields: start_date (Y-m-d), periods (1-120), frequency (daily, weekly,
        monthly, quarterly, annually), method (straight_line, front_loaded, back_loaded),
        allocatable_type (product, brand, supplier or sales_channel) and allocatable_id.


        Optional: proration_strategy (default specific_line).


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                start_date:
                  type: string
                periods:
                  type: integer
                frequency:
                  type: string
                method:
                  type: string
                allocatable_type:
                  type: string
                allocatable_id:
                  type: integer
                proration_strategy:
                  type: string
              example:
                start_date: '2026-07-01'
                periods: 12
                frequency: monthly
                method: straight_line
                allocatable_type: product
                allocatable_id: 101
                proration_strategy: specific_line
      parameters:
      - name: costEntry
        in: path
        schema:
          type: integer
        required: true
        description: Cost entry ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      cost_entry_id:
                        type: integer
                      start_date:
                        type: string
                      end_date:
                        type: string
                      total_periods:
                        type: integer
                      frequency:
                        type: string
                      method:
                        type: string
                      total_amount:
                        type: number
                      amount_per_period:
                        type: number
                      is_fully_processed:
                        type: boolean
                      pending_periods_count:
                        type: integer
                      processed_periods_count:
                        type: integer
                      allocation_config:
                        type: object
                        properties:
                          allocatable_type:
                            type: string
                          allocatable_id:
                            type: integer
                          allocatable_name:
                            type: string
                          proration_strategy:
                            type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      periods:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            period_number:
                              type: integer
                            period_start:
                              type: string
                            period_end:
                              type: string
                            amount:
                              type: number
                            is_processed:
                              type: boolean
                example:
                  data:
                    id: 7
                    cost_entry_id: 42
                    start_date: '2026-07-01'
                    end_date: '2027-06-30'
                    total_periods: 12
                    frequency: monthly
                    method: straight_line
                    total_amount: 2500.0
                    amount_per_period: 208.33
                    is_fully_processed: false
                    pending_periods_count: 12
                    processed_periods_count: 0
                    allocation_config:
                      allocatable_type: product
                      allocatable_id: 101
                      allocatable_name: Widget
                      proration_strategy: specific_line
                    created_at: '2026-06-01T10:10:00.000000Z'
                    updated_at: '2026-06-01T10:10:00.000000Z'
                    periods:
                    - id: 601
                      period_number: 1
                      period_start: '2026-07-01'
                      period_end: '2026-07-31'
                      amount: 208.33
                      is_processed: false
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Cost entry already has an amortization schedule
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:write
      operationId: post-api-cost-entries-costentry-amortization-schedule
  /api/cost-allocations:
    get:
      tags:
      - Costing
      summary: List Cost Allocations
      description: 'Returns a paginated list of cost allocations. A cost allocation
        assigns part (or all) of a cost entry''s amount to a target entity - a product,
        brand, supplier, sales channel or sales order line - for landed cost and profitability
        reporting.


        :::info[Required scope: `purchase-orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Each allocation includes the target type, a human-readable type label, a summary
        of the target entity (allocatable), the allocated amount in the cost entry''s
        currency and in the account currency (amount_in_tenant_currency), the proration
        strategy that produced it, and whether it was generated by an amortization
        schedule (is_amortized).


        Filtering uses plain query parameters (not the filter[...] syntax used elsewhere
        in this API): cost_entry_id, allocatable_type, allocatable_id, date_from,
        date_to and proration_strategy - see each parameter''s description. Results
        are always sorted by allocation date, newest first; there is no sort parameter.


        Pagination: page (default 1) and per_page (default 15, max 100).


        Authentication: Requires Bearer token. Scope: `purchase-orders` (read/write).'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        cost_entry_id:
                          type: integer
                        allocatable_type:
                          type: string
                        allocatable_type_label:
                          type: string
                        allocatable_id:
                          type: integer
                        allocatable:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            sku:
                              type: string
                        allocation_date:
                          type: string
                        period_start:
                          type: string
                        period_end:
                          type: string
                        amount:
                          type: number
                        amount_in_tenant_currency:
                          type: number
                        proration_strategy:
                          type: string
                        proration_weight:
                          type: string
                          nullable: true
                        amortization_period_id:
                          type: string
                          nullable: true
                        is_amortized:
                          type: boolean
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                    items:
                      type: object
                      properties:
                        url:
                          type: string
                          nullable: true
                        label:
                          type: string
                        active:
                          type: boolean
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 88
                    cost_entry_id: 42
                    allocatable_type: App\Models\Product
                    allocatable_type_label: Product
                    allocatable_id: 101
                    allocatable:
                      id: 101
                      name: Widget
                      sku: WIDGET-001
                    allocation_date: '2026-06-01'
                    period_start: '2026-06-01'
                    period_end: '2026-06-30'
                    amount: 1000.0
                    amount_in_tenant_currency: 1000.0
                    proration_strategy: manual
                    proration_weight: null
                    amortization_period_id: null
                    is_amortized: false
                    created_at: '2026-06-01T10:05:00.000000Z'
                    updated_at: '2026-06-01T10:05:00.000000Z'
                  - id: 91
                    cost_entry_id: 45
                    allocatable_type: App\Models\Supplier
                    allocatable_type_label: Supplier
                    allocatable_id: 3
                    allocatable:
                      id: 3
                      name: Global Freight Co
                    allocation_date: '2026-05-15'
                    period_start: null
                    period_end: null
                    amount: 450.0
                    amount_in_tenant_currency: 450.0
                    proration_strategy: cost_based
                    proration_weight: 0.45
                    amortization_period_id: null
                    is_amortized: false
                    created_at: '2026-05-15T08:20:00.000000Z'
                    updated_at: '2026-05-15T08:20:00.000000Z'
                  current_page: 1
                  first_page_url: '{{protocol}}{{domain}}/api/cost-allocations?page=1'
                  from: 1
                  last_page: 1
                  last_page_url: '{{protocol}}{{domain}}/api/cost-allocations?page=1'
                  links:
                  - url: null
                    label: '&laquo; Previous'
                    active: false
                  - url: '{{protocol}}{{domain}}/api/cost-allocations?page=1'
                    label: '1'
                    active: true
                  - url: null
                    label: Next &raquo;
                    active: false
                  next_page_url: null
                  path: '{{protocol}}{{domain}}/api/cost-allocations'
                  per_page: 15
                  prev_page_url: null
                  to: 2
                  total: 2
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: purchase-orders:read
      operationId: get-api-cost-allocations
    post:
      tags:
      - Costing
      summary: Create Cost Allocation
      description: 'Creates a single cost allocation directly, assigning part (or
        all) of a cost entry''s amount to a target entity. This is the low-level create:
        the caller supplies both currency amounts and the proration metadata explicitly.
        For most integrations the allocate endpoints under /api/cost-entries/{cost_entry}/allocate/...
        are simpler - they compute the account-currency amount and proration weights
        automatically.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Fields:

        - cost_entry_id (required, integer): ID of the cost entry to allocate from.
        Unknown IDs return 404.

        - allocatable_type (required, string): fully qualified target type. One of:
        App\Models\Product, App\Models\ProductBrand, App\Models\Supplier, App\Models\SalesChannel,
        App\Models\SalesOrderLine.

        - allocatable_id (required, integer): ID of the target entity.

        - allocation_date (required, date YYYY-MM-DD): ledger date of the allocation.

        - amount (required, number): amount to allocate, in the cost entry''s currency.

        - amount_in_tenant_currency (required, number): the same amount expressed
        in the account currency.

        - proration_strategy (required, string): one of revenue_based, cost_based,
        weight_based, volume_based, quantity_based, specific_line, manual. Use manual
        for a direct allocation.

        - period_start, period_end (optional, date YYYY-MM-DD): the period the cost
        applies to.

        - proration_weight (optional, number): the weight used when the allocation
        is part of a prorated distribution.

        - amortization_period_id (optional, integer): links the allocation to an amortization
        period. Leave null for manual allocations - amortization-linked allocations
        are normally created by the amortization processor.


        The allocated amount is validated against the cost entry''s remaining unallocated
        amount (taking into account amounts reserved by a pending amortization schedule);
        exceeding it returns 422. Creating an allocation also recalculates the parent
        cost entry''s allocation status (pending_allocation, partially_allocated or
        allocated).


        Note that this endpoint returns HTTP 200 (not 201) on success.


        Authentication: Requires Bearer token. Scope: `purchase-orders` (read/write).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                cost_entry_id:
                  type: integer
                allocatable_type:
                  type: string
                allocatable_id:
                  type: integer
                allocation_date:
                  type: string
                amount:
                  type: integer
                amount_in_tenant_currency:
                  type: integer
                proration_strategy:
                  type: string
                period_start:
                  type: string
                period_end:
                  type: string
                proration_weight:
                  type: string
                  nullable: true
                amortization_period_id:
                  type: string
                  nullable: true
              example:
                cost_entry_id: 42
                allocatable_type: App\Models\Product
                allocatable_id: 101
                allocation_date: '2026-06-01'
                amount: 1000
                amount_in_tenant_currency: 1000
                proration_strategy: manual
                period_start: '2026-06-01'
                period_end: '2026-06-30'
                proration_weight: null
                amortization_period_id: null
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      cost_entry_id:
                        type: integer
                      allocatable_type:
                        type: string
                      allocatable_type_label:
                        type: string
                      allocatable_id:
                        type: integer
                      allocatable:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          sku:
                            type: string
                      allocation_date:
                        type: string
                      period_start:
                        type: string
                      period_end:
                        type: string
                      amount:
                        type: number
                      amount_in_tenant_currency:
                        type: number
                      proration_strategy:
                        type: string
                      proration_weight:
                        type: string
                        nullable: true
                      amortization_period_id:
                        type: string
                        nullable: true
                      is_amortized:
                        type: boolean
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 88
                    cost_entry_id: 42
                    allocatable_type: App\Models\Product
                    allocatable_type_label: Product
                    allocatable_id: 101
                    allocatable:
                      id: 101
                      name: Widget
                      sku: WIDGET-001
                    allocation_date: '2026-06-01'
                    period_start: '2026-06-01'
                    period_end: '2026-06-30'
                    amount: 1000.0
                    amount_in_tenant_currency: 1000.0
                    proration_strategy: manual
                    proration_weight: null
                    amortization_period_id: null
                    is_amortized: false
                    created_at: '2026-06-01T10:05:00.000000Z'
                    updated_at: '2026-06-01T10:05:00.000000Z'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 422 Unprocessable Entity (amount exceeds unallocated)
                  value:
                    message: Allocation amount (3000) exceeds remaining unallocated
                      amount (1500)
                example-1:
                  summary: 422 Unprocessable Entity (validation)
                  value:
                    message: The cost entry id field is required.
                    errors:
                      cost_entry_id:
                      - The cost entry id field is required.
                      proration_strategy:
                      - The selected proration strategy is invalid.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: purchase-orders:write
      operationId: post-api-cost-allocations
  /api/cost-allocations/{costAllocation}:
    get:
      tags:
      - Costing
      summary: Get Cost Allocation
      description: 'Returns a single cost allocation by ID, including a summary of
        the target entity (allocatable). The summary fields depend on the target type:
        products include name and sku; brands, suppliers and sales channels include
        name; sales order lines include sales_order_id, product_id, product_name and
        quantity. amount is in the parent cost entry''s currency and amount_in_tenant_currency
        is the equivalent in the account currency.


        :::info[Required scope: `purchase-orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token. Scope: `purchase-orders` (read/write).'
      parameters:
      - name: costAllocation
        in: path
        schema:
          type: integer
        required: true
        description: Cost allocation ID
        example: '88'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      cost_entry_id:
                        type: integer
                      allocatable_type:
                        type: string
                      allocatable_type_label:
                        type: string
                      allocatable_id:
                        type: integer
                      allocatable:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          sku:
                            type: string
                      allocation_date:
                        type: string
                      period_start:
                        type: string
                      period_end:
                        type: string
                      amount:
                        type: number
                      amount_in_tenant_currency:
                        type: number
                      proration_strategy:
                        type: string
                      proration_weight:
                        type: string
                        nullable: true
                      amortization_period_id:
                        type: string
                        nullable: true
                      is_amortized:
                        type: boolean
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 88
                    cost_entry_id: 42
                    allocatable_type: App\Models\Product
                    allocatable_type_label: Product
                    allocatable_id: 101
                    allocatable:
                      id: 101
                      name: Widget
                      sku: WIDGET-001
                    allocation_date: '2026-06-01'
                    period_start: '2026-06-01'
                    period_end: '2026-06-30'
                    amount: 1000.0
                    amount_in_tenant_currency: 1000.0
                    proration_strategy: manual
                    proration_weight: null
                    amortization_period_id: null
                    is_amortized: false
                    created_at: '2026-06-01T10:05:00.000000Z'
                    updated_at: '2026-06-01T10:05:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:read
      operationId: get-api-cost-allocations-costallocation
    delete:
      tags:
      - Costing
      summary: Delete Cost Allocation
      description: 'Deletes a cost allocation and recalculates the parent cost entry''s
        allocation status, freeing the amount to be allocated again.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Allocations that were created by an amortization schedule cannot be deleted
        individually - the request fails with HTTP 422. Delete the amortization schedule
        instead (DELETE /api/amortization-schedules/{amortization_schedule}).


        Authentication: Requires Bearer token. Scope: `purchase-orders` (read/write).'
      parameters:
      - name: costAllocation
        in: path
        schema:
          type: integer
        required: true
        description: Cost allocation ID
        example: '88'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Allocation deleted successfully
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: This allocation was created by an amortization schedule.
                    Delete the amortization schedule instead.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:write
      operationId: delete-api-cost-allocations-costallocation
  /api/cost-entries/{costEntry}/allocate/product/{product}:
    post:
      tags:
      - Costing
      summary: Allocate Cost Entry to Product
      description: 'Allocates part of a cost entry to a specific product. The allocation
        feeds into landed cost and profitability reporting.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Fields: amount (required, the amount to allocate), allocation_date (the ledger
        date for the allocation, defaults to today), period_start and period_end (optional
        period the cost applies to).


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                amount:
                  type: integer
                allocation_date:
                  type: string
                period_start:
                  type: string
                period_end:
                  type: string
              example:
                amount: 1000
                allocation_date: '2026-06-15'
                period_start: '2026-06-01'
                period_end: '2026-06-30'
      parameters:
      - name: costEntry
        in: path
        schema:
          type: integer
        required: true
        description: Cost entry ID
        example: '42'
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: Product ID
        example: '101'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      cost_entry_id:
                        type: integer
                      allocatable_type:
                        type: string
                      allocatable_type_label:
                        type: string
                      allocatable_id:
                        type: integer
                      allocatable:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          sku:
                            type: string
                      allocation_date:
                        type: string
                      period_start:
                        type: string
                      period_end:
                        type: string
                      amount:
                        type: number
                      amount_in_tenant_currency:
                        type: number
                      proration_strategy:
                        type: string
                      proration_weight:
                        type: string
                        nullable: true
                      amortization_period_id:
                        type: string
                        nullable: true
                      is_amortized:
                        type: boolean
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 88
                    cost_entry_id: 42
                    allocatable_type: App\Models\Product
                    allocatable_type_label: Product
                    allocatable_id: 101
                    allocatable:
                      id: 101
                      name: Widget
                      sku: WIDGET-001
                    allocation_date: '2026-06-01'
                    period_start: '2026-06-01'
                    period_end: '2026-06-30'
                    amount: 1000.0
                    amount_in_tenant_currency: 1000.0
                    proration_strategy: specific_line
                    proration_weight: null
                    amortization_period_id: null
                    is_amortized: false
                    created_at: '2026-06-01T10:05:00.000000Z'
                    updated_at: '2026-06-01T10:05:00.000000Z'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Allocation amount exceeds the cost entry's unallocated
                    amount
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:write
      operationId: post-api-cost-entries-costentry-allocate-product-product
  /api/cost-entries/{costEntry}/allocate/brand/{brand}:
    post:
      tags:
      - Costing
      summary: Allocate Cost Entry to Brand
      description: 'Allocates part of a cost entry to a product brand.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Fields: amount (required, the amount to allocate), allocation_date (the ledger
        date for the allocation, defaults to today), period_start and period_end (optional
        period the cost applies to).


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                amount:
                  type: integer
                allocation_date:
                  type: string
              example:
                amount: 500
                allocation_date: '2026-06-15'
      parameters:
      - name: costEntry
        in: path
        schema:
          type: integer
        required: true
        description: Cost entry ID
        example: '42'
      - name: brand
        in: path
        schema:
          type: integer
        required: true
        description: Product brand ID
        example: '7'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      cost_entry_id:
                        type: integer
                      allocatable_type:
                        type: string
                      allocatable_type_label:
                        type: string
                      allocatable_id:
                        type: integer
                      allocatable:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          sku:
                            type: string
                      allocation_date:
                        type: string
                      period_start:
                        type: string
                      period_end:
                        type: string
                      amount:
                        type: number
                      amount_in_tenant_currency:
                        type: number
                      proration_strategy:
                        type: string
                      proration_weight:
                        type: string
                        nullable: true
                      amortization_period_id:
                        type: string
                        nullable: true
                      is_amortized:
                        type: boolean
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 88
                    cost_entry_id: 42
                    allocatable_type: App\Models\Product
                    allocatable_type_label: Product
                    allocatable_id: 101
                    allocatable:
                      id: 101
                      name: Widget
                      sku: WIDGET-001
                    allocation_date: '2026-06-01'
                    period_start: '2026-06-01'
                    period_end: '2026-06-30'
                    amount: 1000.0
                    amount_in_tenant_currency: 1000.0
                    proration_strategy: specific_line
                    proration_weight: null
                    amortization_period_id: null
                    is_amortized: false
                    created_at: '2026-06-01T10:05:00.000000Z'
                    updated_at: '2026-06-01T10:05:00.000000Z'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Allocation amount exceeds the cost entry's unallocated
                    amount
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:write
      operationId: post-api-cost-entries-costentry-allocate-brand-brand
  /api/cost-entries/{costEntry}/allocate/supplier/{supplier}:
    post:
      tags:
      - Costing
      summary: Allocate Cost Entry to Supplier
      description: 'Allocates part of a cost entry to a supplier.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Fields: amount (required, the amount to allocate), allocation_date (the ledger
        date for the allocation, defaults to today), period_start and period_end (optional
        period the cost applies to).


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                amount:
                  type: integer
                allocation_date:
                  type: string
              example:
                amount: 500
                allocation_date: '2026-06-15'
      parameters:
      - name: costEntry
        in: path
        schema:
          type: integer
        required: true
        description: Cost entry ID
        example: '42'
      - name: supplier
        in: path
        schema:
          type: integer
        required: true
        description: Supplier ID
        example: '3'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      cost_entry_id:
                        type: integer
                      allocatable_type:
                        type: string
                      allocatable_type_label:
                        type: string
                      allocatable_id:
                        type: integer
                      allocatable:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          sku:
                            type: string
                      allocation_date:
                        type: string
                      period_start:
                        type: string
                      period_end:
                        type: string
                      amount:
                        type: number
                      amount_in_tenant_currency:
                        type: number
                      proration_strategy:
                        type: string
                      proration_weight:
                        type: string
                        nullable: true
                      amortization_period_id:
                        type: string
                        nullable: true
                      is_amortized:
                        type: boolean
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 88
                    cost_entry_id: 42
                    allocatable_type: App\Models\Product
                    allocatable_type_label: Product
                    allocatable_id: 101
                    allocatable:
                      id: 101
                      name: Widget
                      sku: WIDGET-001
                    allocation_date: '2026-06-01'
                    period_start: '2026-06-01'
                    period_end: '2026-06-30'
                    amount: 1000.0
                    amount_in_tenant_currency: 1000.0
                    proration_strategy: specific_line
                    proration_weight: null
                    amortization_period_id: null
                    is_amortized: false
                    created_at: '2026-06-01T10:05:00.000000Z'
                    updated_at: '2026-06-01T10:05:00.000000Z'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Allocation amount exceeds the cost entry's unallocated
                    amount
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:write
      operationId: post-api-cost-entries-costentry-allocate-supplier-supplier
  /api/cost-entries/{costEntry}/allocate/sales-channel/{salesChannel}:
    post:
      tags:
      - Costing
      summary: Allocate Cost Entry to Sales Channel
      description: 'Allocates part of a cost entry to a sales channel.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Fields: amount (required, the amount to allocate), allocation_date (the ledger
        date for the allocation, defaults to today), period_start and period_end (optional
        period the cost applies to).


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                amount:
                  type: integer
                allocation_date:
                  type: string
              example:
                amount: 750
                allocation_date: '2026-06-15'
      parameters:
      - name: costEntry
        in: path
        schema:
          type: integer
        required: true
        description: Cost entry ID
        example: '42'
      - name: salesChannel
        in: path
        schema:
          type: integer
        required: true
        description: Sales channel ID
        example: '2'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      cost_entry_id:
                        type: integer
                      allocatable_type:
                        type: string
                      allocatable_type_label:
                        type: string
                      allocatable_id:
                        type: integer
                      allocatable:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          sku:
                            type: string
                      allocation_date:
                        type: string
                      period_start:
                        type: string
                      period_end:
                        type: string
                      amount:
                        type: number
                      amount_in_tenant_currency:
                        type: number
                      proration_strategy:
                        type: string
                      proration_weight:
                        type: string
                        nullable: true
                      amortization_period_id:
                        type: string
                        nullable: true
                      is_amortized:
                        type: boolean
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 88
                    cost_entry_id: 42
                    allocatable_type: App\Models\Product
                    allocatable_type_label: Product
                    allocatable_id: 101
                    allocatable:
                      id: 101
                      name: Widget
                      sku: WIDGET-001
                    allocation_date: '2026-06-01'
                    period_start: '2026-06-01'
                    period_end: '2026-06-30'
                    amount: 1000.0
                    amount_in_tenant_currency: 1000.0
                    proration_strategy: specific_line
                    proration_weight: null
                    amortization_period_id: null
                    is_amortized: false
                    created_at: '2026-06-01T10:05:00.000000Z'
                    updated_at: '2026-06-01T10:05:00.000000Z'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Allocation amount exceeds the cost entry's unallocated
                    amount
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:write
      operationId: post-api-cost-entries-costentry-allocate-sales-channel-saleschannel
  /api/cost-entries/{costEntry}/allocate/sales-order-line/{salesOrderLine}:
    post:
      tags:
      - Costing
      summary: Allocate Cost Entry to Sales Order Line
      description: 'Allocates part of a cost entry to a specific sales order line.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Fields: amount (required, the amount to allocate), allocation_date (the ledger
        date for the allocation, defaults to today), period_start and period_end (optional
        period the cost applies to).


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                amount:
                  type: integer
                allocation_date:
                  type: string
              example:
                amount: 120
                allocation_date: '2026-06-15'
      parameters:
      - name: costEntry
        in: path
        schema:
          type: integer
        required: true
        description: Cost entry ID
        example: '42'
      - name: salesOrderLine
        in: path
        schema:
          type: integer
        required: true
        description: Sales order line ID
        example: '5501'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      cost_entry_id:
                        type: integer
                      allocatable_type:
                        type: string
                      allocatable_type_label:
                        type: string
                      allocatable_id:
                        type: integer
                      allocatable:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          sku:
                            type: string
                      allocation_date:
                        type: string
                      period_start:
                        type: string
                      period_end:
                        type: string
                      amount:
                        type: number
                      amount_in_tenant_currency:
                        type: number
                      proration_strategy:
                        type: string
                      proration_weight:
                        type: string
                        nullable: true
                      amortization_period_id:
                        type: string
                        nullable: true
                      is_amortized:
                        type: boolean
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 88
                    cost_entry_id: 42
                    allocatable_type: App\Models\Product
                    allocatable_type_label: Product
                    allocatable_id: 101
                    allocatable:
                      id: 101
                      name: Widget
                      sku: WIDGET-001
                    allocation_date: '2026-06-01'
                    period_start: '2026-06-01'
                    period_end: '2026-06-30'
                    amount: 1000.0
                    amount_in_tenant_currency: 1000.0
                    proration_strategy: specific_line
                    proration_weight: null
                    amortization_period_id: null
                    is_amortized: false
                    created_at: '2026-06-01T10:05:00.000000Z'
                    updated_at: '2026-06-01T10:05:00.000000Z'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Allocation amount exceeds the cost entry's unallocated
                    amount
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:write
      operationId: post-api-cost-entries-costentry-allocate-sales-order-line-salesorderline
  /api/cost-entries/{costEntry}/allocate/proration:
    post:
      tags:
      - Costing
      summary: Allocate Cost Entry by Proration
      description: 'Allocates a cost entry across a custom list of products, splitting
        the amount by the chosen proration strategy.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Required fields: strategy (straight_line, front_loaded, back_loaded, revenue_based,
        cost_based, weight_based, volume_based, quantity_based, specific_line, manual)
        and items (array of {product_id, quantity, revenue, cost, weight, volume}
        - the strategy determines which measure drives each product''s share).


        Optional: amount (defaults to the entry''s unallocated amount), allocation_date
        (defaults to today), period_start, period_end.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                strategy:
                  type: string
                amount:
                  type: integer
                allocation_date:
                  type: string
                items:
                  type: array
                  items:
                    type: object
                    properties:
                      product_id:
                        type: integer
                      quantity:
                        type: integer
                      revenue:
                        type: integer
                      cost:
                        type: integer
                      weight:
                        type: integer
                      volume:
                        type: integer
              example:
                strategy: quantity_based
                amount: 1500
                allocation_date: '2026-06-15'
                items:
                - product_id: 101
                  quantity: 100
                  revenue: 0
                  cost: 0
                  weight: 0
                  volume: 0
                - product_id: 102
                  quantity: 50
                  revenue: 0
                  cost: 0
                  weight: 0
                  volume: 0
      parameters:
      - name: costEntry
        in: path
        schema:
          type: integer
        required: true
        description: Cost entry ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        cost_entry_id:
                          type: integer
                        allocatable_type:
                          type: string
                        allocatable_type_label:
                          type: string
                        allocatable_id:
                          type: integer
                        allocatable:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            sku:
                              type: string
                        allocation_date:
                          type: string
                        period_start:
                          type: string
                        period_end:
                          type: string
                        amount:
                          type: number
                        amount_in_tenant_currency:
                          type: number
                        proration_strategy:
                          type: string
                        proration_weight:
                          type: string
                          nullable: true
                        amortization_period_id:
                          type: string
                          nullable: true
                        is_amortized:
                          type: boolean
                        created_at:
                          type: string
                        updated_at:
                          type: string
                example:
                  data:
                  - id: 88
                    cost_entry_id: 42
                    allocatable_type: App\Models\Product
                    allocatable_type_label: Product
                    allocatable_id: 101
                    allocatable:
                      id: 101
                      name: Widget
                      sku: WIDGET-001
                    allocation_date: '2026-06-01'
                    period_start: '2026-06-01'
                    period_end: '2026-06-30'
                    amount: 1000.0
                    amount_in_tenant_currency: 1000.0
                    proration_strategy: specific_line
                    proration_weight: null
                    amortization_period_id: null
                    is_amortized: false
                    created_at: '2026-06-01T10:05:00.000000Z'
                    updated_at: '2026-06-01T10:05:00.000000Z'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Allocation amount exceeds the cost entry's unallocated
                    amount
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:write
      operationId: post-api-cost-entries-costentry-allocate-proration
  /api/cost-entries/{costEntry}/allocate/purchase-order/{purchaseOrder}:
    post:
      tags:
      - Costing
      summary: Allocate Cost Entry to Purchase Order
      description: 'Allocates the cost entry across the lines of a purchase order,
        creating one allocation per product using the chosen proration strategy (default
        cost_based).


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Fields: strategy (optional proration strategy: straight_line, front_loaded,
        back_loaded, revenue_based, cost_based, weight_based, volume_based, quantity_based,
        specific_line, manual), amount (optional - defaults to the cost entry''s unallocated
        amount), allocation_date (defaults to today), period_start and period_end.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                strategy:
                  type: string
                amount:
                  type: integer
                allocation_date:
                  type: string
              example:
                strategy: cost_based
                amount: 1500
                allocation_date: '2026-06-15'
      parameters:
      - name: costEntry
        in: path
        schema:
          type: integer
        required: true
        description: Cost entry ID
        example: '42'
      - name: purchaseOrder
        in: path
        schema:
          type: integer
        required: true
        description: Purchase order ID
        example: '88'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      message:
                        type: string
                      allocations:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            cost_entry_id:
                              type: integer
                            allocatable_type:
                              type: string
                            allocatable_type_label:
                              type: string
                            allocatable_id:
                              type: integer
                            allocatable:
                              type: object
                              properties:
                                id:
                                  type: integer
                                name:
                                  type: string
                                sku:
                                  type: string
                            allocation_date:
                              type: string
                            period_start:
                              type: string
                            period_end:
                              type: string
                            amount:
                              type: number
                            amount_in_tenant_currency:
                              type: number
                            proration_strategy:
                              type: string
                            proration_weight:
                              type: string
                              nullable: true
                            amortization_period_id:
                              type: string
                              nullable: true
                            is_amortized:
                              type: boolean
                            created_at:
                              type: string
                            updated_at:
                              type: string
                example:
                  data:
                    message: Allocated to 3 products from the lines of a purchase
                      order
                    allocations:
                    - id: 88
                      cost_entry_id: 42
                      allocatable_type: App\Models\Product
                      allocatable_type_label: Product
                      allocatable_id: 101
                      allocatable:
                        id: 101
                        name: Widget
                        sku: WIDGET-001
                      allocation_date: '2026-06-01'
                      period_start: '2026-06-01'
                      period_end: '2026-06-30'
                      amount: 1000.0
                      amount_in_tenant_currency: 1000.0
                      proration_strategy: specific_line
                      proration_weight: null
                      amortization_period_id: null
                      is_amortized: false
                      created_at: '2026-06-01T10:05:00.000000Z'
                      updated_at: '2026-06-01T10:05:00.000000Z'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Allocation amount exceeds the cost entry's unallocated
                    amount
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:write
      operationId: post-api-cost-entries-costentry-allocate-purchase-order-purchaseorder
  /api/cost-entries/{costEntry}/allocate/sales-order/{salesOrder}:
    post:
      tags:
      - Costing
      summary: Allocate Cost Entry to Sales Order
      description: 'Allocates the cost entry across the lines of a sales order, creating
        one allocation per product using the chosen proration strategy (default revenue_based).


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Fields: strategy (optional proration strategy: straight_line, front_loaded,
        back_loaded, revenue_based, cost_based, weight_based, volume_based, quantity_based,
        specific_line, manual), amount (optional - defaults to the cost entry''s unallocated
        amount), allocation_date (defaults to today), period_start and period_end.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                strategy:
                  type: string
                amount:
                  type: integer
                allocation_date:
                  type: string
              example:
                strategy: revenue_based
                amount: 1500
                allocation_date: '2026-06-15'
      parameters:
      - name: costEntry
        in: path
        schema:
          type: integer
        required: true
        description: Cost entry ID
        example: '42'
      - name: salesOrder
        in: path
        schema:
          type: integer
        required: true
        description: Sales order ID
        example: '1204'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      message:
                        type: string
                      allocations:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            cost_entry_id:
                              type: integer
                            allocatable_type:
                              type: string
                            allocatable_type_label:
                              type: string
                            allocatable_id:
                              type: integer
                            allocatable:
                              type: object
                              properties:
                                id:
                                  type: integer
                                name:
                                  type: string
                                sku:
                                  type: string
                            allocation_date:
                              type: string
                            period_start:
                              type: string
                            period_end:
                              type: string
                            amount:
                              type: number
                            amount_in_tenant_currency:
                              type: number
                            proration_strategy:
                              type: string
                            proration_weight:
                              type: string
                              nullable: true
                            amortization_period_id:
                              type: string
                              nullable: true
                            is_amortized:
                              type: boolean
                            created_at:
                              type: string
                            updated_at:
                              type: string
                example:
                  data:
                    message: Allocated to 3 products from the lines of a sales order
                    allocations:
                    - id: 88
                      cost_entry_id: 42
                      allocatable_type: App\Models\Product
                      allocatable_type_label: Product
                      allocatable_id: 101
                      allocatable:
                        id: 101
                        name: Widget
                        sku: WIDGET-001
                      allocation_date: '2026-06-01'
                      period_start: '2026-06-01'
                      period_end: '2026-06-30'
                      amount: 1000.0
                      amount_in_tenant_currency: 1000.0
                      proration_strategy: specific_line
                      proration_weight: null
                      amortization_period_id: null
                      is_amortized: false
                      created_at: '2026-06-01T10:05:00.000000Z'
                      updated_at: '2026-06-01T10:05:00.000000Z'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Allocation amount exceeds the cost entry's unallocated
                    amount
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:write
      operationId: post-api-cost-entries-costentry-allocate-sales-order-salesorder
  /api/cost-entries/{costEntry}/allocate/warehouse-transfer/{warehouseTransfer}:
    post:
      tags:
      - Costing
      summary: Allocate Cost Entry to Warehouse Transfer
      description: 'Allocates the cost entry across the lines of a warehouse transfer,
        creating one allocation per product using the chosen proration strategy (default
        quantity_based).


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Fields: strategy (optional proration strategy: straight_line, front_loaded,
        back_loaded, revenue_based, cost_based, weight_based, volume_based, quantity_based,
        specific_line, manual), amount (optional - defaults to the cost entry''s unallocated
        amount), allocation_date (defaults to today), period_start and period_end.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                strategy:
                  type: string
                amount:
                  type: integer
                allocation_date:
                  type: string
              example:
                strategy: quantity_based
                amount: 1500
                allocation_date: '2026-06-15'
      parameters:
      - name: costEntry
        in: path
        schema:
          type: integer
        required: true
        description: Cost entry ID
        example: '42'
      - name: warehouseTransfer
        in: path
        schema:
          type: integer
        required: true
        description: Warehouse transfer ID
        example: '512'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      message:
                        type: string
                      allocations:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            cost_entry_id:
                              type: integer
                            allocatable_type:
                              type: string
                            allocatable_type_label:
                              type: string
                            allocatable_id:
                              type: integer
                            allocatable:
                              type: object
                              properties:
                                id:
                                  type: integer
                                name:
                                  type: string
                                sku:
                                  type: string
                            allocation_date:
                              type: string
                            period_start:
                              type: string
                            period_end:
                              type: string
                            amount:
                              type: number
                            amount_in_tenant_currency:
                              type: number
                            proration_strategy:
                              type: string
                            proration_weight:
                              type: string
                              nullable: true
                            amortization_period_id:
                              type: string
                              nullable: true
                            is_amortized:
                              type: boolean
                            created_at:
                              type: string
                            updated_at:
                              type: string
                example:
                  data:
                    message: Allocated to 3 products from the lines of a warehouse
                      transfer
                    allocations:
                    - id: 88
                      cost_entry_id: 42
                      allocatable_type: App\Models\Product
                      allocatable_type_label: Product
                      allocatable_id: 101
                      allocatable:
                        id: 101
                        name: Widget
                        sku: WIDGET-001
                      allocation_date: '2026-06-01'
                      period_start: '2026-06-01'
                      period_end: '2026-06-30'
                      amount: 1000.0
                      amount_in_tenant_currency: 1000.0
                      proration_strategy: specific_line
                      proration_weight: null
                      amortization_period_id: null
                      is_amortized: false
                      created_at: '2026-06-01T10:05:00.000000Z'
                      updated_at: '2026-06-01T10:05:00.000000Z'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Allocation amount exceeds the cost entry's unallocated
                    amount
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:write
      operationId: post-api-cost-entries-costentry-allocate-warehouse-transfer-warehousetransfer
  /api/cost-entries/{costEntry}/allocate/inventory-assembly/{inventoryAssembly}:
    post:
      tags:
      - Costing
      summary: Allocate Cost Entry to Inventory Assembly
      description: 'Allocates the cost entry across the component lines of an inventory
        assembly, creating one allocation per product using the chosen proration strategy
        (default cost_based).


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Fields: strategy (optional proration strategy: straight_line, front_loaded,
        back_loaded, revenue_based, cost_based, weight_based, volume_based, quantity_based,
        specific_line, manual), amount (optional - defaults to the cost entry''s unallocated
        amount), allocation_date (defaults to today), period_start and period_end.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                strategy:
                  type: string
                amount:
                  type: integer
                allocation_date:
                  type: string
              example:
                strategy: cost_based
                amount: 1500
                allocation_date: '2026-06-15'
      parameters:
      - name: costEntry
        in: path
        schema:
          type: integer
        required: true
        description: Cost entry ID
        example: '42'
      - name: inventoryAssembly
        in: path
        schema:
          type: integer
        required: true
        description: Inventory assembly ID
        example: '33'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      message:
                        type: string
                      allocations:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            cost_entry_id:
                              type: integer
                            allocatable_type:
                              type: string
                            allocatable_type_label:
                              type: string
                            allocatable_id:
                              type: integer
                            allocatable:
                              type: object
                              properties:
                                id:
                                  type: integer
                                name:
                                  type: string
                                sku:
                                  type: string
                            allocation_date:
                              type: string
                            period_start:
                              type: string
                            period_end:
                              type: string
                            amount:
                              type: number
                            amount_in_tenant_currency:
                              type: number
                            proration_strategy:
                              type: string
                            proration_weight:
                              type: string
                              nullable: true
                            amortization_period_id:
                              type: string
                              nullable: true
                            is_amortized:
                              type: boolean
                            created_at:
                              type: string
                            updated_at:
                              type: string
                example:
                  data:
                    message: Allocated to 3 products from the component lines of an
                      inventory assembly
                    allocations:
                    - id: 88
                      cost_entry_id: 42
                      allocatable_type: App\Models\Product
                      allocatable_type_label: Product
                      allocatable_id: 101
                      allocatable:
                        id: 101
                        name: Widget
                        sku: WIDGET-001
                      allocation_date: '2026-06-01'
                      period_start: '2026-06-01'
                      period_end: '2026-06-30'
                      amount: 1000.0
                      amount_in_tenant_currency: 1000.0
                      proration_strategy: specific_line
                      proration_weight: null
                      amortization_period_id: null
                      is_amortized: false
                      created_at: '2026-06-01T10:05:00.000000Z'
                      updated_at: '2026-06-01T10:05:00.000000Z'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Allocation amount exceeds the cost entry's unallocated
                    amount
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:write
      operationId: post-api-cost-entries-costentry-allocate-inventory-assembly-inventoryassembly
  /api/cost-entries/{costEntry}/allocate/stock-take/{stockTake}:
    post:
      tags:
      - Costing
      summary: Allocate Cost Entry to Stock Take
      description: 'Allocates the cost entry across the items of a stock take, creating
        one allocation per product using the chosen proration strategy (default quantity_based).


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Fields: strategy (optional proration strategy: straight_line, front_loaded,
        back_loaded, revenue_based, cost_based, weight_based, volume_based, quantity_based,
        specific_line, manual), amount (optional - defaults to the cost entry''s unallocated
        amount), allocation_date (defaults to today), period_start and period_end.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                strategy:
                  type: string
                amount:
                  type: integer
                allocation_date:
                  type: string
              example:
                strategy: quantity_based
                amount: 1500
                allocation_date: '2026-06-15'
      parameters:
      - name: costEntry
        in: path
        schema:
          type: integer
        required: true
        description: Cost entry ID
        example: '42'
      - name: stockTake
        in: path
        schema:
          type: integer
        required: true
        description: Stock take ID
        example: '19'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      message:
                        type: string
                      allocations:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            cost_entry_id:
                              type: integer
                            allocatable_type:
                              type: string
                            allocatable_type_label:
                              type: string
                            allocatable_id:
                              type: integer
                            allocatable:
                              type: object
                              properties:
                                id:
                                  type: integer
                                name:
                                  type: string
                                sku:
                                  type: string
                            allocation_date:
                              type: string
                            period_start:
                              type: string
                            period_end:
                              type: string
                            amount:
                              type: number
                            amount_in_tenant_currency:
                              type: number
                            proration_strategy:
                              type: string
                            proration_weight:
                              type: string
                              nullable: true
                            amortization_period_id:
                              type: string
                              nullable: true
                            is_amortized:
                              type: boolean
                            created_at:
                              type: string
                            updated_at:
                              type: string
                example:
                  data:
                    message: Allocated to 3 products from the items of a stock take
                    allocations:
                    - id: 88
                      cost_entry_id: 42
                      allocatable_type: App\Models\Product
                      allocatable_type_label: Product
                      allocatable_id: 101
                      allocatable:
                        id: 101
                        name: Widget
                        sku: WIDGET-001
                      allocation_date: '2026-06-01'
                      period_start: '2026-06-01'
                      period_end: '2026-06-30'
                      amount: 1000.0
                      amount_in_tenant_currency: 1000.0
                      proration_strategy: specific_line
                      proration_weight: null
                      amortization_period_id: null
                      is_amortized: false
                      created_at: '2026-06-01T10:05:00.000000Z'
                      updated_at: '2026-06-01T10:05:00.000000Z'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Allocation amount exceeds the cost entry's unallocated
                    amount
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:write
      operationId: post-api-cost-entries-costentry-allocate-stock-take-stocktake
  /api/cost-entry-types:
    get:
      tags:
      - Costing
      summary: List Cost Entry Types
      description: 'Returns all cost entry types, ordered alphabetically by name.
        Cost entry types are user-defined categories used to classify cost entries
        (for example Freight, Duty, Warehousing) for landed cost and profitability
        tracking.


        :::info[Required scope: `purchase-orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        This endpoint is not paginated and accepts no filter or sort parameters -
        the complete list is always returned.


        Authentication: Requires Bearer token. Scope: `purchase-orders` (read/write).'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                example:
                  data:
                  - id: 3
                    name: Duty
                    created_at: '2026-05-12T09:31:00.000000Z'
                    updated_at: '2026-05-12T09:31:00.000000Z'
                  - id: 2
                    name: Freight
                    created_at: '2026-05-12T09:30:00.000000Z'
                    updated_at: '2026-05-12T09:30:00.000000Z'
                  - id: 5
                    name: Warehousing
                    created_at: '2026-05-20T14:05:00.000000Z'
                    updated_at: '2026-05-20T14:05:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: purchase-orders:read
      operationId: get-api-cost-entry-types
    post:
      tags:
      - Costing
      summary: Create Cost Entry Type
      description: 'Creates a new cost entry type.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Fields:

        - name (required, string, max 100 characters): display name of the category,
        e.g. "Freight", "Duty" or "Warehousing".


        Returns the created cost entry type. Note that this endpoint returns HTTP
        200 (not 201) on success.


        Authentication: Requires Bearer token. Scope: `purchase-orders` (read/write).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
              example:
                name: Freight
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 2
                    name: Freight
                    created_at: '2026-05-12T09:30:00.000000Z'
                    updated_at: '2026-05-12T09:30:00.000000Z'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      name:
                        type: array
                        items:
                          type: string
                example:
                  message: The name field is required.
                  errors:
                    name:
                    - The name field is required.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: purchase-orders:write
      operationId: post-api-cost-entry-types
  /api/cost-entry-types/{costEntryType}:
    get:
      tags:
      - Costing
      summary: Get Cost Entry Type
      description: 'Returns a single cost entry type by ID.


        :::info[Required scope: `purchase-orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token. Scope: `purchase-orders` (read/write).'
      parameters:
      - name: costEntryType
        in: path
        schema:
          type: integer
        required: true
        description: Cost entry type ID
        example: '2'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 2
                    name: Freight
                    created_at: '2026-05-12T09:30:00.000000Z'
                    updated_at: '2026-05-12T09:30:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:read
      operationId: get-api-cost-entry-types-costentrytype
    put:
      tags:
      - Costing
      summary: Update Cost Entry Type
      description: 'Updates the name of an existing cost entry type. Cost entries
        already assigned to the type keep their assignment and reflect the new name.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Fields:

        - name (required, string, max 100 characters): the new display name.


        Returns the updated cost entry type.


        Authentication: Requires Bearer token. Scope: `purchase-orders` (read/write).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
              example:
                name: Ocean Freight
      parameters:
      - name: costEntryType
        in: path
        schema:
          type: integer
        required: true
        description: Cost entry type ID
        example: '2'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 2
                    name: Ocean Freight
                    created_at: '2026-05-12T09:30:00.000000Z'
                    updated_at: '2026-06-15T11:42:00.000000Z'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      name:
                        type: array
                        items:
                          type: string
                example:
                  message: The name field must not be greater than 100 characters.
                  errors:
                    name:
                    - The name field must not be greater than 100 characters.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:write
      operationId: put-api-cost-entry-types-costentrytype
    delete:
      tags:
      - Costing
      summary: Delete Cost Entry Type
      description: 'Deletes a cost entry type.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        A type that is currently assigned to one or more cost entries cannot be deleted
        - the request fails with HTTP 422. Reassign or delete the cost entries using
        the type first.


        Authentication: Requires Bearer token. Scope: `purchase-orders` (read/write).'
      parameters:
      - name: costEntryType
        in: path
        schema:
          type: integer
        required: true
        description: Cost entry type ID
        example: '5'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Cost entry type deleted successfully.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Cannot delete cost entry type that is in use.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:write
      operationId: delete-api-cost-entry-types-costentrytype
  /api/fifo-layers/{id}:
    get:
      tags:
      - Costing
      summary: Get FIFO Layer
      description: 'Returns a single FIFO layer by ID with related product and warehouse
        data.


        :::info[Required scope: `inventory:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        For layers produced by an outsourced manufacturing order, `origin.outsourced_purchase_order`
        carries the backing purchase order (`id`, `purchase_order_number`) the goods
        physically arrived through — the layer itself stays linked to the manufacturing
        output for production genealogy.'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      product_id:
                        type: integer
                      fifo_layer_date:
                        type: string
                      sku:
                        type: string
                      product_name:
                        type: string
                      product_barcode:
                        type: string
                      batch_number:
                        type: string
                      manufacture_date:
                        type: string
                      expiry_date:
                        type: string
                      lot_notes:
                        type: string
                      days_to_expiry:
                        type: integer
                      original_quantity:
                        type: integer
                      fulfilled_quantity:
                        type: integer
                      avg_cost:
                        type: number
                      total_cost:
                        type: number
                      origin:
                        type: object
                        properties:
                          link_type:
                            type: string
                          link_id:
                            type: integer
                          name:
                            type: string
                          parent_link_id:
                            type: string
                            nullable: true
                          detail_link_id:
                            type: string
                            nullable: true
                          reference:
                            type: string
                          manufacturing_order:
                            type: string
                            nullable: true
                      warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      is_fba:
                        type: boolean
                      is_consignment:
                        type: boolean
                      condition:
                        type: string
                      integration_unique_id:
                        type: string
                        nullable: true
                      allocated_quantity:
                        type: integer
                      available_quantity:
                        type: integer
                      archived_at:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 1
                    product_id: 10
                    fifo_layer_date: '2024-01-15'
                    sku: PROD-A-001
                    product_name: Product A
                    product_barcode: '123456789'
                    batch_number: LOT-2026-0042
                    manufacture_date: '2026-01-04T00:00:00.000000Z'
                    expiry_date: '2026-07-04T00:00:00.000000Z'
                    lot_notes: Original shipped lot
                    days_to_expiry: 18
                    original_quantity: 100
                    fulfilled_quantity: 40
                    avg_cost: 5.5
                    total_cost: 550.0
                    origin:
                      link_type: purchase_order
                      link_id: 42
                      name: PO-2024-001
                      parent_link_id: null
                      detail_link_id: null
                      reference: PO-2024-001
                      manufacturing_order: null
                    warehouse:
                      id: 2
                      name: Main Warehouse
                    is_fba: false
                    is_consignment: false
                    condition: new
                    integration_unique_id: null
                    allocated_quantity: 20
                    available_quantity: 60
                    archived_at: null
                    created_at: '2024-01-15T10:00:00.000000Z'
                    updated_at: '2024-01-15T10:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: inventory:read
      operationId: get-api-fifo-layers-id
  /api/fifo-layers/{id}/archive:
    put:
      tags:
      - Costing
      summary: Archive FIFO Layer
      description: 'Archives a single FIFO layer. Only fully utilized layers (available_quantity
        === 0) can be archived.


        :::info[Required scope: `inventory:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 OK - Archived
                  value:
                    message: fifo layer 1 archived successfully.
                    data:
                      id: 1
                      available_quantity: 0
                      archived_at: '2024-06-01T12:00:00.000000Z'
                example-1:
                  summary: 200 OK - Cannot Archive (Still Available)
                  value:
                    errors:
                    - message: fifo layer 1 cannot be archived because it is not fully
                        fulfilled.
                      error_code: FifoLayerNOT_FULLY_FULFILLED
                      field: id
                      meta:
                        id: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: inventory:write
      operationId: put-api-fifo-layers-id-archive
  /api/fifo-layers/{id}/unarchived:
    put:
      tags:
      - Costing
      summary: Unarchive FIFO Layer
      description: 'Unarchives a previously archived FIFO layer.


        :::info[Required scope: `inventory:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      archived_at:
                        type: string
                        nullable: true
                example:
                  message: fifo layer 1 unarchived successfully.
                  data:
                    id: 1
                    archived_at: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: inventory:write
      operationId: put-api-fifo-layers-id-unarchived
  /api/fifo-layers/archive:
    put:
      tags:
      - Costing
      summary: Bulk Archive FIFO Layers
      description: 'Archives multiple FIFO layers by ID. Only fully utilized layers
        are archived; partially available layers are skipped.


        :::info[Required scope: `inventory:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Body:

        - ids (required): Array of FIFO layer IDs to archive'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1
                - 2
                - 3
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 3 of 3 fifo layers archived successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: inventory:write
      operationId: put-api-fifo-layers-archive
  /api/fifo-layers/unarchive:
    put:
      tags:
      - Costing
      summary: Bulk Unarchive FIFO Layers
      description: 'Unarchives multiple FIFO layers by ID.


        :::info[Required scope: `inventory:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Body:

        - ids (required): Array of FIFO layer IDs to unarchive'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1
                - 2
                - 3
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 3 of 3 fifo layers unarchived successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: inventory:write
      operationId: put-api-fifo-layers-unarchive
  /api/fifo-layers/archivable:
    post:
      tags:
      - Costing
      summary: Check FIFO Layers Archivable
      description: 'Checks whether each specified FIFO layer can be archived (i.e.,
        available_quantity === 0). Returns a per-layer result with archivable flag
        and reason.


        :::info[Required scope: `inventory:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Body:

        - ids (required): Array of FIFO layer IDs to check (min 1, must exist)'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1
                - 2
                - 3
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        archivable:
                          type: boolean
                        reason:
                          type: string
                          nullable: true
                example:
                  data:
                  - id: 1
                    archivable: true
                    reason: null
                  - id: 2
                    archivable: false
                    reason:
                      unfulfilledQuantity: fifo layer 2 cannot be archived because
                        it is not fully fulfilled.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      ids:
                        type: array
                        items:
                          type: string
                      ids.0:
                        type: array
                        items:
                          type: string
                example:
                  message: The given data was invalid.
                  errors:
                    ids:
                    - The ids field is required.
                    ids.0:
                    - The selected ids.0 is invalid.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: inventory:write
      operationId: post-api-fifo-layers-archivable
  /api/fifo-layers/{id}/inventory-movements:
    get:
      tags:
      - Costing
      summary: Get FIFO Layer Inventory Movements
      description: 'Returns a paginated list of inventory movements linked to a specific
        FIFO layer.


        :::info[Required scope: `inventory:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      - name: page
        in: query
        schema:
          type: integer
        description: Page number
        example: '1'
      - name: per_page
        in: query
        schema:
          type: integer
        description: Items per page
        example: '15'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        inventory_movement_date:
                          type: string
                        product_id:
                          type: integer
                        type:
                          type: object
                          properties:
                            name:
                              type: string
                            link_type:
                              type: string
                            link_id:
                              type: integer
                            parent_link_id:
                              type: string
                              nullable: true
                            detail_link_id:
                              type: string
                              nullable: true
                            manufacturing_order:
                              type: string
                              nullable: true
                        inventory_status:
                          type: string
                        quantity:
                          type: integer
                        warehouse:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        layer:
                          type: object
                          properties:
                            fifo_layer_id:
                              type: integer
                            name:
                              type: string
                        fifo_layer_id:
                          type: integer
                        reference:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 100
                    inventory_movement_date: '2024-01-15'
                    product_id: 10
                    type:
                      name: purchase_receipt
                      link_type: purchase_order
                      link_id: 42
                      parent_link_id: null
                      detail_link_id: null
                      manufacturing_order: null
                    inventory_status: on_hand
                    quantity: 100
                    warehouse:
                      id: 2
                      name: Main Warehouse
                    layer:
                      fifo_layer_id: 1
                      name: PO-2024-001
                    fifo_layer_id: 1
                    reference: PO-2024-001
                    created_at: '2024-01-15T10:00:00.000000Z'
                    updated_at: '2024-01-15T10:00:00.000000Z'
                  per_page: 15
                  total: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: inventory:read
      operationId: get-api-fifo-layers-id-inventory-movements
  /api/fifo-layers/{id}/activity-log:
    get:
      tags:
      - Costing
      summary: Get FIFO Layer Activity Log
      description: 'Returns a paginated activity log for a specific FIFO layer. Shows
        who changed the layer and what was changed.


        :::info[Required scope: `inventory:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      - name: per_page
        in: query
        schema:
          type: integer
        description: 'Items per page (default: 15)'
        example: '15'
      - name: filter[search]
        in: query
        schema:
          type: string
        description: Search in causer name, properties, event, or subject_type
        example: archive
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        description:
                          type: string
                        event:
                          type: string
                        subject_type:
                          type: string
                        subject_id:
                          type: integer
                        properties:
                          type: object
                          properties:
                            attributes:
                              type: object
                              properties:
                                archived_at:
                                  type: string
                            old:
                              type: object
                              properties:
                                archived_at:
                                  type: string
                                  nullable: true
                        causer_name:
                          type: string
                        created_at:
                          type: string
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 500
                    description: updated
                    event: updated
                    subject_type: FifoLayer
                    subject_id: 1
                    properties:
                      attributes:
                        archived_at: '2024-06-01 12:00:00'
                      old:
                        archived_at: null
                    causer_name: Dev User
                    created_at: '2024-06-01T12:00:00.000000Z'
                  per_page: 15
                  total: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: inventory:read
      operationId: get-api-fifo-layers-id-activity-log
  /api/fifo-layers/recalculate-total-costs:
    post:
      tags:
      - Costing
      summary: Recalculate Total Costs
      description: 'Recalculates the total_cost field for the specified FIFO layers.
        Useful after manual avg_cost corrections.


        :::info[Required scope: `inventory:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Body:

        - ids (required): Array of FIFO layer IDs to recalculate (min 1, must exist)'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1
                - 2
                - 3
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                example:
                  status: success
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      ids:
                        type: array
                        items:
                          type: string
                example:
                  message: The given data was invalid.
                  errors:
                    ids:
                    - The ids field is required.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: inventory:write
      operationId: post-api-fifo-layers-recalculate-total-costs
  /api/fifo-layers/{id}/parents:
    get:
      tags:
      - Costing
      summary: Get FIFO Layer Parents
      description: 'Returns the immediate (depth-1) parent FIFO layers consumed to
        produce the given output layer, with the aggregated quantity consumed from
        each parent. Used by the FIFO Layer detail page''s ''Consumed From'' panel
        to render the upstream lots that were assembled into this batch.


        :::info[Required scope: `inventory:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        For standard MO output layers, parents are resolved by walking inventory_movements
        where movement.fifo_layer_id points at a consumption (component) movement
        and the resulting upstream FIFO layer is the parent. For Simple Mode (assemble/disassemble)
        outputs, the same walk works because the consumption movements link back to
        component FIFO layers identically.


        Returns an empty `data` array for raw layers (e.g. purchase receipts) with
        no upstream consumption movements.


        Results are sorted: most recently produced parents first, then by largest
        quantity consumed.


        Authentication: Requires Bearer token.'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 OK
                  value:
                    data:
                    - id: parent-3
                      fifo_layer_id: 3
                      entity_type: purchase_order
                      reference: PO-2024-014
                      batch_number: LBL-2024-014
                      product_id: 51
                      product_name: Adhesive Label 60x40
                      sku: LBL-60x40
                      manufacture_date: '2024-05-01'
                      fifo_layer_date: '2024-05-12'
                      quantity_consumed: 2
                      lot_notes: Original shipped lot
                    - id: parent-2
                      fifo_layer_id: 2
                      entity_type: purchase_order
                      reference: PO-2024-011
                      batch_number: POUCH-2024-011
                      product_id: 47
                      product_name: Empty 250g Pouch
                      sku: POUCH-250
                      manufacture_date: '2024-04-28'
                      fifo_layer_date: '2024-05-10'
                      quantity_consumed: 2
                      lot_notes: Original shipped lot
                example-1:
                  summary: 200 OK (no parents)
                  value:
                    data: []
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: inventory:read
      operationId: get-api-fifo-layers-id-parents
  /api/fifo-layers:
    get:
      tags:
      - Costing
      summary: List FIFO Layers
      description: 'Returns a paginated list of FIFO layers. Supports filtering, sorting,
        and column inclusion/exclusion.


        Authentication: Requires Bearer token.


        Allowed sorts: id, fifo_layer_date, avg_cost, total_cost, original_quantity,
        fulfilled_quantity, created_at, updated_at'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        description: 'Page number (default: 1)'
        example: '1'
      - name: limit
        in: query
        schema:
          type: integer
        description: 'Items per page (default: 10)'
        example: '15'
      - name: sort
        in: query
        schema:
          type: string
        description: 'Sort field. Prefix with - for descending (e.g. -fifo_layer_date).
          Allowed: id, fifo_layer_date, avg_cost, total_cost, original_quantity, fulfilled_quantity,
          created_at, updated_at'
        example: fifo_layer_date
      - name: search
        in: query
        schema:
          type: string
        description: Search term across SKU, product name, reference
      - name: archived
        in: query
        schema:
          type: integer
        description: 0 = exclude archived, 1 = include archived
        example: '0'
      - name: included[]
        in: query
        schema:
          type: string
        description: Column names to include in response
      - name: excluded[]
        in: query
        schema:
          type: string
        description: Column names to exclude from response
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        product_id:
                          type: integer
                        fifo_layer_date:
                          type: string
                        sku:
                          type: string
                        product_name:
                          type: string
                        product_barcode:
                          type: string
                        original_quantity:
                          type: integer
                        fulfilled_quantity:
                          type: integer
                        avg_cost:
                          type: number
                        total_cost:
                          type: number
                        origin:
                          type: object
                          properties:
                            link_type:
                              type: string
                            link_id:
                              type: integer
                            name:
                              type: string
                            parent_link_id:
                              type: string
                              nullable: true
                            detail_link_id:
                              type: string
                              nullable: true
                            reference:
                              type: string
                            manufacturing_order:
                              type: string
                              nullable: true
                        warehouse:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        is_fba:
                          type: boolean
                        condition:
                          type: string
                        integration_unique_id:
                          type: string
                          nullable: true
                        allocated_quantity:
                          type: integer
                        available_quantity:
                          type: integer
                        archived_at:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 1
                    product_id: 10
                    fifo_layer_date: '2024-01-15'
                    sku: PROD-A-001
                    product_name: Product A
                    product_barcode: '123456789'
                    original_quantity: 100
                    fulfilled_quantity: 40
                    avg_cost: 5.5
                    total_cost: 550.0
                    origin:
                      link_type: purchase_order
                      link_id: 42
                      name: PO-2024-001
                      parent_link_id: null
                      detail_link_id: null
                      reference: PO-2024-001
                      manufacturing_order: null
                    warehouse:
                      id: 2
                      name: Main Warehouse
                    is_fba: false
                    condition: new
                    integration_unique_id: null
                    allocated_quantity: 20
                    available_quantity: 60
                    archived_at: null
                    created_at: '2024-01-15T10:00:00.000000Z'
                    updated_at: '2024-01-15T10:00:00.000000Z'
                  current_page: 1
                  per_page: 15
                  total: 1
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-fifo-layers
  /api/cogs/sku-health:
    get:
      tags:
      - Costing
      summary: List SKU COGS Health
      description: 'Returns paginated SKU COGS health metrics. Each item includes
        unit cost, initial COGS, statistics (min/max/median/avg/variation), and inventory
        totals.


        :::info[Required scope: `inventory:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Sort fields: sku, product_name, unit_cost, variation_pct, total_quantity (default:
        sku asc).'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        description: 'Page number (default: 1)'
        example: '1'
      - name: per_page
        in: query
        schema:
          type: integer
        description: 'Items per page (default: 50)'
        example: '50'
      - name: sort_by
        in: query
        schema:
          type: string
        description: 'Sort field. Options: sku, product_name, unit_cost, variation_pct,
          total_quantity'
        example: sku
      - name: sort_direction
        in: query
        schema:
          type: string
        description: 'Sort direction: asc or desc'
        example: asc
      - name: search
        in: query
        schema:
          type: string
        description: Search by SKU or product name
        example: WIDGET
      - name: variation_min
        in: query
        schema:
          type: integer
        description: Minimum COGS variation percentage filter
        example: '5'
      - name: variation_max
        in: query
        schema:
          type: integer
        description: Maximum COGS variation percentage filter
        example: '50'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        product_id:
                          type: integer
                        sku:
                          type: string
                        product_name:
                          type: string
                        unit_cost:
                          type: number
                        initial_cogs:
                          type: number
                        cogs_statistics:
                          type: object
                          properties:
                            min:
                              type: number
                            max:
                              type: number
                            median:
                              type: number
                            avg:
                              type: number
                            variation_pct:
                              type: number
                        inventory:
                          type: object
                          properties:
                            total_quantity:
                              type: integer
                            total_value:
                              type: number
                            active_layer_count:
                              type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                  last_page:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - product_id: 101
                    sku: WIDGET-RED-L
                    product_name: Red Widget Large
                    unit_cost: 12.5
                    initial_cogs: 12.0
                    cogs_statistics:
                      min: 10.0
                      max: 15.0
                      median: 12.5
                      avg: 12.33
                      variation_pct: 16.67
                    inventory:
                      total_quantity: 500
                      total_value: 6250.0
                      active_layer_count: 3
                  per_page: 50
                  total: 1
                  from: 1
                  to: 1
                  last_page: 1
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: inventory:read
      operationId: get-api-cogs-sku-health
    post:
      tags:
      - Costing
      summary: Search SKU COGS Health
      description: 'Returns the same paginated per-SKU COGS health table as the GET
        version of this endpoint, but accepts its parameters in a JSON request body.
        Each row aggregates a product''s cost-of-goods statistics (min, max, median,
        average, and percentage variation) across its active FIFO cost layers, alongside
        current inventory totals.


        :::info[Required scope: `inventory:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Unlike the other advanced list endpoints, this one does not accept a `filter_groups`
        tree. It reads a small, fixed set of fields:

        - `search`: matches against SKU or product name.

        - `variation_min` / `variation_max`: bound the COGS variation percentage.

        - `sort_by`: column to sort by (defaults to `sku`).

        - `sort_direction`: `asc` or `desc` (defaults to `asc`).

        - `page` / `per_page`: pagination (per_page defaults to 50).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                search:
                  type: string
                variation_min:
                  type: integer
                variation_max:
                  type: integer
                sort_by:
                  type: string
                sort_direction:
                  type: string
                page:
                  type: integer
                per_page:
                  type: integer
              example:
                search: WIDGET
                variation_min: 15
                variation_max: 100
                sort_by: variation_pct
                sort_direction: desc
                page: 1
                per_page: 50
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        product_id:
                          type: integer
                        sku:
                          type: string
                        product_name:
                          type: string
                        unit_cost:
                          type: number
                        initial_cogs:
                          type: number
                        cogs_statistics:
                          type: object
                          properties:
                            min:
                              type: number
                            max:
                              type: number
                            median:
                              type: number
                            avg:
                              type: number
                            variation_pct:
                              type: number
                        inventory:
                          type: object
                          properties:
                            total_quantity:
                              type: integer
                            total_value:
                              type: number
                            active_layer_count:
                              type: integer
                  current_page:
                    type: integer
                  per_page:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                  last_page:
                    type: integer
                  total:
                    type: integer
                  next_page_url:
                    type: string
                  prev_page_url:
                    type: string
                    nullable: true
                example:
                  data:
                  - product_id: 3312
                    sku: WIDGET-BLUE-01
                    product_name: Blue Widget
                    unit_cost: 13.75
                    initial_cogs: 12.5
                    cogs_statistics:
                      min: 11.2
                      max: 15.9
                      median: 13.4
                      avg: 13.62
                      variation_pct: 34.8
                    inventory:
                      total_quantity: 240
                      total_value: 3268.8
                      active_layer_count: 5
                  current_page: 1
                  per_page: 50
                  from: 1
                  to: 1
                  last_page: 3
                  total: 118
                  next_page_url: https://api.example.com/api/cogs/sku-health?page=2
                  prev_page_url: null
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: inventory:write
      operationId: post-api-cogs-sku-health
  /api/cogs/sku-health/summary:
    get:
      tags:
      - Costing
      summary: Get SKU COGS Health Summary
      description: 'Returns aggregate summary statistics for the COGS health dashboard
        — totals across all SKUs matching the given filters.


        :::info[Required scope: `inventory:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: search
        in: query
        schema:
          type: string
        description: Filter by SKU or product name
        example: WIDGET
      - name: variation_min
        in: query
        schema:
          type: integer
        description: Minimum variation % filter
        example: '5'
      - name: variation_max
        in: query
        schema:
          type: integer
        description: Maximum variation % filter
        example: '50'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      total_products:
                        type: integer
                      products_with_variation:
                        type: integer
                      avg_variation_pct:
                        type: number
                      max_variation_pct:
                        type: number
                      total_inventory_value:
                        type: number
                      products_at_risk:
                        type: integer
                example:
                  data:
                    total_products: 120
                    products_with_variation: 35
                    avg_variation_pct: 8.42
                    max_variation_pct: 52.1
                    total_inventory_value: 485320.75
                    products_at_risk: 12
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: inventory:read
      operationId: get-api-cogs-sku-health-summary
  /api/cogs/sku-health/{id}:
    get:
      tags:
      - Costing
      summary: Get SKU COGS Health Detail
      description: 'Returns detailed COGS health metrics for a specific product by
        product ID.


        :::info[Required scope: `inventory:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        **Scope:** The top-level metrics (`cogs_avg`, `cogs_min`, `cogs_max`, `cogs_median`,
        `variation_pct`, `total_quantity`, `total_value`, `active_layer_count`, `init_cogs`)
        cover the **warehouse FIFO ledger only**. Amazon FBA stock — which uses a
        separate WAC ledger and has no `warehouse_id` — is intentionally excluded
        so this matches the cache-backed `inventory_avg_cost` displayed on the product
        Overview page.


        **Amazon FBA inventory** (if the product has any) is returned as a separate
        `amazon_summary` object with its own quantity-weighted average, min/max cost,
        layer count, and integration instance count. `amazon_summary` is `null` when
        the product has no Amazon FBA stock.


        Authentication: Requires Bearer token.'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 OK (with Amazon FBA stock)
                  value:
                    data:
                      product_id: 101
                      sku: WIDGET-RED-L
                      product_name: Red Widget Large
                      unit_cost: 12.5
                      init_cogs: 12.0
                      cogs_min: 10.0
                      cogs_max: 15.0
                      cogs_median: 12.5
                      cogs_avg: 12.33
                      cogs_stddev: 1.85
                      variation_pct: 16.67
                      total_quantity: 500
                      total_value: 6250.0
                      active_layer_count: 3
                      amazon_summary:
                        total_quantity: 1010
                        total_value: 1304.92
                        cogs_avg: 1.292
                        cogs_min: 1.15
                        cogs_max: 1.42
                        active_layer_count: 4
                        integration_instance_count: 1
                example-1:
                  summary: 200 OK (no Amazon FBA stock)
                  value:
                    data:
                      product_id: 102
                      sku: WIDGET-BLUE-M
                      product_name: Blue Widget Medium
                      unit_cost: 8.0
                      init_cogs: 7.5
                      cogs_min: 7.5
                      cogs_max: 8.1
                      cogs_median: 7.8
                      cogs_avg: 7.86
                      cogs_stddev: 0.22
                      variation_pct: 8.0
                      total_quantity: 240
                      total_value: 1886.4
                      active_layer_count: 2
                      amazon_summary: null
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: array
                    items:
                      type: object
                      properties:
                        message:
                          type: string
                        code:
                          type: string
                        field:
                          type: string
                example:
                  errors:
                  - message: Product not found or has no COGS data
                    code: NOT_FOUND
                    field: product
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: inventory:read
      operationId: get-api-cogs-sku-health-id
  /api/cogs/sku-health/value-sources:
    get:
      tags:
      - Costing
      summary: Get All Value Sources
      description: 'Returns paginated COGS value sources across all products.


        :::info[Required scope: `inventory:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        description: 'Page number (default: 1)'
        example: '1'
      - name: per_page
        in: query
        schema:
          type: integer
        description: 'Items per page (default: 50)'
        example: '50'
      - name: sort_by
        in: query
        schema:
          type: string
        description: Sort field
        example: sku
      - name: sort_direction
        in: query
        schema:
          type: string
        description: 'Sort direction: asc or desc'
        example: asc
      - name: search
        in: query
        schema:
          type: string
        description: Search by SKU or product name
        example: WIDGET
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        product_id:
                          type: integer
                        sku:
                          type: string
                        product_name:
                          type: string
                        value_source:
                          type: string
                        unit_cost:
                          type: number
                  per_page:
                    type: integer
                  total:
                    type: integer
                  last_page:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - product_id: 101
                    sku: WIDGET-RED-L
                    product_name: Red Widget Large
                    value_source: purchase_order
                    unit_cost: 12.5
                  per_page: 50
                  total: 1
                  last_page: 1
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: inventory:read
      operationId: get-api-cogs-sku-health-value-sources
  /api/cogs/sku-health/{id}/warehouse-breakdown:
    get:
      tags:
      - Costing
      summary: Get Warehouse Breakdown
      description: 'Returns the COGS warehouse breakdown for a specific product, showing
        how inventory and cost is distributed across warehouses.


        :::info[Required scope: `inventory:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        warehouse_id:
                          type: integer
                        warehouse_name:
                          type: string
                        total_quantity:
                          type: integer
                        total_value:
                          type: number
                        avg_cost:
                          type: number
                        active_layer_count:
                          type: integer
                example:
                  data:
                  - warehouse_id: 1
                    warehouse_name: Main Warehouse
                    total_quantity: 300
                    total_value: 3750.0
                    avg_cost: 12.5
                    active_layer_count: 2
                  - warehouse_id: 2
                    warehouse_name: Secondary Warehouse
                    total_quantity: 200
                    total_value: 2500.0
                    avg_cost: 12.5
                    active_layer_count: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: inventory:read
      operationId: get-api-cogs-sku-health-id-warehouse-breakdown
  /api/cogs/sku-health/{id}/initial-inventory:
    get:
      tags:
      - Costing
      summary: Get Initial Inventory
      description: 'Returns the initial inventory breakdown by warehouse for a specific
        product.


        :::info[Required scope: `inventory:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        warehouse_id:
                          type: integer
                        warehouse_name:
                          type: string
                        quantity:
                          type: integer
                        unit_cost:
                          type: number
                        total_value:
                          type: number
                example:
                  data:
                  - warehouse_id: 1
                    warehouse_name: Main Warehouse
                    quantity: 200
                    unit_cost: 12.0
                    total_value: 2400.0
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: inventory:read
      operationId: get-api-cogs-sku-health-id-initial-inventory
  /api/cogs/sku-health/{id}/fifo-layers:
    get:
      tags:
      - Costing
      summary: Get FIFO Layers
      description: 'Returns current active FIFO layers for a specific product, optionally
        filtered by warehouse.


        :::info[Required scope: `inventory:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      - name: warehouse_id
        in: query
        schema:
          type: integer
        description: 'Optional: filter by warehouse ID'
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        fifo_layer_date:
                          type: string
                        original_quantity:
                          type: integer
                        remaining_quantity:
                          type: integer
                        unit_cost:
                          type: number
                        total_value:
                          type: number
                        warehouse_id:
                          type: integer
                        warehouse_name:
                          type: string
                        link_type:
                          type: string
                        link_id:
                          type: integer
                example:
                  data:
                  - id: 501
                    fifo_layer_date: '2024-01-15T00:00:00.000000Z'
                    original_quantity: 100
                    remaining_quantity: 75
                    unit_cost: 12.5
                    total_value: 937.5
                    warehouse_id: 1
                    warehouse_name: Main Warehouse
                    link_type: App\Models\PurchaseOrderReceiving
                    link_id: 201
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: inventory:read
      operationId: get-api-cogs-sku-health-id-fifo-layers
  /api/cogs/sku-health/{id}/fifo-layers-timeline:
    get:
      tags:
      - Costing
      summary: Get FIFO Layers Timeline
      description: 'Returns paginated FIFO layer parent records (timeline) for a specific
        product. Used to show the historical sequence of inventory additions.


        :::info[Required scope: `inventory:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      - name: page
        in: query
        schema:
          type: integer
        description: 'Page number (default: 1)'
        example: '1'
      - name: per_page
        in: query
        schema:
          type: integer
        description: 'Items per page (default: 20)'
        example: '20'
      - name: warehouse_id
        in: query
        schema:
          type: integer
        description: 'Optional: filter by warehouse ID'
        example: '1'
      - name: warehouse_type
        in: query
        schema:
          type: string
        description: 'Optional: filter by warehouse type'
        example: main
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        fifo_layer_date:
                          type: string
                        original_quantity:
                          type: integer
                        unit_cost:
                          type: number
                  per_page:
                    type: integer
                  total:
                    type: integer
                  last_page:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 501
                    fifo_layer_date: '2024-01-15T00:00:00.000000Z'
                    original_quantity: 100
                    unit_cost: 12.5
                  - id: 502
                    fifo_layer_date: '2024-02-01T00:00:00.000000Z'
                    original_quantity: 50
                    unit_cost: 13.0
                  per_page: 20
                  total: 2
                  last_page: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: inventory:read
      operationId: get-api-cogs-sku-health-id-fifo-layers-timeline
  /api/cogs/sku-health/{id}/layers/{id2}/consumptions:
    get:
      tags:
      - Costing
      summary: Get Layer Consumptions
      description: 'Returns paginated consumption records for a specific FIFO layer.
        Shows how the layer''s quantity was consumed over time.


        :::info[Required scope: `inventory:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      - name: id2
        in: path
        required: true
        schema:
          type: string
        description: The id2 identifier
      - name: page
        in: query
        schema:
          type: integer
        description: 'Page number (default: 1)'
        example: '1'
      - name: per_page
        in: query
        schema:
          type: integer
        description: 'Items per page (default: 20)'
        example: '20'
      - name: layer_type
        in: query
        schema:
          type: string
        description: 'Layer type filter (default: regular)'
        example: regular
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        quantity_consumed:
                          type: integer
                        unit_cost:
                          type: number
                        consumed_at:
                          type: string
                        link_type:
                          type: string
                        link_id:
                          type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  last_page:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 1001
                    quantity_consumed: 10
                    unit_cost: 12.5
                    consumed_at: '2024-01-20T14:30:00.000000Z'
                    link_type: App\Models\SalesOrder
                    link_id: 301
                  per_page: 20
                  total: 1
                  last_page: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: inventory:read
      operationId: get-api-cogs-sku-health-id-layers-id2-consumptions
  /api/cogs/sku-health/{id}/consumption-timeline:
    get:
      tags:
      - Costing
      summary: Get Consumption Timeline
      description: 'Returns paginated consumption timeline for a specific product
        — all historical consumption events in chronological order.


        :::info[Required scope: `inventory:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      - name: page
        in: query
        schema:
          type: integer
        description: 'Page number (default: 1)'
        example: '1'
      - name: per_page
        in: query
        schema:
          type: integer
        description: 'Items per page (default: 20)'
        example: '20'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        consumed_at:
                          type: string
                        quantity:
                          type: integer
                        unit_cost:
                          type: number
                        total_cost:
                          type: number
                  per_page:
                    type: integer
                  total:
                    type: integer
                  last_page:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - consumed_at: '2024-01-20T14:30:00.000000Z'
                    quantity: 10
                    unit_cost: 12.5
                    total_cost: 125.0
                  per_page: 20
                  total: 1
                  last_page: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: inventory:read
      operationId: get-api-cogs-sku-health-id-consumption-timeline
  /api/cogs/sku-health/{id}/recalculate:
    post:
      tags:
      - Costing
      summary: Recalculate SKU COGS
      description: 'Queues a COGS recalculation for all FIFO layers of a specific
        product as a background job. The request returns immediately with a `tracked_job_log_id`
        you can use to track progress; the updated costs land once the job completes.
        Returns a message only (no `tracked_job_log_id`) when the product has no FIFO
        layers to recalculate.


        :::info[Required scope: `inventory:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 4821
                  message: COGS recalculation started. Use the returned tracked_job_log_id
                    to track progress.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: inventory:write
      operationId: post-api-cogs-sku-health-id-recalculate
  /api/cogs/sku-health/export:
    get:
      tags:
      - Costing
      summary: Export SKU COGS Health
      description: 'Export SKU COGS health metrics as spreadsheet-ready JSON rows.
        Unlike file-download exports, this endpoint returns the rows in the JSON response
        body (keyed by column heading) so the caller can save them as CSV/XLSX. Returns
        up to 10,000 products.


        :::info[Required scope: `inventory:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Each row reports the cost-of-goods-sold consistency for one product: initial
        COGS, current unit cost, and the min / max / median / average COGS across
        its active cost layers, plus the variation percentage between layers. `Valuation
        Method` is WAC when the product carries Amazon FBA stock (valued on a weighted-average
        ledger), otherwise FIFO. Monetary values are formatted strings with thousands
        separators.


        Filters (all optional):

        - `search` — matches product SKU or product name (partial match).

        - `variation_min` / `variation_max` — only products whose COGS variation percentage
        is within the given bounds.


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      data:
                        type: array
                        items:
                          type: object
                          properties:
                            SKU:
                              type: string
                            Product Name:
                              type: string
                            Valuation Method:
                              type: string
                            Init COGS:
                              type: string
                            Unit Cost:
                              type: string
                            Variation %:
                              type: string
                            Low COGS:
                              type: string
                            High COGS:
                              type: string
                            Median COGS:
                              type: string
                            Avg COGS:
                              type: string
                            Total Qty:
                              type: integer
                            Total Value:
                              type: string
                            Active Layers:
                              type: integer
                  status:
                    type: string
                example:
                  data:
                    data:
                    - SKU: WIDGET-001
                      Product Name: Blue Widget
                      Valuation Method: FIFO
                      Init COGS: '10.00'
                      Unit Cost: '12.50'
                      Variation %: '18.25'
                      Low COGS: '10.00'
                      High COGS: '14.75'
                      Median COGS: '12.20'
                      Avg COGS: '12.35'
                      Total Qty: 240
                      Total Value: 2,964.00
                      Active Layers: 3
                    - SKU: GADGET-002
                      Product Name: Red Gadget
                      Valuation Method: WAC
                      Init COGS: '22.00'
                      Unit Cost: '21.40'
                      Variation %: '4.10'
                      Low COGS: '21.00'
                      High COGS: '22.60'
                      Median COGS: '21.40'
                      Avg COGS: '21.55'
                      Total Qty: 88
                      Total Value: 1,896.40
                      Active Layers: 2
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: inventory:read
      operationId: get-api-cogs-sku-health-export
  /api/cogs-revaluation:
    get:
      tags:
      - Costing
      summary: List Inventory Revaluations
      description: "List the inventory revaluation ledger (paginated). Every FIFO-layer\
        \ cost change writes one dated row here.\n\n:::info[Required scope: `inventory:read`]\n\
        Grant this scope to your token under [Settings → Developer → Personal Access\
        \ Tokens](https://app.sku.io/settings/api).\n:::\n\n**Authentication:** Requires\
        \ Bearer token (PAT).\n\n**Methods:** GET (query params) or POST (same params\
        \ in the JSON body — use POST when a large `filter_groups` tree exceeds URL\
        \ limits).\n\n**Search** — `filter[search]` spans: ID (exact), FIFO Layer\
        \ ID (exact), product SKU, product name, warehouse name, and reason notes.\n\
        \n**Flat filters** — every column below also supports operator-suffixed variants\
        \ (e.g. `filter[new_unit_cost.greater_than]`, `filter[effective_at.between]`,\
        \ `filter[reason.is_one_of]`):\n- Text (`reason`, `cogs_source`, `reason_notes`,\
        \ `sku`, `product_name`): contains, does_not_contain, is, is_not, is_one_of,\
        \ starts_with, does_not_start_with, ends_with, does_not_end_with, is_empty,\
        \ is_not_empty\n- Numeric (`id`, `fifo_layer_id`, `old_unit_cost`, `new_unit_cost`,\
        \ `units_on_hand_at_time`, `product_id`, `warehouse_id`, `warehouse`): is,\
        \ is_not, is_one_of, greater_than, less_than, greater_than_or_equal, less_than_or_equal,\
        \ between, is_empty, is_not_empty\n- Datetime (`effective_at`, `posted_at`,\
        \ `created_at`): is, is_not, before, after, on_or_before, on_or_after, between,\
        \ today, yesterday, past_week, past_month, past_year, days_ago, past_days,\
        \ is_empty, is_not_empty (timezone-aware)\n- Legacy: `filter[effective_from]`\
        \ / `filter[effective_to]` (date bounds on effective_at, kept for backward\
        \ compatibility)\n\n**Grouped filters** — `filter_groups` accepts a base64-encoded\
        \ JSON tree with AND/OR conjunctions and nested groups (the Advanced Filters\
        \ modal format):\n```json\n{\n  \"conjunction\": \"and\",\n  \"children\"\
        : [\n    {\"type\": \"condition\", \"condition\": {\"column\": \"reason\"\
        , \"operator\": \"is\", \"value\": \"landed_cost_added\"}},\n    {\"type\"\
        : \"group\", \"group\": {\"conjunction\": \"or\", \"children\": [...]}}\n\
        \  ]\n}\n```\nVia POST, `filter_groups` may be sent as a plain (non-encoded)\
        \ JSON object in the body. Unregistered columns return 400.\n\n**Reason values:**\
        \ landed_cost_added, vendor_invoice_correction, market_value_adjustment, system_error,\
        \ other.\n\n**Allowed sorts:** id, effective_at, posted_at, new_unit_cost,\
        \ old_unit_cost, reason, cogs_source, created_at, product (by product SKU),\
        \ warehouse (by warehouse name). Prefix with `-` for DESC. Default: `-effective_at`.\n\
        \n**Pagination:** `page` + `per_page` (default 10).\n\n**Cross-links:** each\
        \ row carries `link_reference`, `link_type_label`, `link_route` pointing at\
        \ the FIFO layer detail page. `effective_at` is the value date (drives the\
        \ valuation report); `posted_at` is the booking date."
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        fifo_layer_id:
                          type: integer
                        reason:
                          type: string
                        reason_label:
                          type: string
                        reason_notes:
                          type: string
                        cogs_source:
                          type: string
                        cost_version_before:
                          type: integer
                        cost_version_after:
                          type: integer
                        old_unit_cost:
                          type: number
                        new_unit_cost:
                          type: number
                        unit_cost_delta:
                          type: number
                        old_total_cost:
                          type: number
                        new_total_cost:
                          type: number
                        total_cost_delta:
                          type: number
                        units_on_hand_at_time:
                          type: number
                        units_consumed_at_time:
                          type: number
                        effective_at:
                          type: string
                        posted_at:
                          type: string
                        created_at:
                          type: string
                        user:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        fifo_layer:
                          type: object
                          properties:
                            id:
                              type: integer
                            fifo_layer_date:
                              type: string
                            original_quantity:
                              type: number
                            available_quantity:
                              type: number
                            avg_cost:
                              type: number
                            link_type:
                              type: string
                            link_id:
                              type: integer
                            link_reference:
                              type: string
                        product:
                          type: object
                          properties:
                            id:
                              type: integer
                            sku:
                              type: string
                            name:
                              type: string
                        warehouse:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        link_reference:
                          type: string
                        link_type_label:
                          type: string
                        link_route:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                  first_page_url:
                    type: string
                  last_page_url:
                    type: string
                  next_page_url:
                    type: string
                  prev_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                example:
                  data:
                  - id: 9001
                    fifo_layer_id: 501
                    reason: landed_cost_added
                    reason_label: Landed Cost Added
                    reason_notes: Freight + duties allocated from customs invoice
                      CI-4471
                    cogs_source: manual
                    cost_version_before: 2
                    cost_version_after: 3
                    old_unit_cost: 10.0
                    new_unit_cost: 12.33
                    unit_cost_delta: 2.33
                    old_total_cost: 1000.0
                    new_total_cost: 1233.0
                    total_cost_delta: 233.0
                    units_on_hand_at_time: 80.0
                    units_consumed_at_time: 20.0
                    effective_at: '2026-05-01T00:00:00.000000Z'
                    posted_at: '2026-05-01T00:00:00.000000Z'
                    created_at: '2026-05-01T14:22:10.000000Z'
                    user:
                      id: 7
                      name: Jane Operator
                    fifo_layer:
                      id: 501
                      fifo_layer_date: '2026-03-15T00:00:00.000000Z'
                      original_quantity: 100.0
                      available_quantity: 80.0
                      avg_cost: 12.33
                      link_type: App\Models\PurchaseOrderReceiving
                      link_id: 3120
                      link_reference: PO-10044
                    product:
                      id: 101
                      sku: WIDGET-RED-L
                      name: Red Widget Large
                    warehouse:
                      id: 3
                      name: Main Warehouse
                    link_reference: PO-10044
                    link_type_label: FIFO Layer
                    link_route: /inventory/fifo-layers/501
                  current_page: 1
                  last_page: 5
                  per_page: 10
                  total: 47
                  from: 1
                  to: 10
                  first_page_url: '{{protocol}}{{domain}}/api/cogs-revaluation?page=1'
                  last_page_url: '{{protocol}}{{domain}}/api/cogs-revaluation?page=5'
                  next_page_url: '{{protocol}}{{domain}}/api/cogs-revaluation?page=2'
                  prev_page_url: null
                  path: '{{protocol}}{{domain}}/api/cogs-revaluation'
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: inventory:read
      operationId: get-api-cogs-revaluation
    post:
      tags:
      - Costing
      summary: Search COGS Revaluations
      description: 'Returns the same paginated inventory revaluation ledger as the
        GET version of this endpoint, but accepts filters as a JSON request body instead
        of the query string. Use this POST variant when the filter set is too large
        or too complex to fit in a URL (for example, deeply nested AND/OR filter groups
        or long lists of values).


        :::info[Required scope: `inventory:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Provide advanced filters under `filter_groups`, a tree of conditions combined
        with a `conjunction` of `and` or `or`. Each condition names a `column`, an
        `operator`, and a `value`.


        Text columns (`reason`, `cogs_source`, `reason_notes`, `sku`, `product_name`)
        accept: is, is_not, contains, does_not_contain, starts_with, ends_with, is_empty,
        is_not_empty, is_one_of, is_not_one_of.

        Numeric and date columns (`id`, `fifo_layer_id`, `old_unit_cost`, `new_unit_cost`,
        `units_on_hand_at_time`, `product_id`, `warehouse_id`, `effective_at`, `posted_at`,
        `created_at`) accept: is, is_not, greater_than, greater_than_or_equal, less_than,
        less_than_or_equal, between, is_empty, is_not_empty.


        Sortable columns (via `sort`, prefix with `-` for descending): id, effective_at,
        posted_at, new_unit_cost, old_unit_cost, reason, cogs_source, created_at,
        product, warehouse. Results default to `-effective_at`. The legacy `effective_from`
        / `effective_to` date-range filters remain supported.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                per_page:
                  type: integer
                page:
                  type: integer
                sort:
                  type: string
                filter_groups:
                  type: object
                  properties:
                    conjunction:
                      type: string
                    children:
                      type: array
                      items:
                        type: object
                        properties:
                          type:
                            type: string
                          condition:
                            type: object
                            properties:
                              column:
                                type: string
                              operator:
                                type: string
                              value:
                                type: string
              example:
                per_page: 25
                page: 1
                sort: -effective_at
                filter_groups:
                  conjunction: and
                  children:
                  - type: condition
                    condition:
                      column: reason
                      operator: is
                      value: recalculation
                  - type: group
                    group:
                      conjunction: or
                      children:
                      - type: condition
                        condition:
                          column: new_unit_cost
                          operator: greater_than
                          value: 10
                      - type: condition
                        condition:
                          column: sku
                          operator: contains
                          value: WIDGET
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        fifo_layer_id:
                          type: integer
                        reason:
                          type: string
                        reason_label:
                          type: string
                        reason_notes:
                          type: string
                        cogs_source:
                          type: string
                        cost_version_before:
                          type: integer
                        cost_version_after:
                          type: integer
                        old_unit_cost:
                          type: number
                        new_unit_cost:
                          type: number
                        unit_cost_delta:
                          type: number
                        old_total_cost:
                          type: integer
                        new_total_cost:
                          type: integer
                        total_cost_delta:
                          type: integer
                        units_on_hand_at_time:
                          type: integer
                        units_consumed_at_time:
                          type: integer
                        effective_at:
                          type: string
                        posted_at:
                          type: string
                        created_at:
                          type: string
                        user:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        fifo_layer:
                          type: object
                          properties:
                            id:
                              type: integer
                            fifo_layer_date:
                              type: string
                            original_quantity:
                              type: integer
                            available_quantity:
                              type: integer
                            avg_cost:
                              type: number
                            link_type:
                              type: string
                            link_id:
                              type: integer
                            link_reference:
                              type: string
                        product:
                          type: object
                          properties:
                            id:
                              type: integer
                            sku:
                              type: string
                            name:
                              type: string
                        warehouse:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        link_reference:
                          type: string
                        link_type_label:
                          type: string
                        link_route:
                          type: string
                  current_page:
                    type: integer
                  per_page:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                  last_page:
                    type: integer
                  total:
                    type: integer
                  next_page_url:
                    type: string
                  prev_page_url:
                    type: string
                    nullable: true
                example:
                  data:
                  - id: 4821
                    fifo_layer_id: 90312
                    reason: recalculation
                    reason_label: Recalculation
                    reason_notes: COGS rebuild after supplier price correction
                    cogs_source: fifo
                    cost_version_before: 3
                    cost_version_after: 4
                    old_unit_cost: 12.5
                    new_unit_cost: 13.75
                    unit_cost_delta: 1.25
                    old_total_cost: 250
                    new_total_cost: 275
                    total_cost_delta: 25
                    units_on_hand_at_time: 20
                    units_consumed_at_time: 0
                    effective_at: '2026-06-30T14:02:11.000000Z'
                    posted_at: '2026-06-30T14:02:12.000000Z'
                    created_at: '2026-06-30T14:02:12.000000Z'
                    user:
                      id: 7
                      name: Jane Doe
                    fifo_layer:
                      id: 90312
                      fifo_layer_date: '2026-05-01T00:00:00.000000Z'
                      original_quantity: 20
                      available_quantity: 20
                      avg_cost: 13.75
                      link_type: App\Models\PurchaseOrderShipmentReceiptLine
                      link_id: 55210
                      link_reference: PO-1042
                    product:
                      id: 3312
                      sku: WIDGET-BLUE-01
                      name: Blue Widget
                    warehouse:
                      id: 2
                      name: Main Warehouse
                    link_reference: PO-1042
                    link_type_label: FIFO Layer
                    link_route: /inventory/fifo-layers/90312
                  current_page: 1
                  per_page: 25
                  from: 1
                  to: 1
                  last_page: 6
                  total: 138
                  next_page_url: https://api.example.com/api/cogs-revaluation?page=2
                  prev_page_url: null
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: inventory:write
      operationId: post-api-cogs-revaluation
  /api/cogs-revaluation/variation-by-product:
    get:
      tags:
      - Costing
      summary: Get Variation by Product Report
      description: 'Returns a report of products whose COGS varies significantly across
        FIFO layers. Products with cost variation above the threshold are flagged
        for revaluation review.


        :::info[Required scope: `inventory:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Query params:

        - variation_threshold (optional): Minimum variation % to include, numeric,
        min 5, default 5'
      parameters:
      - name: variation_threshold
        in: query
        schema:
          type: integer
        description: Minimum variation % to include a product (numeric, min 5, default
          5)
        example: '5'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        product_id:
                          type: integer
                        sku:
                          type: string
                        name:
                          type: string
                        avg_cost:
                          type: number
                        min_cost:
                          type: number
                        max_cost:
                          type: number
                        variation_percentage:
                          type: number
                        layer_count:
                          type: integer
                example:
                  status: success
                  data:
                  - product_id: 42
                    sku: WIDGET-001
                    name: Blue Widget
                    avg_cost: 12.5
                    min_cost: 8.0
                    max_cost: 18.75
                    variation_percentage: 85.0
                    layer_count: 5
                  - product_id: 78
                    sku: GADGET-XL
                    name: XL Gadget
                    avg_cost: 45.0
                    min_cost: 38.0
                    max_cost: 55.0
                    variation_percentage: 36.8
                    layer_count: 3
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: inventory:read
      operationId: get-api-cogs-revaluation-variation-by-product
  /api/cogs-revaluation/product-report/{id}:
    get:
      tags:
      - Costing
      summary: Get Product COGS Report
      description: 'Returns a detailed COGS report for a specific product, including
        all FIFO layers and their costs.


        :::info[Required scope: `inventory:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Path params:

        - product: Product ID


        Query params:

        - outlier_threshold (optional): Percentage threshold for detecting cost outliers
        (5-100, default 5)'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      - name: outlier_threshold
        in: query
        schema:
          type: integer
        description: Outlier detection threshold % (numeric, min 5, max 100, default
          5)
        example: '5'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  data:
                    type: object
                    properties:
                      product_id:
                        type: integer
                      sku:
                        type: string
                      name:
                        type: string
                      avg_cost:
                        type: number
                      outlier_threshold:
                        type: integer
                      fifo_layers:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            fifo_layer_date:
                              type: string
                            unit_cost:
                              type: number
                            original_quantity:
                              type: integer
                            remaining_quantity:
                              type: integer
                            warehouse_name:
                              type: string
                            is_outlier:
                              type: boolean
                example:
                  status: success
                  data:
                    product_id: 42
                    sku: WIDGET-001
                    name: Blue Widget
                    avg_cost: 12.5
                    outlier_threshold: 5
                    fifo_layers:
                    - id: 101
                      fifo_layer_date: '2024-01-15T00:00:00.000000Z'
                      unit_cost: 8.0
                      original_quantity: 500
                      remaining_quantity: 200
                      warehouse_name: Main Warehouse
                      is_outlier: true
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: inventory:read
      operationId: get-api-cogs-revaluation-product-report-id
  /api/cogs-revaluation/fifo-report/{id}:
    get:
      tags:
      - Costing
      summary: Get FIFO Layer COGS Report
      description: 'Returns a detailed COGS report for a specific FIFO layer including
        cost history and revaluation events.


        :::info[Required scope: `inventory:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Path params:

        - fifoLayer: FIFO Layer ID'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  data:
                    type: object
                    properties:
                      fifo_layer_id:
                        type: integer
                      product_id:
                        type: integer
                      sku:
                        type: string
                      unit_cost:
                        type: number
                      original_quantity:
                        type: integer
                      remaining_quantity:
                        type: integer
                      warehouse_name:
                        type: string
                      fifo_layer_date:
                        type: string
                      revaluations:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            old_unit_cost:
                              type: number
                            new_unit_cost:
                              type: number
                            reason:
                              type: string
                            posted_at:
                              type: string
                example:
                  status: success
                  data:
                    fifo_layer_id: 101
                    product_id: 42
                    sku: WIDGET-001
                    unit_cost: 12.5
                    original_quantity: 500
                    remaining_quantity: 200
                    warehouse_name: Main Warehouse
                    fifo_layer_date: '2024-01-15T00:00:00.000000Z'
                    revaluations:
                    - id: 55
                      old_unit_cost: 8.0
                      new_unit_cost: 12.5
                      reason: purchase_cost_update
                      posted_at: '2024-03-01T09:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: inventory:read
      operationId: get-api-cogs-revaluation-fifo-report-id
  /api/cogs-revaluation/bulk-fifo-report:
    get:
      tags:
      - Costing
      summary: Get Bulk FIFO Layer COGS Report
      description: 'Returns COGS reports for multiple FIFO layers in a single request.


        :::info[Required scope: `inventory:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Query params:

        - ids (required): Array of FIFO Layer IDs'
      parameters:
      - name: ids[]
        in: query
        schema:
          type: integer
        description: FIFO Layer IDs (required array, min 1)
        example: '101'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        fifo_layer_id:
                          type: integer
                        unit_cost:
                          type: number
                        product_sku:
                          type: string
                        original_quantity:
                          type: integer
                example:
                  status: success
                  data:
                  - fifo_layer_id: 101
                    unit_cost: 12.5
                    product_sku: WIDGET-001
                    original_quantity: 500
                  - fifo_layer_id: 102
                    unit_cost: 9.75
                    product_sku: GADGET-XL
                    original_quantity: 250
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: inventory:read
      operationId: get-api-cogs-revaluation-bulk-fifo-report
  /api/cogs-revaluation/{id}/revalue:
    post:
      tags:
      - Costing
      summary: Revalue FIFO Layer
      description: 'Revalues a single FIFO layer to a new unit cost, creating an InventoryRevaluation
        record.


        :::info[Required scope: `inventory:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Fields (CreateInventoryRevaluationData):

        - cogs_source (required, CogsSourceEnum): the source for the new cost (e.g.,
        purchase_order)

        - new_unit_cost (required, float): the new per-unit cost

        - reason (optional, InventoryRevaluationReasonEnum): reason for revaluation

        - reason_notes (optional, string): free-text notes

        - effective_at (optional, date-only YYYY-MM-DD or ISO 8601 datetime): date
        the cost change takes effect; drives the point-in-time valuation overlay and
        the GL revaluation period. Defaults to now(). If it falls inside a locked
        accounting period it is moved forward to the first open day.

        - posted_at (optional, date-only YYYY-MM-DD or ISO 8601 datetime): GL posting
        timestamp. Defaults to now().

        - old_unit_cost (optional, float): explicit prior per-unit cost; defaults
        to the layer''s current average cost.

        - old_total_cost (optional, float): explicit prior total cost for the layer.

        - new_total_cost (optional, float): explicit new total cost for the layer.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                cogs_source:
                  type: string
                new_unit_cost:
                  type: number
                reason:
                  type: string
                reason_notes:
                  type: string
                effective_at:
                  type: string
                posted_at:
                  type: string
                old_unit_cost:
                  type: integer
                old_total_cost:
                  type: integer
                new_total_cost:
                  type: integer
              example:
                cogs_source: purchase_order
                new_unit_cost: 12.33
                reason: manual_adjustment
                reason_notes: Correcting cost based on updated supplier invoice
                effective_at: '2026-04-01'
                posted_at: '2024-06-01T00:00:00Z'
                old_unit_cost: 10
                old_total_cost: 1000
                new_total_cost: 1233
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: success
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: array
                    items:
                      type: object
                      properties:
                        message:
                          type: string
                        code:
                          type: integer
                        field:
                          type: string
                example:
                  errors:
                  - message: Cannot source COGS from the specified source for this
                      layer.
                    code: 422
                    field: cogs_sourcing_error
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: inventory:write
      operationId: post-api-cogs-revaluation-id-revalue
  /api/cogs-revaluation/bulk-revalue:
    post:
      tags:
      - Costing
      summary: Bulk Revalue FIFO Layers
      description: "Revalues multiple FIFO layers in a single request.\n\n:::info[Required\
        \ scope: `inventory:write`]\nGrant this scope to your token under [Settings\
        \ → Developer → Personal Access Tokens](https://app.sku.io/settings/api).\n\
        :::\n\nAuthentication: Requires Bearer token.\n\nBody fields:\n- layerDataItems\
        \ (required): Array of layer revaluation items\n  - layerDataItems.*.fifo_layer_id:\
        \ FIFO Layer ID\n  - layerDataItems.*.cogs_source: Source of the cost value\n\
        \  - layerDataItems.*.new_unit_cost: New unit cost as float\n  - layerDataItems.*.effective_at\
        \ (optional, date-only YYYY-MM-DD or ISO 8601 datetime): Date the cost change\
        \ takes effect (per item); defaults to now(), moved to the first open day\
        \ if the period is locked\n  - layerDataItems.*.posted_at (optional): GL posting\
        \ timestamp (per item); defaults to now()\n  - layerDataItems.*.old_unit_cost\
        \ (optional): Explicit prior per-unit cost (per item)\n  - layerDataItems.*.old_total_cost\
        \ (optional): Explicit prior total cost (per item)\n  - layerDataItems.*.new_total_cost\
        \ (optional): Explicit new total cost (per item)\n- reason (required): Reason\
        \ enum value applied to all items\n- reason_notes (optional): Free-text explanation"
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                layerDataItems:
                  type: array
                  items:
                    type: object
                    properties:
                      fifo_layer_id:
                        type: integer
                      cogs_source:
                        type: string
                      new_unit_cost:
                        type: number
                      effective_at:
                        type: string
                      old_unit_cost:
                        type: integer
                reason:
                  type: string
                reason_notes:
                  type: string
              example:
                layerDataItems:
                - fifo_layer_id: 101
                  cogs_source: purchase_order
                  new_unit_cost: 14.99
                  effective_at: '2026-04-01'
                  old_unit_cost: 12
                - fifo_layer_id: 102
                  cogs_source: manual
                  new_unit_cost: 22.5
                reason: purchase_cost_update
                reason_notes: Quarterly cost reconciliation
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                example:
                  status: success
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  errors:
                    type: array
                    items:
                      type: object
                      properties:
                        message:
                          type: string
                        code:
                          type: string
                example:
                  status: error
                  errors:
                  - message: COGS sourcing error for one or more layers
                    code: cogs_sourcing_error
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: inventory:write
      operationId: post-api-cogs-revaluation-bulk-revalue
  /api/cogs-revaluation/rebuild-cogs/{id}:
    post:
      tags:
      - Costing
      summary: Rebuild COGS for Product
      description: 'Rebuilds COGS (recalculates FIFO layer costs from source documents)
        for a single product. This is a synchronous operation.


        :::info[Required scope: `inventory:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Path params:

        - product: Product ID'
      requestBody:
        content: {}
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                example:
                  status: success
                  message: COGS rebuilt successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: inventory:write
      operationId: post-api-cogs-revaluation-rebuild-cogs-id
  /api/cogs-revaluation/rebuild-cogs-bulk:
    post:
      tags:
      - Costing
      summary: Rebuild COGS for Multiple Products
      description: 'Rebuilds COGS for multiple specific products synchronously. Returns
        per-product success/failure summary.


        :::info[Required scope: `inventory:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Body fields:

        - product_ids (required): Array of product IDs (min 1, must exist in products
        table)'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                product_ids:
                  type: array
                  items:
                    type: integer
              example:
                product_ids:
                - 42
                - 78
                - 99
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      product_count:
                        type: integer
                      failed_count:
                        type: integer
                      errors:
                        type: array
                example:
                  status: success
                  message: Successfully rebuilt COGS for 3 products
                  data:
                    product_count: 3
                    failed_count: 0
                    errors: []
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      product_count:
                        type: integer
                      failed_count:
                        type: integer
                      errors:
                        type: array
                        items:
                          type: string
                example:
                  status: error
                  message: Rebuilt COGS for 2 products, 1 failed
                  data:
                    product_count: 2
                    failed_count: 1
                    errors:
                    - 'Product 99 (GADGET-XL): No FIFO layers found'
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: inventory:write
      operationId: post-api-cogs-revaluation-rebuild-cogs-bulk
  /api/cogs-revaluation/rebuild-cogs-tracked:
    post:
      tags:
      - Costing
      summary: Start Tracked COGS Rebuild
      description: 'Starts a background tracked COGS rebuild job for all products
        (or a filtered subset). Returns a tracked_job_id to poll for progress.


        :::info[Required scope: `inventory:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Body fields:

        - last_rebuilt_before (optional): Only rebuild products rebuilt before this
        date

        - product_ids (optional): Array of specific product IDs to rebuild. If omitted,
        rebuilds all products'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                last_rebuilt_before:
                  type: string
                product_ids:
                  type: array
                  items:
                    type: integer
              example:
                last_rebuilt_before: '2024-01-01'
                product_ids:
                - 42
                - 78
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      tracked_job_id:
                        type: integer
                example:
                  status: success
                  message: Tracked COGS rebuild started successfully
                  data:
                    tracked_job_id: 1234
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: inventory:write
      operationId: post-api-cogs-revaluation-rebuild-cogs-tracked
  /api/cogs-revaluation/tracked-job/{id}:
    get:
      tags:
      - Costing
      summary: Get Tracked Job Status
      description: 'Polls the status and progress of a tracked COGS rebuild job.


        :::info[Required scope: `inventory:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Path params:

        - trackedJobId: Tracked job log ID from startTrackedRebuild response'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      status:
                        type: string
                      progress_percentage:
                        type: number
                      total_items:
                        type: integer
                      processed_items:
                        type: integer
                      messages:
                        type: string
                        nullable: true
                      results:
                        type: object
                        properties:
                          batch_ids:
                            type: array
                            items:
                              type: string
                      batch_progress:
                        type: object
                        properties:
                          total_jobs:
                            type: integer
                          pending_jobs:
                            type: integer
                          processed_jobs:
                            type: integer
                          failed_jobs:
                            type: integer
                          finished:
                            type: boolean
                          cancelled:
                            type: boolean
                          progress_percentage:
                            type: number
                          chunks_count:
                            type: integer
                      created_at:
                        type: string
                      attempted_at:
                        type: string
                      completed_at:
                        type: string
                        nullable: true
                example:
                  status: success
                  data:
                    id: 1234
                    status: processing
                    progress_percentage: 65.5
                    total_items: 200
                    processed_items: 131
                    messages: null
                    results:
                      batch_ids:
                      - abc-123
                      - def-456
                    batch_progress:
                      total_jobs: 20
                      pending_jobs: 7
                      processed_jobs: 13
                      failed_jobs: 0
                      finished: false
                      cancelled: false
                      progress_percentage: 65.0
                      chunks_count: 2
                    created_at: '2024-06-15T10:00:00.000000Z'
                    attempted_at: '2024-06-15T10:00:05.000000Z'
                    completed_at: null
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  errors:
                    type: array
                    items:
                      type: object
                      properties:
                        message:
                          type: string
                        code:
                          type: string
                example:
                  status: error
                  errors:
                  - message: Tracked job not found
                    code: not_found
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: inventory:read
      operationId: get-api-cogs-revaluation-tracked-job-id
  /api/cogs-revaluation/unified-tracking/{id}:
    get:
      tags:
      - Costing
      summary: Get Unified Tracking Data
      description: 'Returns combined job status, recently rebuilt products, FIFO layer
        changes, and failed products in a single call. Replaces polling multiple endpoints.


        :::info[Required scope: `inventory:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Path params:

        - trackedJobId: Tracked job log ID


        Query params:

        - since (optional): Show products rebuilt after this datetime (default: 1
        hour ago)

        - limit (optional): Max recently rebuilt products to return (1-1000, default
        100)'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      - name: since
        in: query
        schema:
          type: string
        description: 'Show recently rebuilt products since this datetime (default:
          1 hour ago)'
        example: '2024-06-15T10:00:00Z'
      - name: limit
        in: query
        schema:
          type: integer
        description: Max recently rebuilt products to return (integer 1-1000, default
          100)
        example: '50'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  data:
                    type: object
                    properties:
                      job_status:
                        type: object
                        properties:
                          id:
                            type: integer
                          status:
                            type: string
                          progress_percentage:
                            type: number
                          total_items:
                            type: integer
                          processed_items:
                            type: integer
                          results:
                            type: object
                            properties:
                              batch_ids:
                                type: array
                                items:
                                  type: string
                          batch_progress:
                            type: object
                            properties:
                              total_jobs:
                                type: integer
                              processed_jobs:
                                type: integer
                              finished:
                                type: boolean
                          created_at:
                            type: string
                          attempted_at:
                            type: string
                          completed_at:
                            type: string
                            nullable: true
                      recently_rebuilt_products:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            sku:
                              type: string
                            name:
                              type: string
                            last_rebuilt_cogs_at:
                              type: string
                      fifo_layer_changes:
                        type: array
                        items:
                          type: object
                          properties:
                            fifo_layer_id:
                              type: integer
                            product_sku:
                              type: string
                            product_name:
                              type: string
                            warehouse_name:
                              type: string
                            before_cost:
                              type: number
                            after_cost:
                              type: number
                            cost_difference:
                              type: number
                            cost_change_percentage:
                              type: number
                            changed_at:
                              type: string
                            reason:
                              type: string
                            cogs_source:
                              type: string
                      failed_products:
                        type: array
                example:
                  status: success
                  data:
                    job_status:
                      id: 1234
                      status: processing
                      progress_percentage: 65.5
                      total_items: 200
                      processed_items: 131
                      results:
                        batch_ids:
                        - abc-123
                      batch_progress:
                        total_jobs: 20
                        processed_jobs: 13
                        finished: false
                      created_at: '2024-06-15T10:00:00.000000Z'
                      attempted_at: '2024-06-15T10:00:05.000000Z'
                      completed_at: null
                    recently_rebuilt_products:
                    - id: 42
                      sku: WIDGET-001
                      name: Blue Widget
                      last_rebuilt_cogs_at: '2024-06-15T10:05:00.000000Z'
                    fifo_layer_changes:
                    - fifo_layer_id: 101
                      product_sku: WIDGET-001
                      product_name: Blue Widget
                      warehouse_name: Main Warehouse
                      before_cost: 8.0
                      after_cost: 12.5
                      cost_difference: 4.5
                      cost_change_percentage: 56.25
                      changed_at: '2024-06-15T10:05:00.000000Z'
                      reason: rebuild
                      cogs_source: purchase_order
                    failed_products: []
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: inventory:read
      operationId: get-api-cogs-revaluation-unified-tracking-id
  /api/cogs-revaluation/cancel-tracked-rebuild/{id}:
    post:
      tags:
      - Costing
      summary: Cancel Tracked Rebuild
      description: 'Cancels a running tracked COGS rebuild job. Cancels all associated
        batch jobs and marks the tracked job as cancelled.


        :::info[Required scope: `inventory:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Path params:

        - trackedJobId: Tracked job log ID


        Note: Returns 400 if the job is already completed, failed, or cancelled.'
      requestBody:
        content: {}
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                example:
                  status: success
                  message: Job cancelled successfully - 2 batch(es) cancelled
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  errors:
                    type: array
                    items:
                      type: object
                      properties:
                        message:
                          type: string
                        code:
                          type: string
                example:
                  status: error
                  errors:
                  - message: Job cannot be cancelled - it is already completed
                    code: invalid_status
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: inventory:write
      operationId: post-api-cogs-revaluation-cancel-tracked-rebuild-id
  /api/cogs-revaluation/recently-rebuilt-products:
    get:
      tags:
      - Costing
      summary: Get Recently Rebuilt Products
      description: 'Returns a list of products that have had their COGS rebuilt recently.
        Used for monitoring rebuild progress.


        :::info[Required scope: `inventory:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Query params:

        - since (optional): Datetime filter — only return products rebuilt after this
        time (default: 1 hour ago)

        - limit (optional): Max records to return, integer 1-1000, default 100'
      parameters:
      - name: since
        in: query
        schema:
          type: string
        description: 'Only return products rebuilt after this datetime (ISO 8601,
          default: 1 hour ago)'
        example: '2024-06-01'
      - name: limit
        in: query
        schema:
          type: integer
        description: Max records to return (integer, 1-1000, default 100)
        example: '100'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        sku:
                          type: string
                        name:
                          type: string
                        last_rebuilt_cogs_at:
                          type: string
                example:
                  status: success
                  data:
                  - id: 42
                    sku: WIDGET-001
                    name: Blue Widget
                    last_rebuilt_cogs_at: '2024-06-15T14:30:00.000000Z'
                  - id: 78
                    sku: GADGET-XL
                    name: XL Gadget
                    last_rebuilt_cogs_at: '2024-06-15T14:28:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: inventory:read
      operationId: get-api-cogs-revaluation-recently-rebuilt-products
  /api/cogs-revaluation/export-fifo-changes/{id}:
    get:
      tags:
      - Costing
      summary: Export FIFO Layer Changes CSV
      description: 'Exports FIFO layer cost changes from a tracked rebuild job as
        a CSV file download.


        :::info[Required scope: `inventory:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Path params:

        - trackedJobId: Tracked job log ID


        Response: CSV file download (Content-Type: text/csv)

        Columns: Changed At, Product SKU, Product Name, Warehouse, FIFO Layer ID,
        FIFO Layer Date, Before Cost, After Cost, Cost Difference, Cost Change %,
        Original Quantity, Link Type, Revaluation ID, Drawer Reference, Reason, COGS
        Source'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: text/csv
            Content-Disposition:
              schema:
                type: string
                example: attachment; filename="fifo_layer_changes_job_1234_2024-06-15_10-00-00.csv"
          content:
            text/plain:
              schema:
                type: string
                example: '"Changed At","Product SKU","Product Name","Warehouse","FIFO
                  Layer ID","FIFO Layer Date","Before Cost","After Cost","Cost Difference","Cost
                  Change %","Original Quantity","Link Type","Revaluation ID","Drawer
                  Reference","Reason","COGS Source"

                  "2024-06-15T10:05:00.000000Z","WIDGET-001","Blue Widget","Main Warehouse","101","2024-01-15T00:00:00.000000Z","8","12.5","4.5","56.25%","500","Purchase
                  Order Receiving","55","PO-2024-0042","rebuild","purchase_order"'
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  errors:
                    type: array
                    items:
                      type: object
                      properties:
                        message:
                          type: string
                        code:
                          type: string
                example:
                  status: error
                  errors:
                  - message: No FIFO layer changes found for this job
                    code: no_changes
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: inventory:read
      operationId: get-api-cogs-revaluation-export-fifo-changes-id
  /api/v2/pro-forma/context:
    get:
      tags:
      - Product Pro Forma
      summary: Get Pro Forma Context
      description: 'Full Pro Forma Analyzer bootstrap payload.


        :::info[Required scope: `products:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Returns one channel tab per connected sales-channel family (Amazon, Shopify,
        eBay, ...) plus a `custom` tab. Each tab includes:

        - `instances` — sync-active integration instances of that family

        - `listing` (includes `product_listing_id`) — the product''s listing prefill
        (price, is_fba, listing_sku, asin) when product_id is given

        - `fee_defaults` — engine-resolved default fee lines (rate cards, instance
        settings, listing overrides) with provenance `source`

        - `supports_live_fees` — true for Amazon (use POST /amazon-fees)

        - `fulfillment_options` — `["fba", "fbm"]` for Amazon, empty otherwise

        - `history` — 12-month realized actuals on that channel including returns
        economics (`avg_refund_pct`, `recovery_rate_pct`; both null when no returns);
        null when no orders


        Also returns the product''s per-unit `cogs_breakdown` from open FIFO layers
        (falls back to a single average-cost line) and its saved `proforma_assumptions`.
        The `product` object includes `default_price` — the price at the product default
        pricing tier, used as the selling-price fallback when a channel has no listing
        price (null when no default-tier price is set).


        Channel families with no sync-active instance are excluded unless the product
        has order history there, in which case the tab is kept with an "(inactive)"
        label.


        Requires Bearer token (products scope).'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      product:
                        type: object
                        properties:
                          id:
                            type: integer
                          sku:
                            type: string
                          name:
                            type: string
                          average_cost:
                            type: integer
                          default_price:
                            type: number
                      cogs_breakdown:
                        type: array
                        items:
                          type: object
                          properties:
                            cost_category_id:
                              type: integer
                            name:
                              type: string
                            amount:
                              type: integer
                            source:
                              type: string
                      channels:
                        type: array
                        items:
                          type: object
                          properties:
                            integration_type:
                              type: string
                            label:
                              type: string
                            instances:
                              type: array
                              items:
                                type: object
                                properties:
                                  integration_instance_id:
                                    type: integer
                                  name:
                                    type: string
                                  sales_channel_id:
                                    type: integer
                            listing:
                              type: object
                              properties:
                                product_listing_id:
                                  type: integer
                                price:
                                  type: number
                                is_fba:
                                  type: boolean
                                listing_sku:
                                  type: string
                                asin:
                                  type: string
                            fee_defaults:
                              type: array
                              items:
                                type: object
                                properties:
                                  key:
                                    type: string
                                  label:
                                    type: string
                                  fee_basis:
                                    type: string
                                  percent:
                                    type: integer
                                  fixed_amount:
                                    type: string
                                    nullable: true
                                  source:
                                    type: string
                                  rate_card_version:
                                    type: string
                                  metadata:
                                    type: string
                                    nullable: true
                            supports_live_fees:
                              type: boolean
                            fulfillment_options:
                              type: array
                              items:
                                type: string
                            history:
                              type: object
                              properties:
                                orders:
                                  type: integer
                                units:
                                  type: integer
                                avg_unit_revenue:
                                  type: number
                                avg_unit_cogs:
                                  type: integer
                                avg_unit_shipping:
                                  type: number
                                avg_unit_fees:
                                  type: number
                                avg_margin_pct:
                                  type: number
                                return_rate_pct:
                                  type: number
                                avg_refund_pct:
                                  type: number
                                recovery_rate_pct:
                                  type: number
                                period:
                                  type: string
                      proforma_assumptions:
                        type: object
                        properties:
                          shipping_cost:
                            type: number
                          landed_cost_percentage:
                            type: integer
                          marketplace_cost_percentage:
                            type: string
                            nullable: true
                example:
                  data:
                    product:
                      id: 1
                      sku: GSS342
                      name: Grow Light Panel GSS342
                      average_cost: 70
                      default_price: 129.99
                    cogs_breakdown:
                    - cost_category_id: 1
                      name: Base Product
                      amount: 70
                      source: fifo
                    - cost_category_id: 3
                      name: Freight
                      amount: 4.25
                      source: fifo
                    channels:
                    - integration_type: amazon
                      label: Amazon
                      instances:
                      - integration_instance_id: 4
                        name: Amazon US
                        sales_channel_id: 2
                      listing:
                        product_listing_id: 42
                        price: 99.99
                        is_fba: true
                        listing_sku: GSS342-FBA
                        asin: B08XYZ1234
                      fee_defaults:
                      - key: referral_fee
                        label: Referral fee
                        fee_basis: percent_of_price
                        percent: 15
                        fixed_amount: null
                        source: rate_card
                        rate_card_version: 2026-01
                        metadata: null
                      - key: fba_fulfillment
                        label: FBA fulfillment fee
                        fee_basis: fixed_per_unit
                        percent: null
                        fixed_amount: 6.92
                        source: rate_card
                        rate_card_version: 2026-01
                        metadata:
                          size_tiers: standard
                      supports_live_fees: true
                      fulfillment_options:
                      - fba
                      - fbm
                      history:
                        orders: 312
                        units: 340
                        avg_unit_revenue: 98.45
                        avg_unit_cogs: 70
                        avg_unit_shipping: 1.12
                        avg_unit_fees: 21.6
                        avg_margin_pct: 8.42
                        return_rate_pct: 2.35
                        avg_refund_pct: 96.5
                        recovery_rate_pct: 41.2
                        period: 12m
                    - integration_type: custom
                      label: Custom
                      instances: []
                      listing: null
                      fee_defaults: []
                      supports_live_fees: false
                      fulfillment_options: []
                      history: null
                    proforma_assumptions:
                      shipping_cost: 4.5
                      landed_cost_percentage: 6
                      marketplace_cost_percentage: null
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: products:read
      operationId: get-api-v2-pro-forma-context
  /api/v2/pro-forma/amazon-fees:
    post:
      tags:
      - Product Pro Forma
      summary: Get Amazon Fee Estimate (Live)
      description: 'Live Amazon SP-API Product Fees v0 estimate for a price/fulfillment
        combination.


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Body fields:

        - `integration_instance_id` (required, integer) — Amazon integration instance

        - `id_type` (required, string) — `sku` (existing listing, seller SKU) or `asin`
        (catalog item)

        - `id_value` (required, string, max 255) — the seller SKU or ASIN

        - `price` (required, numeric, min 0.01) — listing price to estimate fees at

        - `is_amazon_fulfilled` (required, boolean) — true = FBA (sends OptionalFulfillmentProgram
        FBA_CORE), false = FBM

        - `refresh` (optional, boolean) — bypass the 24h cache and force a live SP-API
        call


        Results are cached for 24 hours on the exact parameter tuple; `cached` + `fetched_at`
        in the response indicate provenance. Amazon SP-API rate limit is 1 rps — keep
        `refresh` use sparing. The endpoint is throttled to 30 requests/minute (`throttle:30,1,pro-forma-amazon-fees`);
        exceeding it returns 429 Too Many Requests.


        When Amazon is unreachable or rejects the request, returns 422 with an `IntegrationApiError`
        error so the client can fall back to rate-card defaults.


        Requires Bearer token (products scope).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                integration_instance_id:
                  type: integer
                id_type:
                  type: string
                id_value:
                  type: string
                price:
                  type: number
                is_amazon_fulfilled:
                  type: boolean
                refresh:
                  type: boolean
              example:
                integration_instance_id: 4
                id_type: sku
                id_value: GSS342-FBA
                price: 99.99
                is_amazon_fulfilled: true
                refresh: false
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      id_type:
                        type: string
                      id_value:
                        type: string
                      price:
                        type: number
                      is_amazon_fulfilled:
                        type: boolean
                      total_fees_estimate:
                        type: number
                      fee_details:
                        type: array
                        items:
                          type: object
                          properties:
                            fee_type:
                              type: string
                            amount:
                              type: integer
                            included:
                              type: array
                      fetched_at:
                        type: string
                      cached:
                        type: boolean
                example:
                  data:
                    id: 12
                    integration_instance_id: 4
                    id_type: sku
                    id_value: GSS342-FBA
                    price: 99.99
                    is_amazon_fulfilled: true
                    total_fees_estimate: 21.92
                    fee_details:
                    - fee_type: ReferralFee
                      amount: 15
                      included: []
                    - fee_type: FBAFees
                      amount: 6.92
                      included:
                      - fee_type: FBAPerUnitFulfillmentFee
                        amount: 6.92
                        included: []
                    fetched_at: '2026-06-10T18:24:11.000000Z'
                    cached: false
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 422 — Amazon unavailable
                  value:
                    message: null
                    errors:
                      amazon_fees:
                      - message: 'Amazon fee estimate unavailable: Amazon fees estimate
                          returned no estimate (status: ClientError): Invalid SellerSKU'
                        code: IntegrationApiError
                        data: []
                example-1:
                  summary: 422 — validation error
                  value:
                    message: The given data was invalid.
                    errors:
                      price:
                      - message: The price must be greater than zero to estimate fees.
                        code: InternalValidation
                        data: []
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: products:write
      operationId: post-api-v2-pro-forma-amazon-fees
  /api/v2/pro-forma/history:
    get:
      tags:
      - Product Pro Forma
      summary: Get Channel Sales History (Pro Forma)
      description: 'Historical realized actuals for one product on a set of sales
        channels — the "pro forma vs. actuals" comparison.


        :::info[Required scope: `products:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Metrics (per the period):

        - `orders` — distinct order count (drafts and cancelled excluded)

        - `units` — total units sold

        - `avg_unit_revenue` / `avg_unit_cogs` / `avg_unit_fees` — per-unit averages
        from sales order line financials (fees = allocated settlement/channel costs)

        - `avg_unit_shipping` — fulfillment costs prorated to the product by quantity
        share

        - `avg_margin_pct` — profit / revenue * 100

        - `return_rate_pct` — quantity-weighted share of lines with credits or returned
        COGS

        - `avg_refund_pct` — refund $ as % of gross revenue over returned lines (null
        when the period has no returns)

        - `recovery_rate_pct` — COGS recovered (restocked) as % of COGS over returned
        lines (null when the period has no returns)


        `data` is null when the product has no qualifying orders in the period.


        Requires Bearer token (products scope).'
      parameters:
      - name: product_id
        in: query
        schema:
          type: integer
        description: Required. Product to aggregate actuals for.
        example: '1'
      - name: sales_channel_ids[]
        in: query
        schema:
          type: integer
        description: Required (min 1). Sales channel ids to scope to. Repeat for multiple.
        example: '2'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 OK — actuals
                  value:
                    data:
                      orders: 312
                      units: 340
                      avg_unit_revenue: 98.45
                      avg_unit_cogs: 70
                      avg_unit_shipping: 1.12
                      avg_unit_fees: 21.6
                      avg_margin_pct: 8.42
                      return_rate_pct: 2.35
                      avg_refund_pct: 96.5
                      recovery_rate_pct: 41.2
                      period: 12m
                example-1:
                  summary: 200 OK — no history
                  value:
                    data: null
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: products:read
      operationId: get-api-v2-pro-forma-history
  /api/v2/pro-forma/rate-cards:
    get:
      tags:
      - Product Pro Forma
      summary: List Active Rate Cards
      description: 'Active (latest effective) rate-card rows for every channel type,
        keyed by channel_type. Default-category rows only — category-specific variants
        are resolved server-side into the context fee defaults.


        :::info[Required scope: `products:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Used by the frontend calculator as offline fee defaults and for the "rates
        as of" provenance chip (`version` / `effective_from`).


        Requires Bearer token (products scope).'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      amazon:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            channel_type:
                              type: string
                            version:
                              type: string
                            effective_from:
                              type: string
                            fee_key:
                              type: string
                            label:
                              type: string
                            fee_basis:
                              type: string
                            category:
                              type: string
                            percent:
                              type: integer
                            fixed_amount:
                              type: string
                              nullable: true
                            metadata:
                              type: object
                              properties:
                                minimum_per_item:
                                  type: number
                      ebay:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            channel_type:
                              type: string
                            version:
                              type: string
                            effective_from:
                              type: string
                            fee_key:
                              type: string
                            label:
                              type: string
                            fee_basis:
                              type: string
                            category:
                              type: string
                            percent:
                              type: number
                            fixed_amount:
                              type: string
                              nullable: true
                            metadata:
                              type: string
                              nullable: true
                example:
                  data:
                    amazon:
                    - id: 1
                      channel_type: amazon
                      version: 2026-01
                      effective_from: '2026-01-15'
                      fee_key: referral_fee
                      label: Referral fee
                      fee_basis: percent_of_price
                      category: default
                      percent: 15
                      fixed_amount: null
                      metadata:
                        minimum_per_item: 0.3
                    - id: 2
                      channel_type: amazon
                      version: 2026-01
                      effective_from: '2026-01-15'
                      fee_key: fba_fulfillment
                      label: FBA fulfillment fee
                      fee_basis: fixed_per_unit
                      category: default
                      percent: null
                      fixed_amount: 6.92
                      metadata:
                        size_tiers: standard
                    ebay:
                    - id: 5
                      channel_type: ebay
                      version: 2026-01
                      effective_from: '2026-01-15'
                      fee_key: final_value_fee
                      label: Final value fee
                      fee_basis: percent_of_price
                      category: default
                      percent: 13.6
                      fixed_amount: null
                      metadata: null
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: products:read
      operationId: get-api-v2-pro-forma-rate-cards
  /api/v2/pro-forma/scenarios:
    get:
      tags:
      - Product Pro Forma
      summary: List Scenarios
      description: 'The authenticated user''s saved what-if scenarios, newest first.
        Scenarios are strictly per-user — other users'' scenarios are never returned.


        :::info[Required scope: `products:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        `product_id` null on a scenario = hypothetical product (manual profile stored
        in `inputs.manual_profile`).


        Requires Bearer token (products scope).'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        channel_type:
                          type: string
                        product_id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        inputs:
                          type: object
                          properties:
                            price:
                              type: number
                            fulfillment:
                              type: string
                            fee_overrides:
                              type: object
                              properties:
                                referral_fee:
                                  type: object
                                  properties:
                                    percent:
                                      type: integer
                            shipping_cost:
                              type: integer
                        outputs:
                          type: object
                          properties:
                            net_profit:
                              type: number
                            margin_pct:
                              type: number
                            roi_pct:
                              type: number
                            breakeven_price:
                              type: number
                        rate_card_version:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                example:
                  data:
                  - id: 3
                    name: Amazon FBA at $99.99
                    channel_type: amazon
                    product_id: 1
                    integration_instance_id: 4
                    inputs:
                      price: 99.99
                      fulfillment: fba
                      fee_overrides:
                        referral_fee:
                          percent: 15
                      shipping_cost: 0
                    outputs:
                      net_profit: 8.29
                      margin_pct: 8.29
                      roi_pct: 11.84
                      breakeven_price: 91.7
                    rate_card_version: 2026-01
                    created_at: '2026-06-10T18:24:11.000000Z'
                    updated_at: '2026-06-10T18:24:11.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: products:read
      operationId: get-api-v2-pro-forma-scenarios
    post:
      tags:
      - Product Pro Forma
      summary: Create Scenario
      description: 'Save a what-if scenario snapshot for the authenticated user.


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Body fields:

        - `name` (required, string, max 255)

        - `channel_type` (required, string, max 50) — e.g. amazon, shopify, ebay,
        custom

        - `product_id` (optional, nullable, integer, exists:products) — null for hypothetical
        products (store the manual profile in `inputs.manual_profile`)

        - `integration_instance_id` (optional, nullable, integer, exists:integration_instances)

        - `inputs` (required, object) — full input snapshot: prices, fee overrides,
        advanced levers, manual_profile

        - `outputs` (required, object) — computed metrics snapshot: net_profit, margin_pct,
        roi_pct, breakeven_price, ...

        - `rate_card_version` (optional, nullable, string, max 50) — rate-card version
        used, enables "superseded rates" prompts


        Requires Bearer token (products scope).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                channel_type:
                  type: string
                product_id:
                  type: integer
                integration_instance_id:
                  type: integer
                inputs:
                  type: object
                  properties:
                    price:
                      type: number
                    fulfillment:
                      type: string
                    fee_overrides:
                      type: object
                      properties:
                        referral_fee:
                          type: object
                          properties:
                            percent:
                              type: integer
                    shipping_cost:
                      type: integer
                outputs:
                  type: object
                  properties:
                    net_profit:
                      type: number
                    margin_pct:
                      type: number
                    roi_pct:
                      type: number
                    breakeven_price:
                      type: number
                rate_card_version:
                  type: string
              example:
                name: Amazon FBA at $99.99
                channel_type: amazon
                product_id: 1
                integration_instance_id: 4
                inputs:
                  price: 99.99
                  fulfillment: fba
                  fee_overrides:
                    referral_fee:
                      percent: 15
                  shipping_cost: 0
                outputs:
                  net_profit: 8.29
                  margin_pct: 8.29
                  roi_pct: 11.84
                  breakeven_price: 91.7
                rate_card_version: 2026-01
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      channel_type:
                        type: string
                      product_id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      inputs:
                        type: object
                        properties:
                          price:
                            type: number
                          fulfillment:
                            type: string
                          fee_overrides:
                            type: object
                            properties:
                              referral_fee:
                                type: object
                                properties:
                                  percent:
                                    type: integer
                          shipping_cost:
                            type: integer
                      outputs:
                        type: object
                        properties:
                          net_profit:
                            type: number
                          margin_pct:
                            type: number
                          roi_pct:
                            type: number
                          breakeven_price:
                            type: number
                      rate_card_version:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 3
                    name: Amazon FBA at $99.99
                    channel_type: amazon
                    product_id: 1
                    integration_instance_id: 4
                    inputs:
                      price: 99.99
                      fulfillment: fba
                      fee_overrides:
                        referral_fee:
                          percent: 15
                      shipping_cost: 0
                    outputs:
                      net_profit: 8.29
                      margin_pct: 8.29
                      roi_pct: 11.84
                      breakeven_price: 91.7
                    rate_card_version: 2026-01
                    created_at: '2026-06-10T18:24:11.000000Z'
                    updated_at: '2026-06-10T18:24:11.000000Z'
                  message: Scenario saved
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      name:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: array
                example:
                  message: The given data was invalid.
                  errors:
                    name:
                    - message: The name field is required.
                      code: InternalValidation
                      data: []
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: products:write
      operationId: post-api-v2-pro-forma-scenarios
  /api/v2/pro-forma/scenarios/{scenarioId}:
    patch:
      tags:
      - Product Pro Forma
      summary: Update Scenario
      description: 'Partially update a saved scenario. All fields optional (`sometimes`):
        name, channel_type, product_id, integration_instance_id, inputs, outputs,
        rate_card_version.


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        `inputs` and `outputs`, when present, are FULL snapshots — last write wins,
        no deep merge.


        Returns 404 when the scenario does not exist or belongs to another user.


        Requires Bearer token (products scope).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                inputs:
                  type: object
                  properties:
                    price:
                      type: number
                    fulfillment:
                      type: string
                outputs:
                  type: object
                  properties:
                    net_profit:
                      type: number
                    margin_pct:
                      type: number
              example:
                name: Amazon FBA at $109.99
                inputs:
                  price: 109.99
                  fulfillment: fba
                outputs:
                  net_profit: 14.8
                  margin_pct: 13.46
      parameters:
      - name: scenarioId
        in: path
        schema:
          type: integer
        required: true
        description: Scenario id (must belong to the authenticated user)
        example: '3'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      channel_type:
                        type: string
                      product_id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      inputs:
                        type: object
                        properties:
                          price:
                            type: number
                          fulfillment:
                            type: string
                      outputs:
                        type: object
                        properties:
                          net_profit:
                            type: number
                          margin_pct:
                            type: number
                      rate_card_version:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 3
                    name: Amazon FBA at $109.99
                    channel_type: amazon
                    product_id: 1
                    integration_instance_id: 4
                    inputs:
                      price: 109.99
                      fulfillment: fba
                    outputs:
                      net_profit: 14.8
                      margin_pct: 13.46
                    rate_card_version: 2026-01
                    created_at: '2026-06-10T18:24:11.000000Z'
                    updated_at: '2026-06-10T18:24:11.000000Z'
                  message: Scenario updated
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Not Found
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: products:write
      operationId: patch-api-v2-pro-forma-scenarios-scenarioid
    delete:
      tags:
      - Product Pro Forma
      summary: Delete Scenario
      description: 'Delete a saved scenario. Returns 404 when the scenario does not
        exist or belongs to another user.


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Requires Bearer token (products scope).'
      parameters:
      - name: scenarioId
        in: path
        schema:
          type: integer
        required: true
        description: Scenario id (must belong to the authenticated user)
        example: '3'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Scenario deleted
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Not Found
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: products:write
      operationId: delete-api-v2-pro-forma-scenarios-scenarioid
  /api/v2/pro-forma/products/{productId}/assumptions:
    patch:
      tags:
      - Product Pro Forma
      summary: Update Product Assumptions
      description: 'Persist product-level pro forma assumptions used as analyzer defaults,
        plus optional per-listing marketplace fee overrides.


        :::info[Required scope: `products:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Body fields (all optional/nullable):

        - `proforma_shipping_cost` (numeric, min 0) — default outbound shipping cost
        per unit

        - `proforma_landed_cost_percentage` (numeric, 0-100) — landed cost uplift
        percent

        - `proforma_marketplace_cost_percentage` (numeric, 0-100) — marketplace fee
        override percent (beats rate cards; listing-level value beats this)

        - `listings` (array, optional) — per-listing marketplace fee overrides

        - `listings.*.product_listing_id` (integer, required with listings, must exist)
        — listing to override; silently ignored if the listing does not belong to
        this product

        - `listings.*.proforma_marketplace_cost_percentage` (numeric|null, 0-100)
        — listing-level marketplace fee override percent (null clears the override)


        Requires Bearer token (products scope).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                proforma_shipping_cost:
                  type: number
                proforma_landed_cost_percentage:
                  type: integer
                proforma_marketplace_cost_percentage:
                  type: integer
                listings:
                  type: array
                  items:
                    type: object
                    properties:
                      product_listing_id:
                        type: integer
                      proforma_marketplace_cost_percentage:
                        type: number
              example:
                proforma_shipping_cost: 4.5
                proforma_landed_cost_percentage: 6
                proforma_marketplace_cost_percentage: 14
                listings:
                - product_listing_id: 42
                  proforma_marketplace_cost_percentage: 14.5
      parameters:
      - name: productId
        in: path
        schema:
          type: integer
        required: true
        description: Product id
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      shipping_cost:
                        type: number
                      landed_cost_percentage:
                        type: integer
                      marketplace_cost_percentage:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    shipping_cost: 4.5
                    landed_cost_percentage: 6
                    marketplace_cost_percentage: 14
                  message: Pro forma assumptions updated
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      proforma_landed_cost_percentage:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: array
                example:
                  message: The given data was invalid.
                  errors:
                    proforma_landed_cost_percentage:
                    - message: The landed cost percentage must be between 0 and 100.
                      code: InternalValidation
                      data: []
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: products:write
      operationId: patch-api-v2-pro-forma-products-productid-assumptions
  /api/open-to-buy/merchandise-plans:
    get:
      tags:
      - Merchandise Planning
      summary: List Merchandise Plans
      description: 'Paginated Open-to-Buy plan grid. Each row carries its live OTB
        breakdown (otb_value, committed_value, effective_otb_value, otb_remaining_value,
        status) computed on read.


        Effective budget = min(computed OTB, budget_cap_value) when a manual cash
        cap is set; otb_remaining_value = effective budget − committed.


        Requires a Bearer token with the `inventory` read/write scope (middleware:
        scope.rw:inventory).'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        retail_period_id:
                          type: integer
                        node_type:
                          type: string
                        node_id:
                          type: integer
                        planned_sales_value:
                          type: integer
                        planned_sales_units:
                          type: integer
                        planned_markdown_value:
                          type: integer
                        planned_eop_value:
                          type: integer
                        planned_eop_units:
                          type: integer
                        bop_value:
                          type: integer
                        bop_units:
                          type: integer
                        otb_value:
                          type: integer
                        otb_units:
                          type: integer
                        on_order_value:
                          type: integer
                        committed_value:
                          type: integer
                        budget_cap_value:
                          type: integer
                        effective_otb_value:
                          type: integer
                        otb_remaining_value:
                          type: integer
                        status:
                          type: string
                        budget_enforced:
                          type: boolean
                        retail_period:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            type:
                              type: string
                            start_date:
                              type: string
                            end_date:
                              type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - id: 1
                    retail_period_id: 5
                    node_type: category
                    node_id: 1
                    planned_sales_value: 80000
                    planned_sales_units: 1600
                    planned_markdown_value: 2000
                    planned_eop_value: 30000
                    planned_eop_units: 600
                    bop_value: 25000
                    bop_units: 500
                    otb_value: 87000
                    otb_units: 1700
                    on_order_value: 0
                    committed_value: 0
                    budget_cap_value: 30000
                    effective_otb_value: 30000
                    otb_remaining_value: 30000
                    status: under_budget
                    budget_enforced: false
                    retail_period:
                      id: 5
                      name: Fall 2026
                      type: season
                      start_date: '2026-08-01'
                      end_date: '2026-10-31'
                    created_at: '2026-06-22T14:03:11.000000Z'
                    updated_at: '2026-06-22T14:09:52.000000Z'
                  current_page: 1
                  last_page: 1
                  per_page: 10
                  total: 1
                  from: 1
                  to: 1
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-open-to-buy-merchandise-plans
    post:
      tags:
      - Merchandise Planning
      summary: Create Merchandise Plan
      description: 'Create a plan row for a node/period and compute its initial OTB.


        Fields:

        - retail_period_id (required, integer, exists)

        - node_type (required, enum: category | brand | department | product)

        - node_id (required, integer >= 0)

        - planned_sales_value (optional, numeric >= 0)

        - planned_sales_units (optional, integer >= 0)

        - planned_markdown_value (optional, numeric >= 0)

        - planned_eop_value (optional, numeric >= 0)

        - planned_eop_units (optional, integer >= 0)

        - budget_enforced (optional, boolean) — enforce the OTB guardrail on forecast
        buys

        - budget_cap_value (optional, nullable, numeric >= 0) — manual cash ceiling;
        effective budget = min(computed OTB, this)


        Requires the `inventory` read/write scope.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                retail_period_id:
                  type: integer
                node_type:
                  type: string
                node_id:
                  type: integer
                planned_sales_value:
                  type: integer
                planned_sales_units:
                  type: integer
                planned_markdown_value:
                  type: integer
                planned_eop_value:
                  type: integer
                planned_eop_units:
                  type: integer
                budget_enforced:
                  type: boolean
                budget_cap_value:
                  type: integer
              example:
                retail_period_id: 5
                node_type: category
                node_id: 1
                planned_sales_value: 80000
                planned_sales_units: 1600
                planned_markdown_value: 2000
                planned_eop_value: 30000
                planned_eop_units: 600
                budget_enforced: false
                budget_cap_value: 30000
      parameters: []
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      retail_period_id:
                        type: integer
                      node_type:
                        type: string
                      node_id:
                        type: integer
                      planned_sales_value:
                        type: integer
                      planned_sales_units:
                        type: integer
                      planned_markdown_value:
                        type: integer
                      planned_eop_value:
                        type: integer
                      planned_eop_units:
                        type: integer
                      bop_value:
                        type: integer
                      bop_units:
                        type: integer
                      otb_value:
                        type: integer
                      otb_units:
                        type: integer
                      on_order_value:
                        type: integer
                      committed_value:
                        type: integer
                      budget_cap_value:
                        type: integer
                      effective_otb_value:
                        type: integer
                      otb_remaining_value:
                        type: integer
                      status:
                        type: string
                      budget_enforced:
                        type: boolean
                      retail_period:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          type:
                            type: string
                          start_date:
                            type: string
                          end_date:
                            type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 1
                    retail_period_id: 5
                    node_type: category
                    node_id: 1
                    planned_sales_value: 80000
                    planned_sales_units: 1600
                    planned_markdown_value: 2000
                    planned_eop_value: 30000
                    planned_eop_units: 600
                    bop_value: 25000
                    bop_units: 500
                    otb_value: 87000
                    otb_units: 1700
                    on_order_value: 0
                    committed_value: 0
                    budget_cap_value: 30000
                    effective_otb_value: 30000
                    otb_remaining_value: 30000
                    status: under_budget
                    budget_enforced: false
                    retail_period:
                      id: 5
                      name: Fall 2026
                      type: season
                      start_date: '2026-08-01'
                      end_date: '2026-10-31'
                    created_at: '2026-06-22T14:03:11.000000Z'
                    updated_at: '2026-06-22T14:09:52.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-open-to-buy-merchandise-plans
  /api/open-to-buy/merchandise-plans/seed:
    post:
      tags:
      - Merchandise Planning
      summary: Seed Plan From Forecast / Last Year
      description: "Seed a period's grid in bulk from a forecast or last-year actuals.\
        \ Each incoming node row upserts a plan and gets its OTB computed.\n\nFields:\n\
        - retail_period_id (required, integer, exists)\n- source (required, one of:\
        \ forecast, last_year)\n- rows (required, array, min 1)\n  - rows.*.node_type\
        \ (required, enum: category | brand | department | product)\n  - rows.*.node_id\
        \ (required, integer >= 0)\n  - rows.*.planned_sales_value (optional, numeric\
        \ >= 0)\n  - rows.*.planned_sales_units (optional, integer >= 0)\n  - rows.*.planned_markdown_value\
        \ (optional, numeric >= 0)\n  - rows.*.planned_eop_value (optional, numeric\
        \ >= 0)\n  - rows.*.planned_eop_units (optional, integer >= 0)\n\nRequires\
        \ the `inventory` read/write scope."
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                retail_period_id:
                  type: integer
                source:
                  type: string
                rows:
                  type: array
                  items:
                    type: object
                    properties:
                      node_type:
                        type: string
                      node_id:
                        type: integer
                      planned_sales_value:
                        type: integer
                      planned_sales_units:
                        type: integer
                      planned_markdown_value:
                        type: integer
                      planned_eop_value:
                        type: integer
                      planned_eop_units:
                        type: integer
              example:
                retail_period_id: 5
                source: forecast
                rows:
                - node_type: category
                  node_id: 1
                  planned_sales_value: 80000
                  planned_sales_units: 1600
                  planned_markdown_value: 2000
                  planned_eop_value: 30000
                  planned_eop_units: 600
                - node_type: category
                  node_id: 2
                  planned_sales_value: 45000
                  planned_sales_units: 900
                  planned_markdown_value: 1000
                  planned_eop_value: 18000
                  planned_eop_units: 360
      parameters: []
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        retail_period_id:
                          type: integer
                        node_type:
                          type: string
                        node_id:
                          type: integer
                        planned_sales_value:
                          type: integer
                        planned_sales_units:
                          type: integer
                        planned_markdown_value:
                          type: integer
                        planned_eop_value:
                          type: integer
                        planned_eop_units:
                          type: integer
                        bop_value:
                          type: integer
                        bop_units:
                          type: integer
                        otb_value:
                          type: integer
                        otb_units:
                          type: integer
                        on_order_value:
                          type: integer
                        committed_value:
                          type: integer
                        budget_cap_value:
                          type: integer
                        effective_otb_value:
                          type: integer
                        otb_remaining_value:
                          type: integer
                        status:
                          type: string
                        budget_enforced:
                          type: boolean
                        retail_period:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            type:
                              type: string
                            start_date:
                              type: string
                            end_date:
                              type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                example:
                  data:
                  - id: 1
                    retail_period_id: 5
                    node_type: category
                    node_id: 1
                    planned_sales_value: 80000
                    planned_sales_units: 1600
                    planned_markdown_value: 2000
                    planned_eop_value: 30000
                    planned_eop_units: 600
                    bop_value: 25000
                    bop_units: 500
                    otb_value: 87000
                    otb_units: 1700
                    on_order_value: 0
                    committed_value: 0
                    budget_cap_value: 30000
                    effective_otb_value: 30000
                    otb_remaining_value: 30000
                    status: under_budget
                    budget_enforced: false
                    retail_period:
                      id: 5
                      name: Fall 2026
                      type: season
                      start_date: '2026-08-01'
                      end_date: '2026-10-31'
                    created_at: '2026-06-22T14:03:11.000000Z'
                    updated_at: '2026-06-22T14:09:52.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-open-to-buy-merchandise-plans-seed
  /api/open-to-buy/merchandise-plans/{merchandisePlan}:
    get:
      tags:
      - Merchandise Planning
      summary: Get Merchandise Plan
      description: 'Show a single plan row with its live OTB breakdown (including
        budget_cap_value, effective_otb_value, otb_remaining_value).


        Requires the `inventory` read/write scope.'
      parameters:
      - name: merchandisePlan
        in: path
        schema:
          type: integer
        required: true
        description: Merchandise plan id.
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      retail_period_id:
                        type: integer
                      node_type:
                        type: string
                      node_id:
                        type: integer
                      planned_sales_value:
                        type: integer
                      planned_sales_units:
                        type: integer
                      planned_markdown_value:
                        type: integer
                      planned_eop_value:
                        type: integer
                      planned_eop_units:
                        type: integer
                      bop_value:
                        type: integer
                      bop_units:
                        type: integer
                      otb_value:
                        type: integer
                      otb_units:
                        type: integer
                      on_order_value:
                        type: integer
                      committed_value:
                        type: integer
                      budget_cap_value:
                        type: integer
                      effective_otb_value:
                        type: integer
                      otb_remaining_value:
                        type: integer
                      status:
                        type: string
                      budget_enforced:
                        type: boolean
                      retail_period:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          type:
                            type: string
                          start_date:
                            type: string
                          end_date:
                            type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 1
                    retail_period_id: 5
                    node_type: category
                    node_id: 1
                    planned_sales_value: 80000
                    planned_sales_units: 1600
                    planned_markdown_value: 2000
                    planned_eop_value: 30000
                    planned_eop_units: 600
                    bop_value: 25000
                    bop_units: 500
                    otb_value: 87000
                    otb_units: 1700
                    on_order_value: 0
                    committed_value: 0
                    budget_cap_value: 30000
                    effective_otb_value: 30000
                    otb_remaining_value: 30000
                    status: under_budget
                    budget_enforced: false
                    retail_period:
                      id: 5
                      name: Fall 2026
                      type: season
                      start_date: '2026-08-01'
                      end_date: '2026-10-31'
                    created_at: '2026-06-22T14:03:11.000000Z'
                    updated_at: '2026-06-22T14:09:52.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-open-to-buy-merchandise-plans-merchandiseplan
    patch:
      tags:
      - Merchandise Planning
      summary: Update Merchandise Plan (cell save / cash cap)
      description: 'Update editable plan cell(s) — a debounced save — and recompute
        OTB. PATCH only the changed fields.


        Fields (all optional / ''sometimes''):

        - planned_sales_value (numeric >= 0)

        - planned_sales_units (integer >= 0)

        - planned_markdown_value (numeric >= 0)

        - planned_eop_value (numeric >= 0)

        - planned_eop_units (integer >= 0)

        - budget_enforced (boolean)

        - budget_cap_value (nullable, numeric >= 0) — set a manual cash ceiling; pass
        null to clear it (back to the full computed OTB)


        When a cash cap below the computed OTB is set, effective_otb_value and otb_remaining_value
        drop to the cap.


        Requires the `inventory` read/write scope.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                planned_sales_value:
                  type: integer
                planned_eop_value:
                  type: integer
                budget_enforced:
                  type: boolean
                budget_cap_value:
                  type: integer
              example:
                planned_sales_value: 80000
                planned_eop_value: 30000
                budget_enforced: false
                budget_cap_value: 30000
      parameters:
      - name: merchandisePlan
        in: path
        schema:
          type: integer
        required: true
        description: Merchandise plan id.
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      retail_period_id:
                        type: integer
                      node_type:
                        type: string
                      node_id:
                        type: integer
                      planned_sales_value:
                        type: integer
                      planned_sales_units:
                        type: integer
                      planned_markdown_value:
                        type: integer
                      planned_eop_value:
                        type: integer
                      planned_eop_units:
                        type: integer
                      bop_value:
                        type: integer
                      bop_units:
                        type: integer
                      otb_value:
                        type: integer
                      otb_units:
                        type: integer
                      on_order_value:
                        type: integer
                      committed_value:
                        type: integer
                      budget_cap_value:
                        type: integer
                      effective_otb_value:
                        type: integer
                      otb_remaining_value:
                        type: integer
                      status:
                        type: string
                      budget_enforced:
                        type: boolean
                      retail_period:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          type:
                            type: string
                          start_date:
                            type: string
                          end_date:
                            type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 1
                    retail_period_id: 5
                    node_type: category
                    node_id: 1
                    planned_sales_value: 80000
                    planned_sales_units: 1600
                    planned_markdown_value: 2000
                    planned_eop_value: 30000
                    planned_eop_units: 600
                    bop_value: 25000
                    bop_units: 500
                    otb_value: 87000
                    otb_units: 1700
                    on_order_value: 0
                    committed_value: 0
                    budget_cap_value: 30000
                    effective_otb_value: 30000
                    otb_remaining_value: 30000
                    status: under_budget
                    budget_enforced: false
                    retail_period:
                      id: 5
                      name: Fall 2026
                      type: season
                      start_date: '2026-08-01'
                      end_date: '2026-10-31'
                    created_at: '2026-06-22T14:03:11.000000Z'
                    updated_at: '2026-06-22T14:09:52.000000Z'
        '422':
          description: Unprocessable Content
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      budget_cap_value:
                        type: array
                        items:
                          type: string
                example:
                  message: The cash cap cannot be negative.
                  errors:
                    budget_cap_value:
                    - The cash cap cannot be negative.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: patch-api-open-to-buy-merchandise-plans-merchandiseplan
  /api/open-to-buy/merchandise-plans/{merchandisePlan}/otb:
    get:
      tags:
      - Merchandise Planning
      summary: Get OTB Breakdown
      description: 'Live OTB + remaining + committed breakdown for a plan row.


        Returns: otb_value, otb_units, bop_value, bop_units, on_order_value, committed_value,
        budget_cap_value (nullable), effective_otb_value (= min(otb_value, cap)),
        otb_remaining_value (= effective − committed), and status (under_budget |
        near_budget | over_budget).


        Requires the `inventory` read/write scope.'
      parameters:
      - name: merchandisePlan
        in: path
        schema:
          type: integer
        required: true
        description: Merchandise plan id.
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      otb_value:
                        type: integer
                      otb_units:
                        type: integer
                      bop_value:
                        type: integer
                      bop_units:
                        type: integer
                      on_order_value:
                        type: integer
                      committed_value:
                        type: integer
                      budget_cap_value:
                        type: integer
                      effective_otb_value:
                        type: integer
                      otb_remaining_value:
                        type: integer
                      status:
                        type: string
                example:
                  data:
                    otb_value: 87000
                    otb_units: 1700
                    bop_value: 25000
                    bop_units: 500
                    on_order_value: 0
                    committed_value: 0
                    budget_cap_value: 30000
                    effective_otb_value: 30000
                    otb_remaining_value: 30000
                    status: under_budget
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-open-to-buy-merchandise-plans-merchandiseplan-otb
  /api/v2/serial-numbers:
    get:
      tags:
      - Serial Numbers
      summary: List Serial Numbers
      description: Paginated list of individual serial numbers across all products,
        with their lifecycle status and current location/order. Filter by product,
        status, or warehouse, and search the serial value.
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        serial:
                          type: string
                        status:
                          type: string
                        status_label:
                          type: string
                        product:
                          type: object
                          properties:
                            id:
                              type: integer
                            sku:
                              type: string
                            name:
                              type: string
                            link_route:
                              type: string
                        warehouse:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        received_at:
                          type: string
                        shipped_at:
                          type: string
                          nullable: true
                        current_order:
                          type: string
                          nullable: true
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 91
                    serial: SN-100482
                    status: in_stock
                    status_label: In Stock
                    product:
                      id: 2
                      sku: WIDGET-SN
                      name: Serialized Widget
                      link_route: /products/2
                    warehouse:
                      id: 1
                      name: Main Warehouse
                    received_at: '2026-07-19T10:00:00.000000Z'
                    shipped_at: null
                    current_order: null
                  current_page: 1
                  last_page: 1
                  per_page: 10
                  total: 1
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-v2-serial-numbers
  /api/v2/serial-numbers/{serialNumber}:
    get:
      tags:
      - Serial Numbers
      summary: Get Serial Number
      description: A single serial's full detail plus its genealogy timeline (received
        → allocated → committed → shipped → returned/scrapped/quarantined), each event
        cross-linked to its source document, order and customer.
      parameters:
      - name: serialNumber
        in: path
        schema:
          type: integer
        required: true
        description: Serial number id
        example: '91'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      serial:
                        type: string
                      status:
                        type: string
                      status_label:
                        type: string
                      product:
                        type: object
                        properties:
                          id:
                            type: integer
                          sku:
                            type: string
                          name:
                            type: string
                          link_route:
                            type: string
                      warehouse:
                        type: string
                        nullable: true
                      received_at:
                        type: string
                      shipped_at:
                        type: string
                      current_order:
                        type: object
                        properties:
                          number:
                            type: string
                          link_route:
                            type: string
                      warranty_start_at:
                        type: string
                      warranty_registration_ref:
                        type: string
                        nullable: true
                      disposition_reason:
                        type: string
                        nullable: true
                      timeline:
                        type: array
                        items:
                          type: object
                          properties:
                            event:
                              type: string
                            at:
                              type: string
                            movement_id:
                              type: integer
                            link_reference:
                              type: string
                            link_route:
                              type: string
                example:
                  data:
                    id: 91
                    serial: SN-100482
                    status: shipped
                    status_label: Shipped
                    product:
                      id: 2
                      sku: WIDGET-SN
                      name: Serialized Widget
                      link_route: /products/2
                    warehouse: null
                    received_at: '2026-07-19T10:00:00.000000Z'
                    shipped_at: '2026-07-21T09:00:00.000000Z'
                    current_order:
                      number: SO-1234
                      link_route: /orders/sales-orders/33
                    warranty_start_at: '2026-07-21'
                    warranty_registration_ref: null
                    disposition_reason: null
                    timeline:
                    - event: received
                      at: '2026-07-19T10:00:00.000000Z'
                      movement_id: 10
                      link_reference: PO-4501
                      link_route: /orders/purchase-orders/9
                    - event: shipped
                      at: '2026-07-21T09:00:00.000000Z'
                      movement_id: 55
                      sales_order_number: SO-1234
                      customer_name: Acme Corporation
                      link_route: /orders/sales-orders/33
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-v2-serial-numbers-serialnumber
  /api/v2/products/{product}/serial-numbers:
    get:
      tags:
      - Serial Numbers
      summary: List Product Serial Numbers
      description: The serials for a single product (per-product tab). Same filters/sorts
        as the global list.
      parameters:
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: Product id
        example: '2'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        serial:
                          type: string
                        status:
                          type: string
                        status_label:
                          type: string
                        product:
                          type: object
                          properties:
                            id:
                              type: integer
                            sku:
                              type: string
                            name:
                              type: string
                            link_route:
                              type: string
                        warehouse:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        received_at:
                          type: string
                        shipped_at:
                          type: string
                          nullable: true
                        current_order:
                          type: string
                          nullable: true
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 91
                    serial: SN-100482
                    status: in_stock
                    status_label: In Stock
                    product:
                      id: 2
                      sku: WIDGET-SN
                      name: Serialized Widget
                      link_route: /products/2
                    warehouse:
                      id: 1
                      name: Main Warehouse
                    received_at: '2026-07-19T10:00:00.000000Z'
                    shipped_at: null
                    current_order: null
                  current_page: 1
                  last_page: 1
                  per_page: 10
                  total: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-v2-products-product-serial-numbers
  /api/v2/serial-numbers/quarantine:
    post:
      tags:
      - Serial Numbers
      summary: Quarantine Serial Numbers
      description: 'Hold one or more serials (recall / damage / inspection). Quarantined
        serials are excluded from availability and cannot be allocated or shipped
        until released.


        Body: serial_number_ids (required array of ids), reason (optional).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                serial_number_ids:
                  type: array
                  items:
                    type: integer
                reason:
                  type: string
              example:
                serial_number_ids:
                - 91
                - 92
                reason: Recall batch 2026-07
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      quarantined:
                        type: integer
                example:
                  data:
                    quarantined: 2
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-v2-serial-numbers-quarantine
  /api/v2/serial-numbers/release:
    post:
      tags:
      - Serial Numbers
      summary: Release Serial Numbers
      description: 'Release quarantined serials back to in-stock. Body: serial_number_ids
        (required array).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                serial_number_ids:
                  type: array
                  items:
                    type: integer
              example:
                serial_number_ids:
                - 91
                - 92
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      released:
                        type: integer
                example:
                  data:
                    released: 2
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-v2-serial-numbers-release
  /api/v2/serial-numbers/recall-impact:
    get:
      tags:
      - Serial Numbers
      summary: Serial Recall Impact
      description: For a product (optionally narrowed to one receiving movement),
        list the shipped serials with the orders/customers they went to — the affected-customer
        list for a recall.
      parameters:
      - name: product_id
        in: query
        schema:
          type: integer
        description: Required. Product to assess.
        example: '2'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        serial:
                          type: string
                        sales_order_number:
                          type: string
                        customer_name:
                          type: string
                        shipped_at:
                          type: string
                example:
                  data:
                  - serial: SN-100482
                    sales_order_number: SO-1234
                    customer_name: Acme Corporation
                    shipped_at: '2026-07-21'
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-v2-serial-numbers-recall-impact
  /api/reporting/landed-cost-breakdown:
    post:
      tags:
      - Landed Cost Breakdown
      summary: Generate Landed Cost Breakdown Report
      description: 'Dispatch a filtered, hierarchically-grouped report (brand > product)
        restricted to a specific sales channel and warehouse. Returns a `tracked_job_log_id`;
        fetch the payload from the result endpoint once the job completes.


        :::info[Required scope: `reports:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Demonstrates hierarchical grouping combined with filtering — useful for drilling
        into specific segments of the business.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                date_from:
                  type: string
                date_to:
                  type: string
                group_by:
                  type: array
                  items:
                    type: string
                sales_channel_ids:
                  type: array
                  items:
                    type: integer
                warehouse_ids:
                  type: array
                  items:
                    type: integer
              example:
                date_from: '2025-01-01'
                date_to: '2025-12-31'
                group_by:
                - brand
                - product
                sales_channel_ids:
                - 1
                warehouse_ids:
                - 1
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: reports:write
      operationId: post-api-reporting-landed-cost-breakdown
  /api/reporting/landed-cost-breakdown/result/{trackedJobLog}:
    get:
      tags:
      - Landed Cost Breakdown
      summary: Get Generated Report Result
      description: 'Fetch the generated landed cost breakdown payload for a completed
        generation job. Call this once the tracked job (from the generate endpoint)
        reaches `completed`.


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        **Response structure:**

        - `group_by` — the grouping dimensions used.

        - `date_range` — `{ from, to }` for the report.

        - `categories` — the cost categories present in the report (`id`, `name`,
        `is_system`).

        - `groups` — hierarchical breakdown by the grouping dimensions, each with
        `totals` and nested `children`.

        - `grand_totals` — aggregate totals across all groups.


        **Status codes:**

        - `200` — payload returned.

        - `403` — the authenticated user did not generate this report.

        - `404` — the report is not ready yet (job still running) or the cached payload
        has expired (~1 hour TTL). Regenerate.


        **Authentication:** Requires a bearer token. Scoped to the user who generated
        the report.'
      parameters:
      - name: trackedJobLog
        in: path
        schema:
          type: integer
        required: true
        description: The tracked_job_log_id returned by the generate endpoint.
        example: '4821'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: Success Response
                  value:
                    group_by:
                    - sales_channel
                    date_range:
                      from: '2025-01-01'
                      to: '2025-12-31'
                    categories:
                    - id: 1
                      name: Base Product Cost
                      is_system: true
                    - id: 2
                      name: Freight
                      is_system: true
                    - id: 3
                      name: Customs Duty
                      is_system: true
                    groups:
                    - key: Amazon US
                      totals:
                        quantity_sold: 1250
                        base_product: 45230
                        freight: 8540.25
                        customs_duty: 2150
                        brokerage: 425
                        insurance: 312.5
                        handling: 625
                        taxes: 4523
                        other_costs: 180.75
                        total_landed_cost: 61986.5
                      children: []
                    - key: Shopify
                      totals:
                        quantity_sold: 850
                        base_product: 28750
                        freight: 4250
                        customs_duty: 0
                        brokerage: 0
                        insurance: 187.5
                        handling: 425
                        taxes: 2875
                        other_costs: 95.25
                        total_landed_cost: 36582.75
                      children: []
                    grand_totals:
                      quantity_sold: 2100
                      base_product: 73980
                      freight: 12790.25
                      customs_duty: 2150
                      brokerage: 425
                      insurance: 500
                      handling: 1050
                      taxes: 7398
                      other_costs: 276
                      total_landed_cost: 98569.25
                example-1:
                  summary: Hierarchical Grouping Response
                  value:
                    group_by:
                    - sales_channel
                    - brand
                    date_range:
                      from: '2025-01-01'
                      to: '2025-12-31'
                    categories:
                    - id: 1
                      name: Base Product Cost
                      is_system: true
                    - id: 2
                      name: Freight
                      is_system: true
                    groups:
                    - key: Amazon US
                      totals:
                        quantity_sold: 1250
                        base_product: 45230
                        freight: 8540.25
                        total_landed_cost: 61986.5
                      children:
                      - key: Brand A
                        totals:
                          quantity_sold: 750
                          base_product: 28000
                          freight: 5200
                          total_landed_cost: 38395
                        children: []
                      - key: Brand B
                        totals:
                          quantity_sold: 500
                          base_product: 17230
                          freight: 3340.25
                          total_landed_cost: 23591.5
                        children: []
                    grand_totals:
                      quantity_sold: 1250
                      base_product: 45230
                      freight: 8540.25
                      total_landed_cost: 61986.5
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Report is not ready or has expired. Please regenerate.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:read
      operationId: get-api-reporting-landed-cost-breakdown-result-trackedjoblog
  /api/reporting/landed-cost-breakdown/export:
    get:
      tags:
      - Landed Cost Breakdown
      summary: Export Landed Cost Breakdown (CSV)
      description: 'Export a detailed breakdown with multiple grouping levels as CSV.
        The CSV includes a column for each grouping dimension (Sales Channel, Brand,
        Product) followed by all cost breakdown columns. Ideal for pivot-table analysis
        in a spreadsheet.


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: date_from
        in: query
        schema:
          type: string
        description: Start date for the report
        example: '2025-01-01'
      - name: date_to
        in: query
        schema:
          type: string
        description: End date for the report
        example: '2025-12-31'
      - name: group_by[]
        in: query
        schema:
          type: string
        description: First grouping level
        example: sales_channel
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:read
      operationId: get-api-reporting-landed-cost-breakdown-export
  /api/customers/{customer}/loyalty:
    get:
      tags:
      - Loyalty
      summary: Get Loyalty Balance
      description: 'The customer''s current loyalty points balance and its dollar
        redemption value, plus whether the loyalty program is enabled.


        :::info[Required scope: `customers:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token (PAT).

        Permission: authenticated user (no extra permission required for read).


        Returns 200 with `{ data: { customer_id, points_balance, redemption_value,
        program_enabled } }`:

        - `points_balance` (integer) — the running sum of the customer''s loyalty
        ledger.

        - `redemption_value` (float) — the dollar value of that balance at the current
        redemption rate.

        - `program_enabled` (boolean) — whether the loyalty program is active for
        the tenant.'
      parameters:
      - name: customer
        in: path
        schema:
          type: integer
        required: true
        description: The customer id.
        example: '842'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      customer_id:
                        type: integer
                      points_balance:
                        type: integer
                      redemption_value:
                        type: number
                      program_enabled:
                        type: boolean
                example:
                  data:
                    customer_id: 842
                    points_balance: 1250
                    redemption_value: 12.5
                    program_enabled: true
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: customers:read
      operationId: get-api-customers-customer-loyalty
  /api/customers/{customer}/loyalty/history:
    get:
      tags:
      - Loyalty
      summary: Get Loyalty History
      description: 'Paginated loyalty ledger history for a customer, newest first.
        Each entry records a signed points movement, the resulting balance, why it
        was written, and who created it.


        :::info[Required scope: `customers:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token (PAT).

        Permission: authenticated user (no extra permission required for read).


        Entry `type` values: `earn`, `redemption`, `adjustment`, `expiry`, `reversal`.
        `is_earn` is true when the entry adds points (points > 0).


        Pagination: `per_page` (default 10), `page` (default 1). Response includes
        standard Laravel pagination metadata.'
      parameters:
      - name: customer
        in: path
        schema:
          type: integer
        required: true
        description: The customer id.
        example: '842'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        customer_id:
                          type: integer
                        reference:
                          type: string
                        points:
                          type: integer
                        balance_after:
                          type: integer
                        type:
                          type: string
                        type_label:
                          type: string
                        is_earn:
                          type: boolean
                        notes:
                          type: string
                          nullable: true
                        expires_at:
                          type: string
                          nullable: true
                        source_type:
                          type: string
                        source_id:
                          type: integer
                        created_by_user_id:
                          type: integer
                        created_by_name:
                          type: string
                        created_at:
                          type: string
                  current_page:
                    type: integer
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 512
                    customer_id: 842
                    reference: LP-000512
                    points: -300
                    balance_after: 1250
                    type: redemption
                    type_label: Redeemed
                    is_earn: false
                    notes: null
                    expires_at: null
                    source_type: App\Models\PosTransaction
                    source_id: 1001
                    created_by_user_id: 7
                    created_by_name: Jane Cashier
                    created_at: '2026-07-06T15:10:00+00:00'
                  - id: 508
                    customer_id: 842
                    reference: LP-000508
                    points: 50
                    balance_after: 1550
                    type: earn
                    type_label: Earned
                    is_earn: true
                    notes: null
                    expires_at: '2027-07-06T00:00:00+00:00'
                    source_type: App\Models\PosTransaction
                    source_id: 998
                    created_by_user_id: 7
                    created_by_name: Jane Cashier
                    created_at: '2026-07-06T14:45:00+00:00'
                  - id: 500
                    customer_id: 842
                    reference: LP-000500
                    points: 500
                    balance_after: 1500
                    type: adjustment
                    type_label: Adjustment
                    is_earn: true
                    notes: Goodwill points for a delayed order.
                    expires_at: null
                    source_type: null
                    source_id: null
                    created_by_user_id: 7
                    created_by_name: Jane Cashier
                    created_at: '2026-07-06T14:30:00+00:00'
                  current_page: 1
                  first_page_url: '{{protocol}}{{domain}}/api/customers/842/loyalty/history?page=1'
                  from: 1
                  last_page: 1
                  last_page_url: '{{protocol}}{{domain}}/api/customers/842/loyalty/history?page=1'
                  next_page_url: null
                  path: '{{protocol}}{{domain}}/api/customers/842/loyalty/history'
                  per_page: 10
                  prev_page_url: null
                  to: 3
                  total: 3
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: customers:read
      operationId: get-api-customers-customer-loyalty-history
  /api/customers/{customer}/loyalty/adjust:
    post:
      tags:
      - Loyalty
      summary: Adjust Loyalty Points
      description: 'Manually add or remove loyalty points for a customer. Writes a
        signed `adjustment` ledger entry — a positive `points` value adds, a negative
        value removes.


        :::info[Required scope: `customers:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token (PAT).

        Permission: `customers.update`.


        Request body fields:

        - `points` (integer, required, `not_in:0`) — signed points to apply. Positive
        adds, negative removes. Error message when 0: "The points adjustment must
        be non-zero."

        - `notes` (string, nullable, max 2000) — internal note for the adjustment.


        A negative adjustment that would drive the balance below zero is rejected
        with 422 (`InsufficientLoyaltyPointsException`).


        Returns 201 with `{ data: <ledger entry>, points_balance: <int>, message:
        "Loyalty points adjusted." }`.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                points:
                  type: integer
                notes:
                  type: string
              example:
                points: 500
                notes: Goodwill points for a delayed order.
      parameters:
      - name: customer
        in: path
        schema:
          type: integer
        required: true
        description: The customer id.
        example: '842'
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      customer_id:
                        type: integer
                      reference:
                        type: string
                      points:
                        type: integer
                      balance_after:
                        type: integer
                      type:
                        type: string
                      type_label:
                        type: string
                      is_earn:
                        type: boolean
                      notes:
                        type: string
                      expires_at:
                        type: string
                        nullable: true
                      source_type:
                        type: string
                        nullable: true
                      source_id:
                        type: string
                        nullable: true
                      created_by_user_id:
                        type: integer
                      created_by_name:
                        type: string
                      created_at:
                        type: string
                  points_balance:
                    type: integer
                  message:
                    type: string
                example:
                  data:
                    id: 500
                    customer_id: 842
                    reference: LP-000500
                    points: 500
                    balance_after: 1500
                    type: adjustment
                    type_label: Adjustment
                    is_earn: true
                    notes: Goodwill points for a delayed order.
                    expires_at: null
                    source_type: null
                    source_id: null
                    created_by_user_id: 7
                    created_by_name: Jane Cashier
                    created_at: '2026-07-06T14:30:00+00:00'
                  points_balance: 1500
                  message: Loyalty points adjusted.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 422 Points must be non-zero
                  value:
                    message: The points adjustment must be non-zero.
                    errors:
                      points:
                      - The points adjustment must be non-zero.
                example-1:
                  summary: 422 Insufficient balance
                  value:
                    message: Loyalty balance of 40 points is insufficient for a debit
                      of 100.
                    errors:
                      points:
                      - Loyalty balance of 40 points is insufficient for a debit of
                        100.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: customers:write
      operationId: post-api-customers-customer-loyalty-adjust
  /api/loyalty/settings:
    get:
      tags:
      - Loyalty
      summary: Get Loyalty Settings
      description: 'The tenant''s loyalty program configuration.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token (PAT).

        Permission: `pos.operate`.


        Returns 200 with `{ data: { enabled, points_per_dollar, redemption_value_per_point,
        min_redemption_points } }`:

        - `enabled` (boolean) — whether the program is active (default false).

        - `points_per_dollar` (float) — points earned per $1 of sale total before
        tax (default 1.0).

        - `redemption_value_per_point` (float) — dollar value of one point when redeemed
        (default 0.01).

        - `min_redemption_points` (integer) — minimum points a customer must hold
        before any can be redeemed (default 0).'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      enabled:
                        type: boolean
                      points_per_dollar:
                        type: integer
                      redemption_value_per_point:
                        type: number
                      min_redemption_points:
                        type: integer
                example:
                  data:
                    enabled: true
                    points_per_dollar: 1
                    redemption_value_per_point: 0.01
                    min_redemption_points: 100
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: get-api-loyalty-settings
    put:
      tags:
      - Loyalty
      summary: Update Loyalty Settings
      description: 'Update the tenant''s loyalty program configuration. All fields
        are required and fully replace the stored settings.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token (PAT).

        Permission: `pos.manage`.


        Request body fields (all required):

        - `enabled` (boolean, required) — whether the program is active.

        - `points_per_dollar` (numeric, required, min 0) — points earned per $1 of
        sale total before tax.

        - `redemption_value_per_point` (numeric, required, min 0) — dollar value of
        one point when redeemed.

        - `min_redemption_points` (integer, required, min 0) — minimum points required
        before redemption.


        Returns 200 with `{ data: { ...settings }, message: "Loyalty settings updated."
        }`.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                enabled:
                  type: boolean
                points_per_dollar:
                  type: integer
                redemption_value_per_point:
                  type: number
                min_redemption_points:
                  type: integer
              example:
                enabled: true
                points_per_dollar: 1
                redemption_value_per_point: 0.01
                min_redemption_points: 100
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      enabled:
                        type: boolean
                      points_per_dollar:
                        type: integer
                      redemption_value_per_point:
                        type: number
                      min_redemption_points:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    enabled: true
                    points_per_dollar: 1
                    redemption_value_per_point: 0.01
                    min_redemption_points: 100
                  message: Loyalty settings updated.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      points_per_dollar:
                        type: array
                        items:
                          type: string
                      redemption_value_per_point:
                        type: array
                        items:
                          type: string
                      min_redemption_points:
                        type: array
                        items:
                          type: string
                example:
                  message: The points per dollar field must be at least 0. (and 2
                    more errors)
                  errors:
                    points_per_dollar:
                    - The points per dollar field must be at least 0.
                    redemption_value_per_point:
                    - The redemption value per point field is required.
                    min_redemption_points:
                    - The min redemption points field is required.
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: put-api-loyalty-settings
  /api/magento2/oauth/callback:
    post:
      tags:
      - OAuth
      summary: OAuth Callback
      description: '**Public, unauthenticated endpoint** — Magento Admin POSTs the
        OAuth 1.0a activation payload here when the merchant clicks **Activate** on
        a Magento Integration.


        **Flow on success:**

        1. We immediately return `200 { success: true, oauth_verifier: ... }` so Magento
        marks the integration Active.

        2. We then asynchronously POST to `{store_base_url}/oauth/token/request` to
        get a temporary request token, and `{store_base_url}/oauth/token/access` (with
        the verifier) to upgrade it into the permanent access token + secret. This
        deferred-exchange pattern (via `fastcgi_finish_request()` or `register_shutdown_function`)
        avoids deadlocking Magento''s PHP-FPM worker pool — Magento''s own Laminas
        HTTP client expects to read our response before it can serve our outbound
        OAuth calls.

        3. Structured outcomes (success/failure + last-4-of-token) are logged to `laravel.log`
        so install operations can be debugged.


        **Body parameters** (form-urlencoded, as Magento Admin POSTs):

        - `oauth_consumer_key` (required, string) — Magento Integration consumer key.

        - `oauth_consumer_secret` (required, string) — Magento Integration consumer
        secret.

        - `oauth_verifier` (required, string) — one-time verifier for the token exchange.

        - `store_base_url` (required, string) — Magento storefront URL.


        **Behavior:**

        - If any field is missing, the endpoint still returns HTTP 200 (so Magento
        Admin doesn''t surface a misleading ''post to consumer failed'' error) but
        with `success: false` and a message; the OAuth exchange is skipped.

        - The endpoint never throws — exchange failures are logged but not propagated
        to the response (Magento has already left the conversation by then).


        **Authentication:** None — this is a public webhook. CSRF is bypassed by the
        wildcard `*/callback` rule in `bootstrap/app.php`.'
      requestBody:
        content:
          application/x-www-form-urlencoded:
            schema:
              type: object
              properties:
                oauth_consumer_key:
                  type: string
                  description: Consumer key issued by Magento Admin for this Integration.
                  example: abc123def456ghi789jkl012
                oauth_consumer_secret:
                  type: string
                  description: Consumer secret issued by Magento Admin for this Integration.
                  example: mno345pqr678stu901vwx234
                oauth_verifier:
                  type: string
                  description: One-time verifier Magento includes in the activation
                    POST.
                  example: yz567abc890def123ghi456
                store_base_url:
                  type: string
                  description: The merchant's Magento storefront base URL (used as
                    the OAuth token-exchange origin).
                  example: https://shop.example.com
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 — Activation accepted (exchange queued)
                  value:
                    success: true
                    oauth_verifier: yz567abc890def123ghi456
                example-1:
                  summary: 200 — Missing required field (exchange skipped)
                  value:
                    success: false
                    message: Missing one or more required OAuth fields.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-magento2-oauth-callback
  /api/magento2/integration-instances/{magento2IntegrationInstance}/test-connection:
    post:
      tags:
      - Connection
      summary: Test Instance Connection
      description: 'Probe an EXISTING instance''s STORED credentials against the Magento
        2 REST API. Backs the live Connection Status chip on the settings Connection
        tab — the frontend never sees the raw access token, so the server re-uses
        what''s persisted in connection_settings. No request body.


        Returns 200 with `data.connected = true` when the token authenticates, or
        422 with `data.connected = false` and an actionable `message` when Magento
        rejects it (invalid/expired token, missing resource scopes, or unreachable
        host).


        **Authentication:** Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: magento2IntegrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Internal IntegrationInstance ID.
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      connected:
                        type: boolean
                example:
                  success: true
                  data:
                    connected: true
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      connected:
                        type: boolean
                  message:
                    type: string
                example:
                  success: false
                  data:
                    connected: false
                  message: 'Magento rejected the credentials: the access token is
                    invalid or expired. Confirm you copied the entire token from Magento
                    Admin → System → Integrations → Integration Info.'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-magento2-integration-instances-magento2integrationinstance-test-connection
  /api/magento2/integration-instances:
    get:
      tags:
      - Integration Instances
      summary: List Instances
      description: List every Magento 2 IntegrationInstance in your tenant. Returns
        the same shape as `Show` but as a collection. Sorted by instance name ascending.
        No pagination at Phase 1 — most tenants have a handful of instances.
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_id:
                          type: integer
                        name:
                          type: string
                        country:
                          type: string
                        sync_status:
                          type: string
                          nullable: true
                        connection_status:
                          type: string
                          nullable: true
                        is_automatic_sync_enabled:
                          type: boolean
                        connection_settings:
                          type: object
                          properties:
                            base_url:
                              type: string
                            access_token_masked:
                              type: string
                        integration_settings:
                          type: object
                          properties:
                            orders:
                              type: object
                              properties:
                                download:
                                  type: object
                                  properties:
                                    auto_download:
                                      type: object
                                      properties:
                                        enabled:
                                          type: boolean
                                        frequency_mins:
                                          type: integer
                            inventory:
                              type: object
                              properties:
                                master_of_stock:
                                  type: string
                                  nullable: true
                        created_at:
                          type: string
                        updated_at:
                          type: string
                example:
                  data:
                  - id: 42
                    integration_id: 17
                    name: Acme — EU Storefront
                    country: DE
                    sync_status: null
                    connection_status: null
                    is_automatic_sync_enabled: false
                    connection_settings:
                      base_url: https://shop-eu.example.com
                      access_token_masked: ••••••••••••••••••••wxyz
                    integration_settings:
                      orders:
                        download:
                          auto_download:
                            enabled: false
                            frequency_mins: 15
                      inventory:
                        master_of_stock: null
                    created_at: '2026-06-10T12:34:56+00:00'
                    updated_at: '2026-06-10T12:34:56+00:00'
                  - id: 43
                    integration_id: 17
                    name: Acme — US Storefront
                    country: US
                    sync_status: null
                    connection_status: null
                    is_automatic_sync_enabled: false
                    connection_settings:
                      base_url: https://shop.example.com
                      access_token_masked: ••••••••••••••••••••abcd
                    integration_settings:
                      orders:
                        download:
                          auto_download:
                            enabled: false
                            frequency_mins: 15
                      inventory:
                        master_of_stock: null
                    created_at: '2026-06-10T12:34:56+00:00'
                    updated_at: '2026-06-10T12:34:56+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-magento2-integration-instances
  /api/magento2/integration-instances/{magento2IntegrationInstance}:
    get:
      tags:
      - Integration Instances
      summary: Get Instance
      description: Retrieve a single Magento 2 IntegrationInstance by ID. The route
        is scoped to this tenant's Magento 2 instances; IDs that belong to other integration
        types or other tenants return `404`.
      parameters:
      - name: magento2IntegrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Internal IntegrationInstance ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_id:
                        type: integer
                      name:
                        type: string
                      country:
                        type: string
                      sync_status:
                        type: string
                        nullable: true
                      connection_status:
                        type: string
                        nullable: true
                      is_automatic_sync_enabled:
                        type: boolean
                      connection_settings:
                        type: object
                        properties:
                          base_url:
                            type: string
                          access_token_masked:
                            type: string
                          admin_path:
                            type: string
                      integration_settings:
                        type: object
                        properties:
                          orders:
                            type: object
                            properties:
                              download:
                                type: object
                                properties:
                                  last_updated_after:
                                    type: string
                                    nullable: true
                                  status:
                                    type: array
                                  auto_download:
                                    type: object
                                    properties:
                                      enabled:
                                        type: boolean
                                      frequency_mins:
                                        type: integer
                          inventory:
                            type: object
                            properties:
                              master_of_stock:
                                type: string
                                nullable: true
                          communications:
                            type: object
                            properties:
                              email_customers:
                                type: boolean
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 42
                    integration_id: 17
                    name: Acme — US Storefront
                    country: US
                    sync_status: null
                    connection_status: null
                    is_automatic_sync_enabled: false
                    connection_settings:
                      base_url: https://shop.example.com
                      access_token_masked: ••••••••••••••••••••abcd
                      admin_path: admin_gmr1iop
                    integration_settings:
                      orders:
                        download:
                          last_updated_after: null
                          status: []
                          auto_download:
                            enabled: false
                            frequency_mins: 15
                      inventory:
                        master_of_stock: null
                      communications:
                        email_customers: true
                    created_at: '2026-06-10T12:34:56+00:00'
                    updated_at: '2026-06-10T12:34:56+00:00'
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No query results for model [Modules\Magento2\Entities\Magento2IntegrationInstance]
                    999999
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-magento2-integration-instances-magento2integrationinstance
    patch:
      tags:
      - Integration Instances
      summary: Update Instance
      description: 'Partial update — every field is `sometimes`. `connection_settings`
        and `integration_settings` are deep-merged with the existing values, so rotating
        just the access_token does NOT wipe the base_url. Top-level scalars like `name`,
        `country`, and `is_automatic_sync_enabled` overwrite directly.


        **Body parameters (all optional):**

        - `name` (string, max 255)

        - `country` (string, 2 chars — nullable)

        - `connection_settings.base_url` (URL)

        - `connection_settings.access_token` (string, min 8 chars, max 255) — merchant-rotated
        tokens land here.

        - `connection_settings.admin_path` (string, max 120, regex `^[A-Za-z0-9_\-/]+$`,
        nullable) — Magento admin URL frontname (e.g. `admin_gmr1iop`). Used to build
        deep-links into the Magento admin panel; defaults to `admin` server-side when
        null/blank. Magento installs typically randomise this in `app/etc/env.php`
        → `backend.frontName` for security.

        - `integration_settings` (object) — merged into existing settings.

        - `is_automatic_sync_enabled` (boolean)


        **Payment-pending order policy** (`integration_settings.orders.payment_pending`)
        — controls how orders that arrive from Magento 2 unpaid are imported:

        - `integration_settings.orders.payment_pending.enabled` (boolean) — turn the
        policy on/off. When off, unpaid orders import normally.

        - `integration_settings.orders.payment_pending.disposition` (string: `open`,
        `draft`, `reserve`) — what happens to an unpaid order: `open` imports it normally
        (no hold), `draft` imports it without allocating stock until approved, `reserve`
        allocates stock and holds fulfillment until payment arrives.

        - `integration_settings.orders.payment_pending.reserve_expiry_days` (integer
        1-90, nullable) — for the `reserve` disposition, how many days the stock reservation
        is held before it auto-releases if payment never arrives; null means the reservation
        does not expire.

        - `integration_settings.orders.payment_pending.auto_open_on_payment` (boolean)
        — automatically open a held order as soon as its payment is confirmed.

        - Per-payment-method overrides are available via the Payment Method Mappings
        endpoints (`unpaid_disposition`).


        **Accounting sync trigger** (`integration_settings.accounting.sales_order_sync_trigger`,
        string: `always` or `when_paid`, nullable) — when this store''s sales orders
        are pushed to the connected accounting provider: `always` (default — the invoice
        is pushed once the order is confirmed) or `when_paid` (unpaid orders stay
        out of the ledger until payment arrives). Per-payment-method overrides are
        available via the Payment Method Mappings endpoints (`accounting_sync`).


        Does not re-probe Magento — use the test-connection endpoint first if the
        merchant changed `base_url` or `access_token`.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                connection_settings:
                  type: object
                  properties:
                    access_token:
                      type: string
                    admin_path:
                      type: string
                integration_settings:
                  type: object
                  properties:
                    orders:
                      type: object
                      properties:
                        download:
                          type: object
                          properties:
                            auto_download:
                              type: object
                              properties:
                                enabled:
                                  type: boolean
                                frequency_mins:
                                  type: integer
                        payment_pending:
                          type: object
                          properties:
                            enabled:
                              type: boolean
                            disposition:
                              type: string
                            reserve_expiry_days:
                              type: integer
                            auto_open_on_payment:
                              type: boolean
                    accounting:
                      type: object
                      properties:
                        sales_order_sync_trigger:
                          type: string
                is_automatic_sync_enabled:
                  type: boolean
              example:
                name: Acme — US Storefront (renamed)
                connection_settings:
                  access_token: magento_integration_access_token_rotated_yyyyyyyy
                  admin_path: admin_gmr1iop
                integration_settings:
                  orders:
                    download:
                      auto_download:
                        enabled: true
                        frequency_mins: 15
                    payment_pending:
                      enabled: true
                      disposition: reserve
                      reserve_expiry_days: 14
                      auto_open_on_payment: true
                  accounting:
                    sales_order_sync_trigger: when_paid
                is_automatic_sync_enabled: true
      parameters:
      - name: magento2IntegrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Internal IntegrationInstance ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_id:
                        type: integer
                      name:
                        type: string
                      country:
                        type: string
                      sync_status:
                        type: string
                        nullable: true
                      connection_status:
                        type: string
                        nullable: true
                      is_automatic_sync_enabled:
                        type: boolean
                      connection_settings:
                        type: object
                        properties:
                          base_url:
                            type: string
                          access_token_masked:
                            type: string
                      integration_settings:
                        type: object
                        properties:
                          orders:
                            type: object
                            properties:
                              download:
                                type: object
                                properties:
                                  last_updated_after:
                                    type: string
                                    nullable: true
                                  status:
                                    type: array
                                  auto_download:
                                    type: object
                                    properties:
                                      enabled:
                                        type: boolean
                                      frequency_mins:
                                        type: integer
                          inventory:
                            type: object
                            properties:
                              master_of_stock:
                                type: string
                                nullable: true
                          communications:
                            type: object
                            properties:
                              email_customers:
                                type: boolean
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 42
                    integration_id: 17
                    name: Acme — US Storefront (renamed)
                    country: US
                    sync_status: null
                    connection_status: null
                    is_automatic_sync_enabled: true
                    connection_settings:
                      base_url: https://shop.example.com
                      access_token_masked: ••••••••••••••••••••yyyy
                    integration_settings:
                      orders:
                        download:
                          last_updated_after: null
                          status: []
                          auto_download:
                            enabled: true
                            frequency_mins: 15
                      inventory:
                        master_of_stock: null
                      communications:
                        email_customers: true
                    created_at: '2026-06-10T12:34:56+00:00'
                    updated_at: '2026-06-10T13:21:00+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: patch-api-magento2-integration-instances-magento2integrationinstance
    delete:
      tags:
      - Integration Instances
      summary: Delete Instance
      description: 'Permanently delete the IntegrationInstance and its linked SalesChannel,
        data-import mapping, and API logs. Subsequent phases will extend this to also
        clean up Magento2Order / Magento2Product rows.


        This is irreversible — the merchant has to reconnect via `POST /install` to
        resume sync.


        Returns `204 No Content` on success.'
      parameters:
      - name: magento2IntegrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Internal IntegrationInstance ID
        example: '42'
      responses:
        '204':
          description: No Content
          content:
            text/plain:
              schema:
                type: string
                example: ''
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-magento2-integration-instances-magento2integrationinstance
  /api/magento2/integration-instances/{magento2IntegrationInstance}/dashboard:
    get:
      tags:
      - Dashboard
      summary: Get Instance Dashboard
      description: 'Dashboard metrics for a single Magento 2 integration instance.
        Backs the shared `<SalesChannelInstanceDashboard>` component on `/v2/integrations/magento2/dashboard`.


        Returns a hybrid payload: snake_case fields kept for legacy `Magento2DashboardMetrics`
        fallbacks, plus the camelCase `SalesChannelInstanceDashboardData` contract
        (`syncCards`, `integrations`, `entityCounts`, `financialSummary`, `syncStatus`)
        consumed directly by the dashboard component.


        **Path params:**

        - `magento2IntegrationInstance` (required, integer) — Magento 2 IntegrationInstance
        ID.


        **Query params:**

        - `period` (optional, string, default `30d`) — reporting window for `financialSummary`
        / `revenue_30d`. One of: `today`, `7d`, `30d`, `90d`, `All`.


        **Error responses:**

        - `404` — instance ID does not exist in this tenant.

        - `422` — `period` is not one of the allowed values.

        - `401` — caller is not authenticated.'
      parameters:
      - name: magento2IntegrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Internal IntegrationInstance ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      orders_total:
                        type: integer
                      orders_unmapped:
                        type: integer
                      orders_synced_today:
                        type: integer
                      products_total:
                        type: integer
                      products_mapped:
                        type: integer
                      products_unmapped:
                        type: integer
                      customers_total:
                        type: integer
                      revenue_30d:
                        type: number
                      currency:
                        type: string
                      last_sync_at:
                        type: string
                      last_sync_status:
                        type: string
                      generatedAt:
                        type: string
                      channelName:
                        type: string
                      displayName:
                        type: string
                      urlColumnLabel:
                        type: string
                      syncCards:
                        type: object
                        properties:
                          orders:
                            type: object
                            properties:
                              label:
                                type: string
                              icon:
                                type: string
                              lastSyncHuman:
                                type: string
                              lastSyncDate:
                                type: string
                              isStale:
                                type: boolean
                              lastDataHuman:
                                type: string
                              latestItemLabel:
                                type: string
                              latestItemDate:
                                type: string
                          catalog:
                            type: object
                            properties:
                              label:
                                type: string
                              icon:
                                type: string
                              lastSyncHuman:
                                type: string
                              lastSyncDate:
                                type: string
                              isStale:
                                type: boolean
                              lastDataHuman:
                                type: string
                              latestItemLabel:
                                type: string
                              latestItemDate:
                                type: string
                      integrations:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            url:
                              type: string
                            isAutomaticSyncEnabled:
                              type: boolean
                            createdAt:
                              type: string
                            updatedAt:
                              type: string
                      financialSummary:
                        type: object
                        properties:
                          grossRevenue:
                            type: number
                          totalRefunds:
                            type: number
                          netRevenue:
                            type: number
                          unitsSold:
                            type: integer
                          unitsRefunded:
                            type: integer
                          netUnitsSold:
                            type: integer
                      entityCounts:
                        type: object
                        properties:
                          totalRecords:
                            type: integer
                          entities:
                            type: array
                            items:
                              type: object
                              properties:
                                displayName:
                                  type: string
                                total:
                                  type: integer
                                error:
                                  type: string
                                  nullable: true
                      syncStatus:
                        type: object
                        properties:
                          overallHealth:
                            type: object
                            properties:
                              status:
                                type: string
                              healthyEntities:
                                type: integer
                              totalEntities:
                                type: integer
                              healthPercentage:
                                type: integer
                          autoSync:
                            type: object
                            properties:
                              isEnabled:
                                type: boolean
                              statusText:
                                type: string
                          syncTypes:
                            type: array
                            items:
                              type: object
                              properties:
                                name:
                                  type: string
                                lastSyncHuman:
                                  type: string
                                lastSyncDate:
                                  type: string
                                isStale:
                                  type: boolean
                                recordsSyncedLast24h:
                                  type: integer
                                schedule:
                                  type: string
                                nextSyncCountdown:
                                  type: string
                                  nullable: true
                example:
                  data:
                    orders_total: 128
                    orders_unmapped: 4
                    orders_synced_today: 6
                    products_total: 412
                    products_mapped: 380
                    products_unmapped: 32
                    customers_total: 95
                    revenue_30d: 18432.55
                    currency: USD
                    last_sync_at: '2026-06-16T05:32:11+00:00'
                    last_sync_status: success
                    generatedAt: '2026-06-16T07:00:00+00:00'
                    channelName: Magento 2
                    displayName: Acme — US Storefront
                    urlColumnLabel: Base URL
                    syncCards:
                      orders:
                        label: Orders
                        icon: mdi-cart
                        lastSyncHuman: 1 day ago
                        lastSyncDate: '2026-06-15T07:00:00+00:00'
                        isStale: false
                        lastDataHuman: 5 months ago
                        latestItemLabel: '#100000128'
                        latestItemDate: '2026-01-12T15:00:00+00:00'
                      catalog:
                        label: Products
                        icon: mdi-package-variant
                        lastSyncHuman: 2 hours ago
                        lastSyncDate: '2026-06-16T05:00:00+00:00'
                        isStale: false
                        lastDataHuman: 3 days ago
                        latestItemLabel: Acme Hoodie
                        latestItemDate: '2026-06-13T09:14:11+00:00'
                    integrations:
                    - id: 42
                      name: Acme — US Storefront
                      url: https://shop.example.com
                      isAutomaticSyncEnabled: true
                      createdAt: '2026-06-10T12:34:56+00:00'
                      updatedAt: '2026-06-16T05:32:11+00:00'
                    financialSummary:
                      grossRevenue: 18432.55
                      totalRefunds: 312.4
                      netRevenue: 18120.15
                      unitsSold: 0
                      unitsRefunded: 0
                      netUnitsSold: 0
                    entityCounts:
                      totalRecords: 635
                      entities:
                      - displayName: Orders
                        total: 128
                        error: null
                      - displayName: Products
                        total: 412
                        error: null
                      - displayName: Customers
                        total: 95
                        error: null
                    syncStatus:
                      overallHealth:
                        status: healthy
                        healthyEntities: 3
                        totalEntities: 3
                        healthPercentage: 100
                      autoSync:
                        isEnabled: true
                        statusText: Auto-sync enabled (USD)
                      syncTypes:
                      - name: Orders
                        lastSyncHuman: 1 day ago
                        lastSyncDate: '2026-06-15T07:00:00+00:00'
                        isStale: false
                        recordsSyncedLast24h: 6
                        schedule: Every 5 minutes
                        nextSyncCountdown: null
                      - name: Products
                        lastSyncHuman: 2 hours ago
                        lastSyncDate: '2026-06-16T05:00:00+00:00'
                        isStale: false
                        recordsSyncedLast24h: 3
                        schedule: Every hour
                        nextSyncCountdown: null
                      - name: Customers
                        lastSyncHuman: 12 hours ago
                        lastSyncDate: '2026-06-15T19:00:00+00:00'
                        isStale: false
                        recordsSyncedLast24h: 0
                        schedule: Daily
                        nextSyncCountdown: null
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties: {}
                example: {}
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 'Invalid period. Must be one of: today, 7d, 30d, 90d, All.'
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-magento2-integration-instances-magento2integrationinstance-dashboard
  /api/magento2/integration-instances/{magento2IntegrationInstance}/customers:
    get:
      tags:
      - Customers
      summary: List Customers
      description: 'Paginated list of Magento 2 customers scoped to one integration
        instance.


        **Path params:**

        - `magento2IntegrationInstance` (required, integer) — Magento 2 IntegrationInstance
        ID.


        **Query params** — all optional. Sorts: `id`, `magento_entity_id`, `email`,
        `firstname`, `lastname`, `group_id`, `website_id`, `magento_created_at`, `magento_updated_at`,
        `created_at`, `updated_at`. Advanced filters (Spatie AdvancedFilterBuilder)
        are also available for `email`, `firstname`, `lastname`, `telephone`, and
        the datetime columns.


        **Notes:**

        - `filter[integration_instance_ids]` is accepted as a no-op so the channel
        layout''s URL param doesn''t 400.

        - Eager-loads the integration instance + addresses + a withCount(''orders'')
        so the resource can emit `orders_count` and a derived primary-address city
        / region / country without N+1.

        - Fields the schema doesn''t yet carry (`group_name`, `website_name`, `total_spent`,
        etc.) are returned as `null`; Phase 2D''s sync work will populate them.'
      parameters:
      - name: magento2IntegrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Internal IntegrationInstance ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        magento_id:
                          type: integer
                        magento_entity_id:
                          type: integer
                        email:
                          type: string
                        firstname:
                          type: string
                        lastname:
                          type: string
                        first_name:
                          type: string
                        last_name:
                          type: string
                        full_name:
                          type: string
                        telephone:
                          type: string
                        phone:
                          type: string
                        website_id:
                          type: integer
                        group_id:
                          type: integer
                        group_name:
                          type: string
                          nullable: true
                        website_name:
                          type: string
                          nullable: true
                        store_id:
                          type: string
                          nullable: true
                        store_view_code:
                          type: string
                          nullable: true
                        sku_customer_name:
                          type: string
                          nullable: true
                        currency:
                          type: string
                          nullable: true
                        city:
                          type: string
                        region:
                          type: string
                        country_id:
                          type: string
                        orders_count:
                          type: integer
                        total_spent:
                          type: string
                          nullable: true
                        is_active:
                          type: boolean
                        magento_created_at:
                          type: string
                        magento_updated_at:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                        sku_customer_id:
                          type: string
                          nullable: true
                        magento_admin_url:
                          type: string
                        raw_payload:
                          type: string
                          nullable: true
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 17
                    integration_instance_id: 42
                    magento_id: 1234
                    magento_entity_id: 1234
                    email: buyer@example.com
                    firstname: Alex
                    lastname: Buyer
                    first_name: Alex
                    last_name: Buyer
                    full_name: Alex Buyer
                    telephone: +1 415 555 0190
                    phone: +1 415 555 0190
                    website_id: 1
                    group_id: 1
                    group_name: null
                    website_name: null
                    store_id: null
                    store_view_code: null
                    sku_customer_name: null
                    currency: null
                    city: San Francisco
                    region: CA
                    country_id: US
                    orders_count: 4
                    total_spent: null
                    is_active: true
                    magento_created_at: '2026-02-12T18:01:33+00:00'
                    magento_updated_at: '2026-06-01T11:22:18+00:00'
                    created_at: '2026-02-12T18:30:00+00:00'
                    updated_at: '2026-06-15T09:11:08+00:00'
                    sku_customer_id: null
                    magento_admin_url: https://shop.example.com/admin/customer/index/edit/id/1234
                    raw_payload: null
                  first_page_url: https://sku-io-test/api/magento2/integration-instances/42/customers?page=1
                  from: 1
                  last_page: 1
                  last_page_url: https://sku-io-test/api/magento2/integration-instances/42/customers?page=1
                  links: []
                  next_page_url: null
                  path: https://sku-io-test/api/magento2/integration-instances/42/customers
                  per_page: 10
                  prev_page_url: null
                  to: 1
                  total: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-magento2-integration-instances-magento2integrationinstance-customers
  /api/magento2/integration-instances/{magento2IntegrationInstance}/customers/{customer}:
    get:
      tags:
      - Customers
      summary: Get Customer
      description: 'Single customer detail. Eager-loads the integration instance,
        addresses, and orders_count.


        **Path params:**

        - `magento2IntegrationInstance` (required, integer) — Magento 2 IntegrationInstance
        ID.

        - `customer` (required, integer) — Internal `magento2_customers.id`.


        **Error responses:**

        - `404` — customer does not exist OR belongs to a different instance.

        - `401` — caller is not authenticated.'
      parameters:
      - name: magento2IntegrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Internal IntegrationInstance ID
        example: '42'
      - name: customer
        in: path
        schema:
          type: integer
        required: true
        description: Internal magento2_customers.id
        example: '17'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      magento_id:
                        type: integer
                      magento_entity_id:
                        type: integer
                      email:
                        type: string
                      firstname:
                        type: string
                      lastname:
                        type: string
                      first_name:
                        type: string
                      last_name:
                        type: string
                      full_name:
                        type: string
                      telephone:
                        type: string
                      phone:
                        type: string
                      website_id:
                        type: integer
                      group_id:
                        type: integer
                      group_name:
                        type: string
                        nullable: true
                      website_name:
                        type: string
                        nullable: true
                      store_id:
                        type: string
                        nullable: true
                      store_view_code:
                        type: string
                        nullable: true
                      sku_customer_name:
                        type: string
                        nullable: true
                      currency:
                        type: string
                        nullable: true
                      city:
                        type: string
                      region:
                        type: string
                      country_id:
                        type: string
                      orders_count:
                        type: integer
                      total_spent:
                        type: string
                        nullable: true
                      is_active:
                        type: boolean
                      magento_created_at:
                        type: string
                      magento_updated_at:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      sku_customer_id:
                        type: string
                        nullable: true
                      magento_admin_url:
                        type: string
                      raw_payload:
                        type: string
                        nullable: true
                example:
                  data:
                    id: 17
                    integration_instance_id: 42
                    magento_id: 1234
                    magento_entity_id: 1234
                    email: buyer@example.com
                    firstname: Alex
                    lastname: Buyer
                    first_name: Alex
                    last_name: Buyer
                    full_name: Alex Buyer
                    telephone: +1 415 555 0190
                    phone: +1 415 555 0190
                    website_id: 1
                    group_id: 1
                    group_name: null
                    website_name: null
                    store_id: null
                    store_view_code: null
                    sku_customer_name: null
                    currency: null
                    city: San Francisco
                    region: CA
                    country_id: US
                    orders_count: 4
                    total_spent: null
                    is_active: true
                    magento_created_at: '2026-02-12T18:01:33+00:00'
                    magento_updated_at: '2026-06-01T11:22:18+00:00'
                    created_at: '2026-02-12T18:30:00+00:00'
                    updated_at: '2026-06-15T09:11:08+00:00'
                    sku_customer_id: null
                    magento_admin_url: https://shop.example.com/admin/customer/index/edit/id/1234
                    raw_payload: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-magento2-integration-instances-magento2integrationinstance-customers-customer
  /api/magento2/integration-instances/{magento2IntegrationInstance}/customers/filter-options:
    get:
      tags:
      - Customers
      summary: Get Customer Filter Options
      description: Aggregated dropdown options for the customers filter panel — countries
        (via the address rows), customer groups, and websites — each as `{value, label,
        count}` so the picker can render counts inline. Pulled live from the customers
        persisted for this instance; empty / never-synced instances surface empty
        lists.
      parameters:
      - name: magento2IntegrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Internal IntegrationInstance ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      countries:
                        type: array
                        items:
                          type: object
                          properties:
                            value:
                              type: string
                            label:
                              type: string
                            count:
                              type: integer
                      groups:
                        type: array
                        items:
                          type: object
                          properties:
                            value:
                              type: integer
                            label:
                              type: string
                            count:
                              type: integer
                      websites:
                        type: array
                        items:
                          type: object
                          properties:
                            value:
                              type: integer
                            label:
                              type: string
                            count:
                              type: integer
                example:
                  data:
                    countries:
                    - value: US
                      label: US
                      count: 12
                    - value: GB
                      label: GB
                      count: 3
                    groups:
                    - value: 1
                      label: '1'
                      count: 14
                    - value: 2
                      label: '2'
                      count: 1
                    websites:
                    - value: 1
                      label: '1'
                      count: 15
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-magento2-integration-instances-magento2integrationinstance-customers-filter-options
  /api/magento2/integration-instances/{magento2IntegrationInstance}/customers/refresh:
    post:
      tags:
      - Customers
      summary: Refresh Customers
      description: 'Dispatch the tracked job that refreshes Magento 2 customers. Returns
        the `tracked_job_log_id` so the frontend can pivot the global JobProgressTray
        to it. Job name prefix is `Sync Magento 2 Customers: ` — the page''s `lastCompletedJob`
        watcher matches on this prefix.


        Phase 2C scope: the dispatch + tracked-job harness only. The actual `/V1/customers/search`
        walking + upsert lands in Phase 2D — until then the job acknowledges the dispatch
        and completes immediately with zero-counter results.'
      requestBody:
        content: {}
      parameters:
      - name: magento2IntegrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Internal IntegrationInstance ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 91812
                  message: Customer sync queued.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-magento2-integration-instances-magento2integrationinstance-customers-refresh
  /api/magento2/integration-instances/{magento2IntegrationInstance}/customers/{customer}/refresh:
    post:
      tags:
      - Customers
      summary: Refresh Single Customer
      description: 'Dispatch the tracked job to re-fetch a single customer. Shares
        the `Sync Magento 2 Customers: ` job-name prefix with the bulk refresh so
        the page''s `lastCompletedJob` watcher reacts to either run.


        **Error responses:**

        - `404` — customer does not exist OR belongs to a different instance.

        - `401` — caller is not authenticated.'
      requestBody:
        content: {}
      parameters:
      - name: magento2IntegrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Internal IntegrationInstance ID
        example: '42'
      - name: customer
        in: path
        schema:
          type: integer
        required: true
        description: Internal magento2_customers.id
        example: '17'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 91823
                  message: Customer refresh queued.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-magento2-integration-instances-magento2integrationinstance-customers-customer-refresh
  /api/magento2/integration-instances/{magento2IntegrationInstance}/customers/search:
    get:
      tags:
      - Customers
      summary: Search Customers
      description: Search-as-you-type endpoint. Delegates to the same paginated query
        as `List Customers` (Spatie QueryBuilder under the hood) so every filter /
        sort / pagination param the index supports is also accepted here. Provided
        as a separate route so the frontend can wire a dedicated debounce path.
      parameters:
      - name: magento2IntegrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Internal IntegrationInstance ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        magento_id:
                          type: integer
                        magento_entity_id:
                          type: integer
                        email:
                          type: string
                        firstname:
                          type: string
                        lastname:
                          type: string
                        first_name:
                          type: string
                        last_name:
                          type: string
                        full_name:
                          type: string
                        telephone:
                          type: string
                        phone:
                          type: string
                        website_id:
                          type: integer
                        group_id:
                          type: integer
                        group_name:
                          type: string
                          nullable: true
                        website_name:
                          type: string
                          nullable: true
                        store_id:
                          type: string
                          nullable: true
                        store_view_code:
                          type: string
                          nullable: true
                        sku_customer_name:
                          type: string
                          nullable: true
                        currency:
                          type: string
                          nullable: true
                        city:
                          type: string
                        region:
                          type: string
                        country_id:
                          type: string
                        orders_count:
                          type: integer
                        total_spent:
                          type: string
                          nullable: true
                        is_active:
                          type: boolean
                        magento_created_at:
                          type: string
                        magento_updated_at:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                        sku_customer_id:
                          type: string
                          nullable: true
                        magento_admin_url:
                          type: string
                        raw_payload:
                          type: string
                          nullable: true
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 17
                    integration_instance_id: 42
                    magento_id: 1234
                    magento_entity_id: 1234
                    email: buyer@example.com
                    firstname: Alex
                    lastname: Buyer
                    first_name: Alex
                    last_name: Buyer
                    full_name: Alex Buyer
                    telephone: +1 415 555 0190
                    phone: +1 415 555 0190
                    website_id: 1
                    group_id: 1
                    group_name: null
                    website_name: null
                    store_id: null
                    store_view_code: null
                    sku_customer_name: null
                    currency: null
                    city: San Francisco
                    region: CA
                    country_id: US
                    orders_count: 4
                    total_spent: null
                    is_active: true
                    magento_created_at: '2026-02-12T18:01:33+00:00'
                    magento_updated_at: '2026-06-01T11:22:18+00:00'
                    created_at: '2026-02-12T18:30:00+00:00'
                    updated_at: '2026-06-15T09:11:08+00:00'
                    sku_customer_id: null
                    magento_admin_url: https://shop.example.com/admin/customer/index/edit/id/1234
                    raw_payload: null
                  first_page_url: https://sku-io-test/api/magento2/integration-instances/42/customers?page=1
                  from: 1
                  last_page: 1
                  last_page_url: https://sku-io-test/api/magento2/integration-instances/42/customers?page=1
                  links: []
                  next_page_url: null
                  path: https://sku-io-test/api/magento2/integration-instances/42/customers
                  per_page: 10
                  prev_page_url: null
                  to: 1
                  total: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-magento2-integration-instances-magento2integrationinstance-customers-search
  /api/magento2/integration-instances/{magento2IntegrationInstance}/transactions:
    get:
      tags:
      - Transactions
      summary: List Transactions
      description: 'Paginated UNION of invoices + credit memos. Each row carries a
        `type` discriminator and a `magento_admin_url` deep-link that points at the
        correct admin section (invoice vs credit memo) on the storefront.


        **Path params:**

        - `magento2IntegrationInstance` (required, integer) — Magento 2 IntegrationInstance
        ID.


        **Notes:**

        - Implementation uses an in-memory merge of the two Eloquent queries (suitable
        for typical merchant volumes). For high-volume tenants the repository will
        swap to `DB::query()->fromSub(...->unionAll(...))` without changing the API
        contract.

        - The order is eager-loaded so the cell renderer doesn''t N+1.

        - Sort is fixed at `magento_created_at DESC` for now (the merged paginator
        doesn''t yet honour Spatie''s `sort` param).'
      parameters:
      - name: magento2IntegrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Internal IntegrationInstance ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        magento_entity_id:
                          type: integer
                        magento_increment_id:
                          type: string
                        type:
                          type: string
                        state:
                          type: string
                        grand_total:
                          type: number
                        currency:
                          type: string
                        payment_method:
                          type: string
                        order_id:
                          type: integer
                        order:
                          type: object
                          properties:
                            id:
                              type: integer
                            magento_entity_id:
                              type: integer
                            magento_increment_id:
                              type: string
                            customer_email:
                              type: string
                        is_pushed_to_accounting:
                          type: boolean
                        pushed_to_accounting_at:
                          type: string
                          nullable: true
                        is_reconciled:
                          type: boolean
                        reconciled_at:
                          type: string
                          nullable: true
                        accounting_sync_enabled:
                          type: boolean
                        magento_admin_url:
                          type: string
                        magento_created_at:
                          type: string
                        magento_updated_at:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 803
                    integration_instance_id: 42
                    magento_entity_id: 5034
                    magento_increment_id: '1000005034'
                    type: invoice
                    state: paid
                    grand_total: 198.45
                    currency: USD
                    payment_method: stripe_payments
                    order_id: 921
                    order:
                      id: 921
                      magento_entity_id: 700912
                      magento_increment_id: '100000921'
                      customer_email: buyer@example.com
                    is_pushed_to_accounting: false
                    pushed_to_accounting_at: null
                    is_reconciled: false
                    reconciled_at: null
                    accounting_sync_enabled: true
                    magento_admin_url: https://shop.example.com/admin/sales/invoice/view/invoice_id/5034
                    magento_created_at: '2026-06-10T18:01:11+00:00'
                    magento_updated_at: null
                    created_at: '2026-06-10T18:02:01+00:00'
                    updated_at: '2026-06-10T18:02:01+00:00'
                  first_page_url: '...?page=1'
                  from: 1
                  last_page: 1
                  last_page_url: '...?page=1'
                  links: []
                  next_page_url: null
                  path: https://sku-io-test/api/magento2/integration-instances/42/transactions
                  per_page: 10
                  prev_page_url: null
                  to: 1
                  total: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-magento2-integration-instances-magento2integrationinstance-transactions
  /api/magento2/integration-instances/{magento2IntegrationInstance}/transactions/{txn}:
    get:
      tags:
      - Transactions
      summary: Get Transaction
      description: 'Single transaction detail. The `{txn}` id can refer to either
        a `magento2_invoices.id` or a `magento2_credit_memos.id`; the `type` query
        string disambiguates.


        Adds (vs the list row): extended order context (subtotals, tax, discounts,
        shipping), `fees[]`, `total_fees` / `total_fee_tax`, and `raw_magento_payload`
        (the exact body Magento returned).


        **Error responses:**

        - `404` — id does not exist for the supplied `type` in this instance.

        - `401` — caller is not authenticated.'
      parameters:
      - name: type
        in: query
        schema:
          type: string
        description: 'Discriminator — one of: invoice, credit_memo. Default: invoice.'
        example: invoice
      - name: magento2IntegrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Internal IntegrationInstance ID
        example: '42'
      - name: txn
        in: path
        schema:
          type: integer
        required: true
        description: Internal magento2_invoices.id or magento2_credit_memos.id (disambiguated
          by `type` query param)
        example: '803'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      magento_entity_id:
                        type: integer
                      magento_increment_id:
                        type: string
                      type:
                        type: string
                      state:
                        type: string
                      grand_total:
                        type: number
                      currency:
                        type: string
                      payment_method:
                        type: string
                      order_id:
                        type: integer
                      order:
                        type: object
                        properties:
                          id:
                            type: integer
                          magento_entity_id:
                            type: integer
                          magento_increment_id:
                            type: string
                          customer_email:
                            type: string
                      is_pushed_to_accounting:
                        type: boolean
                      pushed_to_accounting_at:
                        type: string
                        nullable: true
                      is_reconciled:
                        type: boolean
                      reconciled_at:
                        type: string
                        nullable: true
                      accounting_sync_enabled:
                        type: boolean
                      magento_admin_url:
                        type: string
                      magento_created_at:
                        type: string
                      magento_updated_at:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      fees:
                        type: array
                      total_fees:
                        type: integer
                      total_fee_tax:
                        type: integer
                      raw_magento_payload:
                        type: object
                        properties:
                          entity_id:
                            type: integer
                          increment_id:
                            type: string
                          grand_total:
                            type: number
                example:
                  data:
                    id: 803
                    integration_instance_id: 42
                    magento_entity_id: 5034
                    magento_increment_id: '1000005034'
                    type: invoice
                    state: paid
                    grand_total: 198.45
                    currency: USD
                    payment_method: stripe_payments
                    order_id: 921
                    order:
                      id: 921
                      magento_entity_id: 700912
                      magento_increment_id: '100000921'
                      customer_email: buyer@example.com
                    is_pushed_to_accounting: false
                    pushed_to_accounting_at: null
                    is_reconciled: false
                    reconciled_at: null
                    accounting_sync_enabled: true
                    magento_admin_url: https://shop.example.com/admin/sales/invoice/view/invoice_id/5034
                    magento_created_at: '2026-06-10T18:01:11+00:00'
                    magento_updated_at: null
                    created_at: '2026-06-10T18:02:01+00:00'
                    updated_at: '2026-06-10T18:02:01+00:00'
                    fees: []
                    total_fees: 0
                    total_fee_tax: 0
                    raw_magento_payload:
                      entity_id: 5034
                      increment_id: '1000005034'
                      grand_total: 198.45
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-magento2-integration-instances-magento2integrationinstance-transactions-txn
  /api/magento2/integration-instances/{magento2IntegrationInstance}/transactions/filter-options:
    get:
      tags:
      - Transactions
      summary: Get Transaction Filter Options
      description: Aggregated dropdown options for the transactions filter panel —
        currencies (pulled live from the linked orders), per-type counts, and per-state
        counts. Empty / never-synced instances surface empty lists.
      parameters:
      - name: magento2IntegrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Internal IntegrationInstance ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      currencies:
                        type: array
                        items:
                          type: string
                      types:
                        type: array
                        items:
                          type: object
                          properties:
                            value:
                              type: string
                            label:
                              type: string
                            count:
                              type: integer
                      states:
                        type: array
                        items:
                          type: object
                          properties:
                            value:
                              type: string
                            label:
                              type: string
                            count:
                              type: integer
                example:
                  data:
                    currencies:
                    - USD
                    - EUR
                    types:
                    - value: invoice
                      label: Invoice
                      count: 38
                    - value: credit_memo
                      label: Credit Memo
                      count: 4
                    states:
                    - value: paid
                      label: Paid
                      count: 32
                    - value: open
                      label: Open
                      count: 6
                    - value: refunded
                      label: Refunded
                      count: 4
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-magento2-integration-instances-magento2integrationinstance-transactions-filter-options
  /api/magento2/integration-instances/{magento2IntegrationInstance}/transactions/refresh:
    post:
      tags:
      - Transactions
      summary: Refresh Transactions
      description: 'Dispatch the tracked job that refreshes invoices + credit memos
        for the instance. Returns the `tracked_job_log_id` so the frontend can pivot
        the global JobProgressTray to it. Job name prefix is `Refresh Magento 2 Transactions:
        ` — the page''s `lastCompletedJob` watcher matches on this prefix.


        Phase 2C scope: dispatch harness only — the actual `/V1/invoices` + `/V1/creditmemo`
        walking lands in Phase 2D.'
      requestBody:
        content: {}
      parameters:
      - name: magento2IntegrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Internal IntegrationInstance ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 91901
                  message: Transaction sync queued.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-magento2-integration-instances-magento2integrationinstance-transactions-refresh
  /api/magento2/integration-instances/{magento2IntegrationInstance}/transactions/{txn}/refresh:
    post:
      tags:
      - Transactions
      summary: Refresh Single Transaction
      description: 'Re-fetch a single transaction from Magento — typically used when
        the merchant reconciled / captured / refunded the row in Magento admin and
        wants SKU.io to pick up the change without a full refresh.


        Currently a no-op stub (Phase 2C) — the row''s `updated_at` is touched so
        downstream watchers see activity. Real refresh lands in Phase 2D.'
      requestBody:
        content: {}
      parameters:
      - name: type
        in: query
        schema:
          type: string
        description: 'Discriminator — one of: invoice, credit_memo. Default: invoice.'
        example: invoice
      - name: magento2IntegrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Internal IntegrationInstance ID
        example: '42'
      - name: txn
        in: path
        schema:
          type: integer
        required: true
        description: Internal magento2_invoices.id or magento2_credit_memos.id (disambiguated
          by `type` query param)
        example: '803'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      magento_entity_id:
                        type: integer
                      magento_increment_id:
                        type: string
                      type:
                        type: string
                      state:
                        type: string
                      grand_total:
                        type: number
                      currency:
                        type: string
                      payment_method:
                        type: string
                      order_id:
                        type: integer
                      order:
                        type: object
                        properties:
                          id:
                            type: integer
                          magento_entity_id:
                            type: integer
                          magento_increment_id:
                            type: string
                          customer_email:
                            type: string
                      is_pushed_to_accounting:
                        type: boolean
                      pushed_to_accounting_at:
                        type: string
                        nullable: true
                      is_reconciled:
                        type: boolean
                      reconciled_at:
                        type: string
                        nullable: true
                      accounting_sync_enabled:
                        type: boolean
                      magento_admin_url:
                        type: string
                      magento_created_at:
                        type: string
                      magento_updated_at:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      fees:
                        type: array
                      total_fees:
                        type: integer
                      total_fee_tax:
                        type: integer
                      raw_magento_payload:
                        type: object
                        properties:
                          entity_id:
                            type: integer
                          increment_id:
                            type: string
                          grand_total:
                            type: number
                  message:
                    type: string
                example:
                  data:
                    id: 803
                    integration_instance_id: 42
                    magento_entity_id: 5034
                    magento_increment_id: '1000005034'
                    type: invoice
                    state: paid
                    grand_total: 198.45
                    currency: USD
                    payment_method: stripe_payments
                    order_id: 921
                    order:
                      id: 921
                      magento_entity_id: 700912
                      magento_increment_id: '100000921'
                      customer_email: buyer@example.com
                    is_pushed_to_accounting: false
                    pushed_to_accounting_at: null
                    is_reconciled: false
                    reconciled_at: null
                    accounting_sync_enabled: true
                    magento_admin_url: https://shop.example.com/admin/sales/invoice/view/invoice_id/5034
                    magento_created_at: '2026-06-10T18:01:11+00:00'
                    magento_updated_at: null
                    created_at: '2026-06-10T18:02:01+00:00'
                    updated_at: '2026-06-10T18:02:01+00:00'
                    fees: []
                    total_fees: 0
                    total_fee_tax: 0
                    raw_magento_payload:
                      entity_id: 5034
                      increment_id: '1000005034'
                      grand_total: 198.45
                  message: Transaction refresh queued.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-magento2-integration-instances-magento2integrationinstance-transactions-txn-refresh
  /api/magento2/integration-instances/{magento2IntegrationInstance}/transactions/{txn}/push-to-accounting:
    post:
      tags:
      - Transactions
      summary: Push Transaction to Accounting
      description: 'Push the transaction to the configured accounting integration
        (QuickBooks Online / Xero / etc.). Synchronous — returns the updated row inline.
        Repeated calls overwrite `pushed_to_accounting_at` so the UI can show ''pushed
        N minutes ago'' deterministically.


        Phase 2C scope: timestamps the row only. Phase 2D will wire the real accounting-connector
        dispatch.'
      requestBody:
        content: {}
      parameters:
      - name: type
        in: query
        schema:
          type: string
        description: 'Discriminator — one of: invoice, credit_memo. Default: invoice.'
        example: invoice
      - name: magento2IntegrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Internal IntegrationInstance ID
        example: '42'
      - name: txn
        in: path
        schema:
          type: integer
        required: true
        description: Internal magento2_invoices.id or magento2_credit_memos.id (disambiguated
          by `type` query param)
        example: '803'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      magento_entity_id:
                        type: integer
                      magento_increment_id:
                        type: string
                      type:
                        type: string
                      state:
                        type: string
                      grand_total:
                        type: number
                      currency:
                        type: string
                      payment_method:
                        type: string
                      order_id:
                        type: integer
                      order:
                        type: object
                        properties:
                          id:
                            type: integer
                          magento_entity_id:
                            type: integer
                          magento_increment_id:
                            type: string
                          customer_email:
                            type: string
                      is_pushed_to_accounting:
                        type: boolean
                      pushed_to_accounting_at:
                        type: string
                      is_reconciled:
                        type: boolean
                      reconciled_at:
                        type: string
                        nullable: true
                      accounting_sync_enabled:
                        type: boolean
                      magento_admin_url:
                        type: string
                      magento_created_at:
                        type: string
                      magento_updated_at:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      fees:
                        type: array
                      total_fees:
                        type: integer
                      total_fee_tax:
                        type: integer
                      raw_magento_payload:
                        type: object
                        properties:
                          entity_id:
                            type: integer
                          increment_id:
                            type: string
                          grand_total:
                            type: number
                  message:
                    type: string
                example:
                  data:
                    id: 803
                    integration_instance_id: 42
                    magento_entity_id: 5034
                    magento_increment_id: '1000005034'
                    type: invoice
                    state: paid
                    grand_total: 198.45
                    currency: USD
                    payment_method: stripe_payments
                    order_id: 921
                    order:
                      id: 921
                      magento_entity_id: 700912
                      magento_increment_id: '100000921'
                      customer_email: buyer@example.com
                    is_pushed_to_accounting: true
                    pushed_to_accounting_at: '2026-06-16T07:30:00+00:00'
                    is_reconciled: false
                    reconciled_at: null
                    accounting_sync_enabled: true
                    magento_admin_url: https://shop.example.com/admin/sales/invoice/view/invoice_id/5034
                    magento_created_at: '2026-06-10T18:01:11+00:00'
                    magento_updated_at: null
                    created_at: '2026-06-10T18:02:01+00:00'
                    updated_at: '2026-06-10T18:02:01+00:00'
                    fees: []
                    total_fees: 0
                    total_fee_tax: 0
                    raw_magento_payload:
                      entity_id: 5034
                      increment_id: '1000005034'
                      grand_total: 198.45
                  message: Transaction pushed to accounting.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-magento2-integration-instances-magento2integrationinstance-transactions-txn-push-to-accounting
  /api/magento2/integration-instances/{magento2IntegrationInstance}/transactions/{txn}/reconcile:
    post:
      tags:
      - Transactions
      summary: Toggle Reconciliation
      description: 'Toggle the manual reconciliation flag on the transaction. The
        note is optional and persists alongside the timestamp; setting `is_reconciled:
        false` clears both fields.


        **Body params:**

        - `is_reconciled` (required, boolean) — true to set, false to clear.

        - `note` (optional, string, max 1000) — free-text reconciliation note.

        - `type` (optional, string) — discriminator. One of: invoice, credit_memo.
        Default: invoice.


        **Error responses:**

        - `404` — id does not exist for the supplied `type` in this instance.

        - `422` — body validation failed.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                is_reconciled:
                  type: boolean
                note:
                  type: string
                type:
                  type: string
              example:
                is_reconciled: true
                note: 'Matched to QBO entry #4810'
                type: invoice
      parameters:
      - name: magento2IntegrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Internal IntegrationInstance ID
        example: '42'
      - name: txn
        in: path
        schema:
          type: integer
        required: true
        description: Internal magento2_invoices.id or magento2_credit_memos.id (disambiguated
          by `type` query param)
        example: '803'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 — Reconciled
                  value:
                    data:
                      id: 803
                      integration_instance_id: 42
                      magento_entity_id: 5034
                      magento_increment_id: '1000005034'
                      type: invoice
                      state: paid
                      grand_total: 198.45
                      currency: USD
                      payment_method: stripe_payments
                      order_id: 921
                      order:
                        id: 921
                        magento_entity_id: 700912
                        magento_increment_id: '100000921'
                        customer_email: buyer@example.com
                      is_pushed_to_accounting: false
                      pushed_to_accounting_at: null
                      is_reconciled: true
                      reconciled_at: '2026-06-16T07:31:00+00:00'
                      accounting_sync_enabled: true
                      magento_admin_url: https://shop.example.com/admin/sales/invoice/view/invoice_id/5034
                      magento_created_at: '2026-06-10T18:01:11+00:00'
                      magento_updated_at: null
                      created_at: '2026-06-10T18:02:01+00:00'
                      updated_at: '2026-06-10T18:02:01+00:00'
                      fees: []
                      total_fees: 0
                      total_fee_tax: 0
                      raw_magento_payload:
                        entity_id: 5034
                        increment_id: '1000005034'
                        grand_total: 198.45
                    message: Transaction reconciled.
                example-1:
                  summary: 200 — Cleared
                  value:
                    data:
                      id: 803
                      integration_instance_id: 42
                      magento_entity_id: 5034
                      magento_increment_id: '1000005034'
                      type: invoice
                      state: paid
                      grand_total: 198.45
                      currency: USD
                      payment_method: stripe_payments
                      order_id: 921
                      order:
                        id: 921
                        magento_entity_id: 700912
                        magento_increment_id: '100000921'
                        customer_email: buyer@example.com
                      is_pushed_to_accounting: false
                      pushed_to_accounting_at: null
                      is_reconciled: false
                      reconciled_at: null
                      accounting_sync_enabled: true
                      magento_admin_url: https://shop.example.com/admin/sales/invoice/view/invoice_id/5034
                      magento_created_at: '2026-06-10T18:01:11+00:00'
                      magento_updated_at: null
                      created_at: '2026-06-10T18:02:01+00:00'
                      updated_at: '2026-06-10T18:02:01+00:00'
                      fees: []
                      total_fees: 0
                      total_fee_tax: 0
                      raw_magento_payload:
                        entity_id: 5034
                        increment_id: '1000005034'
                        grand_total: 198.45
                    message: Reconciliation cleared.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      is_reconciled:
                        type: array
                        items:
                          type: string
                example:
                  message: The is reconciled field is required.
                  errors:
                    is_reconciled:
                    - The is reconciled field is required.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-magento2-integration-instances-magento2integrationinstance-transactions-txn-reconcile
  /api/magento2/integration-instances/{magento2IntegrationInstance}/orders/{magento2Order}:
    get:
      tags:
      - Orders
      summary: Get Order By ID
      description: 'Fetch a single Magento 2 order by its internal ID, scoped to the
        supplied integration instance. The response includes the Magento money block,
        timestamps, the resolved Magento admin URL, all line items, shipments, invoices,
        credit memos, and — when linked — the SKU.io sales order with its fulfillments.
        `sku_sales_order_updated_at` carries that linked order''s last create/update
        timestamp (the "Last SKU Sync" column on the orders list), or null when the
        Magento order isn''t mapped yet.


        **Embedded `sku_sales_order.fulfillments[]`** drives the Fulfillments accordion
        panel on the order detail page. Each fulfillment carries: `id`, `status`,
        `fulfillment_type`, `tracking_number`, `cost`, `fulfilled_at`, `submitted_to_sales_channel_at`,
        the `warehouse` (id + name), the `shipping_method` (id + name), and the per-line
        `line_items[]` array. When the linked SKU sales order has no fulfillments
        the array is empty.


        **Activity log + raw payload** are NOT included here — they are lazy-loaded
        by the detail page from `/orders/:id/activity-log` and `/orders/:id/raw` respectively.
        Pass `include_raw=1` if you need `raw_payload` inline.


        **Authentication:** Requires Bearer token.'
      parameters:
      - name: magento2IntegrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Internal IntegrationInstance ID.
        example: '42'
      - name: magento2Order
        in: path
        schema:
          type: integer
        required: true
        description: Internal Magento2Order ID (NOT the Magento `entity_id`).
        example: '1042'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      magento_entity_id:
                        type: integer
                      magento_increment_id:
                        type: string
                      magento_state:
                        type: string
                      magento_status:
                        type: string
                      store_id:
                        type: integer
                      customer_id:
                        type: integer
                      customer_email:
                        type: string
                      currency_code:
                        type: string
                      base_grand_total:
                        type: string
                      grand_total:
                        type: string
                      tax_amount:
                        type: string
                      shipping_amount:
                        type: string
                      discount_amount:
                        type: string
                      total_paid:
                        type: string
                      total_refunded:
                        type: string
                      magento_created_at:
                        type: string
                      magento_updated_at:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                      error_log:
                        type: string
                        nullable: true
                      magento_admin_url:
                        type: string
                      sku_sales_order_id:
                        type: integer
                      sku_sales_order:
                        type: object
                        properties:
                          id:
                            type: integer
                          number:
                            type: string
                          sales_order_number:
                            type: string
                          status:
                            type: string
                          order_status:
                            type: string
                          fulfillment_status:
                            type: string
                          payment_status:
                            type: string
                          fulfillments:
                            type: array
                            items:
                              type: object
                              properties:
                                id:
                                  type: integer
                                status:
                                  type: string
                                fulfillment_type:
                                  type: string
                                tracking_number:
                                  type: string
                                cost:
                                  type: number
                                fulfilled_at:
                                  type: string
                                submitted_to_sales_channel_at:
                                  type: string
                                warehouse:
                                  type: object
                                  properties:
                                    id:
                                      type: integer
                                    name:
                                      type: string
                                shipping_method:
                                  type: object
                                  properties:
                                    id:
                                      type: integer
                                    name:
                                      type: string
                                line_items:
                                  type: array
                                  items:
                                    type: object
                                    properties:
                                      id:
                                        type: integer
                                      quantity:
                                        type: integer
                                      product_name:
                                        type: string
                                      sku:
                                        type: string
                      sku_sales_order_updated_at:
                        type: string
                      integration_instance:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      customer:
                        type: object
                        properties:
                          id:
                            type: integer
                          magento_customer_id:
                            type: integer
                          email:
                            type: string
                          first_name:
                            type: string
                          last_name:
                            type: string
                      line_items_count:
                        type: integer
                      line_items:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            magento_item_id:
                              type: integer
                            magento_product_id:
                              type: integer
                            sku:
                              type: string
                            name:
                              type: string
                            image_url:
                              type: string
                            qty_ordered:
                              type: integer
                            qty_invoiced:
                              type: integer
                            qty_shipped:
                              type: integer
                            qty_refunded:
                              type: integer
                            price:
                              type: string
                            tax_amount:
                              type: string
                            discount_amount:
                              type: string
                            row_total:
                              type: string
                      shipments:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            magento_entity_id:
                              type: integer
                            magento_increment_id:
                              type: string
                            tracking_number:
                              type: string
                            tracking_carrier:
                              type: string
                            source_code:
                              type: string
                            magento_created_at:
                              type: string
                            pushed_to_magento_at:
                              type: string
                            sku_sales_order_fulfillment_id:
                              type: integer
                      invoices:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            magento_entity_id:
                              type: integer
                            magento_increment_id:
                              type: string
                            state:
                              type: string
                            grand_total:
                              type: number
                            subtotal:
                              type: number
                            tax_amount:
                              type: number
                            shipping_amount:
                              type: number
                            discount_amount:
                              type: integer
                            magento_created_at:
                              type: string
                            pushed_to_accounting_at:
                              type: string
                            reconciled_at:
                              type: string
                              nullable: true
                            payment_method:
                              type: string
                      credit_memos:
                        type: array
                      raw_payload:
                        type: string
                        nullable: true
                example:
                  data:
                    id: 1042
                    integration_instance_id: 42
                    magento_entity_id: 5821
                    magento_increment_id: 000005821
                    magento_state: processing
                    magento_status: processing
                    store_id: 1
                    customer_id: 312
                    customer_email: buyer@example.com
                    currency_code: USD
                    base_grand_total: '129.99'
                    grand_total: '129.99'
                    tax_amount: '10.40'
                    shipping_amount: '9.99'
                    discount_amount: '-5.00'
                    total_paid: '129.99'
                    total_refunded: '0.00'
                    magento_created_at: '2026-06-15T10:22:18+00:00'
                    magento_updated_at: '2026-06-15T10:25:00+00:00'
                    created_at: '2026-06-15T10:22:30+00:00'
                    updated_at: '2026-06-15T10:30:00+00:00'
                    archived_at: null
                    error_log: null
                    magento_admin_url: https://shop.example.com/admin/sales/order/view/order_id/5821
                    sku_sales_order_id: 99012
                    sku_sales_order:
                      id: 99012
                      number: SO-99012
                      sales_order_number: SO-99012
                      status: open
                      order_status: open
                      fulfillment_status: partial
                      payment_status: paid
                      fulfillments:
                      - id: 7710
                        status: fulfilled
                        fulfillment_type: warehouse
                        tracking_number: 1Z999AA10123456784
                        cost: 9.99
                        fulfilled_at: '2026-06-16T14:05:11+00:00'
                        submitted_to_sales_channel_at: '2026-06-16T14:10:00+00:00'
                        warehouse:
                          id: 3
                          name: Main Warehouse
                        shipping_method:
                          id: 12
                          name: UPS Ground
                        line_items:
                        - id: 88410
                          quantity: 1
                          product_name: Acme Widget Pro
                          sku: AWP-001
                    sku_sales_order_updated_at: '2026-06-16T14:10:00+00:00'
                    integration_instance:
                      id: 42
                      name: Acme Magento 2 Store
                    customer:
                      id: 312
                      magento_customer_id: 9001
                      email: buyer@example.com
                      first_name: Jane
                      last_name: Doe
                    line_items_count: 1
                    line_items:
                    - id: 88410
                      magento_item_id: 18221
                      magento_product_id: 4501
                      sku: AWP-001
                      name: Acme Widget Pro
                      image_url: https://shop.example.com/media/catalog/product/a/w/awp-001.jpg
                      qty_ordered: 1
                      qty_invoiced: 1
                      qty_shipped: 1
                      qty_refunded: 0
                      price: '114.60'
                      tax_amount: '10.40'
                      discount_amount: '-5.00'
                      row_total: '129.99'
                    shipments:
                    - id: 4710
                      magento_entity_id: 6611
                      magento_increment_id: '000006611'
                      tracking_number: 1Z999AA10123456784
                      tracking_carrier: ups
                      source_code: default
                      magento_created_at: '2026-06-16T14:00:00+00:00'
                      pushed_to_magento_at: '2026-06-16T14:10:00+00:00'
                      sku_sales_order_fulfillment_id: 7710
                    invoices:
                    - id: 5510
                      magento_entity_id: 7022
                      magento_increment_id: '000007022'
                      state: paid
                      grand_total: 129.99
                      subtotal: 114.6
                      tax_amount: 10.4
                      shipping_amount: 9.99
                      discount_amount: -5
                      magento_created_at: '2026-06-15T10:25:00+00:00'
                      pushed_to_accounting_at: '2026-06-16T09:00:00+00:00'
                      reconciled_at: null
                      payment_method: stripe
                    credit_memos: []
                    raw_payload: null
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Not Found
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-magento2-integration-instances-magento2integrationinstance-orders-magento2order
  /api/magento2/integration-instances/{magento2IntegrationInstance}/orders/refresh:
    post:
      tags:
      - Orders
      summary: Refresh Orders
      description: "Dispatch the tracked job that refreshes Magento 2 orders. Returns\
        \ the `tracked_job_log_id` so the frontend can pivot the global JobProgressTray\
        \ to it. Job name prefix is `Refresh Magento 2 Orders: ` — the page's `lastCompletedJob`\
        \ watcher matches on this prefix.\n\n**Body params:**\n- `mode` *(required)*\
        \ — one of `since_latest`, `from_start_date`, `date_range`, `all`.\n  - `since_latest`\
        \ resumes from the cursor stored on the local orders table (falls back to\
        \ `since_at` then to the integration's configured start_date).\n  - `from_start_date`\
        \ walks from the integration's configured start date (Settings → Orders →\
        \ Start date).\n  - `date_range` walks a bounded `[date_from, date_to]` window.\n\
        \  - `all` — **Full Re-sync.** Walks every order Magento returns, ignoring\
        \ start_date entirely. Mirrors the option BigCommerce / eBay / WooCommerce\
        \ already expose.\n- `since_at` *(optional, ISO datetime)* — fallback cursor\
        \ used by `since_latest` when our local orders table is empty.\n- `date_from`\
        \ / `date_to` *(required when `mode=date_range`, ISO date)* — inclusive bounds\
        \ of the date window."
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                mode:
                  type: string
              example:
                mode: all
      parameters:
      - name: magento2IntegrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Internal IntegrationInstance ID.
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 92148
                  message: Order sync queued.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      mode:
                        type: array
                        items:
                          type: string
                example:
                  message: The selected mode is invalid.
                  errors:
                    mode:
                    - The selected mode is invalid.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-magento2-integration-instances-magento2integrationinstance-orders-refresh
  /api/magento2/integration-instances/{magento2IntegrationInstance}/orders/pre-start-date-search:
    post:
      tags:
      - Orders
      summary: Pre-Start-Date Orders — Search Specific Order
      description: 'Live single-order lookup against the Magento store for the pre-start-date
        import dialog''s **Search specific order** tab. Hits Magento directly via
        the REST API (GET /V1/orders/{id} for `entity_id`, GET /V1/orders?searchCriteria
        for `email`) — local DB lookups would miss orders that have never been imported,
        which is the whole point of a pre-start-date back-fill.


        **Body params:**

        - `search_by` *(required)* — `entity_id` (Magento order entity id) or `email`
        (customer email, exact match).

        - `search_term` *(required, max 255 chars)* — the value to look up. For `entity_id`
        must parse as a positive integer.


        **Response shape** mirrors the Browse-by-date result so the shared dialog
        can render either path uniformly:

        - `data[]` — orders found, each with `eligible`, `eligibility_reason`, `already_imported`,
        `line_items[]`, etc.

        - `inventory_start_date` — the integration''s configured `sync_start_date`
        (orders on or after this date are not eligible — covered by regular sync).

        - `meta.total_queried` / `meta.eligible_count` / `meta.already_imported_count`.


        An `entity_id` that doesn''t exist in Magento returns `data: []` (NOT a 404)
        so the dialog can show a clean ''no results'' state.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                search_by:
                  type: string
                search_term:
                  type: string
              example:
                search_by: entity_id
                search_term: '5421'
      parameters:
      - name: magento2IntegrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Internal IntegrationInstance ID.
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 — Found one eligible order
                  value:
                    data:
                    - magento_entity_id: 5421
                      increment_id: '100000123'
                      name: '100000123'
                      email: customer@example.com
                      created_at: '2023-11-04 14:22:11'
                      magento_status: complete
                      magento_state: complete
                      total_price: '129.95'
                      currency: USD
                      item_count: 2
                      total_quantity: 3
                      line_items:
                      - title: Acme Hoodie - Medium - Blue
                        sku: ACME-HOODIE-M-BLU
                        quantity: 2
                        current_quantity: 2
                        price: '49.99'
                        variant_title: null
                      - title: Stickers Pack
                        sku: STICKER-PK
                        quantity: 1
                        current_quantity: 1
                        price: '29.97'
                        variant_title: null
                      eligible: true
                      eligibility_reason: null
                      already_imported: false
                    inventory_start_date: '2024-01-01'
                    meta:
                      total_queried: 1
                      eligible_count: 1
                      already_imported_count: 0
                example-1:
                  summary: 200 — No results (entity_id not in Magento)
                  value:
                    data: []
                    inventory_start_date: '2024-01-01'
                    meta:
                      total_queried: 0
                      eligible_count: 0
                      already_imported_count: 0
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      search_by:
                        type: array
                        items:
                          type: string
                example:
                  message: The selected search by is invalid.
                  errors:
                    search_by:
                    - The selected search by is invalid.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-magento2-integration-instances-magento2integrationinstance-orders-pre-start-date-search
  /api/magento2/integration-instances/{magento2IntegrationInstance}/orders/import-pre-start-date:
    post:
      tags:
      - Orders
      summary: Pre-Start-Date Orders — Import
      description: "Dispatches the tracked job that back-fills Magento 2 orders pre-dating\
        \ the integration's normal sync start date. Returns `tracked_job_log_id` so\
        \ the frontend can pivot the global JobProgressTray to it. Job name prefix\
        \ is `Import Pre-Start-Date Magento 2 Orders: `.\n\n**Two modes — supply exactly\
        \ one:**\n- **Date-range mode** *(Browse-by-date tab)* — walks every Magento\
        \ order in [`created_at` >= `date_from`, `created_at` <= `date_to`].\n  -\
        \ `date_from` *(required, date)* — inclusive lower bound.\n  - `date_to` *(required,\
        \ date, >= date_from)* — inclusive upper bound.\n- **Entity-ids mode** *(Search-specific-order\
        \ tab)* — imports only the explicit entity ids the user picked from the live\
        \ Magento search.\n  - `magento_entity_ids[]` *(required, array of positive\
        \ integers)* — Magento order entity ids to import. Each is fetched live via\
        \ `syncManager->syncOrder()` and upserted into `magento2_orders`.\n\nWhen\
        \ `magento_entity_ids` is present, `date_from` / `date_to` are not required\
        \ and are ignored if supplied.\n\nAlso accessible via the alias route `POST\
        \ /api/magento2/integration-instances/{instance}/pre-start-date-orders/import`."
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                magento_entity_ids:
                  type: array
                  items:
                    type: integer
              example:
                magento_entity_ids:
                - 5421
                - 5422
      parameters:
      - name: magento2IntegrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Internal IntegrationInstance ID.
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 — Date-range import queued
                  value:
                    message: Pre-start-date import job queued
                    data:
                      tracked_job_log_id: 92201
                example-1:
                  summary: 200 — Entity-ids import queued
                  value:
                    message: Pre-start-date import job queued
                    data:
                      tracked_job_log_id: 92202
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      date_from:
                        type: array
                        items:
                          type: string
                      date_to:
                        type: array
                        items:
                          type: string
                example:
                  message: The date from field is required.
                  errors:
                    date_from:
                    - The date from field is required.
                    date_to:
                    - The date to field is required.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-magento2-integration-instances-magento2integrationinstance-orders-import-pre-start-date
  /api/magento2/integration-instances/{magento2IntegrationInstance}/shipments:
    get:
      tags:
      - Shipments
      summary: List Shipments
      description: 'Paginated Magento 2 shipments for the instance, newest first (by
        magento_created_at, then id).


        **Response contract (matches the frontend Magento2Shipment type):** `shipment_number`
        (shipment''s own Magento increment), `magento_order_id` (internal magento2_orders.id
        — drives the order link + tooltip), `magento_increment_id` (ORDER increment
        — the user-facing reference), `status` (`pushed` | `synced`), `carrier` (alias
        of `tracking_carrier`), `source_code` (MSI source).


        **Authentication:** Requires Bearer token.'
      parameters:
      - name: magento2IntegrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Internal IntegrationInstance ID.
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        magento2_order_id:
                          type: integer
                        magento_entity_id:
                          type: integer
                        shipment_number:
                          type: string
                        magento_order_id:
                          type: integer
                        magento_increment_id:
                          type: string
                        status:
                          type: string
                        tracking_number:
                          type: string
                        tracking_carrier:
                          type: string
                        carrier:
                          type: string
                        source_code:
                          type: string
                        magento_created_at:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                        pushed_to_magento_at:
                          type: string
                        sku_sales_order_fulfillment_id:
                          type: integer
                        order:
                          type: object
                          properties:
                            id:
                              type: integer
                            magento_increment_id:
                              type: string
                            customer_email:
                              type: string
                            grand_total:
                              type: string
                            currency_code:
                              type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - id: 2
                    magento2_order_id: 23
                    magento_entity_id: 3
                    shipment_number: '000000003'
                    magento_order_id: 23
                    magento_increment_id: '000000023'
                    status: pushed
                    tracking_number: 1Z999AA10123456784
                    tracking_carrier: ups
                    carrier: ups
                    source_code: default
                    magento_created_at: '2026-07-04T15:11:20+00:00'
                    created_at: '2026-07-04T15:11:21+00:00'
                    updated_at: '2026-07-04T15:11:21+00:00'
                    pushed_to_magento_at: '2026-07-04T15:11:21+00:00'
                    sku_sales_order_fulfillment_id: 5
                    order:
                      id: 23
                      magento_increment_id: '000000023'
                      customer_email: buyer@example.com
                      grand_total: '9.9900'
                      currency_code: USD
                  current_page: 1
                  last_page: 1
                  per_page: 25
                  total: 1
                  from: 1
                  to: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-magento2-integration-instances-magento2integrationinstance-shipments
  /api/magento2/integration-instances/{magento2IntegrationInstance}/shipments/{shipment}:
    get:
      tags:
      - Shipments
      summary: Get Shipment
      description: 'Fetch a single shipment (same contract as the list row) plus the
        full `raw_payload` from Magento. 404 when the shipment does not belong to
        the supplied instance.


        **Authentication:** Requires Bearer token.'
      parameters:
      - name: magento2IntegrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Internal IntegrationInstance ID.
        example: '42'
      - name: shipment
        in: path
        schema:
          type: integer
        required: true
        description: Internal Magento2Shipment ID.
        example: '2'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      magento2_order_id:
                        type: integer
                      magento_entity_id:
                        type: integer
                      shipment_number:
                        type: string
                      magento_order_id:
                        type: integer
                      magento_increment_id:
                        type: string
                      status:
                        type: string
                      tracking_number:
                        type: string
                      tracking_carrier:
                        type: string
                      carrier:
                        type: string
                      source_code:
                        type: string
                      magento_created_at:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      pushed_to_magento_at:
                        type: string
                      sku_sales_order_fulfillment_id:
                        type: integer
                      order:
                        type: object
                        properties:
                          id:
                            type: integer
                          magento_increment_id:
                            type: string
                          customer_email:
                            type: string
                          grand_total:
                            type: string
                          currency_code:
                            type: string
                      raw_payload:
                        type: object
                        properties:
                          entity_id:
                            type: integer
                          increment_id:
                            type: string
                example:
                  data:
                    id: 2
                    magento2_order_id: 23
                    magento_entity_id: 3
                    shipment_number: '000000003'
                    magento_order_id: 23
                    magento_increment_id: '000000023'
                    status: pushed
                    tracking_number: 1Z999AA10123456784
                    tracking_carrier: ups
                    carrier: ups
                    source_code: default
                    magento_created_at: '2026-07-04T15:11:20+00:00'
                    created_at: '2026-07-04T15:11:21+00:00'
                    updated_at: '2026-07-04T15:11:21+00:00'
                    pushed_to_magento_at: '2026-07-04T15:11:21+00:00'
                    sku_sales_order_fulfillment_id: 5
                    order:
                      id: 23
                      magento_increment_id: '000000023'
                      customer_email: buyer@example.com
                      grand_total: '9.9900'
                      currency_code: USD
                    raw_payload:
                      entity_id: 3
                      increment_id: '000000003'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-magento2-integration-instances-magento2integrationinstance-shipments-shipment
  /api/magento2/integration-instances/{magento2IntegrationInstance}/products:
    get:
      tags:
      - Products
      summary: List Products
      description: 'Paginated list of Magento 2 products scoped to one integration
        instance.


        **Path params:**

        - `magento2IntegrationInstance` (required, integer) — Magento 2 IntegrationInstance
        ID.


        **Pagination:** default `per_page=25`. Default sort: `-id`.


        **Quick filters (exact):** `type_id`, `status`, `visibility`, `magento_parent_id`,
        `attribute_set_id`, `integration_instance_id`.


        **Special filters:**

        - `filter[search]` — LIKE across sku + name; numeric values also match magento_entity_id.

        - `filter[sku_product_id]` — `mapped` / `unmapped` / `all`, or a numeric SKU.io
        product id.

        - `filter[archived]` — `true` (archived only), `false` (active only — default
        behavior), `all`.

        - `filter[integration_instance_ids]` — accepted as a no-op for channel-layout
        parity.


        **Advanced filters (AdvancedFilterBuilder, operator-aware):**

        - Text columns (operators: equals, not_equals, contains, does_not_contain,
        starts_with, ends_with, is_empty, is_not_empty): `sku`, `name`, `type_id`,
        `status`, `visibility`.

        - Numeric columns (operators: equals, not_equals, greater_than, greater_than_or_equal,
        less_than, less_than_or_equal, between, is_empty, is_not_empty): `price`,
        `cost`, `weight`.

        - Datetime columns (operators: equals, not_equals, greater_than, less_than,
        is_within, is_empty, is_not_empty): `magento_created_at`, `magento_updated_at`,
        `created_at`, `updated_at`.


        **Sorts:** id, magento_entity_id, sku, name, type_id, status, visibility,
        price, cost, weight, attribute_set_id, magento_parent_id, magento_created_at,
        magento_updated_at, created_at, updated_at.


        **Eager-loads:** `integrationInstance`, `parent` (the configurable parent
        for simple variants).'
      parameters:
      - name: magento2IntegrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Internal IntegrationInstance ID.
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        magento_id:
                          type: integer
                        magento_entity_id:
                          type: integer
                        sku:
                          type: string
                        name:
                          type: string
                        type_id:
                          type: string
                        status:
                          type: integer
                        visibility:
                          type: integer
                        price:
                          type: number
                        cost:
                          type: number
                        weight:
                          type: number
                        attribute_set_id:
                          type: integer
                        qty:
                          type: integer
                        store_id:
                          type: integer
                        store_view_code:
                          type: string
                        url_key:
                          type: string
                        image_url:
                          type: string
                        magento_parent_id:
                          type: string
                          nullable: true
                        magento_created_at:
                          type: string
                        magento_updated_at:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                        archived_at:
                          type: string
                          nullable: true
                        last_sync_at:
                          type: string
                        sku_product_id:
                          type: integer
                        sku_product_listing_id:
                          type: string
                          nullable: true
                        sku_product_sku:
                          type: string
                        sku_product_name:
                          type: string
                        is_mapped:
                          type: boolean
                        mapped_at:
                          type: string
                        magento_admin_url:
                          type: string
                        inventory_caches:
                          type: array
                        raw_payload:
                          type: string
                          nullable: true
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 312
                    integration_instance_id: 42
                    magento_id: 1024
                    magento_entity_id: 1024
                    sku: WIDGET-001
                    name: Acme Widget
                    type_id: simple
                    status: 1
                    visibility: 4
                    price: 19.99
                    cost: 7.5
                    weight: 0.45
                    attribute_set_id: 4
                    qty: 128
                    store_id: 1
                    store_view_code: default
                    url_key: acme-widget
                    image_url: https://shop.example.com/pub/media/catalog/product/a/c/acme-widget.jpg
                    magento_parent_id: null
                    magento_created_at: '2026-02-12T18:01:33+00:00'
                    magento_updated_at: '2026-06-15T11:22:18+00:00'
                    created_at: '2026-02-12T18:30:00+00:00'
                    updated_at: '2026-06-15T11:30:00+00:00'
                    archived_at: null
                    last_sync_at: '2026-06-15T11:30:00+00:00'
                    sku_product_id: 8821
                    sku_product_listing_id: null
                    sku_product_sku: WIDGET-001
                    sku_product_name: Acme Widget
                    is_mapped: true
                    mapped_at: '2026-06-15T11:30:00+00:00'
                    magento_admin_url: https://shop.example.com/admin/catalog/product/edit/id/1024
                    inventory_caches: []
                    raw_payload: null
                  - id: 313
                    integration_instance_id: 42
                    magento_id: 1025
                    magento_entity_id: 1025
                    sku: WIDGET-002
                    name: Acme Widget Pro
                    type_id: simple
                    status: 1
                    visibility: 4
                    price: 29.99
                    cost: 11.25
                    weight: 0.6
                    attribute_set_id: 4
                    qty: 42
                    store_id: 1
                    store_view_code: default
                    url_key: acme-widget-pro
                    image_url: null
                    magento_parent_id: null
                    magento_created_at: '2026-02-12T18:02:01+00:00'
                    magento_updated_at: '2026-06-15T11:22:18+00:00'
                    created_at: '2026-02-12T18:30:00+00:00'
                    updated_at: '2026-06-15T11:30:00+00:00'
                    archived_at: null
                    last_sync_at: '2026-06-15T11:30:00+00:00'
                    sku_product_id: null
                    sku_product_listing_id: null
                    sku_product_sku: null
                    sku_product_name: null
                    is_mapped: false
                    mapped_at: null
                    magento_admin_url: https://shop.example.com/admin/catalog/product/edit/id/1025
                    inventory_caches: []
                    raw_payload: null
                  first_page_url: https://sku-io-test/api/magento2/integration-instances/42/products?page=1
                  from: 1
                  last_page: 1
                  last_page_url: https://sku-io-test/api/magento2/integration-instances/42/products?page=1
                  links: []
                  next_page_url: null
                  path: https://sku-io-test/api/magento2/integration-instances/42/products
                  per_page: 25
                  prev_page_url: null
                  to: 2
                  total: 2
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-magento2-integration-instances-magento2integrationinstance-products
  /api/magento2/integration-instances/{magento2IntegrationInstance}/products/latest-sync-info:
    get:
      tags:
      - Products
      summary: Get Products Latest Sync Info
      description: 'Returns a summary of the most recent product sync: the latest
        product title and `magento_updated_at`, total / mapped / unmapped product
        counts, and the `last_synced_at` timestamp (the local `updated_at` of the
        most recently fetched product).'
      parameters:
      - name: magento2IntegrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Internal IntegrationInstance ID.
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      latest_product_title:
                        type: string
                      latest_product_date:
                        type: string
                      total_products:
                        type: integer
                      mapped_count:
                        type: integer
                      unmapped_count:
                        type: integer
                      last_synced_at:
                        type: string
                example:
                  data:
                    latest_product_title: Acme Widget Pro
                    latest_product_date: '2026-06-15T11:22:18+00:00'
                    total_products: 412
                    mapped_count: 318
                    unmapped_count: 94
                    last_synced_at: '2026-06-15T11:30:00+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-magento2-integration-instances-magento2integrationinstance-products-latest-sync-info
  /api/magento2/integration-instances/{magento2IntegrationInstance}/products/filter-options:
    get:
      tags:
      - Products
      summary: Get Products Filter Options
      description: 'Aggregated dropdown options for the products filter panel — `attribute_sets`
        (distinct `attribute_set_id` values surfaced as `{id, name}` pairs) and `categories`
        (distinct Magento category ids derived from each product''s raw_payload category
        links, surfaced as `{id, name}` pairs labelled `Category #{id}` until category-name
        sync lands). Drawn live from the locally synced product rows; empty / never-synced
        instances surface empty lists.'
      parameters:
      - name: magento2IntegrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Internal IntegrationInstance ID.
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      attribute_sets:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                      categories:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                example:
                  data:
                    attribute_sets:
                    - id: 4
                      name: 'Attribute Set #4'
                    - id: 9
                      name: 'Attribute Set #9'
                    categories:
                    - id: 3
                      name: 'Category #3'
                    - id: 5
                      name: 'Category #5'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-magento2-integration-instances-magento2integrationinstance-products-filter-options
  /api/magento2/integration-instances/{magento2IntegrationInstance}/products/search:
    get:
      tags:
      - Products
      summary: Search Products (Magento live)
      description: Searches the upstream Magento catalog directly, rather than products
        already synced to SKU.io. Currently returns an empty `data` array — live catalog
        search is not yet available. Use the product list endpoint with `filter[search]=…`
        to search synced products.
      parameters:
      - name: magento2IntegrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Internal IntegrationInstance ID.
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                example:
                  data: []
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-magento2-integration-instances-magento2integrationinstance-products-search
  /api/magento2/integration-instances/{magento2IntegrationInstance}/products/field-mappings:
    get:
      tags:
      - Products
      summary: Get Field Mappings
      description: Returns the Magento attribute → SKU.io Product field mappings used
        by `FieldMappingSettingsModal`. Both arrays come from the integration instance's
        `integration_settings` JSON column (`product_field_mappings` and `magento_attributes`).
      parameters:
      - name: magento2IntegrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Internal IntegrationInstance ID.
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      mappings:
                        type: array
                        items:
                          type: object
                          properties:
                            magento_field:
                              type: string
                            sku_field:
                              type: string
                      magento_attributes:
                        type: array
                        items:
                          type: object
                          properties:
                            attribute_code:
                              type: string
                            frontend_label:
                              type: string
                example:
                  data:
                    mappings:
                    - magento_field: sku
                      sku_field: sku
                    - magento_field: name
                      sku_field: name
                    - magento_field: price
                      sku_field: price
                    magento_attributes:
                    - attribute_code: sku
                      frontend_label: SKU
                    - attribute_code: name
                      frontend_label: Name
                    - attribute_code: price
                      frontend_label: Price
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-magento2-integration-instances-magento2integrationinstance-products-field-mappings
    put:
      tags:
      - Products
      summary: Update Field Mappings
      description: 'Replace the stored `product_field_mappings` array. The modal always
        sends the full list, so the server overwrites (rather than merges).


        **Body:** `{ mappings: [{ magento_field, sku_field }] }` — both fields required
        strings per entry; `mappings` itself is required (may be an empty array to
        clear all mappings).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                mappings:
                  type: array
                  items:
                    type: object
                    properties:
                      magento_field:
                        type: string
                      sku_field:
                        type: string
              example:
                mappings:
                - magento_field: sku
                  sku_field: sku
                - magento_field: name
                  sku_field: name
                - magento_field: price
                  sku_field: price
                - magento_field: weight
                  sku_field: weight
      parameters:
      - name: magento2IntegrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Internal IntegrationInstance ID.
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Field mappings saved.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      mappings.0.magento_field:
                        type: array
                        items:
                          type: string
                example:
                  message: The mappings.0.magento_field field is required.
                  errors:
                    mappings.0.magento_field:
                    - The mappings.0.magento_field field is required.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: put-api-magento2-integration-instances-magento2integrationinstance-products-field-mappings
  /api/magento2/integration-instances/{magento2IntegrationInstance}/products/refresh:
    post:
      tags:
      - Products
      summary: Refresh Products
      description: 'Dispatch the tracked job that refreshes Magento 2 products. Returns
        the `tracked_job_log_id` so the frontend can pivot the global JobProgressTray
        to it. Job name prefix is `Refresh Magento 2 Products: ` — the page''s `lastCompletedJob`
        watcher matches on this prefix.


        **Body params (all optional):**

        - `mode` — one of `since_latest` (default), `full_catalog`, `from_start_date`,
        `date_range`. Drives the cursor the job resolves.

        - `updated_at` — ISO datetime string used when `mode=since_latest` to override
        the auto-detected high-water mark.

        - `date_from` / `date_to` — ISO datetime strings used when `mode=from_start_date`
        (uses `date_from` only) or `mode=date_range` (uses both).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                mode:
                  type: string
                updated_at:
                  type: string
                date_from:
                  type: string
                  nullable: true
                date_to:
                  type: string
                  nullable: true
              example:
                mode: since_latest
                updated_at: '2026-06-15 12:00:00'
                date_from: null
                date_to: null
      parameters:
      - name: magento2IntegrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Internal IntegrationInstance ID.
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 92041
                  message: Product sync queued.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-magento2-integration-instances-magento2integrationinstance-products-refresh
  /api/magento2/integration-instances/{magento2IntegrationInstance}/products/bulk-map:
    post:
      tags:
      - Products
      summary: Bulk Map Products
      description: 'Bulk-map Magento products to SKU.io Products by SKU / SKU-contains
        / name. **Synchronous** (no tracked job) and **caps at 500 products per call**
        to keep the request bounded.


        **Body:**

        - `selection.type` — `selected` (use `ids`) or `filtered` (apply across the
        currently filtered set; the unmapped-only constraint always applies).

        - `selection.ids` — array of `magento2_products.id` (required when `type=selected`).

        - `selection.filters` — filter object (used when `type=filtered`).

        - `options.match_by` — `sku` (exact Magento SKU == SKU.io Product SKU), `sku_contains`
        (SKU.io Product SKU `LIKE %magento_sku%`), or `name` (SKU.io Product name
        == Magento name).

        - `options.create_if_no_match` — when true, create a new SKU.io Product for
        any Magento product that doesn''t match (uses the Magento sku + name).


        Returns counts: `mapped`, `skipped`, `total`. `tracked_job_log_id` is always
        `null` (kept in the response shape for frontend symmetry with the other bulk
        ops).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                selection:
                  type: object
                  properties:
                    type:
                      type: string
                    ids:
                      type: array
                      items:
                        type: integer
                options:
                  type: object
                  properties:
                    match_by:
                      type: string
                    create_if_no_match:
                      type: boolean
              example:
                selection:
                  type: selected
                  ids:
                  - 312
                  - 313
                  - 314
                options:
                  match_by: sku
                  create_if_no_match: false
      parameters:
      - name: magento2IntegrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Internal IntegrationInstance ID.
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: string
                        nullable: true
                      mapped:
                        type: integer
                      skipped:
                        type: integer
                      total:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: null
                    mapped: 2
                    skipped: 1
                    total: 3
                  message: Mapped 2 of 3 products (1 skipped).
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No products selected.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-magento2-integration-instances-magento2integrationinstance-products-bulk-map
  /api/magento2/integration-instances/{magento2IntegrationInstance}/products/bulk-unmap:
    post:
      tags:
      - Products
      summary: Bulk Unmap Products
      description: 'Clear `sku_product_id` + `sku_product_listing_id` on the selected
        products. Synchronous.


        **Body:**

        - `select_all` — when true, applies across every product in the instance (ignores
        `ids`).

        - `ids` — array of `magento2_products.id` to unmap (used when `select_all`
        is false / omitted).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                select_all:
                  type: boolean
                ids:
                  type: array
                  items:
                    type: integer
              example:
                select_all: false
                ids:
                - 312
                - 313
      parameters:
      - name: magento2IntegrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Internal IntegrationInstance ID.
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 2 product(s) unmapped.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-magento2-integration-instances-magento2integrationinstance-products-bulk-unmap
  /api/magento2/integration-instances/{magento2IntegrationInstance}/products/bulk-archive:
    post:
      tags:
      - Products
      summary: Bulk Archive Products
      description: Sets `archived_at = now()` on the selected products. Synchronous.
        Same body shape as `Bulk Unmap Products` (`select_all` + `ids`).
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                select_all:
                  type: boolean
                ids:
                  type: array
                  items:
                    type: integer
              example:
                select_all: false
                ids:
                - 312
                - 313
      parameters:
      - name: magento2IntegrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Internal IntegrationInstance ID.
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 2 product(s) archived.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-magento2-integration-instances-magento2integrationinstance-products-bulk-archive
  /api/magento2/integration-instances/{magento2IntegrationInstance}/products/bulk-unarchive:
    post:
      tags:
      - Products
      summary: Bulk Unarchive Products
      description: Clears `archived_at` on the selected products. Synchronous. Same
        body shape as `Bulk Unmap Products` (`select_all` + `ids`).
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                select_all:
                  type: boolean
                ids:
                  type: array
                  items:
                    type: integer
              example:
                select_all: false
                ids:
                - 312
                - 313
      parameters:
      - name: magento2IntegrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Internal IntegrationInstance ID.
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 2 product(s) unarchived.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-magento2-integration-instances-magento2integrationinstance-products-bulk-unarchive
  /api/magento2/integration-instances/{magento2IntegrationInstance}/products/bulk-delete-magento-records:
    post:
      tags:
      - Products
      summary: Bulk Delete Magento Records
      description: 'Delete the local Magento product records for the selected ids
        (does NOT delete anything in Magento itself — only the locally synced rows).
        Synchronous. Same body shape as the other bulk ops (`select_all` + `ids`).


        Response keeps `tracked_job_log_id` in the data envelope (always `null`) for
        frontend symmetry with the other bulk handlers.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                select_all:
                  type: boolean
                ids:
                  type: array
                  items:
                    type: integer
              example:
                select_all: false
                ids:
                - 312
                - 313
      parameters:
      - name: magento2IntegrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Internal IntegrationInstance ID.
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: string
                        nullable: true
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: null
                  message: 2 product(s) deleted.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-magento2-integration-instances-magento2integrationinstance-products-bulk-delete-magento-records
  /api/magento2/integration-instances/{magento2IntegrationInstance}/products/{product}:
    get:
      tags:
      - Products
      summary: Get Product
      description: 'Single product detail. Eager-loads `integrationInstance`, `parent`,
        and `children` (the children collection populates only for configurable products).


        **Path params:**

        - `magento2IntegrationInstance` (required, integer).

        - `product` (required, integer) — Internal `magento2_products.id`.


        **Error responses:**

        - `404` — product does not exist OR belongs to a different instance.

        - `401` — caller is not authenticated.'
      parameters:
      - name: magento2IntegrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Internal IntegrationInstance ID.
        example: '42'
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: Internal magento2_products.id.
        example: '312'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      magento_id:
                        type: integer
                      magento_entity_id:
                        type: integer
                      sku:
                        type: string
                      name:
                        type: string
                      type_id:
                        type: string
                      status:
                        type: integer
                      visibility:
                        type: integer
                      price:
                        type: number
                      cost:
                        type: number
                      weight:
                        type: number
                      attribute_set_id:
                        type: integer
                      qty:
                        type: integer
                      store_id:
                        type: integer
                      store_view_code:
                        type: string
                      url_key:
                        type: string
                      image_url:
                        type: string
                      magento_parent_id:
                        type: string
                        nullable: true
                      magento_created_at:
                        type: string
                      magento_updated_at:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                      last_sync_at:
                        type: string
                      sku_product_id:
                        type: integer
                      sku_product_listing_id:
                        type: string
                        nullable: true
                      sku_product_sku:
                        type: string
                      sku_product_name:
                        type: string
                      is_mapped:
                        type: boolean
                      mapped_at:
                        type: string
                      magento_admin_url:
                        type: string
                      inventory_caches:
                        type: array
                      parent:
                        type: string
                        nullable: true
                      children:
                        type: array
                      raw_payload:
                        type: string
                        nullable: true
                example:
                  data:
                    id: 312
                    integration_instance_id: 42
                    magento_id: 1024
                    magento_entity_id: 1024
                    sku: WIDGET-001
                    name: Acme Widget
                    type_id: simple
                    status: 1
                    visibility: 4
                    price: 19.99
                    cost: 7.5
                    weight: 0.45
                    attribute_set_id: 4
                    qty: 128
                    store_id: 1
                    store_view_code: default
                    url_key: acme-widget
                    image_url: https://shop.example.com/pub/media/catalog/product/a/c/acme-widget.jpg
                    magento_parent_id: null
                    magento_created_at: '2026-02-12T18:01:33+00:00'
                    magento_updated_at: '2026-06-15T11:22:18+00:00'
                    created_at: '2026-02-12T18:30:00+00:00'
                    updated_at: '2026-06-15T11:30:00+00:00'
                    archived_at: null
                    last_sync_at: '2026-06-15T11:30:00+00:00'
                    sku_product_id: 8821
                    sku_product_listing_id: null
                    sku_product_sku: WIDGET-001
                    sku_product_name: Acme Widget
                    is_mapped: true
                    mapped_at: '2026-06-15T11:30:00+00:00'
                    magento_admin_url: https://shop.example.com/admin/catalog/product/edit/id/1024
                    inventory_caches: []
                    parent: null
                    children: []
                    raw_payload: null
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Not Found
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-magento2-integration-instances-magento2integrationinstance-products-product
    delete:
      tags:
      - Products
      summary: Delete Product
      description: 'Delete the local Magento product row (does NOT delete anything
        in Magento itself). No body.


        **Error responses:**

        - `404` — product does not exist OR belongs to a different instance.'
      parameters:
      - name: magento2IntegrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Internal IntegrationInstance ID.
        example: '42'
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: Internal magento2_products.id.
        example: '312'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Product deleted.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-magento2-integration-instances-magento2integrationinstance-products-product
  /api/magento2/integration-instances/{magento2IntegrationInstance}/products/{product}/orders:
    get:
      tags:
      - Products
      summary: Get Orders For Product
      description: 'Paginated list of Magento 2 orders that contain this product.
        The match is `lineItems.magento_product_id = product.magento_entity_id` OR
        (when the product has a SKU) `lineItems.sku = product.sku`. Ordered by `magento_created_at
        DESC`. Eager-loads `integrationInstance` + `lineItems`.


        **Error responses:**

        - `404` — product does not exist OR belongs to a different instance.'
      parameters:
      - name: magento2IntegrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Internal IntegrationInstance ID.
        example: '42'
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: Internal magento2_products.id.
        example: '312'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        magento_id:
                          type: integer
                        magento_entity_id:
                          type: integer
                        increment_id:
                          type: string
                        status:
                          type: string
                        customer_email:
                          type: string
                        grand_total:
                          type: number
                        magento_created_at:
                          type: string
                        magento_updated_at:
                          type: string
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 7821
                    integration_instance_id: 42
                    magento_id: 50012
                    magento_entity_id: 50012
                    increment_id: '000050012'
                    status: complete
                    customer_email: buyer@example.com
                    grand_total: 39.98
                    magento_created_at: '2026-06-12T14:18:09+00:00'
                    magento_updated_at: '2026-06-12T15:02:33+00:00'
                  first_page_url: https://sku-io-test/api/magento2/integration-instances/42/products/312/orders?page=1
                  from: 1
                  last_page: 1
                  last_page_url: https://sku-io-test/api/magento2/integration-instances/42/products/312/orders?page=1
                  links: []
                  next_page_url: null
                  path: https://sku-io-test/api/magento2/integration-instances/42/products/312/orders
                  per_page: 10
                  prev_page_url: null
                  to: 1
                  total: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-magento2-integration-instances-magento2integrationinstance-products-product-orders
  /api/magento2/integration-instances/{magento2IntegrationInstance}/products/{product}/raw:
    get:
      tags:
      - Products
      summary: Get Raw Product Payload
      description: Returns the stored `raw_payload` JSON (the exact Magento REST product
        shape we last upserted). Intended for debugging the mapping pipeline; the
        frontend exposes it in the detail drawer's Raw tab. Returns `{}` when no payload
        has been stored.
      parameters:
      - name: magento2IntegrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Internal IntegrationInstance ID.
        example: '42'
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: Internal magento2_products.id.
        example: '312'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      product:
                        type: object
                        properties:
                          id:
                            type: integer
                          sku:
                            type: string
                          name:
                            type: string
                          price:
                            type: number
                          status:
                            type: integer
                          visibility:
                            type: integer
                          type_id:
                            type: string
                          attribute_set_id:
                            type: integer
                          created_at:
                            type: string
                          updated_at:
                            type: string
                          weight:
                            type: number
                          extension_attributes:
                            type: object
                            properties:
                              stock_item:
                                type: object
                                properties:
                                  qty:
                                    type: integer
                                  is_in_stock:
                                    type: boolean
                          custom_attributes:
                            type: array
                            items:
                              type: object
                              properties:
                                attribute_code:
                                  type: string
                                value:
                                  type: string
                example:
                  data:
                    product:
                      id: 1024
                      sku: WIDGET-001
                      name: Acme Widget
                      price: 19.99
                      status: 1
                      visibility: 4
                      type_id: simple
                      attribute_set_id: 4
                      created_at: '2026-02-12 18:01:33'
                      updated_at: '2026-06-15 11:22:18'
                      weight: 0.45
                      extension_attributes:
                        stock_item:
                          qty: 128
                          is_in_stock: true
                      custom_attributes:
                      - attribute_code: cost
                        value: '7.50'
                      - attribute_code: url_key
                        value: acme-widget
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-magento2-integration-instances-magento2integrationinstance-products-product-raw
  /api/magento2/integration-instances/{magento2IntegrationInstance}/products/{product}/map:
    post:
      tags:
      - Products
      summary: Map Product
      description: 'Map a single Magento product to a SKU.io Product.


        **Body:**

        - `sku_product_id` (integer | null) — the SKU.io `products.id` to link to.
        Pass `null` to clear the mapping (equivalent to `Unmap Product`).


        Returns the refreshed `Magento2ProductResource` so the frontend can swap the
        row.


        **Error responses:**

        - `404` — product does not exist OR belongs to a different instance.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                sku_product_id:
                  type: integer
              example:
                sku_product_id: 8821
      parameters:
      - name: magento2IntegrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Internal IntegrationInstance ID.
        example: '42'
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: Internal magento2_products.id.
        example: '312'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      magento_id:
                        type: integer
                      magento_entity_id:
                        type: integer
                      sku:
                        type: string
                      name:
                        type: string
                      type_id:
                        type: string
                      status:
                        type: integer
                      visibility:
                        type: integer
                      price:
                        type: number
                      cost:
                        type: number
                      weight:
                        type: number
                      attribute_set_id:
                        type: integer
                      sku_product_id:
                        type: integer
                      sku_product_listing_id:
                        type: string
                        nullable: true
                      sku_product_sku:
                        type: string
                      sku_product_name:
                        type: string
                      is_mapped:
                        type: boolean
                      mapped_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 312
                    integration_instance_id: 42
                    magento_id: 1024
                    magento_entity_id: 1024
                    sku: WIDGET-001
                    name: Acme Widget
                    type_id: simple
                    status: 1
                    visibility: 4
                    price: 19.99
                    cost: 7.5
                    weight: 0.45
                    attribute_set_id: 4
                    sku_product_id: 8821
                    sku_product_listing_id: null
                    sku_product_sku: WIDGET-001
                    sku_product_name: Acme Widget
                    is_mapped: true
                    mapped_at: '2026-06-21T12:00:00+00:00'
                    updated_at: '2026-06-21T12:00:00+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-magento2-integration-instances-magento2integrationinstance-products-product-map
  /api/magento2/integration-instances/{magento2IntegrationInstance}/products/{product}/unmap:
    post:
      tags:
      - Products
      summary: Unmap Product
      description: 'Clears `sku_product_id` and `sku_product_listing_id` on a single
        Magento product (no body). Returns the refreshed `Magento2ProductResource`.


        **Error responses:**

        - `404` — product does not exist OR belongs to a different instance.'
      requestBody:
        content: {}
      parameters:
      - name: magento2IntegrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Internal IntegrationInstance ID.
        example: '42'
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: Internal magento2_products.id.
        example: '312'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      sku:
                        type: string
                      name:
                        type: string
                      sku_product_id:
                        type: string
                        nullable: true
                      sku_product_listing_id:
                        type: string
                        nullable: true
                      sku_product_sku:
                        type: string
                        nullable: true
                      sku_product_name:
                        type: string
                        nullable: true
                      is_mapped:
                        type: boolean
                      mapped_at:
                        type: string
                        nullable: true
                      updated_at:
                        type: string
                example:
                  data:
                    id: 312
                    integration_instance_id: 42
                    sku: WIDGET-001
                    name: Acme Widget
                    sku_product_id: null
                    sku_product_listing_id: null
                    sku_product_sku: null
                    sku_product_name: null
                    is_mapped: false
                    mapped_at: null
                    updated_at: '2026-06-21T12:01:00+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-magento2-integration-instances-magento2integrationinstance-products-product-unmap
  /api/magento2/integration-instances/{magento2IntegrationInstance}/products/{product}/smart-match:
    post:
      tags:
      - Products
      summary: Smart Match SKU Product
      description: 'Suggest SKU.io products that could be mapped to this Magento 2
        product. Returns three buckets:


        - `exact_match` — the SKU.io product whose `sku` is identical to the Magento
        product''s SKU (or `null` if no match).

        - `barcode_match` — the SKU.io product whose barcode matches the Magento product''s
        barcode (or `null`).

        - `similar_matches` — fuzzy name/SKU matches, capped by `limit`.


        **Body (optional):**

        - `query` (string, max 255) — free-text search term. When omitted, the manager
        seeds the search with the Magento product''s `name` (falling back to `sku`).

        - `limit` (integer, 1–50) — max similar matches to return. Defaults to 10.


        **Error responses:**

        - `404` — product does not exist OR belongs to a different instance.

        - `422` — validation failed on `query` or `limit`.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                query:
                  type: string
                limit:
                  type: integer
              example:
                query: widget
                limit: 10
      parameters:
      - name: magento2IntegrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Internal IntegrationInstance ID.
        example: '42'
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: Internal magento2_products.id.
        example: '312'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      exact_match:
                        type: object
                        properties:
                          id:
                            type: integer
                          sku:
                            type: string
                          name:
                            type: string
                          image_url:
                            type: string
                          match_type:
                            type: string
                          match_score:
                            type: integer
                      barcode_match:
                        type: string
                        nullable: true
                      similar_matches:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            sku:
                              type: string
                            name:
                              type: string
                            image_url:
                              type: string
                              nullable: true
                            match_type:
                              type: string
                            match_score:
                              type: number
                example:
                  data:
                    exact_match:
                      id: 8821
                      sku: WIDGET-001
                      name: Acme Widget
                      image_url: https://cdn.sku.io/products/widget-001.jpg
                      match_type: sku
                      match_score: 1
                    barcode_match: null
                    similar_matches:
                    - id: 8835
                      sku: WIDGET-002
                      name: Acme Widget Pro
                      image_url: null
                      match_type: fuzzy
                      match_score: 0.74
                    - id: 9112
                      sku: WGT-RED-01
                      name: Red Widget
                      image_url: null
                      match_type: fuzzy
                      match_score: 0.52
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-magento2-integration-instances-magento2integrationinstance-products-product-smart-match
  /api/magento2/integration-instances/{magento2IntegrationInstance}/products/{product}/create-sku-product:
    post:
      tags:
      - Products
      summary: Create SKU Product From Magento
      description: 'Create a brand-new SKU.io product seeded from this Magento 2 product
        (with optional user overrides + a field-mapping override list), then map the
        Magento row to the newly created SKU product. The whole operation runs inside
        a single DB transaction.


        **Idempotency:** if a SKU.io product with the supplied `sku` already exists,
        the manager links to that existing product instead of creating a new one.
        The response then sets `linked_existing: true` and the message becomes `"Linked
        to existing SKU product."`.


        **Pre-condition:** the Magento product MUST be unmapped. Mapped products return
        `422` and must be unmapped first.


        **Body (all fields optional; modal pre-fills from Magento):**

        - `sku` (string, max 255)

        - `name` (string, max 255)

        - `description` (string)

        - `image_url` (string, max 1024)

        - `barcode` (string, max 255)

        - `cost` (number ≥ 0)

        - `price` (number ≥ 0)

        - `weight` (number ≥ 0)

        - `field_mappings[]` — array of `{ magento_field, sku_field }` pairs the manager
        applies to the Magento payload before persisting. Same shape `GET .../products/field-mappings`
        returns.


        **Error responses:**

        - `404` — product does not exist OR belongs to a different instance.

        - `422` — product is already mapped, or validation failed.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                sku:
                  type: string
                name:
                  type: string
                description:
                  type: string
                image_url:
                  type: string
                barcode:
                  type: string
                cost:
                  type: number
                price:
                  type: number
                weight:
                  type: number
                field_mappings:
                  type: array
                  items:
                    type: object
                    properties:
                      magento_field:
                        type: string
                      sku_field:
                        type: string
              example:
                sku: WIDGET-001
                name: Acme Widget
                description: Imported from Magento on 2026-06-30.
                image_url: https://cdn.example-magento.com/media/catalog/product/w/i/widget.jpg
                barcode: 012345678905
                cost: 7.5
                price: 19.99
                weight: 0.45
                field_mappings:
                - magento_field: sku
                  sku_field: sku
                - magento_field: name
                  sku_field: name
                - magento_field: description
                  sku_field: description
                - magento_field: weight
                  sku_field: weight
                - magento_field: barcode
                  sku_field: barcode
      parameters:
      - name: magento2IntegrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Internal IntegrationInstance ID.
        example: '42'
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: Internal magento2_products.id.
        example: '312'
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 201 — SKU product created and mapped
                  value:
                    data:
                      id: 312
                      integration_instance_id: 42
                      magento_id: 1024
                      sku: WIDGET-001
                      name: Acme Widget
                      sku_product_id: 8821
                      sku_product_sku: WIDGET-001
                      sku_product_name: Acme Widget
                      is_mapped: true
                      mapped_at: '2026-06-30T12:00:00+00:00'
                      updated_at: '2026-06-30T12:00:00+00:00'
                    linked_existing: false
                    message: SKU product created and mapped.
                example-1:
                  summary: 201 — Linked to existing SKU product (idempotent)
                  value:
                    data:
                      id: 312
                      integration_instance_id: 42
                      sku: WIDGET-001
                      name: Acme Widget
                      sku_product_id: 8821
                      sku_product_sku: WIDGET-001
                      sku_product_name: Acme Widget
                      is_mapped: true
                      mapped_at: '2026-06-30T12:00:00+00:00'
                    linked_existing: true
                    message: Linked to existing SKU product.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Magento product is already mapped to a SKU product. Unmap
                    it first.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-magento2-integration-instances-magento2integrationinstance-products-product-create-sku-product
  /api/magento2/integration-instances/{magento2IntegrationInstance}/products/{product}/refresh-single:
    post:
      tags:
      - Products
      summary: Refresh Single Product
      description: '**Synchronous** single-product resync. Looks up the product in
        Magento by its SKU, upserts the local row, and returns the refreshed `Magento2ProductResource`
        so the frontend can swap the row in place. No `tracked_job_log_id` is returned
        (unlike the bulk `Refresh Products` endpoint).


        **No request body.**


        **Error responses:**

        - `404` — product does not exist OR belongs to a different instance.

        - `422` — local product row has no SKU (cannot resolve it against Magento).

        - `502` (or the upstream status, when 4xx) — the Magento API call failed.'
      requestBody:
        content: {}
      parameters:
      - name: magento2IntegrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Internal IntegrationInstance ID.
        example: '42'
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: Internal magento2_products.id.
        example: '312'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      magento_id:
                        type: integer
                      magento_entity_id:
                        type: integer
                      sku:
                        type: string
                      name:
                        type: string
                      type_id:
                        type: string
                      status:
                        type: integer
                      visibility:
                        type: integer
                      price:
                        type: number
                      cost:
                        type: number
                      weight:
                        type: number
                      attribute_set_id:
                        type: integer
                      qty:
                        type: integer
                      store_id:
                        type: integer
                      store_view_code:
                        type: string
                      url_key:
                        type: string
                      image_url:
                        type: string
                      magento_parent_id:
                        type: string
                        nullable: true
                      magento_created_at:
                        type: string
                      magento_updated_at:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                      last_sync_at:
                        type: string
                      sku_product_id:
                        type: integer
                      sku_product_listing_id:
                        type: string
                        nullable: true
                      sku_product_sku:
                        type: string
                      sku_product_name:
                        type: string
                      is_mapped:
                        type: boolean
                      mapped_at:
                        type: string
                      magento_admin_url:
                        type: string
                      inventory_caches:
                        type: array
                      raw_payload:
                        type: string
                        nullable: true
                  message:
                    type: string
                example:
                  data:
                    id: 312
                    integration_instance_id: 42
                    magento_id: 1024
                    magento_entity_id: 1024
                    sku: WIDGET-001
                    name: Acme Widget
                    type_id: simple
                    status: 1
                    visibility: 4
                    price: 19.99
                    cost: 7.5
                    weight: 0.45
                    attribute_set_id: 4
                    qty: 128
                    store_id: 1
                    store_view_code: default
                    url_key: acme-widget
                    image_url: https://shop.example.com/pub/media/catalog/product/a/c/acme-widget.jpg
                    magento_parent_id: null
                    magento_created_at: '2026-02-12T18:01:33+00:00'
                    magento_updated_at: '2026-06-21T12:05:00+00:00'
                    created_at: '2026-02-12T18:30:00+00:00'
                    updated_at: '2026-06-21T12:05:00+00:00'
                    archived_at: null
                    last_sync_at: '2026-06-21T12:05:00+00:00'
                    sku_product_id: 8821
                    sku_product_listing_id: null
                    sku_product_sku: WIDGET-001
                    sku_product_name: Acme Widget
                    is_mapped: true
                    mapped_at: '2026-06-21T12:05:00+00:00'
                    magento_admin_url: https://shop.example.com/admin/catalog/product/edit/id/1024
                    inventory_caches: []
                    raw_payload: null
                  message: Product refreshed.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Cannot refresh a product without a SKU.
        '502':
          description: Bad Gateway
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 'Magento 2 product refresh failed: Connection timed out'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-magento2-integration-instances-magento2integrationinstance-products-product-refresh-single
  /api/magento2/integration-instances/{magento2IntegrationInstance}/products/{product}/archive:
    post:
      tags:
      - Products
      summary: Archive Product
      description: 'Archive a single product (sets `archived_at = now()`). No body.


        **Error responses:**

        - `404` — product does not exist OR belongs to a different instance.'
      requestBody:
        content: {}
      parameters:
      - name: magento2IntegrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Internal IntegrationInstance ID.
        example: '42'
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: Internal magento2_products.id.
        example: '312'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Product archived.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-magento2-integration-instances-magento2integrationinstance-products-product-archive
  /api/magento2/integration-instances/{magento2IntegrationInstance}/products/{product}/unarchive:
    post:
      tags:
      - Products
      summary: Unarchive Product
      description: 'Unarchive a single product (clears `archived_at`). No body.


        **Error responses:**

        - `404` — product does not exist OR belongs to a different instance.'
      requestBody:
        content: {}
      parameters:
      - name: magento2IntegrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Internal IntegrationInstance ID.
        example: '42'
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: Internal magento2_products.id.
        example: '312'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Product unarchived.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-magento2-integration-instances-magento2integrationinstance-products-product-unarchive
  /api/magento2/integration-instances/{magento2IntegrationInstance}/inventory-sources-cache:
    get:
      tags:
      - Inventory Sources (MSI)
      summary: List Cached MSI Sources
      description: 'Returns the paginated list of cached Magento MSI sources for the
        instance.


        Authenticated. Requires a Bearer token.


        Response fields per row:

        - `id` — cache row id

        - `integration_instance_id` — owning integration instance

        - `source_code` — Magento MSI source_code (unique per instance)

        - `name` — human-friendly source name

        - `enabled` — whether the source is enabled in Magento

        - `country_id`, `region`, `city`, `postcode`, `contact_email` — location/contact
        metadata

        - `master_of_stock` — per-source sync direction; one of `sku.io`, `magento2`,
        `disabled` (defaults to `sku.io`). See PATCH `…/inventory-sources/{sourceCode}/master-of-stock`.

        - `last_fetched_at` — ISO8601 timestamp of the most recent refresh


        Allowed sorts: `source_code`, `name`, `enabled`, `updated_at`. Default sort:
        `source_code` ASC.'
      parameters:
      - name: magento2IntegrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: ID of the Magento 2 integration instance.
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        source_code:
                          type: string
                        name:
                          type: string
                        enabled:
                          type: boolean
                        country_id:
                          type: string
                        region:
                          type: string
                        city:
                          type: string
                        postcode:
                          type: string
                        contact_email:
                          type: string
                        last_fetched_at:
                          type: string
                        created_at:
                          type: string
                        master_of_stock:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - id: 1
                    integration_instance_id: 1
                    source_code: default
                    name: Default Source
                    enabled: true
                    country_id: US
                    region: California
                    city: San Francisco
                    postcode: '94103'
                    contact_email: ops@example.test
                    last_fetched_at: '2026-06-20T14:32:11+00:00'
                    created_at: '2026-06-12T09:00:00+00:00'
                    master_of_stock: sku.io
                  - id: 2
                    integration_instance_id: 1
                    source_code: east_dc
                    name: East Coast Warehouse
                    enabled: true
                    country_id: US
                    region: New Jersey
                    city: Newark
                    postcode: '07102'
                    contact_email: null
                    last_fetched_at: '2026-06-20T14:32:11+00:00'
                    created_at: '2026-06-12T09:00:00+00:00'
                    master_of_stock: sku.io
                  current_page: 1
                  last_page: 1
                  per_page: 25
                  total: 2
                  from: 1
                  to: 2
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-magento2-integration-instances-magento2integrationinstance-inventory-sources-cache
  /api/magento2/integration-instances/{magento2IntegrationInstance}/inventory-sources/refresh:
    post:
      tags:
      - Inventory Sources (MSI)
      summary: Refresh MSI Sources from Magento
      description: 'Synchronously fetches MSI sources from Magento via `GET /rest/V1/inventory/sources`
        and upserts them into the local cache.


        Authenticated. Requires a Bearer token. Empty JSON body (`{}`).


        Side effects:

        - Issues one Saloon request to Magento (no tracked job, no queue).

        - Upserts each returned source by `(integration_instance_id, source_code)`.

        - Updates the row''s `updated_at` so the UI can render "last refreshed at".


        When Magento has MSI disabled, it returns HTTP 400. The connector translates
        this into an empty result — the endpoint still returns 200 with `fetched:
        0`, `written: 0` so the UI can surface a friendly message instead of an error.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties: {}
              example: {}
      parameters:
      - name: magento2IntegrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: ID of the Magento 2 integration instance.
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 OK — sources refreshed
                  value:
                    message: Magento 2 MSI sources refreshed.
                    data:
                      fetched: 2
                      written: 2
                      last_fetched_at: '2026-06-20T14:32:11+00:00'
                example-1:
                  summary: 200 OK — MSI disabled
                  value:
                    message: Magento 2 MSI sources refreshed.
                    data:
                      fetched: 0
                      written: 0
                      last_fetched_at: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-magento2-integration-instances-magento2integrationinstance-inventory-sources-refresh
  /api/magento2/integration-instances/{magento2IntegrationInstance}/inventory-sources/{sourceCode}/master-of-stock:
    patch:
      tags:
      - Inventory Sources (MSI)
      summary: Update Master of Stock for a Source
      description: "Update the Master of Stock direction for a single Magento MSI\
        \ source.\n\nPer the sales-channel standard §7.10, Master of Stock lives per-location\
        \ (per MSI source for Magento 2), not as a single global value on the integration\
        \ instance.\n\n**Authentication:** Requires Bearer token.\n\n**Request body:**\n\
        - `master_of_stock` (string, required) — one of `sku.io`, `magento2`, `disabled`.\n\
        \  - `sku.io` — SKU.io pushes on-hand to this Magento source on a schedule.\n\
        \  - `magento2` — RESERVED. Magento→SKU.io direction is not implemented yet;\
        \ the UI exposes it as a disabled \"(contact support)\" option.\n  - `disabled`\
        \ — no automatic sync for this source.\n\n**Responses:**\n- `200 OK` — returns\
        \ `{ data: { source_code, master_of_stock } }`.\n- `404 Not Found` — the MSI\
        \ source is not cached for this instance. Refresh sources on Settings → Locations\
        \ first.\n- `422 Unprocessable Entity` — `master_of_stock` missing or not\
        \ one of the allowed values."
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                master_of_stock:
                  type: string
              example:
                master_of_stock: sku.io
      parameters:
      - name: magento2IntegrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Magento 2 integration instance ID
        example: '1'
      - name: sourceCode
        in: path
        schema:
          type: string
        required: true
        description: Magento MSI source_code (e.g. 'default', 'warehouse_east')
        example: default
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      source_code:
                        type: string
                      master_of_stock:
                        type: string
                example:
                  message: Master of Stock updated.
                  data:
                    source_code: default
                    master_of_stock: sku.io
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: MSI source 'unknown_source' not found for this instance.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      master_of_stock:
                        type: array
                        items:
                          type: string
                example:
                  message: The selected master of stock is invalid.
                  errors:
                    master_of_stock:
                    - The selected master of stock is invalid.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: patch-api-magento2-integration-instances-magento2integrationinstance-inventory-sources-sourcecode-master-of-stock
  /api/magento2/integration-instances/{magento2IntegrationInstance}/warehouse-mappings:
    get:
      tags:
      - Warehouse Mappings
      summary: List Warehouse Mappings
      description: 'Returns the cached MSI inventory sources for the instance joined
        to any persisted SKU.io warehouse mappings, plus the full list of SKU.io warehouses
        available to map to.


        Authenticated. Requires a Bearer token.


        Response fields:

        - `data.sources[]` — one row per cached MSI source. `warehouse_id`/`warehouse_name`
        are null when the source is not yet mapped.

        - `data.warehouses[]` — every SKU.io warehouse the user can pick.

        - `data.mapped_count` / `data.unmapped_count` — counts derived from `sources`.


        The page renders the entire table from this single response — no separate
        calls for the warehouse picker are required.'
      parameters:
      - name: magento2IntegrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: ID of the Magento 2 integration instance.
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      sources:
                        type: array
                        items:
                          type: object
                          properties:
                            source_code:
                              type: string
                            source_name:
                              type: string
                            enabled:
                              type: boolean
                            country_id:
                              type: string
                            region:
                              type: string
                            city:
                              type: string
                            warehouse_id:
                              type: integer
                            warehouse_name:
                              type: string
                      warehouses:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                      mapped_count:
                        type: integer
                      unmapped_count:
                        type: integer
                example:
                  data:
                    sources:
                    - source_code: default
                      source_name: Default Warehouse
                      enabled: true
                      country_id: US
                      region: CA
                      city: Los Angeles
                      warehouse_id: 12
                      warehouse_name: LA Main
                    - source_code: east_dc
                      source_name: East Coast DC
                      enabled: true
                      country_id: US
                      region: NJ
                      city: Newark
                      warehouse_id: null
                      warehouse_name: null
                    warehouses:
                    - id: 12
                      name: LA Main
                    - id: 13
                      name: NJ Hub
                    mapped_count: 1
                    unmapped_count: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-magento2-integration-instances-magento2integrationinstance-warehouse-mappings
    put:
      tags:
      - Warehouse Mappings
      summary: Bulk Replace Warehouse Mappings
      description: 'Bulk-replaces warehouse mappings for the instance in a single
        transaction.


        Authenticated. Requires a Bearer token.


        Request body (`mappings[]`):

        - `source_code` (string, required) — must exist in `magento2_inventory_sources_cache`
        for this instance. Refresh from the Locations tab first if the source is missing.

        - `warehouse_id` (integer or null, required) — must exist in `warehouses`.
        `null` removes the mapping for that source.


        Duplicate `source_code` entries in the same payload are rejected (422).


        Returns the freshly-rebuilt index payload so the UI can re-render without
        an extra GET.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                mappings:
                  type: array
                  items:
                    type: object
                    properties:
                      source_code:
                        type: string
                      warehouse_id:
                        type: integer
              example:
                mappings:
                - source_code: default
                  warehouse_id: 12
                - source_code: east_dc
                  warehouse_id: 13
                - source_code: legacy_pop_up
                  warehouse_id: null
      parameters:
      - name: magento2IntegrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: ID of the Magento 2 integration instance.
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      sources:
                        type: array
                        items:
                          type: object
                          properties:
                            source_code:
                              type: string
                            source_name:
                              type: string
                            enabled:
                              type: boolean
                            country_id:
                              type: string
                            region:
                              type: string
                            city:
                              type: string
                            warehouse_id:
                              type: integer
                            warehouse_name:
                              type: string
                      warehouses:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                      mapped_count:
                        type: integer
                      unmapped_count:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    sources:
                    - source_code: default
                      source_name: Default Warehouse
                      enabled: true
                      country_id: US
                      region: CA
                      city: Los Angeles
                      warehouse_id: 12
                      warehouse_name: LA Main
                    - source_code: east_dc
                      source_name: East Coast DC
                      enabled: true
                      country_id: US
                      region: NJ
                      city: Newark
                      warehouse_id: 13
                      warehouse_name: NJ Hub
                    warehouses:
                    - id: 12
                      name: LA Main
                    - id: 13
                      name: NJ Hub
                    mapped_count: 2
                    unmapped_count: 0
                  message: Warehouse mappings saved successfully
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      mappings.0.source_code:
                        type: array
                        items:
                          type: string
                      mappings.1.warehouse_id:
                        type: array
                        items:
                          type: string
                example:
                  message: The mappings.0.source_code field is invalid.
                  errors:
                    mappings.0.source_code:
                    - The selected mappings.0.source_code is invalid.
                    mappings.1.warehouse_id:
                    - The selected mappings.1.warehouse_id is invalid.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: put-api-magento2-integration-instances-magento2integrationinstance-warehouse-mappings
  /api/magento2/integration-instances/{magento2IntegrationInstance}/shipping-method-mappings:
    get:
      tags:
      - Shipping Method Mappings
      summary: List Shipping Method Mappings
      description: 'Returns the existing Magento -> SKU.io shipping method mappings,
        the distinct Magento shipping methods observed on past imported orders for
        this instance, and the catalogue of SKU.io ShippingMethod records that can
        be picked from the row-level select.


        Authenticated. Requires a Bearer token.


        Response fields:

        - `data.mappings[]` — union of observed methods and any persisted mappings.
        `sku_shipping_method_id`/`sku_shipping_method_name` are null when the method
        is not yet mapped. `magento_method_label` is the human-friendly description
        from `shipping_description` on the original order (when available).

        - `data.observed_methods[]` — raw list of distinct `{carrier}_{method}` codes
        seen on past orders, paired with the latest `shipping_description` observed.

        - `data.sku_shipping_methods[]` — every SKU.io ShippingMethod available to
        pick from. Rendered as friendly labels in the row-level select via `full_name`
        ("Carrier - Method").


        The page renders the entire table from this single response — no separate
        call for the shipping-method catalogue is required.'
      parameters:
      - name: magento2IntegrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: ID of the Magento 2 integration instance.
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 OK
                  value:
                    data:
                      mappings:
                      - id: 42
                        magento_method_code: flatrate_flatrate
                        magento_method_label: Flat Rate - Fixed
                        sku_shipping_method_id: 12
                        sku_shipping_method_name: USPS - Priority Mail
                      - id: null
                        magento_method_code: ups_GND
                        magento_method_label: United Parcel Service - Ground
                        sku_shipping_method_id: null
                        sku_shipping_method_name: null
                      - id: null
                        magento_method_code: fedex_FEDEX_2_DAY
                        magento_method_label: Federal Express - 2 Day
                        sku_shipping_method_id: null
                        sku_shipping_method_name: null
                      observed_methods:
                      - magento_method_code: flatrate_flatrate
                        magento_method_label: Flat Rate - Fixed
                      - magento_method_code: ups_GND
                        magento_method_label: United Parcel Service - Ground
                      - magento_method_code: fedex_FEDEX_2_DAY
                        magento_method_label: Federal Express - 2 Day
                      sku_shipping_methods:
                      - id: 12
                        full_name: USPS - Priority Mail
                      - id: 13
                        full_name: UPS - Ground
                      - id: 14
                        full_name: FedEx - 2 Day Air
                example-1:
                  summary: 200 OK (No Orders Imported Yet)
                  value:
                    data:
                      mappings: []
                      observed_methods: []
                      sku_shipping_methods:
                      - id: 12
                        full_name: USPS - Priority Mail
                      - id: 13
                        full_name: UPS - Ground
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-magento2-integration-instances-magento2integrationinstance-shipping-method-mappings
    put:
      tags:
      - Shipping Method Mappings
      summary: Bulk Replace Shipping Method Mappings
      description: 'Bulk-replaces the shipping method mappings for the instance in
        a single transaction. Uses **replace** semantics:

        - Rows present in the payload with a non-null `sku_shipping_method_id` are
        upserted.

        - Rows present with a null `sku_shipping_method_id` are removed (the user
        cleared the row-level select).

        - Rows whose `magento_method_code` is absent from the payload are removed
        (delete-by-omission).


        Authenticated. Requires a Bearer token.


        Request body (`mappings[]`):

        - `magento_carrier_code` (string, optional, max 64) — informational; the canonical
        key is `magento_method_code`.

        - `magento_method_code` (string, required, max 128) — the Magento `{carrier}_{method}`
        identifier (e.g. `flatrate_flatrate`, `ups_GND`, `fedex_FEDEX_2_DAY`).

        - `sku_shipping_method_id` (integer or null, optional) — must exist in `shipping_methods`.
        `null` removes the mapping.

        - `sku_shipping_method_name` (string, optional, max 255) — informational label
        used by the UI / activity log; not authoritative.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                mappings:
                  type: array
                  items:
                    type: object
                    properties:
                      magento_carrier_code:
                        type: string
                      magento_method_code:
                        type: string
                      sku_shipping_method_id:
                        type: integer
                      sku_shipping_method_name:
                        type: string
              example:
                mappings:
                - magento_carrier_code: flatrate
                  magento_method_code: flatrate_flatrate
                  sku_shipping_method_id: 12
                  sku_shipping_method_name: USPS - Priority Mail
                - magento_carrier_code: ups
                  magento_method_code: ups_GND
                  sku_shipping_method_id: 13
                  sku_shipping_method_name: UPS - Ground
                - magento_carrier_code: fedex
                  magento_method_code: fedex_FEDEX_2_DAY
                  sku_shipping_method_id: null
                  sku_shipping_method_name: null
      parameters:
      - name: magento2IntegrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: ID of the Magento 2 integration instance.
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        magento_method_code:
                          type: string
                        sku_shipping_method_id:
                          type: integer
                example:
                  data:
                  - id: 42
                    magento_method_code: flatrate_flatrate
                    sku_shipping_method_id: 12
                  - id: 43
                    magento_method_code: ups_GND
                    sku_shipping_method_id: 13
        '401':
          description: Unauthorized
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Unauthenticated.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      mappings.0.sku_shipping_method_id:
                        type: array
                        items:
                          type: string
                example:
                  message: The selected mappings.0.sku_shipping_method_id is invalid.
                  errors:
                    mappings.0.sku_shipping_method_id:
                    - The selected mappings.0.sku_shipping_method_id is invalid.
        '429': *id001
        '403': *id003
        '404': *id004
      operationId: put-api-magento2-integration-instances-magento2integrationinstance-shipping-method-mappings
  /api/magento2/integration-instances/{magento2IntegrationInstance}/payment-method-mappings:
    get:
      tags:
      - Payment Method Mappings
      summary: List Payment Method Mappings
      description: 'Returns the Magento 2 -> SKU.io payment-method mapping table for
        this instance, plus the catalogue of SKU.io payment types that can be mapped
        to.


        The mapping rows are the union of every payment method observed on past imported
        orders and every persisted mapping — methods seen on orders that are not yet
        mapped appear with `sku_payment_type_id: null`, and persisted-but-no-longer-observed
        methods still appear so stale mappings can be revisited or cleared.


        Each mapping row contains:

        - `id` — the persisted mapping row ID, or null when the method has been observed
        on orders but not yet mapped.

        - `magento_method` — the Magento 2 payment method code (e.g. `checkmo`, `paypal_express`,
        `banktransfer`).

        - `magento_method_title` — the human-friendly method title observed on orders
        (falls back to the code).

        - `sku_payment_type_id` / `sku_payment_type_name` — the SKU.io payment type
        the method maps to; null when unmapped.

        - `unpaid_disposition` — how orders that arrive UNPAID with this payment method
        are imported: null (inherit the store-level payment-pending policy), `open`
        (import normally, no hold), `draft` (import without allocating stock), or
        `reserve` (allocate stock and hold fulfillment until payment arrives, optionally
        expiring per the store-level reservation expiry).

        - `accounting_sync` — when this method''s orders sync to the connected accounting
        provider: null (inherit the store-level trigger), `always` (sync once confirmed
        regardless of payment), `when_paid` (sync only after payment arrives), or
        `never` (this method''s orders are excluded from accounting sync).


        Response also includes:

        - `data.available_payment_types[]` — every active SKU.io payment type (`id`,
        `name`).

        - `meta` — `total_mappings`, `mapped_count`, `unmapped_count` counters.


        Authenticated. Requires a Bearer token.'
      parameters:
      - name: magento2IntegrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: ID of the Magento 2 integration instance.
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      mappings:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            magento_method:
                              type: string
                            magento_method_title:
                              type: string
                            sku_payment_type_id:
                              type: integer
                            sku_payment_type_name:
                              type: string
                            unpaid_disposition:
                              type: string
                            accounting_sync:
                              type: string
                      available_payment_types:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                  meta:
                    type: object
                    properties:
                      total_mappings:
                        type: integer
                      mapped_count:
                        type: integer
                      unmapped_count:
                        type: integer
                example:
                  data:
                    mappings:
                    - id: 31
                      magento_method: checkmo
                      magento_method_title: Check / Money order
                      sku_payment_type_id: 4
                      sku_payment_type_name: Check
                      unpaid_disposition: reserve
                      accounting_sync: when_paid
                    - id: 32
                      magento_method: paypal_express
                      magento_method_title: PayPal Express Checkout
                      sku_payment_type_id: 2
                      sku_payment_type_name: PayPal
                      unpaid_disposition: null
                      accounting_sync: null
                    - id: null
                      magento_method: banktransfer
                      magento_method_title: Bank Transfer Payment
                      sku_payment_type_id: null
                      sku_payment_type_name: null
                      unpaid_disposition: null
                      accounting_sync: null
                    available_payment_types:
                    - id: 1
                      name: Cash
                    - id: 2
                      name: PayPal
                    - id: 3
                      name: Credit Card
                    - id: 4
                      name: Check
                  meta:
                    total_mappings: 3
                    mapped_count: 2
                    unmapped_count: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-magento2-integration-instances-magento2integrationinstance-payment-method-mappings
    put:
      tags:
      - Payment Method Mappings
      summary: Bulk Replace Payment Method Mappings
      description: "Bulk-replaces the payment-method mapping set for this instance.\
        \ Any persisted row whose `magento_method` is NOT in the supplied payload\
        \ is deleted; the rest are upserted — so send the complete set of mappings\
        \ you want kept, not a delta.\n\nBody parameters:\n- `mappings` (array, required\
        \ — may be empty to clear all mappings). Each row:\n  - `mappings.*.magento_method`\
        \ (string, required, max 128) — the Magento 2 payment method code.\n  - `mappings.*.sku_payment_type_id`\
        \ (integer or null) — the SKU.io payment type to map to; null records the\
        \ method as known but unmapped.\n  - `mappings.*.unpaid_disposition` (string\
        \ or null, optional) — per-method override for how orders arriving unpaid\
        \ with this method are imported: null inherits the store-level payment-pending\
        \ policy, `open` imports normally, `draft` imports without allocating stock,\
        \ `reserve` allocates stock and holds fulfillment with an expiry per the store-level\
        \ reservation settings.\n  - `mappings.*.accounting_sync` (string or null,\
        \ optional) — per-method override for when this method's orders sync to the\
        \ accounting provider: null inherits the store-level trigger, `always`, `when_paid`,\
        \ or `never`.\n\nReturns the same payload as the list endpoint, rebuilt after\
        \ the update.\n\nAuthenticated. Requires a Bearer token."
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                mappings:
                  type: array
                  items:
                    type: object
                    properties:
                      magento_method:
                        type: string
                      sku_payment_type_id:
                        type: integer
                      unpaid_disposition:
                        type: string
                      accounting_sync:
                        type: string
              example:
                mappings:
                - magento_method: checkmo
                  sku_payment_type_id: 4
                  unpaid_disposition: reserve
                  accounting_sync: when_paid
                - magento_method: paypal_express
                  sku_payment_type_id: 2
                  unpaid_disposition: null
                  accounting_sync: null
                - magento_method: banktransfer
                  sku_payment_type_id: null
                  unpaid_disposition: draft
                  accounting_sync: never
      parameters:
      - name: magento2IntegrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: ID of the Magento 2 integration instance.
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      mappings:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            magento_method:
                              type: string
                            magento_method_title:
                              type: string
                            sku_payment_type_id:
                              type: integer
                            sku_payment_type_name:
                              type: string
                            unpaid_disposition:
                              type: string
                            accounting_sync:
                              type: string
                      available_payment_types:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                  meta:
                    type: object
                    properties:
                      total_mappings:
                        type: integer
                      mapped_count:
                        type: integer
                      unmapped_count:
                        type: integer
                example:
                  data:
                    mappings:
                    - id: 31
                      magento_method: checkmo
                      magento_method_title: Check / Money order
                      sku_payment_type_id: 4
                      sku_payment_type_name: Check
                      unpaid_disposition: reserve
                      accounting_sync: when_paid
                    - id: 32
                      magento_method: paypal_express
                      magento_method_title: PayPal Express Checkout
                      sku_payment_type_id: 2
                      sku_payment_type_name: PayPal
                      unpaid_disposition: null
                      accounting_sync: null
                    - id: null
                      magento_method: banktransfer
                      magento_method_title: Bank Transfer Payment
                      sku_payment_type_id: null
                      sku_payment_type_name: null
                      unpaid_disposition: draft
                      accounting_sync: never
                    available_payment_types:
                    - id: 1
                      name: Cash
                    - id: 2
                      name: PayPal
                    - id: 3
                      name: Credit Card
                    - id: 4
                      name: Check
                  meta:
                    total_mappings: 3
                    mapped_count: 2
                    unmapped_count: 1
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      mappings.0.unpaid_disposition:
                        type: array
                        items:
                          type: string
                example:
                  message: The selected mappings.0.unpaid_disposition is invalid.
                  errors:
                    mappings.0.unpaid_disposition:
                    - The selected mappings.0.unpaid_disposition is invalid.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: put-api-magento2-integration-instances-magento2integrationinstance-payment-method-mappings
  /api/manufacturing/boms:
    get:
      tags:
      - BOMs
      summary: List BOMs
      description: 'Paginated list of BOMs. Supports Spatie filters (status, product_id,
        search) and sort.


        :::info[Required scope: `manufacturing:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: per_page
        in: query
        schema:
          type: integer
        example: '25'
        description: Results per page (default 10).
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: manufacturing:read
      operationId: get-api-manufacturing-boms
    post:
      tags:
      - BOMs
      summary: Create BOM
      description: 'Create a new BOM with output lines, component lines, and (optional)
        operations.


        :::info[Required scope: `manufacturing:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        **Consumption method fields:**

        - `default_consumption_method` (optional, enum: `forward_flush` | `backflush`)
        — BOM-level default inherited by component lines that omit their own `consumption_method`.
        Null means no default (lines fall back to `forward_flush`).

        - `component_lines[].consumption_method` (optional, enum: `forward_flush`
        | `backflush`) — how the component is issued when production is recorded.
        `forward_flush` (the default) waits for the operator to issue the component
        explicitly with an actual consumed quantity; `backflush` auto-consumes it
        from the produced output quantity multiplied by the BOM per-unit usage, with
        no operator entry required. An explicit `null` behaves exactly like omitting
        the field — the line inherits `default_consumption_method`, falling back to
        `forward_flush` when the BOM has no default. The method is snapshotted onto
        each manufacturing-order component line at confirmation, so later BOM edits
        never change how an already-open order consumes.


        **Operation cost fields:** each `operations[]` row accepts `time_minutes`,
        `cost_per_hour`, and `fixed_cost` (optional, numeric, min 0) — a flat per-run
        cost added on top of time-based labour. Fixed cost is capitalized onto finished
        goods the same way labour is, but is never marked up by work-center overhead.

        Auth: requires Bearer token.


        `cost_classification` (optional, `labor`|`overhead`, default `labor`) sets
        the expense classification independently of the rate basis: `labor` posts
        the operation''s variable cost to the Labor bucket (marked up by the work
        center''s overhead %); `overhead` posts machine/tooling-style cost to the
        Overhead bucket with no additional markup.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                product_id:
                  type: integer
                name:
                  type: string
                version_notes:
                  type: string
                status:
                  type: string
                effective_from:
                  type: string
                effective_to:
                  type: string
                  nullable: true
                is_default:
                  type: boolean
                is_phantom:
                  type: boolean
                expected_yield_percent:
                  type: integer
                cost_allocation_method:
                  type: string
                default_consumption_method:
                  type: string
                output_lines:
                  type: array
                  items:
                    type: object
                    properties:
                      product_id:
                        type: integer
                      role:
                        type: string
                      quantity:
                        type: integer
                      uom_id:
                        type: integer
                      sort_order:
                        type: integer
                component_lines:
                  type: array
                  items:
                    type: object
                    properties:
                      product_id:
                        type: integer
                      quantity:
                        type: integer
                      uom_id:
                        type: integer
                      expected_scrap_percent:
                        type: integer
                      consumption_method:
                        type: string
                      is_optional:
                        type: boolean
                      sort_order:
                        type: integer
                operations:
                  type: array
                  items:
                    type: object
                    properties:
                      sequence:
                        type: integer
                      name:
                        type: string
                      work_center_id:
                        type: integer
                      operation_type:
                        type: string
                      time_minutes:
                        type: integer
                      cost_per_hour:
                        type: integer
                      fixed_cost:
                        type: integer
                      cost_classification:
                        type: string
                      instructions:
                        type: string
              example:
                product_id: 1
                name: Default Recipe v1
                version_notes: Initial recipe
                status: draft
                effective_from: '2026-01-01'
                effective_to: null
                is_default: true
                is_phantom: false
                expected_yield_percent: 98
                cost_allocation_method: by_value
                default_consumption_method: forward_flush
                output_lines:
                - product_id: 1
                  role: primary
                  quantity: 1
                  uom_id: 1
                  sort_order: 0
                component_lines:
                - product_id: 2
                  quantity: 2
                  uom_id: 1
                  expected_scrap_percent: 2
                  consumption_method: forward_flush
                  is_optional: false
                  sort_order: 0
                - product_id: 3
                  quantity: 1
                  uom_id: 1
                  consumption_method: backflush
                  sort_order: 1
                operations:
                - sequence: 10
                  name: Mix
                  work_center_id: 1
                  operation_type: setup
                  time_minutes: 30
                  cost_per_hour: 45
                  fixed_cost: 0
                  cost_classification: labor
                  instructions: Mix components thoroughly.
      parameters: []
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: integer
                  product_id:
                    type: integer
                  product_variant_id:
                    type: string
                    nullable: true
                  name:
                    type: string
                  version_number:
                    type: integer
                  version_notes:
                    type: string
                  status:
                    type: string
                  effective_from:
                    type: string
                  effective_to:
                    type: string
                    nullable: true
                  is_default:
                    type: boolean
                  is_phantom:
                    type: boolean
                  expected_yield_percent:
                    type: integer
                  manufacturing_leadtime_days:
                    type: string
                    nullable: true
                  cost_allocation_method:
                    type: string
                  default_consumption_method:
                    type: string
                  created_by_id:
                    type: integer
                  component_lines:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        bom_id:
                          type: integer
                        product_id:
                          type: integer
                        product_variant_id:
                          type: string
                          nullable: true
                        quantity:
                          type: integer
                        uom_id:
                          type: integer
                        expected_scrap_percent:
                          type: integer
                        consumption_method:
                          type: string
                        is_optional:
                          type: boolean
                        notes:
                          type: string
                          nullable: true
                        sort_order:
                          type: integer
                        estimated_cost:
                          type: number
                  output_lines:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        bom_id:
                          type: integer
                        product_id:
                          type: integer
                        product_variant_id:
                          type: string
                          nullable: true
                        role:
                          type: string
                        quantity:
                          type: integer
                        uom_id:
                          type: integer
                        manual_cost_percent:
                          type: string
                          nullable: true
                        byproduct_valuation_method:
                          type: string
                          nullable: true
                        byproduct_valuation_amount:
                          type: string
                          nullable: true
                        sort_order:
                          type: integer
                        estimated_cost:
                          type: number
                  operations:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        bom_id:
                          type: integer
                        sequence:
                          type: integer
                        name:
                          type: string
                        work_center_id:
                          type: integer
                        operation_type:
                          type: string
                        time_minutes:
                          type: integer
                        cost_per_hour:
                          type: integer
                        fixed_cost:
                          type: integer
                        cost_classification:
                          type: string
                        instructions:
                          type: string
                  archived_at:
                    type: string
                    nullable: true
                  created_at:
                    type: string
                  updated_at:
                    type: string
                example:
                  id: 12
                  product_id: 1
                  product_variant_id: null
                  name: Default Recipe v1
                  version_number: 1
                  version_notes: Initial recipe
                  status: draft
                  effective_from: '2026-01-01'
                  effective_to: null
                  is_default: true
                  is_phantom: false
                  expected_yield_percent: 98
                  manufacturing_leadtime_days: null
                  cost_allocation_method: by_value
                  default_consumption_method: forward_flush
                  created_by_id: 1
                  component_lines:
                  - id: 31
                    bom_id: 12
                    product_id: 2
                    product_variant_id: null
                    quantity: 2
                    uom_id: 1
                    expected_scrap_percent: 2
                    consumption_method: forward_flush
                    is_optional: false
                    notes: null
                    sort_order: 0
                    estimated_cost: 0.03
                  - id: 32
                    bom_id: 12
                    product_id: 3
                    product_variant_id: null
                    quantity: 1
                    uom_id: 1
                    expected_scrap_percent: null
                    consumption_method: backflush
                    is_optional: false
                    notes: null
                    sort_order: 1
                    estimated_cost: 0.03
                  output_lines:
                  - id: 21
                    bom_id: 12
                    product_id: 1
                    product_variant_id: null
                    role: primary
                    quantity: 1
                    uom_id: 1
                    manual_cost_percent: null
                    byproduct_valuation_method: null
                    byproduct_valuation_amount: null
                    sort_order: 0
                    estimated_cost: 0.03
                  operations:
                  - id: 7
                    bom_id: 12
                    sequence: 10
                    name: Mix
                    work_center_id: 1
                    operation_type: setup
                    time_minutes: 30
                    cost_per_hour: 45
                    fixed_cost: 0
                    cost_classification: labor
                    instructions: Mix components thoroughly.
                  archived_at: null
                  created_at: '2026-07-01T10:15:00.000000Z'
                  updated_at: '2026-07-01T10:15:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: manufacturing:write
      operationId: post-api-manufacturing-boms
    delete:
      tags:
      - BOMs
      summary: Bulk Delete BOMs
      description: 'Permanently delete multiple BOMs in one call.

        Auth: requires Bearer token.

        Body: ids (required, array of BOM ids, min 1). Rows that fail to delete are
        counted in failCount instead of aborting the batch.


        :::info[Required scope: `manufacturing:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      totalCount:
                        type: integer
                      failCount:
                        type: integer
                example:
                  message: Deleted 2 BOM(s)
                  data:
                    totalCount: 2
                    failCount: 0
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      ids:
                        type: array
                        items:
                          type: string
                example:
                  message: The ids field is required.
                  errors:
                    ids:
                    - The ids field is required.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: manufacturing:write
      operationId: delete-api-manufacturing-boms
  /api/manufacturing/boms/{id}:
    get:
      tags:
      - BOMs
      summary: Get BOM
      description: 'Get a single BOM with its product, component lines, output lines,
        operations (with work centers), and creator, plus `manufacturing_orders_count`.


        :::info[Required scope: `manufacturing:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        The BOM carries `default_consumption_method` (`forward_flush` | `backflush`
        | null) — the default inherited by component lines that don''t set their own
        — and each `component_lines[]` row carries its effective `consumption_method`.
        `forward_flush` components are issued explicitly by the operator when production
        is recorded; `backflush` components are auto-consumed from the produced output
        quantity multiplied by the BOM per-unit usage.

        Auth: requires Bearer token.'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: integer
                  product_id:
                    type: integer
                  product_variant_id:
                    type: string
                    nullable: true
                  product:
                    type: object
                    properties:
                      id:
                        type: integer
                      sku:
                        type: string
                      name:
                        type: string
                      stock_uom:
                        type: object
                        properties:
                          id:
                            type: integer
                          product_id:
                            type: integer
                          uom_id:
                            type: integer
                          unit_of_measure:
                            type: object
                            properties:
                              id:
                                type: integer
                              code:
                                type: string
                              name:
                                type: string
                              uom_type:
                                type: string
                              is_system:
                                type: boolean
                          is_stock_uom:
                            type: boolean
                          is_purchase_uom:
                            type: boolean
                          is_sales_uom:
                            type: boolean
                          conversion_factor:
                            type: integer
                          display_precision:
                            type: integer
                          has_transactional_history:
                            type: boolean
                  name:
                    type: string
                  version_number:
                    type: integer
                  version_notes:
                    type: string
                  status:
                    type: string
                  effective_from:
                    type: string
                  effective_to:
                    type: string
                    nullable: true
                  is_default:
                    type: boolean
                  is_phantom:
                    type: boolean
                  expected_yield_percent:
                    type: integer
                  manufacturing_leadtime_days:
                    type: integer
                  cost_allocation_method:
                    type: string
                  default_consumption_method:
                    type: string
                  created_by_id:
                    type: integer
                  created_by:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                  component_lines:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        bom_id:
                          type: integer
                        product_id:
                          type: integer
                        product_variant_id:
                          type: string
                          nullable: true
                        product:
                          type: object
                          properties:
                            id:
                              type: integer
                            sku:
                              type: string
                            name:
                              type: string
                            weight:
                              type: number
                            weight_unit:
                              type: string
                            stock_uom:
                              type: string
                              nullable: true
                        quantity:
                          type: integer
                        uom_id:
                          type: integer
                        unit_of_measure:
                          type: object
                          properties:
                            id:
                              type: integer
                            code:
                              type: string
                            name:
                              type: string
                            uom_type:
                              type: string
                            is_system:
                              type: boolean
                        expected_scrap_percent:
                          type: integer
                        consumption_method:
                          type: string
                        is_optional:
                          type: boolean
                        notes:
                          type: string
                          nullable: true
                        sort_order:
                          type: integer
                        estimated_cost:
                          type: number
                  output_lines:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        bom_id:
                          type: integer
                        product_id:
                          type: integer
                        product_variant_id:
                          type: string
                          nullable: true
                        product:
                          type: object
                          properties:
                            id:
                              type: integer
                            sku:
                              type: string
                            name:
                              type: string
                            weight:
                              type: number
                            weight_unit:
                              type: string
                            stock_uom:
                              type: string
                              nullable: true
                        role:
                          type: string
                        quantity:
                          type: integer
                        uom_id:
                          type: integer
                        unit_of_measure:
                          type: object
                          properties:
                            id:
                              type: integer
                            code:
                              type: string
                            name:
                              type: string
                            uom_type:
                              type: string
                            is_system:
                              type: boolean
                        manual_cost_percent:
                          type: string
                          nullable: true
                        byproduct_valuation_method:
                          type: string
                          nullable: true
                        byproduct_valuation_amount:
                          type: string
                          nullable: true
                        sort_order:
                          type: integer
                        estimated_cost:
                          type: number
                  operations:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        bom_id:
                          type: integer
                        sequence:
                          type: integer
                        name:
                          type: string
                        work_center_id:
                          type: integer
                        work_center:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            overhead_rate_percent:
                              type: integer
                        operation_type:
                          type: string
                        time_minutes:
                          type: integer
                        cost_per_hour:
                          type: integer
                        fixed_cost:
                          type: integer
                        instructions:
                          type: string
                  manufacturing_orders_count:
                    type: integer
                  draft_manufacturing_orders_count:
                    type: integer
                  archived_at:
                    type: string
                    nullable: true
                  created_at:
                    type: string
                  updated_at:
                    type: string
                example:
                  id: 12
                  product_id: 1
                  product_variant_id: null
                  product:
                    id: 1
                    sku: KIT-A
                    name: Widget Kit A
                    stock_uom:
                      id: 11
                      product_id: 1
                      uom_id: 1
                      unit_of_measure:
                        id: 1
                        code: EA
                        name: Each
                        uom_type: count
                        is_system: true
                      is_stock_uom: true
                      is_purchase_uom: true
                      is_sales_uom: true
                      conversion_factor: 1
                      display_precision: 0
                      has_transactional_history: true
                  name: Default Recipe v1
                  version_number: 1
                  version_notes: Initial recipe
                  status: active
                  effective_from: '2026-01-01'
                  effective_to: null
                  is_default: true
                  is_phantom: false
                  expected_yield_percent: 98
                  manufacturing_leadtime_days: 2
                  cost_allocation_method: by_value
                  default_consumption_method: forward_flush
                  created_by_id: 1
                  created_by:
                    id: 1
                    name: Dev User
                  component_lines:
                  - id: 31
                    bom_id: 12
                    product_id: 2
                    product_variant_id: null
                    product:
                      id: 2
                      sku: RM-BEAN
                      name: Raw Coffee Beans
                      weight: 0.5
                      weight_unit: kg
                      stock_uom: null
                    quantity: 2
                    uom_id: 1
                    unit_of_measure:
                      id: 1
                      code: EA
                      name: Each
                      uom_type: count
                      is_system: true
                    expected_scrap_percent: 2
                    consumption_method: forward_flush
                    is_optional: false
                    notes: null
                    sort_order: 0
                    estimated_cost: 0.03
                  - id: 32
                    bom_id: 12
                    product_id: 3
                    product_variant_id: null
                    product:
                      id: 3
                      sku: PKG-POUCH
                      name: 250g Pouch
                      weight: 0.02
                      weight_unit: kg
                      stock_uom: null
                    quantity: 1
                    uom_id: 1
                    unit_of_measure:
                      id: 1
                      code: EA
                      name: Each
                      uom_type: count
                      is_system: true
                    expected_scrap_percent: null
                    consumption_method: backflush
                    is_optional: false
                    notes: null
                    sort_order: 1
                    estimated_cost: 0.03
                  output_lines:
                  - id: 21
                    bom_id: 12
                    product_id: 1
                    product_variant_id: null
                    product:
                      id: 1
                      sku: KIT-A
                      name: Widget Kit A
                      weight: 1.2
                      weight_unit: kg
                      stock_uom: null
                    role: primary
                    quantity: 1
                    uom_id: 1
                    unit_of_measure:
                      id: 1
                      code: EA
                      name: Each
                      uom_type: count
                      is_system: true
                    manual_cost_percent: null
                    byproduct_valuation_method: null
                    byproduct_valuation_amount: null
                    sort_order: 0
                    estimated_cost: 0.03
                  operations:
                  - id: 7
                    bom_id: 12
                    sequence: 10
                    name: Mix
                    work_center_id: 1
                    work_center:
                      id: 1
                      name: Mixing Station
                      overhead_rate_percent: 10
                    operation_type: setup
                    time_minutes: 30
                    cost_per_hour: 45
                    fixed_cost: 75
                    instructions: Mix components thoroughly.
                  manufacturing_orders_count: 3
                  draft_manufacturing_orders_count: 2
                  archived_at: null
                  created_at: '2026-07-01T10:15:00.000000Z'
                  updated_at: '2026-07-02T08:30:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: manufacturing:read
      operationId: get-api-manufacturing-boms-id
    put:
      tags:
      - BOMs
      summary: Update BOM
      description: 'Update a BOM. All fields are optional — omitted fields keep their
        current values.


        :::info[Required scope: `manufacturing:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        `default_consumption_method` (nullable, enum: `forward_flush` | `backflush`)
        sets the BOM-level default inherited by component lines that omit their own
        `consumption_method`; a per-line `consumption_method` always overrides it.
        A component line submitted with an explicit `consumption_method: null` behaves
        exactly like omitting the field — a new line inherits the BOM default (falling
        back to `forward_flush`), and an existing line keeps its current method. Changing
        consumption methods only affects manufacturing orders confirmed after the
        change — each order snapshots the method per component line at confirmation,
        so open orders keep consuming the way they were confirmed.

        Auth: requires Bearer token.


        `cost_classification` (optional, `labor`|`overhead`, default `labor`) sets
        the expense classification independently of the rate basis: `labor` posts
        the operation''s variable cost to the Labor bucket (marked up by the work
        center''s overhead %); `overhead` posts machine/tooling-style cost to the
        Overhead bucket with no additional markup.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                version_notes:
                  type: string
                cost_allocation_method:
                  type: string
                default_consumption_method:
                  type: string
                component_lines:
                  type: array
                  items:
                    type: object
                    properties:
                      id:
                        type: integer
                      product_id:
                        type: integer
                      quantity:
                        type: number
                      uom_id:
                        type: integer
                      expected_scrap_percent:
                        type: integer
                      consumption_method:
                        type: string
              example:
                name: Default Recipe v2
                version_notes: Adjusted scrap
                cost_allocation_method: by_quantity
                default_consumption_method: backflush
                component_lines:
                - id: 11
                  product_id: 2
                  quantity: 2.5
                  uom_id: 1
                  expected_scrap_percent: 3
                  consumption_method: forward_flush
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: integer
                  product_id:
                    type: integer
                  product_variant_id:
                    type: string
                    nullable: true
                  name:
                    type: string
                  version_number:
                    type: integer
                  version_notes:
                    type: string
                  status:
                    type: string
                  effective_from:
                    type: string
                  effective_to:
                    type: string
                    nullable: true
                  is_default:
                    type: boolean
                  is_phantom:
                    type: boolean
                  expected_yield_percent:
                    type: integer
                  manufacturing_leadtime_days:
                    type: integer
                  cost_allocation_method:
                    type: string
                  default_consumption_method:
                    type: string
                  created_by_id:
                    type: integer
                  component_lines:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        bom_id:
                          type: integer
                        product_id:
                          type: integer
                        product_variant_id:
                          type: string
                          nullable: true
                        quantity:
                          type: number
                        uom_id:
                          type: integer
                        expected_scrap_percent:
                          type: integer
                        consumption_method:
                          type: string
                        is_optional:
                          type: boolean
                        notes:
                          type: string
                          nullable: true
                        sort_order:
                          type: integer
                        estimated_cost:
                          type: number
                  output_lines:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        bom_id:
                          type: integer
                        product_id:
                          type: integer
                        product_variant_id:
                          type: string
                          nullable: true
                        role:
                          type: string
                        quantity:
                          type: integer
                        uom_id:
                          type: integer
                        manual_cost_percent:
                          type: string
                          nullable: true
                        byproduct_valuation_method:
                          type: string
                          nullable: true
                        byproduct_valuation_amount:
                          type: string
                          nullable: true
                        sort_order:
                          type: integer
                        estimated_cost:
                          type: number
                  operations:
                    type: array
                  archived_at:
                    type: string
                    nullable: true
                  created_at:
                    type: string
                  updated_at:
                    type: string
                example:
                  id: 12
                  product_id: 1
                  product_variant_id: null
                  name: Default Recipe v2
                  version_number: 1
                  version_notes: Adjusted scrap
                  status: active
                  effective_from: '2026-01-01'
                  effective_to: null
                  is_default: true
                  is_phantom: false
                  expected_yield_percent: 98
                  manufacturing_leadtime_days: 2
                  cost_allocation_method: by_quantity
                  default_consumption_method: backflush
                  created_by_id: 1
                  component_lines:
                  - id: 11
                    bom_id: 12
                    product_id: 2
                    product_variant_id: null
                    quantity: 2.5
                    uom_id: 1
                    expected_scrap_percent: 3
                    consumption_method: forward_flush
                    is_optional: false
                    notes: null
                    sort_order: 0
                    estimated_cost: 0.03
                  output_lines:
                  - id: 21
                    bom_id: 12
                    product_id: 1
                    product_variant_id: null
                    role: primary
                    quantity: 1
                    uom_id: 1
                    manual_cost_percent: null
                    byproduct_valuation_method: null
                    byproduct_valuation_amount: null
                    sort_order: 0
                    estimated_cost: 0.03
                  operations: []
                  archived_at: null
                  created_at: '2026-07-01T10:15:00.000000Z'
                  updated_at: '2026-07-02T11:40:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: manufacturing:write
      operationId: put-api-manufacturing-boms-id
    delete:
      tags:
      - BOMs
      summary: Delete BOM
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: manufacturing:write
      description: 'Delete BOM


        :::info[Required scope: `manufacturing:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      operationId: delete-api-manufacturing-boms-id
  /api/manufacturing/boms/{id}/duplicate:
    post:
      tags:
      - BOMs
      summary: Duplicate BOM
      description: 'Deep-clones a BOM into a new draft (output lines, component lines,
        operations). The new BOM''s name is the source''s name with " (Copy)" appended;
        if that name is already taken for the same product/variant the suffix becomes
        " (Copy 2)", " (Copy 3)", etc.


        :::info[Required scope: `manufacturing:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties: {}
              example: {}
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: manufacturing:write
      operationId: post-api-manufacturing-boms-id-duplicate
  /api/manufacturing/boms/{bom}/save-as-new-version:
    post:
      tags:
      - BOMs
      summary: Save BOM as New Version
      description: 'Create a new version of the BOM from the submitted fields, leaving
        the source version untouched. Accepts the same fields as Update BOM. The new
        version is created as Active with version_number set to the next number for
        the same product/variant.

        Auth: requires Bearer token.

        Path param: bom = source BOM id.


        :::info[Required scope: `manufacturing:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        `update_draft_mos` (boolean, optional, default false): when true, every still-in-Draft
        manufacturing order that references the old version is moved onto the new
        version. Started/completed orders keep their pinned version.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                version_notes:
                  type: string
                effective_from:
                  type: string
                cost_allocation_method:
                  type: string
                default_consumption_method:
                  type: string
                output_lines:
                  type: array
                  items:
                    type: object
                    properties:
                      product_id:
                        type: integer
                      role:
                        type: string
                      quantity:
                        type: integer
                      uom_id:
                        type: integer
                component_lines:
                  type: array
                  items:
                    type: object
                    properties:
                      product_id:
                        type: integer
                      quantity:
                        type: number
                      uom_id:
                        type: integer
                      expected_scrap_percent:
                        type: integer
                      consumption_method:
                        type: string
                update_draft_mos:
                  type: boolean
              example:
                name: Default Recipe
                version_notes: Reduced component scrap
                effective_from: '2026-07-01'
                cost_allocation_method: by_weight
                default_consumption_method: forward_flush
                output_lines:
                - product_id: 1
                  role: primary
                  quantity: 1
                  uom_id: 1
                component_lines:
                - product_id: 2
                  quantity: 2.5
                  uom_id: 1
                  expected_scrap_percent: 3
                  consumption_method: forward_flush
                update_draft_mos: true
      parameters:
      - name: bom
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The bom ID.
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: integer
                  product_id:
                    type: integer
                  product_variant_id:
                    type: string
                    nullable: true
                  name:
                    type: string
                  version_number:
                    type: integer
                  version_notes:
                    type: string
                  status:
                    type: string
                  effective_from:
                    type: string
                  effective_to:
                    type: string
                    nullable: true
                  is_default:
                    type: boolean
                  is_phantom:
                    type: boolean
                  expected_yield_percent:
                    type: string
                    nullable: true
                  manufacturing_leadtime_days:
                    type: integer
                  cost_allocation_method:
                    type: string
                  default_consumption_method:
                    type: string
                  created_by_id:
                    type: integer
                  component_lines:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        product_id:
                          type: integer
                        quantity:
                          type: number
                        uom_id:
                          type: integer
                        expected_scrap_percent:
                          type: integer
                        consumption_method:
                          type: string
                  output_lines:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        product_id:
                          type: integer
                        role:
                          type: string
                        quantity:
                          type: integer
                        uom_id:
                          type: integer
                  operations:
                    type: array
                  manufacturing_orders_count:
                    type: integer
                  draft_manufacturing_orders_count:
                    type: integer
                  archived_at:
                    type: string
                    nullable: true
                  created_at:
                    type: string
                  updated_at:
                    type: string
                example:
                  id: 15
                  product_id: 1
                  product_variant_id: null
                  name: Default Recipe
                  version_number: 3
                  version_notes: Reduced component scrap
                  status: active
                  effective_from: '2026-07-01'
                  effective_to: null
                  is_default: false
                  is_phantom: false
                  expected_yield_percent: null
                  manufacturing_leadtime_days: 2
                  cost_allocation_method: by_weight
                  default_consumption_method: forward_flush
                  created_by_id: 1
                  component_lines:
                  - id: 61
                    product_id: 2
                    quantity: 2.5
                    uom_id: 1
                    expected_scrap_percent: 3
                    consumption_method: forward_flush
                  output_lines:
                  - id: 44
                    product_id: 1
                    role: primary
                    quantity: 1
                    uom_id: 1
                  operations: []
                  manufacturing_orders_count: 0
                  draft_manufacturing_orders_count: 0
                  archived_at: null
                  created_at: '2026-07-01T14:22:09.000000Z'
                  updated_at: '2026-07-01T14:22:09.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: manufacturing:write
      operationId: post-api-manufacturing-boms-bom-save-as-new-version
  /api/manufacturing/boms/{id}/activate:
    post:
      tags:
      - BOMs
      summary: Activate BOM
      description: 'Transitions a draft BOM to active. Optionally overrides effective
        dates.


        :::info[Required scope: `manufacturing:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                effective_from:
                  type: string
                effective_to:
                  type: string
                  nullable: true
              example:
                effective_from: '2026-04-19'
                effective_to: null
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: manufacturing:write
      operationId: post-api-manufacturing-boms-id-activate
  /api/manufacturing/boms/{id}/deactivate:
    post:
      tags:
      - BOMs
      summary: Deactivate BOM
      description: 'Transitions an Active BOM back to Draft so it can be edited without
        archiving it (distinct from Archive, which retires the BOM). If the BOM was
        the default for its product/variant, the next eligible BOM is auto-promoted.
        Returns the refreshed BOM object under `data` (200), plus a root-level `promoted_default`
        object ({id, name, version_number}) naming the newly-promoted default — or
        `null` if nothing was promoted. The optional `reason` (nullable string, max
        1000) is recorded on the BOM activity log.


        :::info[Required scope: `manufacturing:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                reason:
                  type: string
              example:
                reason: Needs a recipe correction before re-activating
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: manufacturing:write
      operationId: post-api-manufacturing-boms-id-deactivate
  /api/manufacturing/boms/{id}/archive:
    post:
      tags:
      - BOMs
      summary: Archive BOM
      description: 'Archives an Active BOM, marking it as retired (sets `archived_at`).
        If the archived BOM was the default for its product/variant, the next eligible
        BOM is auto-promoted to default. Returns the refreshed BOM object under `data`
        (200), plus a root-level `promoted_default` object ({id, name, version_number})
        naming the newly-promoted default — or `null` if nothing was promoted. The
        frontend uses this to show "BOM archived — {name} v{version} is now the default".
        The optional `reason` (nullable string, max 1000) is recorded on the BOM activity
        log.


        :::info[Required scope: `manufacturing:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                reason:
                  type: string
              example:
                reason: Superseded by v2
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: manufacturing:write
      operationId: post-api-manufacturing-boms-id-archive
  /api/manufacturing/boms/{id}/restore:
    post:
      tags:
      - BOMs
      summary: Restore BOM
      description: 'Restores an archived BOM back to Draft status. Clears `archived_at`
        and removes the `is_default` flag so it does not auto-promote on next activation.
        The caller can then re-activate from Draft when ready. Returns the refreshed
        BOM object (200). Returns 500 if the BOM is not currently archived. The optional
        `reason` (nullable string, max 1000) is recorded on the BOM activity log.


        :::info[Required scope: `manufacturing:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                reason:
                  type: string
              example:
                reason: Customer asked us to bring this recipe back.
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: manufacturing:write
      operationId: post-api-manufacturing-boms-id-restore
  /api/manufacturing/boms/bulk-archive:
    post:
      tags:
      - BOMs
      summary: Bulk Archive BOMs
      description: 'Archives multiple BOMs in one call. Body: `ids` (required array
        of BOM IDs, min 1; each must exist in `boms`). Only BOMs currently in `active`
        status are archived; BOMs in any other status are skipped. Each archived BOM
        that was a default triggers auto-promotion of the next eligible BOM for its
        product/variant. Returns a `message` summary and a `data` object: `{ totalCount,
        archivedCount, skippedCount, failCount }`.


        :::info[Required scope: `manufacturing:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1
                - 2
                - 3
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      totalCount:
                        type: integer
                      archivedCount:
                        type: integer
                      skippedCount:
                        type: integer
                      failCount:
                        type: integer
                example:
                  message: Archived 2 BOM(s) (1 skipped)
                  data:
                    totalCount: 3
                    archivedCount: 2
                    skippedCount: 1
                    failCount: 0
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: manufacturing:write
      operationId: post-api-manufacturing-boms-bulk-archive
  /api/manufacturing/boms/bulk-restore:
    post:
      tags:
      - BOMs
      summary: Bulk Restore BOMs
      description: 'Restores multiple archived BOMs back to Draft in one call. Body:
        `ids` (required array of BOM IDs, min 1; each must exist in `boms`). Only
        BOMs currently in `archived` status are restored; BOMs in any other status
        are skipped. Returns a `message` summary and a `data` object: `{ totalCount,
        restoredCount, skippedCount, failCount }`.


        :::info[Required scope: `manufacturing:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1
                - 2
                - 3
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      totalCount:
                        type: integer
                      restoredCount:
                        type: integer
                      skippedCount:
                        type: integer
                      failCount:
                        type: integer
                example:
                  message: Restored 3 BOM(s)
                  data:
                    totalCount: 3
                    restoredCount: 3
                    skippedCount: 0
                    failCount: 0
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: manufacturing:write
      operationId: post-api-manufacturing-boms-bulk-restore
  /api/manufacturing/boms/{id}/set-default:
    post:
      tags:
      - BOMs
      summary: Set BOM as Default
      description: 'Promotes the given BOM to be the default for its product/variant.
        Any other BOM currently marked default for the same product (and variant,
        if scoped) is automatically demoted to `is_default = false`. This is the single-record
        endpoint backing the kebab "Set as Default" action; for status transitions
        use `activate`/`archive` instead. Returns the refreshed BOM object (200).
        No request body is required.


        :::info[Required scope: `manufacturing:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties: {}
              example: {}
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: integer
                  product_id:
                    type: integer
                  product_variant_id:
                    type: string
                    nullable: true
                  name:
                    type: string
                  version_number:
                    type: integer
                  version_notes:
                    type: string
                    nullable: true
                  status:
                    type: string
                  effective_from:
                    type: string
                  effective_to:
                    type: string
                    nullable: true
                  is_default:
                    type: boolean
                  is_phantom:
                    type: boolean
                  expected_yield_percent:
                    type: string
                    nullable: true
                  cost_allocation_method:
                    type: string
                  created_by_id:
                    type: integer
                  archived_at:
                    type: string
                    nullable: true
                  created_at:
                    type: string
                  updated_at:
                    type: string
                example:
                  id: 14
                  product_id: 822
                  product_variant_id: null
                  name: Vanilla Latte v3
                  version_number: 3
                  version_notes: null
                  status: active
                  effective_from: '2026-05-28'
                  effective_to: null
                  is_default: true
                  is_phantom: false
                  expected_yield_percent: null
                  cost_allocation_method: by_weight
                  created_by_id: 1
                  archived_at: null
                  created_at: '2026-05-28T09:14:11.000000Z'
                  updated_at: '2026-05-28T11:02:48.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: manufacturing:write
      operationId: post-api-manufacturing-boms-id-set-default
  /api/manufacturing/boms/{id}/current-default:
    get:
      tags:
      - BOMs
      summary: Get Current Default for BOM
      description: 'Returns the BOM currently marked default for the same product/variant
        as the given BOM, excluding the given BOM itself. Used by the UI to name the
        existing default in a "Set as Default" confirmation dialog (e.g. "This will
        replace ''Vanilla Latte v2'' as the default."). Returns `{ "data": { id, name,
        version_number } }` when another default exists; returns `{ "data": null }`
        when there is no other default for that product/variant.


        :::info[Required scope: `manufacturing:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 OK (existing default found)
                  value:
                    data:
                      id: 12
                      name: Vanilla Latte v2
                      version_number: 2
                example-1:
                  summary: 200 OK (no other default)
                  value:
                    data: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: manufacturing:read
      operationId: get-api-manufacturing-boms-id-current-default
  /api/manufacturing/boms/{id}/explode:
    get:
      tags:
      - BOMs
      summary: Explode BOM
      description: 'Recursively explodes a BOM into its full multi-level component
        list for a target quantity.


        :::info[Required scope: `manufacturing:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      - name: quantity
        in: query
        schema:
          type: integer
        example: '10'
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: manufacturing:read
      operationId: get-api-manufacturing-boms-id-explode
  /api/manufacturing/boms/{bom}/activity-log:
    get:
      tags:
      - BOMs
      summary: List BOM Activity Log
      description: 'Paginated audit trail of changes made to the BOM and its lines
        - who changed what and when, newest first.

        Auth: requires Bearer token.

        Path param: bom = BOM id.


        :::info[Required scope: `manufacturing:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: bom
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The bom ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        description:
                          type: string
                        event:
                          type: string
                        subject_type:
                          type: string
                        subject_id:
                          type: integer
                        properties:
                          type: object
                          properties:
                            attributes:
                              type: object
                              properties:
                                name:
                                  type: string
                            old:
                              type: object
                              properties:
                                name:
                                  type: string
                        causer_name:
                          type: string
                        created_at:
                          type: string
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 911
                    description: updated
                    event: updated
                    subject_type: Bom
                    subject_id: 15
                    properties:
                      attributes:
                        name: Default Recipe v2
                      old:
                        name: Default Recipe
                    causer_name: Jane Smith
                    created_at: '2026-07-01T14:22:09.000000Z'
                  first_page_url: https://your-domain.sku.io/api/manufacturing/boms/15/activity-log?page=1
                  from: 1
                  last_page: 1
                  last_page_url: https://your-domain.sku.io/api/manufacturing/boms/15/activity-log?page=1
                  links: []
                  next_page_url: null
                  path: https://your-domain.sku.io/api/manufacturing/boms/15/activity-log
                  per_page: 15
                  prev_page_url: null
                  to: 1
                  total: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: manufacturing:read
      operationId: get-api-manufacturing-boms-bom-activity-log
  /api/manufacturing/manufacturing-orders:
    get:
      tags:
      - Manufacturing Orders
      summary: List Manufacturing Orders
      description: 'Paginated list of Manufacturing Orders. Supports Spatie QueryBuilder
        filters, sorts, and pagination.


        :::info[Required scope: `manufacturing:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        **Filters** (all optional, all use `filter[key]=value` syntax):

        - `filter[status]` — exact match against `draft|confirmed|in_progress|completed|closed|cancelled`

        - `filter[warehouse_id]` — exact match

        - `filter[is_simple_mode]` — `1` to show only Simple Mode MOs (created via
        /simple-assemble)

        - `filter[is_disassemble]` — `1` to show only disassembly MOs (Simple Mode
        with action=disassemble)


        **Sort:** `sort=<field>`, prefix with `-` for DESC (e.g. `-created_at`). Defaults
        to `-created_at`. Allowed sorts: id, mo_number, status, priority, production_method,
        scheduled_start, scheduled_end, started_at, completed_at, planned_quantity,
        completed_quantity, created_at, updated_at, warehouse_name, contractor_supplier_name,
        assigned_to. `warehouse_name`, `contractor_supplier_name`, and `assigned_to`
        sort by the related warehouse / supplier / assignee name (LEFT JOIN).

        **Pagination:** `page`, `per_page` (default 10).


        Response items are manufacturing order list object (trimmed payload — no component_lines/output_lines).
        `primary_output_name` / `primary_output_product_id` resolve the primary output
        line''s product, falling back to the BOM output product for draft MOs (so
        the list can link the Output cell to the product detail page).'
      parameters:
      - name: per_page
        in: query
        schema:
          type: integer
        example: '25'
        description: Results per page (default 10).
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        mo_number:
                          type: string
                        status:
                          type: string
                        bom_id:
                          type: integer
                        bom_name:
                          type: string
                        warehouse_id:
                          type: integer
                        warehouse_name:
                          type: string
                        destination_warehouse_id:
                          type: integer
                        destination_warehouse_name:
                          type: string
                        primary_output_name:
                          type: string
                        primary_output_product_id:
                          type: integer
                        planned_quantity:
                          type: integer
                        completed_quantity:
                          type: integer
                        production_method:
                          type: string
                        contractor_supplier_id:
                          type: string
                          nullable: true
                        contractor_supplier_name:
                          type: string
                          nullable: true
                        outsourced_purchase_order_id:
                          type: string
                          nullable: true
                        sales_order_id:
                          type: string
                          nullable: true
                        sales_order_line_id:
                          type: string
                          nullable: true
                        priority:
                          type: integer
                        scheduled_start:
                          type: string
                        scheduled_end:
                          type: string
                        started_at:
                          type: string
                          nullable: true
                        completed_at:
                          type: string
                          nullable: true
                        closed_at:
                          type: string
                          nullable: true
                        cancelled_at:
                          type: string
                          nullable: true
                        is_simple_mode:
                          type: boolean
                        is_disassemble:
                          type: boolean
                        internal_reference:
                          type: string
                        assigned_to_id:
                          type: integer
                        assigned_to:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        cost_breakdown:
                          type: string
                          nullable: true
                        has_shortage:
                          type: boolean
                        created_at:
                          type: string
                        updated_at:
                          type: string
                        archived_at:
                          type: string
                          nullable: true
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - id: 1024
                    mo_number: MO-000042
                    status: confirmed
                    bom_id: 88
                    bom_name: Premium Hoodie Assembly v3
                    warehouse_id: 2
                    warehouse_name: Main Warehouse
                    destination_warehouse_id: 2
                    destination_warehouse_name: Main Warehouse
                    primary_output_name: Premium Cotton Hoodie - Black - L
                    primary_output_product_id: 4551
                    planned_quantity: 250
                    completed_quantity: 0
                    production_method: in_house
                    contractor_supplier_id: null
                    contractor_supplier_name: null
                    outsourced_purchase_order_id: null
                    sales_order_id: null
                    sales_order_line_id: null
                    priority: 10
                    scheduled_start: '2026-07-05T08:00:00.000000Z'
                    scheduled_end: '2026-07-08T17:00:00.000000Z'
                    started_at: null
                    completed_at: null
                    closed_at: null
                    cancelled_at: null
                    is_simple_mode: false
                    is_disassemble: false
                    internal_reference: Batch Q3-A
                    assigned_to_id: 7
                    assigned_to:
                      id: 7
                      name: Jamie Rivera
                    cost_breakdown: null
                    has_shortage: false
                    created_at: '2026-07-01T14:32:10.000000Z'
                    updated_at: '2026-07-02T09:15:44.000000Z'
                    archived_at: null
                  current_page: 1
                  last_page: 5
                  per_page: 25
                  total: 118
                  from: 1
                  to: 25
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: manufacturing:read
      operationId: get-api-manufacturing-manufacturing-orders
    post:
      tags:
      - Manufacturing Orders
      summary: Create Manufacturing Order
      description: 'Create a draft MO from a BOM. Hydrates component + output + operation
        snapshot lines from the BOM.


        :::info[Required scope: `manufacturing:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        For outsourced orders (production_method: outsourced) the request also accepts:
        contractor_supplier_id (required for outsourced, integer, must be a supplier
        flagged as a manufacturing contractor); outsourced_cost_basis (optional, string,
        one of: toll, hybrid) - how the contractor''s product charge is costed into
        the finished output. toll = you own all component materials and the charge
        is a processing cost only; hybrid = the contractor supplies additional materials
        of their own and the charge is capitalized into output cost. When omitted
        the contractor''s default_outsourced_cost_basis applies, falling back to hybrid;
        service_fee_amount (optional, numeric, min 0). These three fields are rejected
        for in_house orders.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                bom_id:
                  type: integer
                warehouse_id:
                  type: integer
                destination_warehouse_id:
                  type: integer
                planned_quantity:
                  type: integer
                production_method:
                  type: string
                contractor_supplier_id:
                  type: integer
                outsourced_cost_basis:
                  type: string
                priority:
                  type: integer
                scheduled_start:
                  type: string
                scheduled_end:
                  type: string
                notes:
                  type: string
                internal_reference:
                  type: string
              example:
                bom_id: 1
                warehouse_id: 1
                destination_warehouse_id: 1
                planned_quantity: 100
                production_method: in_house
                contractor_supplier_id: 12
                outsourced_cost_basis: toll
                priority: 10
                scheduled_start: '2026-04-22'
                scheduled_end: '2026-04-24'
                notes: Standard production run
                internal_reference: BATCH-001
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: manufacturing:write
      operationId: post-api-manufacturing-manufacturing-orders
  /api/manufacturing/manufacturing-orders/{id}:
    get:
      tags:
      - Manufacturing Orders
      summary: Get Manufacturing Order
      description: 'Return the full Manufacturing Order with its BOM, component/output
        lines, operations, warehouses, and events.


        :::info[Required scope: `manufacturing:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        **BOM line counts (P5/P6):** The nested `bom` object includes `component_lines_count`,
        `output_lines_count`, and `operations_count` (eager-loaded via `withCount`).
        For **draft** MOs — which have no materialised `component_lines`/`output_lines`/`operations`
        rows yet (those are created by ConfirmMoAction) — clients should fall back
        to these BOM counts when rendering tab badges and the footer summary so the
        user sees what the MO *will* contain once confirmed.


        Once production has been recorded, `cost_breakdown` is populated with cumulative
        cost categories: `materials`, `labor`, `overhead`, `fixed` (flat per-run operation
        costs — never marked up by overhead), `service_fee`, `landed_cost` (outsourced
        orders only), `total`, `allocation_method`, `recorded_at`, and per-output
        allocation rows in `outputs[]`. It is null until the first production record.


        Each `component_lines[]` row carries `consumption_method` (`forward_flush`
        | `backflush`) — snapshotted from the BOM at confirmation — and each `operations[]`
        row carries `fixed_cost` plus `cost_source` (`none` | `actual` | `estimated`
        | `manual`) — the provenance of its `actual_cost`: `estimated` flags a cost
        that fell back to the planned duration because no time was logged, and `manual`
        marks an explicitly supplied cost that is never auto-recalculated (only another
        explicit cost, or an explicitly logged positive time, replaces it).


        **Outsourced cost basis:** `outsourced_cost_basis` is the order''s explicit
        override (`toll` | `hybrid`, null = inherit) and `resolved_outsourced_cost_basis`
        is the basis actually used for costing (override, else the contractor''s `default_outsourced_cost_basis`,
        else `hybrid`). `resolved_outsourced_cost_basis` is null for in-house orders.
        The nested `contractor_supplier` object also carries the contractor''s `default_outsourced_cost_basis`.'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: integer
                  mo_number:
                    type: string
                  status:
                    type: string
                  bom_id:
                    type: integer
                  bom:
                    type: object
                    properties:
                      id:
                        type: integer
                      product_id:
                        type: integer
                      product:
                        type: object
                        properties:
                          id:
                            type: integer
                          sku:
                            type: string
                          name:
                            type: string
                      name:
                        type: string
                      version_number:
                        type: integer
                      status:
                        type: string
                      effective_from:
                        type: string
                      effective_to:
                        type: string
                        nullable: true
                      is_default:
                        type: boolean
                      is_phantom:
                        type: boolean
                      cost_allocation_method:
                        type: string
                      component_lines_count:
                        type: integer
                      output_lines_count:
                        type: integer
                      operations_count:
                        type: integer
                      archived_at:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                  warehouse_id:
                    type: integer
                  warehouse:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                  destination_warehouse_id:
                    type: integer
                  destination_warehouse:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                  planned_quantity:
                    type: integer
                  completed_quantity:
                    type: integer
                  production_method:
                    type: string
                  contractor_supplier_id:
                    type: string
                    nullable: true
                  outsourced_cost_basis:
                    type: string
                    nullable: true
                  resolved_outsourced_cost_basis:
                    type: string
                    nullable: true
                  outsourced_purchase_order_id:
                    type: string
                    nullable: true
                  sales_order_id:
                    type: string
                    nullable: true
                  sales_order_line_id:
                    type: string
                    nullable: true
                  priority:
                    type: integer
                  scheduled_start:
                    type: string
                    nullable: true
                  scheduled_end:
                    type: string
                    nullable: true
                  started_at:
                    type: string
                    nullable: true
                  completed_at:
                    type: string
                    nullable: true
                  closed_at:
                    type: string
                    nullable: true
                  cancelled_at:
                    type: string
                    nullable: true
                  cancelled_reason_code:
                    type: string
                    nullable: true
                  cancelled_reason_notes:
                    type: string
                    nullable: true
                  is_simple_mode:
                    type: boolean
                  is_disassemble:
                    type: boolean
                  notes:
                    type: string
                    nullable: true
                  internal_reference:
                    type: string
                    nullable: true
                  cost_breakdown:
                    type: string
                    nullable: true
                  created_by_id:
                    type: integer
                  created_by:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                  assigned_to_id:
                    type: string
                    nullable: true
                  component_lines:
                    type: array
                  output_lines:
                    type: array
                  operations:
                    type: array
                  events:
                    type: array
                  created_at:
                    type: string
                  updated_at:
                    type: string
                  archived_at:
                    type: string
                    nullable: true
                example:
                  id: 18
                  mo_number: MO-000018
                  status: draft
                  bom_id: 2
                  bom:
                    id: 2
                    product_id: 412
                    product:
                      id: 412
                      sku: WIDGET-A
                      name: Widget A — Finished
                    name: Widget A BOM
                    version_number: 1
                    status: active
                    effective_from: '2026-01-01'
                    effective_to: null
                    is_default: true
                    is_phantom: false
                    cost_allocation_method: by_weight
                    component_lines_count: 3
                    output_lines_count: 1
                    operations_count: 2
                    archived_at: null
                    created_at: '2026-05-20T10:00:00.000000Z'
                    updated_at: '2026-05-20T10:00:00.000000Z'
                  warehouse_id: 1
                  warehouse:
                    id: 1
                    name: Main Warehouse
                  destination_warehouse_id: 1
                  destination_warehouse:
                    id: 1
                    name: Main Warehouse
                  planned_quantity: 10
                  completed_quantity: 0
                  production_method: in_house
                  contractor_supplier_id: null
                  outsourced_cost_basis: null
                  resolved_outsourced_cost_basis: null
                  outsourced_purchase_order_id: null
                  sales_order_id: null
                  sales_order_line_id: null
                  priority: 100
                  scheduled_start: null
                  scheduled_end: null
                  started_at: null
                  completed_at: null
                  closed_at: null
                  cancelled_at: null
                  cancelled_reason_code: null
                  cancelled_reason_notes: null
                  is_simple_mode: false
                  is_disassemble: false
                  notes: null
                  internal_reference: null
                  cost_breakdown: null
                  created_by_id: 1
                  created_by:
                    id: 1
                    name: Dev User
                  assigned_to_id: null
                  component_lines: []
                  output_lines: []
                  operations: []
                  events: []
                  created_at: '2026-05-28T09:00:00.000000Z'
                  updated_at: '2026-05-28T09:00:00.000000Z'
                  archived_at: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: manufacturing:read
      operationId: get-api-manufacturing-manufacturing-orders-id
    put:
      tags:
      - Manufacturing Orders
      summary: Update Manufacturing Order
      description: 'Update Manufacturing Order


        :::info[Required scope: `manufacturing:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        `warehouse_id`, `destination_warehouse_id` and `planned_quantity` are only
        applied while the order is Draft — from Confirmed onward component requirements
        and allocations are already sized to them, so the values are pinned.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                planned_quantity:
                  type: integer
                priority:
                  type: integer
                notes:
                  type: string
              example:
                planned_quantity: 120
                priority: 20
                notes: Increased to cover backorders
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: manufacturing:write
      operationId: put-api-manufacturing-manufacturing-orders-id
    delete:
      tags:
      - Manufacturing Orders
      summary: Delete Manufacturing Order
      description: 'Only draft MOs may be deleted.


        :::info[Required scope: `manufacturing:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: manufacturing:write
      operationId: delete-api-manufacturing-manufacturing-orders-id
  /api/manufacturing/manufacturing-orders/{id}/confirm:
    post:
      tags:
      - Manufacturing Orders
      summary: Confirm Manufacturing Order
      description: 'Draft -> Confirmed. Reserves components. Optionally lock in FIFO
        layer picks keyed by mo_component_line_id.


        :::info[Required scope: `manufacturing:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                priority:
                  type: integer
                scheduled_start:
                  type: string
                scheduled_end:
                  type: string
                lot_picks:
                  type: object
                  properties:
                    '1':
                      type: array
                      items:
                        type: integer
              example:
                priority: 10
                scheduled_start: '2026-04-22'
                scheduled_end: '2026-04-24'
                lot_picks:
                  '1':
                  - 101
                  - 102
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: manufacturing:write
      operationId: post-api-manufacturing-manufacturing-orders-id-confirm
  /api/manufacturing/manufacturing-orders/{manufacturingOrder}/confirm-preview:
    get:
      tags:
      - Manufacturing Orders
      summary: Preview Manufacturing Order Confirmation
      description: 'Dry run of Confirm for a Draft manufacturing order. Computes per-component
        shortages and the largest planned quantity current inventory could support
        end-to-end, without changing any state. For orders that are no longer Draft,
        the response contains empty shortages and a reason explaining that the preview
        only applies before confirmation.

        Auth: requires Bearer token.

        Path param: manufacturingOrder = manufacturing order id.


        :::info[Required scope: `manufacturing:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: manufacturingOrder
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The manufacturing order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  shortages:
                    type: array
                    items:
                      type: object
                      properties:
                        product_id:
                          type: integer
                        product_sku:
                          type: string
                        product_name:
                          type: string
                        required_quantity:
                          type: integer
                        allocated_quantity:
                          type: integer
                        short_by_quantity:
                          type: integer
                        uom_code:
                          type: string
                  max_producible_quantity:
                    type: integer
                  requested_quantity:
                    type: integer
                example:
                  shortages:
                  - product_id: 2
                    product_sku: CMP-001
                    product_name: Widget Frame
                    required_quantity: 250
                    allocated_quantity: 180
                    short_by_quantity: 70
                    uom_code: EA
                  max_producible_quantity: 72
                  requested_quantity: 100
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: manufacturing:read
      operationId: get-api-manufacturing-manufacturing-orders-manufacturingorder-confirm-preview
  /api/manufacturing/manufacturing-orders/{manufacturingOrder}/unconfirm:
    post:
      tags:
      - Manufacturing Orders
      summary: Unconfirm Manufacturing Order
      description: 'Reverse a Confirm: moves the order from Confirmed back to Draft,
        releases its component inventory allocations, and discards the BOM-derived
        component lines, output lines, and operations. Operations added manually after
        confirmation are kept.

        Auth: requires Bearer token.

        Path param: manufacturingOrder = manufacturing order id.

        Body: reason (optional, string, max 1000) recorded on the order''s event log.


        :::info[Required scope: `manufacturing:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                reason:
                  type: string
              example:
                reason: Confirmed against the wrong warehouse
      parameters:
      - name: manufacturingOrder
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The manufacturing order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: integer
                  mo_number:
                    type: string
                  status:
                    type: string
                  bom_id:
                    type: integer
                  warehouse_id:
                    type: integer
                  destination_warehouse_id:
                    type: integer
                  planned_quantity:
                    type: integer
                  completed_quantity:
                    type: integer
                  production_method:
                    type: string
                  contractor_supplier_id:
                    type: string
                    nullable: true
                  outsourced_purchase_order_id:
                    type: string
                    nullable: true
                  sales_order_id:
                    type: string
                    nullable: true
                  sales_order_line_id:
                    type: string
                    nullable: true
                  priority:
                    type: integer
                  scheduled_start:
                    type: string
                    nullable: true
                  scheduled_end:
                    type: string
                    nullable: true
                  started_at:
                    type: string
                    nullable: true
                  completed_at:
                    type: string
                    nullable: true
                  closed_at:
                    type: string
                    nullable: true
                  cancelled_at:
                    type: string
                    nullable: true
                  cancelled_reason_code:
                    type: string
                    nullable: true
                  cancelled_reason_notes:
                    type: string
                    nullable: true
                  is_simple_mode:
                    type: boolean
                  is_disassemble:
                    type: boolean
                  notes:
                    type: string
                    nullable: true
                  internal_reference:
                    type: string
                    nullable: true
                  cost_breakdown:
                    type: string
                    nullable: true
                  created_by_id:
                    type: integer
                  assigned_to_id:
                    type: string
                    nullable: true
                  created_at:
                    type: string
                  updated_at:
                    type: string
                  archived_at:
                    type: string
                    nullable: true
                example:
                  id: 42
                  mo_number: MO-00042
                  status: draft
                  bom_id: 15
                  warehouse_id: 3
                  destination_warehouse_id: 3
                  planned_quantity: 100
                  completed_quantity: 0
                  production_method: in_house
                  contractor_supplier_id: null
                  outsourced_purchase_order_id: null
                  sales_order_id: null
                  sales_order_line_id: null
                  priority: 0
                  scheduled_start: null
                  scheduled_end: null
                  started_at: null
                  completed_at: null
                  closed_at: null
                  cancelled_at: null
                  cancelled_reason_code: null
                  cancelled_reason_notes: null
                  is_simple_mode: false
                  is_disassemble: false
                  notes: null
                  internal_reference: null
                  cost_breakdown: null
                  created_by_id: 1
                  assigned_to_id: null
                  created_at: '2026-06-28T10:15:00.000000Z'
                  updated_at: '2026-07-01T14:22:09.000000Z'
                  archived_at: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: manufacturing:write
      operationId: post-api-manufacturing-manufacturing-orders-manufacturingorder-unconfirm
  /api/manufacturing/manufacturing-orders/{id}/start:
    post:
      tags:
      - Manufacturing Orders
      summary: Start Manufacturing Order
      description: 'Confirmed -> In Progress.


        :::info[Required scope: `manufacturing:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                started_at:
                  type: string
                assigned_to_id:
                  type: integer
                notes:
                  type: string
              example:
                started_at: '2026-04-22T08:00:00Z'
                assigned_to_id: 1
                notes: Production run kicked off
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: manufacturing:write
      operationId: post-api-manufacturing-manufacturing-orders-id-start
  /api/manufacturing/manufacturing-orders/{id}/record-production:
    post:
      tags:
      - Manufacturing Orders
      summary: Record Production
      description: 'Record actual component consumption, output produced, and operation
        actuals for an in-progress MO. Posts inventory movements (consumption + receipts)
        and creates FIFO layers for outputs.


        :::info[Required scope: `manufacturing:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        **Lot tracking validation (B23/B24):**

        - `outputs[].batch_number` is **required** when the output product is `is_lot_tracked
        = true`.

        - `outputs[].expiry_date` is **required** when the output product has `lot_tracking_method
        = fefo`.

        - Validation errors are returned per-output with dot notation, e.g. `outputs.0.batch_number`.


        The MO Show endpoint (`GET /api/manufacturing/manufacturing-orders/{id}`)
        exposes `output_lines[].product` and `component_lines[].product` with `is_lot_tracked`,
        `lot_tracking_method`, `shelf_life_days`, `near_expiry_threshold_days`, and
        `min_remaining_shelf_life_days` so clients can drive UI gating before submitting.


        **Component lot consumption override (FEFO suggest-with-override):**

        - Each `components[]` entry may carry an optional `lot_allocation[]` of `{fifo_layer_id,
        quantity}` to choose exactly which lots of a lot-tracked component are consumed.
        Omit it to consume by automatic FEFO/FIFO.

        - The allocation must reconcile to that component''s total draw this run (`actual_consumed_quantity
        + actual_scrap_quantity`), reference active FIFO layers of that component
        product + the MO''s source warehouse, and respect the tenant''s lot-override
        policy (under `enforce`, consuming expired stock or a later-expiry lot for
        a FEFO product is hard-blocked).

        - The legacy `components[].fifo_layer_ids[]` (restrict-eligibility, FEFO-ordered)
        is still accepted; `lot_allocation[]` takes precedence when both are present.

        - Validation errors are returned per row with dot notation, e.g. `components.0.lot_allocation.1.fifo_layer_id`.


        **Over-consumption guard (BQ8):** if `components[].actual_consumed_quantity`
        exceeds the quantity reserved (Allocated) for that component line at Start,
        the call returns **422** with `code = over_consumption` and an `offending[]`
        array (per-component `requested_quantity` vs `allocated_quantity`) instead
        of a 500. The whole call rolls back — MO status and consumption are unchanged.


        Destination bin: each output may optionally set `warehouse_location_id` —
        the bin the produced quantity is received into. When omitted, the assembly''s
        preferred bin (or the warehouse''s default storage location) is used.


        **Request `components` (present, may be empty):** the `components` array must
        always be present, but it no longer needs at least one entry. Only `forward_flush`
        component lines need entries — omit `backflush` lines entirely (they are consumed
        automatically, prorated to the recorded output), and submit `"components":
        []` when every component line on the order is backflush. Including an entry
        for a backflush line acts as a manual override of the automatic quantity for
        that run.


        **Backflush components:** component lines with `consumption_method = backflush`
        are consumed automatically — for each backflush line without an explicit `components[]`
        entry, the recorded output is converted to that line''s BOM-implied usage
        (per-unit usage multiplied by cumulative primary output produced — deliberately
        uncapped, so over-yield beyond the planned quantity consumes proportionally
        more — minus what earlier production records already consumed) and issued
        through the same FIFO/lot machinery as operator entries. Consumption beyond
        the quantity reserved at confirmation automatically tops up the line''s allocation
        from free (unreserved) stock; when free stock cannot cover the excess the
        request fails with the same structured 422s as a manual over-issue (`code
        = insufficient_inventory` when the stock physically does not exist, `code
        = over_consumption` when it exists but is reserved by other documents) and
        the whole call rolls back. Submitting an explicit `components[]` entry for
        a backflush line overrides the automatic quantity for that run. `forward_flush`
        lines are only consumed when an explicit entry is submitted.


        **Response `cost_breakdown`:** the returned manufacturing order carries a
        cumulative `cost_breakdown` object: `materials` (FIFO value consumed so far),
        `labor` (time-based operation labour), `overhead` (labour multiplied by the
        work-center overhead percent), `fixed` (flat per-run operation costs — never
        marked up by overhead), `service_fee` and `landed_cost` (outsourced orders
        only), `total`, `allocation_method`, `recorded_at`, and per-output allocation
        rows in `outputs[]`.


        **Operation costing without a timer:** each `operations[]` row in the response
        reports `fixed_cost`, `actual_cost`, and `cost_source` — `none` (no cost recorded),
        `actual` (from logged time or a flat fixed-cost operation), `estimated` (fell
        back to the planned duration because no time was logged), or `manual` (an
        explicitly supplied cost that is never auto-recalculated — only another explicit
        cost, or an explicitly logged positive time, replaces it).


        **Insufficient stock guard:** if a component''s FIFO layers in the MO''s source
        warehouse cannot cover the quantity to consume (forward-flush or backflush),
        the call returns **422** with `code = insufficient_inventory` and an `offending[]`
        array (`product_id`, `product_sku`, `product_name`, `warehouse_id`, `requested_quantity`,
        `available_quantity`). The whole call rolls back — no movements, FIFO layers,
        or production iterations are written.


        **Explicit lot allocation shortages:** shortage failures inside an explicit
        `lot_allocation[]` return the same **422** `code = insufficient_inventory`
        envelope (previously an internal error). A named lot that is no longer an
        active layer for the component at consumption time, or a lot that cannot cover
        its requested quantity, reports the usual `product_id`, `product_sku`, `product_name`,
        `warehouse_id`, `requested_quantity`, `available_quantity` row. A lot-level
        overdraw detected mid-consumption (e.g. duplicate entries naming the same
        lot whose combined quantity exceeds its availability) identifies the lot with
        `fifo_layer_id` and reports the layer''s real state at the failed draw — `layer_original_quantity`,
        `layer_fulfilled_quantity` (includes quantities drawn earlier in the same
        rolled-back call), and `layer_remaining_quantity` — rather than a fabricated
        requested/available pair. The whole call rolls back.


        **Downward cost revision guard:** operation cost revisions between production
        records are recognized as SIGNED deltas on the next iteration''s journal —
        negative buckets post as balanced flipped legs (e.g. a debit to Direct Labor
        Applied) and a net-zero reclassification still posts its offsetting legs.
        When a negative conversion delta exceeds the value this run''s output FIFO
        layers can absorb (a layer''s cost would drop below zero), the call returns
        **422** with `code = cost_revision_exceeds_layer_value`, the signed `conversion_delta`,
        and an `offending[]` array (`output_line_id`, `fifo_layer_id`, `product_id`,
        `product_sku`, `product_name`, `layer_cost`, `revision_share`, `resulting_cost`).
        The whole call rolls back — reverse the over-costed earlier iteration and
        re-record it with the corrected operation costs.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                completed_quantity:
                  type: integer
                production_date:
                  type: string
                notes:
                  type: string
                components:
                  type: array
                  items:
                    type: object
                    properties:
                      mo_component_line_id:
                        type: integer
                      actual_consumed_quantity:
                        type: integer
                      actual_scrap_quantity:
                        type: integer
                      lot_allocation:
                        type: array
                        items:
                          type: object
                          properties:
                            fifo_layer_id:
                              type: integer
                            quantity:
                              type: integer
                      scrap_reason_code:
                        type: string
                outputs:
                  type: array
                  items:
                    type: object
                    properties:
                      mo_output_line_id:
                        type: integer
                      actual_produced_quantity:
                        type: integer
                      batch_number:
                        type: string
                      expiry_date:
                        type: string
                      catch_weight:
                        type: string
                        nullable: true
                      warehouse_location_id:
                        type: integer
                operation_actuals:
                  type: array
                  items:
                    type: object
                    properties:
                      mo_operation_id:
                        type: integer
                      actual_time_minutes:
                        type: integer
                      operator_id:
                        type: integer
                      status:
                        type: string
                      notes:
                        type: string
              example:
                completed_quantity: 100
                production_date: '2026-04-23'
                notes: Full run completed
                components:
                - mo_component_line_id: 1
                  actual_consumed_quantity: 200
                  actual_scrap_quantity: 4
                  lot_allocation:
                  - fifo_layer_id: 101
                    quantity: 150
                  - fifo_layer_id: 102
                    quantity: 54
                  scrap_reason_code: spillage
                - mo_component_line_id: 2
                  actual_consumed_quantity: 100
                  actual_scrap_quantity: 0
                outputs:
                - mo_output_line_id: 1
                  actual_produced_quantity: 100
                  batch_number: LOT-2026-04-001
                  expiry_date: '2027-04-23'
                  catch_weight: null
                  warehouse_location_id: 15
                operation_actuals:
                - mo_operation_id: 1
                  actual_time_minutes: 35
                  operator_id: 1
                  status: completed
                  notes: Ran 5 minutes over
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: integer
                  mo_number:
                    type: string
                  status:
                    type: string
                  bom_id:
                    type: integer
                  warehouse_id:
                    type: integer
                  destination_warehouse_id:
                    type: integer
                  planned_quantity:
                    type: integer
                  completed_quantity:
                    type: integer
                  production_method:
                    type: string
                  contractor_supplier_id:
                    type: string
                    nullable: true
                  outsourced_purchase_order_id:
                    type: string
                    nullable: true
                  sales_order_id:
                    type: string
                    nullable: true
                  sales_order_line_id:
                    type: string
                    nullable: true
                  priority:
                    type: integer
                  scheduled_start:
                    type: string
                  scheduled_end:
                    type: string
                  started_at:
                    type: string
                  completed_at:
                    type: string
                    nullable: true
                  closed_at:
                    type: string
                    nullable: true
                  cancelled_at:
                    type: string
                    nullable: true
                  cancelled_reason_code:
                    type: string
                    nullable: true
                  cancelled_reason_notes:
                    type: string
                    nullable: true
                  is_simple_mode:
                    type: boolean
                  is_disassemble:
                    type: boolean
                  notes:
                    type: string
                  internal_reference:
                    type: string
                    nullable: true
                  cost_breakdown:
                    type: object
                    properties:
                      materials:
                        type: number
                      labor:
                        type: number
                      overhead:
                        type: number
                      fixed:
                        type: integer
                      service_fee:
                        type: integer
                      landed_cost:
                        type: integer
                      total:
                        type: number
                      allocation_method:
                        type: string
                      outputs:
                        type: array
                        items:
                          type: object
                          properties:
                            mo_output_line_id:
                              type: integer
                            product_id:
                              type: integer
                            role:
                              type: string
                            produced_quantity:
                              type: integer
                            allocated_cost:
                              type: number
                            allocated_this_step:
                              type: number
                            unit_cost:
                              type: number
                      recorded_at:
                        type: string
                  created_by_id:
                    type: integer
                  assigned_to_id:
                    type: string
                    nullable: true
                  component_lines:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        manufacturing_order_id:
                          type: integer
                        bom_component_line_id:
                          type: integer
                        product_id:
                          type: integer
                        product_variant_id:
                          type: string
                          nullable: true
                        expected_quantity:
                          type: integer
                        actual_consumed_quantity:
                          type: integer
                        expected_scrap_quantity:
                          type: integer
                        actual_scrap_quantity:
                          type: integer
                        scrap_reason_code:
                          type: string
                        uom_id:
                          type: integer
                        consumption_method:
                          type: string
                        consumption_posted_at:
                          type: string
                        estimated_cost:
                          type: integer
                  output_lines:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        manufacturing_order_id:
                          type: integer
                        bom_output_line_id:
                          type: integer
                        product_id:
                          type: integer
                        product_variant_id:
                          type: string
                          nullable: true
                        role:
                          type: string
                        expected_quantity:
                          type: integer
                        actual_produced_quantity:
                          type: integer
                        uom_id:
                          type: integer
                        allocated_cost:
                          type: number
                        batch_number:
                          type: string
                        expiry_date:
                          type: string
                  operations:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        manufacturing_order_id:
                          type: integer
                        source:
                          type: string
                        bom_operation_id:
                          type: integer
                        sequence:
                          type: integer
                        name:
                          type: string
                        type:
                          type: string
                        operation_type:
                          type: string
                        expected_duration_minutes:
                          type: integer
                        hourly_rate:
                          type: integer
                        status:
                          type: string
                        scheduled_start:
                          type: string
                          nullable: true
                        started_at:
                          type: string
                          nullable: true
                        completed_at:
                          type: string
                        actual_time_minutes:
                          type: integer
                        operator_id:
                          type: integer
                        default_operator_id:
                          type: string
                          nullable: true
                        work_center_id:
                          type: integer
                        fixed_cost:
                          type: integer
                        actual_cost:
                          type: number
                        cost_source:
                          type: string
                        notes:
                          type: string
                        is_modified_from_bom:
                          type: boolean
                  events:
                    type: array
                  created_at:
                    type: string
                  updated_at:
                    type: string
                  archived_at:
                    type: string
                    nullable: true
                example:
                  id: 14
                  mo_number: MO-000014
                  status: in_progress
                  bom_id: 12
                  warehouse_id: 1
                  destination_warehouse_id: 1
                  planned_quantity: 100
                  completed_quantity: 100
                  production_method: in_house
                  contractor_supplier_id: null
                  outsourced_purchase_order_id: null
                  sales_order_id: null
                  sales_order_line_id: null
                  priority: 0
                  scheduled_start: '2026-04-22T08:00:00.000000Z'
                  scheduled_end: '2026-04-24T17:00:00.000000Z'
                  started_at: '2026-04-22T08:05:00.000000Z'
                  completed_at: null
                  closed_at: null
                  cancelled_at: null
                  cancelled_reason_code: null
                  cancelled_reason_notes: null
                  is_simple_mode: false
                  is_disassemble: false
                  notes: Full run completed
                  internal_reference: null
                  cost_breakdown:
                    materials: 1240.5
                    labor: 26.25
                    overhead: 2.625
                    fixed: 75
                    service_fee: 0
                    landed_cost: 0
                    total: 1344.375
                    allocation_method: by_value
                    outputs:
                    - mo_output_line_id: 1
                      product_id: 1
                      role: primary
                      produced_quantity: 100
                      allocated_cost: 1344.375
                      allocated_this_step: 1344.375
                      unit_cost: 13.44375
                    recorded_at: '2026-04-23T14:12:09+00:00'
                  created_by_id: 1
                  assigned_to_id: null
                  component_lines:
                  - id: 1
                    manufacturing_order_id: 14
                    bom_component_line_id: 31
                    product_id: 2
                    product_variant_id: null
                    expected_quantity: 200
                    actual_consumed_quantity: 200
                    expected_scrap_quantity: 4
                    actual_scrap_quantity: 4
                    scrap_reason_code: spillage
                    uom_id: 1
                    consumption_method: forward_flush
                    consumption_posted_at: '2026-04-23T14:12:09.000000Z'
                    estimated_cost: 100
                  - id: 2
                    manufacturing_order_id: 14
                    bom_component_line_id: 32
                    product_id: 3
                    product_variant_id: null
                    expected_quantity: 100
                    actual_consumed_quantity: 100
                    expected_scrap_quantity: 0
                    actual_scrap_quantity: 0
                    scrap_reason_code: null
                    uom_id: 1
                    consumption_method: backflush
                    consumption_posted_at: '2026-04-23T14:12:09.000000Z'
                    estimated_cost: 100
                  output_lines:
                  - id: 1
                    manufacturing_order_id: 14
                    bom_output_line_id: 21
                    product_id: 1
                    product_variant_id: null
                    role: primary
                    expected_quantity: 100
                    actual_produced_quantity: 100
                    uom_id: 1
                    allocated_cost: 1344.375
                    batch_number: LOT-2026-04-001
                    expiry_date: '2027-04-23'
                  operations:
                  - id: 1
                    manufacturing_order_id: 14
                    source: from_bom
                    bom_operation_id: 7
                    sequence: 10
                    name: Mix
                    type: setup
                    operation_type: setup
                    expected_duration_minutes: 30
                    hourly_rate: 45
                    status: completed
                    scheduled_start: null
                    started_at: null
                    completed_at: '2026-04-23T14:12:09.000000Z'
                    actual_time_minutes: 35
                    operator_id: 1
                    default_operator_id: null
                    work_center_id: 1
                    fixed_cost: 75
                    actual_cost: 101.25
                    cost_source: actual
                    notes: Ran 5 minutes over
                    is_modified_from_bom: false
                  events: []
                  created_at: '2026-04-20T09:00:00.000000Z'
                  updated_at: '2026-04-23T14:12:09.000000Z'
                  archived_at: null
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 422 Missing batch_number on lot-tracked output
                  value:
                    message: 'Batch number is required for lot-tracked product ''Coffee
                      250g Pouch'' (SKU: QA-COFFEE-250).'
                    errors:
                      outputs.0.batch_number:
                      - 'Batch number is required for lot-tracked product ''Coffee
                        250g Pouch'' (SKU: QA-COFFEE-250).'
                example-1:
                  summary: 422 — Cost Allocation Zero Weight
                  value:
                    error: 'MO-000001 cannot record production: cost allocation method
                      is "by weight" but no output product has a non-zero weight.
                      Set a weight on each output product (Products → Edit → Weight)
                      or switch the BOM to a different cost allocation method.'
                    message: 'MO-000001 cannot record production: cost allocation
                      method is "by weight" but no output product has a non-zero weight.
                      Set a weight on each output product (Products → Edit → Weight)
                      or switch the BOM to a different cost allocation method.'
                    code: cost_allocation_zero_weight
                    allocation_method: by_weight
                    total_input_cost: 35.81
                    offending:
                    - output_line_id: 1
                      product_id: 4
                      product_sku: QA-COFFEE-250
                      product_name: Coffee 250g Pouch
                      produced_quantity: 10
                      weight: 0
                      manual_cost_percent: null
                example-2:
                  summary: 422 — Downward Cost Revision Exceeds Layer Value
                  value:
                    error: 'MO-000001 cannot record production: this run recognizes
                      a downward cost revision of 50.00, which exceeds the value its
                      produced output can absorb. Reverse the affected earlier production
                      iteration(s) and re-record them with the corrected operation
                      costs instead.'
                    message: 'MO-000001 cannot record production: this run recognizes
                      a downward cost revision of 50.00, which exceeds the value its
                      produced output can absorb. Reverse the affected earlier production
                      iteration(s) and re-record them with the corrected operation
                      costs instead.'
                    code: cost_revision_exceeds_layer_value
                    conversion_delta: -50
                    offending:
                    - output_line_id: 1
                      fifo_layer_id: 42
                      product_id: 9
                      product_sku: QA-ROAST
                      product_name: Roasted Coffee Beans
                      layer_cost: 20
                      revision_share: -50
                      resulting_cost: -30
                example-3:
                  summary: 422 — Over-Consumption (exceeds allocated)
                  value:
                    error: 'MO-000001: cannot consume 10 EACH of QA-BEAN (Coffee Beans)
                      — only 6 EACH is reserved for this manufacturing order. Reduce
                      the consumed quantity to 6 EACH or less, or allocate more stock
                      to the order before recording production.'
                    message: 'MO-000001: cannot consume 10 EACH of QA-BEAN (Coffee
                      Beans) — only 6 EACH is reserved for this manufacturing order.
                      Reduce the consumed quantity to 6 EACH or less, or allocate
                      more stock to the order before recording production.'
                    code: over_consumption
                    offending:
                    - component_line_id: 1
                      product_id: 7
                      product_sku: QA-BEAN
                      product_name: Coffee Beans
                      uom_code: EACH
                      requested_quantity: 10
                      allocated_quantity: 6
                example-4:
                  summary: 422 — Insufficient Component Inventory
                  value:
                    error: 'Insufficient FIFO inventory for WIDGET-RAW (Raw Widget)
                      in warehouse 3: 30 required, only 4 available. Receive or transfer
                      more stock before recording production.'
                    message: 'Insufficient FIFO inventory for WIDGET-RAW (Raw Widget)
                      in warehouse 3: 30 required, only 4 available. Receive or transfer
                      more stock before recording production.'
                    code: insufficient_inventory
                    offending:
                    - product_id: 88
                      product_sku: WIDGET-RAW
                      product_name: Raw Widget
                      warehouse_id: 3
                      requested_quantity: 30
                      available_quantity: 4
                example-5:
                  summary: 422 — Lot Overdraw (Duplicate Allocation Entries)
                  value:
                    error: 'updateFulfilledQuantity would oversubscribe FifoLayer
                      412: 6+6=12 > original 10'
                    message: 'updateFulfilledQuantity would oversubscribe FifoLayer
                      412: 6+6=12 > original 10'
                    code: insufficient_inventory
                    offending:
                    - fifo_layer_id: 412
                      product_id: 88
                      product_sku: WIDGET-RAW
                      product_name: Raw Widget
                      warehouse_id: 3
                      layer_original_quantity: 10
                      layer_fulfilled_quantity: 6
                      layer_remaining_quantity: 4
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: manufacturing:write
      operationId: post-api-manufacturing-manufacturing-orders-id-record-production
  /api/manufacturing/manufacturing-orders/{id}/complete:
    post:
      tags:
      - Manufacturing Orders
      summary: Complete Manufacturing Order
      description: 'In Progress -> Completed. Finalizes variance calculations.


        :::info[Required scope: `manufacturing:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties: {}
              example: {}
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: manufacturing:write
      operationId: post-api-manufacturing-manufacturing-orders-id-complete
  /api/manufacturing/manufacturing-orders/{id}/cancel:
    post:
      tags:
      - Manufacturing Orders
      summary: Cancel Manufacturing Order
      description: "Cancel a manufacturing order. Transitions any non-closed status\
        \ → Cancelled and releases any inventory reservations.\n\n**Required body\
        \ fields:**\n- `reason_code` (string, required) — must be one of the 5 allowed\
        \ values:\n  - `plan_changed` — Plan changed\n  - `materials_unavailable`\
        \ — Materials unavailable\n  - `customer_cancellation` — Customer cancellation\n\
        \  - `equipment_issue` — Equipment issue\n  - `other` — Other\n\n**Optional\
        \ body fields:**\n- `notes` (string, nullable, max 2000) — Free-text reason\
        \ explanation\n- `reason_notes` (string, nullable, max 2000) — **Alias for\
        \ `notes`** — accepted for API consistency. If `notes` is absent and `reason_notes`\
        \ is provided, it is copied into `notes` during validation. Sending both means\
        \ `notes` wins.\n\n**Returns 422 if `reason_code` is missing or not in the\
        \ allowed list.**\n**Authentication:** Bearer token required.\n\n:::info[Required\
        \ scope: `manufacturing:write`]\nGrant this scope to your token under [Settings\
        \ → Developer → Personal Access Tokens](https://app.sku.io/settings/api).\n\
        :::"
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                reason_code:
                  type: string
                notes:
                  type: string
              example:
                reason_code: customer_cancellation
                notes: Sales order cancelled upstream
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: integer
                  manufacturing_order_number:
                    type: string
                  status:
                    type: string
                  bom_id:
                    type: integer
                  warehouse_id:
                    type: integer
                  quantity_planned:
                    type: string
                  quantity_produced:
                    type: string
                  scheduled_start:
                    type: string
                  scheduled_end:
                    type: string
                  started_at:
                    type: string
                    nullable: true
                  completed_at:
                    type: string
                    nullable: true
                  closed_at:
                    type: string
                  notes:
                    type: string
                    nullable: true
                  created_at:
                    type: string
                  updated_at:
                    type: string
                example:
                  id: 1
                  manufacturing_order_number: MO-000001
                  status: cancelled
                  bom_id: 12
                  warehouse_id: 3
                  quantity_planned: '10.000000'
                  quantity_produced: '0.000000'
                  scheduled_start: '2026-06-01T00:00:00.000000Z'
                  scheduled_end: '2026-06-03T00:00:00.000000Z'
                  started_at: null
                  completed_at: null
                  closed_at: '2026-05-28T14:32:11.000000Z'
                  notes: null
                  created_at: '2026-05-25T09:00:00.000000Z'
                  updated_at: '2026-05-28T14:32:11.000000Z'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      reason_code:
                        type: array
                        items:
                          type: string
                example:
                  message: 'The selected reason is not valid. Allowed values: plan_changed,
                    materials_unavailable, customer_cancellation, equipment_issue,
                    other. (and 1 more error)'
                  errors:
                    reason_code:
                    - 'The selected reason is not valid. Allowed values: plan_changed,
                      materials_unavailable, customer_cancellation, equipment_issue,
                      other.'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: manufacturing:write
      operationId: post-api-manufacturing-manufacturing-orders-id-cancel
  /api/manufacturing/manufacturing-orders/{id}/close:
    post:
      tags:
      - Manufacturing Orders
      summary: Close Manufacturing Order
      description: 'Completed -> Closed. Locks the MO from further changes.


        :::info[Required scope: `manufacturing:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                notes:
                  type: string
              example:
                notes: Costing locked
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: manufacturing:write
      operationId: post-api-manufacturing-manufacturing-orders-id-close
  /api/manufacturing/manufacturing-orders/{id}/reopen:
    post:
      tags:
      - Manufacturing Orders
      summary: Reopen Manufacturing Order
      description: 'Closed -> Partially Completed (or Completed if completed_quantity
        >= planned_quantity). Required reason (string, max 2000) is captured in the
        Reopened event payload.


        :::info[Required scope: `manufacturing:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                reason:
                  type: string
              example:
                reason: Correcting component consumption
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: manufacturing:write
      operationId: post-api-manufacturing-manufacturing-orders-id-reopen
  /api/manufacturing/manufacturing-orders/{id}/generate-accounting-transaction:
    post:
      tags:
      - Manufacturing Orders
      summary: Generate Accounting Transaction (MO)
      description: 'Generate (or rebuild) the WIP-routed GL journals for this MO —
        ONE journal per production iteration, each dated to that iteration''s production
        date (so multi-day / multi-period production is period-accurate). Conversion
        costs (labor + overhead + outsourced service) are capitalized into finished
        goods through Work In Process:


        :::info[Required scope: `manufacturing:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        - Dr Work In Process (total)

        - Cr Raw Materials Inventory (materials), Cr Direct Labor Applied (labor),
        Cr Manufacturing Overhead Applied (overhead), Cr Accrued Purchases (outsourced
        service fee)

        - Dr Finished Goods Inventory (total), Cr Work In Process (total)


        WIP nets to zero. Each journal links polymorphically to the MO and is tagged
        with its mo_production_iteration_id. Requires the Work In Process / Direct
        Labor Applied / Manufacturing Overhead Applied nominal codes to be mapped
        (Settings -> Nominal Code Mappings). No request body. Returns an ARRAY of
        accounting transaction object (one per iteration) with their journal lines.
        Each iteration''s journal is also posted automatically as production is recorded
        (when accounting is enabled), and removed if the iteration is reversed.'
      requestBody:
        content: {}
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 OK
                  value:
                    message: Production journals generated successfully.
                    data:
                    - id: 5012
                      display_status:
                        label: Synced
                        color: success
                      total: 37
                      reference: 'Production MO-000001 #1: QA-COFFEE-250'
                      transaction_date: '2026-06-05T00:00:00+00:00'
                      type: manufacturing_order
                example-1:
                  summary: 200 OK (ledger disabled)
                  value:
                    message: Ledger generation is disabled for this tenant.
                    data: []
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: manufacturing:write
      operationId: post-api-manufacturing-manufacturing-orders-id-generate-accounting-transaction
  /api/manufacturing/manufacturing-orders/{id}/events:
    get:
      tags:
      - Manufacturing Orders
      summary: MO Events (Audit Log)
      description: 'Returns audit log of every status transition and significant action
        on the MO.


        :::info[Required scope: `manufacturing:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: manufacturing:read
      operationId: get-api-manufacturing-manufacturing-orders-id-events
  /api/manufacturing/manufacturing-orders/{id}/inventory-movements:
    get:
      tags:
      - Manufacturing Orders
      summary: List MO Inventory Movements
      description: 'Paginated list of inventory movements created by this Manufacturing
        Order. Includes movements linked to the MO itself, to any of its component
        lines (consumption + scrap) and to any of its output lines (production output).


        :::info[Required scope: `manufacturing:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        **Query parameters:**

        - `per_page` — items per page (default: 15)

        - `filter[search]` — search by product SKU or name'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        type:
                          type: string
                        inventory_status:
                          type: string
                        quantity:
                          type: integer
                        reference:
                          type: string
                        link_type:
                          type: string
                        link_id:
                          type: integer
                        parent_link_id:
                          type: string
                          nullable: true
                        detail_link_id:
                          type: string
                          nullable: true
                        product_id:
                          type: integer
                        product_sku:
                          type: string
                        product_name:
                          type: string
                        warehouse_id:
                          type: integer
                        warehouse_name:
                          type: string
                        unit_cost:
                          type: number
                        layer:
                          type: object
                          properties:
                            fifo_layer_id:
                              type: integer
                            name:
                              type: string
                              nullable: true
                        fifo_layer_id:
                          type: integer
                        inventory_movement_date:
                          type: string
                        created_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - id: 4012
                    type: production_output
                    inventory_status: on_hand
                    quantity: 10
                    reference: MO-000014
                    link_type: App\Models\MoOutputLine
                    link_id: 88
                    parent_link_id: null
                    detail_link_id: null
                    product_id: 412
                    product_sku: KIT-A
                    product_name: Widget Kit
                    warehouse_id: 1
                    warehouse_name: Main Warehouse
                    unit_cost: 7.25
                    layer:
                      fifo_layer_id: 19
                      name: null
                    fifo_layer_id: 19
                    inventory_movement_date: '2026-04-15T09:30:00.000000Z'
                    created_at: '2026-04-15T09:30:00.000000Z'
                  current_page: 1
                  last_page: 1
                  per_page: 15
                  total: 1
                  from: 1
                  to: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: manufacturing:read
      operationId: get-api-manufacturing-manufacturing-orders-id-inventory-movements
  /api/manufacturing/manufacturing-orders/{id}/fifo-layers:
    get:
      tags:
      - Manufacturing Orders
      summary: List MO FIFO Layers
      description: 'Paginated list of FIFO layers CREATED by this Manufacturing Order
        (production output layers). Layers consumed by this MO are surfaced on each
        layer''s own detail view.


        :::info[Required scope: `manufacturing:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        **Query parameters:**

        - `per_page` — items per page (default: 15)

        - `filter[search]` — search by product SKU or name'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        product_id:
                          type: integer
                        warehouse_id:
                          type: integer
                        batch_number:
                          type: string
                        manufacture_date:
                          type: string
                        expiry_date:
                          type: string
                        original_quantity:
                          type: integer
                        fulfilled_quantity:
                          type: integer
                        quantity_on_hand:
                          type: integer
                        available_quantity:
                          type: integer
                        avg_cost:
                          type: number
                        total_cost:
                          type: number
                        fifo_layer_date:
                          type: string
                        created_at:
                          type: string
                        link_type:
                          type: string
                        link_id:
                          type: integer
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - id: 19
                    product_id: 412
                    warehouse_id: 1
                    batch_number: LOT-2026-04-001
                    manufacture_date: '2026-04-15'
                    expiry_date: '2027-04-15'
                    original_quantity: 50
                    fulfilled_quantity: 12
                    quantity_on_hand: 38
                    available_quantity: 38
                    avg_cost: 7.25
                    total_cost: 362.5
                    fifo_layer_date: '2026-04-15T00:00:00.000000Z'
                    created_at: '2026-04-15T09:30:00.000000Z'
                    link_type: App\Models\MoOutputLine
                    link_id: 88
                  current_page: 1
                  last_page: 1
                  per_page: 15
                  total: 1
                  from: 1
                  to: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: manufacturing:read
      operationId: get-api-manufacturing-manufacturing-orders-id-fifo-layers
  /api/manufacturing/mo-output-lines/{id}:
    get:
      tags:
      - Manufacturing Orders
      summary: Get Manufacturing Order Output Line
      description: 'Show a single Manufacturing Output line — the canonical detail
        view used by the standalone Manufacturing Output page.


        :::info[Required scope: `manufacturing:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Returns the output-line resource plus three derived blocks:

        - `fifo_layer` — the FIFO layer this output created (one per output, max)

        - `inventory_movement` — the single production-output movement created when
        the line posted

        - `layer_movements` — every movement that touched the FIFO layer this output
        produced: the production movement itself plus any downstream consumption (sales,
        transfers, further manufacturing). Drives the Movements tab.

        - `production_date` — top-level canonical date (movement''s `inventory_movement_date`
        when available, else MO `completed_at`)'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      manufacturing_order_id:
                        type: integer
                      bom_output_line_id:
                        type: integer
                      product_id:
                        type: integer
                      role:
                        type: string
                      expected_quantity:
                        type: integer
                      actual_produced_quantity:
                        type: integer
                      allocated_cost:
                        type: number
                      batch_number:
                        type: string
                      expiry_date:
                        type: string
                      manufacturing_order:
                        type: object
                        properties:
                          id:
                            type: integer
                          mo_number:
                            type: string
                          status:
                            type: string
                      product:
                        type: object
                        properties:
                          id:
                            type: integer
                          sku:
                            type: string
                          name:
                            type: string
                      unit_of_measure:
                        type: object
                        properties:
                          id:
                            type: integer
                          code:
                            type: string
                          name:
                            type: string
                      fifo_layer:
                        type: object
                        properties:
                          id:
                            type: integer
                          original_quantity:
                            type: integer
                          available_quantity:
                            type: integer
                          fulfilled_quantity:
                            type: integer
                          avg_cost:
                            type: number
                          total_cost:
                            type: number
                          fifo_layer_date:
                            type: string
                          created_at:
                            type: string
                      inventory_movement:
                        type: object
                        properties:
                          id:
                            type: integer
                          type:
                            type: string
                          inventory_status:
                            type: string
                          quantity:
                            type: integer
                          inventory_movement_date:
                            type: string
                          created_at:
                            type: string
                      production_date:
                        type: string
                example:
                  data:
                    id: 88
                    manufacturing_order_id: 14
                    bom_output_line_id: 42
                    product_id: 412
                    role: primary
                    expected_quantity: 10
                    actual_produced_quantity: 10
                    allocated_cost: 72.5
                    batch_number: LOT-2026-04-001
                    expiry_date: '2027-04-15'
                    manufacturing_order:
                      id: 14
                      mo_number: MO-000014
                      status: completed
                    product:
                      id: 412
                      sku: KIT-A
                      name: Widget Kit
                    unit_of_measure:
                      id: 1
                      code: EA
                      name: Each
                    fifo_layer:
                      id: 19
                      original_quantity: 50
                      available_quantity: 38
                      fulfilled_quantity: 12
                      avg_cost: 7.25
                      total_cost: 362.5
                      fifo_layer_date: '2026-04-15T00:00:00.000000Z'
                      created_at: '2026-04-15T09:30:00.000000Z'
                    inventory_movement:
                      id: 4012
                      type: production_output
                      inventory_status: on_hand
                      quantity: 10
                      inventory_movement_date: '2026-04-15T09:30:00.000000Z'
                      created_at: '2026-04-15T09:30:00.000000Z'
                    production_date: '2026-04-15T09:30:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: manufacturing:read
      operationId: get-api-manufacturing-mo-output-lines-id
  /api/manufacturing/mo-component-lines/{id}:
    get:
      tags:
      - Manufacturing Orders
      summary: Get Manufacturing Order Component Line
      description: 'Show a single Manufacturing Consumption (component) line — the
        detail view used by the standalone Manufacturing Consumption page.


        :::info[Required scope: `manufacturing:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Returns the component-line resource plus:

        - `inventory_movements` — every movement attached to this consumption line
        (one consumption row per FIFO layer drawn, plus optionally one scrap row)

        - `layers_drawn` — denormalised summary of the FIFO layers consumed (with
        quantity taken, unit cost, layer date)

        - `consumption_date` — top-level canonical date (component `consumption_posted_at`,
        falling back to first movement date or MO `completed_at`)'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      manufacturing_order_id:
                        type: integer
                      bom_component_line_id:
                        type: integer
                      product_id:
                        type: integer
                      expected_quantity:
                        type: integer
                      expected_scrap_quantity:
                        type: integer
                      actual_consumed_quantity:
                        type: integer
                      actual_scrap_quantity:
                        type: integer
                      scrap_reason_code:
                        type: string
                        nullable: true
                      is_optional:
                        type: boolean
                      consumption_method:
                        type: string
                      consumption_posted_at:
                        type: string
                      estimated_cost:
                        type: integer
                      manufacturing_order:
                        type: object
                        properties:
                          id:
                            type: integer
                          mo_number:
                            type: string
                          status:
                            type: string
                      product:
                        type: object
                        properties:
                          id:
                            type: integer
                          sku:
                            type: string
                          name:
                            type: string
                      unit_of_measure:
                        type: object
                        properties:
                          id:
                            type: integer
                          code:
                            type: string
                          name:
                            type: string
                      consumption_date:
                        type: string
                      inventory_movements:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            type:
                              type: string
                            inventory_status:
                              type: string
                            quantity:
                              type: integer
                            fifo_layer_id:
                              type: integer
                            unit_cost:
                              type: integer
                            inventory_movement_date:
                              type: string
                      layers_drawn:
                        type: array
                        items:
                          type: object
                          properties:
                            fifo_layer_id:
                              type: integer
                            quantity_taken:
                              type: integer
                            unit_cost:
                              type: integer
                            fifo_layer_date:
                              type: string
                            movement_id:
                              type: integer
                            movement_type:
                              type: string
                example:
                  data:
                    id: 211
                    manufacturing_order_id: 14
                    bom_component_line_id: 305
                    product_id: 305
                    expected_quantity: 22
                    expected_scrap_quantity: 2
                    actual_consumed_quantity: 22
                    actual_scrap_quantity: 2
                    scrap_reason_code: null
                    is_optional: false
                    consumption_method: backflush
                    consumption_posted_at: '2026-04-15T09:30:00.000000Z'
                    estimated_cost: 100
                    manufacturing_order:
                      id: 14
                      mo_number: MO-000014
                      status: completed
                    product:
                      id: 305
                      sku: WIDGET-A
                      name: Widget Component A
                    unit_of_measure:
                      id: 1
                      code: EA
                      name: Each
                    consumption_date: '2026-04-15T09:30:00.000000Z'
                    inventory_movements:
                    - id: 4010
                      type: manufacturing_consumption
                      inventory_status: on_hand
                      quantity: -20
                      fifo_layer_id: 14
                      unit_cost: 3
                      inventory_movement_date: '2026-04-15T09:30:00.000000Z'
                    - id: 4011
                      type: manufacturing_scrap
                      inventory_status: on_hand
                      quantity: -2
                      fifo_layer_id: 14
                      unit_cost: 3
                      inventory_movement_date: '2026-04-15T09:30:00.000000Z'
                    layers_drawn:
                    - fifo_layer_id: 14
                      quantity_taken: 20
                      unit_cost: 3
                      fifo_layer_date: '2026-03-01T00:00:00.000000Z'
                      movement_id: 4010
                      movement_type: manufacturing_consumption
                    - fifo_layer_id: 14
                      quantity_taken: 2
                      unit_cost: 3
                      fifo_layer_date: '2026-03-01T00:00:00.000000Z'
                      movement_id: 4011
                      movement_type: manufacturing_scrap
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: manufacturing:read
      operationId: get-api-manufacturing-mo-component-lines-id
  /api/manufacturing/mo-output-lines/{id}/inventory-movements:
    get:
      tags:
      - Manufacturing Orders
      summary: List Output Line Inventory Movements
      description: 'Paginated inventory movements scoped to a single MO output line
        — every movement that touches the FIFO layer this output produced. Includes
        the production-output movement itself and any downstream consumption of the
        batch (sales, transfers, further manufacturing). Backs the Movements tab on
        the Manufacturing Output detail page.


        :::info[Required scope: `manufacturing:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        **Query parameters:**

        - `per_page` — items per page (default: 15)

        - `filter[search]` — search by product SKU or name'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        type:
                          type: string
                        inventory_status:
                          type: string
                        quantity:
                          type: integer
                        reference:
                          type: string
                          nullable: true
                        link_type:
                          type: string
                        link_id:
                          type: integer
                        parent_link_id:
                          type: string
                          nullable: true
                        detail_link_id:
                          type: string
                          nullable: true
                        product_id:
                          type: integer
                        product_sku:
                          type: string
                        product_name:
                          type: string
                        warehouse_id:
                          type: integer
                        warehouse_name:
                          type: string
                        unit_cost:
                          type: number
                        layer:
                          type: object
                          properties:
                            fifo_layer_id:
                              type: integer
                            name:
                              type: string
                              nullable: true
                        fifo_layer_id:
                          type: integer
                        inventory_movement_date:
                          type: string
                        created_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - id: 8
                    type: manufacturing_output
                    inventory_status: on_hand
                    quantity: 10
                    reference: null
                    link_type: App\Models\MoOutputLine
                    link_id: 1
                    parent_link_id: null
                    detail_link_id: null
                    product_id: 4
                    product_sku: QA-COFFEE-250
                    product_name: Coffee 250g Pouch
                    warehouse_id: 1
                    warehouse_name: Main Warehouse
                    unit_cost: 3.58
                    layer:
                      fifo_layer_id: 5
                      name: null
                    fifo_layer_id: 5
                    inventory_movement_date: '2026-06-02T20:36:22.000000Z'
                    created_at: '2026-06-02T20:36:22.000000Z'
                  current_page: 1
                  last_page: 1
                  per_page: 15
                  total: 1
                  from: 1
                  to: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: manufacturing:read
      operationId: get-api-manufacturing-mo-output-lines-id-inventory-movements
  /api/manufacturing/mo-output-lines/{id}/fifo-layers:
    get:
      tags:
      - Manufacturing Orders
      summary: List Output Line FIFO Layers
      description: 'Paginated FIFO layers scoped to a single MO output line. Always
        returns at most one row — the layer this output produced — but shapes the
        response as a paginated collection so the frontend can reuse the same list
        view contract as the MO-scoped equivalent.


        :::info[Required scope: `manufacturing:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        **Query parameters:**

        - `per_page` — items per page (default: 15)

        - `filter[search]` — search by product SKU or name'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        product_id:
                          type: integer
                        warehouse_id:
                          type: integer
                        batch_number:
                          type: string
                        manufacture_date:
                          type: string
                        expiry_date:
                          type: string
                          nullable: true
                        original_quantity:
                          type: integer
                        fulfilled_quantity:
                          type: integer
                        available_quantity:
                          type: integer
                        avg_cost:
                          type: number
                        total_cost:
                          type: number
                        fifo_layer_date:
                          type: string
                        created_at:
                          type: string
                        link_type:
                          type: string
                        link_id:
                          type: integer
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - id: 5
                    product_id: 4
                    warehouse_id: 1
                    batch_number: MO-000001-2026-06-02
                    manufacture_date: '2026-06-02'
                    expiry_date: null
                    original_quantity: 10
                    fulfilled_quantity: 0
                    available_quantity: 10
                    avg_cost: 3.58
                    total_cost: 35.81
                    fifo_layer_date: '2026-06-02T00:00:00.000000Z'
                    created_at: '2026-06-02T20:36:22.000000Z'
                    link_type: App\Models\MoOutputLine
                    link_id: 1
                  current_page: 1
                  last_page: 1
                  per_page: 15
                  total: 1
                  from: 1
                  to: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: manufacturing:read
      operationId: get-api-manufacturing-mo-output-lines-id-fifo-layers
  /api/manufacturing/manufacturing-orders/{id}/production-iterations:
    get:
      tags:
      - Manufacturing Orders
      summary: List MO Production Iterations
      description: 'Paginated list of production iterations for this Manufacturing
        Order. Each iteration is one call to Record Production; includes restore-cost
        information and a reversibility flag.


        :::info[Required scope: `manufacturing:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        **Query parameters:**

        - `per_page` — items per page (default: 15)

        - `sort` — sort field. Prefix with `-` for DESC. Allowed: id, iteration_number,
        production_date, output_quantity, total_input_cost, created_at. Default: `-iteration_number`

        - `filter[is_reversed]` — true/false

        - `filter[iteration_number]` — exact match

        - `filter[search]` — LIKE on iteration_number / reverse_reason

        - `filter[date_from]`, `filter[date_to]` — production_date range (Y-m-d)'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: string
                        manufacturing_order_id:
                          type: integer
                        iteration_number:
                          type: integer
                        created_by:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        production_date:
                          type: string
                        output_quantity:
                          type: integer
                        total_input_cost:
                          type: number
                        total_allocated_cost:
                          type: number
                        is_reversed:
                          type: boolean
                        reversed_at:
                          type: string
                          nullable: true
                        reversed_by:
                          type: string
                          nullable: true
                        reverse_reason:
                          type: string
                          nullable: true
                        reversible:
                          type: boolean
                        non_reversible_reason:
                          type: string
                          nullable: true
                        movement_count:
                          type: integer
                        output_fifo_layer_id:
                          type: integer
                        created_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - id: 0fa1c2bb-8b1b-4c5a-9d63-1f4b5e6d7c80
                    manufacturing_order_id: 1
                    iteration_number: 1
                    created_by:
                      id: 1
                      name: Kalvin Mizzi
                    production_date: '2026-06-02T20:36:22.000000Z'
                    output_quantity: 10
                    total_input_cost: 35.81
                    total_allocated_cost: 35.81
                    is_reversed: false
                    reversed_at: null
                    reversed_by: null
                    reverse_reason: null
                    reversible: true
                    non_reversible_reason: null
                    movement_count: 5
                    output_fifo_layer_id: 5
                    created_at: '2026-06-02T20:36:22.000000Z'
                  current_page: 1
                  last_page: 1
                  per_page: 15
                  total: 1
                  from: 1
                  to: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: manufacturing:read
      operationId: get-api-manufacturing-manufacturing-orders-id-production-iterations
  /api/manufacturing/production-iterations/{id}:
    get:
      tags:
      - Manufacturing Orders
      summary: Get Production Iteration
      description: 'Returns a single production iteration with all relations eagerly
        loaded (manufacturing order, created_by user, reversed_by user) plus the output
        FIFO layer expanded. Backs the standalone Production Iteration detail page.


        :::info[Required scope: `manufacturing:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        **Path parameters:**

        - `moProductionIteration` (string, UUID) — the iteration''s UUID primary key.
        Iteration IDs are globally unique so no MO scope is required.


        **Notes:**

        - `reversible` / `non_reversible_reason` reflect whether the iteration can
        still be reversed (e.g. blocked by downstream consumption of its output layer).

        - `output_fifo_layer` is the single FIFO layer this iteration produced (nullable
        for outsourced or partial iterations).'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: string
                      manufacturing_order_id:
                        type: integer
                      manufacturing_order:
                        type: object
                        properties:
                          id:
                            type: integer
                          mo_number:
                            type: string
                          status:
                            type: string
                      iteration_number:
                        type: integer
                      created_by:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      production_date:
                        type: string
                      output_quantity:
                        type: integer
                      total_input_cost:
                        type: number
                      total_allocated_cost:
                        type: number
                      is_reversed:
                        type: boolean
                      reversed_at:
                        type: string
                        nullable: true
                      reversed_by:
                        type: string
                        nullable: true
                      reverse_reason:
                        type: string
                        nullable: true
                      reversible:
                        type: boolean
                      non_reversible_reason:
                        type: string
                        nullable: true
                      movement_count:
                        type: integer
                      output_fifo_layer_id:
                        type: integer
                      output_fifo_layer:
                        type: object
                        properties:
                          id:
                            type: integer
                          original_quantity:
                            type: integer
                          available_quantity:
                            type: integer
                          fulfilled_quantity:
                            type: integer
                          avg_cost:
                            type: number
                          total_cost:
                            type: number
                          fifo_layer_date:
                            type: string
                          created_at:
                            type: string
                      created_at:
                        type: string
                example:
                  data:
                    id: 0fa1c2bb-8b1b-4c5a-9d63-1f4b5e6d7c80
                    manufacturing_order_id: 1
                    manufacturing_order:
                      id: 1
                      mo_number: MO-000001
                      status: in_progress
                    iteration_number: 1
                    created_by:
                      id: 1
                      name: Administrator
                    production_date: '2026-06-03T04:32:22.000000Z'
                    output_quantity: 10
                    total_input_cost: 35.81
                    total_allocated_cost: 35.81
                    is_reversed: false
                    reversed_at: null
                    reversed_by: null
                    reverse_reason: null
                    reversible: true
                    non_reversible_reason: null
                    movement_count: 4
                    output_fifo_layer_id: 5
                    output_fifo_layer:
                      id: 5
                      original_quantity: 10
                      available_quantity: 10
                      fulfilled_quantity: 0
                      avg_cost: 3.581
                      total_cost: 35.81
                      fifo_layer_date: '2026-06-03T04:32:22.000000Z'
                      created_at: '2026-06-03T04:32:22.000000Z'
                    created_at: '2026-06-03T04:32:22.000000Z'
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No query results for model [App\Models\MoProductionIteration].
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: manufacturing:read
      operationId: get-api-manufacturing-production-iterations-id
  /api/manufacturing/production-iterations/{id}/inventory-movements:
    get:
      tags:
      - Manufacturing Orders
      summary: List Production Iteration Inventory Movements
      description: 'Paginated inventory movements scoped to a single production iteration
        — every movement created by the underlying Record Production call (component
        consumption, scrap, and output). Scope is `inventory_movements.production_iteration_id
        = {iteration.id}`. Backs the Movements tab on the Production Iteration detail
        page.


        :::info[Required scope: `manufacturing:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        **Path parameters:**

        - `moProductionIteration` (string, UUID) — the iteration''s UUID primary key.


        **Query parameters (Spatie QueryBuilder):**

        - `per_page` — items per page (default: 15)

        - `sort` — sort field. Prefix with `-` for DESC. Allowed: `id`, `inventory_movement_date`,
        `type`, `inventory_status`, `quantity`, `reference`, `created_at`. Default:
        `-id`

        - `filter[type]` — exact match (e.g. `manufacturing_consumption`, `manufacturing_output`,
        `manufacturing_scrap`)

        - `filter[inventory_status]` — exact match (e.g. `on_hand`, `scrapped`)

        - `filter[link_type]` — exact FQN model class (e.g. `App\Models\MoOutputLine`,
        `App\Models\MoComponentLine`)

        - `filter[warehouse_id]` — exact match

        - `filter[fifo_layer_id]` — exact match

        - `filter[search]` — LIKE on product SKU or product name

        - `filter[inventory_movement_date_from]`, `filter[inventory_movement_date_to]`
        — date range (Y-m-d)

        - `filter[created_at_from]`, `filter[created_at_to]` — date range (Y-m-d)'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        type:
                          type: string
                        inventory_status:
                          type: string
                        quantity:
                          type: integer
                        reference:
                          type: string
                          nullable: true
                        link_type:
                          type: string
                        link_id:
                          type: integer
                        parent_link_id:
                          type: string
                          nullable: true
                        detail_link_id:
                          type: string
                          nullable: true
                        product_id:
                          type: integer
                        product_sku:
                          type: string
                        product_name:
                          type: string
                        warehouse_id:
                          type: integer
                        warehouse_name:
                          type: string
                        unit_cost:
                          type: number
                        layer:
                          type: object
                          properties:
                            fifo_layer_id:
                              type: integer
                            name:
                              type: string
                              nullable: true
                        fifo_layer_id:
                          type: integer
                        inventory_movement_date:
                          type: string
                        created_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - id: 8
                    type: manufacturing_output
                    inventory_status: on_hand
                    quantity: 10
                    reference: null
                    link_type: App\Models\MoOutputLine
                    link_id: 1
                    parent_link_id: null
                    detail_link_id: null
                    product_id: 4
                    product_sku: QA-COFFEE-250
                    product_name: Coffee 250g Pouch
                    warehouse_id: 1
                    warehouse_name: Main Warehouse
                    unit_cost: 3.581
                    layer:
                      fifo_layer_id: 5
                      name: null
                    fifo_layer_id: 5
                    inventory_movement_date: '2026-06-03T04:32:22.000000Z'
                    created_at: '2026-06-03T04:32:22.000000Z'
                  - id: 7
                    type: manufacturing_consumption
                    inventory_status: on_hand
                    quantity: -25
                    reference: null
                    link_type: App\Models\MoComponentLine
                    link_id: 3
                    parent_link_id: null
                    detail_link_id: null
                    product_id: 7
                    product_sku: QA-BEAN-1KG
                    product_name: Raw Coffee Bean 1kg
                    warehouse_id: 1
                    warehouse_name: Main Warehouse
                    unit_cost: 1.2
                    layer:
                      fifo_layer_id: 2
                      name: null
                    fifo_layer_id: 2
                    inventory_movement_date: '2026-06-03T04:32:22.000000Z'
                    created_at: '2026-06-03T04:32:22.000000Z'
                  current_page: 1
                  last_page: 1
                  per_page: 15
                  total: 4
                  from: 1
                  to: 4
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: manufacturing:read
      operationId: get-api-manufacturing-production-iterations-id-inventory-movements
  /api/manufacturing/production-iterations/{id}/fifo-layers:
    get:
      tags:
      - Manufacturing Orders
      summary: List Production Iteration FIFO Layers
      description: 'Paginated FIFO layers scoped to a single production iteration
        — every layer (output + any auxiliary) created by the underlying Record Production
        call. Scope is `fifo_layers.production_iteration_id = {iteration.id}`. Mirrors
        the MO-output-line FIFO-layers endpoint so the frontend list view can reuse
        the same contract.


        :::info[Required scope: `manufacturing:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        **Path parameters:**

        - `moProductionIteration` (string, UUID) — the iteration''s UUID primary key.


        **Query parameters (Spatie QueryBuilder):**

        - `per_page` — items per page (default: 15)

        - `sort` — sort field. Prefix with `-` for DESC. Allowed: `id`, `fifo_layer_date`,
        `original_quantity`, `fulfilled_quantity`, `avg_cost`, `total_cost`, `created_at`.
        Default: `-created_at`

        - `filter[warehouse_id]` — exact match

        - `filter[product_id]` — exact match

        - `filter[search]` — LIKE on product SKU or product name

        - `filter[fifo_layer_date_from]`, `filter[fifo_layer_date_to]` — date range
        (Y-m-d)

        - `filter[avg_cost_min]`, `filter[avg_cost_max]` — avg_cost range'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        product_id:
                          type: integer
                        warehouse_id:
                          type: integer
                        batch_number:
                          type: string
                        manufacture_date:
                          type: string
                        expiry_date:
                          type: string
                          nullable: true
                        original_quantity:
                          type: integer
                        available_quantity:
                          type: integer
                        fulfilled_quantity:
                          type: integer
                        avg_cost:
                          type: number
                        total_cost:
                          type: number
                        fifo_layer_date:
                          type: string
                        link_type:
                          type: string
                        link_id:
                          type: integer
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - id: 5
                    product_id: 4
                    warehouse_id: 1
                    batch_number: MO-000001-2026-06-03
                    manufacture_date: '2026-06-03'
                    expiry_date: null
                    original_quantity: 10
                    available_quantity: 10
                    fulfilled_quantity: 0
                    avg_cost: 3.581
                    total_cost: 35.81
                    fifo_layer_date: '2026-06-03T04:32:22.000000Z'
                    link_type: App\Models\MoOutputLine
                    link_id: 1
                    created_at: '2026-06-03T04:32:22.000000Z'
                    updated_at: '2026-06-03T04:32:22.000000Z'
                  current_page: 1
                  last_page: 1
                  per_page: 15
                  total: 1
                  from: 1
                  to: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: manufacturing:read
      operationId: get-api-manufacturing-production-iterations-id-fifo-layers
  /api/manufacturing/manufacturing-orders/{id}/production-iterations/{id2}/reverse:
    post:
      tags:
      - Manufacturing Orders
      summary: Reverse Production Iteration
      description: 'Reverses a production iteration: restores input FIFO layers, deletes
        the output layer (if not yet drawn from), rolls back actuals on the component/output
        lines, decrements `completed_quantity` on the MO, and writes a `production_reversed`
        audit event. Refuses with 422 if already reversed, mismatched MO, or downstream-drawn.


        :::info[Required scope: `manufacturing:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        **Request body:**

        - `reason` (string, optional, max 1000) — free-text reason for the reversal


        **Failure modes (422 JSON with discriminator `code`):**

        - `iteration_already_reversed`

        - `downstream_draw_blocks_reverse` — carries `details.layer_id`, `details.fulfilled_quantity`,
        `details.original_quantity`

        - `iteration_belongs_to_other_mo`


        **Success:** 200 with the refreshed manufacturing order object.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                reason:
                  type: string
              example:
                reason: Quality control rejected this batch
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      - name: id2
        in: path
        required: true
        schema:
          type: string
        description: The id2 identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: integer
                  mo_number:
                    type: string
                  status:
                    type: string
                  bom_id:
                    type: integer
                  planned_quantity:
                    type: integer
                  completed_quantity:
                    type: integer
                  production_method:
                    type: string
                  started_at:
                    type: string
                  completed_at:
                    type: string
                    nullable: true
                  cost_breakdown:
                    type: string
                    nullable: true
                  created_at:
                    type: string
                  updated_at:
                    type: string
                example:
                  id: 1
                  mo_number: MO-000001
                  status: in_progress
                  bom_id: 5
                  planned_quantity: 100
                  completed_quantity: 0
                  production_method: in_house
                  started_at: '2026-06-02T20:30:00.000000Z'
                  completed_at: null
                  cost_breakdown: null
                  created_at: '2026-06-02T20:00:00.000000Z'
                  updated_at: '2026-06-02T20:38:00.000000Z'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 422 — Already Reversed
                  value:
                    code: iteration_already_reversed
                    message: 'Iteration #1 on MO 1 has already been reversed.'
                example-1:
                  summary: 422 — Downstream Draw Blocks Reverse
                  value:
                    code: downstream_draw_blocks_reverse
                    message: 'Cannot reverse iteration #1: output FIFO Layer #5 has
                      4 of 10 units already consumed downstream.'
                    details:
                      layer_id: 5
                      fulfilled_quantity: 4
                      original_quantity: 10
                example-2:
                  summary: 422 — Mo Mismatch
                  value:
                    code: iteration_belongs_to_other_mo
                    message: Iteration 0fa1c2bb-8b1b-4c5a-9d63-1f4b5e6d7c80 does not
                      belong to MO MO-000002.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: manufacturing:write
      operationId: post-api-manufacturing-manufacturing-orders-id-production-iterations-id2-reverse
  /api/manufacturing/manufacturing-orders/{manufacturingOrder}/cost-allocation-breakdown:
    get:
      tags:
      - Manufacturing Orders
      summary: Get MO Cost Allocation Breakdown
      description: 'Get the cumulative cost-allocation breakdown across all posted
        production for this manufacturing order: the allocation method in use, each
        output''s basis value, share percent, allocated cost, and unit cost, plus
        byproduct valuations. Always returns a usable shape - has_production is false
        when no production has been recorded yet.

        Auth: requires Bearer token.

        Path param: manufacturingOrder = manufacturing order id.


        :::info[Required scope: `manufacturing:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: manufacturingOrder
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The manufacturing order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      method:
                        type: string
                      method_label:
                        type: string
                      method_formula:
                        type: string
                      basis_label:
                        type: string
                      basis_hint:
                        type: string
                      has_production:
                        type: boolean
                      total_input_cost:
                        type: integer
                      byproduct_value:
                        type: integer
                      remaining_pool:
                        type: integer
                      allocatable_outputs:
                        type: array
                        items:
                          type: object
                          properties:
                            output_line_id:
                              type: integer
                            product_id:
                              type: integer
                            product_sku:
                              type: string
                            product_name:
                              type: string
                            role:
                              type: string
                            produced_quantity:
                              type: integer
                            basis_value:
                              type: number
                            weight:
                              type: integer
                            allocated_cost:
                              type: integer
                            unit_cost:
                              type: integer
                            missing_basis:
                              type: boolean
                            share_percent:
                              type: integer
                      byproducts:
                        type: array
                        items:
                          type: object
                          properties:
                            output_line_id:
                              type: integer
                            product_id:
                              type: integer
                            product_sku:
                              type: string
                            product_name:
                              type: string
                            role:
                              type: string
                            produced_quantity:
                              type: integer
                            valuation_method:
                              type: string
                            valuation_amount:
                              type: integer
                            allocated_cost:
                              type: integer
                            unit_cost:
                              type: integer
                example:
                  data:
                    method: by_weight
                    method_label: By Weight
                    method_formula: share = (producedQty × product.weight) ÷ Σ
                    basis_label: Weight
                    basis_hint: Product weight
                    has_production: true
                    total_input_cost: 1250
                    byproduct_value: 50
                    remaining_pool: 1200
                    allocatable_outputs:
                    - output_line_id: 88
                      product_id: 1
                      product_sku: KIT-A
                      product_name: Widget Kit A
                      role: primary
                      produced_quantity: 100
                      basis_value: 0.5
                      weight: 50
                      allocated_cost: 1200
                      unit_cost: 12
                      missing_basis: false
                      share_percent: 100
                    byproducts:
                    - output_line_id: 89
                      product_id: 9
                      product_sku: SCRAP-01
                      product_name: Offcut Material
                      role: byproduct
                      produced_quantity: 5
                      valuation_method: fixed_value
                      valuation_amount: 10
                      allocated_cost: 50
                      unit_cost: 10
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: manufacturing:read
      operationId: get-api-manufacturing-manufacturing-orders-manufacturingorder-cost-allocation-breakdown
  /api/manufacturing/manufacturing-orders/{manufacturingOrder}/print:
    get:
      tags:
      - Manufacturing Orders
      summary: Download Work Order PDF
      description: 'Download a printable work order PDF for the manufacturing order
        (returned inline with Content-Type application/pdf). For Draft orders that
        have not been confirmed yet, component and output rows fall back to the BOM
        definition.

        Auth: requires Bearer token.

        Path param: manufacturingOrder = manufacturing order id.


        :::info[Required scope: `manufacturing:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: manufacturingOrder
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The manufacturing order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/pdf
          content:
            text/plain:
              schema:
                type: string
                example: ''
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: manufacturing:read
      operationId: get-api-manufacturing-manufacturing-orders-manufacturingorder-print
  /api/manufacturing/manufacturing-orders/{id}/production-iterations/{id2}/reverse-impact:
    get:
      tags:
      - Manufacturing Orders
      summary: Preview Reverse Production Iteration Impact
      description: 'Read-only preview of the allocation-demotion impact of reversing
        this production iteration. Because reversing it removes the stock it added,
        this behaves like a manual negative adjustment and returns one row per affected
        product: how much of the removed quantity is unallocated vs soft-allocated
        vs hard-allocated, plus every sales-order allocation and fulfillment (printed
        shipping label) the removal would disturb. Use it to decide which fulfillments
        to authorize voiding via `void_confirmations` on the reversing call. Nothing
        is mutated. A removal that only re-adds stock returns an empty `data` array.


        Authentication: Requires Bearer token.'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      - name: id2
        in: path
        required: true
        schema:
          type: string
        description: The id2 identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        product_id:
                          type: integer
                        product_sku:
                          type: string
                        product_name:
                          type: string
                        shortfall_quantity:
                          type: integer
                        unallocated_quantity:
                          type: integer
                        soft_allocated_quantity:
                          type: integer
                        hard_allocated_quantity:
                          type: integer
                        affected_allocations:
                          type: array
                          items:
                            type: object
                            properties:
                              allocation_id:
                                type: integer
                              allocation_type:
                                type: string
                              sales_order_id:
                                type: integer
                              order_number:
                                type: string
                              customer_name:
                                type: string
                              fulfillment_id:
                                type: string
                                nullable: true
                              carrier:
                                type: string
                                nullable: true
                              carrier_void_supported:
                                type: string
                                nullable: true
                              voidable_status:
                                type: string
                                nullable: true
                              voidable_detail:
                                type: string
                                nullable: true
                              quantity:
                                type: integer
                example:
                  data:
                  - product_id: 5567
                    product_sku: WIDGET-BLUE
                    product_name: Blue Widget
                    shortfall_quantity: 0
                    unallocated_quantity: 10
                    soft_allocated_quantity: 6
                    hard_allocated_quantity: 4
                    affected_allocations:
                    - allocation_id: 88201
                      allocation_type: soft
                      sales_order_id: 3120
                      order_number: SO-3120
                      customer_name: Acme Co.
                      fulfillment_id: null
                      carrier: null
                      carrier_void_supported: null
                      voidable_status: null
                      voidable_detail: null
                      quantity: 6
                    - allocation_id: 88205
                      allocation_type: hard
                      sales_order_id: 3125
                      order_number: SO-3125
                      customer_name: Beta LLC
                      fulfillment_id: 90142
                      carrier: ups
                      carrier_void_supported: true
                      voidable_status: voidable
                      voidable_detail: null
                      quantity: 4
                      allocation_ids:
                      - 88205
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-manufacturing-manufacturing-orders-id-production-iterations-id2-reverse-impact
  /api/manufacturing/manufacturing-orders/{id}/record-production/preview-release-impact:
    post:
      tags:
      - Manufacturing Orders
      summary: Preview Record Production Release Impact
      description: 'Read-only preview of which back-ordered sales orders the proposed
        produced quantities would release finished-good stock to, returned one row
        per output product. Nothing is mutated — post the outputs you intend to record
        and get the release picture before committing.


        **Request body:**

        - `outputs` (array, optional) — the produced outputs to evaluate.

        - `outputs[].mo_output_line_id` (integer, required) — the output line being
        produced.

        - `outputs[].actual_produced_quantity` (number, required, min 0) — the quantity
        that would be produced.


        **Response (`data[]`, one row per output product):**

        - `releasable_quantity` — units of the newly produced stock that can be released
        to back-ordered demand.

        - `orders[]` — the back-ordered sales orders that would be filled (`sales_order_id`,
        `order_number`, `customer_name`, `quantity`).

        - `held_back[]` — demand that stays back-ordered, each with `reason_kept`
        explaining why (e.g. "Insufficient supply").


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                outputs:
                  type: array
                  items:
                    type: object
                    properties:
                      mo_output_line_id:
                        type: integer
                      actual_produced_quantity:
                        type: integer
              example:
                outputs:
                - mo_output_line_id: 1
                  actual_produced_quantity: 100
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        product_id:
                          type: integer
                        product_sku:
                          type: string
                        product_name:
                          type: string
                        releasable_quantity:
                          type: integer
                        orders:
                          type: array
                          items:
                            type: object
                            properties:
                              sales_order_id:
                                type: integer
                              order_number:
                                type: string
                              customer_name:
                                type: string
                              quantity:
                                type: integer
                        held_back:
                          type: array
                          items:
                            type: object
                            properties:
                              allocation_id:
                                type: integer
                              product_id:
                                type: integer
                              sales_order_id:
                                type: integer
                              sales_order_line_id:
                                type: integer
                              sales_order_number:
                                type: string
                              customer_name:
                                type: string
                              quantity:
                                type: integer
                              from_status:
                                type: string
                              to_status:
                                type: string
                              reason_kept:
                                type: string
                example:
                  data:
                  - product_id: 123
                    product_sku: WIDGET-001
                    product_name: Blue Widget 500ml
                    releasable_quantity: 8
                    orders:
                    - sales_order_id: 4602
                      order_number: SO-10501
                      customer_name: Acme Retail
                      quantity: 5
                    - sales_order_id: 4610
                      order_number: SO-10509
                      customer_name: Gamma Foods
                      quantity: 3
                    held_back:
                    - allocation_id: 90311
                      product_id: 123
                      sales_order_id: 4620
                      sales_order_line_id: 55123
                      sales_order_number: SO-10518
                      customer_name: Delta Mart
                      quantity: 4
                      from_status: planned
                      to_status: allocated
                      reason_kept: Insufficient supply
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-manufacturing-manufacturing-orders-id-record-production-preview-release-impact
  /api/manufacturing/manufacturing-orders/{manufacturingOrder}/operations:
    post:
      tags:
      - MO Operations
      summary: Create Manual MO Operation
      description: 'Create a manual operation against a specific MO. The new row is
        stamped source=''manual'' with bom_operation_id=null.


        :::info[Required scope: `manufacturing:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        **Body fields:**

        - `sequence` (required, integer, min 0) — ordering on the MO; can interleave
        with from_bom rows

        - `name` (required, string, max 255)

        - `type` (required, enum) — one of: process, setup, per_unit, fixed_cost.
        Stored on the row as operation_type.

        - `work_center_id` (optional, integer, exists:work_centers,id)

        - `default_operator_id` (optional, integer, exists:users,id) — planned operator
        (distinct from operator_id which is set when the timer starts)

        - `expected_duration_minutes` (optional, integer, min 0)

        - `hourly_rate` (optional, numeric, min 0)

        - `fixed_cost` (optional, numeric, min 0) — flat per-run cost added on top
        of labour for any operation type (or the entire cost of a fixed_cost operation).
        Capitalized onto finished goods like labour, but never marked up by work-center
        overhead.

        - `notes` (optional, string, max 1000)


        **Refused** with 422 {code:''mo_locked''} when MO status is completed | closed
        | cancelled.


        `cost_classification` (optional, `labor`|`overhead`, default `labor`) sets
        the expense classification independently of the rate basis: `labor` posts
        the operation''s variable cost to the Labor bucket (marked up by the work
        center''s overhead %); `overhead` posts machine/tooling-style cost to the
        Overhead bucket with no additional markup.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                sequence:
                  type: integer
                name:
                  type: string
                type:
                  type: string
                work_center_id:
                  type: integer
                default_operator_id:
                  type: integer
                expected_duration_minutes:
                  type: integer
                hourly_rate:
                  type: integer
                fixed_cost:
                  type: integer
                cost_classification:
                  type: string
                notes:
                  type: string
              example:
                sequence: 40
                name: Final QA Check
                type: process
                work_center_id: 3
                default_operator_id: 7
                expected_duration_minutes: 15
                hourly_rate: 35
                fixed_cost: 0
                cost_classification: labor
                notes: Added for this MO only — not on the BOM.
      parameters:
      - name: manufacturingOrder
        in: path
        schema:
          type: integer
        required: true
        description: Manufacturing order ID
        example: '1'
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      manufacturing_order_id:
                        type: integer
                      source:
                        type: string
                      bom_operation_id:
                        type: string
                        nullable: true
                      sequence:
                        type: integer
                      name:
                        type: string
                      type:
                        type: string
                      operation_type:
                        type: string
                      expected_duration_minutes:
                        type: integer
                      hourly_rate:
                        type: integer
                      status:
                        type: string
                      scheduled_start:
                        type: string
                        nullable: true
                      started_at:
                        type: string
                        nullable: true
                      completed_at:
                        type: string
                        nullable: true
                      actual_time_minutes:
                        type: string
                        nullable: true
                      operator_id:
                        type: string
                        nullable: true
                      default_operator_id:
                        type: integer
                      default_operator:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      work_center_id:
                        type: integer
                      work_center:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      fixed_cost:
                        type: integer
                      cost_classification:
                        type: string
                      actual_cost:
                        type: string
                        nullable: true
                      cost_source:
                        type: string
                      notes:
                        type: string
                      bom_operation:
                        type: string
                        nullable: true
                      is_modified_from_bom:
                        type: boolean
                example:
                  data:
                    id: 412
                    manufacturing_order_id: 14
                    source: manual
                    bom_operation_id: null
                    sequence: 40
                    name: Final QA Check
                    type: process
                    operation_type: process
                    expected_duration_minutes: 15
                    hourly_rate: 35
                    status: pending
                    scheduled_start: null
                    started_at: null
                    completed_at: null
                    actual_time_minutes: null
                    operator_id: null
                    default_operator_id: 7
                    default_operator:
                      id: 7
                      name: Sam Cooper
                    work_center_id: 3
                    work_center:
                      id: 3
                      name: QA Bench
                    fixed_cost: 0
                    cost_classification: labor
                    actual_cost: null
                    cost_source: none
                    notes: Added for this MO only — not on the BOM.
                    bom_operation: null
                    is_modified_from_bom: false
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  code:
                    type: string
                  message:
                    type: string
                example:
                  code: mo_locked
                  message: This MO is no longer editable.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: manufacturing:write
      operationId: post-api-manufacturing-manufacturing-orders-manufacturingorder-operations
  /api/manufacturing/mo-operations/{moOperation}:
    put:
      tags:
      - MO Operations
      summary: Update MO Operation
      description: 'Update an MO operation. Allowed on both source=''manual'' AND
        source=''from_bom'' rows — edits to from_bom rows do NOT propagate back to
        the BOM master.


        :::info[Required scope: `manufacturing:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        All body fields are ''sometimes'' (omit to leave unchanged):

        - `sequence` (integer, min 0)

        - `name` (string, max 255)

        - `type` (enum: process, setup, per_unit, fixed_cost) — maps to operation_type
        column

        - `work_center_id` (integer, exists:work_centers,id, nullable)

        - `default_operator_id` (integer, exists:users,id, nullable)

        - `expected_duration_minutes` (integer, min 0, nullable)

        - `hourly_rate` (numeric, min 0, nullable)

        - `fixed_cost` (numeric, min 0, nullable) — flat per-run cost added additively
        to labour. Changing it re-derives actual_cost as (time × rate) + fixed_cost.

        - `notes` (string, max 1000, nullable)


        When the row is source=''from_bom'' and any of {sequence, name, operation_type,
        work_center_id, default_operator_id, expected_duration_minutes, hourly_rate,
        fixed_cost} now differs from the linked BOM operation, the response field
        `is_modified_from_bom` flips to true.


        **Refused** with 422 {code:''mo_locked''} when MO status is completed | closed
        | cancelled.


        The response also carries a `cost_source` field: ''none'' (no actual_cost
        yet), ''actual'' (cost backed by logged time, or a fixed_cost operation),
        ''estimated'' (cost fell back to planned duration because no timer was logged),
        or ''manual'' (an explicitly supplied `actual_cost`). Sending `actual_cost`
        in the body stamps cost_source=''manual'' and locks the cost against automatic
        re-derivation — rate, fixed-cost, or type edits no longer recompute it; only
        another explicit `actual_cost` (null clears both cost and source), or an explicitly
        logged positive time, replaces it.


        `cost_classification` (optional, `labor`|`overhead`, default `labor`) sets
        the expense classification independently of the rate basis: `labor` posts
        the operation''s variable cost to the Labor bucket (marked up by the work
        center''s overhead %); `overhead` posts machine/tooling-style cost to the
        Overhead bucket with no additional markup.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                sequence:
                  type: integer
                name:
                  type: string
                work_center_id:
                  type: integer
                expected_duration_minutes:
                  type: integer
                hourly_rate:
                  type: integer
                fixed_cost:
                  type: integer
                cost_classification:
                  type: string
              example:
                sequence: 25
                name: Mix (revised)
                work_center_id: 2
                expected_duration_minutes: 45
                hourly_rate: 55
                fixed_cost: 5
                cost_classification: labor
      parameters:
      - name: moOperation
        in: path
        schema:
          type: integer
        required: true
        description: MO operation ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      manufacturing_order_id:
                        type: integer
                      source:
                        type: string
                      bom_operation_id:
                        type: integer
                      sequence:
                        type: integer
                      name:
                        type: string
                      type:
                        type: string
                      operation_type:
                        type: string
                      expected_duration_minutes:
                        type: integer
                      hourly_rate:
                        type: integer
                      status:
                        type: string
                      scheduled_start:
                        type: string
                        nullable: true
                      started_at:
                        type: string
                        nullable: true
                      completed_at:
                        type: string
                        nullable: true
                      actual_time_minutes:
                        type: string
                        nullable: true
                      operator_id:
                        type: string
                        nullable: true
                      default_operator_id:
                        type: string
                        nullable: true
                      work_center_id:
                        type: integer
                      work_center:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      fixed_cost:
                        type: integer
                      cost_classification:
                        type: string
                      actual_cost:
                        type: string
                        nullable: true
                      cost_source:
                        type: string
                      notes:
                        type: string
                        nullable: true
                      bom_operation:
                        type: object
                        properties:
                          id:
                            type: integer
                          bom_id:
                            type: integer
                          sequence:
                            type: integer
                          name:
                            type: string
                          work_center_id:
                            type: integer
                          operation_type:
                            type: string
                          time_minutes:
                            type: integer
                          cost_per_hour:
                            type: integer
                          fixed_cost:
                            type: string
                            nullable: true
                          cost_classification:
                            type: string
                          instructions:
                            type: string
                            nullable: true
                      is_modified_from_bom:
                        type: boolean
                example:
                  data:
                    id: 1
                    manufacturing_order_id: 14
                    source: from_bom
                    bom_operation_id: 12
                    sequence: 25
                    name: Mix (revised)
                    type: setup
                    operation_type: setup
                    expected_duration_minutes: 45
                    hourly_rate: 55
                    status: pending
                    scheduled_start: null
                    started_at: null
                    completed_at: null
                    actual_time_minutes: null
                    operator_id: null
                    default_operator_id: null
                    work_center_id: 2
                    work_center:
                      id: 2
                      name: Mixing Station
                    fixed_cost: 5
                    cost_classification: labor
                    actual_cost: null
                    cost_source: none
                    notes: null
                    bom_operation:
                      id: 12
                      bom_id: 2
                      sequence: 10
                      name: Mix
                      work_center_id: 1
                      operation_type: setup
                      time_minutes: 30
                      cost_per_hour: 45
                      fixed_cost: null
                      cost_classification: labor
                      instructions: null
                    is_modified_from_bom: true
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  code:
                    type: string
                  message:
                    type: string
                example:
                  code: mo_locked
                  message: This MO is no longer editable.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: manufacturing:write
      operationId: put-api-manufacturing-mo-operations-mooperation
    delete:
      tags:
      - MO Operations
      summary: Delete MO Operation
      description: 'Delete an MO operation. Allowed on both source=''manual'' AND
        source=''from_bom'' rows — industry pattern lets an operator drop an inherited
        step on a one-off MO. The linked BOM operation is untouched.


        :::info[Required scope: `manufacturing:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        **Refused** with 422 {code:''mo_locked''} when MO status is completed | closed
        | cancelled.'
      parameters:
      - name: moOperation
        in: path
        schema:
          type: integer
        required: true
        description: MO operation ID
        example: '1'
      responses:
        '204':
          description: No Content
          content:
            text/plain:
              schema:
                type: string
                example: ''
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  code:
                    type: string
                  message:
                    type: string
                example:
                  code: mo_locked
                  message: This MO is no longer editable.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: manufacturing:write
      operationId: delete-api-manufacturing-mo-operations-mooperation
  /api/manufacturing/mo-operations/{moOperation}/start:
    post:
      tags:
      - MO Operations
      summary: Start Operation Timer
      description: 'Start the per-operation timer (shop-floor use). Stamps started_at=now()
        and sets operator_id to the authenticated user. Rejects with 422 if the operation
        is already done.


        :::info[Required scope: `manufacturing:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Returns **422** with `code = mo_locked` when the parent manufacturing order
        is Completed, Closed, or Cancelled — operations on a terminal order are immutable.'
      requestBody:
        content: {}
      parameters:
      - name: moOperation
        in: path
        schema:
          type: integer
        required: true
        description: MO operation ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      manufacturing_order_id:
                        type: integer
                      source:
                        type: string
                      bom_operation_id:
                        type: integer
                      sequence:
                        type: integer
                      name:
                        type: string
                      type:
                        type: string
                      operation_type:
                        type: string
                      expected_duration_minutes:
                        type: integer
                      hourly_rate:
                        type: integer
                      status:
                        type: string
                      scheduled_start:
                        type: string
                        nullable: true
                      started_at:
                        type: string
                      completed_at:
                        type: string
                        nullable: true
                      actual_time_minutes:
                        type: string
                        nullable: true
                      operator_id:
                        type: integer
                      operator:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      default_operator_id:
                        type: string
                        nullable: true
                      work_center_id:
                        type: integer
                      work_center:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      fixed_cost:
                        type: integer
                      actual_cost:
                        type: string
                        nullable: true
                      cost_source:
                        type: string
                      notes:
                        type: string
                        nullable: true
                      bom_operation:
                        type: string
                        nullable: true
                      is_modified_from_bom:
                        type: boolean
                example:
                  data:
                    id: 1
                    manufacturing_order_id: 14
                    source: from_bom
                    bom_operation_id: 12
                    sequence: 25
                    name: Mix
                    type: process
                    operation_type: process
                    expected_duration_minutes: 30
                    hourly_rate: 55
                    status: in_progress
                    scheduled_start: null
                    started_at: '2026-07-15T09:12:00.000000Z'
                    completed_at: null
                    actual_time_minutes: null
                    operator_id: 7
                    operator:
                      id: 7
                      name: Sam Cooper
                    default_operator_id: null
                    work_center_id: 2
                    work_center:
                      id: 2
                      name: Mixing Station
                    fixed_cost: 5
                    actual_cost: null
                    cost_source: none
                    notes: null
                    bom_operation: null
                    is_modified_from_bom: false
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  code:
                    type: string
                  message:
                    type: string
                example:
                  code: mo_locked
                  message: This MO is no longer editable.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: manufacturing:write
      operationId: post-api-manufacturing-mo-operations-mooperation-start
  /api/manufacturing/mo-operations/{moOperation}/complete:
    post:
      tags:
      - MO Operations
      summary: Complete Operation Timer
      description: 'Stop the timer and mark the operation done. When `actual_time_minutes`
        is omitted it''s computed from the started_at timestamp.


        :::info[Required scope: `manufacturing:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        **Body fields:**

        - `actual_time_minutes` (optional, numeric, min 0)

        - `notes` (optional, string, max 2000)


        When `actual_time_minutes` is omitted or 0, the labour cost falls back to
        the operation''s planned `expected_duration_minutes` so a bare mark-done still
        costs out. The response''s `cost_source` then reads ''estimated'' (vs ''actual''
        when a timer was logged, or for a fixed_cost operation). If the operation
        carries a manually-set cost (cost_source=''manual''), a bare mark-done without
        a positive `actual_time_minutes` keeps that cost and source untouched; logging
        a positive time re-derives the cost and replaces the manual value.


        Returns **422** with `code = mo_locked` when the parent manufacturing order
        is Completed, Closed, or Cancelled — operations on a terminal order are immutable.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                actual_time_minutes:
                  type: integer
                notes:
                  type: string
              example:
                actual_time_minutes: 35
                notes: Ran a bit over.
      parameters:
      - name: moOperation
        in: path
        schema:
          type: integer
        required: true
        description: MO operation ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 OK — Timer logged
                  value:
                    data:
                      id: 1
                      manufacturing_order_id: 14
                      source: from_bom
                      bom_operation_id: 12
                      sequence: 25
                      name: Mix
                      type: process
                      operation_type: process
                      expected_duration_minutes: 30
                      hourly_rate: 55
                      status: done
                      scheduled_start: null
                      started_at: '2026-07-15T09:12:00.000000Z'
                      completed_at: '2026-07-15T09:47:00.000000Z'
                      actual_time_minutes: 35
                      operator_id: 7
                      operator:
                        id: 7
                        name: Sam Cooper
                      default_operator_id: null
                      work_center_id: 2
                      work_center:
                        id: 2
                        name: Mixing Station
                      fixed_cost: 5
                      actual_cost: 37.08
                      cost_source: actual
                      notes: Ran a bit over.
                      bom_operation: null
                      is_modified_from_bom: false
                example-1:
                  summary: 200 OK — No timer (estimated fallback)
                  value:
                    data:
                      id: 1
                      manufacturing_order_id: 14
                      source: from_bom
                      bom_operation_id: 12
                      sequence: 25
                      name: Mix
                      type: process
                      operation_type: process
                      expected_duration_minutes: 30
                      hourly_rate: 55
                      status: done
                      scheduled_start: null
                      started_at: null
                      completed_at: '2026-07-15T09:47:00.000000Z'
                      actual_time_minutes: null
                      operator_id: null
                      operator:
                        id: 7
                        name: Sam Cooper
                      default_operator_id: null
                      work_center_id: 2
                      work_center:
                        id: 2
                        name: Mixing Station
                      fixed_cost: 5
                      actual_cost: 32.5
                      cost_source: estimated
                      notes: null
                      bom_operation: null
                      is_modified_from_bom: false
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  code:
                    type: string
                  message:
                    type: string
                example:
                  code: mo_locked
                  message: This MO is no longer editable.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: manufacturing:write
      operationId: post-api-manufacturing-mo-operations-mooperation-complete
  /api/manufacturing/manufacturing-orders/{manufacturingOrder}/outsource:
    post:
      tags:
      - Outsourced Production
      summary: Outsource MO
      description: 'Switches an existing draft or confirmed Manufacturing Order to
        outsourced production.


        Persists `production_method=outsourced`, the contractor supplier, scheduling
        dates, and notes on the MO row. Writes a `production_method_changed` event
        with the full payload (including contractor warehouse and service fee).


        **Request body fields:**

        - `contractor_supplier_id` (int, required) — Supplier id with `is_manufacturing_contractor=true`.
        Must exist in `suppliers`.

        - `contractor_warehouse_id` (int, nullable) — Warehouse the contractor will
        receive components into. Must exist in `warehouses`.

        - `outsourced_purchase_order_id` (int, nullable) — Optional existing PO to
        link. Must exist in `purchase_orders`. If omitted, an Open outsourced PO is
        auto-created against the contractor and linked.

        - `scheduled_start` (datetime, nullable) — `Y-m-d H:i:s`. Persisted to `manufacturing_orders.scheduled_start`.

        - `scheduled_end` (datetime, nullable, must be >= scheduled_start) — Persisted
        to `manufacturing_orders.scheduled_end`.

        - `service_fee_amount` (decimal, nullable, min:0) — Recorded as a cost FinancialLine
        on the backing PO; flows into the MO cost_breakdown.service_fee when production
        is received.

        - `notes` (string, nullable, max:5000) — Persisted to `manufacturing_orders.notes`.


        **Rejected (500)** if the MO status is not `draft` or `confirmed`.

        **Rejected (422)** if `contractor_supplier_id` is missing or any FK does not
        exist.


        :::info[Required scope: `manufacturing:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        **Validation:** the supplier must be flagged as a manufacturing contractor;
        `contractor_warehouse_id` must be that contractor''s own warehouse (when supplied,
        a Draft order''s source warehouse is re-pointed to it; a Confirmed order releases
        its component reservations and re-reserves at the new warehouse); `outsourced_purchase_order_id`
        must reference an outsourced-manufacturing purchase order that is unlinked
        or already linked to this order. Omitting `service_fee_amount` preserves the
        existing fee on a reused purchase order — supply a value (including 0) to
        change it.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                contractor_supplier_id:
                  type: integer
                contractor_warehouse_id:
                  type: integer
                outsourced_purchase_order_id:
                  type: string
                  nullable: true
                scheduled_start:
                  type: string
                scheduled_end:
                  type: string
                service_fee_amount:
                  type: integer
                notes:
                  type: string
              example:
                contractor_supplier_id: 9
                contractor_warehouse_id: 2
                outsourced_purchase_order_id: null
                scheduled_start: '2026-06-01 09:00:00'
                scheduled_end: '2026-06-05 17:00:00'
                service_fee_amount: 250
                notes: Co-packer run for TecMATE
      parameters:
      - name: manufacturingOrder
        in: path
        required: true
        schema:
          type: string
        description: The manufacturingOrder identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      mo_number:
                        type: string
                      status:
                        type: string
                      production_method:
                        type: string
                      contractor_supplier_id:
                        type: integer
                      outsourced_purchase_order_id:
                        type: string
                        nullable: true
                      scheduled_start:
                        type: string
                      scheduled_end:
                        type: string
                      notes:
                        type: string
                      planned_quantity:
                        type: string
                      completed_quantity:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 1
                    mo_number: MO-000001
                    status: draft
                    production_method: outsourced
                    contractor_supplier_id: 9
                    outsourced_purchase_order_id: null
                    scheduled_start: '2026-06-01 09:00:00'
                    scheduled_end: '2026-06-05 17:00:00'
                    notes: Co-packer run for TecMATE
                    planned_quantity: '5.000'
                    completed_quantity: '0.000'
                    created_at: '2026-05-28T16:50:00.000000Z'
                    updated_at: '2026-05-28T16:56:55.000000Z'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      contractor_supplier_id:
                        type: array
                        items:
                          type: string
                example:
                  message: The contractor supplier id field is required.
                  errors:
                    contractor_supplier_id:
                    - The contractor supplier id field is required.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: manufacturing:write
      operationId: post-api-manufacturing-manufacturing-orders-manufacturingorder-outsource
  /api/manufacturing/manufacturing-orders/{manufacturingOrder}/outsourced-receipt:
    post:
      tags:
      - Outsourced Production
      summary: Record Outsourced Receipt
      description: "Record receipt of finished goods from a contractor for an outsourced\
        \ MO. Runs the production-costing flow: consumes the reserved components from\
        \ FIFO, produces the output inventory, and costs it as materials + the PO's\
        \ service fee. The MO must be Started (in_progress / partially_completed).\n\
        \n:::info[Required scope: `manufacturing:write`]\nGrant this scope to your\
        \ token under [Settings → Developer → Personal Access Tokens](https://app.sku.io/settings/api).\n\
        :::\n\nA service_fee_amount override updates the cost FinancialLine on the\
        \ backing PO before costing, so it flows into cost_breakdown.service_fee.\n\
        \nFields:\n- receipt_date (required, date)\n- service_fee_amount (optional,\
        \ numeric ≥ 0) — overrides the PO service-fee financial line\n- lines (required,\
        \ min 1):\n  - mo_output_line_id (NULLABLE integer) — the MO output line this\
        \ received quantity produces; defaults to the primary output\n  - purchase_order_line_id\
        \ (NULLABLE integer) — not used for finished-goods mapping; reserved for PO-linked\
        \ receipts\n  - received_quantity (required, numeric ≥ 0)\n  - batch_number\
        \ (optional, ≤ 128 chars) — auto-generated if blank\n  - expiry_date (optional,\
        \ date)\n- component_variance (optional): mo_component_line_id + actually_consumed_at_contractor\
        \ — overrides per-component consumption"
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                receipt_date:
                  type: string
                service_fee_amount:
                  type: integer
                lines:
                  type: array
                  items:
                    type: object
                    properties:
                      mo_output_line_id:
                        type: integer
                      purchase_order_line_id:
                        type: string
                        nullable: true
                      received_quantity:
                        type: integer
                      batch_number:
                        type: string
                      expiry_date:
                        type: string
                component_variance:
                  type: array
                  items:
                    type: object
                    properties:
                      mo_component_line_id:
                        type: integer
                      actually_consumed_at_contractor:
                        type: integer
              example:
                receipt_date: '2026-04-28'
                service_fee_amount: 250
                lines:
                - mo_output_line_id: 1
                  purchase_order_line_id: null
                  received_quantity: 100
                  batch_number: CP-LOT-042
                  expiry_date: '2027-04-28'
                component_variance:
                - mo_component_line_id: 1
                  actually_consumed_at_contractor: 205
      parameters:
      - name: manufacturingOrder
        in: path
        required: true
        schema:
          type: string
        description: The manufacturingOrder identifier
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: manufacturing:write
      operationId: post-api-manufacturing-manufacturing-orders-manufacturingorder-outsourced-receipt
  /api/manufacturing/manufacturing-orders/{manufacturingOrder}/backflush-preview:
    get:
      tags:
      - Outsourced Production
      summary: Get Backflush Preview
      description: 'Preview the component consumption that receiving the given quantity
        of finished goods would record at the contractor site. Consumption is proportional
        to the manufacturing order''s planned quantity per component line. Rows flag
        a shortage when the projected consumption exceeds the physical on-hand at
        the contractor site.


        Authentication: Requires Bearer token.'
      parameters:
      - name: quantity
        in: query
        schema:
          type: integer
        description: Primary-output quantity you intend to receive. Required.
        example: '30000'
      - name: manufacturingOrder
        in: path
        schema:
          type: string
        required: true
        description: The manufacturing order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        mo_component_line_id:
                          type: integer
                        product:
                          type: object
                          properties:
                            id:
                              type: integer
                            sku:
                              type: string
                            name:
                              type: string
                        on_hand_at_source:
                          type: integer
                        will_consume:
                          type: integer
                        remaining_after:
                          type: integer
                        shortage:
                          type: boolean
                        uom_id:
                          type: integer
                example:
                  data:
                  - mo_component_line_id: 18
                    product:
                      id: 512
                      sku: '100157'
                      name: Single Blade
                    on_hand_at_source: 800000
                    will_consume: 660000
                    remaining_after: 140000
                    shortage: false
                    uom_id: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-manufacturing-manufacturing-orders-manufacturingorder-backflush-preview
  /api/manufacturing/simple-assemble:
    post:
      tags:
      - Simple Assembly
      summary: Simple Assemble / Disassemble
      description: 'Light-manufacturing mode: one-shot assemble/disassemble of a kit
        product. Creates a Completed Manufacturing Order (`is_simple_mode=true`) in
        a single call. Use `action: disassemble` to break a kit back into components;
        the resulting MO is additionally flagged with `is_disassemble=true` so it
        can be filtered out of the standard MO list.


        :::info[Required scope: `manufacturing:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        **Body fields:**

        - `kit_product_id` (int, required) — product to assemble or disassemble

        - `quantity` (numeric, required, >0) — units to produce (assemble) or consume
        (disassemble)

        - `warehouse_id` (int, required)

        - `warehouse_location_id` (int, optional)

        - `action_date` (date, required, m/d/Y or Y-m-d)

        - `action` (string, optional) — `assemble` (default) or `disassemble`


        **Response (201 Created):** Flat manufacturing order object for the newly-created
        Completed MO. The frontend uses the returned `id` to deep-link the success
        toast to the MO detail page.


        **Response (422 Unprocessable Entity — `code: component_shortage`):** Returned
        when there is not enough on-hand stock to fully allocate the components (assemble)
        or the kit (disassemble). The atomic run is rolled back, so no partial MO
        is left behind. The body carries a human-readable `message`/`error` listing
        the shortfalling lines plus a structured `shortages` array. Use `GET /simple-assemble/preview`
        first to warn before submit.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                kit_product_id:
                  type: integer
                quantity:
                  type: integer
                warehouse_id:
                  type: integer
                warehouse_location_id:
                  type: string
                  nullable: true
                action_date:
                  type: string
                action:
                  type: string
              example:
                kit_product_id: 42
                quantity: 5
                warehouse_id: 1
                warehouse_location_id: null
                action_date: '2026-05-28'
                action: assemble
      parameters: []
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: integer
                  mo_number:
                    type: string
                  status:
                    type: string
                  bom_id:
                    type: integer
                  warehouse_id:
                    type: integer
                  destination_warehouse_id:
                    type: integer
                  planned_quantity:
                    type: integer
                  completed_quantity:
                    type: integer
                  production_method:
                    type: string
                  contractor_supplier_id:
                    type: string
                    nullable: true
                  outsourced_purchase_order_id:
                    type: string
                    nullable: true
                  sales_order_id:
                    type: string
                    nullable: true
                  sales_order_line_id:
                    type: string
                    nullable: true
                  priority:
                    type: integer
                  scheduled_start:
                    type: string
                    nullable: true
                  scheduled_end:
                    type: string
                    nullable: true
                  started_at:
                    type: string
                  completed_at:
                    type: string
                  closed_at:
                    type: string
                    nullable: true
                  cancelled_at:
                    type: string
                    nullable: true
                  cancelled_reason_code:
                    type: string
                    nullable: true
                  cancelled_reason_notes:
                    type: string
                    nullable: true
                  is_simple_mode:
                    type: boolean
                  is_disassemble:
                    type: boolean
                  notes:
                    type: string
                  internal_reference:
                    type: string
                    nullable: true
                  cost_breakdown:
                    type: string
                    nullable: true
                  created_by_id:
                    type: integer
                  assigned_to_id:
                    type: string
                    nullable: true
                  created_at:
                    type: string
                  updated_at:
                    type: string
                  archived_at:
                    type: string
                    nullable: true
                example:
                  id: 15
                  mo_number: MO-000014
                  status: completed
                  bom_id: 4
                  warehouse_id: 1
                  destination_warehouse_id: 1
                  planned_quantity: 2
                  completed_quantity: 2
                  production_method: in_house
                  contractor_supplier_id: null
                  outsourced_purchase_order_id: null
                  sales_order_id: null
                  sales_order_line_id: null
                  priority: 1000
                  scheduled_start: null
                  scheduled_end: null
                  started_at: '2026-05-28T00:00:00.000000Z'
                  completed_at: '2026-05-28T00:00:00.000000Z'
                  closed_at: null
                  cancelled_at: null
                  cancelled_reason_code: null
                  cancelled_reason_notes: null
                  is_simple_mode: true
                  is_disassemble: true
                  notes: Simple Mode disassembly of QA-COFFEE-250
                  internal_reference: null
                  cost_breakdown: null
                  created_by_id: 1
                  assigned_to_id: null
                  created_at: '2026-05-28T00:00:00.000000Z'
                  updated_at: '2026-05-28T00:00:00.000000Z'
                  archived_at: null
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                  message:
                    type: string
                  code:
                    type: string
                  shortages:
                    type: array
                    items:
                      type: object
                      properties:
                        mo_component_line_id:
                          type: integer
                        product_id:
                          type: integer
                        product_sku:
                          type: string
                        product_name:
                          type: string
                        required_quantity:
                          type: number
                        allocated_quantity:
                          type: number
                        short_by_quantity:
                          type: number
                        uom_code:
                          type: string
                example:
                  error: 'Not enough stock to assemble. Short on: QA-BEAN (need 0.5
                    kg, available 0.05 kg).'
                  message: 'Not enough stock to assemble. Short on: QA-BEAN (need
                    0.5 kg, available 0.05 kg).'
                  code: component_shortage
                  shortages:
                  - mo_component_line_id: 88
                    product_id: 91
                    product_sku: QA-BEAN
                    product_name: Coffee Beans
                    required_quantity: 0.5
                    allocated_quantity: 0.05
                    short_by_quantity: 0.45
                    uom_code: kg
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: manufacturing:write
      operationId: post-api-manufacturing-simple-assemble
  /api/manufacturing/simple-assemble/preview:
    post:
      tags:
      - Simple Assembly
      summary: Preview Simple Assemble / Disassemble (Dry-Run)
      description: "U25: Dry-run preview that returns the BOM-derived components (action=assemble)\
        \ or the kit itself (action=disassemble) along with required and live on-hand\
        \ quantities at the chosen warehouse. Does NOT create an MO or consume inventory\
        \ — used to render a shortage warning beneath the Simple Mode form before\
        \ submit.\n\n:::info[Required scope: `manufacturing:write`]\nGrant this scope\
        \ to your token under [Settings → Developer → Personal Access Tokens](https://app.sku.io/settings/api).\n\
        :::\n\n**Body fields** (same validation as POST /simple-assemble):\n- `kit_product_id`\
        \ (int, required) — product to assemble or disassemble\n- `quantity` (numeric,\
        \ required, >0)\n- `warehouse_id` (int, required)\n- `warehouse_location_id`\
        \ (int, optional)\n- `action_date` (date, required)\n- `action` (string, optional)\
        \ — `assemble` (default) or `disassemble`\n\nEach line is also valued: `unit_cost`\
        \ is the weighted-average cost of the product's available FIFO layers at the\
        \ chosen warehouse (catalog cost when out of stock), and `extended_cost =\
        \ unit_cost × required_quantity`. `total_input_cost` sums the line values.\
        \ For `action=assemble`, `output` carries the expected manufactured product\
        \ valued at the full component spend (`total_cost = total_input_cost`, `unit_cost\
        \ = total_cost / quantity`); for `action=disassemble`, `output` is `null`.\n\
        \n**Response shape**:\n```json\n{\n  \"data\": {\n    \"action\": \"assemble\"\
        ,\n    \"has_shortage\": true,\n    \"total_input_cost\": 36,\n    \"output\"\
        : {\n      \"product_id\": 42,\n      \"sku\": \"KIT-001\",\n      \"name\"\
        : \"Sample Kit\",\n      \"quantity\": 3,\n      \"total_cost\": 36,\n   \
        \   \"unit_cost\": 12\n    },\n    \"lines\": [\n      {\n        \"product_id\"\
        : 91,\n        \"sku\": \"COMP-A\",\n        \"name\": \"Component A\",\n\
        \        \"required_quantity\": 6,\n        \"available_quantity\": 5,\n \
        \       \"uom\": \"EACH\",\n        \"unit_cost\": 5,\n        \"extended_cost\"\
        : 30,\n        \"shortage\": true\n      }\n    ]\n  }\n}\n```"
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                kit_product_id:
                  type: integer
                quantity:
                  type: integer
                warehouse_id:
                  type: integer
                warehouse_location_id:
                  type: string
                  nullable: true
                action_date:
                  type: string
                action:
                  type: string
              example:
                kit_product_id: 42
                quantity: 5
                warehouse_id: 1
                warehouse_location_id: null
                action_date: '2026-05-28'
                action: assemble
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 OK — assemble preview with shortage
                  value:
                    data:
                      action: assemble
                      has_shortage: true
                      total_input_cost: 36
                      output:
                        product_id: 42
                        sku: KIT-001
                        name: Sample Kit
                        quantity: 3
                        total_cost: 36
                        unit_cost: 12
                      lines:
                      - product_id: 91
                        sku: COMP-A
                        name: Component A
                        required_quantity: 6
                        available_quantity: 5
                        uom: EACH
                        unit_cost: 5
                        extended_cost: 30
                        shortage: true
                      - product_id: 92
                        sku: COMP-B
                        name: Component B
                        required_quantity: 3
                        available_quantity: 12
                        uom: EACH
                        unit_cost: 2
                        extended_cost: 6
                        shortage: false
                example-1:
                  summary: 200 OK — disassemble preview
                  value:
                    data:
                      action: disassemble
                      has_shortage: true
                      total_input_cost: 8.5
                      output: null
                      lines:
                      - product_id: 42
                        sku: KIT-001
                        name: Sample Kit
                        required_quantity: 1
                        available_quantity: 0
                        uom: EACH
                        unit_cost: 8.5
                        extended_cost: 8.5
                        shortage: true
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      kit_product_id:
                        type: array
                        items:
                          type: string
                      quantity:
                        type: array
                        items:
                          type: string
                      warehouse_id:
                        type: array
                        items:
                          type: string
                      action_date:
                        type: array
                        items:
                          type: string
                example:
                  message: The kit product id field is required. (and 3 more errors)
                  errors:
                    kit_product_id:
                    - The kit product id field is required.
                    quantity:
                    - The quantity field is required.
                    warehouse_id:
                    - The warehouse id field is required.
                    action_date:
                    - The action date field is required.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: manufacturing:write
      operationId: post-api-manufacturing-simple-assemble-preview
  /api/manufacturing/work-centers:
    get:
      tags:
      - Work Centers
      summary: List Work Centers
      parameters:
      - name: per_page
        in: query
        schema:
          type: integer
        example: '25'
        description: Results per page (default 10).
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: manufacturing:read
      description: 'List Work Centers


        :::info[Required scope: `manufacturing:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      operationId: get-api-manufacturing-work-centers
    post:
      tags:
      - Work Centers
      summary: Create Work Center
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                code:
                  type: string
                default_hourly_rate:
                  type: integer
                default_operator_id:
                  type: string
                  nullable: true
                overhead_rate_percent:
                  type: integer
                capacity_hours_per_day:
                  type: integer
                is_active:
                  type: boolean
              example:
                name: Mixing Station
                code: WC-MIX-01
                default_hourly_rate: 45
                default_operator_id: null
                overhead_rate_percent: 15
                capacity_hours_per_day: 8
                is_active: true
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: manufacturing:write
      description: 'Create Work Center


        :::info[Required scope: `manufacturing:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      operationId: post-api-manufacturing-work-centers
    delete:
      tags:
      - Work Centers
      summary: Bulk Delete Work Centers
      description: 'Permanently delete multiple work centers in one call.

        Auth: requires Bearer token.

        Body: ids (required, array of work center ids, min 1). Rows that fail to delete
        are counted in failCount instead of aborting the batch.


        :::info[Required scope: `manufacturing:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      totalCount:
                        type: integer
                      failCount:
                        type: integer
                example:
                  message: Deleted 2 work center(s)
                  data:
                    totalCount: 2
                    failCount: 0
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      ids:
                        type: array
                        items:
                          type: string
                example:
                  message: The ids field is required.
                  errors:
                    ids:
                    - The ids field is required.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: manufacturing:write
      operationId: delete-api-manufacturing-work-centers
  /api/manufacturing/work-centers/active:
    get:
      tags:
      - Work Centers
      summary: List Active Work Centers
      description: 'Non-paginated list of active work centers. Used for dropdowns
        on BOM operation editors.


        :::info[Required scope: `manufacturing:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: manufacturing:read
      operationId: get-api-manufacturing-work-centers-active
  /api/manufacturing/work-centers/{id}:
    get:
      tags:
      - Work Centers
      summary: Get Work Center
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: manufacturing:read
      description: 'Get Work Center


        :::info[Required scope: `manufacturing:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      operationId: get-api-manufacturing-work-centers-id
    put:
      tags:
      - Work Centers
      summary: Update Work Center
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                default_hourly_rate:
                  type: integer
                is_active:
                  type: boolean
              example:
                name: Mixing Station (updated)
                default_hourly_rate: 50
                is_active: true
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: manufacturing:write
      description: 'Update Work Center


        :::info[Required scope: `manufacturing:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      operationId: put-api-manufacturing-work-centers-id
    delete:
      tags:
      - Work Centers
      summary: Delete Work Center
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: manufacturing:write
      description: 'Delete Work Center


        :::info[Required scope: `manufacturing:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      operationId: delete-api-manufacturing-work-centers-id
  /api/manufacturing/contractors:
    get:
      tags:
      - Contractors
      summary: List Contractors
      description: 'List suppliers flagged as manufacturing contractors, with their
        default contractor warehouse and default outsourced cost basis (toll | hybrid,
        null when not set).


        :::info[Required scope: `manufacturing:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: array
                items:
                  type: object
                  properties:
                    id:
                      type: integer
                    name:
                      type: string
                    email:
                      type: string
                    phone:
                      type: string
                    is_manufacturing_contractor:
                      type: boolean
                    contractor_default_warehouse_id:
                      type: integer
                    default_outsourced_cost_basis:
                      type: string
                    virtual_warehouse:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                    active_mo_count:
                      type: integer
                    total_mo_count:
                      type: integer
                example:
                - id: 12
                  name: Acme Assembly Co
                  email: ops@acmeassembly.com
                  phone: +1-555-0142
                  is_manufacturing_contractor: true
                  contractor_default_warehouse_id: 9
                  default_outsourced_cost_basis: toll
                  virtual_warehouse:
                    id: 9
                    name: Acme Assembly Co (Contractor)
                  active_mo_count: 2
                  total_mo_count: 14
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: manufacturing:read
      operationId: get-api-manufacturing-contractors
    post:
      tags:
      - Contractors
      summary: Create Contractor
      description: 'Designate an existing supplier as a manufacturing contractor for
        outsourced production. Provisions a virtual warehouse that holds the stock
        issued to the contractor for its manufacturing orders.

        Auth: requires Bearer token.

        Body: supplier_id (required, integer, existing supplier id); virtual_warehouse_name
        (optional, string, max 255) - name for the contractor''s virtual warehouse,
        a default is generated when omitted; default_outsourced_cost_basis (optional,
        string, one of: toll, hybrid) - default cost basis applied to new outsourced
        manufacturing orders for this contractor. Use toll when you own all component
        materials and the contractor only charges for processing (the contractor''s
        product charge is treated as a processing cost, not added on top of your component
        costs). Use hybrid when the contractor supplies materials of their own beyond
        the components you provide (their charge is capitalized into the output cost).
        Omit or null to fall back to hybrid.


        :::info[Required scope: `manufacturing:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                supplier_id:
                  type: integer
                virtual_warehouse_name:
                  type: string
                default_outsourced_cost_basis:
                  type: string
              example:
                supplier_id: 12
                virtual_warehouse_name: Acme Assembly Co (Contractor)
                default_outsourced_cost_basis: toll
      parameters: []
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: integer
                  name:
                    type: string
                  email:
                    type: string
                  phone:
                    type: string
                  is_manufacturing_contractor:
                    type: boolean
                  contractor_default_warehouse_id:
                    type: integer
                  default_outsourced_cost_basis:
                    type: string
                  virtual_warehouse:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                  active_mo_count:
                    type: integer
                  total_mo_count:
                    type: integer
                example:
                  id: 12
                  name: Acme Assembly Co
                  email: ops@acmeassembly.com
                  phone: +1-555-0142
                  is_manufacturing_contractor: true
                  contractor_default_warehouse_id: 9
                  default_outsourced_cost_basis: toll
                  virtual_warehouse:
                    id: 9
                    name: Acme Assembly Co (Contractor)
                  active_mo_count: 0
                  total_mo_count: 0
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      supplier_id:
                        type: array
                        items:
                          type: string
                example:
                  message: The supplier id field is required.
                  errors:
                    supplier_id:
                    - The supplier id field is required.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: manufacturing:write
      operationId: post-api-manufacturing-contractors
  /api/manufacturing/contractors/{supplier}:
    patch:
      tags:
      - Contractors
      summary: Update Contractor
      description: 'Update a contractor''s manufacturing settings.

        Auth: requires Bearer token.

        Path param: supplier = supplier id.

        Body: default_outsourced_cost_basis (optional, string, one of: toll, hybrid)
        - default cost basis applied to new outsourced manufacturing orders for this
        contractor. Use toll when you own all component materials and the contractor
        only charges for processing (the contractor''s product charge is treated as
        a processing cost, not added on top of your component costs). Use hybrid when
        the contractor supplies materials of their own beyond the components you provide
        (their charge is capitalized into the output cost). Omit or null to fall back
        to hybrid.

        Send null to clear the setting (new outsourced orders then fall back to hybrid).
        Changing the default does not alter existing manufacturing orders; each order
        may also set its own outsourced_cost_basis override at creation.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                default_outsourced_cost_basis:
                  type: string
              example:
                default_outsourced_cost_basis: toll
      parameters:
      - name: supplier
        in: path
        schema:
          type: integer
        required: true
        example: '12'
        description: The supplier ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: integer
                  name:
                    type: string
                  email:
                    type: string
                  phone:
                    type: string
                  is_manufacturing_contractor:
                    type: boolean
                  contractor_default_warehouse_id:
                    type: integer
                  default_outsourced_cost_basis:
                    type: string
                  virtual_warehouse:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                  active_mo_count:
                    type: integer
                  total_mo_count:
                    type: integer
                example:
                  id: 12
                  name: Acme Assembly Co
                  email: ops@acmeassembly.com
                  phone: +1-555-0142
                  is_manufacturing_contractor: true
                  contractor_default_warehouse_id: 9
                  default_outsourced_cost_basis: toll
                  virtual_warehouse:
                    id: 9
                    name: Acme Assembly Co (Contractor)
                  active_mo_count: 0
                  total_mo_count: 0
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      default_outsourced_cost_basis:
                        type: array
                        items:
                          type: string
                example:
                  message: The selected default outsourced cost basis is invalid.
                  errors:
                    default_outsourced_cost_basis:
                    - The selected default outsourced cost basis is invalid.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: patch-api-manufacturing-contractors-supplier
    delete:
      tags:
      - Contractors
      summary: Delete Contractor
      description: 'Remove the manufacturing-contractor designation from a supplier.
        The supplier record itself is not deleted. Fails with 409 while the contractor
        still has active manufacturing orders.

        Auth: requires Bearer token.

        Path param: supplier = supplier id.


        :::info[Required scope: `manufacturing:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: supplier
        in: path
        schema:
          type: integer
        required: true
        example: '12'
        description: The supplier ID.
      responses:
        '204':
          description: No Content
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties: {}
                example: {}
        '409':
          description: Conflict
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Cannot deactivate contractor while active manufacturing
                    orders exist.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: manufacturing:write
      operationId: delete-api-manufacturing-contractors-supplier
  /api/manufacturing/units-of-measure:
    get:
      tags:
      - Units of Measure
      summary: List Units of Measure
      description: 'List every unit of measure, ordered by type then code. Includes
        both system-defined units (is_system=true, read-only) and custom units.

        Auth: requires Bearer token.


        :::info[Required scope: `manufacturing:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        code:
                          type: string
                        name:
                          type: string
                        uom_type:
                          type: string
                        is_system:
                          type: boolean
                example:
                  data:
                  - id: 12
                    code: BOX12
                    name: Box of 12
                    uom_type: count
                    is_system: false
                  - id: 1
                    code: EA
                    name: Each
                    uom_type: count
                    is_system: true
                  - id: 7
                    code: KG
                    name: Kilogram
                    uom_type: weight
                    is_system: true
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: manufacturing:read
      operationId: get-api-manufacturing-units-of-measure
    post:
      tags:
      - Units of Measure
      summary: Create Unit of Measure
      description: 'Create a custom unit of measure.

        Auth: requires Bearer token.

        Body: code (required, string, max 16, unique - stored uppercased); name (required,
        string, max 64); uom_type (required, one of: weight, volume, count).


        :::info[Required scope: `manufacturing:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                code:
                  type: string
                name:
                  type: string
                uom_type:
                  type: string
              example:
                code: BOX12
                name: Box of 12
                uom_type: count
      parameters: []
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: integer
                  code:
                    type: string
                  name:
                    type: string
                  uom_type:
                    type: string
                  is_system:
                    type: boolean
                example:
                  id: 12
                  code: BOX12
                  name: Box of 12
                  uom_type: count
                  is_system: false
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      code:
                        type: array
                        items:
                          type: string
                example:
                  message: The code has already been taken.
                  errors:
                    code:
                    - The code has already been taken.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: manufacturing:write
      operationId: post-api-manufacturing-units-of-measure
  /api/manufacturing/units-of-measure/{unitOfMeasure}:
    get:
      tags:
      - Units of Measure
      summary: Get Unit of Measure
      description: 'Get a single unit of measure by id.

        Auth: requires Bearer token.

        Path param: unitOfMeasure = unit of measure id.


        :::info[Required scope: `manufacturing:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: unitOfMeasure
        in: path
        schema:
          type: integer
        required: true
        example: '12'
        description: The unit of measure ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: integer
                  code:
                    type: string
                  name:
                    type: string
                  uom_type:
                    type: string
                  is_system:
                    type: boolean
                example:
                  id: 12
                  code: BOX12
                  name: Box of 12
                  uom_type: count
                  is_system: false
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: manufacturing:read
      operationId: get-api-manufacturing-units-of-measure-unitofmeasure
    put:
      tags:
      - Units of Measure
      summary: Update Unit of Measure
      description: 'Update a custom unit of measure. All fields are optional - only
        submitted fields change.

        Auth: requires Bearer token.

        Path param: unitOfMeasure = unit of measure id.

        Body: code (string, max 16, unique - stored uppercased); name (string, max
        64); uom_type (one of: weight, volume, count).

        System units of measure (is_system=true) cannot be modified and return 422.


        :::info[Required scope: `manufacturing:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
              example:
                name: Box of Twelve
      parameters:
      - name: unitOfMeasure
        in: path
        schema:
          type: integer
        required: true
        example: '12'
        description: The unit of measure ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: integer
                  code:
                    type: string
                  name:
                    type: string
                  uom_type:
                    type: string
                  is_system:
                    type: boolean
                example:
                  id: 12
                  code: BOX12
                  name: Box of Twelve
                  uom_type: count
                  is_system: false
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: System units of measure cannot be modified.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: manufacturing:write
      operationId: put-api-manufacturing-units-of-measure-unitofmeasure
    delete:
      tags:
      - Units of Measure
      summary: Delete Unit of Measure
      description: 'Delete a custom unit of measure. System units cannot be deleted,
        and units still referenced by product configurations, BOM lines, or manufacturing
        order lines return 422 with the reference count.

        Auth: requires Bearer token.

        Path param: unitOfMeasure = unit of measure id.


        :::info[Required scope: `manufacturing:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: unitOfMeasure
        in: path
        schema:
          type: integer
        required: true
        example: '12'
        description: The unit of measure ID.
      responses:
        '204':
          description: No Content
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties: {}
                example: {}
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: This unit of measure is referenced by 3 record(s) and cannot
                    be deleted.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: manufacturing:write
      operationId: delete-api-manufacturing-units-of-measure-unitofmeasure
  /api/manufacturing/products/{product}/units-of-measure:
    get:
      tags:
      - Units of Measure
      summary: List Product Units of Measure
      description: 'List the unit-of-measure configuration for a product: which unit
        is the stock unit, which are used for purchasing and sales, and the conversion
        factor of each unit into stock units.

        Auth: requires Bearer token.

        Path param: product = product id.


        :::info[Required scope: `manufacturing:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: product
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The product ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        product_id:
                          type: integer
                        uom_id:
                          type: integer
                        unit_of_measure:
                          type: object
                          properties:
                            id:
                              type: integer
                            code:
                              type: string
                            name:
                              type: string
                            uom_type:
                              type: string
                            is_system:
                              type: boolean
                        is_stock_uom:
                          type: boolean
                        is_purchase_uom:
                          type: boolean
                        is_sales_uom:
                          type: boolean
                        conversion_factor:
                          type: integer
                        display_precision:
                          type: integer
                example:
                  data:
                  - id: 41
                    product_id: 1
                    uom_id: 1
                    unit_of_measure:
                      id: 1
                      code: EA
                      name: Each
                      uom_type: count
                      is_system: true
                    is_stock_uom: true
                    is_purchase_uom: false
                    is_sales_uom: false
                    conversion_factor: 1
                    display_precision: 0
                  - id: 42
                    product_id: 1
                    uom_id: 12
                    unit_of_measure:
                      id: 12
                      code: BOX12
                      name: Box of 12
                      uom_type: count
                      is_system: false
                    is_stock_uom: false
                    is_purchase_uom: true
                    is_sales_uom: true
                    conversion_factor: 12
                    display_precision: 0
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: manufacturing:read
      operationId: get-api-manufacturing-products-product-units-of-measure
    put:
      tags:
      - Units of Measure
      summary: Update Product Units of Measure
      description: 'Replace the product''s full unit-of-measure configuration in one
        call. Exactly one row must be the stock unit with conversion_factor 1; at
        most one purchase unit and at most one sales unit are allowed.

        Auth: requires Bearer token.

        Path param: product = product id.

        Body: units_of_measure (required, array, min 1). Per row: uom_id (required,
        existing unit id); conversion_factor (required, numeric, greater than 0 -
        how many stock units one of this unit represents); display_precision (optional,
        integer 0-8); is_stock_uom / is_purchase_uom / is_sales_uom (optional booleans).


        :::info[Required scope: `manufacturing:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                units_of_measure:
                  type: array
                  items:
                    type: object
                    properties:
                      uom_id:
                        type: integer
                      conversion_factor:
                        type: integer
                      is_stock_uom:
                        type: boolean
              example:
                units_of_measure:
                - uom_id: 1
                  conversion_factor: 1
                  is_stock_uom: true
                - uom_id: 12
                  conversion_factor: 12
                  is_purchase_uom: true
                  is_sales_uom: true
                  display_precision: 0
      parameters:
      - name: product
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The product ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        product_id:
                          type: integer
                        uom_id:
                          type: integer
                        unit_of_measure:
                          type: object
                          properties:
                            id:
                              type: integer
                            code:
                              type: string
                            name:
                              type: string
                            uom_type:
                              type: string
                            is_system:
                              type: boolean
                        is_stock_uom:
                          type: boolean
                        is_purchase_uom:
                          type: boolean
                        is_sales_uom:
                          type: boolean
                        conversion_factor:
                          type: integer
                        display_precision:
                          type: integer
                example:
                  data:
                  - id: 41
                    product_id: 1
                    uom_id: 1
                    unit_of_measure:
                      id: 1
                      code: EA
                      name: Each
                      uom_type: count
                      is_system: true
                    is_stock_uom: true
                    is_purchase_uom: false
                    is_sales_uom: false
                    conversion_factor: 1
                    display_precision: 0
                  - id: 42
                    product_id: 1
                    uom_id: 12
                    unit_of_measure:
                      id: 12
                      code: BOX12
                      name: Box of 12
                      uom_type: count
                      is_system: false
                    is_stock_uom: false
                    is_purchase_uom: true
                    is_sales_uom: true
                    conversion_factor: 12
                    display_precision: 0
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Exactly one unit of measure must be marked as the stock
                    unit.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: manufacturing:write
      operationId: put-api-manufacturing-products-product-units-of-measure
  /api/manufacturing/products/{product}/units-of-measure/enable:
    post:
      tags:
      - Units of Measure
      summary: Enable Product Unit of Measure
      description: 'Idempotently enable a single unit of measure for a product so
        a bill-of-materials or manufacturing-order line referencing it can be saved
        without first configuring the full unit-of-measure set. The unit is added
        as a pending alternate with no conversion factor (0), which lets draft documents
        validate; a real conversion factor must still be set before the bill of materials
        can be activated. Calling this repeatedly for the same unit is safe and returns
        the existing configuration untouched.

        Auth: requires Bearer token.

        Path param: product = product id.

        Body: uom_id = id of the unit of measure to enable (must exist).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                uom_id:
                  type: integer
              example:
                uom_id: 12
      parameters:
      - name: product
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The product ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      product_id:
                        type: integer
                      uom_id:
                        type: integer
                      unit_of_measure:
                        type: object
                        properties:
                          id:
                            type: integer
                          code:
                            type: string
                          name:
                            type: string
                          uom_type:
                            type: string
                          is_system:
                            type: boolean
                      is_stock_uom:
                        type: boolean
                      is_purchase_uom:
                        type: boolean
                      is_sales_uom:
                        type: boolean
                      conversion_factor:
                        type: integer
                      display_precision:
                        type: integer
                      has_transactional_history:
                        type: boolean
                example:
                  data:
                    id: 43
                    product_id: 1
                    uom_id: 12
                    unit_of_measure:
                      id: 12
                      code: BOX12
                      name: Box of 12
                      uom_type: count
                      is_system: false
                    is_stock_uom: false
                    is_purchase_uom: false
                    is_sales_uom: false
                    conversion_factor: 0
                    display_precision: 2
                    has_transactional_history: false
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      uom_id:
                        type: array
                        items:
                          type: string
                example:
                  message: The selected unit of measure does not exist.
                  errors:
                    uom_id:
                    - The selected unit of measure does not exist.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-manufacturing-products-product-units-of-measure-enable
  /api/manufacturing/scheduler/scheduled:
    get:
      tags:
      - Scheduler
      summary: List Scheduled Manufacturing Orders
      description: 'Returns MOs with a scheduled_start within the date range. Non-paginated
        response shaped as `{ data, from, to, include_unscheduled, status, warehouse_ids
        }`.


        :::info[Required scope: `manufacturing:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        **Show Unscheduled (U19 / U41):** Pass `include_unscheduled=1` (default) to
        include MOs that have a priority value but no `scheduled_start` — these appear
        in the application UI Production Scheduler''s Priority Queue sidebar so users
        can clear the production backlog. Pass `include_unscheduled=0` to restrict
        the response to MOs whose `scheduled_start` falls inside the `from`/`to` date
        range.


        **Status filter (U40):** Pass `status[]=draft&status[]=in_progress` (or comma-separated
        `status=draft,in_progress`) to restrict the timeline to specific MO statuses.
        Allowed values: `draft`, `confirmed`, `in_progress`, `partially_completed`.
        Unknown values are dropped; if nothing valid remains the filter falls back
        to all four active statuses. Omit to include all four.


        **Warehouse filter (U40):** Pass `warehouse_ids[]=5&warehouse_ids[]=7` (or
        comma-separated `warehouse_ids=5,7`) to restrict the timeline to MOs whose
        production warehouse OR destination warehouse matches one of the listed IDs.
        Non-numeric / zero / negative values are dropped. Omit to include all warehouses.


        The top-level `include_unscheduled`, `status`, and `warehouse_ids` fields
        in the response echo the resolved filters that were applied.


        **Primary output name:** `primary_output_name` resolves from the MO output
        lines. Draft MOs have no materialized output lines yet (they are created from
        the BOM at confirm time), so for drafts the value falls back to the BOM''s
        primary output product — the Priority Queue never shows a blank output for
        a valid MO.'
      parameters:
      - name: from
        in: query
        schema:
          type: string
        description: Start date (inclusive) for scheduled_start. Defaults to today's
          start-of-day when omitted.
        example: '2026-04-01'
      - name: to
        in: query
        schema:
          type: string
        description: End date (inclusive) for scheduled_start. Defaults to today +
          30 days end-of-day when omitted.
        example: '2026-04-30'
      - name: include_unscheduled
        in: query
        schema:
          type: integer
        description: 'Include MOs with priority but no scheduled_start (U19 / U41).
          Default: 1 (true). Accepts truthy values 1, true, yes, on. Set to 0 / false
          to restrict the response to MOs whose scheduled_start falls inside the from/to
          range.'
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        mo_number:
                          type: string
                        status:
                          type: string
                        bom_id:
                          type: integer
                        bom_name:
                          type: string
                        warehouse_id:
                          type: integer
                        warehouse_name:
                          type: string
                        destination_warehouse_id:
                          type: integer
                        destination_warehouse_name:
                          type: string
                        primary_output_name:
                          type: string
                        planned_quantity:
                          type: string
                        completed_quantity:
                          type: string
                        production_method:
                          type: string
                        contractor_supplier_id:
                          type: string
                          nullable: true
                        contractor_supplier_name:
                          type: string
                          nullable: true
                        outsourced_purchase_order_id:
                          type: string
                          nullable: true
                        sales_order_id:
                          type: string
                          nullable: true
                        sales_order_line_id:
                          type: string
                          nullable: true
                        priority:
                          type: integer
                        scheduled_start:
                          type: string
                        scheduled_end:
                          type: string
                        started_at:
                          type: string
                        completed_at:
                          type: string
                          nullable: true
                        closed_at:
                          type: string
                          nullable: true
                        cancelled_at:
                          type: string
                          nullable: true
                        is_simple_mode:
                          type: boolean
                        internal_reference:
                          type: string
                        assigned_to_id:
                          type: integer
                        assigned_to:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        cost_breakdown:
                          type: object
                          properties:
                            materials:
                              type: string
                            labor:
                              type: string
                            overhead:
                              type: string
                            fixed:
                              type: string
                        has_shortage:
                          type: boolean
                        created_at:
                          type: string
                        updated_at:
                          type: string
                        archived_at:
                          type: string
                          nullable: true
                  from:
                    type: string
                  to:
                    type: string
                  include_unscheduled:
                    type: boolean
                  status:
                    type: array
                    items:
                      type: string
                  warehouse_ids:
                    type: array
                    items:
                      type: integer
                example:
                  data:
                  - id: 1042
                    mo_number: MO-001042
                    status: in_progress
                    bom_id: 318
                    bom_name: Widget Assembly v3
                    warehouse_id: 5
                    warehouse_name: Main Production
                    destination_warehouse_id: 5
                    destination_warehouse_name: Main Production
                    primary_output_name: Widget Output
                    planned_quantity: '100.000000'
                    completed_quantity: '42.000000'
                    production_method: in_house
                    contractor_supplier_id: null
                    contractor_supplier_name: null
                    outsourced_purchase_order_id: null
                    sales_order_id: null
                    sales_order_line_id: null
                    priority: 1
                    scheduled_start: '2026-04-05T08:00:00+00:00'
                    scheduled_end: '2026-04-07T17:00:00+00:00'
                    started_at: '2026-04-05T08:15:00+00:00'
                    completed_at: null
                    closed_at: null
                    cancelled_at: null
                    is_simple_mode: false
                    internal_reference: REF-Q2-001
                    assigned_to_id: 12
                    assigned_to:
                      id: 12
                      name: Jane Doe
                    cost_breakdown:
                      materials: '1240.50'
                      labor: '320.00'
                      overhead: '85.00'
                      fixed: '25.00'
                    has_shortage: false
                    created_at: '2026-03-28T14:22:11+00:00'
                    updated_at: '2026-04-05T08:15:00+00:00'
                    archived_at: null
                  - id: 1058
                    mo_number: MO-001058
                    status: draft
                    bom_id: 412
                    bom_name: Gadget Pro Kit
                    warehouse_id: 5
                    warehouse_name: Main Production
                    destination_warehouse_id: 7
                    destination_warehouse_name: Downtown DC
                    primary_output_name: Gadget Pro
                    planned_quantity: '50.000000'
                    completed_quantity: '0.000000'
                    production_method: outsourced
                    contractor_supplier_id: 22
                    contractor_supplier_name: Acme Contracting Co.
                    outsourced_purchase_order_id: 9871
                    sales_order_id: null
                    sales_order_line_id: null
                    priority: 5
                    scheduled_start: null
                    scheduled_end: null
                    started_at: null
                    completed_at: null
                    closed_at: null
                    cancelled_at: null
                    is_simple_mode: false
                    internal_reference: null
                    assigned_to_id: null
                    assigned_to: null
                    cost_breakdown: null
                    has_shortage: true
                    created_at: '2026-04-01T09:10:33+00:00'
                    updated_at: '2026-04-01T09:10:33+00:00'
                    archived_at: null
                  from: '2026-04-01T00:00:00+00:00'
                  to: '2026-04-30T23:59:59+00:00'
                  include_unscheduled: true
                  status:
                  - draft
                  - in_progress
                  warehouse_ids:
                  - 5
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: manufacturing:read
      operationId: get-api-manufacturing-scheduler-scheduled
  /api/manufacturing/scheduler/reprioritize:
    put:
      tags:
      - Scheduler
      summary: Reprioritize Manufacturing Orders
      description: 'Bulk update MO priorities after a drag-and-drop reorder on the
        scheduler board. Each MO whose priority actually changes records a `priority_changed`
        event on its Manufacturing Order event timeline (with `from_priority` / `to_priority`
        in the payload); entries whose priority is unchanged are skipped and not counted
        in `updated`.


        :::info[Required scope: `manufacturing:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                items:
                  type: array
                  items:
                    type: object
                    properties:
                      id:
                        type: integer
                      priority:
                        type: integer
              example:
                items:
                - id: 1
                  priority: 10
                - id: 2
                  priority: 20
                - id: 3
                  priority: 30
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      updated:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    updated: 3
                  message: Priorities updated.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: manufacturing:write
      operationId: put-api-manufacturing-scheduler-reprioritize
  /api/manufacturing/manufacturing-orders/{id}/reschedule:
    put:
      tags:
      - Scheduler
      summary: Reschedule MO
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                scheduled_start:
                  type: string
                scheduled_end:
                  type: string
              example:
                scheduled_start: '2026-04-25'
                scheduled_end: '2026-04-27'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: manufacturing:write
      description: 'Reschedule MO


        :::info[Required scope: `manufacturing:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      operationId: put-api-manufacturing-manufacturing-orders-id-reschedule
  /api/manufacturing/demand-suggestions:
    get:
      tags:
      - Demand Suggestions
      summary: List Demand Suggestions
      parameters:
      - name: per_page
        in: query
        schema:
          type: integer
        example: '25'
        description: Results per page (default 10).
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: manufacturing:read
      description: 'List Demand Suggestions


        :::info[Required scope: `manufacturing:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      operationId: get-api-manufacturing-demand-suggestions
  /api/manufacturing/demand-suggestions/generate:
    post:
      tags:
      - Demand Suggestions
      summary: Generate Demand Suggestions
      description: 'Regenerate the pending demand suggestions from current inventory
        + sales state and return them. PERSISTS: existing pending rows are replaced;
        confirmed and dismissed suggestions are preserved. Body params: `look_back_days`
        (int, default 30) — sales-history window used to compute velocity; `safety_days`
        (int, default 7) — safety-stock buffer added to the need. Response: `{ data:
        [DemandSuggestion], message: "N suggestions generated", look_back_days, safety_days
        }`.


        :::info[Required scope: `manufacturing:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                look_back_days:
                  type: integer
                safety_days:
                  type: integer
              example:
                look_back_days: 30
                safety_days: 7
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: manufacturing:write
      operationId: post-api-manufacturing-demand-suggestions-generate
  /api/manufacturing/demand-suggestions/{demandSuggestion}:
    patch:
      tags:
      - Demand Suggestions
      summary: Update Demand Suggestion
      description: 'Update the suggested quantity on a pending demand suggestion.

        Auth: requires Bearer token.

        Path param: demandSuggestion = demand suggestion id.

        Body: suggested_qty (required, numeric, greater than 0).

        Only pending suggestions can be edited - confirmed or dismissed suggestions
        return 422.


        :::info[Required scope: `manufacturing:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                suggested_qty:
                  type: integer
              example:
                suggested_qty: 150
      parameters:
      - name: demandSuggestion
        in: path
        schema:
          type: integer
        required: true
        example: '31'
        description: The demand suggestion ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      product_id:
                        type: integer
                      product:
                        type: object
                        properties:
                          id:
                            type: integer
                          sku:
                            type: string
                          name:
                            type: string
                      bom_id:
                        type: integer
                      bom:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      suggested_qty:
                        type: integer
                      on_hand:
                        type: integer
                      days_of_supply:
                        type: number
                      reason:
                        type: string
                      status:
                        type: string
                      confirmed_at:
                        type: string
                        nullable: true
                      dismissed_at:
                        type: string
                        nullable: true
                      confirmed_manufacturing_order_id:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 31
                    product_id: 1
                    product:
                      id: 1
                      sku: KIT-A
                      name: Widget Kit A
                    bom_id: 15
                    bom:
                      id: 15
                      name: Default Recipe
                    suggested_qty: 150
                    on_hand: 12
                    days_of_supply: 2.5
                    reason: Projected to run out in 2.5 days based on recent sales
                      velocity
                    status: pending
                    confirmed_at: null
                    dismissed_at: null
                    confirmed_manufacturing_order_id: null
                    created_at: '2026-06-30T02:00:00.000000Z'
                    updated_at: '2026-07-01T14:22:09.000000Z'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Only pending suggestions can be updated.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: manufacturing:write
      operationId: patch-api-manufacturing-demand-suggestions-demandsuggestion
  /api/manufacturing/demand-suggestions/{demandSuggestion}/confirm:
    post:
      tags:
      - Demand Suggestions
      summary: Confirm Demand Suggestion
      description: 'Confirm a pending demand suggestion. Creates a Draft manufacturing
        order from the suggestion''s BOM and suggested quantity, and links it via
        confirmed_manufacturing_order_id.

        Auth: requires Bearer token.

        Path param: demandSuggestion = demand suggestion id.

        Returns 422 when the suggestion is not pending or has no default BOM.


        :::info[Required scope: `manufacturing:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters:
      - name: demandSuggestion
        in: path
        schema:
          type: integer
        required: true
        example: '31'
        description: The demand suggestion ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      product_id:
                        type: integer
                      product:
                        type: object
                        properties:
                          id:
                            type: integer
                          sku:
                            type: string
                          name:
                            type: string
                      bom_id:
                        type: integer
                      bom:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      suggested_qty:
                        type: integer
                      on_hand:
                        type: integer
                      days_of_supply:
                        type: number
                      reason:
                        type: string
                      status:
                        type: string
                      confirmed_at:
                        type: string
                      dismissed_at:
                        type: string
                        nullable: true
                      confirmed_manufacturing_order_id:
                        type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 31
                    product_id: 1
                    product:
                      id: 1
                      sku: KIT-A
                      name: Widget Kit A
                    bom_id: 15
                    bom:
                      id: 15
                      name: Default Recipe
                    suggested_qty: 150
                    on_hand: 12
                    days_of_supply: 2.5
                    reason: Projected to run out in 2.5 days based on recent sales
                      velocity
                    status: confirmed
                    confirmed_at: '2026-07-01T14:22:09.000000Z'
                    dismissed_at: null
                    confirmed_manufacturing_order_id: 57
                    created_at: '2026-06-30T02:00:00.000000Z'
                    updated_at: '2026-07-01T14:22:09.000000Z'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Cannot confirm a suggestion without a default BOM.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: manufacturing:write
      operationId: post-api-manufacturing-demand-suggestions-demandsuggestion-confirm
  /api/manufacturing/demand-suggestions/{demandSuggestion}/dismiss:
    post:
      tags:
      - Demand Suggestions
      summary: Dismiss Demand Suggestion
      description: 'Dismiss a pending demand suggestion so it no longer appears as
        actionable. Dismissed suggestions are preserved and are not recreated by the
        next generation run.

        Auth: requires Bearer token.

        Path param: demandSuggestion = demand suggestion id.

        Returns 422 when the suggestion is not pending.


        :::info[Required scope: `manufacturing:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters:
      - name: demandSuggestion
        in: path
        schema:
          type: integer
        required: true
        example: '31'
        description: The demand suggestion ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      product_id:
                        type: integer
                      product:
                        type: object
                        properties:
                          id:
                            type: integer
                          sku:
                            type: string
                          name:
                            type: string
                      bom_id:
                        type: integer
                      bom:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      suggested_qty:
                        type: integer
                      on_hand:
                        type: integer
                      days_of_supply:
                        type: number
                      reason:
                        type: string
                      status:
                        type: string
                      confirmed_at:
                        type: string
                        nullable: true
                      dismissed_at:
                        type: string
                      confirmed_manufacturing_order_id:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 31
                    product_id: 1
                    product:
                      id: 1
                      sku: KIT-A
                      name: Widget Kit A
                    bom_id: 15
                    bom:
                      id: 15
                      name: Default Recipe
                    suggested_qty: 150
                    on_hand: 12
                    days_of_supply: 2.5
                    reason: Projected to run out in 2.5 days based on recent sales
                      velocity
                    status: dismissed
                    confirmed_at: null
                    dismissed_at: '2026-07-01T14:22:09.000000Z'
                    confirmed_manufacturing_order_id: null
                    created_at: '2026-06-30T02:00:00.000000Z'
                    updated_at: '2026-07-01T14:22:09.000000Z'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Only pending suggestions can be updated.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: manufacturing:write
      operationId: post-api-manufacturing-demand-suggestions-demandsuggestion-dismiss
  /api/manufacturing/demand-suggestions/bulk/confirm:
    post:
      tags:
      - Demand Suggestions
      summary: Bulk Confirm Demand Suggestions
      description: 'Confirm multiple pending demand suggestions in one call - each
        confirmed suggestion gets its own Draft manufacturing order. Suggestions that
        are not pending or have no default BOM are skipped silently; only the confirmed
        rows are returned.

        Auth: requires Bearer token.

        Body: ids (required, array of demand suggestion ids, min 1).


        :::info[Required scope: `manufacturing:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 31
                - 32
                - 33
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        product_id:
                          type: integer
                        product:
                          type: object
                          properties:
                            id:
                              type: integer
                            sku:
                              type: string
                            name:
                              type: string
                        bom_id:
                          type: integer
                        bom:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        suggested_qty:
                          type: integer
                        on_hand:
                          type: integer
                        days_of_supply:
                          type: number
                        reason:
                          type: string
                        status:
                          type: string
                        confirmed_at:
                          type: string
                        dismissed_at:
                          type: string
                          nullable: true
                        confirmed_manufacturing_order_id:
                          type: integer
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  message:
                    type: string
                example:
                  data:
                  - id: 31
                    product_id: 1
                    product:
                      id: 1
                      sku: KIT-A
                      name: Widget Kit A
                    bom_id: 15
                    bom:
                      id: 15
                      name: Default Recipe
                    suggested_qty: 150
                    on_hand: 12
                    days_of_supply: 2.5
                    reason: Projected to run out in 2.5 days based on recent sales
                      velocity
                    status: confirmed
                    confirmed_at: '2026-07-01T14:22:09.000000Z'
                    dismissed_at: null
                    confirmed_manufacturing_order_id: 57
                    created_at: '2026-06-30T02:00:00.000000Z'
                    updated_at: '2026-07-01T14:22:09.000000Z'
                  message: 1 suggestions confirmed
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: manufacturing:write
      operationId: post-api-manufacturing-demand-suggestions-bulk-confirm
  /api/manufacturing/demand-suggestions/bulk/dismiss:
    post:
      tags:
      - Demand Suggestions
      summary: Bulk Dismiss Demand Suggestions
      description: 'Dismiss multiple pending demand suggestions in one call. Suggestions
        that are not pending are skipped silently; only the dismissed rows are returned.

        Auth: requires Bearer token.

        Body: ids (required, array of demand suggestion ids, min 1).


        :::info[Required scope: `manufacturing:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 31
                - 32
                - 33
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        product_id:
                          type: integer
                        product:
                          type: object
                          properties:
                            id:
                              type: integer
                            sku:
                              type: string
                            name:
                              type: string
                        bom_id:
                          type: integer
                        bom:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        suggested_qty:
                          type: integer
                        on_hand:
                          type: integer
                        days_of_supply:
                          type: number
                        reason:
                          type: string
                        status:
                          type: string
                        confirmed_at:
                          type: string
                          nullable: true
                        dismissed_at:
                          type: string
                        confirmed_manufacturing_order_id:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  message:
                    type: string
                example:
                  data:
                  - id: 31
                    product_id: 1
                    product:
                      id: 1
                      sku: KIT-A
                      name: Widget Kit A
                    bom_id: 15
                    bom:
                      id: 15
                      name: Default Recipe
                    suggested_qty: 150
                    on_hand: 12
                    days_of_supply: 2.5
                    reason: Projected to run out in 2.5 days based on recent sales
                      velocity
                    status: dismissed
                    confirmed_at: null
                    dismissed_at: '2026-07-01T14:22:09.000000Z'
                    confirmed_manufacturing_order_id: null
                    created_at: '2026-06-30T02:00:00.000000Z'
                    updated_at: '2026-07-01T14:22:09.000000Z'
                  message: 1 suggestions dismissed
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: manufacturing:write
      operationId: post-api-manufacturing-demand-suggestions-bulk-dismiss
  /api/manufacturing/lots:
    get:
      tags:
      - Lots
      summary: List Lots
      description: 'Paginated list of FIFO layers that have a `batch_number` ("lots").
        Drives the Manufacturing → Lots screen and is the data source the Source chip
        uses to deep-link back to the originating Manufacturing Order, Purchase Order,
        etc.


        :::info[Required scope: `manufacturing:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Simple-Mode disassembly produces component lots whose `link_type` is `InventoryMovement`
        (which itself links to the ManufacturingOrder). The `source` block resolves
        `parent_link_id` to the navigable parent document (e.g. ManufacturingOrder.id)
        so the UI can build a working link in one hop.'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        description: Page number (1-indexed). Defaults to 1.
        example: '1'
      - name: per_page
        in: query
        schema:
          type: integer
        description: Items per page. Defaults to 15.
        example: '15'
      - name: sort
        in: query
        schema:
          type: string
        description: 'Prefix with `-` for descending. Allowed: `id`, `batch_number`,
          `manufacture_date`, `expiry_date`, `fifo_layer_date`, `original_quantity`,
          `fulfilled_quantity`, `created_at`, `updated_at`, `warehouse_name`, `sku`,
          `product_name`. Defaults to `-manufacture_date,-id`.'
        example: -manufacture_date
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        batch_number:
                          type: string
                        manufacture_date:
                          type: string
                        expiry_date:
                          type: string
                          nullable: true
                        product_id:
                          type: integer
                        product:
                          type: object
                          properties:
                            id:
                              type: integer
                            sku:
                              type: string
                            name:
                              type: string
                        warehouse_id:
                          type: integer
                        warehouse:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        original_quantity:
                          type: integer
                        fulfilled_quantity:
                          type: integer
                        quantity_on_hand:
                          type: integer
                        source_type:
                          type: string
                        source_reference:
                          type: string
                        source:
                          type: object
                          properties:
                            link_type:
                              type: string
                            link_id:
                              type: integer
                            parent_link_id:
                              type: integer
                            reference:
                              type: string
                        fifo_layer_date:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                  first_page_url:
                    type: string
                  last_page_url:
                    type: string
                  next_page_url:
                    type: string
                  prev_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  links:
                    type: array
                example:
                  data:
                  - id: 20
                    batch_number: DA-MO-000015-2026-05-28
                    manufacture_date: '2026-05-28'
                    expiry_date: null
                    product_id: 305
                    product:
                      id: 305
                      sku: WIDGET-A
                      name: Widget Component A
                    warehouse_id: 1
                    warehouse:
                      id: 1
                      name: Main Warehouse
                    original_quantity: 4
                    fulfilled_quantity: 0
                    quantity_on_hand: 4
                    source_type: manufacturing_order
                    source_reference: MO-000015
                    source:
                      link_type: App\Models\InventoryMovement
                      link_id: 40
                      parent_link_id: 17
                      reference: MO-000015
                    fifo_layer_date: '2026-05-28T00:00:00.000000Z'
                    created_at: '2026-05-28T14:12:33.000000Z'
                    updated_at: '2026-05-28T14:12:33.000000Z'
                  - id: 19
                    batch_number: LOT-2026-04-001
                    manufacture_date: '2026-04-15'
                    expiry_date: '2027-04-15'
                    product_id: 412
                    product:
                      id: 412
                      sku: KIT-A
                      name: Widget Kit
                    warehouse_id: 1
                    warehouse:
                      id: 1
                      name: Main Warehouse
                    original_quantity: 50
                    fulfilled_quantity: 12
                    quantity_on_hand: 38
                    source_type: manufacturing_order
                    source_reference: MO-000014
                    source:
                      link_type: App\Models\MoOutputLine
                      link_id: 88
                      parent_link_id: 14
                      reference: MO-000014
                    fifo_layer_date: '2026-04-15T00:00:00.000000Z'
                    created_at: '2026-04-15T09:30:00.000000Z'
                    updated_at: '2026-04-20T11:45:12.000000Z'
                  current_page: 1
                  last_page: 3
                  per_page: 15
                  total: 42
                  from: 1
                  to: 15
                  first_page_url: https://your-domain.sku.io/api/manufacturing/lots?page=1
                  last_page_url: https://your-domain.sku.io/api/manufacturing/lots?page=3
                  next_page_url: https://your-domain.sku.io/api/manufacturing/lots?page=2
                  prev_page_url: null
                  path: https://your-domain.sku.io/api/manufacturing/lots
                  links: []
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: manufacturing:read
      operationId: get-api-manufacturing-lots
  /api/manufacturing/lot-genealogy:
    get:
      tags:
      - Lot Genealogy
      summary: Trace Lot Genealogy
      description: 'Returns a genealogy tree for a batch/lot. `batch_number` is required;
        `product_id` is optional and auto-resolved from the batch number when it uniquely
        identifies a FIFO layer. When the same batch number is used across multiple
        products, the API responds 409 with a `candidates` array so a UI can prompt
        for product disambiguation. Direction `backward` traces from finished good
        back to raw material inputs (recall use case); `forward` traces from raw material
        to all downstream produced lots (recall impact analysis).


        :::info[Required scope: `manufacturing:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: batch_number
        in: query
        schema:
          type: string
        description: Required. Exact batch number to trace.
        example: LOT-2026-04-001
      - name: product_id
        in: query
        schema:
          type: integer
        description: Optional. Omit and the API auto-resolves it from the batch number.
          If the same batch number is shared by multiple products the response is
          409 with a `candidates` array.
        example: '1'
      - name: direction
        in: query
        schema:
          type: string
        description: backward = trace inputs; forward = trace outputs
        example: backward
      - name: max_depth
        in: query
        schema:
          type: integer
        description: Optional. 1–10, defaults to 5.
        example: '5'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: string
                      entity_type:
                        type: string
                      reference:
                        type: string
                      product_id:
                        type: integer
                      product_name:
                        type: string
                      batch_number:
                        type: string
                      quantity:
                        type: integer
                      date:
                        type: string
                      fifo_layer_id:
                        type: integer
                      children:
                        type: array
                  direction:
                    type: string
                  resolved_product_id:
                    type: integer
                example:
                  data:
                    id: fifo-512
                    entity_type: manufacturing_order
                    reference: MO-000123
                    product_id: 88
                    product_name: Widget Kit
                    batch_number: LOT-2026-04-001
                    quantity: 50
                    date: '2026-04-01'
                    fifo_layer_id: 512
                    children: []
                  direction: backward
                  resolved_product_id: 88
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: string
                    nullable: true
                  message:
                    type: string
                example:
                  data: null
                  message: No FIFO layer found for batch 'NONEXISTENT'.
        '409':
          description: Conflict
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: string
                    nullable: true
                  message:
                    type: string
                  candidates:
                    type: array
                    items:
                      type: object
                      properties:
                        product_id:
                          type: integer
                        sku:
                          type: string
                        name:
                          type: string
                        batch_number:
                          type: string
                example:
                  data: null
                  message: Batch 'LOT-SHARED-001' is shared across multiple products.
                    Pick one to continue.
                  candidates:
                  - product_id: 88
                    sku: PROD-A
                    name: Widget Kit
                    batch_number: LOT-SHARED-001
                  - product_id: 142
                    sku: PROD-B
                    name: Gadget Kit
                    batch_number: LOT-SHARED-001
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: manufacturing:read
      operationId: get-api-manufacturing-lot-genealogy
  /api/manufacturing/lot-genealogy/batches:
    get:
      tags:
      - Lot Genealogy
      summary: Search Batch Numbers (Typeahead)
      description: 'Typeahead for the "Trace a Lot" batch-number field. Returns up
        to 25 distinct FIFO-layer batch numbers matching the `search` term, each with
        single-product context. Authentication: requires a Bearer token (PAT).


        :::info[Required scope: `manufacturing:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Returns an empty array (`{"data": []}`) for searches under 2 characters.


        When a batch number maps to exactly one product, `product_count` is 1 and
        `product_id`/`product_sku`/`product_name` are populated. When `product_count`
        is greater than 1 the batch spans multiple products, so those context fields
        are null and the caller should also supply a `product_id` on the genealogy
        trace request (or follow the 409 `candidates` disambiguation flow from `GET
        /api/manufacturing/lot-genealogy`).'
      parameters:
      - name: search
        in: query
        schema:
          type: string
        description: Search term matched against FIFO-layer batch numbers (partial
          match). Returns an empty array for searches shorter than 2 characters.
        example: VIT
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 OK — Matching batch numbers
                  value:
                    data:
                    - batch_number: VIT-2026-04-001
                      product_id: 88
                      product_sku: VIT-C-1000
                      product_name: Vitamin C 1000mg
                      product_count: 1
                    - batch_number: VIT-SHARED-002
                      product_id: null
                      product_sku: null
                      product_name: null
                      product_count: 2
                example-1:
                  summary: 200 OK — Search under 2 characters
                  value:
                    data: []
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: manufacturing:read
      operationId: get-api-manufacturing-lot-genealogy-batches
  /api/manufacturing/lot-genealogy/by-sales-orders:
    get:
      tags:
      - Lot Genealogy
      summary: Trace by Sales Orders
      description: 'Recall (reverse) — backward "made-from" forest for one or more
        sales orders. For every finished-good batch shipped on each order, traces
        upstream to the raw-ingredient lots (and their vendors) that went into it.
        Drives the genealogy page''s "trace by sales order(s)" mode and the Sales
        Orders list view''s "Trace Genealogy (Backward)" bulk action. Authentication:
        requires a Bearer token (PAT).


        :::info[Required scope: `manufacturing:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Accepts `sales_order_ids` as a comma-separated string or an array. Orders
        with no shipped finished goods are silently skipped.


        Returns:

        - `data.roots` — one synthetic sales-order root node per traced order (entity_type
        `sales_order`, carrying `reference`, `customer_name`, and `link_parent_id`).
        Each root''s `children` are the backward traces of the finished-good batches
        that order shipped; each finished-good node''s `consumed_quantity` is the
        qty of that batch shipped on the order, and its descendants are the component
        lots with `supplier_name` on purchased raw-ingredient layers.

        - `summary` — `order_count` (ids supplied), `traced_order_count` (roots returned),
        `finished_good_count` (finished-good batches traced).


        Errors:

        - `422` when no ids are supplied, or more than 500 are.

        - `404` when none of the supplied orders have shipped finished goods to trace.


        The response also embeds `affected_lots` (rows + summary) — the deduplicated
        implicated-lots/suppliers list — computed from the same forest build so the
        UI needn''t fetch/rebuild it separately.


        `requested_orders` lists every selected order (traced or not) with its number,
        so the UI can label each selected-order chip — the SO list endpoint can''t
        resolve multiple ids.'
      parameters:
      - name: sales_order_ids
        in: query
        schema:
          type: string
        description: Required. One or more sales-order ids to trace, as a comma-separated
          string (`4821,4822`) or an array (`sales_order_ids[]=4821&sales_order_ids[]=4822`).
          Max 500 per request.
        example: 4821,4822
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      roots:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: string
                            entity_type:
                              type: string
                            reference:
                              type: string
                            link_parent_id:
                              type: integer
                            customer_name:
                              type: string
                            date:
                              type: string
                            children:
                              type: array
                              items:
                                type: object
                                properties:
                                  id:
                                    type: string
                                  entity_type:
                                    type: string
                                  reference:
                                    type: string
                                  product_name:
                                    type: string
                                  product_sku:
                                    type: string
                                  batch_number:
                                    type: string
                                  consumed_quantity:
                                    type: integer
                                  manufacturing_order_id:
                                    type: integer
                                  children:
                                    type: array
                                    items:
                                      type: object
                                      properties:
                                        id:
                                          type: string
                                        entity_type:
                                          type: string
                                        reference:
                                          type: string
                                        product_name:
                                          type: string
                                        product_sku:
                                          type: string
                                        batch_number:
                                          type: string
                                        consumed_quantity:
                                          type: integer
                                        purchase_order_id:
                                          type: integer
                                        supplier_id:
                                          type: integer
                                        supplier_name:
                                          type: string
                                        children:
                                          type: array
                  requested_orders:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        reference:
                          type: string
                        customer_name:
                          type: string
                  summary:
                    type: object
                    properties:
                      order_count:
                        type: integer
                      traced_order_count:
                        type: integer
                      finished_good_count:
                        type: integer
                  affected_lots:
                    type: object
                    properties:
                      rows:
                        type: array
                        items:
                          type: object
                          properties:
                            fifo_layer_id:
                              type: integer
                            batch_number:
                              type: string
                            product_sku:
                              type: string
                            product_name:
                              type: string
                            lot_type:
                              type: string
                            supplier_id:
                              type: integer
                            supplier_name:
                              type: string
                            source_reference:
                              type: string
                            quantity:
                              type: integer
                            order_count:
                              type: integer
                      summary:
                        type: object
                        properties:
                          lot_count:
                            type: integer
                          supplier_count:
                            type: integer
                          order_count:
                            type: integer
                          total_quantity:
                            type: integer
                example:
                  data:
                    roots:
                    - id: so-4821
                      entity_type: sales_order
                      reference: SO-7881
                      link_parent_id: 4821
                      customer_name: Acme Health Foods
                      date: '2026-04-12'
                      children:
                      - id: fifo-135
                        entity_type: manufacturing_order
                        reference: MO-504211
                        product_name: Calm Gummies
                        product_sku: CALM-GUMMIES
                        batch_number: CALM-MO-2026-0001
                        consumed_quantity: 6
                        manufacturing_order_id: 504211
                        children:
                        - id: fifo-134
                          entity_type: purchase_order
                          reference: PO-0003
                          product_name: Ashwagandha Extract
                          product_sku: ASHWA-EXT
                          batch_number: ASH-2026-RAW-0001
                          consumed_quantity: 20
                          purchase_order_id: 3
                          supplier_id: 4
                          supplier_name: Acme Botanicals
                          children: []
                  requested_orders:
                  - id: 4821
                    reference: SO-7881
                    customer_name: Acme Health Foods
                  - id: 4822
                    reference: SO-7882
                    customer_name: Bright Wellness Co
                  summary:
                    order_count: 2
                    traced_order_count: 1
                    finished_good_count: 1
                  affected_lots:
                    rows:
                    - fifo_layer_id: 134
                      batch_number: ASH-2026-RAW-0001
                      product_sku: ASHWA-EXT
                      product_name: Ashwagandha Extract
                      lot_type: Purchased
                      supplier_id: 4
                      supplier_name: Acme Botanicals
                      source_reference: PO-0003
                      quantity: 20
                      order_count: 2
                    - fifo_layer_id: 135
                      batch_number: CALM-MO-2026-0001
                      product_sku: CALM-GUMMIES
                      product_name: Calm Gummies
                      lot_type: Manufactured
                      supplier_id: null
                      supplier_name: null
                      source_reference: MO-504211
                      quantity: 7
                      order_count: 2
                    summary:
                      lot_count: 2
                      supplier_count: 1
                      order_count: 2
                      total_quantity: 27
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: string
                    nullable: true
                  message:
                    type: string
                example:
                  data: null
                  message: None of the selected sales orders have shipped finished
                    goods to trace.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: string
                    nullable: true
                  message:
                    type: string
                example:
                  data: null
                  message: Provide one or more sales_order_ids to trace.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: manufacturing:read
      operationId: get-api-manufacturing-lot-genealogy-by-sales-orders
  /api/manufacturing/lot-genealogy/sales-order-refs:
    get:
      tags:
      - Lot Genealogy
      summary: Resolve Sales Order Numbers
      description: 'Resolve selected order ids -> their numbers + customers via a
        direct whereIn (the SO list filter[id] coerces "3,4" to a single id and can''t
        resolve multiple). Lets the "trace by sales order(s)" chips show real "SO-…"
        labels before the slower trace returns. Authentication: requires a Bearer
        token (PAT).


        :::info[Required scope: `manufacturing:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: sales_order_ids
        in: query
        schema:
          type: string
        description: Required. Comma-separated or array of sales-order ids.
        example: 4821,4822
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        reference:
                          type: string
                        customer_name:
                          type: string
                example:
                  data:
                  - id: 4821
                    reference: SO-7881
                    customer_name: Acme Health Foods
                  - id: 4822
                    reference: SO-7882
                    customer_name: Bright Wellness Co
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: manufacturing:read
      operationId: get-api-manufacturing-lot-genealogy-sales-order-refs
  /api/manufacturing/lot-genealogy/resolve-sales-order-numbers:
    post:
      tags:
      - Lot Genealogy
      summary: Bulk Resolve Sales Order Numbers
      description: 'Bulk-resolve pasted / imported sales-order NUMBERS into ids, so
        a recall can be seeded from a spreadsheet column or CSV instead of typing
        each order. Body: `numbers` (array, max 2000, each <= 64 chars). Returns `matched`
        (id + number + customer) and `unmatched` (numbers that matched no order).
        Authentication: requires a Bearer token (PAT).


        :::info[Required scope: `manufacturing:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                numbers:
                  type: array
                  items:
                    type: string
              example:
                numbers:
                - SO-7881
                - SO-7882
                - SO-DOES-NOT-EXIST
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  matched:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        reference:
                          type: string
                        customer_name:
                          type: string
                  unmatched:
                    type: array
                    items:
                      type: string
                example:
                  matched:
                  - id: 4821
                    reference: SO-7881
                    customer_name: Acme Health Foods
                  unmatched:
                  - SO-DOES-NOT-EXIST
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: manufacturing:write
      operationId: post-api-manufacturing-lot-genealogy-resolve-sales-order-numbers
  /api/manufacturing/lot-genealogy/affected-lots-by-sales-orders:
    get:
      tags:
      - Lot Genealogy
      summary: List Affected Lots and Suppliers
      description: 'Recall (reverse) — the implicated lots + suppliers behind a set
        of sales orders: every raw-ingredient / finished-good lot that fed the orders''
        shipped goods, deduplicated, with supplier and a count of how many of the
        orders each lot touches. Authentication: requires a Bearer token (PAT).


        :::info[Required scope: `manufacturing:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Quantities are summed across DISTINCT consumption edges, so a shared upstream
        ingredient consumed once by a finished good isn''t double-counted across the
        multiple orders that finished good shipped to (finished-good shipment quantities
        to different orders ARE summed). Supplier-backed lots (the recall-actionable
        raw materials) sort first.


        Returns `data` (one row per implicated lot — batch, product, lot_type, supplier,
        source_reference, quantity, order_count) and `summary` (lot_count, supplier_count,
        order_count, total_quantity). 422 when no ids / over 500.'
      parameters:
      - name: sales_order_ids
        in: query
        schema:
          type: string
        description: Required. One or more sales-order ids, comma-separated (`4821,4822`)
          or as an array. Max 500.
        example: 4821,4822
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        fifo_layer_id:
                          type: integer
                        batch_number:
                          type: string
                        product_id:
                          type: integer
                        product_sku:
                          type: string
                        product_name:
                          type: string
                        lot_type:
                          type: string
                        supplier_id:
                          type: integer
                        supplier_name:
                          type: string
                        source_reference:
                          type: string
                        quantity:
                          type: integer
                        order_count:
                          type: integer
                  summary:
                    type: object
                    properties:
                      lot_count:
                        type: integer
                      supplier_count:
                        type: integer
                      order_count:
                        type: integer
                      total_quantity:
                        type: integer
                example:
                  data:
                  - fifo_layer_id: 134
                    batch_number: ASH-2026-RAW-0001
                    product_id: 22
                    product_sku: ASHWA-EXT
                    product_name: Ashwagandha Extract
                    lot_type: Purchased
                    supplier_id: 4
                    supplier_name: Acme Botanicals
                    source_reference: PO-0003
                    quantity: 20
                    order_count: 2
                  - fifo_layer_id: 135
                    batch_number: CALM-MO-2026-0001
                    product_id: 23
                    product_sku: CALM-GUMMIES
                    product_name: Calm Gummies
                    lot_type: Manufactured
                    supplier_id: null
                    supplier_name: null
                    source_reference: MO-504211
                    quantity: 7
                    order_count: 2
                  summary:
                    lot_count: 2
                    supplier_count: 1
                    order_count: 2
                    total_quantity: 27
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: manufacturing:read
      operationId: get-api-manufacturing-lot-genealogy-affected-lots-by-sales-orders
  /api/manufacturing/lot-genealogy/affected-lots-by-sales-orders/export:
    get:
      tags:
      - Lot Genealogy
      summary: Export Affected Lots and Suppliers (CSV)
      description: 'Recall (reverse) — streams the implicated lots + suppliers for
        a set of sales orders as a CSV download for the recall paper trail. Same resolution
        + 422 semantics as `GET /api/manufacturing/lot-genealogy/affected-lots-by-sales-orders`.
        Authentication: requires a Bearer token (PAT).


        :::info[Required scope: `manufacturing:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Response is a `text/csv` file download. Columns: Batch, Product SKU, Product,
        Type, Supplier, Source, Quantity Consumed, Affected Orders.'
      parameters:
      - name: sales_order_ids
        in: query
        schema:
          type: string
        description: Required. One or more sales-order ids, comma-separated (`4821,4822`)
          or as an array. Max 500.
        example: 4821,4822
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: text/csv
          content:
            text/plain:
              schema:
                type: string
                example: 'Batch,"Product SKU",Product,Type,Supplier,Source,"Quantity
                  Consumed","Affected Orders"

                  ASH-2026-RAW-0001,ASHWA-EXT,"Ashwagandha Extract",Purchased,"Acme
                  Botanicals",PO-0003,20,2'
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: manufacturing:read
      operationId: get-api-manufacturing-lot-genealogy-affected-lots-by-sales-orders-export
  /api/manufacturing/lot-genealogy/affected-sales-orders:
    get:
      tags:
      - Lot Genealogy
      summary: List Affected Sales Orders
      description: 'Recall workflow — the sales orders / customers that consumed the
        traced batch (or a finished good produced from it). Forward trace only; backward
        traces (sources) have no customers. Authentication: requires a Bearer token
        (PAT).


        :::info[Required scope: `manufacturing:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Resolves the batch the same way as `GET /api/manufacturing/lot-genealogy`
        (404 when nothing matches; 409 with a `candidates` array when the batch number
        is shared across multiple products).


        Returns:

        - `data` — one row per (sales order, shipped product, shipped batch), with
        customer name/email/company, order date, shipped-at date, the shipped product,
        and the aggregated quantity of the traced batch that reached that order.

        - `order_ids` — the distinct sales-order id list (use this directly as the
        `{ids: [...]}` selection payload for `POST /api/sales-orders/bulk-email`).

        - `summary` — `customer_count`, `order_count`, `total_quantity`.'
      parameters:
      - name: batch_number
        in: query
        schema:
          type: string
        description: Required. Exact batch number to trace forward to its sales-order
          consumers.
        example: LOT-2026-04-001
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        sales_order_id:
                          type: integer
                        sales_order_number:
                          type: string
                        customer_name:
                          type: string
                        customer_email:
                          type: string
                        customer_company:
                          type: string
                        order_date:
                          type: string
                        shipped_at:
                          type: string
                        shipped_product_id:
                          type: integer
                        shipped_product_sku:
                          type: string
                        shipped_product_name:
                          type: string
                        shipped_batch_number:
                          type: string
                        quantity:
                          type: integer
                  order_ids:
                    type: array
                    items:
                      type: integer
                  summary:
                    type: object
                    properties:
                      customer_count:
                        type: integer
                      order_count:
                        type: integer
                      total_quantity:
                        type: integer
                example:
                  data:
                  - sales_order_id: 4821
                    sales_order_number: SO-7881
                    customer_name: Acme Health Foods
                    customer_email: recall@acmehealth.test
                    customer_company: Acme Health Foods Ltd
                    order_date: '2026-04-12'
                    shipped_at: '2026-04-15'
                    shipped_product_id: 88
                    shipped_product_sku: VIT-C-1000
                    shipped_product_name: Vitamin C 1000mg
                    shipped_batch_number: LOT-2026-04-001
                    quantity: 6
                  order_ids:
                  - 4821
                  summary:
                    customer_count: 1
                    order_count: 1
                    total_quantity: 6
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: string
                    nullable: true
                  message:
                    type: string
                example:
                  data: null
                  message: No FIFO layer found for batch 'NONEXISTENT'.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: manufacturing:read
      operationId: get-api-manufacturing-lot-genealogy-affected-sales-orders
  /api/manufacturing/lot-genealogy/affected-sales-orders/export:
    get:
      tags:
      - Lot Genealogy
      summary: Export Affected Sales Orders (CSV)
      description: 'Recall workflow — streams the affected sales-order / customer
        rows as a CSV download for the recall paper trail. Same batch resolution +
        404/409 semantics as `GET /api/manufacturing/lot-genealogy/affected-sales-orders`.
        Authentication: requires a Bearer token (PAT).


        :::info[Required scope: `manufacturing:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Response is a `text/csv` file download (filename `recall-affected-orders-{batch}.csv`),
        not JSON. Columns: Sales Order, Customer, Email, Company, Order Date, Shipped
        At, Product SKU, Product, Batch, Quantity.'
      parameters:
      - name: batch_number
        in: query
        schema:
          type: string
        description: Required. Exact batch number to export the affected sales-order
          / customer rows for.
        example: LOT-2026-04-001
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: text/csv
          content:
            text/plain:
              schema:
                type: string
                example: '"Sales Order",Customer,Email,Company,"Order Date","Shipped
                  At","Product SKU",Product,Batch,Quantity

                  SO-7881,"Acme Health Foods",recall@acmehealth.test,"Acme Health
                  Foods Ltd",2026-04-12,2026-04-15,VIT-C-1000,"Vitamin C 1000mg",LOT-2026-04-001,6

                  '
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: manufacturing:read
      operationId: get-api-manufacturing-lot-genealogy-affected-sales-orders-export
  /api/manufacturing/mrp/runs:
    get:
      tags:
      - MRP Planning
      summary: List MRP Runs
      description: 'Paginated list of MRP runs, most recent first.

        Auth: requires Bearer token.

        Returns a standard Laravel paginator (MRP run object items in data).

        Pagination defaults: per_page=10.


        :::info[Required scope: `manufacturing:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        scenario_id:
                          type: string
                          nullable: true
                        mode:
                          type: string
                        status:
                          type: string
                        horizon_days:
                          type: integer
                        bucket_size:
                          type: string
                        include_capacity:
                          type: boolean
                        include_forecast:
                          type: boolean
                        counts:
                          type: object
                          properties:
                            planned_orders:
                              type: integer
                            action_messages:
                              type: integer
                            pegging:
                              type: integer
                            time_phased_records:
                              type: integer
                        started_at:
                          type: string
                        completed_at:
                          type: string
                        runtime_ms:
                          type: integer
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 42
                    scenario_id: null
                    mode: regenerative
                    status: completed
                    horizon_days: 90
                    bucket_size: week
                    include_capacity: true
                    include_forecast: true
                    counts:
                      planned_orders: 128
                      action_messages: 17
                      pegging: 240
                      time_phased_records: 512
                    started_at: '2026-06-17T14:03:11.000000Z'
                    completed_at: '2026-06-17T14:03:19.000000Z'
                    runtime_ms: 8421
                    created_at: '2026-06-17T14:03:11.000000Z'
                    updated_at: '2026-06-17T14:03:19.000000Z'
                  current_page: 1
                  first_page_url: '...'
                  from: 1
                  last_page: 1
                  last_page_url: '...'
                  links: []
                  next_page_url: null
                  path: '...'
                  per_page: 10
                  prev_page_url: null
                  to: 1
                  total: 24
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: manufacturing:read
      operationId: get-api-manufacturing-mrp-runs
    post:
      tags:
      - MRP Planning
      summary: Start MRP Run
      description: 'Create and synchronously execute a regenerative or net-change
        MRP run, then return the completed run.

        Auth: requires Bearer token.

        FormRequest: StartMrpRunRequest (all fields optional; controller applies defaults).

        Fields: mode (in: regenerative, net_change; default regenerative), scenario_id
        (nullable, exists:mrp_scenarios), horizon_days (1-1095; default 90), bucket_size
        (in: day, week, month; default week), warehouse_ids[] (exists:warehouses),
        product_ids[] (exists:products), include_capacity (bool; default false), include_forecast
        (bool; default true).


        :::info[Required scope: `manufacturing:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                mode:
                  type: string
                scenario_id:
                  type: string
                  nullable: true
                horizon_days:
                  type: integer
                bucket_size:
                  type: string
                warehouse_ids:
                  type: array
                  items:
                    type: integer
                product_ids:
                  type: array
                  items:
                    type: integer
                include_capacity:
                  type: boolean
                include_forecast:
                  type: boolean
              example:
                mode: regenerative
                scenario_id: null
                horizon_days: 120
                bucket_size: week
                warehouse_ids:
                - 1
                - 2
                product_ids:
                - 101
                - 102
                - 103
                include_capacity: true
                include_forecast: true
      parameters: []
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      scenario_id:
                        type: string
                        nullable: true
                      mode:
                        type: string
                      status:
                        type: string
                      horizon_days:
                        type: integer
                      bucket_size:
                        type: string
                      include_capacity:
                        type: boolean
                      include_forecast:
                        type: boolean
                      counts:
                        type: object
                        properties:
                          planned_orders:
                            type: integer
                          action_messages:
                            type: integer
                          pegging:
                            type: integer
                          time_phased_records:
                            type: integer
                      started_at:
                        type: string
                      completed_at:
                        type: string
                      runtime_ms:
                        type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 43
                    scenario_id: null
                    mode: regenerative
                    status: completed
                    horizon_days: 120
                    bucket_size: week
                    include_capacity: true
                    include_forecast: true
                    counts:
                      planned_orders: 128
                      action_messages: 17
                      pegging: 240
                      time_phased_records: 512
                    started_at: '2026-06-17T14:03:11.000000Z'
                    completed_at: '2026-06-17T14:03:19.000000Z'
                    runtime_ms: 8421
                    created_at: '2026-06-17T14:03:11.000000Z'
                    updated_at: '2026-06-17T14:03:19.000000Z'
                  message: MRP run completed
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: manufacturing:write
      operationId: post-api-manufacturing-mrp-runs
  /api/manufacturing/mrp/runs/{mrpRun}:
    get:
      tags:
      - MRP Planning
      summary: Get MRP Run
      description: 'Return a single MRP run by id.

        Auth: requires Bearer token.

        Path param: mrpRun = MRP run id.


        :::info[Required scope: `manufacturing:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: mrpRun
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The mrp run ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      scenario_id:
                        type: string
                        nullable: true
                      mode:
                        type: string
                      status:
                        type: string
                      horizon_days:
                        type: integer
                      bucket_size:
                        type: string
                      include_capacity:
                        type: boolean
                      include_forecast:
                        type: boolean
                      counts:
                        type: object
                        properties:
                          planned_orders:
                            type: integer
                          action_messages:
                            type: integer
                          pegging:
                            type: integer
                          time_phased_records:
                            type: integer
                      started_at:
                        type: string
                      completed_at:
                        type: string
                      runtime_ms:
                        type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 42
                    scenario_id: null
                    mode: regenerative
                    status: completed
                    horizon_days: 90
                    bucket_size: week
                    include_capacity: true
                    include_forecast: true
                    counts:
                      planned_orders: 128
                      action_messages: 17
                      pegging: 240
                      time_phased_records: 512
                    started_at: '2026-06-17T14:03:11.000000Z'
                    completed_at: '2026-06-17T14:03:19.000000Z'
                    runtime_ms: 8421
                    created_at: '2026-06-17T14:03:11.000000Z'
                    updated_at: '2026-06-17T14:03:19.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: manufacturing:read
      operationId: get-api-manufacturing-mrp-runs-mrprun
  /api/manufacturing/mrp/runs/{mrpRun}/planned-orders:
    get:
      tags:
      - MRP Planning
      summary: List Run Planned Orders
      description: 'Paginated planned orders for a run, ordered by low_level_code
        then release_date. Eager-loads product, warehouse, supplier, bom.

        Auth: requires Bearer token.

        Filters: filter[supply_type] (make|buy|transfer), filter[state] (planned|firm|released),
        filter[warehouse_id] (int).

        Pagination defaults: per_page=10.


        :::info[Required scope: `manufacturing:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: mrpRun
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The mrp run ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        mrp_run_id:
                          type: integer
                        product_id:
                          type: integer
                        product:
                          type: object
                          properties:
                            id:
                              type: integer
                            sku:
                              type: string
                            name:
                              type: string
                        warehouse_id:
                          type: integer
                        warehouse:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        supply_type:
                          type: string
                        state:
                          type: string
                        quantity:
                          type: integer
                        net_requirement:
                          type: integer
                        due_date:
                          type: string
                        release_date:
                          type: string
                        bucket_start:
                          type: string
                        lead_time_days:
                          type: integer
                        lot_sizing_rule:
                          type: string
                        supplier_id:
                          type: string
                          nullable: true
                        supplier:
                          type: string
                          nullable: true
                        bom_id:
                          type: integer
                        bom:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        source_warehouse_id:
                          type: string
                          nullable: true
                        low_level_code:
                          type: integer
                        accepted:
                          type: boolean
                        firm_quantity:
                          type: string
                          nullable: true
                        firm_due_date:
                          type: string
                          nullable: true
                        released_order_type:
                          type: string
                          nullable: true
                        released_order_id:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 901
                    mrp_run_id: 42
                    product_id: 101
                    product:
                      id: 101
                      sku: WIDGET-RED
                      name: Red Widget
                    warehouse_id: 2
                    warehouse:
                      id: 2
                      name: Main DC
                    supply_type: make
                    state: planned
                    quantity: 500
                    net_requirement: 480
                    due_date: '2026-07-15'
                    release_date: '2026-07-01'
                    bucket_start: '2026-06-29'
                    lead_time_days: 14
                    lot_sizing_rule: lot_for_lot
                    supplier_id: null
                    supplier: null
                    bom_id: 55
                    bom:
                      id: 55
                      name: Red Widget BOM v3
                    source_warehouse_id: null
                    low_level_code: 1
                    accepted: false
                    firm_quantity: null
                    firm_due_date: null
                    released_order_type: null
                    released_order_id: null
                    created_at: '2026-06-17T14:03:18.000000Z'
                    updated_at: '2026-06-17T14:03:18.000000Z'
                  current_page: 1
                  first_page_url: '...'
                  from: 1
                  last_page: 1
                  last_page_url: '...'
                  links: []
                  next_page_url: null
                  path: '...'
                  per_page: 10
                  prev_page_url: null
                  to: 1
                  total: 128
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: manufacturing:read
      operationId: get-api-manufacturing-mrp-runs-mrprun-planned-orders
  /api/manufacturing/mrp/runs/{mrpRun}/items/{product}/time-phased:
    get:
      tags:
      - MRP Planning
      summary: Get Item Time-Phased Grid
      description: 'Time-phased MRP grid (gross-to-net buckets) for one product within
        a run, optionally scoped to a warehouse. Plain array, not a Resource.

        Auth: requires Bearer token.

        Path params: mrpRun = run id, product = product id.

        Optional query: warehouse_id to restrict buckets to one warehouse.


        :::info[Required scope: `manufacturing:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: mrpRun
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The mrp run ID.
      - name: product
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The product ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      product:
                        type: object
                        properties:
                          id:
                            type: integer
                          sku:
                            type: string
                          name:
                            type: string
                      buckets:
                        type: array
                        items:
                          type: object
                          properties:
                            warehouse_id:
                              type: integer
                            bucket_start:
                              type: string
                            bucket_end:
                              type: string
                            gross_requirements:
                              type: integer
                            scheduled_receipts:
                              type: integer
                            projected_available:
                              type: integer
                            net_requirements:
                              type: integer
                            planned_order_receipts:
                              type: integer
                            planned_order_releases:
                              type: integer
                example:
                  data:
                    product:
                      id: 101
                      sku: WIDGET-RED
                      name: Red Widget
                    buckets:
                    - warehouse_id: 2
                      bucket_start: '2026-06-22'
                      bucket_end: '2026-06-28'
                      gross_requirements: 120
                      scheduled_receipts: 0
                      projected_available: 80
                      net_requirements: 40
                      planned_order_receipts: 40
                      planned_order_releases: 0
                    - warehouse_id: 2
                      bucket_start: '2026-06-29'
                      bucket_end: '2026-07-05'
                      gross_requirements: 200
                      scheduled_receipts: 0
                      projected_available: 0
                      net_requirements: 160
                      planned_order_receipts: 160
                      planned_order_releases: 500
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: manufacturing:read
      operationId: get-api-manufacturing-mrp-runs-mrprun-items-product-time-phased
  /api/manufacturing/mrp/runs/{mrpRun}/action-messages:
    get:
      tags:
      - MRP Planning
      summary: List Run Action Messages
      description: 'Paginated action/exception messages for a run, ordered by severity
        priority then id. Eager-loads product, warehouse.

        Auth: requires Bearer token.

        Filters: filter[type] (enum), filter[severity] (emergency|exception|attention),
        filter[message_class] (action|exception), filter[status] (open|accepted|dismissed).

        Pagination defaults: per_page=10.


        :::info[Required scope: `manufacturing:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: mrpRun
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The mrp run ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        mrp_run_id:
                          type: integer
                        product_id:
                          type: integer
                        product:
                          type: object
                          properties:
                            id:
                              type: integer
                            sku:
                              type: string
                            name:
                              type: string
                        warehouse_id:
                          type: integer
                        warehouse:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        message_class:
                          type: string
                        type:
                          type: string
                        severity:
                          type: string
                        order_type:
                          type: string
                        order_id:
                          type: integer
                        current_due_date:
                          type: string
                        current_qty:
                          type: integer
                        recommended_due_date:
                          type: string
                        recommended_qty:
                          type: integer
                        days_late:
                          type: integer
                        peg_id:
                          type: integer
                        status:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 5001
                    mrp_run_id: 42
                    product_id: 101
                    product:
                      id: 101
                      sku: WIDGET-RED
                      name: Red Widget
                    warehouse_id: 2
                    warehouse:
                      id: 2
                      name: Main DC
                    message_class: action
                    type: reschedule_in
                    severity: exception
                    order_type: purchase_order
                    order_id: 7788
                    current_due_date: '2026-07-20'
                    current_qty: 500
                    recommended_due_date: '2026-07-12'
                    recommended_qty: 500
                    days_late: 8
                    peg_id: 3120
                    status: open
                    created_at: '2026-06-17T14:03:19.000000Z'
                    updated_at: '2026-06-17T14:03:19.000000Z'
                  current_page: 1
                  first_page_url: '...'
                  from: 1
                  last_page: 1
                  last_page_url: '...'
                  links: []
                  next_page_url: null
                  path: '...'
                  per_page: 10
                  prev_page_url: null
                  to: 1
                  total: 17
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: manufacturing:read
      operationId: get-api-manufacturing-mrp-runs-mrprun-action-messages
  /api/manufacturing/mrp/runs/{mrpRun}/action-messages/counts:
    get:
      tags:
      - MRP Planning
      summary: Get Action Message Counts
      description: 'Grouped counts of action messages for the run, bucketed by type
        and by severity. Plain array.

        Auth: requires Bearer token.

        Path param: mrpRun = run id.


        :::info[Required scope: `manufacturing:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: mrpRun
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The mrp run ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      by_type:
                        type: object
                        properties:
                          release:
                            type: integer
                          reschedule_in:
                            type: integer
                          reschedule_out:
                            type: integer
                          past_due:
                            type: integer
                          shortage:
                            type: integer
                      by_severity:
                        type: object
                        properties:
                          emergency:
                            type: integer
                          exception:
                            type: integer
                          attention:
                            type: integer
                example:
                  data:
                    by_type:
                      release: 6
                      reschedule_in: 4
                      reschedule_out: 2
                      past_due: 3
                      shortage: 2
                    by_severity:
                      emergency: 2
                      exception: 7
                      attention: 8
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: manufacturing:read
      operationId: get-api-manufacturing-mrp-runs-mrprun-action-messages-counts
  /api/manufacturing/mrp/runs/{mrpRun}/planned-orders/{plannedOrder}/pegging:
    get:
      tags:
      - MRP Planning
      summary: Get Planned Order Pegging
      description: 'Bottom-up peg trace for a planned order: walks the parent chain
        from the supply order up to the originating independent demand. Plain array.

        Auth: requires Bearer token.

        Path params: mrpRun = run id, plannedOrder = planned order id.


        :::info[Required scope: `manufacturing:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: mrpRun
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The mrp run ID.
      - name: plannedOrder
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The planned order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      planned_order_id:
                        type: integer
                      trace:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            level:
                              type: integer
                            quantity:
                              type: integer
                            demand_type:
                              type: string
                            demand_ref:
                              type: string
                            demand_product_id:
                              type: integer
                            demand_product:
                              type: object
                              properties:
                                id:
                                  type: integer
                                sku:
                                  type: string
                                name:
                                  type: string
                            supply_planned_order_id:
                              type: integer
                            supply_order_type:
                              type: string
                            parent_planned_order_id:
                              type: integer
                example:
                  data:
                    planned_order_id: 901
                    trace:
                    - id: 3120
                      level: 2
                      quantity: 500
                      demand_type: dependent
                      demand_ref: PO-901
                      demand_product_id: 205
                      demand_product:
                        id: 205
                        sku: SUBASSY-A
                        name: Sub-assembly A
                      supply_planned_order_id: 901
                      supply_order_type: planned
                      parent_planned_order_id: 880
                    - id: 3090
                      level: 1
                      quantity: 500
                      demand_type: sales_order_line
                      demand_ref: SO-10042-1
                      demand_product_id: 101
                      demand_product:
                        id: 101
                        sku: WIDGET-RED
                        name: Red Widget
                      supply_planned_order_id: 880
                      supply_order_type: planned
                      parent_planned_order_id: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: manufacturing:read
      operationId: get-api-manufacturing-mrp-runs-mrprun-planned-orders-plannedorder-pegging
  /api/manufacturing/mrp/runs/{mrpRun}/capacity/load-profile:
    get:
      tags:
      - MRP Planning
      summary: Get Capacity Load Profile
      description: 'Detailed CRP load profile from BOM routings: required vs rated
        capacity per work center per time bucket. Plain array.

        Auth: requires Bearer token.

        Path param: mrpRun = run id.

        Status per bucket: under (<50% util), ok, over (required > rated or util >
        100%).


        :::info[Required scope: `manufacturing:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: mrpRun
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The mrp run ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        work_center_id:
                          type: integer
                        work_center_name:
                          type: string
                        buckets:
                          type: array
                          items:
                            type: object
                            properties:
                              bucket_index:
                                type: integer
                              bucket_start:
                                type: string
                              required_hours:
                                type: number
                              rated_capacity:
                                type: integer
                              utilization_pct:
                                type: number
                              status:
                                type: string
                example:
                  data:
                  - work_center_id: 11
                    work_center_name: Assembly Line 1
                    buckets:
                    - bucket_index: 0
                      bucket_start: '2026-06-18'
                      required_hours: 42.5
                      rated_capacity: 40
                      utilization_pct: 106.25
                      status: over
                    - bucket_index: 1
                      bucket_start: '2026-06-25'
                      required_hours: 18
                      rated_capacity: 40
                      utilization_pct: 45
                      status: under
                    - bucket_index: 2
                      bucket_start: '2026-07-02'
                      required_hours: 30
                      rated_capacity: 40
                      utilization_pct: 75
                      status: ok
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: manufacturing:read
      operationId: get-api-manufacturing-mrp-runs-mrprun-capacity-load-profile
  /api/manufacturing/mrp/runs/{mrpRun}/capacity/heatmap:
    get:
      tags:
      - MRP Planning
      summary: Get Capacity Heatmap
      description: 'CRP data reshaped into a heatmap grid (work centers x buckets)
        with a color band per cell. Plain object.

        Auth: requires Bearer token.

        Path param: mrpRun = run id.

        Colors: under -> blue, over -> orange, ok -> green.


        :::info[Required scope: `manufacturing:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: mrpRun
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The mrp run ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      buckets:
                        type: array
                        items:
                          type: object
                          properties:
                            bucket_index:
                              type: integer
                            bucket_start:
                              type: string
                      rows:
                        type: array
                        items:
                          type: object
                          properties:
                            work_center_id:
                              type: integer
                            work_center_name:
                              type: string
                            cells:
                              type: array
                              items:
                                type: object
                                properties:
                                  bucket_index:
                                    type: integer
                                  required_hours:
                                    type: number
                                  rated_capacity:
                                    type: integer
                                  utilization_pct:
                                    type: number
                                  status:
                                    type: string
                                  color:
                                    type: string
                example:
                  data:
                    buckets:
                    - bucket_index: 0
                      bucket_start: '2026-06-18'
                    - bucket_index: 1
                      bucket_start: '2026-06-25'
                    - bucket_index: 2
                      bucket_start: '2026-07-02'
                    rows:
                    - work_center_id: 11
                      work_center_name: Assembly Line 1
                      cells:
                      - bucket_index: 0
                        required_hours: 42.5
                        rated_capacity: 40
                        utilization_pct: 106.25
                        status: over
                        color: orange
                      - bucket_index: 1
                        required_hours: 18
                        rated_capacity: 40
                        utilization_pct: 45
                        status: under
                        color: blue
                      - bucket_index: 2
                        required_hours: 30
                        rated_capacity: 40
                        utilization_pct: 75
                        status: ok
                        color: green
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: manufacturing:read
      operationId: get-api-manufacturing-mrp-runs-mrprun-capacity-heatmap
  /api/manufacturing/mrp/runs/{mrpRun}/capacity/rough-cut:
    get:
      tags:
      - MRP Planning
      summary: Get Rough-Cut Capacity Plan
      description: 'Rough-Cut Capacity Planning (RCCP) using the bill of resources
        (is_key_resource rows): required hours time-phased per key work center vs
        rated capacity. Plain array (same shape as load-profile).

        Auth: requires Bearer token.

        Path param: mrpRun = run id.


        :::info[Required scope: `manufacturing:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: mrpRun
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The mrp run ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        work_center_id:
                          type: integer
                        work_center_name:
                          type: string
                        buckets:
                          type: array
                          items:
                            type: object
                            properties:
                              bucket_index:
                                type: integer
                              bucket_start:
                                type: string
                              required_hours:
                                type: integer
                              rated_capacity:
                                type: integer
                              utilization_pct:
                                type: integer
                              status:
                                type: string
                example:
                  data:
                  - work_center_id: 11
                    work_center_name: Assembly Line 1
                    buckets:
                    - bucket_index: 0
                      bucket_start: '2026-06-18'
                      required_hours: 50
                      rated_capacity: 40
                      utilization_pct: 125
                      status: over
                    - bucket_index: 1
                      bucket_start: '2026-06-25'
                      required_hours: 20
                      rated_capacity: 40
                      utilization_pct: 50
                      status: ok
                  - work_center_id: 12
                    work_center_name: Paint Booth
                    buckets:
                    - bucket_index: 0
                      bucket_start: '2026-06-18'
                      required_hours: 12
                      rated_capacity: 32
                      utilization_pct: 37.5
                      status: under
                    - bucket_index: 1
                      bucket_start: '2026-06-25'
                      required_hours: 0
                      rated_capacity: 32
                      utilization_pct: 0
                      status: under
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: manufacturing:read
      operationId: get-api-manufacturing-mrp-runs-mrprun-capacity-rough-cut
  /api/manufacturing/mrp/planned-orders/firm:
    post:
      tags:
      - MRP Planning
      summary: Firm Planned Orders
      description: 'Firm one or more planned orders (planned -> firm), optionally
        overriding quantity and/or due date.

        Auth: requires Bearer token.

        FormRequest: FirmPlannedOrderRequest.

        Fields: ids[] (required, exists:mrp_planned_orders), firm_quantity (nullable,
        numeric, gt:0), firm_due_date (nullable, date).


        :::info[Required scope: `manufacturing:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
                firm_quantity:
                  type: integer
                firm_due_date:
                  type: string
              example:
                ids:
                - 101
                - 102
                - 103
                firm_quantity: 500
                firm_due_date: '2026-07-15'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        mrp_run_id:
                          type: integer
                        product_id:
                          type: integer
                        product:
                          type: object
                          properties:
                            id:
                              type: integer
                            sku:
                              type: string
                            name:
                              type: string
                        warehouse_id:
                          type: integer
                        warehouse:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        supply_type:
                          type: string
                        state:
                          type: string
                        quantity:
                          type: integer
                        net_requirement:
                          type: integer
                        due_date:
                          type: string
                        release_date:
                          type: string
                        bucket_start:
                          type: string
                        lead_time_days:
                          type: integer
                        lot_sizing_rule:
                          type: string
                        supplier_id:
                          type: string
                          nullable: true
                        supplier:
                          type: string
                          nullable: true
                        bom_id:
                          type: integer
                        bom:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        source_warehouse_id:
                          type: string
                          nullable: true
                        low_level_code:
                          type: integer
                        accepted:
                          type: boolean
                        firm_quantity:
                          type: integer
                        firm_due_date:
                          type: string
                        released_order_type:
                          type: string
                          nullable: true
                        released_order_id:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  message:
                    type: string
                example:
                  data:
                  - id: 101
                    mrp_run_id: 42
                    product_id: 9001
                    product:
                      id: 9001
                      sku: WIDGET-A
                      name: Blue Widget Assembly
                    warehouse_id: 3
                    warehouse:
                      id: 3
                      name: Main Distribution Center
                    supply_type: make
                    state: firm
                    quantity: 500
                    net_requirement: 480
                    due_date: '2026-07-15'
                    release_date: '2026-07-01'
                    bucket_start: '2026-06-29'
                    lead_time_days: 14
                    lot_sizing_rule: lot_for_lot
                    supplier_id: null
                    supplier: null
                    bom_id: 55
                    bom:
                      id: 55
                      name: Blue Widget Assembly BOM v3
                    source_warehouse_id: null
                    low_level_code: 1
                    accepted: false
                    firm_quantity: 500
                    firm_due_date: '2026-07-15'
                    released_order_type: null
                    released_order_id: null
                    created_at: '2026-06-17T14:03:18.000000Z'
                    updated_at: '2026-06-17T14:03:18.000000Z'
                  message: 1 planned orders firmed
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: manufacturing:write
      operationId: post-api-manufacturing-mrp-planned-orders-firm
  /api/manufacturing/mrp/planned-orders/unfirm:
    post:
      tags:
      - MRP Planning
      summary: Unfirm Planned Orders
      description: 'Revert firmed planned orders back to planned (clears firm overrides).

        Auth: requires Bearer token.

        FormRequest: BulkPlannedOrderRequest.

        Fields: ids[] (required, exists:mrp_planned_orders).


        :::info[Required scope: `manufacturing:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 101
                - 102
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        mrp_run_id:
                          type: integer
                        product_id:
                          type: integer
                        product:
                          type: object
                          properties:
                            id:
                              type: integer
                            sku:
                              type: string
                            name:
                              type: string
                        warehouse_id:
                          type: integer
                        warehouse:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        supply_type:
                          type: string
                        state:
                          type: string
                        quantity:
                          type: integer
                        net_requirement:
                          type: integer
                        due_date:
                          type: string
                        release_date:
                          type: string
                        bucket_start:
                          type: string
                        lead_time_days:
                          type: integer
                        lot_sizing_rule:
                          type: string
                        supplier_id:
                          type: string
                          nullable: true
                        supplier:
                          type: string
                          nullable: true
                        bom_id:
                          type: integer
                        bom:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        source_warehouse_id:
                          type: string
                          nullable: true
                        low_level_code:
                          type: integer
                        accepted:
                          type: boolean
                        firm_quantity:
                          type: string
                          nullable: true
                        firm_due_date:
                          type: string
                          nullable: true
                        released_order_type:
                          type: string
                          nullable: true
                        released_order_id:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  message:
                    type: string
                example:
                  data:
                  - id: 101
                    mrp_run_id: 42
                    product_id: 9001
                    product:
                      id: 9001
                      sku: WIDGET-A
                      name: Blue Widget Assembly
                    warehouse_id: 3
                    warehouse:
                      id: 3
                      name: Main Distribution Center
                    supply_type: make
                    state: planned
                    quantity: 500
                    net_requirement: 480
                    due_date: '2026-07-15'
                    release_date: '2026-07-01'
                    bucket_start: '2026-06-29'
                    lead_time_days: 14
                    lot_sizing_rule: lot_for_lot
                    supplier_id: null
                    supplier: null
                    bom_id: 55
                    bom:
                      id: 55
                      name: Blue Widget Assembly BOM v3
                    source_warehouse_id: null
                    low_level_code: 1
                    accepted: false
                    firm_quantity: null
                    firm_due_date: null
                    released_order_type: null
                    released_order_id: null
                    created_at: '2026-06-17T14:03:18.000000Z'
                    updated_at: '2026-06-17T14:03:18.000000Z'
                  message: 1 planned orders unfirmed
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: manufacturing:write
      operationId: post-api-manufacturing-mrp-planned-orders-unfirm
  /api/manufacturing/mrp/planned-orders/accept:
    post:
      tags:
      - MRP Planning
      summary: Accept Planned Orders
      description: 'Mark planned orders as accepted (accepted = true).

        Auth: requires Bearer token.

        FormRequest: BulkPlannedOrderRequest.

        Fields: ids[] (required, exists:mrp_planned_orders).


        :::info[Required scope: `manufacturing:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 101
                - 102
                - 103
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        mrp_run_id:
                          type: integer
                        product_id:
                          type: integer
                        product:
                          type: object
                          properties:
                            id:
                              type: integer
                            sku:
                              type: string
                            name:
                              type: string
                        warehouse_id:
                          type: integer
                        warehouse:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        supply_type:
                          type: string
                        state:
                          type: string
                        quantity:
                          type: integer
                        net_requirement:
                          type: integer
                        due_date:
                          type: string
                        release_date:
                          type: string
                        bucket_start:
                          type: string
                        lead_time_days:
                          type: integer
                        lot_sizing_rule:
                          type: string
                        supplier_id:
                          type: integer
                        supplier:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        bom_id:
                          type: string
                          nullable: true
                        bom:
                          type: string
                          nullable: true
                        source_warehouse_id:
                          type: string
                          nullable: true
                        low_level_code:
                          type: integer
                        accepted:
                          type: boolean
                        firm_quantity:
                          type: string
                          nullable: true
                        firm_due_date:
                          type: string
                          nullable: true
                        released_order_type:
                          type: string
                          nullable: true
                        released_order_id:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  message:
                    type: string
                example:
                  data:
                  - id: 101
                    mrp_run_id: 42
                    product_id: 9001
                    product:
                      id: 9001
                      sku: WIDGET-A
                      name: Blue Widget Assembly
                    warehouse_id: 3
                    warehouse:
                      id: 3
                      name: Main Distribution Center
                    supply_type: buy
                    state: planned
                    quantity: 1000
                    net_requirement: 1000
                    due_date: '2026-07-15'
                    release_date: '2026-07-01'
                    bucket_start: '2026-06-29'
                    lead_time_days: 14
                    lot_sizing_rule: fixed_order_qty
                    supplier_id: 7
                    supplier:
                      id: 7
                      name: Acme Components Ltd
                    bom_id: null
                    bom: null
                    source_warehouse_id: null
                    low_level_code: 0
                    accepted: true
                    firm_quantity: null
                    firm_due_date: null
                    released_order_type: null
                    released_order_id: null
                    created_at: '2026-06-17T14:03:18.000000Z'
                    updated_at: '2026-06-17T14:03:18.000000Z'
                  message: 1 planned orders accepted
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: manufacturing:write
      operationId: post-api-manufacturing-mrp-planned-orders-accept
  /api/manufacturing/mrp/planned-orders/dismiss:
    post:
      tags:
      - MRP Planning
      summary: Dismiss Planned Orders
      description: 'Dismiss (delete) the given planned orders from the run. Returns
        a count, not a resource collection.

        Auth: requires Bearer token.

        FormRequest: BulkPlannedOrderRequest.

        Fields: ids[] (required, exists:mrp_planned_orders).


        :::info[Required scope: `manufacturing:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 104
                - 105
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      dismissed:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    dismissed: 2
                  message: 2 planned orders dismissed
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: manufacturing:write
      operationId: post-api-manufacturing-mrp-planned-orders-dismiss
  /api/manufacturing/mrp/planned-orders/release:
    post:
      tags:
      - MRP Planning
      summary: Release Planned Orders
      description: 'Release planned orders into real supply documents: make -> draft
        Manufacturing Orders, buy -> one Purchase Order per supplier, transfer ->
        Warehouse Transfers. Already-released and buy-without-supplier orders are
        skipped. Returns created document IDs grouped by type plus a released count.

        Auth: requires Bearer token.

        FormRequest: ReleasePlannedOrderRequest.

        Fields: ids[] (required, exists:mrp_planned_orders).


        :::info[Required scope: `manufacturing:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 101
                - 102
                - 103
                - 106
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      manufacturing_orders:
                        type: array
                        items:
                          type: integer
                      purchase_orders:
                        type: array
                        items:
                          type: integer
                      warehouse_transfers:
                        type: array
                        items:
                          type: integer
                      released:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    manufacturing_orders:
                    - 3201
                    purchase_orders:
                    - 880
                    warehouse_transfers:
                    - 145
                    released: 4
                  message: 4 planned orders released
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: manufacturing:write
      operationId: post-api-manufacturing-mrp-planned-orders-release
  /api/manufacturing/mrp/planned-orders/{plannedOrder}:
    patch:
      tags:
      - MRP Planning
      summary: Update Planned Order
      description: 'Update a single planned order''s quantity, due date, supplier,
        and/or supply type. All fields optional - send only what changes.

        Auth: requires Bearer token.

        Path param: plannedOrder = planned order id.

        FormRequest: UpdateMrpPlannedOrderRequest.

        Fields: quantity (nullable, numeric, gt:0), due_date (nullable, date), supplier_id
        (nullable, exists:suppliers), supply_type (nullable, in: make, buy, transfer).

        Returns 422 with {message} when the manager rejects the change (e.g. changing
        supply type of a released order).


        :::info[Required scope: `manufacturing:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                quantity:
                  type: integer
                due_date:
                  type: string
                supplier_id:
                  type: integer
                supply_type:
                  type: string
              example:
                quantity: 750
                due_date: '2026-08-01'
                supplier_id: 7
                supply_type: buy
      parameters:
      - name: plannedOrder
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The planned order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      mrp_run_id:
                        type: integer
                      product_id:
                        type: integer
                      product:
                        type: object
                        properties:
                          id:
                            type: integer
                          sku:
                            type: string
                          name:
                            type: string
                      warehouse_id:
                        type: integer
                      warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      supply_type:
                        type: string
                      state:
                        type: string
                      quantity:
                        type: integer
                      net_requirement:
                        type: integer
                      due_date:
                        type: string
                      release_date:
                        type: string
                      bucket_start:
                        type: string
                      lead_time_days:
                        type: integer
                      lot_sizing_rule:
                        type: string
                      supplier_id:
                        type: integer
                      supplier:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      bom_id:
                        type: string
                        nullable: true
                      bom:
                        type: string
                        nullable: true
                      source_warehouse_id:
                        type: string
                        nullable: true
                      low_level_code:
                        type: integer
                      accepted:
                        type: boolean
                      firm_quantity:
                        type: string
                        nullable: true
                      firm_due_date:
                        type: string
                        nullable: true
                      released_order_type:
                        type: string
                        nullable: true
                      released_order_id:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 101
                    mrp_run_id: 42
                    product_id: 9001
                    product:
                      id: 9001
                      sku: WIDGET-A
                      name: Blue Widget Assembly
                    warehouse_id: 3
                    warehouse:
                      id: 3
                      name: Main Distribution Center
                    supply_type: buy
                    state: planned
                    quantity: 750
                    net_requirement: 480
                    due_date: '2026-08-01'
                    release_date: '2026-07-01'
                    bucket_start: '2026-06-29'
                    lead_time_days: 25
                    lot_sizing_rule: fixed_order_qty
                    supplier_id: 7
                    supplier:
                      id: 7
                      name: Acme Components Ltd
                    bom_id: null
                    bom: null
                    source_warehouse_id: null
                    low_level_code: 1
                    accepted: false
                    firm_quantity: null
                    firm_due_date: null
                    released_order_type: null
                    released_order_id: null
                    created_at: '2026-06-17T14:03:18.000000Z'
                    updated_at: '2026-06-17T14:03:18.000000Z'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Cannot change supply type of a released planned order.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: manufacturing:write
      operationId: patch-api-manufacturing-mrp-planned-orders-plannedorder
  /api/manufacturing/mrp/planning-policies:
    get:
      tags:
      - MRP Planning
      summary: List Planning Policies
      description: 'Paginated list of item planning policies (item-level defaults
        and warehouse overrides), product and warehouse eager-loaded, ordered by id
        desc.

        Auth: requires Bearer token.

        Filters: filter[planning_method], filter[procurement_type], filter[warehouse_id],
        search (LIKE on product sku/name).

        Note: page size is fixed at 10 - per_page is accepted but ignored for this
        endpoint.


        :::info[Required scope: `manufacturing:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        product_id:
                          type: integer
                        product:
                          type: object
                          properties:
                            id:
                              type: integer
                            sku:
                              type: string
                            name:
                              type: string
                        warehouse_id:
                          type: integer
                        warehouse:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        is_warehouse_override:
                          type: boolean
                        planning_method:
                          type: string
                        procurement_type:
                          type: string
                        lot_sizing_rule:
                          type: string
                        order_minimum:
                          type: integer
                        order_multiple:
                          type: integer
                        order_maximum:
                          type: integer
                        fixed_order_quantity:
                          type: integer
                        period_order_days:
                          type: integer
                        days_of_supply:
                          type: string
                          nullable: true
                        eoq_ordering_cost:
                          type: string
                          nullable: true
                        eoq_holding_cost_pct:
                          type: string
                          nullable: true
                        safety_stock:
                          type: integer
                        safety_lead_time_days:
                          type: integer
                        reorder_point:
                          type: integer
                        reorder_up_to_level:
                          type: integer
                        lead_time_source:
                          type: string
                        lead_time_days:
                          type: integer
                        demand_time_fence_days:
                          type: integer
                        planning_time_fence_days:
                          type: integer
                        release_time_fence_days:
                          type: integer
                        is_phantom_planning:
                          type: boolean
                        make_to_order:
                          type: boolean
                        planning_calendar_id:
                          type: string
                          nullable: true
                        low_level_code:
                          type: integer
                        dampener_days:
                          type: integer
                        dampener_qty:
                          type: integer
                        dampener_pct:
                          type: integer
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 42
                    product_id: 1001
                    product:
                      id: 1001
                      sku: WIDGET-RED
                      name: Red Widget
                    warehouse_id: 3
                    warehouse:
                      id: 3
                      name: Main Warehouse
                    is_warehouse_override: true
                    planning_method: mrp
                    procurement_type: make
                    lot_sizing_rule: fixed_order_qty
                    order_minimum: 10
                    order_multiple: 5
                    order_maximum: 1000
                    fixed_order_quantity: 100
                    period_order_days: 7
                    days_of_supply: null
                    eoq_ordering_cost: null
                    eoq_holding_cost_pct: null
                    safety_stock: 25
                    safety_lead_time_days: 2
                    reorder_point: 50
                    reorder_up_to_level: 200
                    lead_time_source: manual
                    lead_time_days: 14
                    demand_time_fence_days: 7
                    planning_time_fence_days: 30
                    release_time_fence_days: 3
                    is_phantom_planning: false
                    make_to_order: false
                    planning_calendar_id: null
                    low_level_code: 0
                    dampener_days: 1
                    dampener_qty: 5
                    dampener_pct: 10
                    created_at: '2026-06-17T14:22:05.000000Z'
                    updated_at: '2026-06-18T09:10:41.000000Z'
                  current_page: 1
                  first_page_url: '...'
                  from: 1
                  last_page: 1
                  last_page_url: '...'
                  links: []
                  next_page_url: null
                  path: '...'
                  per_page: 10
                  prev_page_url: null
                  to: 1
                  total: 37
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: manufacturing:read
      operationId: get-api-manufacturing-mrp-planning-policies
  /api/manufacturing/mrp/planning-policies/{product}:
    get:
      tags:
      - MRP Planning
      summary: Get Planning Policy
      description: 'Resolve the effective item-level policy for a product. Returns
        data: null when no policy exists.

        Auth: requires Bearer token.

        Path param: product = product id.


        :::info[Required scope: `manufacturing:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: product
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The product ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 OK
                  value:
                    data:
                      id: 42
                      product_id: 1001
                      product:
                        id: 1001
                        sku: WIDGET-RED
                        name: Red Widget
                      warehouse_id: null
                      warehouse: null
                      is_warehouse_override: false
                      planning_method: reorder_point
                      procurement_type: buy
                      lot_sizing_rule: min_max
                      order_minimum: 10
                      order_multiple: null
                      order_maximum: null
                      fixed_order_quantity: null
                      period_order_days: null
                      days_of_supply: null
                      eoq_ordering_cost: null
                      eoq_holding_cost_pct: null
                      safety_stock: 25
                      safety_lead_time_days: 0
                      reorder_point: 50
                      reorder_up_to_level: 200
                      lead_time_source: supplier
                      lead_time_days: 14
                      demand_time_fence_days: 0
                      planning_time_fence_days: 0
                      release_time_fence_days: 0
                      is_phantom_planning: false
                      make_to_order: false
                      planning_calendar_id: null
                      low_level_code: 0
                      dampener_days: null
                      dampener_qty: null
                      dampener_pct: null
                      created_at: '2026-06-17T14:22:05.000000Z'
                      updated_at: '2026-06-18T09:10:41.000000Z'
                example-1:
                  summary: 200 No Policy
                  value:
                    data: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: manufacturing:read
      operationId: get-api-manufacturing-mrp-planning-policies-product
    put:
      tags:
      - MRP Planning
      summary: Upsert Planning Policy
      description: 'Create or update the planning policy for a product (and optional
        warehouse scope).

        Auth: requires Bearer token.

        Path param: product = product id.

        Body fields (UpsertItemPlanningPolicyRequest / shared policyAttributeRules):
        warehouse_id (nullable, exists:warehouses; null = item-level default), planning_method
        (required, in: mrp, reorder_point, mps, min_max, none), procurement_type (nullable,
        in: make, buy, transfer, make_or_buy), lot_sizing_rule (required, in: lot_for_lot,
        fixed_order_qty, min_max, eoq, period_order_qty, days_of_supply, fixed_period),
        lead_time_source (nullable, in: manual, bom, supplier, computed), order_minimum,
        order_multiple, order_maximum, fixed_order_quantity, days_of_supply, eoq_ordering_cost,
        eoq_holding_cost_pct, safety_stock, reorder_point, reorder_up_to_level, dampener_qty,
        dampener_pct (numeric, nullable), period_order_days, safety_lead_time_days,
        lead_time_days, demand_time_fence_days, planning_time_fence_days, release_time_fence_days,
        low_level_code, dampener_days (integer, nullable), planning_calendar_id (nullable,
        exists:planning_calendars), is_phantom_planning, make_to_order (boolean, nullable).

        Returns 422 {message} on manager coherence violations (e.g. fixed_order_quantity
        required when lot_sizing_rule=fixed_order_qty; eoq costs required when lot_sizing_rule=eoq;
        reorder_point required when planning_method is min_max or reorder_point).


        :::info[Required scope: `manufacturing:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                warehouse_id:
                  type: integer
                planning_method:
                  type: string
                procurement_type:
                  type: string
                lot_sizing_rule:
                  type: string
                lead_time_source:
                  type: string
                order_minimum:
                  type: integer
                order_multiple:
                  type: integer
                order_maximum:
                  type: integer
                fixed_order_quantity:
                  type: integer
                days_of_supply:
                  type: string
                  nullable: true
                eoq_ordering_cost:
                  type: string
                  nullable: true
                eoq_holding_cost_pct:
                  type: string
                  nullable: true
                safety_stock:
                  type: integer
                reorder_point:
                  type: integer
                reorder_up_to_level:
                  type: integer
                dampener_qty:
                  type: integer
                dampener_pct:
                  type: integer
                period_order_days:
                  type: integer
                safety_lead_time_days:
                  type: integer
                lead_time_days:
                  type: integer
                demand_time_fence_days:
                  type: integer
                planning_time_fence_days:
                  type: integer
                release_time_fence_days:
                  type: integer
                low_level_code:
                  type: integer
                dampener_days:
                  type: integer
                planning_calendar_id:
                  type: string
                  nullable: true
                is_phantom_planning:
                  type: boolean
                make_to_order:
                  type: boolean
              example:
                warehouse_id: 3
                planning_method: mrp
                procurement_type: make
                lot_sizing_rule: fixed_order_qty
                lead_time_source: manual
                order_minimum: 10
                order_multiple: 5
                order_maximum: 1000
                fixed_order_quantity: 100
                days_of_supply: null
                eoq_ordering_cost: null
                eoq_holding_cost_pct: null
                safety_stock: 25
                reorder_point: 50
                reorder_up_to_level: 200
                dampener_qty: 5
                dampener_pct: 10
                period_order_days: 7
                safety_lead_time_days: 2
                lead_time_days: 14
                demand_time_fence_days: 7
                planning_time_fence_days: 30
                release_time_fence_days: 3
                low_level_code: 0
                dampener_days: 1
                planning_calendar_id: null
                is_phantom_planning: false
                make_to_order: false
      parameters:
      - name: product
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The product ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      product_id:
                        type: integer
                      product:
                        type: object
                        properties:
                          id:
                            type: integer
                          sku:
                            type: string
                          name:
                            type: string
                      warehouse_id:
                        type: integer
                      warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      is_warehouse_override:
                        type: boolean
                      planning_method:
                        type: string
                      procurement_type:
                        type: string
                      lot_sizing_rule:
                        type: string
                      order_minimum:
                        type: integer
                      order_multiple:
                        type: integer
                      order_maximum:
                        type: integer
                      fixed_order_quantity:
                        type: integer
                      period_order_days:
                        type: integer
                      days_of_supply:
                        type: string
                        nullable: true
                      eoq_ordering_cost:
                        type: string
                        nullable: true
                      eoq_holding_cost_pct:
                        type: string
                        nullable: true
                      safety_stock:
                        type: integer
                      safety_lead_time_days:
                        type: integer
                      reorder_point:
                        type: integer
                      reorder_up_to_level:
                        type: integer
                      lead_time_source:
                        type: string
                      lead_time_days:
                        type: integer
                      demand_time_fence_days:
                        type: integer
                      planning_time_fence_days:
                        type: integer
                      release_time_fence_days:
                        type: integer
                      is_phantom_planning:
                        type: boolean
                      make_to_order:
                        type: boolean
                      planning_calendar_id:
                        type: string
                        nullable: true
                      low_level_code:
                        type: integer
                      dampener_days:
                        type: integer
                      dampener_qty:
                        type: integer
                      dampener_pct:
                        type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 42
                    product_id: 1001
                    product:
                      id: 1001
                      sku: WIDGET-RED
                      name: Red Widget
                    warehouse_id: 3
                    warehouse:
                      id: 3
                      name: Main Warehouse
                    is_warehouse_override: true
                    planning_method: mrp
                    procurement_type: make
                    lot_sizing_rule: fixed_order_qty
                    order_minimum: 10
                    order_multiple: 5
                    order_maximum: 1000
                    fixed_order_quantity: 100
                    period_order_days: 7
                    days_of_supply: null
                    eoq_ordering_cost: null
                    eoq_holding_cost_pct: null
                    safety_stock: 25
                    safety_lead_time_days: 2
                    reorder_point: 50
                    reorder_up_to_level: 200
                    lead_time_source: manual
                    lead_time_days: 14
                    demand_time_fence_days: 7
                    planning_time_fence_days: 30
                    release_time_fence_days: 3
                    is_phantom_planning: false
                    make_to_order: false
                    planning_calendar_id: null
                    low_level_code: 0
                    dampener_days: 1
                    dampener_qty: 5
                    dampener_pct: 10
                    created_at: '2026-06-17T14:22:05.000000Z'
                    updated_at: '2026-06-18T09:10:41.000000Z'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: A fixed order quantity greater than zero is required when
                    the lot sizing rule is fixed_order_qty.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: manufacturing:write
      operationId: put-api-manufacturing-mrp-planning-policies-product
  /api/manufacturing/mrp/planning-policies/bulk-apply:
    post:
      tags:
      - MRP Planning
      summary: Bulk Apply Planning Policy
      description: 'Apply one identical set of policy attributes to many products
        at once.

        Auth: requires Bearer token.

        FormRequest: BulkApplyPlanningPolicyRequest.

        Fields: product_ids[] (required, min:1, exists:products), warehouse_id (nullable,
        exists:warehouses), plus the shared policyAttributeRules() (planning_method
        and lot_sizing_rule required; rest as in Upsert Planning Policy).


        :::info[Required scope: `manufacturing:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                product_ids:
                  type: array
                  items:
                    type: integer
                warehouse_id:
                  type: integer
                planning_method:
                  type: string
                procurement_type:
                  type: string
                lot_sizing_rule:
                  type: string
                lead_time_source:
                  type: string
                order_minimum:
                  type: integer
                order_multiple:
                  type: string
                  nullable: true
                order_maximum:
                  type: string
                  nullable: true
                fixed_order_quantity:
                  type: string
                  nullable: true
                days_of_supply:
                  type: string
                  nullable: true
                eoq_ordering_cost:
                  type: string
                  nullable: true
                eoq_holding_cost_pct:
                  type: string
                  nullable: true
                safety_stock:
                  type: integer
                reorder_point:
                  type: integer
                reorder_up_to_level:
                  type: integer
                dampener_qty:
                  type: string
                  nullable: true
                dampener_pct:
                  type: string
                  nullable: true
                period_order_days:
                  type: string
                  nullable: true
                safety_lead_time_days:
                  type: integer
                lead_time_days:
                  type: integer
                demand_time_fence_days:
                  type: integer
                planning_time_fence_days:
                  type: integer
                release_time_fence_days:
                  type: integer
                low_level_code:
                  type: integer
                dampener_days:
                  type: string
                  nullable: true
                planning_calendar_id:
                  type: string
                  nullable: true
                is_phantom_planning:
                  type: boolean
                make_to_order:
                  type: boolean
              example:
                product_ids:
                - 1001
                - 1002
                - 1003
                warehouse_id: 3
                planning_method: reorder_point
                procurement_type: buy
                lot_sizing_rule: min_max
                lead_time_source: supplier
                order_minimum: 10
                order_multiple: null
                order_maximum: null
                fixed_order_quantity: null
                days_of_supply: null
                eoq_ordering_cost: null
                eoq_holding_cost_pct: null
                safety_stock: 25
                reorder_point: 50
                reorder_up_to_level: 200
                dampener_qty: null
                dampener_pct: null
                period_order_days: null
                safety_lead_time_days: 2
                lead_time_days: 14
                demand_time_fence_days: 0
                planning_time_fence_days: 0
                release_time_fence_days: 0
                low_level_code: 0
                dampener_days: null
                planning_calendar_id: null
                is_phantom_planning: false
                make_to_order: false
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        product_id:
                          type: integer
                        product:
                          type: object
                          properties:
                            id:
                              type: integer
                            sku:
                              type: string
                            name:
                              type: string
                        warehouse_id:
                          type: integer
                        warehouse:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        is_warehouse_override:
                          type: boolean
                        planning_method:
                          type: string
                        procurement_type:
                          type: string
                        lot_sizing_rule:
                          type: string
                        order_minimum:
                          type: integer
                        order_multiple:
                          type: string
                          nullable: true
                        order_maximum:
                          type: string
                          nullable: true
                        fixed_order_quantity:
                          type: string
                          nullable: true
                        period_order_days:
                          type: string
                          nullable: true
                        days_of_supply:
                          type: string
                          nullable: true
                        eoq_ordering_cost:
                          type: string
                          nullable: true
                        eoq_holding_cost_pct:
                          type: string
                          nullable: true
                        safety_stock:
                          type: integer
                        safety_lead_time_days:
                          type: integer
                        reorder_point:
                          type: integer
                        reorder_up_to_level:
                          type: integer
                        lead_time_source:
                          type: string
                        lead_time_days:
                          type: integer
                        demand_time_fence_days:
                          type: integer
                        planning_time_fence_days:
                          type: integer
                        release_time_fence_days:
                          type: integer
                        is_phantom_planning:
                          type: boolean
                        make_to_order:
                          type: boolean
                        planning_calendar_id:
                          type: string
                          nullable: true
                        low_level_code:
                          type: integer
                        dampener_days:
                          type: string
                          nullable: true
                        dampener_qty:
                          type: string
                          nullable: true
                        dampener_pct:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  message:
                    type: string
                example:
                  data:
                  - id: 42
                    product_id: 1001
                    product:
                      id: 1001
                      sku: WIDGET-RED
                      name: Red Widget
                    warehouse_id: 3
                    warehouse:
                      id: 3
                      name: Main Warehouse
                    is_warehouse_override: true
                    planning_method: reorder_point
                    procurement_type: buy
                    lot_sizing_rule: min_max
                    order_minimum: 10
                    order_multiple: null
                    order_maximum: null
                    fixed_order_quantity: null
                    period_order_days: null
                    days_of_supply: null
                    eoq_ordering_cost: null
                    eoq_holding_cost_pct: null
                    safety_stock: 25
                    safety_lead_time_days: 2
                    reorder_point: 50
                    reorder_up_to_level: 200
                    lead_time_source: supplier
                    lead_time_days: 14
                    demand_time_fence_days: 0
                    planning_time_fence_days: 0
                    release_time_fence_days: 0
                    is_phantom_planning: false
                    make_to_order: false
                    planning_calendar_id: null
                    low_level_code: 0
                    dampener_days: null
                    dampener_qty: null
                    dampener_pct: null
                    created_at: '2026-06-17T14:22:05.000000Z'
                    updated_at: '2026-06-18T09:10:41.000000Z'
                  - id: 43
                    product_id: 1002
                    product:
                      id: 1002
                      sku: WIDGET-BLUE
                      name: Blue Widget
                    warehouse_id: 3
                    warehouse:
                      id: 3
                      name: Main Warehouse
                    is_warehouse_override: true
                    planning_method: reorder_point
                    procurement_type: buy
                    lot_sizing_rule: min_max
                    order_minimum: 10
                    order_multiple: null
                    order_maximum: null
                    fixed_order_quantity: null
                    period_order_days: null
                    days_of_supply: null
                    eoq_ordering_cost: null
                    eoq_holding_cost_pct: null
                    safety_stock: 25
                    safety_lead_time_days: 2
                    reorder_point: 50
                    reorder_up_to_level: 200
                    lead_time_source: supplier
                    lead_time_days: 14
                    demand_time_fence_days: 0
                    planning_time_fence_days: 0
                    release_time_fence_days: 0
                    is_phantom_planning: false
                    make_to_order: false
                    planning_calendar_id: null
                    low_level_code: 0
                    dampener_days: null
                    dampener_qty: null
                    dampener_pct: null
                    created_at: '2026-06-17T14:22:05.000000Z'
                    updated_at: '2026-06-18T09:10:41.000000Z'
                  message: 3 policies updated
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: manufacturing:write
      operationId: post-api-manufacturing-mrp-planning-policies-bulk-apply
  /api/manufacturing/mrp/action-messages/accept:
    post:
      tags:
      - MRP Planning
      summary: Accept Action Messages
      description: 'Accept one or more MRP action messages (planner agrees with the
        recommendation). Returns a count.

        Auth: requires Bearer token.

        FormRequest: BulkActionMessageRequest.

        Fields: ids[] (required, min:1, exists:mrp_action_messages).


        :::info[Required scope: `manufacturing:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 501
                - 502
                - 503
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      accepted:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    accepted: 3
                  message: 3 action messages accepted
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: manufacturing:write
      operationId: post-api-manufacturing-mrp-action-messages-accept
  /api/manufacturing/mrp/action-messages/dismiss:
    post:
      tags:
      - MRP Planning
      summary: Dismiss Action Messages
      description: 'Dismiss one or more MRP action messages (planner rejects/ignores
        the recommendation). Returns a count.

        Auth: requires Bearer token.

        FormRequest: BulkActionMessageRequest.

        Fields: ids[] (required, min:1, exists:mrp_action_messages).


        :::info[Required scope: `manufacturing:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 504
                - 505
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      dismissed:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    dismissed: 2
                  message: 2 action messages dismissed
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: manufacturing:write
      operationId: post-api-manufacturing-mrp-action-messages-dismiss
  /api/manufacturing/mrp/mps:
    get:
      tags:
      - MRP Planning
      summary: List MPS Entries
      description: 'Paginated list of Master Production Schedule entries (time-phased
        independent demand), product and warehouse eager-loaded.

        Auth: requires Bearer token.

        Pagination defaults: per_page=10 (honored).


        :::info[Required scope: `manufacturing:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        product_id:
                          type: integer
                        product:
                          type: object
                          properties:
                            id:
                              type: integer
                            sku:
                              type: string
                            name:
                              type: string
                        warehouse_id:
                          type: integer
                        warehouse:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        bucket_start:
                          type: string
                        quantity:
                          type: integer
                        source:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 5
                    product_id: 1001
                    product:
                      id: 1001
                      sku: WIDGET-RED
                      name: Red Widget
                    warehouse_id: 3
                    warehouse:
                      id: 3
                      name: Main Warehouse
                    bucket_start: '2026-06-22'
                    quantity: 250
                    source: manual
                    created_at: '2026-06-17T14:22:05.000000Z'
                    updated_at: '2026-06-18T09:10:41.000000Z'
                  current_page: 1
                  first_page_url: '...'
                  from: 1
                  last_page: 1
                  last_page_url: '...'
                  links: []
                  next_page_url: null
                  path: '...'
                  per_page: 10
                  prev_page_url: null
                  to: 1
                  total: 14
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: manufacturing:read
      operationId: get-api-manufacturing-mrp-mps
    put:
      tags:
      - MRP Planning
      summary: Upsert MPS Entry
      description: 'Create or update one MPS entry keyed on (product_id, warehouse_id,
        bucket_start).

        Auth: requires Bearer token.

        FormRequest: UpsertMpsEntryRequest.

        Fields: product_id (required, exists:products), warehouse_id (required, exists:warehouses),
        bucket_start (required, date), quantity (required, numeric, min:0), source
        (sometimes, in: manual, forecast, drp; defaults manual).


        :::info[Required scope: `manufacturing:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                product_id:
                  type: integer
                warehouse_id:
                  type: integer
                bucket_start:
                  type: string
                quantity:
                  type: integer
                source:
                  type: string
              example:
                product_id: 1001
                warehouse_id: 3
                bucket_start: '2026-06-22'
                quantity: 250
                source: manual
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      product_id:
                        type: integer
                      warehouse_id:
                        type: integer
                      bucket_start:
                        type: string
                      quantity:
                        type: integer
                      source:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 5
                    product_id: 1001
                    warehouse_id: 3
                    bucket_start: '2026-06-22'
                    quantity: 250
                    source: manual
                    created_at: '2026-06-18T09:10:41.000000Z'
                    updated_at: '2026-06-18T09:10:41.000000Z'
                  message: MPS entry saved
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: manufacturing:write
      operationId: put-api-manufacturing-mrp-mps
  /api/manufacturing/mrp/mps/grid:
    get:
      tags:
      - MRP Planning
      summary: Get MPS Grid
      description: 'Per-product, per-bucket MPS grid. Plain array. Each cell exposes
        mps_qty plus forecast and customer_orders placeholders.

        Auth: requires Bearer token.

        Query: product_ids[] (grid rows; default none), warehouse_id (scope grid to
        one warehouse).


        :::info[Required scope: `manufacturing:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      warehouse_id:
                        type: integer
                      products:
                        type: array
                        items:
                          type: object
                          properties:
                            product_id:
                              type: integer
                            buckets:
                              type: array
                              items:
                                type: object
                                properties:
                                  bucket_start:
                                    type: string
                                  forecast:
                                    type: integer
                                  customer_orders:
                                    type: integer
                                  mps_qty:
                                    type: integer
                example:
                  data:
                    warehouse_id: 3
                    products:
                    - product_id: 1001
                      buckets:
                      - bucket_start: '2026-06-22'
                        forecast: 0
                        customer_orders: 0
                        mps_qty: 250
                      - bucket_start: '2026-06-29'
                        forecast: 0
                        customer_orders: 0
                        mps_qty: 300
                    - product_id: 1002
                      buckets: []
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: manufacturing:read
      operationId: get-api-manufacturing-mrp-mps-grid
  /api/manufacturing/mrp/mps/{mpsEntry}:
    delete:
      tags:
      - MRP Planning
      summary: Delete MPS Entry
      description: 'Delete one MPS entry by id. Returns 204 No Content.

        Auth: requires Bearer token.

        Path param: mpsEntry = MPS entry id.


        :::info[Required scope: `manufacturing:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: mpsEntry
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The mps entry ID.
      responses:
        '204':
          description: No Content
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties: {}
                example: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: manufacturing:write
      operationId: delete-api-manufacturing-mrp-mps-mpsentry
  /api/manufacturing/mrp/atp:
    post:
      tags:
      - MRP Planning
      summary: Check Available-to-Promise (ATP)
      description: 'Compute Available-To-Promise quantity for a product at a warehouse
        (on-hand + inbound + in-transit; excludes forecast). Plain array.

        Auth: requires Bearer token.

        FormRequest: AtpCheckRequest.

        Fields: product_id (required, exists:products), warehouse_id (required, exists:warehouses),
        method (in: discrete, cumulative_no_lookahead, cumulative_lookahead; default
        cumulative_lookahead).


        :::info[Required scope: `manufacturing:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                product_id:
                  type: integer
                warehouse_id:
                  type: integer
                method:
                  type: string
              example:
                product_id: 1001
                warehouse_id: 3
                method: cumulative_lookahead
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      product_id:
                        type: integer
                      warehouse_id:
                        type: integer
                      method:
                        type: string
                      atp_quantity:
                        type: integer
                      detail:
                        type: object
                        properties:
                          available:
                            type: integer
                          inbound:
                            type: integer
                          in_transit:
                            type: integer
                example:
                  data:
                    product_id: 1001
                    warehouse_id: 3
                    method: cumulative_lookahead
                    atp_quantity: 480
                    detail:
                      available: 300
                      inbound: 150
                      in_transit: 30
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: manufacturing:write
      operationId: post-api-manufacturing-mrp-atp
  /api/manufacturing/mrp/ctp:
    post:
      tags:
      - MRP Planning
      summary: Check Capable-to-Promise (CTP)
      description: 'Capable-To-Promise: determine how much of a requested quantity
        can be promised - directly from ATP, or by exploding the active BOM and checking
        component availability for the shortfall. Plain array.

        Auth: requires Bearer token.

        FormRequest: CtpCheckRequest.

        Fields: product_id (required, exists:products), warehouse_id (required, exists:warehouses),
        quantity (required, numeric, gt:0).


        :::info[Required scope: `manufacturing:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                product_id:
                  type: integer
                warehouse_id:
                  type: integer
                quantity:
                  type: integer
              example:
                product_id: 1001
                warehouse_id: 3
                quantity: 600
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 Fully Promisable
                  value:
                    data:
                      product_id: 1001
                      requested_quantity: 600
                      promisable_quantity: 600
                      can_promise: true
                      atp_quantity: 720
                      buildable_quantity: 0
                      limiting_components: []
                example-1:
                  summary: 200 Partial (BOM)
                  value:
                    data:
                      product_id: 1001
                      requested_quantity: 600
                      promisable_quantity: 560
                      can_promise: false
                      atp_quantity: 480
                      buildable_quantity: 80
                      limiting_components:
                      - product_id: 2001
                        required_per_unit: 2
                        available: 400
                        buildable_units: 200
                      - product_id: 2002
                        required_per_unit: 1
                        available: 80
                        buildable_units: 80
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: manufacturing:write
      operationId: post-api-manufacturing-mrp-ctp
  /api/manufacturing/mrp/distribution-network:
    get:
      tags:
      - MRP Planning
      summary: List Distribution Edges
      description: 'Paginated distribution-network edges (warehouse-to-warehouse replenishment
        links), ordered by priority then id. Source/destination warehouses eager-loaded.

        Auth: requires Bearer token.

        Pagination defaults: per_page=10.


        :::info[Required scope: `manufacturing:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        source_warehouse_id:
                          type: integer
                        source_warehouse:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        destination_warehouse_id:
                          type: integer
                        destination_warehouse:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        transfer_lead_time_days:
                          type: integer
                        priority:
                          type: integer
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 1
                    source_warehouse_id: 10
                    source_warehouse:
                      id: 10
                      name: Main DC
                    destination_warehouse_id: 22
                    destination_warehouse:
                      id: 22
                      name: West Coast Store
                    transfer_lead_time_days: 3
                    priority: 1
                    created_at: '2026-06-01T14:20:05.000000Z'
                    updated_at: '2026-06-10T09:11:42.000000Z'
                  current_page: 1
                  first_page_url: '...'
                  from: 1
                  last_page: 1
                  last_page_url: '...'
                  links: []
                  next_page_url: null
                  path: '...'
                  per_page: 10
                  prev_page_url: null
                  to: 1
                  total: 1
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: manufacturing:read
      operationId: get-api-manufacturing-mrp-distribution-network
    post:
      tags:
      - MRP Planning
      summary: Create Distribution Edge
      description: 'Create a distribution edge. Self-edges and cycles are rejected
        with 422 {message}.

        Auth: requires Bearer token.

        FormRequest: UpsertDistributionNetworkRequest.

        Fields: source_warehouse_id (required, exists:warehouses), destination_warehouse_id
        (required, exists:warehouses, different:source), transfer_lead_time_days (nullable,
        integer, min:0), priority (nullable, integer).


        :::info[Required scope: `manufacturing:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                source_warehouse_id:
                  type: integer
                destination_warehouse_id:
                  type: integer
                transfer_lead_time_days:
                  type: integer
                priority:
                  type: integer
              example:
                source_warehouse_id: 10
                destination_warehouse_id: 22
                transfer_lead_time_days: 3
                priority: 1
      parameters: []
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      source_warehouse_id:
                        type: integer
                      source_warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      destination_warehouse_id:
                        type: integer
                      destination_warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      transfer_lead_time_days:
                        type: integer
                      priority:
                        type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 5
                    source_warehouse_id: 10
                    source_warehouse:
                      id: 10
                      name: Main DC
                    destination_warehouse_id: 22
                    destination_warehouse:
                      id: 22
                      name: West Coast Store
                    transfer_lead_time_days: 3
                    priority: 1
                    created_at: '2026-06-18T12:00:00.000000Z'
                    updated_at: '2026-06-18T12:00:00.000000Z'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: This edge would create a cycle in the distribution network.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: manufacturing:write
      operationId: post-api-manufacturing-mrp-distribution-network
  /api/manufacturing/mrp/distribution-network/{distributionNetwork}:
    put:
      tags:
      - MRP Planning
      summary: Update Distribution Edge
      description: 'Update an existing edge (acyclic-graph check re-runs on endpoint
        changes). Same FormRequest as create - source/destination remain required.

        Auth: requires Bearer token.

        Path param: distributionNetwork = edge id.

        Fields: source_warehouse_id (required, exists:warehouses), destination_warehouse_id
        (required, exists:warehouses, different:source), transfer_lead_time_days (nullable,
        integer, min:0), priority (nullable, integer).


        :::info[Required scope: `manufacturing:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                source_warehouse_id:
                  type: integer
                destination_warehouse_id:
                  type: integer
                transfer_lead_time_days:
                  type: integer
                priority:
                  type: integer
              example:
                source_warehouse_id: 10
                destination_warehouse_id: 30
                transfer_lead_time_days: 5
                priority: 2
      parameters:
      - name: distributionNetwork
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The distribution network ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      source_warehouse_id:
                        type: integer
                      source_warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      destination_warehouse_id:
                        type: integer
                      destination_warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      transfer_lead_time_days:
                        type: integer
                      priority:
                        type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 5
                    source_warehouse_id: 10
                    source_warehouse:
                      id: 10
                      name: Main DC
                    destination_warehouse_id: 30
                    destination_warehouse:
                      id: 30
                      name: East Coast Store
                    transfer_lead_time_days: 5
                    priority: 2
                    created_at: '2026-06-01T14:20:05.000000Z'
                    updated_at: '2026-06-18T12:05:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: manufacturing:write
      operationId: put-api-manufacturing-mrp-distribution-network-distributionnetwork
    delete:
      tags:
      - MRP Planning
      summary: Delete Distribution Edge
      description: 'Delete a distribution edge. Returns 204 No Content.

        Auth: requires Bearer token.

        Path param: distributionNetwork = edge id.


        :::info[Required scope: `manufacturing:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: distributionNetwork
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The distribution network ID.
      responses:
        '204':
          description: No Content
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties: {}
                example: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: manufacturing:write
      operationId: delete-api-manufacturing-mrp-distribution-network-distributionnetwork
  /api/manufacturing/mrp/scenarios:
    get:
      tags:
      - MRP Planning
      summary: List Scenarios
      description: 'Paginated MRP what-if scenarios, newest first. No relations loaded.

        Auth: requires Bearer token.

        Pagination defaults: per_page=10.


        :::info[Required scope: `manufacturing:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        description:
                          type: string
                        base_run_id:
                          type: integer
                        status:
                          type: string
                        overrides:
                          type: object
                          properties:
                            demand_multiplier:
                              type: number
                            lead_time_buffer_days:
                              type: integer
                        created_by_user_id:
                          type: integer
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 3
                    name: Holiday demand spike
                    description: Model a 30% Q4 surge
                    base_run_id: 12
                    status: draft
                    overrides:
                      demand_multiplier: 1.3
                      lead_time_buffer_days: 5
                    created_by_user_id: 7
                    created_at: '2026-06-15T10:00:00.000000Z'
                    updated_at: '2026-06-15T10:00:00.000000Z'
                  current_page: 1
                  first_page_url: '...'
                  from: 1
                  last_page: 1
                  last_page_url: '...'
                  links: []
                  next_page_url: null
                  path: '...'
                  per_page: 10
                  prev_page_url: null
                  to: 1
                  total: 1
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: manufacturing:read
      operationId: get-api-manufacturing-mrp-scenarios
    post:
      tags:
      - MRP Planning
      summary: Create Scenario
      description: 'Create a scenario. created_by_user_id is set from the authenticated
        user; status defaults to draft (not settable here).

        Auth: requires Bearer token.

        FormRequest: UpsertMrpScenarioRequest.

        Fields: name (required, max:255), description (nullable), base_run_id (nullable,
        exists:mrp_runs), overrides (nullable, array/object).


        :::info[Required scope: `manufacturing:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                description:
                  type: string
                base_run_id:
                  type: integer
                overrides:
                  type: object
                  properties:
                    demand_multiplier:
                      type: number
                    lead_time_buffer_days:
                      type: integer
              example:
                name: Holiday demand spike
                description: Model a 30% Q4 surge
                base_run_id: 12
                overrides:
                  demand_multiplier: 1.3
                  lead_time_buffer_days: 5
      parameters: []
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      description:
                        type: string
                      base_run_id:
                        type: integer
                      status:
                        type: string
                      overrides:
                        type: object
                        properties:
                          demand_multiplier:
                            type: number
                          lead_time_buffer_days:
                            type: integer
                      created_by_user_id:
                        type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 3
                    name: Holiday demand spike
                    description: Model a 30% Q4 surge
                    base_run_id: 12
                    status: draft
                    overrides:
                      demand_multiplier: 1.3
                      lead_time_buffer_days: 5
                    created_by_user_id: 7
                    created_at: '2026-06-18T12:00:00.000000Z'
                    updated_at: '2026-06-18T12:00:00.000000Z'
                  message: Scenario created
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: manufacturing:write
      operationId: post-api-manufacturing-mrp-scenarios
  /api/manufacturing/mrp/scenarios/compare:
    get:
      tags:
      - MRP Planning
      summary: Compare Scenario Runs
      description: 'Compare the planned-order output of two MRP RUNS (not scenarios)
        and return aggregate deltas. Plain object. Validation is inline.

        Auth: requires Bearer token.

        Query (both required): run_id_a (exists:mrp_runs), run_id_b (exists:mrp_runs).


        :::info[Required scope: `manufacturing:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: run_id_a
        in: query
        schema:
          type: integer
        description: First MRP run to compare (required, exists:mrp_runs)
        example: '12'
      - name: run_id_b
        in: query
        schema:
          type: integer
        description: Second MRP run to compare (required, exists:mrp_runs)
        example: '15'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      run_id_a:
                        type: integer
                      run_id_b:
                        type: integer
                      planned_orders_a:
                        type: integer
                      planned_orders_b:
                        type: integer
                      total_qty_a:
                        type: integer
                      total_qty_b:
                        type: number
                      by_supply_type:
                        type: object
                        properties:
                          manufacture:
                            type: object
                            properties:
                              count_a:
                                type: integer
                              count_b:
                                type: integer
                              qty_a:
                                type: integer
                              qty_b:
                                type: integer
                          purchase:
                            type: object
                            properties:
                              count_a:
                                type: integer
                              count_b:
                                type: integer
                              qty_a:
                                type: integer
                              qty_b:
                                type: number
                          transfer:
                            type: object
                            properties:
                              count_a:
                                type: integer
                              count_b:
                                type: integer
                              qty_a:
                                type: integer
                              qty_b:
                                type: integer
                example:
                  data:
                    run_id_a: 12
                    run_id_b: 15
                    planned_orders_a: 48
                    planned_orders_b: 52
                    total_qty_a: 12750
                    total_qty_b: 13980.5
                    by_supply_type:
                      manufacture:
                        count_a: 20
                        count_b: 22
                        qty_a: 8000
                        qty_b: 8600
                      purchase:
                        count_a: 25
                        count_b: 26
                        qty_a: 4500
                        qty_b: 5180.5
                      transfer:
                        count_a: 3
                        count_b: 4
                        qty_a: 250
                        qty_b: 200
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: manufacturing:read
      operationId: get-api-manufacturing-mrp-scenarios-compare
  /api/manufacturing/mrp/scenarios/{mrpScenario}:
    get:
      tags:
      - MRP Planning
      summary: Get Scenario
      description: 'Return a single scenario by id. No relations loaded.

        Auth: requires Bearer token.

        Path param: mrpScenario = scenario id.


        :::info[Required scope: `manufacturing:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: mrpScenario
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The mrp scenario ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      description:
                        type: string
                      base_run_id:
                        type: integer
                      status:
                        type: string
                      overrides:
                        type: object
                        properties:
                          demand_multiplier:
                            type: number
                          lead_time_buffer_days:
                            type: integer
                      created_by_user_id:
                        type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 3
                    name: Holiday demand spike
                    description: Model a 30% Q4 surge
                    base_run_id: 12
                    status: draft
                    overrides:
                      demand_multiplier: 1.3
                      lead_time_buffer_days: 5
                    created_by_user_id: 7
                    created_at: '2026-06-15T10:00:00.000000Z'
                    updated_at: '2026-06-15T10:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: manufacturing:read
      operationId: get-api-manufacturing-mrp-scenarios-mrpscenario
    put:
      tags:
      - MRP Planning
      summary: Update Scenario
      description: 'Update a scenario. Same FormRequest as create - name remains required.
        status and created_by_user_id are not settable here.

        Auth: requires Bearer token.

        Path param: mrpScenario = scenario id.

        Fields: name (required, max:255), description (nullable), base_run_id (nullable,
        exists:mrp_runs), overrides (nullable, array/object).


        :::info[Required scope: `manufacturing:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                description:
                  type: string
                base_run_id:
                  type: integer
                overrides:
                  type: object
                  properties:
                    demand_multiplier:
                      type: number
              example:
                name: Holiday demand spike (revised)
                description: Updated to 40% surge
                base_run_id: 12
                overrides:
                  demand_multiplier: 1.4
      parameters:
      - name: mrpScenario
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The mrp scenario ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      description:
                        type: string
                      base_run_id:
                        type: integer
                      status:
                        type: string
                      overrides:
                        type: object
                        properties:
                          demand_multiplier:
                            type: number
                      created_by_user_id:
                        type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 3
                    name: Holiday demand spike (revised)
                    description: Updated to 40% surge
                    base_run_id: 12
                    status: draft
                    overrides:
                      demand_multiplier: 1.4
                    created_by_user_id: 7
                    created_at: '2026-06-15T10:00:00.000000Z'
                    updated_at: '2026-06-18T12:10:00.000000Z'
                  message: Scenario updated
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: manufacturing:write
      operationId: put-api-manufacturing-mrp-scenarios-mrpscenario
    delete:
      tags:
      - MRP Planning
      summary: Delete Scenario
      description: 'Delete a scenario. Returns 204 No Content.

        Auth: requires Bearer token.

        Path param: mrpScenario = scenario id.


        :::info[Required scope: `manufacturing:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: mrpScenario
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The mrp scenario ID.
      responses:
        '204':
          description: No Content
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties: {}
                example: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: manufacturing:write
      operationId: delete-api-manufacturing-mrp-scenarios-mrpscenario
  /api/manufacturing/mrp/planning-calendars:
    get:
      tags:
      - MRP Planning
      summary: List Planning Calendars
      description: 'Paginated list of planning calendars, ordered by name asc. No
        filtering.

        Auth: requires Bearer token.

        Pagination defaults: per_page=10.


        :::info[Required scope: `manufacturing:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        is_default:
                          type: boolean
                        working_days:
                          type: array
                          items:
                            type: integer
                        holidays:
                          type: array
                          items:
                            type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 1
                    name: Standard Factory Calendar
                    is_default: true
                    working_days:
                    - 1
                    - 2
                    - 3
                    - 4
                    - 5
                    holidays:
                    - '2026-07-04'
                    - '2026-12-25'
                    created_at: '2026-06-01T09:00:00.000000Z'
                    updated_at: '2026-06-10T11:15:30.000000Z'
                  - id: 2
                    name: Weekend Shift Calendar
                    is_default: false
                    working_days:
                    - 6
                    - 7
                    holidays: []
                    created_at: '2026-06-01T09:00:00.000000Z'
                    updated_at: '2026-06-10T11:15:30.000000Z'
                  current_page: 1
                  first_page_url: '...'
                  from: 1
                  last_page: 1
                  last_page_url: '...'
                  links: []
                  next_page_url: null
                  path: '...'
                  per_page: 10
                  prev_page_url: null
                  to: 2
                  total: 2
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: manufacturing:read
      operationId: get-api-manufacturing-mrp-planning-calendars
    post:
      tags:
      - MRP Planning
      summary: Create Planning Calendar
      description: 'Create a planning calendar. Setting is_default truthy unsets default
        on all other calendars.

        Auth: requires Bearer token.

        FormRequest: StorePlanningCalendarRequest.

        Fields: name (required, max:255), is_default (sometimes, boolean), working_days
        (nullable, array), working_days.* (integer, min:1, max:7; 1=Mon..7=Sun), holidays
        (nullable, array), holidays.* (date_format:Y-m-d).


        :::info[Required scope: `manufacturing:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                is_default:
                  type: boolean
                working_days:
                  type: array
                  items:
                    type: integer
                holidays:
                  type: array
                  items:
                    type: string
              example:
                name: Standard Factory Calendar
                is_default: true
                working_days:
                - 1
                - 2
                - 3
                - 4
                - 5
                holidays:
                - '2026-07-04'
                - '2026-12-25'
      parameters: []
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      is_default:
                        type: boolean
                      working_days:
                        type: array
                        items:
                          type: integer
                      holidays:
                        type: array
                        items:
                          type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 3
                    name: Standard Factory Calendar
                    is_default: true
                    working_days:
                    - 1
                    - 2
                    - 3
                    - 4
                    - 5
                    holidays:
                    - '2026-07-04'
                    - '2026-12-25'
                    created_at: '2026-06-18T14:32:05.000000Z'
                    updated_at: '2026-06-18T14:32:05.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: manufacturing:write
      operationId: post-api-manufacturing-mrp-planning-calendars
  /api/manufacturing/mrp/planning-calendars/{planningCalendar}:
    get:
      tags:
      - MRP Planning
      summary: Get Planning Calendar
      description: 'Return a single planning calendar by id.

        Auth: requires Bearer token.

        Path param: planningCalendar = calendar id.


        :::info[Required scope: `manufacturing:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: planningCalendar
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The planning calendar ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      is_default:
                        type: boolean
                      working_days:
                        type: array
                        items:
                          type: integer
                      holidays:
                        type: array
                        items:
                          type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 1
                    name: Standard Factory Calendar
                    is_default: true
                    working_days:
                    - 1
                    - 2
                    - 3
                    - 4
                    - 5
                    holidays:
                    - '2026-07-04'
                    - '2026-12-25'
                    created_at: '2026-06-01T09:00:00.000000Z'
                    updated_at: '2026-06-10T11:15:30.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: manufacturing:read
      operationId: get-api-manufacturing-mrp-planning-calendars-planningcalendar
    put:
      tags:
      - MRP Planning
      summary: Update Planning Calendar
      description: 'Update a planning calendar (partial). Setting is_default truthy
        unsets default on all others.

        Auth: requires Bearer token.

        Path param: planningCalendar = calendar id.

        FormRequest: UpdatePlanningCalendarRequest.

        Fields: name (sometimes, max:255), is_default (sometimes, boolean), working_days
        (nullable, array of int 1-7), holidays (nullable, array of Y-m-d).


        :::info[Required scope: `manufacturing:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                is_default:
                  type: boolean
                working_days:
                  type: array
                  items:
                    type: integer
                holidays:
                  type: array
                  items:
                    type: string
              example:
                name: Standard Factory Calendar (Revised)
                is_default: false
                working_days:
                - 1
                - 2
                - 3
                - 4
                - 5
                - 6
                holidays:
                - '2026-07-04'
      parameters:
      - name: planningCalendar
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The planning calendar ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      is_default:
                        type: boolean
                      working_days:
                        type: array
                        items:
                          type: integer
                      holidays:
                        type: array
                        items:
                          type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 1
                    name: Standard Factory Calendar (Revised)
                    is_default: false
                    working_days:
                    - 1
                    - 2
                    - 3
                    - 4
                    - 5
                    - 6
                    holidays:
                    - '2026-07-04'
                    created_at: '2026-06-01T09:00:00.000000Z'
                    updated_at: '2026-06-18T14:40:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: manufacturing:write
      operationId: put-api-manufacturing-mrp-planning-calendars-planningcalendar
    delete:
      tags:
      - MRP Planning
      summary: Delete Planning Calendar
      description: 'Delete a planning calendar. Returns 204 No Content.

        Auth: requires Bearer token.

        Path param: planningCalendar = calendar id.


        :::info[Required scope: `manufacturing:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: planningCalendar
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The planning calendar ID.
      responses:
        '204':
          description: No Content
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties: {}
                example: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: manufacturing:write
      operationId: delete-api-manufacturing-mrp-planning-calendars-planningcalendar
  /api/manufacturing/mrp/work-centers/{workCenter}/calendar:
    get:
      tags:
      - MRP Planning
      summary: Get Work Center Calendar
      description: 'Return the work center''s calendar with the related planning calendar
        eager-loaded. Returns data: null when none exists.

        Auth: requires Bearer token.

        Path param: workCenter = work center id.


        :::info[Required scope: `manufacturing:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: workCenter
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The work center ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 OK
                  value:
                    data:
                      id: 12
                      work_center_id: 5
                      planning_calendar_id: 1
                      planning_calendar:
                        id: 1
                        name: Standard Factory Calendar
                      shifts:
                      - start: 08:00
                        end: '12:00'
                      - start: '13:00'
                        end: '17:00'
                      utilization_pct: 85
                      efficiency_pct: 92.5
                      finite_capacity: true
                      finite_time_fence_days: 14
                      created_at: '2026-06-05T10:00:00.000000Z'
                      updated_at: '2026-06-12T08:30:00.000000Z'
                example-1:
                  summary: 200 No Calendar
                  value:
                    data: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: manufacturing:read
      operationId: get-api-manufacturing-mrp-work-centers-workcenter-calendar
    put:
      tags:
      - MRP Planning
      summary: Upsert Work Center Calendar
      description: 'Create or update the single calendar for the work center (work_center_id
        comes from the route).

        Auth: requires Bearer token.

        Path param: workCenter = work center id.

        FormRequest: UpsertWorkCenterCalendarRequest.

        Fields: planning_calendar_id (nullable, exists:planning_calendars), shifts
        (nullable, array), shifts.*.start & shifts.*.end (required_with:shifts, string),
        utilization_pct (sometimes, numeric, 0-100), efficiency_pct (sometimes, numeric,
        0-100), finite_capacity (sometimes, boolean), finite_time_fence_days (nullable,
        integer, min:0).

        Note: the planning_calendar nested object is omitted from this response (relation
        not eager-loaded on upsert); only planning_calendar_id appears.


        :::info[Required scope: `manufacturing:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                planning_calendar_id:
                  type: integer
                shifts:
                  type: array
                  items:
                    type: object
                    properties:
                      start:
                        type: string
                      end:
                        type: string
                utilization_pct:
                  type: integer
                efficiency_pct:
                  type: number
                finite_capacity:
                  type: boolean
                finite_time_fence_days:
                  type: integer
              example:
                planning_calendar_id: 1
                shifts:
                - start: 08:00
                  end: '12:00'
                - start: '13:00'
                  end: '17:00'
                utilization_pct: 85
                efficiency_pct: 92.5
                finite_capacity: true
                finite_time_fence_days: 14
      parameters:
      - name: workCenter
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The work center ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      work_center_id:
                        type: integer
                      planning_calendar_id:
                        type: integer
                      shifts:
                        type: array
                        items:
                          type: object
                          properties:
                            start:
                              type: string
                            end:
                              type: string
                      utilization_pct:
                        type: integer
                      efficiency_pct:
                        type: number
                      finite_capacity:
                        type: boolean
                      finite_time_fence_days:
                        type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 12
                    work_center_id: 5
                    planning_calendar_id: 1
                    shifts:
                    - start: 08:00
                      end: '12:00'
                    - start: '13:00'
                      end: '17:00'
                    utilization_pct: 85
                    efficiency_pct: 92.5
                    finite_capacity: true
                    finite_time_fence_days: 14
                    created_at: '2026-06-05T10:00:00.000000Z'
                    updated_at: '2026-06-18T14:40:12.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: manufacturing:write
      operationId: put-api-manufacturing-mrp-work-centers-workcenter-calendar
  /api/manufacturing/mrp/bill-of-resources:
    get:
      tags:
      - MRP Planning
      summary: List Bill of Resources
      description: 'Paginated bill-of-resource rows (product x work center x hours_per_unit)
        with product and workCenter eager-loaded, newest first. No filtering.

        Auth: requires Bearer token.

        Pagination defaults: per_page=10.


        :::info[Required scope: `manufacturing:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        product_id:
                          type: integer
                        product:
                          type: object
                          properties:
                            id:
                              type: integer
                            sku:
                              type: string
                            name:
                              type: string
                        work_center_id:
                          type: integer
                        work_center:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            code:
                              type: string
                        hours_per_unit:
                          type: number
                        is_key_resource:
                          type: boolean
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 7
                    product_id: 101
                    product:
                      id: 101
                      sku: WIDGET-RED-01
                      name: Red Widget
                    work_center_id: 5
                    work_center:
                      id: 5
                      name: Assembly Line A
                      code: ASM-A
                    hours_per_unit: 0.75
                    is_key_resource: true
                    created_at: '2026-06-15T12:00:00.000000Z'
                    updated_at: '2026-06-15T12:00:00.000000Z'
                  current_page: 1
                  first_page_url: '...'
                  from: 1
                  last_page: 1
                  last_page_url: '...'
                  links: []
                  next_page_url: null
                  path: '...'
                  per_page: 10
                  prev_page_url: null
                  to: 1
                  total: 1
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: manufacturing:read
      operationId: get-api-manufacturing-mrp-bill-of-resources
    post:
      tags:
      - MRP Planning
      summary: Create Bill of Resource
      description: 'Create a bill-of-resource link. Returns 201 with product and workCenter
        loaded.

        Auth: requires Bearer token.

        FormRequest: StoreBillOfResourceRequest.

        Fields: product_id (required, exists:products), work_center_id (required,
        exists:work_centers), hours_per_unit (required, numeric, min:0), is_key_resource
        (sometimes, boolean).


        :::info[Required scope: `manufacturing:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                product_id:
                  type: integer
                work_center_id:
                  type: integer
                hours_per_unit:
                  type: number
                is_key_resource:
                  type: boolean
              example:
                product_id: 101
                work_center_id: 5
                hours_per_unit: 0.75
                is_key_resource: true
      parameters: []
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      product_id:
                        type: integer
                      product:
                        type: object
                        properties:
                          id:
                            type: integer
                          sku:
                            type: string
                          name:
                            type: string
                      work_center_id:
                        type: integer
                      work_center:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          code:
                            type: string
                      hours_per_unit:
                        type: number
                      is_key_resource:
                        type: boolean
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 8
                    product_id: 101
                    product:
                      id: 101
                      sku: WIDGET-RED-01
                      name: Red Widget
                    work_center_id: 5
                    work_center:
                      id: 5
                      name: Assembly Line A
                      code: ASM-A
                    hours_per_unit: 0.75
                    is_key_resource: true
                    created_at: '2026-06-18T14:45:00.000000Z'
                    updated_at: '2026-06-18T14:45:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: manufacturing:write
      operationId: post-api-manufacturing-mrp-bill-of-resources
  /api/manufacturing/mrp/bill-of-resources/{billOfResource}:
    get:
      tags:
      - MRP Planning
      summary: Get Bill of Resource
      description: 'Return a single bill-of-resource row with product and workCenter
        loaded.

        Auth: requires Bearer token.

        Path param: billOfResource = row id.


        :::info[Required scope: `manufacturing:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: billOfResource
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The bill of resource ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      product_id:
                        type: integer
                      product:
                        type: object
                        properties:
                          id:
                            type: integer
                          sku:
                            type: string
                          name:
                            type: string
                      work_center_id:
                        type: integer
                      work_center:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          code:
                            type: string
                      hours_per_unit:
                        type: number
                      is_key_resource:
                        type: boolean
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 7
                    product_id: 101
                    product:
                      id: 101
                      sku: WIDGET-RED-01
                      name: Red Widget
                    work_center_id: 5
                    work_center:
                      id: 5
                      name: Assembly Line A
                      code: ASM-A
                    hours_per_unit: 0.75
                    is_key_resource: true
                    created_at: '2026-06-15T12:00:00.000000Z'
                    updated_at: '2026-06-15T12:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: manufacturing:read
      operationId: get-api-manufacturing-mrp-bill-of-resources-billofresource
    put:
      tags:
      - MRP Planning
      summary: Update Bill of Resource
      description: 'Update a bill-of-resource row (partial). Returns 200 with product
        and workCenter loaded.

        Auth: requires Bearer token.

        Path param: billOfResource = row id.

        FormRequest: UpdateBillOfResourceRequest.

        Fields: product_id (sometimes, exists:products), work_center_id (sometimes,
        exists:work_centers), hours_per_unit (sometimes, numeric, min:0), is_key_resource
        (sometimes, boolean).


        :::info[Required scope: `manufacturing:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                hours_per_unit:
                  type: number
                is_key_resource:
                  type: boolean
              example:
                hours_per_unit: 1.25
                is_key_resource: false
      parameters:
      - name: billOfResource
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The bill of resource ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      product_id:
                        type: integer
                      product:
                        type: object
                        properties:
                          id:
                            type: integer
                          sku:
                            type: string
                          name:
                            type: string
                      work_center_id:
                        type: integer
                      work_center:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          code:
                            type: string
                      hours_per_unit:
                        type: number
                      is_key_resource:
                        type: boolean
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 7
                    product_id: 101
                    product:
                      id: 101
                      sku: WIDGET-RED-01
                      name: Red Widget
                    work_center_id: 5
                    work_center:
                      id: 5
                      name: Assembly Line A
                      code: ASM-A
                    hours_per_unit: 1.25
                    is_key_resource: false
                    created_at: '2026-06-15T12:00:00.000000Z'
                    updated_at: '2026-06-18T14:50:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: manufacturing:write
      operationId: put-api-manufacturing-mrp-bill-of-resources-billofresource
    delete:
      tags:
      - MRP Planning
      summary: Delete Bill of Resource
      description: 'Delete a bill-of-resource row. Returns 204 No Content.

        Auth: requires Bearer token.

        Path param: billOfResource = row id.


        :::info[Required scope: `manufacturing:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: billOfResource
        in: path
        schema:
          type: integer
        required: true
        example: '1'
        description: The bill of resource ID.
      responses:
        '204':
          description: No Content
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties: {}
                example: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: manufacturing:write
      operationId: delete-api-manufacturing-mrp-bill-of-resources-billofresource
  /api/sales-orders/{salesOrder}/archive:
    put:
      tags:
      - Sales Orders
      summary: Archive Sales Order
      description: 'Archives a sales order (stamps its archived timestamp so it is
        hidden from active lists), then runs the legacy archive-and-fulfill flow:
        a fulfillment is created for the order''s remaining unfulfilled items and
        the tracking is submitted to the order''s sales channel. The success message
        and returned `data` describe the created fulfillment.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        To archive orders without this fulfillment side effect, use the bulk endpoint
        `PUT /api/sales-orders/archive` with a single ID instead.


        Authentication: Requires Bearer token.


        Request body fields (all optional — when omitted, a fulfillment is created
        for all remaining unfulfilled items):

        - fulfillment_type (string): `manual`, `shipstation`, `starshipit`, `shipmyorders`,
        `fba`, `walmart_wfs`, `veracore`, `shiphero`, `shipfusion`, `d3`, `trackstar`,
        `pickup`, or `sales_channel`.

        - fulfilled_at (date): Shipment date; required for `manual` fulfillments.

        - tracking_number (string, max 255).

        - requested_shipping_method_id (integer) / requested_shipping_method (string,
        max 255).

        - fulfilled_shipping_method_id (integer) / manual_fulfilled_shipping_method
        (string, max 255): For manual fulfillments.

        - cost (number, < 100,000): Shipping cost.

        - fulfillment_lines (array): Restrict the fulfillment to specific lines; each
        item needs sales_order_line_id (integer, required) and quantity (number, required,
        >= 0). Per-line `metadata.fba_seller_sku` (string) and `lot_allocation` (array
        of {fifo_layer_id, quantity}) are supported for lot-tracked products.

        - metadata.signature_required (boolean), metadata.saturday_delivery (boolean),
        metadata.shipping_speed (string), metadata.comments (string), metadata.veracore_packing_slip_comments
        (string, max 500), metadata.veracore_shipping_comments (string, max 500),
        metadata.veracore_third_party_account_number (string, max 100), metadata.veracore_third_party_type
        (integer, 1-3).

        - packing_slip_printed_at (date), status (string), submit_to_shipping_provider
        (boolean), submit_to_sales_channel (boolean).


        Behavior:

        - If the order is already archived, a warning is returned and no fulfillment
        is created.

        - Orders held until a future date (`hold_until_date`) cannot be fulfilled
        and return 400.

        - Draft orders and closed (non-out-of-sync) orders fail fulfillment validation.


        Path parameters:

        - salesOrder (required): Sales order ID.


        **Requires permission:** `sales_orders.update`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                fulfillment_type:
                  type: string
                fulfilled_at:
                  type: string
                tracking_number:
                  type: string
              example:
                fulfillment_type: manual
                fulfilled_at: '2026-07-06'
                tracking_number: '9405511899561234567890'
      parameters:
      - name: salesOrder
        in: path
        schema:
          type: integer
        required: true
        description: Sales order ID
        example: '500'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 Archived and Fulfilled
                  value:
                    message: The sales order fulfillment created successfully
                    data:
                      id: 91
                      fulfillment_sequence: 1
                      ssi_imported: false
                example-1:
                  summary: 200 Already Archived (Warning)
                  value:
                    message: The :resource ':id' is already archived
                    warnings:
                      id:
                      - message: The :resource ':id' is already archived
                        code: SalesOrderIsAlreadyArchived
                        data:
                          id: 500
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      hold_until_date:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: array
                example:
                  message: This order is held until Sat, Jul 11, 2026 12:00 AM and
                    cannot be fulfilled before then.
                  errors:
                    hold_until_date:
                    - message: This order is held until Sat, Jul 11, 2026 12:00 AM
                        and cannot be fulfilled before then.
                      code: IsLocked
                      data: []
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: orders:write
      operationId: put-api-sales-orders-salesorder-archive
  /api/sales-orders/{salesOrder}/unarchived:
    put:
      tags:
      - Sales Orders
      summary: Unarchive Sales Order
      description: 'Restores an archived sales order so it appears in active lists
        again (clears its archived timestamp). Returns the order in `data`.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        If the order is not archived, a warning is returned (the order is still included
        in `data`).


        Note: the path segment is literally `unarchived`.


        Authentication: Requires Bearer token.


        Path parameters:

        - salesOrder (required): Sales order ID.


        **Requires permission:** `sales_orders.update`'
      requestBody:
        content: {}
      parameters:
      - name: salesOrder
        in: path
        schema:
          type: integer
        required: true
        description: Sales order ID
        example: '500'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 Success
                  value:
                    message: The sales order '500' unarchived successfully
                    data:
                      id: 500
                      sales_order_number: SO-0158
                      customer_po_number: PO-88213
                      sales_channel_id: 3
                      sub_sales_channel_id: null
                      sales_rep_id: null
                      accounting: {}
                      order_date: '2026-06-18T14:23:11.000000Z'
                      payment_date: '2026-06-18T14:25:02.000000Z'
                      created_at: '2026-06-18T14:23:15.000000Z'
                      updated_at: '2026-07-06T11:20:31.000000Z'
                      archived_at: null
                      canceled_at: null
                      currency: USD
                      currency_rate: 1
                      discount_lines: null
                      order_discounts: null
                      line_discount_total: 0
                      order_discount_total: 0
                      total_discount_amount: 0
                      apply_order_discount_on: null
                      tax_lines: null
                      packing_slip_printed_at: null
                      is_fba: false
                      is_replacement_order: false
                      need_mapping: false
                      memo_for_customer: null
                      reserved_at: null
                      payment_hold_status: null
                      reservation_expires_at: null
                      ship_by_date: '2026-06-19T00:00:00.000000Z'
                      hold_until_date: null
                      is_held: false
                      deliver_by_date: null
                      fulfilled_at: '2026-06-19T16:40:21.000000Z'
                      shipping_method_id: 7
                      shipping_method: USPS Priority Mail
                      is_pickup: false
                      shipped_is_pickup: false
                      address_check:
                        has_warning: true
                        has_block: false
                        highest_severity: warning
                        warnings:
                        - rule_id: missing-required
                          severity: warning
                          message: Shipping address is missing required fields (name,
                            street, city, postcode or country).
                      requested_shipping_method: Standard Shipping
                      mapped_shipping_method: USPS Priority Mail
                      fulfillment_channel: null
                      customer_name:
                        id: null
                        name: Jane Cooper
                      customer_email: jane.cooper@example.com
                      customer_company: null
                      customer_phone: +1 555-201-4477
                      sales_order_shipping_address:
                        id: 1201
                        name: Jane Cooper
                        email: jane.cooper@example.com
                        company: null
                        phone: +1 555-201-4477
                        address1: 982 Maple Avenue
                        address2: Apt 4B
                        address3: null
                        city: Portland
                        province: Oregon
                        province_code: OR
                        zip: '97205'
                        country: United States
                        country_code: US
                      shipping_overridden_at: null
                      is_shipping_overridden: false
                      sales_order_billing_address:
                        id: 1202
                        name: Jane Cooper
                        email: jane.cooper@example.com
                        company: null
                        phone: +1 555-201-4477
                        address1: 982 Maple Avenue
                        address2: Apt 4B
                        address3: null
                        city: Portland
                        province: Oregon
                        province_code: OR
                        zip: '97205'
                        country: United States
                        country_code: US
                      order_status: closed
                      fulfillment_status: fulfilled
                      payment_status: paid
                      currency_code: USD
                      exact_discount_total: 0.95
                      is_tax_included: false
                      tax_total: 4.11
                      calculated_tax_total: 4.11
                      exact_tax_total: 4.11
                      tax_rate_id: null
                      tax_rate: null
                example-1:
                  summary: 200 Already Unarchived (Warning)
                  value:
                    message: The sales order '500' is already unarchived
                    warnings:
                      id:
                      - message: The sales order '500' is already unarchived
                        code: SalesOrderIsAlreadyUnarchived
                        data:
                          id: 500
                    data:
                      id: 500
                      sales_order_number: SO-0158
                      customer_po_number: PO-88213
                      sales_channel_id: 3
                      sub_sales_channel_id: null
                      sales_rep_id: null
                      accounting: {}
                      order_date: '2026-06-18T14:23:11.000000Z'
                      payment_date: '2026-06-18T14:25:02.000000Z'
                      created_at: '2026-06-18T14:23:15.000000Z'
                      updated_at: '2026-07-06T11:20:31.000000Z'
                      archived_at: null
                      canceled_at: null
                      currency: USD
                      currency_rate: 1
                      discount_lines: null
                      order_discounts: null
                      line_discount_total: 0
                      order_discount_total: 0
                      total_discount_amount: 0
                      apply_order_discount_on: null
                      tax_lines: null
                      packing_slip_printed_at: null
                      is_fba: false
                      is_replacement_order: false
                      need_mapping: false
                      memo_for_customer: null
                      reserved_at: null
                      payment_hold_status: null
                      reservation_expires_at: null
                      ship_by_date: '2026-06-19T00:00:00.000000Z'
                      hold_until_date: null
                      is_held: false
                      deliver_by_date: null
                      fulfilled_at: '2026-06-19T16:40:21.000000Z'
                      shipping_method_id: 7
                      shipping_method: USPS Priority Mail
                      is_pickup: false
                      shipped_is_pickup: false
                      address_check:
                        has_warning: true
                        has_block: false
                        highest_severity: warning
                        warnings:
                        - rule_id: missing-required
                          severity: warning
                          message: Shipping address is missing required fields (name,
                            street, city, postcode or country).
                      requested_shipping_method: Standard Shipping
                      mapped_shipping_method: USPS Priority Mail
                      fulfillment_channel: null
                      customer_name:
                        id: null
                        name: Jane Cooper
                      customer_email: jane.cooper@example.com
                      customer_company: null
                      customer_phone: +1 555-201-4477
                      sales_order_shipping_address:
                        id: 1201
                        name: Jane Cooper
                        email: jane.cooper@example.com
                        company: null
                        phone: +1 555-201-4477
                        address1: 982 Maple Avenue
                        address2: Apt 4B
                        address3: null
                        city: Portland
                        province: Oregon
                        province_code: OR
                        zip: '97205'
                        country: United States
                        country_code: US
                      shipping_overridden_at: null
                      is_shipping_overridden: false
                      sales_order_billing_address:
                        id: 1202
                        name: Jane Cooper
                        email: jane.cooper@example.com
                        company: null
                        phone: +1 555-201-4477
                        address1: 982 Maple Avenue
                        address2: Apt 4B
                        address3: null
                        city: Portland
                        province: Oregon
                        province_code: OR
                        zip: '97205'
                        country: United States
                        country_code: US
                      order_status: closed
                      fulfillment_status: fulfilled
                      payment_status: paid
                      currency_code: USD
                      exact_discount_total: 0.95
                      is_tax_included: false
                      tax_total: 4.11
                      calculated_tax_total: 4.11
                      exact_tax_total: 4.11
                      tax_rate_id: null
                      tax_rate: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: orders:write
      operationId: put-api-sales-orders-salesorder-unarchived
  /api/sales-orders/archive:
    put:
      tags:
      - Sales Orders
      summary: Bulk Archive Sales Orders
      description: 'Archives multiple sales orders at once (stamps each order''s archived
        timestamp so it disappears from active lists). Unlike the single-order archive
        endpoint, this performs a pure archive with no fulfillment side effects.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Request body (one of `ids` or `filters` is required):

        - ids (array of integers, required without filters, min 1): Sales order IDs;
        each must exist.

        - filters (required without ids): Filter payload resolved against the sales-orders
        list — accepts the grouped `filter_groups` shape (base64-encoded JSON, same
        as the V2 sales-orders list) as well as the legacy JSON-string filter set.


        When targeting by `filters`, only currently non-archived matching orders are
        processed.


        Behavior:

        - Orders that are already archived are skipped and reported under `warnings`,
        keyed by `ids.{id}.id`.

        - The message reports `{archived}/{total}` counts. If every targeted order
        was already archived, the message is "The sales orders maybe already archived".


        **Requires permission:** `sales_orders.update`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 7116
                - 7117
                - 7118
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 All Archived
                  value:
                    message: 3/3 sales orders had been archived successfully
                example-1:
                  summary: 200 Partial (some already archived)
                  value:
                    message: 2/3 sales orders had been archived successfully
                    warnings:
                      ids.7118.id:
                      - message: The sales order '7118' is already archived
                        code: SalesOrderIsAlreadyArchived
                        data: []
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      ids:
                        type: array
                        items:
                          type: string
                example:
                  message: The given data was invalid.
                  errors:
                    ids:
                    - The ids field is required when filters is not present.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: orders:write
      operationId: put-api-sales-orders-archive
  /api/sales-orders/unarchive:
    put:
      tags:
      - Sales Orders
      summary: Bulk Unarchive Sales Orders
      description: 'Restores multiple archived sales orders at once (clears each order''s
        archived timestamp so it reappears in active lists).


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Request body (one of `ids` or `filters` is required):

        - ids (array of integers, required without filters, min 1): Sales order IDs;
        each must exist.

        - filters (required without ids): Filter payload resolved against the sales-orders
        list — accepts the grouped `filter_groups` shape (base64-encoded JSON, same
        as the V2 sales-orders list) as well as the legacy JSON-string filter set.


        When targeting by `filters`, only currently archived matching orders are processed.


        Behavior:

        - Orders that are not archived are skipped and reported under `warnings`,
        keyed by `ids.{id}.id`.

        - The message reports `{unarchived}/{total}` counts. If every targeted order
        was already active, the message is "The sales orders are already un archived".


        **Requires permission:** `sales_orders.update`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 7116
                - 7117
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 All Unarchived
                  value:
                    message: 2/2 sales orders had been un archived successfully
                example-1:
                  summary: 200 Partial (some not archived)
                  value:
                    message: 1/2 sales orders had been un archived successfully
                    warnings:
                      ids.7117.id:
                      - message: The sales order '7117' is already unarchived
                        code: SalesOrderIsAlreadyUnarchived
                        data: []
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: orders:write
      operationId: put-api-sales-orders-unarchive
  /api/sales-orders/deletable:
    post:
      tags:
      - Sales Orders
      summary: Check Sales Orders Deletable
      description: 'Checks whether the given sales orders can be deleted, returning
        one result per order. Use this before calling the delete endpoints to warn
        users about related records that will be removed along with each order.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Request body fields:

        - ids (array of integers, required, min 1): Sales order IDs; each must exist.


        Response: `data` is an array with one entry per order:

        - id (integer), sales_order_number (string)

        - deletable (boolean): Whether the order can be deleted. Deletion cascades
        related records, so this is true in normal cases.

        - reason (string|null): Populated when the order is not deletable.

        - warnings (object, present only when applicable): Informational warnings
        — e.g. `warnings.fulfillments` describes how many fulfillments will be removed
        with the order.


        **Requires permission:** `sales_orders.delete`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 500
                - 501
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        sales_order_number:
                          type: string
                        deletable:
                          type: boolean
                        reason:
                          type: string
                          nullable: true
                        warnings:
                          type: object
                          properties:
                            fulfillments:
                              type: string
                example:
                  data:
                  - id: 500
                    sales_order_number: SO-0158
                    deletable: true
                    reason: null
                    warnings:
                      fulfillments: There is 1 sales order fulfillment associated
                        with this sales order (SO-0158).
                  - id: 501
                    sales_order_number: SO-0159
                    deletable: true
                    reason: null
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      ids.0:
                        type: array
                        items:
                          type: string
                example:
                  message: The given data was invalid.
                  errors:
                    ids.0:
                    - The selected ids.0 is invalid.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: orders:write
      operationId: post-api-sales-orders-deletable
  /api/sales-orders/approve:
    post:
      tags:
      - Sales Orders
      summary: Bulk Approve Sales Orders
      description: 'Approves multiple draft (or reserved) sales orders, transitioning
        them to `open`. Newly opened orders are automatically routed for fulfillment.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Request body (one of `ids` or `filters` is required):

        - ids (array of integers, required without filters): Sales order IDs to approve.

        - filters (required without ids): Filter payload resolved against the sales-orders
        list — accepts the grouped `filter_groups` shape (base64-encoded JSON, same
        as the V2 sales-orders list) as well as the legacy JSON-string filter set.

        - archived (integer, optional, default 0): Used with `filters` — set to 1
        to include archived orders when resolving IDs.


        Behavior:

        - Only `draft` and `reserved` orders can be approved; other orders are reported
        as errors.

        - An order that cannot be approved (no line items, or unmapped products) is
        reported as an error.

        - Returns 200 when all orders approve; 200 with `warnings` when only some
        approve; 400 when none were selected or all failed.


        **Requires permission:** `sales_orders.approve`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 7116
                - 7117
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 All Approved
                  value:
                    message: Sales orders approved successfully
                    data:
                      '7116': The sales order 'SO-7116' approved successfully
                      '7117': The sales order 'SO-7117' approved successfully
                example-1:
                  summary: 200 Partial Success (some skipped)
                  value:
                    message: 1/2 sales orders had been approved successfully
                    warnings:
                      '7116': The sales order 'SO-7116' approved successfully
                      '7117':
                      - id:
                        - message: The sales order 'SO-7117' is not draft
                          code: SalesOrderIsNotDraft
                          data: []
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 400 None Selected
                  value:
                    message: There is no sales order selected
                example-1:
                  summary: 400 All Failed
                  value:
                    message: Failed to approve all selected sales orders
                    errors:
                      '7117':
                      - id:
                        - message: The sales order 'SO-7117' could not be approved.
                            Ensure it has at least one line item and all products
                            are mapped.
                          code: SalesOrderIsNotDraft
                          data: []
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: orders:write
      operationId: post-api-sales-orders-approve
  /api/sales-orders/mark-as-draft:
    post:
      tags:
      - Sales Orders
      summary: Bulk Mark Sales Orders as Draft
      description: 'Reverts multiple sales orders back to `draft`. Reverting an order
        deletes its payments and fulfillments, reverses its inventory movements and
        cost layers, tears down its fulfillment routing, removes its accounting transaction,
        and resets order/fulfillment/payment statuses (including clearing any cancellation).


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Request body (one of `ids` or `filters` is required):

        - ids (array of integers, required without filters): Sales order IDs to revert.

        - filters (required without ids): Filter payload resolved against the sales-orders
        list — accepts the grouped `filter_groups` shape (base64-encoded JSON, same
        as the V2 sales-orders list) as well as the legacy JSON-string filter set.

        - archived (integer, optional, default 0): Used with `filters` — set to 1
        to include archived orders when resolving IDs.


        Behavior:

        - Orders awaiting tracking cannot be reverted (remove their fulfillments first);
        closed orders cannot be reverted.

        - Returns 200 when all orders revert; 200 with per-order `warnings` (keyed
        by order ID) when only some revert; 400 when none were found or all failed.


        **Requires permission:** `sales_orders.update`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 7116
                - 7117
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      '7116':
                        type: string
                      '7117':
                        type: string
                example:
                  message: Successfully marked all sales orders as draft.
                  data:
                    '7116': Successfully marked sales order SO-7116 as draft.
                    '7117': Successfully marked sales order SO-7117 as draft.
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No sales orders found to mark as draft.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: orders:write
      operationId: post-api-sales-orders-mark-as-draft
  /api/sales-orders/{salesOrder}/duplicate:
    post:
      tags:
      - Sales Orders
      summary: Duplicate Sales Order
      description: 'Creates a copy of a sales order as a new draft order and returns
        the new order''s full detail. The copy gets the next local order number, `draft`
        status, `unfulfilled` / `unpaid` statuses, and is assigned to the local (SKU.io)
        sales channel. Line items are copied without any fulfillment progress or sales-channel
        linkage; reservation and packing-slip state are cleared.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        No request body.


        Path parameters:

        - salesOrder (required): Sales order ID to duplicate.


        **Requires permission:** `sales_orders.update`'
      requestBody:
        content: {}
      parameters:
      - name: salesOrder
        in: path
        schema:
          type: integer
        required: true
        description: Sales order ID
        example: '500'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      sales_order_number:
                        type: string
                      customer_po_number:
                        type: string
                        nullable: true
                      sales_channel_id:
                        type: integer
                      sales_channel_name:
                        type: string
                      sub_sales_channel_id:
                        type: string
                        nullable: true
                      sub_sales_channel:
                        type: string
                        nullable: true
                      sub_sales_channel_name:
                        type: string
                        nullable: true
                      integration_instance_id:
                        type: integer
                      integration:
                        type: string
                      integration_id:
                        type: integer
                      integration_image:
                        type: string
                      can_submit_fulfillments_to_channel:
                        type: boolean
                      store:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      sales_rep_id:
                        type: string
                        nullable: true
                      sales_rep:
                        type: string
                        nullable: true
                      accounting:
                        type: object
                        properties:
                          transaction:
                            type: string
                            nullable: true
                      order_date:
                        type: string
                      payment_date:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                      canceled_at:
                        type: string
                        nullable: true
                      currency:
                        type: string
                      currency_rate:
                        type: integer
                      discount_lines:
                        type: string
                        nullable: true
                      discounts:
                        type: array
                      order_discounts:
                        type: string
                        nullable: true
                      line_discount_total:
                        type: integer
                      order_discount_total:
                        type: integer
                      total_discount_amount:
                        type: integer
                      apply_order_discount_on:
                        type: string
                        nullable: true
                      tax_lines:
                        type: string
                        nullable: true
                      packing_slip_printed_at:
                        type: string
                        nullable: true
                      is_fba:
                        type: boolean
                      is_replacement_order:
                        type: boolean
                      need_mapping:
                        type: boolean
                      memo_for_customer:
                        type: string
                        nullable: true
                      reserved_at:
                        type: string
                        nullable: true
                      payment_hold_status:
                        type: string
                        nullable: true
                      reservation_expires_at:
                        type: string
                        nullable: true
                      ship_by_date:
                        type: string
                      hold_until_date:
                        type: string
                        nullable: true
                      is_held:
                        type: boolean
                      deliver_by_date:
                        type: string
                        nullable: true
                      fulfilled_at:
                        type: string
                        nullable: true
                      shipping_method_id:
                        type: integer
                      shipping_method:
                        type: string
                      is_pickup:
                        type: boolean
                      shipped_is_pickup:
                        type: boolean
                      address_check:
                        type: object
                        properties:
                          has_warning:
                            type: boolean
                          has_block:
                            type: boolean
                          highest_severity:
                            type: string
                          warnings:
                            type: array
                            items:
                              type: object
                              properties:
                                rule_id:
                                  type: string
                                severity:
                                  type: string
                                message:
                                  type: string
                      requested_shipping_method:
                        type: string
                      mapped_shipping_method:
                        type: string
                      has_backorder:
                        type: boolean
                      fulfillment:
                        type: array
                      fulfillment_channel:
                        type: string
                        nullable: true
                      customer_name:
                        type: object
                        properties:
                          id:
                            type: string
                            nullable: true
                          name:
                            type: string
                      customer_email:
                        type: string
                      customer_company:
                        type: string
                        nullable: true
                      customer_phone:
                        type: string
                      sales_order_shipping_address:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          email:
                            type: string
                          company:
                            type: string
                            nullable: true
                          phone:
                            type: string
                          address1:
                            type: string
                          address2:
                            type: string
                          address3:
                            type: string
                            nullable: true
                          city:
                            type: string
                          province:
                            type: string
                          province_code:
                            type: string
                          zip:
                            type: string
                          country:
                            type: string
                          country_code:
                            type: string
                      shipping_overridden_at:
                        type: string
                        nullable: true
                      is_shipping_overridden:
                        type: boolean
                      sales_order_billing_address:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          email:
                            type: string
                          company:
                            type: string
                            nullable: true
                          phone:
                            type: string
                          address1:
                            type: string
                          address2:
                            type: string
                          address3:
                            type: string
                            nullable: true
                          city:
                            type: string
                          province:
                            type: string
                          province_code:
                            type: string
                          zip:
                            type: string
                          country:
                            type: string
                          country_code:
                            type: string
                      item_info:
                        type: array
                        items:
                          type: object
                          properties:
                            sales_order_line_id:
                              type: integer
                            sales_channel_line_id:
                              type: string
                              nullable: true
                            bundle_quantity_cache:
                              type: string
                              nullable: true
                            unit_cost:
                              type: number
                            tax_rate:
                              type: integer
                            tax_rate_id:
                              type: string
                              nullable: true
                            item_tax_value:
                              type: integer
                            fifo_layer_id:
                              type: string
                              nullable: true
                            item_quantity:
                              type: integer
                            item_canceled_quantity:
                              type: integer
                            item_allocated_quantity:
                              type: integer
                            item_on_hand_allocated_quantity:
                              type: integer
                            item_unallocated_quantity:
                              type: integer
                            sales_channel_fulfillment_out_of_sync:
                              type: boolean
                            item_externally_fulfilled_quantity:
                              type: integer
                            fulfilled_quantity:
                              type: integer
                            submitted_quantity:
                              type: integer
                            item_dropshipped_quantity:
                              type: integer
                            item_sku:
                              type: object
                              properties:
                                id:
                                  type: integer
                                sku:
                                  type: string
                            item_bundle_sku:
                              type: string
                              nullable: true
                            item_barcode:
                              type: string
                            item_weight:
                              type: number
                            item_weight_unit:
                              type: string
                            item_brand:
                              type: object
                              properties:
                                id:
                                  type: integer
                                name:
                                  type: string
                            bundle:
                              type: string
                              nullable: true
                            bundle_proration_basis:
                              type: string
                              nullable: true
                            item_price:
                              type: number
                            item_price_with_tax:
                              type: number
                            item_name:
                              type: string
                            item_nominal_code_id:
                              type: string
                              nullable: true
                            item_nominal_code:
                              type: string
                              nullable: true
                            item_nominal_code_code:
                              type: string
                              nullable: true
                            item_discount:
                              type: integer
                            item_line_discounts:
                              type: array
                            item_line_discount_total:
                              type: integer
                            item_net_total:
                              type: number
                            price_after_line_discount:
                              type: number
                            line_discount_total:
                              type: integer
                            allocated_order_discount:
                              type: integer
                            net_total:
                              type: number
                            item_has_backorder:
                              type: boolean
                            allocation_locked:
                              type: boolean
                            allocation_locked_reason:
                              type: string
                              nullable: true
                            is_product:
                              type: boolean
                            is_bundle:
                              type: boolean
                            is_variation:
                              type: boolean
                            credited_quantity:
                              type: integer
                            credit_sources:
                              type: array
                              items:
                                type: object
                                properties:
                                  vendor_credit_id:
                                    type: integer
                                  vendor_credit_number:
                                    type: string
                                  quantity:
                                    type: integer
                                  credit_status:
                                    type: string
                                  restock_inventory:
                                    type: boolean
                            warehouse_routing_method:
                              type: string
                            warehouse:
                              type: object
                              properties:
                                id:
                                  type: integer
                                name:
                                  type: string
                                supplier_id:
                                  type: string
                                  nullable: true
                                supplier_name:
                                  type: string
                                  nullable: true
                            is_fulfilled:
                              type: boolean
                            no_audit_trail:
                              type: boolean
                            unfulfilled_quantity:
                              type: integer
                            remaining_to_fulfill_quantity:
                              type: integer
                            available_to_fulfill:
                              type: integer
                            committed_to_fulfillment_quantity:
                              type: integer
                            returnable_quantity:
                              type: integer
                            inventory_allocation_id:
                              type: string
                              nullable: true
                            backordered_quantity:
                              type: integer
                            listing:
                              type: string
                              nullable: true
                            channel_product_external_id:
                              type: string
                              nullable: true
                            sales_channel_product_id:
                              type: string
                              nullable: true
                            subscription_edition_id:
                              type: string
                              nullable: true
                            subscription_edition:
                              type: string
                              nullable: true
                            subscription_offering:
                              type: string
                              nullable: true
                            created_at:
                              type: string
                            updated_at:
                              type: string
                            cogs:
                              type: string
                              nullable: true
                            estimated_decoration_cost:
                              type: integer
                            actual_decoration_cost:
                              type: integer
                            decoration_cost_breakdown:
                              type: string
                              nullable: true
                            is_taxable:
                              type: boolean
                            default_tax_rate_id:
                              type: string
                              nullable: true
                            item_img_url:
                              type: string
                            item_inventory:
                              type: object
                              properties:
                                total:
                                  type: object
                                  properties:
                                    inbound:
                                      type: integer
                                    stock:
                                      type: integer
                                    allocated:
                                      type: integer
                                    on_hold:
                                      type: integer
                                    available:
                                      type: integer
                                    in_transit:
                                      type: integer
                                warehouses:
                                  type: object
                                  properties:
                                    Main Warehouse:
                                      type: object
                                      properties:
                                        inbound:
                                          type: integer
                                        stock:
                                          type: integer
                                        allocated:
                                          type: integer
                                        on_hold:
                                          type: integer
                                        available:
                                          type: integer
                                        supplier_in_stock:
                                          type: string
                                          nullable: true
                                        in_transit:
                                          type: integer
                                        warehouse_id:
                                          type: integer
                                        warehouse_name:
                                          type: string
                                        warehouse_type:
                                          type: string
                                        supplier:
                                          type: string
                                          nullable: true
                                        country_code:
                                          type: string
                            item_stock:
                              type: integer
                      purchase_orders:
                        type: array
                      adjustments:
                        type: array
                      financial_lines:
                        type: array
                      custom_field_values:
                        type: array
                      order_status:
                        type: string
                      fulfillment_status:
                        type: string
                      fulfillment_sequence:
                        type: string
                        nullable: true
                      payment_status:
                        type: string
                      tax_revenue:
                        type: integer
                      product_total:
                        type: number
                      total:
                        type: number
                      discount_total:
                        type: integer
                      currency_code:
                        type: string
                      tags:
                        type: array
                        items:
                          type: string
                      warehouses:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            supplier_id:
                              type: string
                              nullable: true
                            supplier_name:
                              type: string
                              nullable: true
                      can_fulfill:
                        type: boolean
                      exact_discount_total:
                        type: integer
                      is_tax_included:
                        type: boolean
                      tax_total:
                        type: integer
                      calculated_tax_total:
                        type: integer
                      exact_tax_total:
                        type: integer
                      tax_rate_id:
                        type: string
                        nullable: true
                      tax_rate:
                        type: string
                        nullable: true
                      payments:
                        type: array
                      notes:
                        type: array
                      earliest_covered_ship_by_date:
                        type: string
                        nullable: true
                      latest_covered_ship_by_date:
                        type: string
                        nullable: true
                      has_backorder_lines:
                        type: boolean
                example:
                  message: The sales order duplicated successfully
                  data:
                    id: 612
                    sales_order_number: SO-01044
                    customer_po_number: null
                    sales_channel_id: 3
                    sales_channel_name: Shopify - Main Store
                    sub_sales_channel_id: null
                    sub_sales_channel: null
                    sub_sales_channel_name: null
                    integration_instance_id: 2
                    integration: Shopify
                    integration_id: 4
                    integration_image: https://cdn.sku.io/integrations/shopify.png
                    can_submit_fulfillments_to_channel: true
                    store:
                      id: 1
                      name: Main Store
                    sales_rep_id: null
                    sales_rep: null
                    accounting:
                      transaction: null
                    order_date: '2026-07-06T10:15:00.000000Z'
                    payment_date: null
                    created_at: '2026-07-06T10:15:00.000000Z'
                    updated_at: '2026-07-06T10:15:00.000000Z'
                    archived_at: null
                    canceled_at: null
                    currency: USD
                    currency_rate: 1
                    discount_lines: null
                    discounts: []
                    order_discounts: null
                    line_discount_total: 0
                    order_discount_total: 0
                    total_discount_amount: 0
                    apply_order_discount_on: null
                    tax_lines: null
                    packing_slip_printed_at: null
                    is_fba: false
                    is_replacement_order: false
                    need_mapping: false
                    memo_for_customer: null
                    reserved_at: null
                    payment_hold_status: null
                    reservation_expires_at: null
                    ship_by_date: '2026-06-19T00:00:00.000000Z'
                    hold_until_date: null
                    is_held: false
                    deliver_by_date: null
                    fulfilled_at: null
                    shipping_method_id: 7
                    shipping_method: USPS Priority Mail
                    is_pickup: false
                    shipped_is_pickup: false
                    address_check:
                      has_warning: true
                      has_block: false
                      highest_severity: warning
                      warnings:
                      - rule_id: missing-required
                        severity: warning
                        message: Shipping address is missing required fields (name,
                          street, city, postcode or country).
                    requested_shipping_method: Standard Shipping
                    mapped_shipping_method: USPS Priority Mail
                    has_backorder: false
                    fulfillment: []
                    fulfillment_channel: null
                    customer_name:
                      id: null
                      name: Jane Cooper
                    customer_email: jane.cooper@example.com
                    customer_company: null
                    customer_phone: +1 555-201-4477
                    sales_order_shipping_address:
                      id: 1201
                      name: Jane Cooper
                      email: jane.cooper@example.com
                      company: null
                      phone: +1 555-201-4477
                      address1: 982 Maple Avenue
                      address2: Apt 4B
                      address3: null
                      city: Portland
                      province: Oregon
                      province_code: OR
                      zip: '97205'
                      country: United States
                      country_code: US
                    shipping_overridden_at: null
                    is_shipping_overridden: false
                    sales_order_billing_address:
                      id: 1202
                      name: Jane Cooper
                      email: jane.cooper@example.com
                      company: null
                      phone: +1 555-201-4477
                      address1: 982 Maple Avenue
                      address2: Apt 4B
                      address3: null
                      city: Portland
                      province: Oregon
                      province_code: OR
                      zip: '97205'
                      country: United States
                      country_code: US
                    item_info:
                    - sales_order_line_id: 2310
                      sales_channel_line_id: null
                      bundle_quantity_cache: null
                      unit_cost: 11.42
                      tax_rate: 0
                      tax_rate_id: null
                      item_tax_value: 0
                      fifo_layer_id: null
                      item_quantity: 2
                      item_canceled_quantity: 0
                      item_allocated_quantity: 0
                      item_on_hand_allocated_quantity: 0
                      item_unallocated_quantity: 2
                      sales_channel_fulfillment_out_of_sync: false
                      item_externally_fulfilled_quantity: 0
                      fulfilled_quantity: 0
                      submitted_quantity: 0
                      item_dropshipped_quantity: 0
                      item_sku:
                        id: 812
                        sku: WB-32-BLU
                      item_bundle_sku: null
                      item_barcode: 0812345678905
                      item_weight: 1.2
                      item_weight_unit: lb
                      item_brand:
                        id: 14
                        name: HydraPeak
                      bundle: null
                      bundle_proration_basis: null
                      item_price: 25.99
                      item_price_with_tax: 25.99
                      item_name: Stainless Steel Water Bottle 32oz - Ocean Blue
                      item_nominal_code_id: null
                      item_nominal_code: null
                      item_nominal_code_code: null
                      item_discount: 0
                      item_line_discounts: []
                      item_line_discount_total: 0
                      item_net_total: 51.98
                      price_after_line_discount: 25.99
                      line_discount_total: 0
                      allocated_order_discount: 0
                      net_total: 51.98
                      item_has_backorder: false
                      allocation_locked: false
                      allocation_locked_reason: null
                      is_product: true
                      is_bundle: false
                      is_variation: false
                      credited_quantity: 0
                      credit_sources:
                      - vendor_credit_id: 42
                        vendor_credit_number: VC-1001
                        quantity: 5
                        credit_status: open
                        restock_inventory: false
                      warehouse_routing_method: advanced
                      warehouse:
                        id: 3
                        name: Main Warehouse
                        supplier_id: null
                        supplier_name: null
                      is_fulfilled: false
                      no_audit_trail: false
                      unfulfilled_quantity: 2
                      remaining_to_fulfill_quantity: 2
                      available_to_fulfill: 2
                      committed_to_fulfillment_quantity: 0
                      returnable_quantity: 0
                      inventory_allocation_id: null
                      backordered_quantity: 0
                      listing: null
                      channel_product_external_id: null
                      sales_channel_product_id: null
                      subscription_edition_id: null
                      subscription_edition: null
                      subscription_offering: null
                      created_at: '2026-06-18T14:23:15.000000Z'
                      updated_at: '2026-06-19T16:40:21.000000Z'
                      cogs: null
                      estimated_decoration_cost: 0
                      actual_decoration_cost: 0
                      decoration_cost_breakdown: null
                      is_taxable: true
                      default_tax_rate_id: null
                      item_img_url: https://cdn.sku.io/products/wb-32-blu.jpg
                      item_inventory:
                        total:
                          inbound: 24
                          stock: 150
                          allocated: 2
                          on_hold: 0
                          available: 148
                          in_transit: 0
                        warehouses:
                          Main Warehouse:
                            inbound: 24
                            stock: 150
                            allocated: 2
                            on_hold: 0
                            available: 148
                            supplier_in_stock: null
                            in_transit: 0
                            warehouse_id: 3
                            warehouse_name: Main Warehouse
                            warehouse_type: standard
                            supplier: null
                            country_code: US
                      item_stock: 148
                    purchase_orders: []
                    adjustments: []
                    financial_lines: []
                    custom_field_values: []
                    order_status: draft
                    fulfillment_status: unfulfilled
                    fulfillment_sequence: null
                    payment_status: unpaid
                    tax_revenue: 0
                    product_total: 51.98
                    total: 51.98
                    discount_total: 0
                    currency_code: USD
                    tags:
                    - wholesale
                    warehouses:
                    - id: 3
                      name: Main Warehouse
                      supplier_id: null
                      supplier_name: null
                    can_fulfill: false
                    exact_discount_total: 0
                    is_tax_included: false
                    tax_total: 0
                    calculated_tax_total: 0
                    exact_tax_total: 0
                    tax_rate_id: null
                    tax_rate: null
                    payments: []
                    notes: []
                    earliest_covered_ship_by_date: null
                    latest_covered_ship_by_date: null
                    has_backorder_lines: false
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      App\Models\SalesOrder:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: array
                example:
                  message: No query results for model [App\Models\SalesOrder] 999999
                  errors:
                    App\Models\SalesOrder:
                    - message: No query results for model [App\Models\SalesOrder]
                        999999
                      code: NotFound
                      data: []
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: orders:write
      operationId: post-api-sales-orders-salesorder-duplicate
  /api/sales-orders/{salesOrder}/resend:
    post:
      tags:
      - Sales Orders
      summary: Resend Sales Order
      description: 'Creates a $0 resend order for replacing items from an existing
        order (e.g. lost or damaged shipments), linked to the original order, and
        returns the new order''s full detail.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        The new order is a draft copy of the original with:

        - order number `{original}-R-{YYYYMMDD}` and order date set to now

        - only the requested lines, at the requested quantities, with line amounts
        zeroed (no charge)

        - a ship-by date computed from your default handling days and same-day shipping
        cutoff, skipping weekends; a deliver-by date is derived from the shipping
        method''s maximum delivery days when available

        - a resend link back to the original order (the original shows the resend
        under its linked orders)


        Approve the returned draft order to release it for fulfillment.


        Authentication: Requires Bearer token.


        Request body fields:

        - sales_order_lines (array, optional): Lines to resend. Each item: id (integer,
        required — must be a line of this order), quantity (number, required — must
        not exceed the original line quantity). When omitted or empty, the resend
        order is created with no lines.


        Path parameters:

        - salesOrder (required): Sales order ID to resend from.


        **Requires permission:** `sales_orders.update`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                sales_order_lines:
                  type: array
                  items:
                    type: object
                    properties:
                      id:
                        type: integer
                      quantity:
                        type: integer
              example:
                sales_order_lines:
                - id: 2101
                  quantity: 2
      parameters:
      - name: salesOrder
        in: path
        schema:
          type: integer
        required: true
        description: Sales order ID
        example: '500'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      sales_order_number:
                        type: string
                      customer_po_number:
                        type: string
                        nullable: true
                      sales_channel_id:
                        type: integer
                      sales_channel_name:
                        type: string
                      sub_sales_channel_id:
                        type: string
                        nullable: true
                      sub_sales_channel:
                        type: string
                        nullable: true
                      sub_sales_channel_name:
                        type: string
                        nullable: true
                      integration_instance_id:
                        type: integer
                      integration:
                        type: string
                      integration_id:
                        type: integer
                      integration_image:
                        type: string
                      can_submit_fulfillments_to_channel:
                        type: boolean
                      store:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      sales_rep_id:
                        type: string
                        nullable: true
                      sales_rep:
                        type: string
                        nullable: true
                      accounting:
                        type: object
                        properties:
                          transaction:
                            type: string
                            nullable: true
                      order_date:
                        type: string
                      payment_date:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                      canceled_at:
                        type: string
                        nullable: true
                      currency:
                        type: string
                      currency_rate:
                        type: integer
                      discount_lines:
                        type: string
                        nullable: true
                      discounts:
                        type: array
                      order_discounts:
                        type: string
                        nullable: true
                      line_discount_total:
                        type: integer
                      order_discount_total:
                        type: integer
                      total_discount_amount:
                        type: integer
                      apply_order_discount_on:
                        type: string
                        nullable: true
                      tax_lines:
                        type: string
                        nullable: true
                      packing_slip_printed_at:
                        type: string
                        nullable: true
                      is_fba:
                        type: boolean
                      is_replacement_order:
                        type: boolean
                      need_mapping:
                        type: boolean
                      memo_for_customer:
                        type: string
                        nullable: true
                      reserved_at:
                        type: string
                        nullable: true
                      payment_hold_status:
                        type: string
                        nullable: true
                      reservation_expires_at:
                        type: string
                        nullable: true
                      ship_by_date:
                        type: string
                      hold_until_date:
                        type: string
                        nullable: true
                      is_held:
                        type: boolean
                      deliver_by_date:
                        type: string
                        nullable: true
                      fulfilled_at:
                        type: string
                        nullable: true
                      shipping_method_id:
                        type: integer
                      shipping_method:
                        type: string
                      is_pickup:
                        type: boolean
                      shipped_is_pickup:
                        type: boolean
                      address_check:
                        type: object
                        properties:
                          has_warning:
                            type: boolean
                          has_block:
                            type: boolean
                          highest_severity:
                            type: string
                          warnings:
                            type: array
                            items:
                              type: object
                              properties:
                                rule_id:
                                  type: string
                                severity:
                                  type: string
                                message:
                                  type: string
                      requested_shipping_method:
                        type: string
                      mapped_shipping_method:
                        type: string
                      has_backorder:
                        type: boolean
                      fulfillment:
                        type: array
                      fulfillment_channel:
                        type: string
                        nullable: true
                      customer_name:
                        type: object
                        properties:
                          id:
                            type: string
                            nullable: true
                          name:
                            type: string
                      customer_email:
                        type: string
                      customer_company:
                        type: string
                        nullable: true
                      customer_phone:
                        type: string
                      sales_order_shipping_address:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          email:
                            type: string
                          company:
                            type: string
                            nullable: true
                          phone:
                            type: string
                          address1:
                            type: string
                          address2:
                            type: string
                          address3:
                            type: string
                            nullable: true
                          city:
                            type: string
                          province:
                            type: string
                          province_code:
                            type: string
                          zip:
                            type: string
                          country:
                            type: string
                          country_code:
                            type: string
                      shipping_overridden_at:
                        type: string
                        nullable: true
                      is_shipping_overridden:
                        type: boolean
                      sales_order_billing_address:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          email:
                            type: string
                          company:
                            type: string
                            nullable: true
                          phone:
                            type: string
                          address1:
                            type: string
                          address2:
                            type: string
                          address3:
                            type: string
                            nullable: true
                          city:
                            type: string
                          province:
                            type: string
                          province_code:
                            type: string
                          zip:
                            type: string
                          country:
                            type: string
                          country_code:
                            type: string
                      item_info:
                        type: array
                        items:
                          type: object
                          properties:
                            sales_order_line_id:
                              type: integer
                            sales_channel_line_id:
                              type: string
                              nullable: true
                            bundle_quantity_cache:
                              type: string
                              nullable: true
                            unit_cost:
                              type: number
                            tax_rate:
                              type: integer
                            tax_rate_id:
                              type: string
                              nullable: true
                            item_tax_value:
                              type: integer
                            fifo_layer_id:
                              type: string
                              nullable: true
                            item_quantity:
                              type: integer
                            item_canceled_quantity:
                              type: integer
                            item_allocated_quantity:
                              type: integer
                            item_on_hand_allocated_quantity:
                              type: integer
                            item_unallocated_quantity:
                              type: integer
                            sales_channel_fulfillment_out_of_sync:
                              type: boolean
                            item_externally_fulfilled_quantity:
                              type: integer
                            fulfilled_quantity:
                              type: integer
                            submitted_quantity:
                              type: integer
                            item_dropshipped_quantity:
                              type: integer
                            item_sku:
                              type: object
                              properties:
                                id:
                                  type: integer
                                sku:
                                  type: string
                            item_bundle_sku:
                              type: string
                              nullable: true
                            item_barcode:
                              type: string
                            item_weight:
                              type: number
                            item_weight_unit:
                              type: string
                            item_brand:
                              type: object
                              properties:
                                id:
                                  type: integer
                                name:
                                  type: string
                            bundle:
                              type: string
                              nullable: true
                            bundle_proration_basis:
                              type: string
                              nullable: true
                            item_price:
                              type: integer
                            item_price_with_tax:
                              type: integer
                            item_name:
                              type: string
                            item_nominal_code_id:
                              type: string
                              nullable: true
                            item_nominal_code:
                              type: string
                              nullable: true
                            item_nominal_code_code:
                              type: string
                              nullable: true
                            item_discount:
                              type: integer
                            item_line_discounts:
                              type: array
                            item_line_discount_total:
                              type: integer
                            item_net_total:
                              type: integer
                            price_after_line_discount:
                              type: integer
                            line_discount_total:
                              type: integer
                            allocated_order_discount:
                              type: integer
                            net_total:
                              type: integer
                            item_has_backorder:
                              type: boolean
                            allocation_locked:
                              type: boolean
                            allocation_locked_reason:
                              type: string
                              nullable: true
                            is_product:
                              type: boolean
                            is_bundle:
                              type: boolean
                            is_variation:
                              type: boolean
                            credited_quantity:
                              type: integer
                            credit_sources:
                              type: array
                              items:
                                type: object
                                properties:
                                  vendor_credit_id:
                                    type: integer
                                  vendor_credit_number:
                                    type: string
                                  quantity:
                                    type: integer
                                  credit_status:
                                    type: string
                                  restock_inventory:
                                    type: boolean
                            warehouse_routing_method:
                              type: string
                            warehouse:
                              type: object
                              properties:
                                id:
                                  type: integer
                                name:
                                  type: string
                                supplier_id:
                                  type: string
                                  nullable: true
                                supplier_name:
                                  type: string
                                  nullable: true
                            is_fulfilled:
                              type: boolean
                            no_audit_trail:
                              type: boolean
                            unfulfilled_quantity:
                              type: integer
                            remaining_to_fulfill_quantity:
                              type: integer
                            available_to_fulfill:
                              type: integer
                            committed_to_fulfillment_quantity:
                              type: integer
                            returnable_quantity:
                              type: integer
                            inventory_allocation_id:
                              type: string
                              nullable: true
                            backordered_quantity:
                              type: integer
                            listing:
                              type: string
                              nullable: true
                            channel_product_external_id:
                              type: string
                              nullable: true
                            sales_channel_product_id:
                              type: string
                              nullable: true
                            subscription_edition_id:
                              type: string
                              nullable: true
                            subscription_edition:
                              type: string
                              nullable: true
                            subscription_offering:
                              type: string
                              nullable: true
                            created_at:
                              type: string
                            updated_at:
                              type: string
                            cogs:
                              type: string
                              nullable: true
                            estimated_decoration_cost:
                              type: integer
                            actual_decoration_cost:
                              type: integer
                            decoration_cost_breakdown:
                              type: string
                              nullable: true
                            is_taxable:
                              type: boolean
                            default_tax_rate_id:
                              type: string
                              nullable: true
                            item_img_url:
                              type: string
                            item_inventory:
                              type: object
                              properties:
                                total:
                                  type: object
                                  properties:
                                    inbound:
                                      type: integer
                                    stock:
                                      type: integer
                                    allocated:
                                      type: integer
                                    on_hold:
                                      type: integer
                                    available:
                                      type: integer
                                    in_transit:
                                      type: integer
                                warehouses:
                                  type: object
                                  properties:
                                    Main Warehouse:
                                      type: object
                                      properties:
                                        inbound:
                                          type: integer
                                        stock:
                                          type: integer
                                        allocated:
                                          type: integer
                                        on_hold:
                                          type: integer
                                        available:
                                          type: integer
                                        supplier_in_stock:
                                          type: string
                                          nullable: true
                                        in_transit:
                                          type: integer
                                        warehouse_id:
                                          type: integer
                                        warehouse_name:
                                          type: string
                                        warehouse_type:
                                          type: string
                                        supplier:
                                          type: string
                                          nullable: true
                                        country_code:
                                          type: string
                            item_stock:
                              type: integer
                      purchase_orders:
                        type: array
                      adjustments:
                        type: array
                      financial_lines:
                        type: array
                      custom_field_values:
                        type: array
                      order_status:
                        type: string
                      fulfillment_status:
                        type: string
                      fulfillment_sequence:
                        type: string
                        nullable: true
                      payment_status:
                        type: string
                      tax_revenue:
                        type: integer
                      product_total:
                        type: integer
                      total:
                        type: integer
                      discount_total:
                        type: integer
                      currency_code:
                        type: string
                      tags:
                        type: array
                        items:
                          type: string
                      warehouses:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            supplier_id:
                              type: string
                              nullable: true
                            supplier_name:
                              type: string
                              nullable: true
                      can_fulfill:
                        type: boolean
                      exact_discount_total:
                        type: integer
                      is_tax_included:
                        type: boolean
                      tax_total:
                        type: integer
                      calculated_tax_total:
                        type: integer
                      exact_tax_total:
                        type: integer
                      tax_rate_id:
                        type: string
                        nullable: true
                      tax_rate:
                        type: string
                        nullable: true
                      payments:
                        type: array
                      notes:
                        type: array
                      earliest_covered_ship_by_date:
                        type: string
                        nullable: true
                      latest_covered_ship_by_date:
                        type: string
                        nullable: true
                      has_backorder_lines:
                        type: boolean
                example:
                  message: The sales order resend successfully
                  data:
                    id: 612
                    sales_order_number: SO-0158-R-20260706
                    customer_po_number: null
                    sales_channel_id: 3
                    sales_channel_name: Shopify - Main Store
                    sub_sales_channel_id: null
                    sub_sales_channel: null
                    sub_sales_channel_name: null
                    integration_instance_id: 2
                    integration: Shopify
                    integration_id: 4
                    integration_image: https://cdn.sku.io/integrations/shopify.png
                    can_submit_fulfillments_to_channel: true
                    store:
                      id: 1
                      name: Main Store
                    sales_rep_id: null
                    sales_rep: null
                    accounting:
                      transaction: null
                    order_date: '2026-07-06T10:15:00.000000Z'
                    payment_date: null
                    created_at: '2026-07-06T10:15:00.000000Z'
                    updated_at: '2026-07-06T10:15:00.000000Z'
                    archived_at: null
                    canceled_at: null
                    currency: USD
                    currency_rate: 1
                    discount_lines: null
                    discounts: []
                    order_discounts: null
                    line_discount_total: 0
                    order_discount_total: 0
                    total_discount_amount: 0
                    apply_order_discount_on: null
                    tax_lines: null
                    packing_slip_printed_at: null
                    is_fba: false
                    is_replacement_order: false
                    need_mapping: false
                    memo_for_customer: null
                    reserved_at: null
                    payment_hold_status: null
                    reservation_expires_at: null
                    ship_by_date: '2026-06-19T00:00:00.000000Z'
                    hold_until_date: null
                    is_held: false
                    deliver_by_date: null
                    fulfilled_at: null
                    shipping_method_id: 7
                    shipping_method: USPS Priority Mail
                    is_pickup: false
                    shipped_is_pickup: false
                    address_check:
                      has_warning: true
                      has_block: false
                      highest_severity: warning
                      warnings:
                      - rule_id: missing-required
                        severity: warning
                        message: Shipping address is missing required fields (name,
                          street, city, postcode or country).
                    requested_shipping_method: Standard Shipping
                    mapped_shipping_method: USPS Priority Mail
                    has_backorder: false
                    fulfillment: []
                    fulfillment_channel: null
                    customer_name:
                      id: null
                      name: Jane Cooper
                    customer_email: jane.cooper@example.com
                    customer_company: null
                    customer_phone: +1 555-201-4477
                    sales_order_shipping_address:
                      id: 1201
                      name: Jane Cooper
                      email: jane.cooper@example.com
                      company: null
                      phone: +1 555-201-4477
                      address1: 982 Maple Avenue
                      address2: Apt 4B
                      address3: null
                      city: Portland
                      province: Oregon
                      province_code: OR
                      zip: '97205'
                      country: United States
                      country_code: US
                    shipping_overridden_at: null
                    is_shipping_overridden: false
                    sales_order_billing_address:
                      id: 1202
                      name: Jane Cooper
                      email: jane.cooper@example.com
                      company: null
                      phone: +1 555-201-4477
                      address1: 982 Maple Avenue
                      address2: Apt 4B
                      address3: null
                      city: Portland
                      province: Oregon
                      province_code: OR
                      zip: '97205'
                      country: United States
                      country_code: US
                    item_info:
                    - sales_order_line_id: 2310
                      sales_channel_line_id: null
                      bundle_quantity_cache: null
                      unit_cost: 11.42
                      tax_rate: 0
                      tax_rate_id: null
                      item_tax_value: 0
                      fifo_layer_id: null
                      item_quantity: 2
                      item_canceled_quantity: 0
                      item_allocated_quantity: 0
                      item_on_hand_allocated_quantity: 0
                      item_unallocated_quantity: 2
                      sales_channel_fulfillment_out_of_sync: false
                      item_externally_fulfilled_quantity: 0
                      fulfilled_quantity: 0
                      submitted_quantity: 0
                      item_dropshipped_quantity: 0
                      item_sku:
                        id: 812
                        sku: WB-32-BLU
                      item_bundle_sku: null
                      item_barcode: 0812345678905
                      item_weight: 1.2
                      item_weight_unit: lb
                      item_brand:
                        id: 14
                        name: HydraPeak
                      bundle: null
                      bundle_proration_basis: null
                      item_price: 0
                      item_price_with_tax: 0
                      item_name: Stainless Steel Water Bottle 32oz - Ocean Blue
                      item_nominal_code_id: null
                      item_nominal_code: null
                      item_nominal_code_code: null
                      item_discount: 0
                      item_line_discounts: []
                      item_line_discount_total: 0
                      item_net_total: 0
                      price_after_line_discount: 0
                      line_discount_total: 0
                      allocated_order_discount: 0
                      net_total: 0
                      item_has_backorder: false
                      allocation_locked: false
                      allocation_locked_reason: null
                      is_product: true
                      is_bundle: false
                      is_variation: false
                      credited_quantity: 0
                      credit_sources:
                      - vendor_credit_id: 42
                        vendor_credit_number: VC-1001
                        quantity: 5
                        credit_status: open
                        restock_inventory: false
                      warehouse_routing_method: advanced
                      warehouse:
                        id: 3
                        name: Main Warehouse
                        supplier_id: null
                        supplier_name: null
                      is_fulfilled: false
                      no_audit_trail: false
                      unfulfilled_quantity: 2
                      remaining_to_fulfill_quantity: 2
                      available_to_fulfill: 2
                      committed_to_fulfillment_quantity: 0
                      returnable_quantity: 0
                      inventory_allocation_id: null
                      backordered_quantity: 0
                      listing: null
                      channel_product_external_id: null
                      sales_channel_product_id: null
                      subscription_edition_id: null
                      subscription_edition: null
                      subscription_offering: null
                      created_at: '2026-06-18T14:23:15.000000Z'
                      updated_at: '2026-06-19T16:40:21.000000Z'
                      cogs: null
                      estimated_decoration_cost: 0
                      actual_decoration_cost: 0
                      decoration_cost_breakdown: null
                      is_taxable: true
                      default_tax_rate_id: null
                      item_img_url: https://cdn.sku.io/products/wb-32-blu.jpg
                      item_inventory:
                        total:
                          inbound: 24
                          stock: 150
                          allocated: 2
                          on_hold: 0
                          available: 148
                          in_transit: 0
                        warehouses:
                          Main Warehouse:
                            inbound: 24
                            stock: 150
                            allocated: 2
                            on_hold: 0
                            available: 148
                            supplier_in_stock: null
                            in_transit: 0
                            warehouse_id: 3
                            warehouse_name: Main Warehouse
                            warehouse_type: standard
                            supplier: null
                            country_code: US
                      item_stock: 148
                    purchase_orders: []
                    adjustments: []
                    financial_lines: []
                    custom_field_values: []
                    order_status: draft
                    fulfillment_status: unfulfilled
                    fulfillment_sequence: null
                    payment_status: unpaid
                    tax_revenue: 0
                    product_total: 0
                    total: 0
                    discount_total: 0
                    currency_code: USD
                    tags:
                    - wholesale
                    warehouses:
                    - id: 3
                      name: Main Warehouse
                      supplier_id: null
                      supplier_name: null
                    can_fulfill: false
                    exact_discount_total: 0
                    is_tax_included: false
                    tax_total: 0
                    calculated_tax_total: 0
                    exact_tax_total: 0
                    tax_rate_id: null
                    tax_rate: null
                    payments: []
                    notes: []
                    earliest_covered_ship_by_date: null
                    latest_covered_ship_by_date: null
                    has_backorder_lines: false
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      sales_order_lines.0.quantity:
                        type: array
                        items:
                          type: string
                example:
                  message: The given data was invalid.
                  errors:
                    sales_order_lines.0.quantity:
                    - The selected quantity '5' is greater than original quantity
                      line
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:write
      operationId: post-api-sales-orders-salesorder-resend
  /api/sales-orders/{salesOrder}/exchange:
    post:
      tags:
      - Sales Orders
      summary: Exchange Sales Order
      description: 'Creates an exchange order for an existing order (e.g. swapping
        returned items), linked to the original order or to a sales credit, and returns
        the new order''s full detail.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        The new order is a copy of the original with:

        - order number `{original}-E-{YYYYMMDD}` and order date set to now

        - only the requested lines, at the requested quantities, keeping the original
        line prices

        - a sales-credit payment automatically recorded for the new order''s total
        (the exchange is paid by credit), and the order is approved immediately

        - an exchange link to the sales credit when `sales_credit_id` is provided,
        otherwise to the original order


        Authentication: Requires Bearer token.


        Request body fields:

        - sales_order_lines (array, optional): Lines to exchange. Each item: id (integer,
        required — must be a line of this order), quantity (number, required).

        - sales_credit_id (integer, optional): Existing sales credit to link the exchange
        order to.


        Path parameters:

        - salesOrder (required): Sales order ID to exchange from.


        **Requires permission:** `sales_orders.update`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                sales_order_lines:
                  type: array
                  items:
                    type: object
                    properties:
                      id:
                        type: integer
                      quantity:
                        type: integer
                sales_credit_id:
                  type: integer
              example:
                sales_order_lines:
                - id: 2101
                  quantity: 2
                sales_credit_id: 88
      parameters:
      - name: salesOrder
        in: path
        schema:
          type: integer
        required: true
        description: Sales order ID
        example: '500'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      sales_order_number:
                        type: string
                      customer_po_number:
                        type: string
                        nullable: true
                      sales_channel_id:
                        type: integer
                      sales_channel_name:
                        type: string
                      sub_sales_channel_id:
                        type: string
                        nullable: true
                      sub_sales_channel:
                        type: string
                        nullable: true
                      sub_sales_channel_name:
                        type: string
                        nullable: true
                      integration_instance_id:
                        type: integer
                      integration:
                        type: string
                      integration_id:
                        type: integer
                      integration_image:
                        type: string
                      can_submit_fulfillments_to_channel:
                        type: boolean
                      store:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      sales_rep_id:
                        type: string
                        nullable: true
                      sales_rep:
                        type: string
                        nullable: true
                      accounting:
                        type: object
                        properties:
                          transaction:
                            type: string
                            nullable: true
                      order_date:
                        type: string
                      payment_date:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                      canceled_at:
                        type: string
                        nullable: true
                      currency:
                        type: string
                      currency_rate:
                        type: integer
                      discount_lines:
                        type: string
                        nullable: true
                      discounts:
                        type: array
                      order_discounts:
                        type: string
                        nullable: true
                      line_discount_total:
                        type: integer
                      order_discount_total:
                        type: integer
                      total_discount_amount:
                        type: integer
                      apply_order_discount_on:
                        type: string
                        nullable: true
                      tax_lines:
                        type: string
                        nullable: true
                      packing_slip_printed_at:
                        type: string
                        nullable: true
                      is_fba:
                        type: boolean
                      is_replacement_order:
                        type: boolean
                      need_mapping:
                        type: boolean
                      memo_for_customer:
                        type: string
                        nullable: true
                      reserved_at:
                        type: string
                        nullable: true
                      payment_hold_status:
                        type: string
                        nullable: true
                      reservation_expires_at:
                        type: string
                        nullable: true
                      ship_by_date:
                        type: string
                      hold_until_date:
                        type: string
                        nullable: true
                      is_held:
                        type: boolean
                      deliver_by_date:
                        type: string
                        nullable: true
                      fulfilled_at:
                        type: string
                        nullable: true
                      shipping_method_id:
                        type: integer
                      shipping_method:
                        type: string
                      is_pickup:
                        type: boolean
                      shipped_is_pickup:
                        type: boolean
                      address_check:
                        type: object
                        properties:
                          has_warning:
                            type: boolean
                          has_block:
                            type: boolean
                          highest_severity:
                            type: string
                          warnings:
                            type: array
                            items:
                              type: object
                              properties:
                                rule_id:
                                  type: string
                                severity:
                                  type: string
                                message:
                                  type: string
                      requested_shipping_method:
                        type: string
                      mapped_shipping_method:
                        type: string
                      has_backorder:
                        type: boolean
                      fulfillment:
                        type: array
                      fulfillment_channel:
                        type: string
                        nullable: true
                      customer_name:
                        type: object
                        properties:
                          id:
                            type: string
                            nullable: true
                          name:
                            type: string
                      customer_email:
                        type: string
                      customer_company:
                        type: string
                        nullable: true
                      customer_phone:
                        type: string
                      sales_order_shipping_address:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          email:
                            type: string
                          company:
                            type: string
                            nullable: true
                          phone:
                            type: string
                          address1:
                            type: string
                          address2:
                            type: string
                          address3:
                            type: string
                            nullable: true
                          city:
                            type: string
                          province:
                            type: string
                          province_code:
                            type: string
                          zip:
                            type: string
                          country:
                            type: string
                          country_code:
                            type: string
                      shipping_overridden_at:
                        type: string
                        nullable: true
                      is_shipping_overridden:
                        type: boolean
                      sales_order_billing_address:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          email:
                            type: string
                          company:
                            type: string
                            nullable: true
                          phone:
                            type: string
                          address1:
                            type: string
                          address2:
                            type: string
                          address3:
                            type: string
                            nullable: true
                          city:
                            type: string
                          province:
                            type: string
                          province_code:
                            type: string
                          zip:
                            type: string
                          country:
                            type: string
                          country_code:
                            type: string
                      item_info:
                        type: array
                        items:
                          type: object
                          properties:
                            sales_order_line_id:
                              type: integer
                            sales_channel_line_id:
                              type: string
                              nullable: true
                            bundle_quantity_cache:
                              type: string
                              nullable: true
                            unit_cost:
                              type: number
                            tax_rate:
                              type: integer
                            tax_rate_id:
                              type: string
                              nullable: true
                            item_tax_value:
                              type: integer
                            fifo_layer_id:
                              type: string
                              nullable: true
                            item_quantity:
                              type: integer
                            item_canceled_quantity:
                              type: integer
                            item_allocated_quantity:
                              type: integer
                            item_on_hand_allocated_quantity:
                              type: integer
                            item_unallocated_quantity:
                              type: integer
                            sales_channel_fulfillment_out_of_sync:
                              type: boolean
                            item_externally_fulfilled_quantity:
                              type: integer
                            fulfilled_quantity:
                              type: integer
                            submitted_quantity:
                              type: integer
                            item_dropshipped_quantity:
                              type: integer
                            item_sku:
                              type: object
                              properties:
                                id:
                                  type: integer
                                sku:
                                  type: string
                            item_bundle_sku:
                              type: string
                              nullable: true
                            item_barcode:
                              type: string
                            item_weight:
                              type: number
                            item_weight_unit:
                              type: string
                            item_brand:
                              type: object
                              properties:
                                id:
                                  type: integer
                                name:
                                  type: string
                            bundle:
                              type: string
                              nullable: true
                            bundle_proration_basis:
                              type: string
                              nullable: true
                            item_price:
                              type: number
                            item_price_with_tax:
                              type: number
                            item_name:
                              type: string
                            item_nominal_code_id:
                              type: string
                              nullable: true
                            item_nominal_code:
                              type: string
                              nullable: true
                            item_nominal_code_code:
                              type: string
                              nullable: true
                            item_discount:
                              type: integer
                            item_line_discounts:
                              type: array
                            item_line_discount_total:
                              type: integer
                            item_net_total:
                              type: number
                            price_after_line_discount:
                              type: number
                            line_discount_total:
                              type: integer
                            allocated_order_discount:
                              type: integer
                            net_total:
                              type: number
                            item_has_backorder:
                              type: boolean
                            allocation_locked:
                              type: boolean
                            allocation_locked_reason:
                              type: string
                              nullable: true
                            is_product:
                              type: boolean
                            is_bundle:
                              type: boolean
                            is_variation:
                              type: boolean
                            credited_quantity:
                              type: integer
                            credit_sources:
                              type: array
                              items:
                                type: object
                                properties:
                                  vendor_credit_id:
                                    type: integer
                                  vendor_credit_number:
                                    type: string
                                  quantity:
                                    type: integer
                                  credit_status:
                                    type: string
                                  restock_inventory:
                                    type: boolean
                            warehouse_routing_method:
                              type: string
                            warehouse:
                              type: object
                              properties:
                                id:
                                  type: integer
                                name:
                                  type: string
                                supplier_id:
                                  type: string
                                  nullable: true
                                supplier_name:
                                  type: string
                                  nullable: true
                            is_fulfilled:
                              type: boolean
                            no_audit_trail:
                              type: boolean
                            unfulfilled_quantity:
                              type: integer
                            remaining_to_fulfill_quantity:
                              type: integer
                            available_to_fulfill:
                              type: integer
                            committed_to_fulfillment_quantity:
                              type: integer
                            returnable_quantity:
                              type: integer
                            inventory_allocation_id:
                              type: string
                              nullable: true
                            backordered_quantity:
                              type: integer
                            listing:
                              type: string
                              nullable: true
                            channel_product_external_id:
                              type: string
                              nullable: true
                            sales_channel_product_id:
                              type: string
                              nullable: true
                            subscription_edition_id:
                              type: string
                              nullable: true
                            subscription_edition:
                              type: string
                              nullable: true
                            subscription_offering:
                              type: string
                              nullable: true
                            created_at:
                              type: string
                            updated_at:
                              type: string
                            cogs:
                              type: string
                              nullable: true
                            estimated_decoration_cost:
                              type: integer
                            actual_decoration_cost:
                              type: integer
                            decoration_cost_breakdown:
                              type: string
                              nullable: true
                            is_taxable:
                              type: boolean
                            default_tax_rate_id:
                              type: string
                              nullable: true
                            item_img_url:
                              type: string
                            item_inventory:
                              type: object
                              properties:
                                total:
                                  type: object
                                  properties:
                                    inbound:
                                      type: integer
                                    stock:
                                      type: integer
                                    allocated:
                                      type: integer
                                    on_hold:
                                      type: integer
                                    available:
                                      type: integer
                                    in_transit:
                                      type: integer
                                warehouses:
                                  type: object
                                  properties:
                                    Main Warehouse:
                                      type: object
                                      properties:
                                        inbound:
                                          type: integer
                                        stock:
                                          type: integer
                                        allocated:
                                          type: integer
                                        on_hold:
                                          type: integer
                                        available:
                                          type: integer
                                        supplier_in_stock:
                                          type: string
                                          nullable: true
                                        in_transit:
                                          type: integer
                                        warehouse_id:
                                          type: integer
                                        warehouse_name:
                                          type: string
                                        warehouse_type:
                                          type: string
                                        supplier:
                                          type: string
                                          nullable: true
                                        country_code:
                                          type: string
                            item_stock:
                              type: integer
                      purchase_orders:
                        type: array
                      adjustments:
                        type: array
                      financial_lines:
                        type: array
                      custom_field_values:
                        type: array
                      order_status:
                        type: string
                      fulfillment_status:
                        type: string
                      fulfillment_sequence:
                        type: string
                        nullable: true
                      payment_status:
                        type: string
                      tax_revenue:
                        type: integer
                      product_total:
                        type: number
                      total:
                        type: number
                      discount_total:
                        type: integer
                      currency_code:
                        type: string
                      tags:
                        type: array
                        items:
                          type: string
                      warehouses:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            supplier_id:
                              type: string
                              nullable: true
                            supplier_name:
                              type: string
                              nullable: true
                      can_fulfill:
                        type: boolean
                      exact_discount_total:
                        type: integer
                      is_tax_included:
                        type: boolean
                      tax_total:
                        type: integer
                      calculated_tax_total:
                        type: integer
                      exact_tax_total:
                        type: integer
                      tax_rate_id:
                        type: string
                        nullable: true
                      tax_rate:
                        type: string
                        nullable: true
                      payments:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            amount:
                              type: number
                            cost:
                              type: string
                              nullable: true
                            payment_date:
                              type: string
                            payment_type:
                              type: object
                              properties:
                                id:
                                  type: integer
                                name:
                                  type: string
                            external_reference:
                              type: string
                              nullable: true
                            type:
                              type: string
                            currency_code:
                              type: string
                            sales_credit_allocation:
                              type: string
                              nullable: true
                      notes:
                        type: array
                      earliest_covered_ship_by_date:
                        type: string
                        nullable: true
                      latest_covered_ship_by_date:
                        type: string
                        nullable: true
                      has_backorder_lines:
                        type: boolean
                example:
                  message: The sales order exchanged successfully
                  data:
                    id: 612
                    sales_order_number: SO-0158-E-20260706
                    customer_po_number: null
                    sales_channel_id: 3
                    sales_channel_name: Shopify - Main Store
                    sub_sales_channel_id: null
                    sub_sales_channel: null
                    sub_sales_channel_name: null
                    integration_instance_id: 2
                    integration: Shopify
                    integration_id: 4
                    integration_image: https://cdn.sku.io/integrations/shopify.png
                    can_submit_fulfillments_to_channel: true
                    store:
                      id: 1
                      name: Main Store
                    sales_rep_id: null
                    sales_rep: null
                    accounting:
                      transaction: null
                    order_date: '2026-07-06T10:15:00.000000Z'
                    payment_date: null
                    created_at: '2026-07-06T10:15:00.000000Z'
                    updated_at: '2026-07-06T10:15:00.000000Z'
                    archived_at: null
                    canceled_at: null
                    currency: USD
                    currency_rate: 1
                    discount_lines: null
                    discounts: []
                    order_discounts: null
                    line_discount_total: 0
                    order_discount_total: 0
                    total_discount_amount: 0
                    apply_order_discount_on: null
                    tax_lines: null
                    packing_slip_printed_at: null
                    is_fba: false
                    is_replacement_order: false
                    need_mapping: false
                    memo_for_customer: null
                    reserved_at: null
                    payment_hold_status: null
                    reservation_expires_at: null
                    ship_by_date: '2026-06-19T00:00:00.000000Z'
                    hold_until_date: null
                    is_held: false
                    deliver_by_date: null
                    fulfilled_at: null
                    shipping_method_id: 7
                    shipping_method: USPS Priority Mail
                    is_pickup: false
                    shipped_is_pickup: false
                    address_check:
                      has_warning: true
                      has_block: false
                      highest_severity: warning
                      warnings:
                      - rule_id: missing-required
                        severity: warning
                        message: Shipping address is missing required fields (name,
                          street, city, postcode or country).
                    requested_shipping_method: Standard Shipping
                    mapped_shipping_method: USPS Priority Mail
                    has_backorder: false
                    fulfillment: []
                    fulfillment_channel: null
                    customer_name:
                      id: null
                      name: Jane Cooper
                    customer_email: jane.cooper@example.com
                    customer_company: null
                    customer_phone: +1 555-201-4477
                    sales_order_shipping_address:
                      id: 1201
                      name: Jane Cooper
                      email: jane.cooper@example.com
                      company: null
                      phone: +1 555-201-4477
                      address1: 982 Maple Avenue
                      address2: Apt 4B
                      address3: null
                      city: Portland
                      province: Oregon
                      province_code: OR
                      zip: '97205'
                      country: United States
                      country_code: US
                    shipping_overridden_at: null
                    is_shipping_overridden: false
                    sales_order_billing_address:
                      id: 1202
                      name: Jane Cooper
                      email: jane.cooper@example.com
                      company: null
                      phone: +1 555-201-4477
                      address1: 982 Maple Avenue
                      address2: Apt 4B
                      address3: null
                      city: Portland
                      province: Oregon
                      province_code: OR
                      zip: '97205'
                      country: United States
                      country_code: US
                    item_info:
                    - sales_order_line_id: 2310
                      sales_channel_line_id: null
                      bundle_quantity_cache: null
                      unit_cost: 11.42
                      tax_rate: 0
                      tax_rate_id: null
                      item_tax_value: 0
                      fifo_layer_id: null
                      item_quantity: 2
                      item_canceled_quantity: 0
                      item_allocated_quantity: 0
                      item_on_hand_allocated_quantity: 0
                      item_unallocated_quantity: 2
                      sales_channel_fulfillment_out_of_sync: false
                      item_externally_fulfilled_quantity: 0
                      fulfilled_quantity: 0
                      submitted_quantity: 0
                      item_dropshipped_quantity: 0
                      item_sku:
                        id: 812
                        sku: WB-32-BLU
                      item_bundle_sku: null
                      item_barcode: 0812345678905
                      item_weight: 1.2
                      item_weight_unit: lb
                      item_brand:
                        id: 14
                        name: HydraPeak
                      bundle: null
                      bundle_proration_basis: null
                      item_price: 25.99
                      item_price_with_tax: 25.99
                      item_name: Stainless Steel Water Bottle 32oz - Ocean Blue
                      item_nominal_code_id: null
                      item_nominal_code: null
                      item_nominal_code_code: null
                      item_discount: 0
                      item_line_discounts: []
                      item_line_discount_total: 0
                      item_net_total: 51.98
                      price_after_line_discount: 25.99
                      line_discount_total: 0
                      allocated_order_discount: 0
                      net_total: 51.98
                      item_has_backorder: false
                      allocation_locked: false
                      allocation_locked_reason: null
                      is_product: true
                      is_bundle: false
                      is_variation: false
                      credited_quantity: 0
                      credit_sources:
                      - vendor_credit_id: 42
                        vendor_credit_number: VC-1001
                        quantity: 5
                        credit_status: open
                        restock_inventory: false
                      warehouse_routing_method: advanced
                      warehouse:
                        id: 3
                        name: Main Warehouse
                        supplier_id: null
                        supplier_name: null
                      is_fulfilled: false
                      no_audit_trail: false
                      unfulfilled_quantity: 2
                      remaining_to_fulfill_quantity: 2
                      available_to_fulfill: 2
                      committed_to_fulfillment_quantity: 0
                      returnable_quantity: 0
                      inventory_allocation_id: null
                      backordered_quantity: 0
                      listing: null
                      channel_product_external_id: null
                      sales_channel_product_id: null
                      subscription_edition_id: null
                      subscription_edition: null
                      subscription_offering: null
                      created_at: '2026-06-18T14:23:15.000000Z'
                      updated_at: '2026-06-19T16:40:21.000000Z'
                      cogs: null
                      estimated_decoration_cost: 0
                      actual_decoration_cost: 0
                      decoration_cost_breakdown: null
                      is_taxable: true
                      default_tax_rate_id: null
                      item_img_url: https://cdn.sku.io/products/wb-32-blu.jpg
                      item_inventory:
                        total:
                          inbound: 24
                          stock: 150
                          allocated: 2
                          on_hold: 0
                          available: 148
                          in_transit: 0
                        warehouses:
                          Main Warehouse:
                            inbound: 24
                            stock: 150
                            allocated: 2
                            on_hold: 0
                            available: 148
                            supplier_in_stock: null
                            in_transit: 0
                            warehouse_id: 3
                            warehouse_name: Main Warehouse
                            warehouse_type: standard
                            supplier: null
                            country_code: US
                      item_stock: 148
                    purchase_orders: []
                    adjustments: []
                    financial_lines: []
                    custom_field_values: []
                    order_status: open
                    fulfillment_status: unfulfilled
                    fulfillment_sequence: null
                    payment_status: paid
                    tax_revenue: 0
                    product_total: 51.98
                    total: 51.98
                    discount_total: 0
                    currency_code: USD
                    tags:
                    - wholesale
                    warehouses:
                    - id: 3
                      name: Main Warehouse
                      supplier_id: null
                      supplier_name: null
                    can_fulfill: false
                    exact_discount_total: 0
                    is_tax_included: false
                    tax_total: 0
                    calculated_tax_total: 0
                    exact_tax_total: 0
                    tax_rate_id: null
                    tax_rate: null
                    payments:
                    - id: 78
                      amount: 51.98
                      cost: null
                      payment_date: '2026-07-06T10:15:00.000000Z'
                      payment_type:
                        id: 6
                        name: Sales Credit
                      external_reference: null
                      type: payment
                      currency_code: USD
                      sales_credit_allocation: null
                    notes: []
                    earliest_covered_ship_by_date: null
                    latest_covered_ship_by_date: null
                    has_backorder_lines: false
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      sales_order_lines.0.id:
                        type: array
                        items:
                          type: string
                example:
                  message: The given data was invalid.
                  errors:
                    sales_order_lines.0.id:
                    - The selected line '99999' does not belongs to the sales order
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:write
      operationId: post-api-sales-orders-salesorder-exchange
  /api/sales-orders/{salesOrder}/refresh-address-snapshots:
    post:
      tags:
      - Sales Orders
      summary: Refresh Sales Order Address Snapshots
      description: 'Re-copies the current contents of the order''s shipping and billing
        address records into the order''s own inline address snapshot columns. Use
        this after editing an address record''s content (same address ID, different
        data) so the order''s stored snapshot — which is what documents and the order
        detail display — reflects the corrected address.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Only addresses linked by ID are refreshed; orders whose snapshot has no backing
        address record are left unchanged.


        Authentication: Requires Bearer token.


        No request body.


        Path parameters:

        - salesOrder (required): Sales order ID.


        **Requires permission:** `sales_orders.update`'
      requestBody:
        content: {}
      parameters:
      - name: salesOrder
        in: path
        schema:
          type: integer
        required: true
        description: Sales order ID
        example: '500'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Address columns refreshed
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      App\Models\SalesOrder:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: array
                example:
                  message: No query results for model [App\Models\SalesOrder] 999999
                  errors:
                    App\Models\SalesOrder:
                    - message: No query results for model [App\Models\SalesOrder]
                        999999
                      code: NotFound
                      data: []
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: orders:write
      operationId: post-api-sales-orders-salesorder-refresh-address-snapshots
  /api/sales-orders/{salesOrder}/fulfill:
    post:
      tags:
      - Sales Orders
      summary: Fulfill Sales Order
      description: "Records a fulfillment (shipment) against a sales order, deducting\
        \ inventory and, by default, submitting the fulfillment to the warehouse's\
        \ shipping provider and reporting it to the originating sales channel.\n\n\
        :::info[Required scope: `orders:write`]\nGrant this scope to your token under\
        \ [Settings → Developer → Personal Access Tokens](https://app.sku.io/settings/api).\n\
        :::\n\nAuthentication: Requires Bearer token.\n\nRequest body fields:\n- fulfillment_type\
        \ (string, required): How the order was/will be fulfilled. One of: manual,\
        \ shipstation, starshipit, shipmyorders, fba, walmart_wfs, veracore, shiphero,\
        \ shipfusion, d3, trackstar, pickup, sales_channel.\n- warehouse_id (integer,\
        \ optional): Warehouse to fulfill from. Auto-resolved when every product line\
        \ on the order is routed to the same warehouse; required when lines span multiple\
        \ warehouses, and it must be one of the order's line warehouses.\n- requested_shipping_method_id\
        \ (integer, optional): Mapped shipping method to request from the provider.\n\
        - requested_shipping_method (string, optional, max 255): Free-text requested\
        \ shipping method.\n- fulfilled_shipping_method_id (integer, optional): The\
        \ shipping method actually used (manual fulfillments).\n- manual_fulfilled_shipping_method\
        \ (string, optional, max 255): Free-text actual shipping method (manual fulfillments).\n\
        - fulfilled_at (date-time, required when fulfillment_type is manual): When\
        \ the shipment left the warehouse.\n- cost (number, optional, < 100000): Shipping\
        \ cost.\n- tracking_number (string, optional, max 255): Carrier tracking number.\n\
        - fulfillment_sequence (integer, optional): Sequence number; must be unique\
        \ within the sales order.\n- packing_slip_printed_at (date-time, optional):\
        \ When the packing slip was printed.\n- status (string, optional): Initial\
        \ fulfillment status.\n- submit_to_shipping_provider (boolean, optional, default\
        \ true): Set false to record the fulfillment without notifying the shipping\
        \ provider.\n- submit_to_sales_channel (boolean, optional, default true):\
        \ Set false to record the fulfillment without reporting it to the sales channel.\n\
        - fulfillment_lines (array, optional, min 1 when present): Lines and quantities\
        \ to fulfill. When omitted, defaults to every unfulfilled product line in\
        \ the resolved warehouse at its full remaining quantity.\n  - fulfillment_lines.*.sales_order_line_id\
        \ (integer, required): Sales order line to fulfill; must belong to the order\
        \ and to the resolved warehouse.\n  - fulfillment_lines.*.quantity (number,\
        \ required, >= 0, < 100000): Quantity to fulfill; cannot exceed the line's\
        \ remaining-to-fulfill quantity (already-shipped and in-flight quantities\
        \ are subtracted).\n  - fulfillment_lines.*.metadata.fba_seller_sku (string,\
        \ optional): Amazon seller SKU override for FBA fulfillments.\n  - fulfillment_lines.*.lot_allocation\
        \ (array, optional): Per-line lot override for lot-tracked products. When\
        \ omitted, lots are consumed first-expired-first-out. Entries must reconcile\
        \ to the line quantity and reference active lots of the line's product and\
        \ warehouse.\n    - fulfillment_lines.*.lot_allocation.*.fifo_layer_id (integer,\
        \ required with lot_allocation): Inventory lot/layer to consume from.\n  \
        \  - fulfillment_lines.*.lot_allocation.*.quantity (number, required with\
        \ lot_allocation, > 0): Quantity to take from that lot.\n- metadata.signature_required\
        \ (boolean, optional): Require a delivery signature.\n- metadata.saturday_delivery\
        \ (boolean, optional): Request Saturday delivery.\n- metadata.shipping_speed\
        \ (string, optional): Provider shipping speed hint.\n- metadata.comments (string,\
        \ optional): Comments passed to the provider.\n- metadata.veracore_packing_slip_comments\
        \ (string, optional, max 500): Packing slip comments (Veracore fulfillments).\n\
        - metadata.veracore_shipping_comments (string, optional, max 500): Shipping\
        \ comments (Veracore fulfillments).\n- metadata.veracore_third_party_account_number\
        \ (string, optional, max 100): Third-party billing account number (Veracore\
        \ fulfillments).\n- metadata.veracore_third_party_type (integer, optional,\
        \ one of 1, 2, 3): Third-party billing type (Veracore fulfillments).\n\nBehavior:\n\
        - The order must be approved (not draft). Closed orders can only be fulfilled\
        \ while their fulfillment status is out_of_sync.\n- Fulfillments recorded\
        \ with a Personal Access Token are treated as external/channel imports (the\
        \ order was shipped outside SKU.io) rather than shipments dispatched from\
        \ SKU.io.\n- Insufficient allocated inventory returns 422 with a structured\
        \ `shortfalls` list, and the shortfall is also recorded as a note on the order.\n\
        - If the shipping provider times out, the fulfillment is queued and processed\
        \ in the background; the request still succeeds with a processing message.\n\
        \nPath parameters:\n- salesOrder (required): Sales order ID.\n\n**Requires\
        \ permission:** `sales_orders.fulfill`"
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                fulfillment_type:
                  type: string
                warehouse_id:
                  type: integer
                fulfilled_at:
                  type: string
                fulfilled_shipping_method_id:
                  type: integer
                tracking_number:
                  type: string
                cost:
                  type: number
                fulfillment_lines:
                  type: array
                  items:
                    type: object
                    properties:
                      sales_order_line_id:
                        type: integer
                      quantity:
                        type: integer
                      lot_allocation:
                        type: array
                        items:
                          type: object
                          properties:
                            fifo_layer_id:
                              type: integer
                            quantity:
                              type: integer
                metadata:
                  type: object
                  properties:
                    signature_required:
                      type: boolean
                    comments:
                      type: string
                submit_to_shipping_provider:
                  type: boolean
                submit_to_sales_channel:
                  type: boolean
              example:
                fulfillment_type: manual
                warehouse_id: 2
                fulfilled_at: '2026-07-01 14:30:00'
                fulfilled_shipping_method_id: 4
                tracking_number: 1Z999AA10123456784
                cost: 12.85
                fulfillment_lines:
                - sales_order_line_id: 8912
                  quantity: 3
                  lot_allocation:
                  - fifo_layer_id: 5521
                    quantity: 3
                metadata:
                  signature_required: false
                  comments: Leave at front desk
                submit_to_shipping_provider: true
                submit_to_sales_channel: true
      parameters:
      - name: salesOrder
        in: path
        schema:
          type: integer
        required: true
        description: Sales order ID
        example: '500'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                example:
                  message: The sales order created successfully
                  data:
                    id: 9107
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      resource:
                        type: string
                example:
                  message: Sales order line 8912 is not fulfillable.
                  errors:
                    resource: fulfillment
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 422 Insufficient Allocation
                  value:
                    message: 'Fulfillment blocked on sales order SO-1042: insufficient
                      allocation. SKU WIDGET-BLUE (line #8912): requested 5, allocated
                      2'
                    errors:
                      shortfalls:
                      - sales_order_line_id: 8912
                        sku: WIDGET-BLUE
                        requested: 5
                        allocated: 2
                        shortfall: 3
                example-1:
                  summary: 422 Validation Error
                  value:
                    message: The given data was invalid.
                    errors:
                      fulfillment_type:
                      - The selected fulfillment type is invalid.
                      fulfillment_lines.0.quantity:
                      - Exceeds remaining to fulfill
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:write
      operationId: post-api-sales-orders-salesorder-fulfill
  /api/sales-orders/fulfill:
    post:
      tags:
      - Sales Orders
      summary: Bulk Fulfill Sales Orders
      description: 'Fulfills multiple sales orders at once by submitting each order''s
        pending fulfillment work to the shipping provider or fulfillment service configured
        for its warehouse(s). This is an operator-initiated action, so warehouse auto-dispatch
        eligibility rules are bypassed.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Request body fields (one of `ids` or `filters` is required):

        - ids (array of integers, required without `filters`): Sales order IDs to
        fulfill.

        - filters (object, required without `ids`): Filter set that resolves to a
        list of sales order IDs (same shape used by the sales-orders listing endpoint).


        Behavior:

        - Orders on hold (a `hold_until_date` in the future) are skipped and reported
        in the result errors.

        - No shipment record is created at submit time — the provider''s ship confirmation
        records the shipment later.

        - Per-order failures do not abort the batch; they are collected and returned.

        - Returns a summary with `total`, `success`, `errors`, and an overall `status`
        of `success` or `error`. When some orders fail, the response is returned as
        a warning with the per-order errors listed under `warnings`.


        **Requires permission:** `sales_orders.fulfill`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 7116
                - 7117
                - 7118
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 All Fulfilled
                  value:
                    message: All fulfillable sales orders fulfilled successfully
                    data:
                      errors: []
                      total: 3
                      success: 3
                      status: success
                example-1:
                  summary: 200 Partial Success (some skipped)
                  value:
                    message: 2/3 sales orders had been fulfilled successfully
                    warnings:
                    - sales_order_id: 7118
                      message: Order SO-7118 is held until Fri, Jul 10, 2026 5:00
                        PM and cannot be fulfilled before then.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      ids:
                        type: array
                        items:
                          type: string
                example:
                  message: The given data was invalid.
                  errors:
                    ids:
                    - The ids field is required when filters is not present.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: orders:write
      operationId: post-api-sales-orders-fulfill
  /api/sales-orders/{salesOrder}/fulfill-fba:
    post:
      tags:
      - Sales Orders
      summary: Fulfill Sales Order via FBA
      description: "Submits a Fulfilled-by-Amazon multi-channel fulfillment request\
        \ for the sales order — Amazon picks, packs, and ships the selected lines\
        \ out of FBA stock on your behalf. Only available in production environments.\n\
        \n:::info[Required scope: `orders:write`]\nGrant this scope to your token\
        \ under [Settings → Developer → Personal Access Tokens](https://app.sku.io/settings/api).\n\
        :::\n\nAuthentication: Requires Bearer token.\n\nRequest body fields:\n- warehouse_id\
        \ (integer, optional): The Amazon FBA warehouse to fulfill from (must be an\
        \ FBA-type warehouse). Auto-resolved when every product line on the order\
        \ is routed to the same warehouse; required when lines span multiple warehouses.\n\
        - shipping_speed (string, required): Amazon shipping speed category. One of:\
        \ Standard, Expedited, Priority.\n- comments (string, required): Displayable\
        \ order comment passed to Amazon.\n- fulfillment_lines (array, optional, min\
        \ 1 when present): Lines and quantities to fulfill. When omitted, defaults\
        \ to every unfulfilled product line in the resolved warehouse at its full\
        \ remaining quantity.\n  - fulfillment_lines.*.sales_order_line_id (integer,\
        \ required): Sales order line to fulfill; must belong to the order and the\
        \ resolved warehouse, and must not already be fulfilled.\n  - fulfillment_lines.*.quantity\
        \ (number, required, >= 1): Quantity to fulfill; cannot exceed the line's\
        \ remaining-to-fulfill quantity.\n  - fulfillment_lines.*.product_listing_id\
        \ (integer, required): The Amazon product listing to ship for this line.\n\
        \nBehavior:\n- The order must be approved (not draft) and not closed.\n- On\
        \ success, the fulfillment order is created at Amazon and the response includes\
        \ the new fulfillment record ID and Amazon's request identifier.\n- Outside\
        \ production environments the request is rejected with an `IsUnacceptable`\
        \ error and no fulfillment is created.\n\nPath parameters:\n- salesOrder (required):\
        \ Sales order ID.\n\n**Requires permission:** `sales_orders.fulfill`"
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                warehouse_id:
                  type: integer
                shipping_speed:
                  type: string
                comments:
                  type: string
                fulfillment_lines:
                  type: array
                  items:
                    type: object
                    properties:
                      sales_order_line_id:
                        type: integer
                      quantity:
                        type: integer
                      product_listing_id:
                        type: integer
              example:
                warehouse_id: 7
                shipping_speed: Standard
                comments: Multi-channel fulfillment for web order SO-1042
                fulfillment_lines:
                - sales_order_line_id: 8912
                  quantity: 2
                  product_listing_id: 4410
      parameters:
      - name: salesOrder
        in: path
        schema:
          type: integer
        required: true
        description: Sales order ID
        example: '500'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 Success
                  value:
                    message: The sales order fulfillment created successfully
                    data:
                      resource: sales order fulfillment
                      id: 9111
                      request_id: 8f2a6c1e-3d4b-4f6a-9b21-77d0c3a51e90
                example-1:
                  summary: 200 Rejected Outside Production
                  value:
                    status: failure
                    message: Only available on production.
                    errors:
                      FulfillFBA:
                      - message: Only available on production.
                        code: IsUnacceptable
                        data: []
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      shipping_speed:
                        type: array
                        items:
                          type: string
                      fulfillment_lines.0.product_listing_id:
                        type: array
                        items:
                          type: string
                example:
                  message: The given data was invalid.
                  errors:
                    shipping_speed:
                    - The selected shipping speed is invalid.
                    fulfillment_lines.0.product_listing_id:
                    - The selected fulfillment_lines.0.product_listing_id is invalid.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:write
      operationId: post-api-sales-orders-salesorder-fulfill-fba
  /api/sales-orders/{salesOrder}/mark-for-pickup:
    post:
      tags:
      - Sales Orders
      summary: Mark Sales Order for Pickup
      description: "Stages a subset of the order's allocated line quantities for customer\
        \ pickup. The order's pending fulfillment work is parked in an awaiting-pickup\
        \ state — no shipment record is created until the customer actually collects\
        \ — and the request records who marked the items, when, and the expected pickup\
        \ date. Partial quantities are supported, so some units can be marked for\
        \ pickup while the rest are fulfilled normally.\n\n:::info[Required scope:\
        \ `orders:write`]\nGrant this scope to your token under [Settings → Developer\
        \ → Personal Access Tokens](https://app.sku.io/settings/api).\n:::\n\nAuthentication:\
        \ Requires Bearer token.\n\nRequest body fields:\n- warehouse_id (integer,\
        \ required): Warehouse the customer will collect from. Every listed line must\
        \ be routed to this warehouse.\n- expected_pickup_at (date-time, optional):\
        \ When the customer is expected to collect.\n- note (string, optional, max\
        \ 2000): Free-text note; recorded on the order as \"Marked for pickup: &lt;note>\"\
        .\n- items (array, required, min 1): Lines and quantities to mark for pickup.\n\
        \  - items.*.sales_order_line_id (integer, required): Sales order line; must\
        \ belong to the order and the given warehouse.\n  - items.*.quantity (number,\
        \ required, > 0, < 100000): Quantity to mark; cannot exceed the line's unfulfilled\
        \ quantity.\n\nBehavior:\n- Returns the ID of the pickup-staged fulfillment\
        \ order in `fulfillment_order_id`.\n- Items with a zero quantity are ignored;\
        \ if no item has a positive quantity the request fails with 400.\n\nPath parameters:\n\
        - salesOrder (required): Sales order ID.\n\n**Requires permission:** `sales_orders.fulfill`"
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                warehouse_id:
                  type: integer
                expected_pickup_at:
                  type: string
                note:
                  type: string
                items:
                  type: array
                  items:
                    type: object
                    properties:
                      sales_order_line_id:
                        type: integer
                      quantity:
                        type: integer
              example:
                warehouse_id: 2
                expected_pickup_at: '2026-07-10 15:00:00'
                note: Customer will collect at the will-call window
                items:
                - sales_order_line_id: 8912
                  quantity: 2
      parameters:
      - name: salesOrder
        in: path
        schema:
          type: integer
        required: true
        description: Sales order ID
        example: '500'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      fulfillment_order_id:
                        type: integer
                example:
                  message: The pickup fulfillment created successfully
                  data:
                    fulfillment_order_id: 3312
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: At least one item with a positive quantity is required
                    to mark for pickup.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      warehouse_id:
                        type: array
                        items:
                          type: string
                example:
                  message: The given data was invalid.
                  errors:
                    warehouse_id:
                    - The warehouse id field is required.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:write
      operationId: post-api-sales-orders-salesorder-mark-for-pickup
  /api/sales-orders/{salesOrder}/reset-fulfillment-status:
    put:
      tags:
      - Sales Orders
      summary: Reset Sales Order Fulfillment Status
      description: 'Recalculates a sales order''s fulfillment status from its actual
        fulfillment data. Only allowed while the order''s current fulfillment status
        is `out_of_sync`; the recomputed status is one of unfulfilled, partially_fulfilled,
        fulfilled, or over_fulfilled based on the quantities actually fulfilled per
        line.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        No request body.


        Path parameters:

        - salesOrder (required): Sales order ID.


        **Requires permission:** `sales_orders.update`'
      requestBody:
        content: {}
      parameters:
      - name: salesOrder
        in: path
        schema:
          type: integer
        required: true
        description: Sales order ID
        example: '500'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      fulfillment_status:
                        type: string
                example:
                  message: Fulfillment status has been recalculated.
                  data:
                    fulfillment_status: fulfilled
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Fulfillment status can only be reset when it is out of
                    sync.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: orders:write
      operationId: put-api-sales-orders-salesorder-reset-fulfillment-status
  /api/sales-orders/{salesOrder}/compare-fulfillments-with-sales-channel:
    get:
      tags:
      - Sales Orders
      summary: Compare Fulfillments with Sales Channel
      description: 'Compares the fulfillments recorded in SKU.io against the fulfillments
        reported by the order''s originating sales channel. Currently only orders
        linked to a Shopify order are compared; orders from other channels return
        an empty success response.


        :::info[Required scope: `orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        No query parameters.


        Response payload (for orders linked to a Shopify order):

        - fulfillmentsToSubmit (array): Fulfillments recorded in SKU.io that have
        not been reported to the sales channel.

        - fulfillmentToCreate (array): Channel fulfillments not yet recorded in SKU.io.

        - differences (array): Field-level differences between matched fulfillments.


        The current Shopify integration reports fulfillments to the channel automatically
        as part of order sync, so all three lists are typically empty.


        Path parameters:

        - salesOrder (required): Sales order ID.'
      parameters:
      - name: salesOrder
        in: path
        schema:
          type: integer
        required: true
        description: Sales order ID
        example: '500'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 Linked Channel Order
                  value:
                    status: success
                    data:
                      fulfillmentsToSubmit: []
                      fulfillmentToCreate: []
                      differences: []
                example-1:
                  summary: 200 No Linked Channel Order
                  value:
                    status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:read
      operationId: get-api-sales-orders-salesorder-compare-fulfillments-with-sales-channel
  /api/sales-orders/{salesOrder}/dispatch-fulfillments:
    post:
      tags:
      - Sales Orders
      summary: Dispatch Fulfillments for Sales Order
      description: 'Runs the fulfillment dispatcher for a single sales order: validates
        that the order is dispatchable (approved, fulfillment status in sync, all
        lines mapped to products, a shipping method selected, valid addresses), groups
        the fulfillable allocated lines by warehouse, and submits each warehouse''s
        pending fulfillment order to the shipping provider or fulfillment service
        configured for that warehouse.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Request body fields (all optional; each flag bypasses one pre-dispatch check):

        - overrideOutOfSync (boolean, default false): Dispatch even when the order''s
        fulfillment status is out of sync with the sales channel.

        - overrideSelectShippingMethod (boolean, default false): Dispatch even when
        no shipping method has been selected or mapped for the order.

        - overrideUnmappedLines (boolean, default false): Dispatch even when some
        order lines are not mapped to products (only mapped lines are dispatched).

        - overrideManualDispatch (boolean, default false): Dispatch warehouses that
        are configured for manual dispatch only.

        - overridePartialDispatch (boolean, default false): Allow dispatching when
        only part of the order''s quantity is currently fulfillable.


        Behavior:

        - Dispatch is treated as user-requested, so warehouse auto-dispatch eligibility
        rules are bypassed.

        - Orders with a pickup shipping method are staged for customer pickup instead
        of being submitted to a carrier.

        - Submitting a fulfillment order to a provider does not create a shipment
        record; the provider''s ship confirmation records the shipment later. The
        `data` array therefore contains only fulfillment records created immediately
        during dispatch and is often empty even after a successful dispatch.

        - Failed pre-dispatch checks do not error — the order is skipped and a note
        explaining why is recorded on the order; the response returns an empty `data`
        array.

        - Concurrent dispatch requests for the same order are serialized; if another
        dispatch is already running the request fails with 409.


        Path parameters:

        - salesOrder (required): Sales order ID.


        **Requires permission:** `sales_orders.fulfill`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                overrideOutOfSync:
                  type: boolean
                overrideSelectShippingMethod:
                  type: boolean
                overrideUnmappedLines:
                  type: boolean
                overrideManualDispatch:
                  type: boolean
                overridePartialDispatch:
                  type: boolean
              example:
                overrideOutOfSync: false
                overrideSelectShippingMethod: false
                overrideUnmappedLines: false
                overrideManualDispatch: true
                overridePartialDispatch: false
      parameters:
      - name: salesOrder
        in: path
        schema:
          type: integer
        required: true
        description: Sales order ID
        example: '500'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 Dispatched (no immediate shipment record)
                  value:
                    data: []
                example-1:
                  summary: 200 Dispatched with Fulfillment Created
                  value:
                    data:
                    - id: 9107
                      fulfillment_number: F-9107
                      sales_order_id: 500
                      fulfillment_order_id: 3312
                      fulfillment_type: shipstation
                      fulfillment_status: submitted
                      shipping_method_id: 4
                      requested_shipping_method: null
                      requested_shipping_method_id: 4
                      fulfilled_shipping_method: null
                      fulfilled_shipping_method_id: null
                      fulfilled_date: null
                      tracking_number: null
                      tracking_url: null
                      tracking_link: null
                      warehouse:
                        id: 2
                        name: Main Warehouse
                        type: standard
                        supplier_id: null
                        is_dropship: false
                      warehouse_id: 2
                      fulfilled_by: null
                      fulfilled_quantity: 2
                      fulfillment_lines:
                      - id: 15501
                        sales_order_line_id: 8912
                        sales_order_fulfillment_id: 9107
                        quantity: 2
                        unit_cost: 6.25
                        metadata: null
                      cost: null
                      status: submitted
                      voided_at: null
                      void_reason: null
                      voided_by: null
                      fulfilled_at: null
                      marked_for_pickup_at: null
                      marked_for_pickup_by: null
                      expected_pickup_at: null
                      packing_slip_printed_at: null
                      submitted_to_sales_channel_at: null
                      last_synced_to_provider_at: '2026-07-06T18:22:41.000000Z'
                      last_synced_from_provider_at: null
                      metadata: null
                      fulfillment_sequence: 1
                      is_parent: false
                      parent_id: null
                      created_at: '2026-07-06T18:22:41.000000Z'
                      provider_order_id: SS-448121
                      sales_channel_fulfillment_link: null
        '409':
          description: Conflict
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      sales_order_id:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: object
                              properties:
                                sales_order_id:
                                  type: integer
                                sales_order_number:
                                  type: string
                example:
                  status: failure
                  message: Another fulfillment dispatch is in progress for sales order
                    SO-1042. Please try again in a moment.
                  errors:
                    sales_order_id:
                    - message: Another fulfillment dispatch is in progress for sales
                        order SO-1042. Please try again in a moment.
                      code: FulfillmentDispatchInProgress
                      data:
                        sales_order_id: 500
                        sales_order_number: SO-1042
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: orders:write
      operationId: post-api-sales-orders-salesorder-dispatch-fulfillments
  /api/sales-orders/dispatch-fulfillments:
    post:
      tags:
      - Sales Orders
      summary: Bulk Dispatch Fulfillments for Sales Orders
      description: 'Runs the fulfillment dispatcher for multiple sales orders — each
        order is validated and its pending fulfillment orders are submitted to the
        shipping provider or fulfillment service configured for its warehouse(s).


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Request body fields (provide `ids` or `filters`):

        - ids (array of integers, optional, min 1): Sales order IDs to dispatch. Dispatched
        synchronously; the response reports how many fulfillment orders were dispatched.

        - filters (string, optional): Filter query that resolves to a list of sales
        order IDs (same format used by the sales-orders listing endpoint). When provided,
        dispatching is queued and processed in the background and the response returns
        immediately.

        - overrideData (object, optional): Pre-dispatch check overrides applied to
        every order. Keys: overrideOutOfSync, overrideSelectShippingMethod, overrideUnmappedLines,
        overrideManualDispatch, overridePartialDispatch (all boolean, default false).


        Behavior:

        - Dispatch is treated as user-requested, so warehouse auto-dispatch eligibility
        rules are bypassed.

        - The success message counts fulfillment orders dispatched to providers. Shipment
        records are created later when each provider confirms shipment.

        - Orders skipped because another dispatch already holds their lock are listed
        in the message; if every requested order is skipped this way the request fails
        with 409 so it can be retried.


        **Requires permission:** `sales_orders.fulfill`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
                overrideData:
                  type: object
                  properties:
                    overrideManualDispatch:
                      type: boolean
              example:
                ids:
                - 500
                - 501
                - 502
                overrideData:
                  overrideManualDispatch: true
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 Dispatched
                  value:
                    status: success
                    message: 3 Fulfillment Orders dispatched.
                example-1:
                  summary: 200 Nothing to Dispatch
                  value:
                    status: success
                    message: No fulfillment orders were dispatched — the selected
                      order(s) had nothing new to fulfill.
                example-2:
                  summary: 200 Queued in Background (filters)
                  value:
                    status: success
                    message: Fulfillment dispatching processing in the background.
        '409':
          description: Conflict
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      ids:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: object
                              properties:
                                skipped:
                                  type: array
                                  items:
                                    type: object
                                    properties:
                                      sales_order_id:
                                        type: integer
                                      sales_order_number:
                                        type: string
                example:
                  status: failure
                  message: Another fulfillment dispatch is already in progress for
                    the selected sales order(s). Please try again in a moment.
                  errors:
                    ids:
                    - message: Another fulfillment dispatch is already in progress
                        for the selected sales order(s). Please try again in a moment.
                      code: FulfillmentDispatchInProgress
                      data:
                        skipped:
                        - sales_order_id: 500
                          sales_order_number: SO-1042
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: orders:write
      operationId: post-api-sales-orders-dispatch-fulfillments
  /api/sales-orders/{salesOrder}/dropship-preview:
    get:
      tags:
      - Sales Orders
      summary: Preview Dropship Request
      description: 'Previews the supplier cost for each of the order''s product lines
        routed to a dropship (supplier) warehouse, before creating the dropship purchase
        order.


        :::info[Required scope: `orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Query parameters:

        - warehouse_id (integer, required): The dropship warehouse to preview against.
        Only lines routed to this warehouse are returned.


        Response fields (per line):

        - sales_order_line_id (integer): The sales order line.

        - product_id (integer): The product on the line.

        - supplier_cost (number): The product''s unit cost for the warehouse''s supplier,
        rounded to 4 decimal places.


        Path parameters:

        - salesOrder (required): Sales order ID.'
      parameters:
      - name: warehouse_id
        in: query
        schema:
          type: integer
        description: Dropship (supplier) warehouse ID to preview supplier costs for
          (required)
        example: '9'
      - name: salesOrder
        in: path
        schema:
          type: integer
        required: true
        description: Sales order ID
        example: '500'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        sales_order_line_id:
                          type: integer
                        product_id:
                          type: integer
                        supplier_cost:
                          type: number
                example:
                  data:
                  - sales_order_line_id: 8912
                    product_id: 341
                    supplier_cost: 12.5
                  - sales_order_line_id: 8913
                    product_id: 355
                    supplier_cost: 4.75
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      warehouse_id:
                        type: array
                        items:
                          type: string
                example:
                  message: The given data was invalid.
                  errors:
                    warehouse_id:
                    - The warehouse id field is required.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:read
      operationId: get-api-sales-orders-salesorder-dropship-preview
  /api/sales-orders/{salesOrder}/dropship-request:
    post:
      tags:
      - Sales Orders
      summary: Create Dropship Request
      description: "Creates a dropship request for the sales order: a purchase order\
        \ is created and submitted to the supplier behind the given dropship warehouse\
        \ for the selected lines, priced at supplier cost, with the sales order's\
        \ shipping address as the delivery destination.\n\n:::info[Required scope:\
        \ `orders:write`]\nGrant this scope to your token under [Settings → Developer\
        \ → Personal Access Tokens](https://app.sku.io/settings/api).\n:::\n\nAuthentication:\
        \ Requires Bearer token.\n\nRequest body fields:\n- warehouse_id (integer,\
        \ required): The supplier (dropship) warehouse to order from. Must have the\
        \ dropship setting enabled, otherwise the request fails with 400.\n- sales_order_lines\
        \ (array, required): The order lines to dropship.\n  - sales_order_lines.*.id\
        \ (integer, required): Sales order line ID.\n  - sales_order_lines.*.quantity\
        \ (integer, optional): Quantity to dropship. Defaults to the full line quantity;\
        \ values above the line quantity are capped.\n- requested_shipping_method_id\
        \ (integer, optional): Mapped shipping method to request from the supplier.\n\
        - requested_shipping_method (string, optional): Free-text requested shipping\
        \ method.\n- supplier_notes (string, optional): Notes shown to the supplier\
        \ on the purchase order.\n- internal_notes (string, optional): Internal notes\
        \ on the purchase order.\n\nBehavior:\n- The purchase order is linked to the\
        \ sales order and submitted immediately.\n- The order's pending fulfillment\
        \ work for that warehouse is marked as ordered, and the order's fulfillment\
        \ status is recalculated.\n- The response returns the created purchase order.\n\
        \nPath parameters:\n- salesOrder (required): Sales order ID.\n\n**Requires\
        \ permission:** `sales_orders.fulfill`"
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                warehouse_id:
                  type: integer
                requested_shipping_method_id:
                  type: integer
                supplier_notes:
                  type: string
                internal_notes:
                  type: string
                sales_order_lines:
                  type: array
                  items:
                    type: object
                    properties:
                      id:
                        type: integer
                      quantity:
                        type: integer
              example:
                warehouse_id: 9
                requested_shipping_method_id: 4
                supplier_notes: Ship directly to the customer in plain packaging
                internal_notes: Customer requested expedited handling
                sales_order_lines:
                - id: 8912
                  quantity: 2
                - id: 8913
      parameters:
      - name: salesOrder
        in: path
        schema:
          type: integer
        required: true
        description: Sales order ID
        example: '500'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      po_number:
                        type: string
                      purchase_order_date:
                        type: string
                      other_date:
                        type: string
                        nullable: true
                      payment_term_id:
                        type: integer
                      payment_term:
                        type: string
                      incoterm_id:
                        type: string
                        nullable: true
                      incoterm:
                        type: string
                        nullable: true
                      submission_format:
                        type: string
                      currency_id:
                        type: integer
                      currency:
                        type: string
                      currency_rate:
                        type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      created_by:
                        type: string
                      last_updated_by:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                      is_dropship:
                        type: boolean
                      tracking_number:
                        type: string
                        nullable: true
                      supplier_id:
                        type: integer
                      supplier_name:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      supplier_email:
                        type: string
                      destination_warehouse_id:
                        type: string
                        nullable: true
                      destination_warehouse_type:
                        type: string
                        nullable: true
                      order_status:
                        type: string
                      submission_status:
                        type: string
                      submission_blocked_no_email:
                        type: boolean
                      receipt_status:
                        type: string
                      shipment_status:
                        type: string
                      invoice_status:
                        type: string
                      additional_cost:
                        type: integer
                      discount:
                        type: integer
                      product_total:
                        type: number
                      total:
                        type: number
                      subtotal:
                        type: number
                      tax_cost:
                        type: integer
                      is_tax_included:
                        type: boolean
                      total_quantity:
                        type: integer
                      supplier_notes:
                        type: string
                      estimated_delivery_date:
                        type: string
                        nullable: true
                      fully_received_at:
                        type: string
                        nullable: true
                      tags:
                        type: array
                      store_id:
                        type: integer
                      items:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            product_id:
                              type: integer
                            description:
                              type: string
                            quantity:
                              type: integer
                            amount:
                              type: number
                            received_quantity:
                              type: integer
                      summary_info:
                        type: object
                        properties:
                          total_lines:
                            type: integer
                          total_product_lines:
                            type: integer
                          total_units:
                            type: integer
                          total_quantity_pending_receipt:
                            type: integer
                      financial_lines:
                        type: array
                      bills:
                        type: array
                      invoices:
                        type: array
                      amazon_pending_inbound:
                        type: string
                        nullable: true
                      has_active_allocations:
                        type: boolean
                      walmart_wfs_inbound_shipment:
                        type: string
                        nullable: true
                example:
                  data:
                    id: 2101
                    po_number: PO-02101
                    purchase_order_date: '2026-07-01'
                    other_date: null
                    payment_term_id: 1
                    payment_term: Net 30
                    incoterm_id: null
                    incoterm: null
                    submission_format: email
                    currency_id: 1
                    currency: USD
                    currency_rate: 1
                    created_at: '2026-07-06T18:40:12.000000Z'
                    updated_at: '2026-07-06T18:40:12.000000Z'
                    created_by: Kalvin Mizzi
                    last_updated_by: Kalvin Mizzi
                    archived_at: null
                    is_dropship: true
                    tracking_number: null
                    supplier_id: 5
                    supplier_name:
                      id: 5
                      name: Acme Supplies
                    supplier_email: orders@acme.com
                    destination_warehouse_id: null
                    destination_warehouse_type: null
                    order_status: open
                    submission_status: sent
                    submission_blocked_no_email: false
                    receipt_status: unreceived
                    shipment_status: pending
                    invoice_status: uninvoiced
                    additional_cost: 0
                    discount: 0
                    product_total: 29.75
                    total: 29.75
                    subtotal: 29.75
                    tax_cost: 0
                    is_tax_included: false
                    total_quantity: 3
                    supplier_notes: Ship directly to the customer in plain packaging
                    estimated_delivery_date: null
                    fully_received_at: null
                    tags: []
                    store_id: 1
                    items:
                    - id: 5201
                      product_id: 341
                      description: Blue Widget
                      quantity: 2
                      amount: 12.5
                      received_quantity: 0
                    - id: 5202
                      product_id: 355
                      description: Red Widget
                      quantity: 1
                      amount: 4.75
                      received_quantity: 0
                    summary_info:
                      total_lines: 2
                      total_product_lines: 2
                      total_units: 3
                      total_quantity_pending_receipt: 3
                    financial_lines: []
                    bills: []
                    invoices: []
                    amazon_pending_inbound: null
                    has_active_allocations: false
                    walmart_wfs_inbound_shipment: null
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Warehouse 'Acme Supplies' is not configured as a dropship
                    warehouse. Please enable the dropship setting on this warehouse
                    before creating dropship orders.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      warehouse_id:
                        type: array
                        items:
                          type: string
                example:
                  message: The given data was invalid.
                  errors:
                    warehouse_id:
                    - The warehouse id field is required.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:write
      operationId: post-api-sales-orders-salesorder-dropship-request
  /api/sales-orders/bulk-allocate/preview:
    post:
      tags:
      - Sales Orders
      summary: Preview Bulk Allocate Sales Orders
      description: "Previews a bulk allocate action without changing any data. For\
        \ each targeted sales order the response reports per-line eligibility, the\
        \ quantities involved, and the allocation impact, plus aggregate totals —\
        \ use it to confirm what a bulk allocate will do before running it.\n\n:::info[Required\
        \ scope: `orders:write`]\nGrant this scope to your token under [Settings →\
        \ Developer → Personal Access Tokens](https://app.sku.io/settings/api).\n\
        :::\n\nAuthentication: Requires Bearer token.\n\nRequest body fields (one\
        \ of `ids` or `filters` is required):\n- ids (array of integers, required\
        \ without `filters`): Sales order IDs to target. Each ID must exist.\n- filters\
        \ (object or string, required without `ids`): Resolves to the matching sales\
        \ order IDs — the same targeting the sales-orders list uses. Two shapes are\
        \ accepted:\n  - Grouped filters: `{ \"filter_groups\": \"<base64-encoded\
        \ JSON tree>\" }`. The decoded tree looks like `{\"conjunction\":\"and\",\"\
        children\":[{\"type\":\"condition\",\"condition\":{\"column\":\"order_status\"\
        ,\"operator\":\"is\",\"value\":\"open\"}}]}`.\n  - Legacy filter set (JSON\
        \ string) for older clients.\n\nResponse fields:\n- orders[] — one entry per\
        \ targeted order:\n  - sales_order_id (integer), sales_order_number (string)\n\
        \  - status (string|null): Raw status value of the order, when available.\n\
        \  - eligibility (string): `eligible`, `partially_eligible`, or `ineligible`.\n\
        \  - reason (string|null): Populated only when the order is ineligible, with\
        \ the shared line-level reason or an order-level summary.\n  - lines[] — one\
        \ entry per warehoused product line:\n    - sales_order_line_id (integer),\
        \ product_sku (string|null), product_name (string|null), warehouse_name (string|null)\n\
        \    - eligible (boolean), reason (string|null)\n    - processable_quantity\
        \ (integer): Ordered quantity net of cancellations.\n    - fulfilled_quantity\
        \ (integer): Quantity already committed to non-cancelled fulfillments.\n \
        \   - currently_allocated (integer): Units already covered by active allocations.\n\
        \    - impact_quantity (integer): Units this action would change on the line.\n\
        - totals — orders_total, orders_eligible, orders_partially_eligible, orders_ineligible,\
        \ lines_total, lines_eligible, lines_impact_quantity (all integers).\n\nBehavior\
        \ notes:\n- Only lines stocked in warehouses that track inventory allocations\
        \ are considered; lines in warehouses that do not are reported with reason\
        \ \"Warehouse does not require inventory allocation\".\n- Lines already fully\
        \ allocated or fulfilled are ineligible with reason \"Already fully allocated\
        \ or fulfilled\".\n- impact_quantity is the remaining unallocated demand that\
        \ a bulk allocate would newly allocate.\n\n**Requires permission:** `sales_orders.update`"
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 7116
                - 7117
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      orders:
                        type: array
                        items:
                          type: object
                          properties:
                            sales_order_id:
                              type: integer
                            sales_order_number:
                              type: string
                            status:
                              type: string
                              nullable: true
                            eligibility:
                              type: string
                            reason:
                              type: string
                              nullable: true
                            lines:
                              type: array
                              items:
                                type: object
                                properties:
                                  sales_order_line_id:
                                    type: integer
                                  product_sku:
                                    type: string
                                  product_name:
                                    type: string
                                  warehouse_name:
                                    type: string
                                  eligible:
                                    type: boolean
                                  reason:
                                    type: string
                                    nullable: true
                                  processable_quantity:
                                    type: integer
                                  fulfilled_quantity:
                                    type: integer
                                  currently_allocated:
                                    type: integer
                                  impact_quantity:
                                    type: integer
                      totals:
                        type: object
                        properties:
                          orders_total:
                            type: integer
                          orders_eligible:
                            type: integer
                          orders_partially_eligible:
                            type: integer
                          orders_ineligible:
                            type: integer
                          lines_total:
                            type: integer
                          lines_eligible:
                            type: integer
                          lines_impact_quantity:
                            type: integer
                example:
                  data:
                    orders:
                    - sales_order_id: 7116
                      sales_order_number: SO-7116
                      status: null
                      eligibility: eligible
                      reason: null
                      lines:
                      - sales_order_line_id: 90211
                        product_sku: WID-BLU-M
                        product_name: Blue Widget (Medium)
                        warehouse_name: Main Warehouse
                        eligible: true
                        reason: null
                        processable_quantity: 5
                        fulfilled_quantity: 0
                        currently_allocated: 2
                        impact_quantity: 3
                    - sales_order_id: 7117
                      sales_order_number: SO-7117
                      status: null
                      eligibility: ineligible
                      reason: Already fully allocated or fulfilled
                      lines:
                      - sales_order_line_id: 90315
                        product_sku: WID-RED-S
                        product_name: Red Widget (Small)
                        warehouse_name: Main Warehouse
                        eligible: false
                        reason: Already fully allocated or fulfilled
                        processable_quantity: 2
                        fulfilled_quantity: 0
                        currently_allocated: 2
                        impact_quantity: 0
                    totals:
                      orders_total: 2
                      orders_eligible: 1
                      orders_partially_eligible: 0
                      orders_ineligible: 1
                      lines_total: 2
                      lines_eligible: 1
                      lines_impact_quantity: 3
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      ids:
                        type: array
                        items:
                          type: string
                      filters:
                        type: array
                        items:
                          type: string
                example:
                  message: The ids field is required when filters is not present.
                  errors:
                    ids:
                    - The ids field is required when filters is not present.
                    filters:
                    - The filters field is required when ids is not present.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: orders:write
      operationId: post-api-sales-orders-bulk-allocate-preview
  /api/sales-orders/bulk-allocate:
    post:
      tags:
      - Sales Orders
      summary: Bulk Allocate Sales Orders
      description: "Starts an asynchronous bulk allocate operation for the targeted\
        \ sales orders and returns immediately with a `tracked_job_log_id` to poll\
        \ for progress and results.\n\n:::info[Required scope: `orders:write`]\nGrant\
        \ this scope to your token under [Settings → Developer → Personal Access Tokens](https://app.sku.io/settings/api).\n\
        :::\n\nAuthentication: Requires Bearer token.\n\nRequest body fields (one\
        \ of `ids` or `filters` is required):\n- ids (array of integers, required\
        \ without `filters`): Sales order IDs to target. Each ID must exist.\n- filters\
        \ (object or string, required without `ids`): Resolves to the matching sales\
        \ order IDs — the same targeting the sales-orders list uses. Two shapes are\
        \ accepted:\n  - Grouped filters: `{ \"filter_groups\": \"<base64-encoded\
        \ JSON tree>\" }`. The decoded tree looks like `{\"conjunction\":\"and\",\"\
        children\":[{\"type\":\"condition\",\"condition\":{\"column\":\"order_status\"\
        ,\"operator\":\"is\",\"value\":\"open\"}}]}`.\n  - Legacy filter set (JSON\
        \ string) for older clients.\n\nBehavior:\n- For each order, inventory is\
        \ allocated to every eligible line's remaining unallocated demand. Lines whose\
        \ warehouse does not track allocations, and lines already fully allocated\
        \ or fulfilled, are skipped.\n- The operation runs in the background. Poll\
        \ the tracked job log endpoints with the returned ID for progress and the\
        \ completion summary (orders processed / fully allocated / partially allocated\
        \ / skipped; lines allocated / already allocated / failed) plus any per-order\
        \ errors.\n- Call the preview endpoint (`POST /api/sales-orders/bulk-allocate/preview`)\
        \ first to see exactly which orders and lines will be affected.\n\n**Requires\
        \ permission:** `sales_orders.update`"
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 7116
                - 7117
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 84291
                  message: Bulk allocate started. Track progress using the returned
                    ID.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      ids:
                        type: array
                        items:
                          type: string
                      filters:
                        type: array
                        items:
                          type: string
                example:
                  message: The ids field is required when filters is not present.
                  errors:
                    ids:
                    - The ids field is required when filters is not present.
                    filters:
                    - The filters field is required when ids is not present.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: orders:write
      operationId: post-api-sales-orders-bulk-allocate
  /api/sales-orders/bulk-unallocate/preview:
    post:
      tags:
      - Sales Orders
      summary: Preview Bulk Unallocate Sales Orders
      description: "Previews a bulk unallocate action without changing any data. For\
        \ each targeted sales order the response reports per-line eligibility and\
        \ how many allocated units would be released, plus aggregate totals — use\
        \ it to confirm what a bulk unallocate will do before running it.\n\n:::info[Required\
        \ scope: `orders:write`]\nGrant this scope to your token under [Settings →\
        \ Developer → Personal Access Tokens](https://app.sku.io/settings/api).\n\
        :::\n\nAuthentication: Requires Bearer token.\n\nRequest body fields (one\
        \ of `ids` or `filters` is required):\n- ids (array of integers, required\
        \ without `filters`): Sales order IDs to target. Each ID must exist.\n- filters\
        \ (object or string, required without `ids`): Resolves to the matching sales\
        \ order IDs — the same targeting the sales-orders list uses. Two shapes are\
        \ accepted:\n  - Grouped filters: `{ \"filter_groups\": \"<base64-encoded\
        \ JSON tree>\" }`. The decoded tree looks like `{\"conjunction\":\"and\",\"\
        children\":[{\"type\":\"condition\",\"condition\":{\"column\":\"order_status\"\
        ,\"operator\":\"is\",\"value\":\"open\"}}]}`.\n  - Legacy filter set (JSON\
        \ string) for older clients.\n\nResponse fields:\n- orders[] — one entry per\
        \ targeted order:\n  - sales_order_id (integer), sales_order_number (string)\n\
        \  - status (string|null): Raw status value of the order, when available.\n\
        \  - eligibility (string): `eligible`, `partially_eligible`, or `ineligible`.\n\
        \  - reason (string|null): Populated only when the order is ineligible, with\
        \ the shared line-level reason or an order-level summary.\n  - lines[] — one\
        \ entry per warehoused product line:\n    - sales_order_line_id (integer),\
        \ product_sku (string|null), product_name (string|null), warehouse_name (string|null)\n\
        \    - eligible (boolean), reason (string|null)\n    - processable_quantity\
        \ (integer): Ordered quantity net of cancellations.\n    - fulfilled_quantity\
        \ (integer): Quantity already committed to non-cancelled fulfillments.\n \
        \   - currently_allocated (integer): Units already covered by active allocations.\n\
        \    - impact_quantity (integer): Units this action would change on the line.\n\
        - totals — orders_total, orders_eligible, orders_partially_eligible, orders_ineligible,\
        \ lines_total, lines_eligible, lines_impact_quantity (all integers).\n\nBehavior\
        \ notes:\n- Only lines stocked in warehouses that track inventory allocations\
        \ are considered.\n- Lines with any non-cancelled fulfillment activity are\
        \ ineligible with reason \"Line has fulfillment activity — cannot unallocate\"\
        .\n- Lines without active allocations are ineligible with reason \"No active\
        \ allocations to reverse\".\n- impact_quantity is the number of actively allocated\
        \ units that would be released. Only active allocations are reversed — allocations\
        \ already fulfilled or cancelled are untouched.\n\n**Requires permission:**\
        \ `sales_orders.update`"
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 7116
                - 7118
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      orders:
                        type: array
                        items:
                          type: object
                          properties:
                            sales_order_id:
                              type: integer
                            sales_order_number:
                              type: string
                            status:
                              type: string
                              nullable: true
                            eligibility:
                              type: string
                            reason:
                              type: string
                              nullable: true
                            lines:
                              type: array
                              items:
                                type: object
                                properties:
                                  sales_order_line_id:
                                    type: integer
                                  product_sku:
                                    type: string
                                  product_name:
                                    type: string
                                  warehouse_name:
                                    type: string
                                  eligible:
                                    type: boolean
                                  reason:
                                    type: string
                                    nullable: true
                                  processable_quantity:
                                    type: integer
                                  fulfilled_quantity:
                                    type: integer
                                  currently_allocated:
                                    type: integer
                                  impact_quantity:
                                    type: integer
                      totals:
                        type: object
                        properties:
                          orders_total:
                            type: integer
                          orders_eligible:
                            type: integer
                          orders_partially_eligible:
                            type: integer
                          orders_ineligible:
                            type: integer
                          lines_total:
                            type: integer
                          lines_eligible:
                            type: integer
                          lines_impact_quantity:
                            type: integer
                example:
                  data:
                    orders:
                    - sales_order_id: 7116
                      sales_order_number: SO-7116
                      status: null
                      eligibility: partially_eligible
                      reason: null
                      lines:
                      - sales_order_line_id: 90211
                        product_sku: WID-BLU-M
                        product_name: Blue Widget (Medium)
                        warehouse_name: Main Warehouse
                        eligible: true
                        reason: null
                        processable_quantity: 5
                        fulfilled_quantity: 0
                        currently_allocated: 5
                        impact_quantity: 5
                      - sales_order_line_id: 90212
                        product_sku: WID-GRN-L
                        product_name: Green Widget (Large)
                        warehouse_name: Main Warehouse
                        eligible: false
                        reason: Line has fulfillment activity — cannot unallocate
                        processable_quantity: 3
                        fulfilled_quantity: 3
                        currently_allocated: 0
                        impact_quantity: 0
                    - sales_order_id: 7118
                      sales_order_number: SO-7118
                      status: null
                      eligibility: ineligible
                      reason: No active allocations to reverse
                      lines:
                      - sales_order_line_id: 90410
                        product_sku: WID-RED-S
                        product_name: Red Widget (Small)
                        warehouse_name: Main Warehouse
                        eligible: false
                        reason: No active allocations to reverse
                        processable_quantity: 2
                        fulfilled_quantity: 0
                        currently_allocated: 0
                        impact_quantity: 0
                    totals:
                      orders_total: 2
                      orders_eligible: 0
                      orders_partially_eligible: 1
                      orders_ineligible: 1
                      lines_total: 3
                      lines_eligible: 1
                      lines_impact_quantity: 5
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      ids:
                        type: array
                        items:
                          type: string
                      filters:
                        type: array
                        items:
                          type: string
                example:
                  message: The ids field is required when filters is not present.
                  errors:
                    ids:
                    - The ids field is required when filters is not present.
                    filters:
                    - The filters field is required when ids is not present.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: orders:write
      operationId: post-api-sales-orders-bulk-unallocate-preview
  /api/sales-orders/bulk-unallocate:
    post:
      tags:
      - Sales Orders
      summary: Bulk Unallocate Sales Orders
      description: "Starts an asynchronous bulk unallocate operation for the targeted\
        \ sales orders and returns immediately with a `tracked_job_log_id` to poll\
        \ for progress and results.\n\n:::info[Required scope: `orders:write`]\nGrant\
        \ this scope to your token under [Settings → Developer → Personal Access Tokens](https://app.sku.io/settings/api).\n\
        :::\n\nAuthentication: Requires Bearer token.\n\nRequest body fields (one\
        \ of `ids` or `filters` is required):\n- ids (array of integers, required\
        \ without `filters`): Sales order IDs to target. Each ID must exist.\n- filters\
        \ (object or string, required without `ids`): Resolves to the matching sales\
        \ order IDs — the same targeting the sales-orders list uses. Two shapes are\
        \ accepted:\n  - Grouped filters: `{ \"filter_groups\": \"<base64-encoded\
        \ JSON tree>\" }`. The decoded tree looks like `{\"conjunction\":\"and\",\"\
        children\":[{\"type\":\"condition\",\"condition\":{\"column\":\"order_status\"\
        ,\"operator\":\"is\",\"value\":\"open\"}}]}`.\n  - Legacy filter set (JSON\
        \ string) for older clients.\n\nBehavior:\n- For each order, active inventory\
        \ allocations on eligible lines are released. Lines with any non-cancelled\
        \ fulfillment activity are skipped, as are lines with no active allocations.\
        \ Allocations that are already fulfilled or cancelled are never touched.\n\
        - The operation runs in the background. Poll the tracked job log endpoints\
        \ with the returned ID for progress and the completion summary plus any per-order\
        \ errors.\n- Call the preview endpoint (`POST /api/sales-orders/bulk-unallocate/preview`)\
        \ first to see exactly which orders and lines will be affected.\n\n**Requires\
        \ permission:** `sales_orders.update`"
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 7116
                - 7118
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 84292
                  message: Bulk unallocate started. Track progress using the returned
                    ID.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      ids:
                        type: array
                        items:
                          type: string
                      filters:
                        type: array
                        items:
                          type: string
                example:
                  message: The ids field is required when filters is not present.
                  errors:
                    ids:
                    - The ids field is required when filters is not present.
                    filters:
                    - The filters field is required when ids is not present.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: orders:write
      operationId: post-api-sales-orders-bulk-unallocate
  /api/sales-orders/{salesOrder}/mark-as-printed:
    put:
      tags:
      - Sales Orders
      summary: Mark Sales Order as Printed
      description: 'Marks a sales order''s packing slip as printed by setting the
        order''s `packing_slip_printed_at` timestamp to the current time. Orders already
        marked as printed are simply re-stamped.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        No request body.


        Path parameters:

        - salesOrder (required): Sales order ID.


        **Requires permission:** `sales_orders.print`'
      requestBody:
        content: {}
      parameters:
      - name: salesOrder
        in: path
        schema:
          type: integer
        required: true
        description: Sales order ID
        example: '500'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: The selected sales order fulfillment marked as printed
                    successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: orders:write
      operationId: put-api-sales-orders-salesorder-mark-as-printed
  /api/sales-orders/bulk-print-packing-slips:
    post:
      tags:
      - Sales Orders
      summary: Bulk Print Packing Slips
      description: 'Generates packing slips for the targeted sales orders as a single
        merged PDF. The generation runs as an asynchronous background operation; the
        response returns a `tracked_job_log_id` to poll for progress, and the finished
        job''s results contain the PDF download URL.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Request body fields (one of `ids`, `filters`, or `apply_to_all` is required):

        - ids (array of integers, required without `filters`/`apply_to_all`): Sales
        order IDs to print. Each ID must exist.

        - filters (string, required without `ids`/`apply_to_all`): Legacy JSON-string
        filter payload; resolves to the matching sales order IDs.

        - apply_to_all (boolean, optional): When true, targets every order matching
        the request''s active filters instead of an explicit ID list.

        - engine (string, optional, default `snappy`): PDF renderer — `snappy` (current
        pipeline) or `jasper` (legacy pipeline).


        Behavior:

        - Returns the tracked job log ID immediately; PDF generation runs in the background.

        - If the job finishes before the response is sent (small batches / fast queues),
        the response additionally includes `file` (the PDF download URL), `printed_count`,
        and `failed_count` so the file can be opened right away.

        - Otherwise, poll the tracked job log endpoints with the returned ID; the
        completed job''s results include the download URL and per-order failures.


        **Requires permission:** `sales_orders.update`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
                engine:
                  type: string
              example:
                ids:
                - 7116
                - 7117
                - 7118
                engine: snappy
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 Generation Started
                  value:
                    data:
                      tracked_job_log_id: 84310
                    message: Packing slip generation started. Track progress in the
                      job tray.
                example-1:
                  summary: 200 Completed Immediately (small batch)
                  value:
                    data:
                      tracked_job_log_id: 84311
                      file: https://cdn.sku.io/tenant-acme/reports/packing-slips-2026-07-06-9f3b1c.pdf
                      printed_count: 3
                      failed_count: 0
                    message: Packing slip generation started. Track progress in the
                      job tray.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      filters:
                        type: array
                        items:
                          type: string
                      ids:
                        type: array
                        items:
                          type: string
                example:
                  message: The filters field is required when none of ids / apply
                    to all are present.
                  errors:
                    filters:
                    - The filters field is required when none of ids / apply to all
                      are present.
                    ids:
                    - The ids field is required when none of filters / apply to all
                      are present.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: orders:write
      operationId: post-api-sales-orders-bulk-print-packing-slips
  /api/sales-orders/{salesOrder}/notes:
    post:
      tags:
      - Sales Orders
      summary: Add Sales Order Note
      description: 'Adds a note to a sales order. The authenticated user is recorded
        as the note''s author.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Request body fields:

        - note (string, required): The note text.


        Behavior:

        - The created note is returned with its author (`user`).

        - Notes are created unpinned; use the toggle-pin endpoint to pin one.

        - Adding a note queues the order''s packing slip for regeneration so printed
        slips reflect the latest notes.


        Path parameters:

        - salesOrder (required): Sales order ID.


        **Requires permission:** `sales_orders.update`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                note:
                  type: string
              example:
                note: Customer requested signature on delivery.
      parameters:
      - name: salesOrder
        in: path
        schema:
          type: integer
        required: true
        description: Sales order ID
        example: '500'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      note:
                        type: string
                      link_id:
                        type: integer
                      link_type:
                        type: string
                      user_id:
                        type: integer
                      created_at:
                        type: string
                      id:
                        type: integer
                      user:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          email:
                            type: string
                  message:
                    type: string
                example:
                  data:
                    note: Customer requested signature on delivery.
                    link_id: 500
                    link_type: App\Models\SalesOrder
                    user_id: 7
                    created_at: '2026-07-06T15:04:11.000000Z'
                    id: 3412
                    user:
                      id: 7
                      name: Jane Smith
                      email: jane@example.com
                  message: The note created successfully
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      note:
                        type: array
                        items:
                          type: string
                example:
                  message: The note field is required.
                  errors:
                    note:
                    - The note field is required.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:write
      operationId: post-api-sales-orders-salesorder-notes
    get:
      tags:
      - Sales Orders
      summary: List Sales Order Notes
      description: 'Lists the notes on a sales order, newest first, as a paginated
        set (15 per page).


        :::info[Required scope: `orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Query parameters:

        - page (integer, optional, default 1): Page number.


        Each note includes:

        - id (integer), note (string), is_pinned (boolean), created_at (date-time)

        - link_type / link_id: The sales order the note belongs to.

        - user_id (integer|null) and user (object|null): The note''s author.


        Path parameters:

        - salesOrder (required): Sales order ID.'
      parameters:
      - name: salesOrder
        in: path
        schema:
          type: integer
        required: true
        description: Sales order ID
        example: '500'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        link_type:
                          type: string
                        link_id:
                          type: integer
                        user_id:
                          type: integer
                        note:
                          type: string
                        is_pinned:
                          type: boolean
                        created_at:
                          type: string
                        user:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            email:
                              type: string
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 3412
                    link_type: App\Models\SalesOrder
                    link_id: 500
                    user_id: 7
                    note: Customer requested signature on delivery.
                    is_pinned: false
                    created_at: '2026-07-06T15:04:11.000000Z'
                    user:
                      id: 7
                      name: Jane Smith
                      email: jane@example.com
                  - id: 3398
                    link_type: App\Models\SalesOrder
                    link_id: 500
                    user_id: 3
                    note: Confirmed replacement item with the customer by phone.
                    is_pinned: true
                    created_at: '2026-07-02T09:41:27.000000Z'
                    user:
                      id: 3
                      name: Sam Ortiz
                      email: sam@example.com
                  first_page_url: https://example.sku.io/api/sales-orders/500/notes?page=1
                  from: 1
                  last_page: 1
                  last_page_url: https://example.sku.io/api/sales-orders/500/notes?page=1
                  next_page_url: null
                  path: https://example.sku.io/api/sales-orders/500/notes
                  per_page: 15
                  prev_page_url: null
                  to: 2
                  total: 2
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:read
      operationId: get-api-sales-orders-salesorder-notes
  /api/sales-orders/{salesOrder}/notes/{noteId}:
    delete:
      tags:
      - Sales Orders
      summary: Delete Sales Order Note
      description: 'Deletes a note from a sales order.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Behavior:

        - The delete is idempotent — a 200 is returned even if the note no longer
        exists on the order.

        - Deleting a note queues the order''s packing slip for regeneration so printed
        slips reflect the latest notes.


        Path parameters:

        - salesOrder (required): Sales order ID.

        - noteId (required): Note ID.


        **Requires permission:** `sales_orders.update`'
      parameters:
      - name: salesOrder
        in: path
        schema:
          type: integer
        required: true
        description: Sales order ID
        example: '500'
      - name: noteId
        in: path
        schema:
          type: integer
        required: true
        description: Note ID
        example: '3412'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: The note 3412 deleted successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:write
      operationId: delete-api-sales-orders-salesorder-notes-noteid
  /api/sales-orders/{salesOrder}/notes/{noteId}/toggle-pin:
    put:
      tags:
      - Sales Orders
      summary: Toggle Sales Order Note Pin
      description: 'Toggles the pinned state of a sales order note. Pinned notes surface
        at the top of the order''s notes.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Behavior:

        - Flips `is_pinned` and returns the updated note with its author.

        - The response message is "Note pinned" or "Note unpinned" depending on the
        new state.

        - Returns 404 if the note does not exist on this sales order.


        Path parameters:

        - salesOrder (required): Sales order ID.

        - noteId (required): Note ID.


        **Requires permission:** `sales_orders.update`'
      requestBody:
        content: {}
      parameters:
      - name: salesOrder
        in: path
        schema:
          type: integer
        required: true
        description: Sales order ID
        example: '500'
      - name: noteId
        in: path
        schema:
          type: integer
        required: true
        description: Note ID
        example: '3412'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      link_type:
                        type: string
                      link_id:
                        type: integer
                      user_id:
                        type: integer
                      note:
                        type: string
                      is_pinned:
                        type: boolean
                      created_at:
                        type: string
                      user:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          email:
                            type: string
                  message:
                    type: string
                example:
                  data:
                    id: 3412
                    link_type: App\Models\SalesOrder
                    link_id: 500
                    user_id: 7
                    note: Customer requested signature on delivery.
                    is_pinned: true
                    created_at: '2026-07-06T15:04:11.000000Z'
                    user:
                      id: 7
                      name: Jane Smith
                      email: jane@example.com
                  message: Note pinned
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      App\Models\Note:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: array
                example:
                  message: No query results for model [App\Models\Note] 9999
                  errors:
                    App\Models\Note:
                    - message: No query results for model [App\Models\Note] 9999
                      code: NotFound
                      data: []
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: orders:write
      operationId: put-api-sales-orders-salesorder-notes-noteid-toggle-pin
  /api/sales-orders/{salesOrder}/discounts:
    get:
      tags:
      - Sales Orders
      summary: List Sales Order Discounts
      description: 'Lists every discount applied to a sales order, ordered by `sequence`
        (the order in which discounts are applied). Includes line-level discounts
        — tied to a product line via `sales_order_line_id`, or to a charge line such
        as shipping via `financial_line_id` — and order-level discounts.


        :::info[Required scope: `orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Response fields (per discount):

        - id (integer): Discount ID.

        - sales_order_id (integer): Owning sales order.

        - sales_order_line_id (integer|null): Product line the discount applies to
        (line scope).

        - financial_line_id (integer|null): Charge line (e.g. shipping) the discount
        applies to (line scope).

        - scope (string): `line` or `order`.

        - type (string): `percentage` or `fixed_amount`.

        - rate (number|null): Percentage rate (0-100) for percentage discounts; null
        for fixed amounts.

        - amount (number): Discount total in the order currency. For percentage discounts
        this is the computed amount.

        - name (string): Display label.

        - source_type (string): Where the discount came from — `manual` for user-entered
        discounts, or a sales-channel identifier for imported ones.

        - source_id (integer|null), source_reference (string|null): External identifiers,
        e.g. a coupon code.

        - channel_discount_type (string|null), allocation_method (string|null), target_type
        (string|null): Raw sales-channel discount metadata, set only on imported discounts.

        - apply_before_tax (boolean): Whether the discount is applied before tax is
        calculated.

        - sequence (integer): Application order — lower values apply first.


        Path parameters:

        - salesOrder (required): Sales order ID.'
      parameters:
      - name: salesOrder
        in: path
        schema:
          type: integer
        required: true
        description: Sales order ID
        example: '500'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        sales_order_id:
                          type: integer
                        sales_order_line_id:
                          type: integer
                        financial_line_id:
                          type: string
                          nullable: true
                        scope:
                          type: string
                        type:
                          type: string
                        rate:
                          type: integer
                        amount:
                          type: number
                        name:
                          type: string
                        source_type:
                          type: string
                        source_id:
                          type: string
                          nullable: true
                        source_reference:
                          type: string
                          nullable: true
                        channel_discount_type:
                          type: string
                          nullable: true
                        allocation_method:
                          type: string
                          nullable: true
                        target_type:
                          type: string
                          nullable: true
                        apply_before_tax:
                          type: boolean
                        sequence:
                          type: integer
                        created_at:
                          type: string
                        updated_at:
                          type: string
                example:
                  data:
                  - id: 12
                    sales_order_id: 500
                    sales_order_line_id: 8801
                    financial_line_id: null
                    scope: line
                    type: percentage
                    rate: 10
                    amount: 25.5
                    name: Loyalty discount
                    source_type: manual
                    source_id: null
                    source_reference: null
                    channel_discount_type: null
                    allocation_method: null
                    target_type: null
                    apply_before_tax: true
                    sequence: 0
                    created_at: '2026-07-01T14:22:05.000000Z'
                    updated_at: '2026-07-06T09:10:41.000000Z'
                  - id: 13
                    sales_order_id: 500
                    sales_order_line_id: null
                    financial_line_id: null
                    scope: order
                    type: fixed_amount
                    rate: null
                    amount: 20
                    name: SUMMER20
                    source_type: shopify
                    source_id: 918273
                    source_reference: SUMMER20
                    channel_discount_type: fixed_amount
                    allocation_method: across
                    target_type: line_item
                    apply_before_tax: true
                    sequence: 1
                    created_at: '2026-06-30T08:03:19.000000Z'
                    updated_at: '2026-06-30T08:03:19.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:read
      operationId: get-api-sales-orders-salesorder-discounts
    post:
      tags:
      - Sales Orders
      summary: Create Sales Order Discount
      description: 'Adds a discount to a sales order and recalculates the order''s
        discount totals.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Request body fields:

        - scope (string, required): `line` (applies to one product line or charge
        line) or `order` (applies to the whole order).

        - type (string, required): `percentage` or `fixed_amount`.

        - rate (number, required when type is `percentage`): Percentage rate, 0-100.

        - amount (number, required when type is `fixed_amount`): Discount amount in
        the order currency, minimum 0. Defaults to 0 when omitted.

        - name (string, required, max 255): Display label.

        - sales_order_line_id (integer, required when scope is `line`): Existing product
        line on the order the discount applies to.

        - financial_line_id (integer, optional): Existing charge line (e.g. shipping)
        the discount applies to instead of a product line.

        - source_type (string, optional, max 50): Origin of the discount. Defaults
        to `manual`.

        - source_reference (string, optional, max 255): External reference such as
        a coupon code.

        - apply_before_tax (boolean, optional, default true): Whether the discount
        applies before tax is calculated.

        - sequence (integer, optional, min 0, default 0): Application order — lower
        values apply first.


        Behavior:

        - Creating a discount immediately recalculates the order: per-line discount
        totals, proportional allocation of order-level discounts across product lines
        (any rounding remainder goes to the largest line), and the order''s denormalized
        discount totals.

        - For percentage discounts the effective `amount` is computed during this
        recalculation and returned in the response.

        - Order-level percentage discounts are based on the order subtotal after line
        discounts; tax is included in the base when the order is configured to discount
        the grand total.


        The response is the created discount object (no envelope), returned with status
        201.


        Path parameters:

        - salesOrder (required): Sales order ID.


        **Requires permission:** `sales_orders.update`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                scope:
                  type: string
                type:
                  type: string
                rate:
                  type: integer
                name:
                  type: string
                sales_order_line_id:
                  type: integer
                apply_before_tax:
                  type: boolean
                sequence:
                  type: integer
              example:
                scope: line
                type: percentage
                rate: 10
                name: Loyalty discount
                sales_order_line_id: 8801
                apply_before_tax: true
                sequence: 0
      parameters:
      - name: salesOrder
        in: path
        schema:
          type: integer
        required: true
        description: Sales order ID
        example: '500'
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: integer
                  sales_order_id:
                    type: integer
                  sales_order_line_id:
                    type: integer
                  financial_line_id:
                    type: string
                    nullable: true
                  scope:
                    type: string
                  type:
                    type: string
                  rate:
                    type: integer
                  amount:
                    type: number
                  name:
                    type: string
                  source_type:
                    type: string
                  source_id:
                    type: string
                    nullable: true
                  source_reference:
                    type: string
                    nullable: true
                  channel_discount_type:
                    type: string
                    nullable: true
                  allocation_method:
                    type: string
                    nullable: true
                  target_type:
                    type: string
                    nullable: true
                  apply_before_tax:
                    type: boolean
                  sequence:
                    type: integer
                  created_at:
                    type: string
                  updated_at:
                    type: string
                example:
                  id: 12
                  sales_order_id: 500
                  sales_order_line_id: 8801
                  financial_line_id: null
                  scope: line
                  type: percentage
                  rate: 10
                  amount: 25.5
                  name: Loyalty discount
                  source_type: manual
                  source_id: null
                  source_reference: null
                  channel_discount_type: null
                  allocation_method: null
                  target_type: null
                  apply_before_tax: true
                  sequence: 0
                  created_at: '2026-07-01T14:22:05.000000Z'
                  updated_at: '2026-07-06T09:10:41.000000Z'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      rate:
                        type: array
                        items:
                          type: string
                      sales_order_line_id:
                        type: array
                        items:
                          type: string
                example:
                  message: The rate field is required when type is percentage.
                  errors:
                    rate:
                    - The rate field is required when type is percentage.
                    sales_order_line_id:
                    - The sales order line id field is required when scope is line.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:write
      operationId: post-api-sales-orders-salesorder-discounts
  /api/sales-orders/{salesOrder}/discounts/{discount}:
    get:
      tags:
      - Sales Orders
      summary: Get Sales Order Discount
      description: 'Returns a single discount on a sales order. The response body
        is the discount object itself — it is not wrapped in a `data` envelope.


        :::info[Required scope: `orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Path parameters:

        - salesOrder (required): Sales order ID.

        - discount (required): Discount ID.


        Returns 404 when the sales order or discount does not exist.'
      parameters:
      - name: salesOrder
        in: path
        schema:
          type: integer
        required: true
        description: Sales order ID
        example: '500'
      - name: discount
        in: path
        schema:
          type: integer
        required: true
        description: Discount ID
        example: '12'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: integer
                  sales_order_id:
                    type: integer
                  sales_order_line_id:
                    type: integer
                  financial_line_id:
                    type: string
                    nullable: true
                  scope:
                    type: string
                  type:
                    type: string
                  rate:
                    type: integer
                  amount:
                    type: number
                  name:
                    type: string
                  source_type:
                    type: string
                  source_id:
                    type: string
                    nullable: true
                  source_reference:
                    type: string
                    nullable: true
                  channel_discount_type:
                    type: string
                    nullable: true
                  allocation_method:
                    type: string
                    nullable: true
                  target_type:
                    type: string
                    nullable: true
                  apply_before_tax:
                    type: boolean
                  sequence:
                    type: integer
                  created_at:
                    type: string
                  updated_at:
                    type: string
                example:
                  id: 12
                  sales_order_id: 500
                  sales_order_line_id: 8801
                  financial_line_id: null
                  scope: line
                  type: percentage
                  rate: 10
                  amount: 25.5
                  name: Loyalty discount
                  source_type: manual
                  source_id: null
                  source_reference: null
                  channel_discount_type: null
                  allocation_method: null
                  target_type: null
                  apply_before_tax: true
                  sequence: 0
                  created_at: '2026-07-01T14:22:05.000000Z'
                  updated_at: '2026-07-06T09:10:41.000000Z'
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No query results for model.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: orders:read
      operationId: get-api-sales-orders-salesorder-discounts-discount
    put:
      tags:
      - Sales Orders
      summary: Update Sales Order Discount
      description: 'Updates an existing discount on a sales order and recalculates
        the order''s discount totals.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Request body fields (all optional — omitted fields keep their current values):

        - scope (string): `line` or `order`.

        - type (string): `percentage` or `fixed_amount`.

        - rate (number): Percentage rate, 0-100.

        - amount (number): Discount amount in the order currency, minimum 0.

        - name (string, max 255): Display label.

        - sales_order_line_id (integer): Existing product line the discount applies
        to.

        - financial_line_id (integer): Existing charge line the discount applies to.

        - source_type (string, max 50): Origin of the discount.

        - source_reference (string, max 255): External reference such as a coupon
        code.

        - apply_before_tax (boolean): Whether the discount applies before tax is calculated.

        - sequence (integer, min 0): Application order.


        Behavior:

        - The update triggers the same full discount recalculation as creating a discount
        — line totals, order-level allocation across lines, and the order''s discount
        totals are refreshed.

        - For percentage discounts the effective `amount` is recomputed and returned
        in the response.


        The response is the updated discount object (no envelope).


        Path parameters:

        - salesOrder (required): Sales order ID.

        - discount (required): Discount ID.


        **Requires permission:** `sales_orders.update`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                rate:
                  type: integer
                name:
                  type: string
              example:
                rate: 15
                name: Loyalty discount (increased)
      parameters:
      - name: salesOrder
        in: path
        schema:
          type: integer
        required: true
        description: Sales order ID
        example: '500'
      - name: discount
        in: path
        schema:
          type: integer
        required: true
        description: Discount ID
        example: '12'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: integer
                  sales_order_id:
                    type: integer
                  sales_order_line_id:
                    type: integer
                  financial_line_id:
                    type: string
                    nullable: true
                  scope:
                    type: string
                  type:
                    type: string
                  rate:
                    type: integer
                  amount:
                    type: number
                  name:
                    type: string
                  source_type:
                    type: string
                  source_id:
                    type: string
                    nullable: true
                  source_reference:
                    type: string
                    nullable: true
                  channel_discount_type:
                    type: string
                    nullable: true
                  allocation_method:
                    type: string
                    nullable: true
                  target_type:
                    type: string
                    nullable: true
                  apply_before_tax:
                    type: boolean
                  sequence:
                    type: integer
                  created_at:
                    type: string
                  updated_at:
                    type: string
                example:
                  id: 12
                  sales_order_id: 500
                  sales_order_line_id: 8801
                  financial_line_id: null
                  scope: line
                  type: percentage
                  rate: 15
                  amount: 38.25
                  name: Loyalty discount (increased)
                  source_type: manual
                  source_id: null
                  source_reference: null
                  channel_discount_type: null
                  allocation_method: null
                  target_type: null
                  apply_before_tax: true
                  sequence: 0
                  created_at: '2026-07-01T14:22:05.000000Z'
                  updated_at: '2026-07-06T15:02:12.000000Z'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      type:
                        type: array
                        items:
                          type: string
                example:
                  message: The selected type is invalid.
                  errors:
                    type:
                    - The selected type is invalid.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:write
      operationId: put-api-sales-orders-salesorder-discounts-discount
    delete:
      tags:
      - Sales Orders
      summary: Delete Sales Order Discount
      description: 'Deletes a discount from a sales order and recalculates the order''s
        discount totals (line totals, order-level allocation across lines, and the
        order''s denormalized totals are refreshed without the removed discount).


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Path parameters:

        - salesOrder (required): Sales order ID.

        - discount (required): Discount ID.


        Returns 404 when the sales order or discount does not exist.


        **Requires permission:** `sales_orders.update`'
      parameters:
      - name: salesOrder
        in: path
        schema:
          type: integer
        required: true
        description: Sales order ID
        example: '500'
      - name: discount
        in: path
        schema:
          type: integer
        required: true
        description: Discount ID
        example: '12'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Discount deleted successfully.
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No query results for model.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: orders:write
      operationId: delete-api-sales-orders-salesorder-discounts-discount
  /api/sales-orders/{salesOrder}/financial-lines:
    get:
      tags:
      - Sales Orders
      summary: List Sales Order Financial Lines
      description: 'Lists the financial lines attached to a sales order — shipping,
        handling, fees, and other non-product revenue or cost lines.


        :::info[Required scope: `orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        The response body is a plain JSON array of financial line objects. It is NOT
        wrapped in a `data` envelope. Each line includes a nested `financial_line_type`
        object carrying the type''s `classification` (`revenue` or `cost`).


        Authentication: Requires Bearer token.


        Query parameters:

        - filter[financialLineType.classification] (string, optional): Restrict to
        lines whose type is classified `revenue` or `cost`.


        Response fields (per line):

        - id (integer): Financial line ID.

        - financial_line_type_id (integer): The line type (e.g. Shipping, Handling).

        - link_type (string), link_id (integer): The owning document — always the
        sales order for this endpoint.

        - nominal_code_id (integer|null): Accounting nominal code.

        - description (string): Display description.

        - quantity (integer): Quantity.

        - amount (number): Unit amount in the order currency.

        - discount_rate (number): Fractional discount (0-1) applied to the extended
        amount.

        - extended_amount (number): Computed as quantity x amount x (1 - discount_rate).

        - tax_allocation (number): Tax amount attributed to this line.

        - tax_rate_id (integer|null), tax_rate (number): Tax rate reference and percentage.

        - allocate_to_products (boolean): Whether the line''s value is prorated across
        the order''s product lines.

        - proration_strategy (string): How the value is prorated — one of revenue_based,
        cost_based, weight_based, volume_based, quantity_based, specific_line, manual.

        - allocate_to_id (integer|null), allocate_to_type (string|null): Target line
        when proration_strategy is specific_line.

        - sales_channel_line_id (string|null): Channel line reference for lines imported
        from a sales channel.

        - external_source_type (string|null), external_source_id (integer|null): External
        record that produced the line.

        - financial_line_type (object): `{id, classification}` of the line type.


        Path parameters:

        - salesOrder (required): Sales order ID.'
      parameters:
      - name: salesOrder
        in: path
        schema:
          type: integer
        required: true
        description: Sales order ID
        example: '500'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: array
                items:
                  type: object
                  properties:
                    id:
                      type: integer
                    financial_line_type_id:
                      type: integer
                    link_type:
                      type: string
                    link_id:
                      type: integer
                    nominal_code_id:
                      type: integer
                    description:
                      type: string
                    quantity:
                      type: integer
                    amount:
                      type: integer
                    discount_rate:
                      type: integer
                    extended_amount:
                      type: integer
                    tax_allocation:
                      type: number
                    tax_rate_id:
                      type: integer
                    tax_rate:
                      type: number
                    allocate_to_products:
                      type: boolean
                    proration_strategy:
                      type: string
                    allocate_to_id:
                      type: string
                      nullable: true
                    allocate_to_type:
                      type: string
                      nullable: true
                    line_discounts:
                      type: string
                      nullable: true
                    sales_channel_line_id:
                      type: string
                      nullable: true
                    hash:
                      type: string
                      nullable: true
                    external_source_type:
                      type: string
                      nullable: true
                    external_source_id:
                      type: string
                      nullable: true
                    created_at:
                      type: string
                    updated_at:
                      type: string
                    financial_line_type:
                      type: object
                      properties:
                        id:
                          type: integer
                        classification:
                          type: string
                example:
                - id: 310
                  financial_line_type_id: 3
                  link_type: App\Models\SalesOrder
                  link_id: 500
                  nominal_code_id: 41
                  description: Shipping
                  quantity: 1
                  amount: 15
                  discount_rate: 0
                  extended_amount: 15
                  tax_allocation: 1.2375
                  tax_rate_id: 2
                  tax_rate: 8.25
                  allocate_to_products: true
                  proration_strategy: quantity_based
                  allocate_to_id: null
                  allocate_to_type: null
                  line_discounts: null
                  sales_channel_line_id: null
                  hash: null
                  external_source_type: null
                  external_source_id: null
                  created_at: '2026-07-01T14:22:05.000000Z'
                  updated_at: '2026-07-06T09:10:41.000000Z'
                  financial_line_type:
                    id: 3
                    classification: revenue
                - id: 311
                  financial_line_type_id: 9
                  link_type: App\Models\SalesOrder
                  link_id: 500
                  nominal_code_id: null
                  description: Marketplace commission
                  quantity: 1
                  amount: 8.7
                  discount_rate: 0
                  extended_amount: 8.7
                  tax_allocation: 0
                  tax_rate_id: null
                  tax_rate: 0
                  allocate_to_products: true
                  proration_strategy: revenue_based
                  allocate_to_id: null
                  allocate_to_type: null
                  line_discounts: null
                  sales_channel_line_id: null
                  hash: null
                  external_source_type: null
                  external_source_id: null
                  created_at: '2026-07-02T10:15:44.000000Z'
                  updated_at: '2026-07-02T10:15:44.000000Z'
                  financial_line_type:
                    id: 9
                    classification: cost
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:read
      operationId: get-api-sales-orders-salesorder-financial-lines
    post:
      tags:
      - Sales Orders
      summary: Create Sales Order Financial Line
      description: 'Adds a financial line (shipping, handling, fee, or other non-product
        revenue/cost line) to a sales order.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Request body fields:

        - financial_line_type_id (integer, required): Existing financial line type.

        - amount (number, required, min 0): Unit amount in the order currency.

        - description (string, optional): Display description. Defaults to the line
        type''s name when omitted.

        - quantity (integer, optional, min 1): Quantity.

        - discount_rate (number, optional, 0-1): Fractional discount applied to the
        extended amount.

        - tax_allocation (number, optional, min 0): Tax amount for the line. When
        omitted and a tax_rate is set, it is computed automatically from the extended
        amount (and backed out of the amount on tax-inclusive orders).

        - tax_rate_id (integer, optional): Existing tax rate.

        - tax_rate (number, optional, min 0): Tax percentage used for the automatic
        tax_allocation computation.

        - allocate_to_products (boolean, optional): Whether the line''s value is prorated
        across the order''s product lines. Defaults from the line type.

        - proration_strategy (string, optional): One of revenue_based, cost_based,
        weight_based, volume_based, quantity_based, specific_line, manual. Defaults
        from the line type.

        - allocate_to_id (integer, optional), allocate_to_type (string, optional):
        The specific line to allocate to when proration_strategy is specific_line.

        - nominal_code_id (integer, optional): Existing accounting nominal code. Defaults
        from the line type.


        The response is the created financial line as a bare JSON object (no envelope),
        returned with status 201. Computed columns such as extended_amount appear
        when the line is next read via the list endpoint.


        Path parameters:

        - salesOrder (required): Sales order ID.


        **Requires permission:** `sales_orders.update`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                financial_line_type_id:
                  type: integer
                description:
                  type: string
                quantity:
                  type: integer
                amount:
                  type: integer
                tax_rate_id:
                  type: integer
                tax_rate:
                  type: number
                nominal_code_id:
                  type: integer
                allocate_to_products:
                  type: boolean
                proration_strategy:
                  type: string
              example:
                financial_line_type_id: 3
                description: Shipping
                quantity: 1
                amount: 15
                tax_rate_id: 2
                tax_rate: 8.25
                nominal_code_id: 41
                allocate_to_products: true
                proration_strategy: quantity_based
      parameters:
      - name: salesOrder
        in: path
        schema:
          type: integer
        required: true
        description: Sales order ID
        example: '500'
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  financial_line_type_id:
                    type: integer
                  nominal_code_id:
                    type: integer
                  description:
                    type: string
                  quantity:
                    type: integer
                  amount:
                    type: integer
                  tax_rate_id:
                    type: integer
                  tax_rate:
                    type: number
                  proration_strategy:
                    type: string
                  allocate_to_products:
                    type: boolean
                  link_type:
                    type: string
                  link_id:
                    type: integer
                  tax_allocation:
                    type: number
                  updated_at:
                    type: string
                  created_at:
                    type: string
                  id:
                    type: integer
                example:
                  financial_line_type_id: 3
                  nominal_code_id: 41
                  description: Shipping
                  quantity: 1
                  amount: 15
                  tax_rate_id: 2
                  tax_rate: 8.25
                  proration_strategy: quantity_based
                  allocate_to_products: true
                  link_type: App\Models\SalesOrder
                  link_id: 500
                  tax_allocation: 1.2375
                  updated_at: '2026-07-06T14:22:05.000000Z'
                  created_at: '2026-07-06T14:22:05.000000Z'
                  id: 310
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      financial_line_type_id:
                        type: array
                        items:
                          type: string
                      amount:
                        type: array
                        items:
                          type: string
                example:
                  message: The financial line type id field is required. (and 1 more
                    error)
                  errors:
                    financial_line_type_id:
                    - The financial line type id field is required.
                    amount:
                    - The amount field is required.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:write
      operationId: post-api-sales-orders-salesorder-financial-lines
  /api/sales-orders/{salesOrder}/financial-lines/{financialLine}:
    put:
      tags:
      - Sales Orders
      summary: Update Sales Order Financial Line
      description: 'Updates a financial line on a sales order.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Returns `true` on success — the response body is literally the JSON boolean
        `true`, not the updated record. Re-read the line via the list endpoint to
        see the stored values.


        Authentication: Requires Bearer token.


        Request body fields (all optional on update — same meanings as on create):

        - financial_line_type_id (integer): Existing financial line type.

        - amount (number, min 0): Unit amount in the order currency.

        - description (string): Display description.

        - quantity (integer, min 1): Quantity.

        - discount_rate (number, 0-1): Fractional discount applied to the extended
        amount.

        - tax_allocation (number, min 0): Tax amount for the line; recomputed from
        tax_rate when not explicitly provided.

        - tax_rate_id (integer): Existing tax rate.

        - tax_rate (number, min 0): Tax percentage.

        - allocate_to_products (boolean): Whether the line''s value is prorated across
        product lines.

        - proration_strategy (string): One of revenue_based, cost_based, weight_based,
        volume_based, quantity_based, specific_line, manual.

        - allocate_to_id (integer), allocate_to_type (string): Target line when proration_strategy
        is specific_line.

        - nominal_code_id (integer): Existing accounting nominal code.


        Important — omitted nullable fields are cleared:

        - If you do not send nominal_code_id, allocate_to_id, or allocate_to_type,
        they are reset to null on the line.

        - Channel and external source references on the line (sales_channel_line_id,
        external_source_type, external_source_id) are also cleared by every update.

        - Send every value you want to keep.


        Path parameters:

        - salesOrder (required): Sales order ID.

        - financialLine (required): Financial line ID.


        **Requires permission:** `sales_orders.update`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                financial_line_type_id:
                  type: integer
                description:
                  type: string
                quantity:
                  type: integer
                amount:
                  type: number
                tax_rate_id:
                  type: integer
                tax_rate:
                  type: number
                nominal_code_id:
                  type: integer
                allocate_to_products:
                  type: boolean
                proration_strategy:
                  type: string
              example:
                financial_line_type_id: 3
                description: Shipping (expedited)
                quantity: 1
                amount: 22.5
                tax_rate_id: 2
                tax_rate: 8.25
                nominal_code_id: 41
                allocate_to_products: true
                proration_strategy: quantity_based
      parameters:
      - name: salesOrder
        in: path
        schema:
          type: integer
        required: true
        description: Sales order ID
        example: '500'
      - name: financialLine
        in: path
        schema:
          type: integer
        required: true
        description: Financial line ID
        example: '310'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: boolean
                example: true
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      amount:
                        type: array
                        items:
                          type: string
                example:
                  message: The amount must be at least 0.
                  errors:
                    amount:
                    - The amount must be at least 0.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:write
      operationId: put-api-sales-orders-salesorder-financial-lines-financialline
    delete:
      tags:
      - Sales Orders
      summary: Delete Sales Order Financial Line
      description: 'Deletes a financial line from a sales order. The order''s product-line
        financial figures are flagged for recalculation so the removed amount drops
        out of prorated revenue/cost on the next computation.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Returns 204 No Content with an empty body on success.


        Authentication: Requires Bearer token.


        Path parameters:

        - salesOrder (required): Sales order ID.

        - financialLine (required): Financial line ID.


        Returns 404 when the sales order or financial line does not exist.


        **Requires permission:** `sales_orders.update`'
      parameters:
      - name: salesOrder
        in: path
        schema:
          type: integer
        required: true
        description: Sales order ID
        example: '500'
      - name: financialLine
        in: path
        schema:
          type: integer
        required: true
        description: Financial line ID
        example: '310'
      responses:
        '204':
          description: No Content
          content:
            text/plain:
              schema:
                type: string
                example: ''
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No query results for model.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: orders:write
      operationId: delete-api-sales-orders-salesorder-financial-lines-financialline
  /api/sales-orders/{salesOrder}/accounting:
    get:
      tags:
      - Sales Orders
      summary: Get Sales Order Accounting Transaction
      description: 'Gets the accounting transaction (invoice journal) generated for
        a sales order, including its lines with nominal codes and tax rates, any child
        transactions, and a summary of its parent batch transaction. Returns `data:
        null` when no accounting transaction has been generated for the order yet.


        :::info[Required scope: `orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Response fields:

        - id (integer), transaction_date (date-time), reference (string): The order
        number the transaction posts against.

        - type (object): name (e.g. `sales_order_invoice`), link_type / link_id (the
        source record), link_type_label (human-friendly label), link_route (in-app
        path to the source record).

        - name (string|null): The counterparty name (customer).

        - integration_invoice_number_override (string|null): Invoice number override
        used when posting to the accounting integration.

        - is_tax_included (boolean), total (number).

        - parent_type (object): Summary of the parent batch transaction; all values
        are null when the transaction has no parent.

        - children (array): Child transactions in the same structure (e.g. fulfillment
        journals), empty when none.

        - last_synced_at (date-time|null) and link (string|null): Last sync time and
        deep link into the connected accounting system, present when an accounting
        integration is connected.

        - last_sync_error (string|object|null): The most recent sync error, if any.

        - is_sync_enabled (boolean): Whether this transaction is allowed to sync.

        - is_type_sync_enabled (boolean): Whether this transaction type is enabled
        in the accounting sync settings.

        - lines (array): id, type (`debit` or `credit`), nominal_code {id, code, name},
        description, quantity, amount (unit amount), subtotal (amount x quantity),
        tax_amount, tax {id, name, rate} (null when no tax rate applies), created_at,
        updated_at.

        - status (string): `toSync`, `synced`, `hasErrors`, `submissionInProgress`,
        or `ineligibleToSync`.

        - is_locked (boolean): Locked transactions cannot be regenerated or edited.

        - is_batchable (boolean), created_at, updated_at.


        Path parameters:

        - salesOrder (required): Sales order ID.'
      parameters:
      - name: salesOrder
        in: path
        schema:
          type: integer
        required: true
        description: Sales order ID
        example: '500'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 Success
                  value:
                    data:
                      id: 9210
                      transaction_date: '2026-06-18T00:00:00.000000Z'
                      type:
                        name: sales_order_invoice
                        link_type: App\Models\SalesOrder
                        link_id: 500
                        link_type_label: Sales Order Invoice
                        link_route: /orders/sales-orders/500
                      integration_invoice_number_override: null
                      name: Acme Retail Group
                      is_tax_included: false
                      total: 258.9
                      reference: SO-0158
                      parent_type:
                        id: null
                        reference: null
                        name: null
                        link_type: null
                        link_id: null
                        link_type_label: null
                        link_route: null
                      children: []
                      last_synced_at: '2026-06-18T14:22:05.000000Z'
                      link: https://app.qbo.intuit.com/app/invoice?txnId=145
                      last_sync_error: null
                      is_sync_enabled: true
                      is_type_sync_enabled: true
                      lines:
                      - id: 30411
                        type: credit
                        nominal_code:
                          id: 12
                          code: '4000'
                          name: Sales Revenue
                        description: Blue Widget (Medium) x 5
                        quantity: 5
                        amount: 45
                        subtotal: 225
                        tax_amount: 18.9
                        tax:
                          id: 4
                          name: CA Sales Tax
                          rate: 8.4
                        updated_at: '2026-06-18T14:22:05.000000Z'
                        created_at: '2026-06-18T14:20:44.000000Z'
                      - id: 30412
                        type: credit
                        nominal_code:
                          id: 18
                          code: '4400'
                          name: Shipping Income
                        description: Shipping
                        quantity: 1
                        amount: 15
                        subtotal: 15
                        tax_amount: 0
                        tax: null
                        updated_at: '2026-06-18T14:22:05.000000Z'
                        created_at: '2026-06-18T14:20:44.000000Z'
                      status: synced
                      is_locked: false
                      is_batchable: true
                      updated_at: '2026-06-18T14:22:05.000000Z'
                      created_at: '2026-06-18T14:20:44.000000Z'
                example-1:
                  summary: 200 No Transaction Yet
                  value:
                    data: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:read
      operationId: get-api-sales-orders-salesorder-accounting
  /api/sales-orders/{salesOrder}/generate-accounting-transaction:
    post:
      tags:
      - Sales Orders
      summary: Generate Sales Order Accounting Transaction
      description: 'Generates — or regenerates — the accounting transaction (invoice
        journal) for a sales order from its current lines and financial data. Use
        this after correcting an order to refresh the journal without waiting for
        the next scheduled accounting sync.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Behavior:

        - No request body is required.

        - The response returns the generated transaction with its lines and nominal
        codes. Tax rate details, parent/children, and accounting-integration sync
        metadata are not expanded on this response — fetch `GET /api/sales-orders/{salesOrder}/accounting`
        for the fully expanded transaction.

        - Regeneration replaces the transaction''s lines to match the order''s current
        state.


        Path parameters:

        - salesOrder (required): Sales order ID.


        **Requires permission:** `sales_orders.update`'
      requestBody:
        content: {}
      parameters:
      - name: salesOrder
        in: path
        schema:
          type: integer
        required: true
        description: Sales order ID
        example: '500'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      transaction_date:
                        type: string
                      type:
                        type: object
                        properties:
                          name:
                            type: string
                          link_type:
                            type: string
                          link_id:
                            type: integer
                          link_type_label:
                            type: string
                          link_route:
                            type: string
                      integration_invoice_number_override:
                        type: string
                        nullable: true
                      name:
                        type: string
                      is_tax_included:
                        type: boolean
                      total:
                        type: number
                      reference:
                        type: string
                      last_sync_error:
                        type: string
                        nullable: true
                      is_sync_enabled:
                        type: boolean
                      is_type_sync_enabled:
                        type: boolean
                      lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            type:
                              type: string
                            nominal_code:
                              type: object
                              properties:
                                id:
                                  type: integer
                                code:
                                  type: string
                                name:
                                  type: string
                            description:
                              type: string
                            quantity:
                              type: integer
                            amount:
                              type: integer
                            subtotal:
                              type: integer
                            tax_amount:
                              type: number
                            updated_at:
                              type: string
                            created_at:
                              type: string
                      status:
                        type: string
                      is_locked:
                        type: boolean
                      is_batchable:
                        type: boolean
                      updated_at:
                        type: string
                      created_at:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 9210
                    transaction_date: '2026-07-06T00:00:00.000000Z'
                    type:
                      name: sales_order_invoice
                      link_type: App\Models\SalesOrder
                      link_id: 500
                      link_type_label: Sales Order Invoice
                      link_route: /orders/sales-orders/500
                    integration_invoice_number_override: null
                    name: Acme Retail Group
                    is_tax_included: false
                    total: 258.9
                    reference: SO-0158
                    last_sync_error: null
                    is_sync_enabled: true
                    is_type_sync_enabled: true
                    lines:
                    - id: 30411
                      type: credit
                      nominal_code:
                        id: 12
                        code: '4000'
                        name: Sales Revenue
                      description: Blue Widget (Medium) x 5
                      quantity: 5
                      amount: 45
                      subtotal: 225
                      tax_amount: 18.9
                      updated_at: '2026-07-06T16:10:02.000000Z'
                      created_at: '2026-06-18T14:20:44.000000Z'
                    status: toSync
                    is_locked: false
                    is_batchable: true
                    updated_at: '2026-07-06T16:10:02.000000Z'
                    created_at: '2026-06-18T14:20:44.000000Z'
                  message: Accounting transaction generated successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: orders:write
      operationId: post-api-sales-orders-salesorder-generate-accounting-transaction
  /api/sales-orders/{salesOrder}/recalculate-financials:
    post:
      tags:
      - Sales Orders
      summary: Recalculate Sales Order Financials
      description: 'Recalculates the line-level financial figures (revenue, cost of
        goods sold, fees, and profit) for every line on the sales order and refreshes
        the dependent daily financial aggregates.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Behavior:

        - No request body is required.

        - The recalculation normally runs synchronously under a short per-order lock
        so concurrent recalculations do not conflict.

        - If another recalculation currently holds the lock, the order''s lines are
        flagged for recalculation and picked up in the background instead; the response
        is still a 200.


        Path parameters:

        - salesOrder (required): Sales order ID.


        **Requires permission:** `sales_orders.update`'
      requestBody:
        content: {}
      parameters:
      - name: salesOrder
        in: path
        schema:
          type: integer
        required: true
        description: Sales order ID
        example: '500'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Financials recalculated successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: orders:write
      operationId: post-api-sales-orders-salesorder-recalculate-financials
  /api/v2/sales-orders/{salesOrder}:
    get:
      tags:
      - Sales Orders
      summary: Get Sales Order
      description: 'Returns core sales order data for the V2 show page. Includes essential
        fields, addresses, channel info, totals, counts, custom fields, financial
        lines, tags, discounts, credits, RMAs, and purchase orders.


        :::info[Required scope: `orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Line items are loaded separately via the lineItems endpoint for parallel loading.


        Also returns the top-level flag `use_sales_order_line_nominal_codes` (boolean)
        — sibling to `data` — indicating whether the per-line nominal code editor
        should be enabled in the UI. Mirrors the `accounting.use_sales_order_line_nominal_codes`
        config value.


        Payment / credit totals:

        - `total_paid`: aggregated sum of `payments.amount` for the order — lets the
        UI render Paid/Balance Due without lazy-loading the payments array.

        - Each entry in `sales_credits[]` includes `refund_payments_total` (sum of
        cash/card refunds against the credit, always positive), `applied_to_other_total`
        (sum of credit consumed by Loop Returns EXC-* exchange orders, always positive),
        `fees_retained_total` (sum of fees Loop withheld out of the customer''s credit
        — return shipping, restocking, etc., always positive), and `outstanding_amount`
        (= total − refund_payments_total − applied_to_other_total − fees_retained_total,
        clamped to zero). The frontend uses `outstanding_amount` for the Credits line
        so partially-refunded credits no longer double-count against Balance Due.
        Each credit also includes `metadata` (nullable object) — a minimal source
        subset `{source, sales_channel_refund_id}` used to render the channel-source
        chip (e.g. eBay refund-synced credits); null for manually created credits.


        Authentication: Requires Bearer token.


        **Address override fields:** `shipping_overridden_at` is an ISO-8601 UTC timestamp
        (or null) set when an operator manually corrects the ship-to/billing address;
        `is_shipping_overridden` is the boolean equivalent. When set, sales-channel
        resyncs (e.g. Amazon) will not overwrite the corrected inline address columns.'
      parameters:
      - name: salesOrder
        in: path
        schema:
          type: integer
        required: true
        description: Sales order ID
        example: '500'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      sales_order_number:
                        type: string
                      order_status:
                        type: string
                      order_date:
                        type: string
                      ship_by_date:
                        type: string
                      deliver_by_date:
                        type: string
                      hold_until_date:
                        type: string
                      customer_id:
                        type: integer
                      customer:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      store:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      sales_channel:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      shipping_address:
                        type: object
                        properties:
                          name:
                            type: string
                          address1:
                            type: string
                          city:
                            type: string
                          province:
                            type: string
                          zip:
                            type: string
                          country:
                            type: string
                      shipping_overridden_at:
                        type: string
                        nullable: true
                      is_shipping_overridden:
                        type: boolean
                      billing_address:
                        type: object
                        properties:
                          name:
                            type: string
                          address1:
                            type: string
                      subtotal:
                        type: string
                      tax_total:
                        type: string
                      total:
                        type: string
                      currency:
                        type: object
                        properties:
                          code:
                            type: string
                      notes_count:
                        type: integer
                      payments_count:
                        type: integer
                      total_paid:
                        type: number
                      sales_order_fulfillments_count:
                        type: integer
                      activities_count:
                        type: integer
                      tags:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                      discounts:
                        type: array
                      sales_credits:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            sales_credit_number:
                              type: string
                            credit_date:
                              type: string
                            total:
                              type: integer
                            refund_payments_total:
                              type: number
                            applied_to_other_total:
                              type: number
                            fees_retained_total:
                              type: integer
                            outstanding_amount:
                              type: number
                            statuses:
                              type: object
                              properties:
                                credit_status:
                                  type: string
                            metadata:
                              type: object
                              properties:
                                source:
                                  type: string
                                sales_channel_refund_id:
                                  type: string
                      purchase_orders:
                        type: array
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      incoterm_id:
                        type: integer
                      incoterm_place:
                        type: string
                      incoterm_version:
                        type: integer
                      incoterm_code:
                        type: string
                      incoterm_display:
                        type: string
                      importer_of_record:
                        type: string
                      seller_must_insure:
                        type: boolean
                      incoterm:
                        type: object
                        properties:
                          id:
                            type: integer
                          code:
                            type: string
                          name:
                            type: string
                          transport_mode:
                            type: string
                          family:
                            type: string
                          seller_pays_main_carriage:
                            type: boolean
                          export_cleared_by:
                            type: string
                          import_cleared_by:
                            type: string
                          seller_insurance:
                            type: string
                          risk_transfer_point:
                            type: string
                          is_standard:
                            type: boolean
                          is_deprecated:
                            type: boolean
                          sort_order:
                            type: integer
                  use_sales_order_line_nominal_codes:
                    type: boolean
                example:
                  data:
                    id: 500
                    sales_order_number: SO-20240115-500
                    order_status: fulfilled
                    order_date: '2024-01-15'
                    ship_by_date: '2024-01-20'
                    deliver_by_date: '2024-01-25'
                    hold_until_date: '2024-01-18'
                    customer_id: 10
                    customer:
                      id: 10
                      name: Acme Corp
                    store:
                      id: 1
                      name: Main Store
                    sales_channel:
                      id: 5
                      name: Shopify Store
                    shipping_address:
                      name: John Doe
                      address1: 456 Ship Lane
                      city: Los Angeles
                      province: California
                      zip: '90001'
                      country: United States
                    shipping_overridden_at: null
                    is_shipping_overridden: false
                    billing_address:
                      name: Acme Corp
                      address1: 123 Main St
                    subtotal: '89.97'
                    tax_total: '7.65'
                    total: '97.62'
                    currency:
                      code: USD
                    notes_count: 2
                    payments_count: 1
                    total_paid: 97.62
                    sales_order_fulfillments_count: 1
                    activities_count: 5
                    tags:
                    - id: 3
                      name: priority
                    discounts: []
                    sales_credits:
                    - id: 55
                      sales_credit_number: SC-00055
                      credit_date: '2024-01-20'
                      total: 30
                      refund_payments_total: 14.4
                      applied_to_other_total: 4.09
                      fees_retained_total: 0
                      outstanding_amount: 11.51
                      statuses:
                        credit_status: open
                      metadata:
                        source: ebay
                        sales_channel_refund_id: '5000012345'
                    purchase_orders: []
                    created_at: '2024-01-15T08:00:00.000000Z'
                    updated_at: '2024-01-18T14:00:00.000000Z'
                    incoterm_id: 4
                    incoterm_place: Rotterdam
                    incoterm_version: 2020
                    incoterm_code: DAP
                    incoterm_display: DAP Rotterdam, Incoterms 2020
                    importer_of_record: Buyer
                    seller_must_insure: false
                    incoterm:
                      id: 4
                      code: DAP
                      name: Delivered at Place
                      transport_mode: any
                      family: D
                      seller_pays_main_carriage: true
                      export_cleared_by: seller
                      import_cleared_by: buyer
                      seller_insurance: none
                      risk_transfer_point: At the named destination, on the arriving
                        vehicle ready for unloading.
                      is_standard: true
                      is_deprecated: false
                      sort_order: 9
                  use_sales_order_line_nominal_codes: false
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:read
      operationId: get-api-v2-sales-orders-salesorder
  /api/sales-orders/{salesOrder}:
    put:
      tags:
      - Sales Orders
      summary: Update Sales Order
      description: 'Updates a sales order. Accepts a partial payload — only the provided
        fields are applied.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Common use cases:

        - Reopen a closed order: send `{"order_status": "open", "force_reopen": true}`

        - Close an open order: send `{"order_status": "closed"}`

        - Cancel an order: send `{"canceled_at": "2026-05-08T12:00:00Z"}`

        - Update lines, addresses, or other fields by including only the keys you
        want to change.


        Reopen behavior (force_reopen):

        - A closed order is normally not reopened by `order_status: open` if its `fulfillment_status`
        is `fulfilled` or `over_fulfilled`. This guard suppresses spurious reopens
        from sales-channel sync paths (e.g. Walmart Seller-Fulfilled "Shipped") that
        would leave the order stuck in `open` after `updateFulfillmentStatus` runs.

        - Manual UI reopens express explicit user intent and pass `force_reopen: true`
        to bypass the guard.


        Selected request body fields (all optional unless noted):

        - order_status (string): One of draft, open, reserved, closed, cancelled,
        refunded, completed.

        - force_reopen (bool, default false): When true, allow reopening a closed
        order even if it is fulfilled / over-fulfilled. Only meaningful when `order_status:
        open` is sent on a currently `closed` order.

        - fulfillment_status (string): unfulfilled, partially_fulfilled, fulfilled,
        over_fulfilled, out_of_sync.

        - payment_status (string|null): unpaid, partially_paid, paid, refunded.

        - canceled_at (date-time|null): Cancel the order by setting; uncancel by setting
        to null.

        - sales_order_number (string), customer_po_number (string|null), order_date
        (date), payment_date (date|null), ship_by_date (date|null), hold_until_date
        (date|null) — "do not ship before" release date for preorders / holds, deliver_by_date
        (date|null), fulfilled_at (date-time|null), tracking_number (string|null).

        - store_id (int|null), sales_channel_id (int), shipping_method_id (int|null),
        customer_id (int|null), sales_rep_id (int|null), sales_rep_name (string|null),
        shipping_address_id (int|null), billing_address_id (int|null), currency_id
        (int), currency_code (string|null), tax_rate_id (int|null), sub_sales_channel_id
        (int|null).

        - requested_shipping_method (string|null), packing_slip_printed_at (date-time|null),
        last_synced_from_sales_channel_at (date-time|null), is_tax_included (bool|null).

        - tags (array|null), discount_lines (array|null), sales_order_lines (array
        of SalesOrderLineData), financial_lines (array of FinancialLineData), custom_field_values
        (array), notes (array of NoteData), customer (CustomerData|null), shipping_address
        (AddressData|null), billing_address (AddressData|null).

        - Quote fields: is_quote (bool), memo_for_customer (string|null), quote_sent_at
        (date-time|null), quote_approved_by_customer_at (date-time|null), quote_expires_at
        (date-time|null).

        - Behavioral flags: shouldDeleteFulfillments (bool, default false), shippingAddressChanged
        (bool, default false), on_hold (bool, default false), deleteFulfillmentsReason
        (string).


        Path parameters:

        - salesOrder (required): Sales order ID.


        **Requires permission:** `sales_orders.update`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                order_status:
                  type: string
                force_reopen:
                  type: boolean
                incoterm_id:
                  type: integer
                incoterm_place:
                  type: string
                incoterm_version:
                  type: integer
              example:
                order_status: open
                force_reopen: true
                incoterm_id: 12
                incoterm_place: Port of Los Angeles, CA
                incoterm_version: 2020
      parameters:
      - name: salesOrder
        in: path
        schema:
          type: integer
        required: true
        description: Sales order ID
        example: '500'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      sales_order_number:
                        type: string
                      shipping_overridden_at:
                        type: string
                        nullable: true
                      is_shipping_overridden:
                        type: boolean
                      order_status:
                        type: string
                      fulfillment_status:
                        type: string
                      payment_status:
                        type: string
                        nullable: true
                      order_date:
                        type: string
                      canceled_at:
                        type: string
                        nullable: true
                      updated_at:
                        type: string
                example:
                  message: The sales order ':id' updated successfully
                  data:
                    id: 500
                    sales_order_number: SO-0158
                    shipping_overridden_at: null
                    is_shipping_overridden: false
                    order_status: open
                    fulfillment_status: fulfilled
                    payment_status: null
                    order_date: '2026-05-06T00:00:00.000000Z'
                    canceled_at: null
                    updated_at: '2026-05-08T17:14:33.000000Z'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      order_status:
                        type: array
                        items:
                          type: string
                example:
                  message: The given data was invalid.
                  errors:
                    order_status:
                    - The selected order status is invalid.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:write
      operationId: put-api-sales-orders-salesorder
    get:
      tags:
      - Sales Orders
      summary: Get Sales Order Details
      description: 'Returns the complete order graph for a single sales order: header
        fields, line items with inventory and cost-of-goods breakdowns, fulfillments
        (with shipment lines and tracking), payments, notes, financial lines, discounts,
        addresses, linked purchase orders, and backorder coverage dates.


        :::info[Required scope: `orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        This is the full detail endpoint. For a lighter order summary, use `GET /api/v2/sales-orders/{id}`
        instead.


        Authentication: Requires Bearer token.


        Response notes:

        - `item_info` contains the order lines, each with allocation/fulfillment quantities,
        product info, warehouse, per-warehouse inventory, and a `cogs` object aggregating
        the inventory cost layers consumed by the line.

        - `fulfillment` contains the order''s shipments, each with its shipment lines,
        tracking, warehouse, and provider sync timestamps.

        - `sales_order_shipping_address` / `sales_order_billing_address` are the order''s
        own address snapshots (they survive later edits to the underlying address
        records).

        - `customer_name`, `customer_email`, `customer_company`, `customer_phone`
        render the order''s buyer snapshot; channel orders without a stored customer
        record still populate these.

        - Monetary totals (`total`, `product_total`, `tax_total`, `discount_total`,
        etc.) are in the order currency.


        Path parameters:

        - salesOrder (required): Sales order ID.'
      parameters:
      - name: salesOrder
        in: path
        schema:
          type: integer
        required: true
        description: Sales order ID
        example: '500'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      sales_order_number:
                        type: string
                      customer_po_number:
                        type: string
                      sales_channel_id:
                        type: integer
                      sales_channel_name:
                        type: string
                      sub_sales_channel_id:
                        type: string
                        nullable: true
                      sub_sales_channel:
                        type: string
                        nullable: true
                      sub_sales_channel_name:
                        type: string
                        nullable: true
                      integration_instance_id:
                        type: integer
                      integration:
                        type: string
                      integration_id:
                        type: integer
                      integration_image:
                        type: string
                      can_submit_fulfillments_to_channel:
                        type: boolean
                      store:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      sales_rep_id:
                        type: string
                        nullable: true
                      sales_rep:
                        type: string
                        nullable: true
                      accounting:
                        type: object
                        properties:
                          transaction:
                            type: string
                            nullable: true
                      order_date:
                        type: string
                      payment_date:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                      canceled_at:
                        type: string
                        nullable: true
                      currency:
                        type: string
                      currency_rate:
                        type: integer
                      discount_lines:
                        type: string
                        nullable: true
                      discounts:
                        type: array
                      order_discounts:
                        type: string
                        nullable: true
                      line_discount_total:
                        type: integer
                      order_discount_total:
                        type: integer
                      total_discount_amount:
                        type: integer
                      apply_order_discount_on:
                        type: string
                        nullable: true
                      tax_lines:
                        type: string
                        nullable: true
                      packing_slip_printed_at:
                        type: string
                        nullable: true
                      is_fba:
                        type: boolean
                      is_replacement_order:
                        type: boolean
                      need_mapping:
                        type: boolean
                      memo_for_customer:
                        type: string
                        nullable: true
                      reserved_at:
                        type: string
                        nullable: true
                      payment_hold_status:
                        type: string
                        nullable: true
                      reservation_expires_at:
                        type: string
                        nullable: true
                      ship_by_date:
                        type: string
                      hold_until_date:
                        type: string
                        nullable: true
                      is_held:
                        type: boolean
                      deliver_by_date:
                        type: string
                        nullable: true
                      fulfilled_at:
                        type: string
                      shipping_method_id:
                        type: integer
                      shipping_method:
                        type: string
                      is_pickup:
                        type: boolean
                      shipped_is_pickup:
                        type: boolean
                      address_check:
                        type: object
                        properties:
                          has_warning:
                            type: boolean
                          has_block:
                            type: boolean
                          highest_severity:
                            type: string
                          warnings:
                            type: array
                            items:
                              type: object
                              properties:
                                rule_id:
                                  type: string
                                severity:
                                  type: string
                                message:
                                  type: string
                      requested_shipping_method:
                        type: string
                      mapped_shipping_method:
                        type: string
                      has_backorder:
                        type: boolean
                      fulfillment:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            fulfillment_number:
                              type: string
                            sales_order_id:
                              type: integer
                            fulfillment_order_id:
                              type: integer
                            fulfillment_type:
                              type: string
                            fulfillment_status:
                              type: string
                            shipping_method_id:
                              type: integer
                            requested_shipping_method:
                              type: string
                            requested_shipping_method_id:
                              type: integer
                            fulfilled_shipping_method:
                              type: string
                              nullable: true
                            fulfilled_shipping_method_id:
                              type: string
                              nullable: true
                            fulfilled_date:
                              type: string
                            tracking_number:
                              type: string
                            tracking_url:
                              type: string
                            tracking_link:
                              type: string
                            warehouse:
                              type: object
                              properties:
                                id:
                                  type: integer
                                supplier_id:
                                  type: string
                                  nullable: true
                                is_dropship:
                                  type: boolean
                            warehouse_id:
                              type: integer
                            fulfilled_by:
                              type: object
                              properties:
                                id:
                                  type: integer
                                name:
                                  type: string
                            fulfilled_quantity:
                              type: integer
                            fulfillment_lines:
                              type: array
                              items:
                                type: object
                                properties:
                                  id:
                                    type: integer
                                  sales_order_line_id:
                                    type: integer
                                  sales_order_fulfillment_id:
                                    type: integer
                                  quantity:
                                    type: integer
                                  unit_cost:
                                    type: number
                                  metadata:
                                    type: string
                                    nullable: true
                                  sales_order_line:
                                    type: object
                                    properties:
                                      id:
                                        type: integer
                                      product_id:
                                        type: integer
                                      quantity:
                                        type: integer
                                      amount:
                                        type: number
                                      description:
                                        type: string
                                      warehouse_id:
                                        type: integer
                                      product:
                                        type: object
                                        properties:
                                          id:
                                            type: integer
                                          sku:
                                            type: string
                                          name:
                                            type: string
                                          weight:
                                            type: number
                                          weight_unit:
                                            type: string
                                          height:
                                            type: integer
                                          width:
                                            type: number
                                          length:
                                            type: number
                                          dimension_unit:
                                            type: string
                                          is_lot_tracked:
                                            type: boolean
                                          lot_tracking_method:
                                            type: string
                                            nullable: true
                                          shelf_life_days:
                                            type: string
                                            nullable: true
                                          near_expiry_threshold_days:
                                            type: string
                                            nullable: true
                                          min_remaining_shelf_life_days:
                                            type: string
                                            nullable: true
                            cost:
                              type: number
                            status:
                              type: string
                            voided_at:
                              type: string
                              nullable: true
                            void_reason:
                              type: string
                              nullable: true
                            voided_by:
                              type: string
                              nullable: true
                            fulfilled_at:
                              type: string
                            marked_for_pickup_at:
                              type: string
                              nullable: true
                            marked_for_pickup_by:
                              type: string
                              nullable: true
                            expected_pickup_at:
                              type: string
                              nullable: true
                            packing_slip_printed_at:
                              type: string
                              nullable: true
                            submitted_to_sales_channel_at:
                              type: string
                            last_synced_to_provider_at:
                              type: string
                            last_synced_from_provider_at:
                              type: string
                            metadata:
                              type: string
                              nullable: true
                            fulfillment_sequence:
                              type: integer
                            is_parent:
                              type: boolean
                            parent_id:
                              type: string
                              nullable: true
                            created_at:
                              type: string
                            provider_order_id:
                              type: string
                            sales_channel_fulfillment_link:
                              type: string
                              nullable: true
                      fulfillment_channel:
                        type: string
                        nullable: true
                      customer_name:
                        type: object
                        properties:
                          id:
                            type: string
                            nullable: true
                          name:
                            type: string
                      customer_email:
                        type: string
                      customer_company:
                        type: string
                        nullable: true
                      customer_phone:
                        type: string
                      sales_order_shipping_address:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          email:
                            type: string
                          company:
                            type: string
                            nullable: true
                          phone:
                            type: string
                          address1:
                            type: string
                          address2:
                            type: string
                          address3:
                            type: string
                            nullable: true
                          city:
                            type: string
                          province:
                            type: string
                          province_code:
                            type: string
                          zip:
                            type: string
                          country:
                            type: string
                          country_code:
                            type: string
                      shipping_overridden_at:
                        type: string
                        nullable: true
                      is_shipping_overridden:
                        type: boolean
                      sales_order_billing_address:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          email:
                            type: string
                          company:
                            type: string
                            nullable: true
                          phone:
                            type: string
                          address1:
                            type: string
                          address2:
                            type: string
                          address3:
                            type: string
                            nullable: true
                          city:
                            type: string
                          province:
                            type: string
                          province_code:
                            type: string
                          zip:
                            type: string
                          country:
                            type: string
                          country_code:
                            type: string
                      item_info:
                        type: array
                        items:
                          type: object
                          properties:
                            sales_order_line_id:
                              type: integer
                            sales_channel_line_id:
                              type: string
                              nullable: true
                            bundle_quantity_cache:
                              type: string
                              nullable: true
                            unit_cost:
                              type: number
                            tax_rate:
                              type: integer
                            tax_rate_id:
                              type: string
                              nullable: true
                            item_tax_value:
                              type: integer
                            fifo_layer_id:
                              type: string
                              nullable: true
                            item_quantity:
                              type: integer
                            item_canceled_quantity:
                              type: integer
                            item_allocated_quantity:
                              type: integer
                            item_on_hand_allocated_quantity:
                              type: integer
                            item_unallocated_quantity:
                              type: integer
                            sales_channel_fulfillment_out_of_sync:
                              type: boolean
                            item_externally_fulfilled_quantity:
                              type: integer
                            fulfilled_quantity:
                              type: integer
                            submitted_quantity:
                              type: integer
                            item_dropshipped_quantity:
                              type: integer
                            item_sku:
                              type: object
                              properties:
                                id:
                                  type: integer
                                sku:
                                  type: string
                            item_bundle_sku:
                              type: string
                              nullable: true
                            item_barcode:
                              type: string
                            item_weight:
                              type: number
                            item_weight_unit:
                              type: string
                            item_brand:
                              type: object
                              properties:
                                id:
                                  type: integer
                                name:
                                  type: string
                            bundle:
                              type: string
                              nullable: true
                            bundle_proration_basis:
                              type: string
                              nullable: true
                            item_price:
                              type: number
                            item_price_with_tax:
                              type: number
                            item_name:
                              type: string
                            item_nominal_code_id:
                              type: string
                              nullable: true
                            item_nominal_code:
                              type: string
                              nullable: true
                            item_nominal_code_code:
                              type: string
                              nullable: true
                            item_discount:
                              type: integer
                            item_line_discounts:
                              type: array
                            item_line_discount_total:
                              type: integer
                            item_net_total:
                              type: number
                            price_after_line_discount:
                              type: number
                            line_discount_total:
                              type: integer
                            allocated_order_discount:
                              type: integer
                            net_total:
                              type: number
                            item_has_backorder:
                              type: boolean
                            allocation_locked:
                              type: boolean
                            allocation_locked_reason:
                              type: string
                              nullable: true
                            is_product:
                              type: boolean
                            is_bundle:
                              type: boolean
                            is_variation:
                              type: boolean
                            credited_quantity:
                              type: integer
                            credit_sources:
                              type: array
                              items:
                                type: object
                                properties:
                                  vendor_credit_id:
                                    type: integer
                                  vendor_credit_number:
                                    type: string
                                  quantity:
                                    type: integer
                                  credit_status:
                                    type: string
                                  restock_inventory:
                                    type: boolean
                            warehouse_routing_method:
                              type: string
                            warehouse:
                              type: object
                              properties:
                                id:
                                  type: integer
                                name:
                                  type: string
                                supplier_id:
                                  type: string
                                  nullable: true
                                supplier_name:
                                  type: string
                                  nullable: true
                            is_fulfilled:
                              type: boolean
                            no_audit_trail:
                              type: boolean
                            unfulfilled_quantity:
                              type: integer
                            remaining_to_fulfill_quantity:
                              type: integer
                            available_to_fulfill:
                              type: integer
                            committed_to_fulfillment_quantity:
                              type: integer
                            returnable_quantity:
                              type: integer
                            inventory_allocation_id:
                              type: integer
                            backordered_quantity:
                              type: integer
                            listing:
                              type: string
                              nullable: true
                            channel_product_external_id:
                              type: string
                              nullable: true
                            sales_channel_product_id:
                              type: string
                              nullable: true
                            subscription_edition_id:
                              type: string
                              nullable: true
                            subscription_edition:
                              type: string
                              nullable: true
                            subscription_offering:
                              type: string
                              nullable: true
                            created_at:
                              type: string
                            updated_at:
                              type: string
                            cogs:
                              type: object
                              properties:
                                base_unit_cost:
                                  type: number
                                cost_lines_total:
                                  type: integer
                                cost_lines:
                                  type: array
                                landed_costs_total:
                                  type: integer
                                landed_costs:
                                  type: array
                                unallocated_total:
                                  type: integer
                                unallocated:
                                  type: array
                                fifo_layers:
                                  type: array
                                  items:
                                    type: object
                                    properties:
                                      fifo_layer_id:
                                        type: integer
                                      fifo_layer_date:
                                        type: string
                                      quantity:
                                        type: integer
                                      source_label:
                                        type: string
                                      source_id:
                                        type: integer
                                      unit_cost:
                                        type: number
                                total_cost:
                                  type: number
                                unit_cost:
                                  type: number
                                is_finalized:
                                  type: boolean
                            estimated_decoration_cost:
                              type: integer
                            actual_decoration_cost:
                              type: integer
                            decoration_cost_breakdown:
                              type: string
                              nullable: true
                            is_taxable:
                              type: boolean
                            default_tax_rate_id:
                              type: string
                              nullable: true
                            item_img_url:
                              type: string
                            item_inventory:
                              type: object
                              properties:
                                total:
                                  type: object
                                  properties:
                                    inbound:
                                      type: integer
                                    stock:
                                      type: integer
                                    allocated:
                                      type: integer
                                    on_hold:
                                      type: integer
                                    available:
                                      type: integer
                                    in_transit:
                                      type: integer
                                warehouses:
                                  type: object
                                  properties:
                                    Main Warehouse:
                                      type: object
                                      properties:
                                        inbound:
                                          type: integer
                                        stock:
                                          type: integer
                                        allocated:
                                          type: integer
                                        on_hold:
                                          type: integer
                                        available:
                                          type: integer
                                        supplier_in_stock:
                                          type: string
                                          nullable: true
                                        in_transit:
                                          type: integer
                                        warehouse_id:
                                          type: integer
                                        warehouse_name:
                                          type: string
                                        warehouse_type:
                                          type: string
                                        supplier:
                                          type: string
                                          nullable: true
                                        country_code:
                                          type: string
                            item_stock:
                              type: integer
                      purchase_orders:
                        type: array
                      adjustments:
                        type: array
                      financial_lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            description:
                              type: string
                            quantity:
                              type: integer
                            amount:
                              type: number
                            extended_amount:
                              type: number
                            discount_rate:
                              type: integer
                            amount_in_tenant_currency:
                              type: number
                            tax_allocation:
                              type: integer
                            tax_allocation_in_tenant_currency:
                              type: integer
                            tax_rate_id:
                              type: string
                              nullable: true
                            tax_rate:
                              type: string
                              nullable: true
                            allocate_to_products:
                              type: boolean
                            proration_strategy:
                              type: string
                              nullable: true
                            allocate_to_id:
                              type: string
                              nullable: true
                            allocate_to_type:
                              type: string
                              nullable: true
                            link_type:
                              type: string
                              nullable: true
                            link_id:
                              type: string
                              nullable: true
                            financial_line_type:
                              type: object
                              properties:
                                id:
                                  type: integer
                                name:
                                  type: string
                                classification:
                                  type: string
                                nominal_code_id:
                                  type: integer
                            nominal_code:
                              type: object
                              properties:
                                id:
                                  type: integer
                                name:
                                  type: string
                                code:
                                  type: string
                            credited_amount:
                              type: integer
                            remaining_amount:
                              type: number
                      custom_field_values:
                        type: array
                      order_status:
                        type: string
                      fulfillment_status:
                        type: string
                      fulfillment_sequence:
                        type: integer
                      payment_status:
                        type: string
                      tax_revenue:
                        type: number
                      product_total:
                        type: number
                      total:
                        type: number
                      discount_total:
                        type: number
                      currency_code:
                        type: string
                      tags:
                        type: array
                        items:
                          type: string
                      warehouses:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            supplier_id:
                              type: string
                              nullable: true
                            supplier_name:
                              type: string
                              nullable: true
                      can_fulfill:
                        type: boolean
                      exact_discount_total:
                        type: number
                      is_tax_included:
                        type: boolean
                      tax_total:
                        type: number
                      calculated_tax_total:
                        type: number
                      exact_tax_total:
                        type: number
                      tax_rate_id:
                        type: string
                        nullable: true
                      tax_rate:
                        type: string
                        nullable: true
                      payments:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            amount:
                              type: number
                            cost:
                              type: number
                            payment_date:
                              type: string
                            payment_type:
                              type: object
                              properties:
                                id:
                                  type: integer
                                name:
                                  type: string
                            external_reference:
                              type: string
                            type:
                              type: string
                            currency_code:
                              type: string
                            sales_credit_allocation:
                              type: string
                              nullable: true
                      notes:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            note:
                              type: string
                            created_at:
                              type: string
                            user_name:
                              type: string
                      earliest_covered_ship_by_date:
                        type: string
                        nullable: true
                      latest_covered_ship_by_date:
                        type: string
                        nullable: true
                      has_backorder_lines:
                        type: boolean
                example:
                  data:
                    id: 500
                    sales_order_number: SO-0158
                    customer_po_number: PO-88213
                    sales_channel_id: 3
                    sales_channel_name: Shopify - Main Store
                    sub_sales_channel_id: null
                    sub_sales_channel: null
                    sub_sales_channel_name: null
                    integration_instance_id: 2
                    integration: Shopify
                    integration_id: 4
                    integration_image: https://cdn.sku.io/integrations/shopify.png
                    can_submit_fulfillments_to_channel: true
                    store:
                      id: 1
                      name: Main Store
                    sales_rep_id: null
                    sales_rep: null
                    accounting:
                      transaction: null
                    order_date: '2026-06-18T14:23:11.000000Z'
                    payment_date: '2026-06-18T14:25:02.000000Z'
                    created_at: '2026-06-18T14:23:15.000000Z'
                    updated_at: '2026-06-20T09:12:44.000000Z'
                    archived_at: null
                    canceled_at: null
                    currency: USD
                    currency_rate: 1
                    discount_lines: null
                    discounts: []
                    order_discounts: null
                    line_discount_total: 0
                    order_discount_total: 0
                    total_discount_amount: 0
                    apply_order_discount_on: null
                    tax_lines: null
                    packing_slip_printed_at: null
                    is_fba: false
                    is_replacement_order: false
                    need_mapping: false
                    memo_for_customer: null
                    reserved_at: null
                    payment_hold_status: null
                    reservation_expires_at: null
                    ship_by_date: '2026-06-19T00:00:00.000000Z'
                    hold_until_date: null
                    is_held: false
                    deliver_by_date: null
                    fulfilled_at: '2026-06-19T16:40:21.000000Z'
                    shipping_method_id: 7
                    shipping_method: USPS Priority Mail
                    is_pickup: false
                    shipped_is_pickup: false
                    address_check:
                      has_warning: true
                      has_block: false
                      highest_severity: warning
                      warnings:
                      - rule_id: missing-required
                        severity: warning
                        message: Shipping address is missing required fields (name,
                          street, city, postcode or country).
                    requested_shipping_method: Standard Shipping
                    mapped_shipping_method: USPS Priority Mail
                    has_backorder: false
                    fulfillment:
                    - id: 91
                      fulfillment_number: SO-0158-F1
                      sales_order_id: 500
                      fulfillment_order_id: 120
                      fulfillment_type: shipstation
                      fulfillment_status: fulfilled
                      shipping_method_id: 7
                      requested_shipping_method: Standard Shipping
                      requested_shipping_method_id: 7
                      fulfilled_shipping_method: null
                      fulfilled_shipping_method_id: null
                      fulfilled_date: '2026-06-19T16:40:21.000000Z'
                      tracking_number: '9405511899561234567890'
                      tracking_url: https://tools.usps.com/go/TrackConfirmAction?tLabels=9405511899561234567890
                      tracking_link: https://tools.usps.com/go/TrackConfirmAction?tLabels=9405511899561234567890
                      warehouse:
                        id: 3
                        supplier_id: null
                        is_dropship: false
                      warehouse_id: 3
                      fulfilled_by:
                        id: 4
                        name: Alex Rivera
                      fulfilled_quantity: 3
                      fulfillment_lines:
                      - id: 301
                        sales_order_line_id: 2101
                        sales_order_fulfillment_id: 91
                        quantity: 2
                        unit_cost: 11.42
                        metadata: null
                        sales_order_line:
                          id: 2101
                          product_id: 812
                          quantity: 2
                          amount: 25.99
                          description: Stainless Steel Water Bottle 32oz - Ocean Blue
                          warehouse_id: 3
                          product:
                            id: 812
                            sku: WB-32-BLU
                            name: Stainless Steel Water Bottle 32oz - Ocean Blue
                            weight: 1.2
                            weight_unit: lb
                            height: 11
                            width: 3.5
                            length: 3.5
                            dimension_unit: in
                            is_lot_tracked: false
                            lot_tracking_method: null
                            shelf_life_days: null
                            near_expiry_threshold_days: null
                            min_remaining_shelf_life_days: null
                      - id: 302
                        sales_order_line_id: 2102
                        sales_order_fulfillment_id: 91
                        quantity: 1
                        unit_cost: 3.8
                        metadata: null
                        sales_order_line:
                          id: 2102
                          product_id: 954
                          quantity: 1
                          amount: 9.5
                          description: Bottle Cleaning Brush Kit
                          warehouse_id: 3
                          product:
                            id: 954
                            sku: BR-KIT-01
                            name: Bottle Cleaning Brush Kit
                            weight: 0.3
                            weight_unit: lb
                            height: 8
                            width: 4
                            length: 2
                            dimension_unit: in
                            is_lot_tracked: false
                            lot_tracking_method: null
                            shelf_life_days: null
                            near_expiry_threshold_days: null
                            min_remaining_shelf_life_days: null
                      cost: 6.42
                      status: fulfilled
                      voided_at: null
                      void_reason: null
                      voided_by: null
                      fulfilled_at: '2026-06-19T16:40:21.000000Z'
                      marked_for_pickup_at: null
                      marked_for_pickup_by: null
                      expected_pickup_at: null
                      packing_slip_printed_at: null
                      submitted_to_sales_channel_at: '2026-06-19T16:41:03.000000Z'
                      last_synced_to_provider_at: '2026-06-19T16:40:25.000000Z'
                      last_synced_from_provider_at: '2026-06-19T18:02:10.000000Z'
                      metadata: null
                      fulfillment_sequence: 1
                      is_parent: false
                      parent_id: null
                      created_at: '2026-06-19T09:15:02.000000Z'
                      provider_order_id: SS-40912311
                      sales_channel_fulfillment_link: null
                    fulfillment_channel: null
                    customer_name:
                      id: null
                      name: Jane Cooper
                    customer_email: jane.cooper@example.com
                    customer_company: null
                    customer_phone: +1 555-201-4477
                    sales_order_shipping_address:
                      id: 1201
                      name: Jane Cooper
                      email: jane.cooper@example.com
                      company: null
                      phone: +1 555-201-4477
                      address1: 982 Maple Avenue
                      address2: Apt 4B
                      address3: null
                      city: Portland
                      province: Oregon
                      province_code: OR
                      zip: '97205'
                      country: United States
                      country_code: US
                    shipping_overridden_at: null
                    is_shipping_overridden: false
                    sales_order_billing_address:
                      id: 1202
                      name: Jane Cooper
                      email: jane.cooper@example.com
                      company: null
                      phone: +1 555-201-4477
                      address1: 982 Maple Avenue
                      address2: Apt 4B
                      address3: null
                      city: Portland
                      province: Oregon
                      province_code: OR
                      zip: '97205'
                      country: United States
                      country_code: US
                    item_info:
                    - sales_order_line_id: 2101
                      sales_channel_line_id: null
                      bundle_quantity_cache: null
                      unit_cost: 11.42
                      tax_rate: 0
                      tax_rate_id: null
                      item_tax_value: 0
                      fifo_layer_id: null
                      item_quantity: 2
                      item_canceled_quantity: 0
                      item_allocated_quantity: 2
                      item_on_hand_allocated_quantity: 2
                      item_unallocated_quantity: 0
                      sales_channel_fulfillment_out_of_sync: false
                      item_externally_fulfilled_quantity: 0
                      fulfilled_quantity: 2
                      submitted_quantity: 0
                      item_dropshipped_quantity: 0
                      item_sku:
                        id: 812
                        sku: WB-32-BLU
                      item_bundle_sku: null
                      item_barcode: 0812345678905
                      item_weight: 1.2
                      item_weight_unit: lb
                      item_brand:
                        id: 14
                        name: HydraPeak
                      bundle: null
                      bundle_proration_basis: null
                      item_price: 25.99
                      item_price_with_tax: 25.99
                      item_name: Stainless Steel Water Bottle 32oz - Ocean Blue
                      item_nominal_code_id: null
                      item_nominal_code: null
                      item_nominal_code_code: null
                      item_discount: 0
                      item_line_discounts: []
                      item_line_discount_total: 0
                      item_net_total: 51.98
                      price_after_line_discount: 25.99
                      line_discount_total: 0
                      allocated_order_discount: 0
                      net_total: 51.98
                      item_has_backorder: false
                      allocation_locked: false
                      allocation_locked_reason: null
                      is_product: true
                      is_bundle: false
                      is_variation: false
                      credited_quantity: 0
                      credit_sources:
                      - vendor_credit_id: 42
                        vendor_credit_number: VC-1001
                        quantity: 5
                        credit_status: open
                        restock_inventory: false
                      warehouse_routing_method: advanced
                      warehouse:
                        id: 3
                        name: Main Warehouse
                        supplier_id: null
                        supplier_name: null
                      is_fulfilled: true
                      no_audit_trail: false
                      unfulfilled_quantity: 0
                      remaining_to_fulfill_quantity: 0
                      available_to_fulfill: 0
                      committed_to_fulfillment_quantity: 0
                      returnable_quantity: 2
                      inventory_allocation_id: 5120
                      backordered_quantity: 0
                      listing: null
                      channel_product_external_id: null
                      sales_channel_product_id: null
                      subscription_edition_id: null
                      subscription_edition: null
                      subscription_offering: null
                      created_at: '2026-06-18T14:23:15.000000Z'
                      updated_at: '2026-06-19T16:40:21.000000Z'
                      cogs:
                        base_unit_cost: 11.42
                        cost_lines_total: 0
                        cost_lines: []
                        landed_costs_total: 0
                        landed_costs: []
                        unallocated_total: 0
                        unallocated: []
                        fifo_layers:
                        - fifo_layer_id: 3301
                          fifo_layer_date: '2026-05-02'
                          quantity: 2
                          source_label: PO Receipt
                          source_id: 1207
                          unit_cost: 11.42
                        total_cost: 22.84
                        unit_cost: 11.42
                        is_finalized: true
                      estimated_decoration_cost: 0
                      actual_decoration_cost: 0
                      decoration_cost_breakdown: null
                      is_taxable: true
                      default_tax_rate_id: null
                      item_img_url: https://cdn.sku.io/products/wb-32-blu.jpg
                      item_inventory:
                        total:
                          inbound: 24
                          stock: 150
                          allocated: 2
                          on_hold: 0
                          available: 148
                          in_transit: 0
                        warehouses:
                          Main Warehouse:
                            inbound: 24
                            stock: 150
                            allocated: 2
                            on_hold: 0
                            available: 148
                            supplier_in_stock: null
                            in_transit: 0
                            warehouse_id: 3
                            warehouse_name: Main Warehouse
                            warehouse_type: standard
                            supplier: null
                            country_code: US
                      item_stock: 148
                    - sales_order_line_id: 2102
                      sales_channel_line_id: null
                      bundle_quantity_cache: null
                      unit_cost: 3.8
                      tax_rate: 0
                      tax_rate_id: null
                      item_tax_value: 0
                      fifo_layer_id: null
                      item_quantity: 1
                      item_canceled_quantity: 0
                      item_allocated_quantity: 1
                      item_on_hand_allocated_quantity: 1
                      item_unallocated_quantity: 0
                      sales_channel_fulfillment_out_of_sync: false
                      item_externally_fulfilled_quantity: 0
                      fulfilled_quantity: 1
                      submitted_quantity: 0
                      item_dropshipped_quantity: 0
                      item_sku:
                        id: 954
                        sku: BR-KIT-01
                      item_bundle_sku: null
                      item_barcode: 0812345671231
                      item_weight: 0.3
                      item_weight_unit: lb
                      item_brand:
                        id: 14
                        name: HydraPeak
                      bundle: null
                      bundle_proration_basis: null
                      item_price: 9.5
                      item_price_with_tax: 9.5
                      item_name: Bottle Cleaning Brush Kit
                      item_nominal_code_id: null
                      item_nominal_code: null
                      item_nominal_code_code: null
                      item_discount: 0
                      item_line_discounts: []
                      item_line_discount_total: 0
                      item_net_total: 9.5
                      price_after_line_discount: 9.5
                      line_discount_total: 0
                      allocated_order_discount: 0
                      net_total: 9.5
                      item_has_backorder: false
                      allocation_locked: false
                      allocation_locked_reason: null
                      is_product: true
                      is_bundle: false
                      is_variation: false
                      credited_quantity: 0
                      credit_sources:
                      - vendor_credit_id: 42
                        vendor_credit_number: VC-1001
                        quantity: 5
                        credit_status: open
                        restock_inventory: false
                      warehouse_routing_method: advanced
                      warehouse:
                        id: 3
                        name: Main Warehouse
                        supplier_id: null
                        supplier_name: null
                      is_fulfilled: true
                      no_audit_trail: false
                      unfulfilled_quantity: 0
                      remaining_to_fulfill_quantity: 0
                      available_to_fulfill: 0
                      committed_to_fulfillment_quantity: 0
                      returnable_quantity: 1
                      inventory_allocation_id: 5121
                      backordered_quantity: 0
                      listing: null
                      channel_product_external_id: null
                      sales_channel_product_id: null
                      subscription_edition_id: null
                      subscription_edition: null
                      subscription_offering: null
                      created_at: '2026-06-18T14:23:15.000000Z'
                      updated_at: '2026-06-19T16:40:21.000000Z'
                      cogs:
                        base_unit_cost: 3.8
                        cost_lines_total: 0
                        cost_lines: []
                        landed_costs_total: 0
                        landed_costs: []
                        unallocated_total: 0
                        unallocated: []
                        fifo_layers:
                        - fifo_layer_id: 3312
                          fifo_layer_date: '2026-05-02'
                          quantity: 1
                          source_label: PO Receipt
                          source_id: 1207
                          unit_cost: 3.8
                        total_cost: 3.8
                        unit_cost: 3.8
                        is_finalized: true
                      estimated_decoration_cost: 0
                      actual_decoration_cost: 0
                      decoration_cost_breakdown: null
                      is_taxable: true
                      default_tax_rate_id: null
                      item_img_url: https://cdn.sku.io/products/br-kit-01.jpg
                      item_inventory:
                        total:
                          inbound: 0
                          stock: 61
                          allocated: 1
                          on_hold: 0
                          available: 60
                          in_transit: 0
                        warehouses:
                          Main Warehouse:
                            inbound: 0
                            stock: 61
                            allocated: 1
                            on_hold: 0
                            available: 60
                            supplier_in_stock: null
                            in_transit: 0
                            warehouse_id: 3
                            warehouse_name: Main Warehouse
                            warehouse_type: standard
                            supplier: null
                            country_code: US
                      item_stock: 60
                    purchase_orders: []
                    adjustments: []
                    financial_lines:
                    - id: 610
                      description: Shipping
                      quantity: 1
                      amount: 6.99
                      extended_amount: 6.99
                      discount_rate: 0
                      amount_in_tenant_currency: 6.99
                      tax_allocation: 0
                      tax_allocation_in_tenant_currency: 0
                      tax_rate_id: null
                      tax_rate: null
                      allocate_to_products: false
                      proration_strategy: null
                      allocate_to_id: null
                      allocate_to_type: null
                      link_type: null
                      link_id: null
                      financial_line_type:
                        id: 2
                        name: Shipping
                        classification: revenue
                        nominal_code_id: 12
                      nominal_code:
                        id: 12
                        name: Shipping Income
                        code: '4020'
                      credited_amount: 0
                      remaining_amount: 6.99
                    custom_field_values: []
                    order_status: closed
                    fulfillment_status: fulfilled
                    fulfillment_sequence: 1
                    payment_status: paid
                    tax_revenue: 4.11
                    product_total: 61.48
                    total: 63.08
                    discount_total: 0.95
                    currency_code: USD
                    tags:
                    - wholesale
                    warehouses:
                    - id: 3
                      name: Main Warehouse
                      supplier_id: null
                      supplier_name: null
                    can_fulfill: false
                    exact_discount_total: 0.95
                    is_tax_included: false
                    tax_total: 4.11
                    calculated_tax_total: 4.11
                    exact_tax_total: 4.11
                    tax_rate_id: null
                    tax_rate: null
                    payments:
                    - id: 77
                      amount: 63.08
                      cost: 1.86
                      payment_date: '2026-06-18T14:25:02.000000Z'
                      payment_type:
                        id: 2
                        name: Credit Card
                      external_reference: ch_3PQx8L2eZvKYlo2C1kT9qXaB
                      type: payment
                      currency_code: USD
                      sales_credit_allocation: null
                    notes:
                    - id: 44
                      note: Customer asked for the package to be left at the side
                        door.
                      created_at: '2026-06-18T15:02:40.000000Z'
                      user_name: Alex Rivera
                    earliest_covered_ship_by_date: null
                    latest_covered_ship_by_date: null
                    has_backorder_lines: false
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      App\Models\SalesOrder:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: array
                example:
                  message: No query results for model [App\Models\SalesOrder] 999999
                  errors:
                    App\Models\SalesOrder:
                    - message: No query results for model [App\Models\SalesOrder]
                        999999
                      code: NotFound
                      data: []
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: orders:read
      operationId: get-api-sales-orders-salesorder
    delete:
      tags:
      - Sales Orders
      summary: Delete Sales Order
      description: 'Deletes a sales order along with its dependent records (lines,
        fulfillments, allocations, payments). Inventory consumed by the order is released
        back to stock.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        The order cannot be deleted when any of its return receipts produced inventory
        that has already been consumed by other transactions — deleting it would orphan
        those downstream costs. In that case the request fails with 422 and the response
        `data` details which return receipts and quantities are blocking the delete.


        Use `POST /api/sales-orders/deletable` to pre-check deletability, and the
        bulk delete endpoints to remove many orders in the background.


        Authentication: Requires Bearer token.


        Path parameters:

        - salesOrder (required): Sales order ID.


        **Requires permission:** `sales_orders.delete`'
      parameters:
      - name: salesOrder
        in: path
        schema:
          type: integer
        required: true
        description: Sales order ID
        example: '500'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: The sales order SO-0158 deleted successfully
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      App\Models\SalesOrder:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: array
                example:
                  message: No query results for model [App\Models\SalesOrder] 999999
                  errors:
                    App\Models\SalesOrder:
                    - message: No query results for model [App\Models\SalesOrder]
                        999999
                      code: NotFound
                      data: []
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      sales_order_number:
                        type: string
                      reason:
                        type: string
                      message:
                        type: string
                      consumed_returns:
                        type: array
                        items:
                          type: object
                          properties:
                            return_receipt_number:
                              type: string
                            product_sku:
                              type: string
                            original_quantity:
                              type: integer
                            consumed_quantity:
                              type: integer
                            usages:
                              type: array
                              items:
                                type: object
                                properties:
                                  reference:
                                    type: string
                                  quantity:
                                    type: integer
                example:
                  message: 'Has return receipts with inventory already consumed by
                    other transactions: Return Receipt RR-0021 - Product WB-32-BLU:
                    2 of 2 units used by SO-0201 (2 units)'
                  data:
                    sales_order_number: SO-0158
                    reason: consumed_returns
                    message: 'Has return receipts with inventory already consumed
                      by other transactions: Return Receipt RR-0021 - Product WB-32-BLU:
                      2 of 2 units used by SO-0201 (2 units)'
                    consumed_returns:
                    - return_receipt_number: RR-0021
                      product_sku: WB-32-BLU
                      original_quantity: 2
                      consumed_quantity: 2
                      usages:
                      - reference: SO-0201
                        quantity: 2
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: orders:write
      operationId: delete-api-sales-orders-salesorder
  /api/v2/sales-orders/{salesOrder}/line-items:
    get:
      tags:
      - Sales Orders
      summary: Get Sales Order Line Items
      description: 'Returns line items with full product details, inventory, allocations,
        and warehouse info. Pre-loads realtime inventory for all products in a single
        query. Loaded in parallel with show.


        :::info[Required scope: `orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Unmapped channel lines (product_id is null) include a `listing` object describing
        the raw sales-channel listing (Amazon, Shopify, eBay, WooCommerce) used by
        the "Link Line Item to Product" modal. For Amazon lines whose seller SKU matches
        a synced AmazonProduct, the `listing` object also includes the internal `id`
        and `integration_instance_id`, which the UI uses to deep-link to the Amazon
        product detail page.


        Each line item includes `bundle_proration_basis` ("cost" | "price" | "quantity"
        | null). For bundle component lines this indicates the methodology used to
        prorate the bundle’s price across its components: "cost" — proportional to
        component unit costs (used when all components have unit_cost > 0); "price"
        — proportional to component prices (fallback when any component is missing
        a cost but all have price > 0); "quantity" — equal split per component quantity
        (last-resort fallback). Null for non-component lines and for legacy component
        lines expanded before this feature (those were price-based).


        Each line item also carries immutable order-line provenance: `channel_product_external_id`
        (string|null) is the sales-channel listing identifier the line came in as,
        snapshotted the first time the line is mapped to a product listing — it is
        never overwritten by a later remap, and survives deletion of the convenience
        `listing` pointer. `sales_channel_product_id` (int|null) is reserved for the
        forthcoming sales_channel_products supertype and is null until that phase
        ships. Lines that have not yet been mapped report both as null.


        Authentication: Requires Bearer token.


        **Allocation lock:** `allocation_locked` (bool) is true when the line is tied
        to a fulfillment order beyond open+unsubmitted — submitted to a carrier, or
        a channel-imported/manual/pickup fulfillment. When true, `allocation_locked_reason`
        (string) explains why the line can no longer be allocated/re-allocated (e.g.
        add stock to reconcile an imported fulfillment). The UI disables the "Allocate"
        action and shows the reason.'
      parameters:
      - name: salesOrder
        in: path
        schema:
          type: integer
        required: true
        description: Sales order ID
        example: '500'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        product_id:
                          type: integer
                        channel_product_external_id:
                          type: string
                        sales_channel_product_id:
                          type: string
                          nullable: true
                        quantity:
                          type: integer
                        amount:
                          type: string
                        description:
                          type: string
                        bundle_proration_basis:
                          type: string
                          nullable: true
                        product:
                          type: object
                          properties:
                            id:
                              type: integer
                            sku:
                              type: string
                            name:
                              type: string
                            barcode:
                              type: string
                            weight:
                              type: number
                            weight_unit:
                              type: string
                        warehouse:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        inventory_allocations:
                          type: array
                        sales_order_fulfillment_lines_count:
                          type: integer
                        sales_credit_lines_count:
                          type: integer
                        allocation_locked:
                          type: boolean
                        allocation_locked_reason:
                          type: string
                          nullable: true
                example:
                  data:
                  - id: 3001
                    product_id: 42
                    channel_product_external_id: JGR-JAPANESE-GO_2PK
                    sales_channel_product_id: null
                    quantity: 3
                    amount: '29.99'
                    description: Premium Widget
                    bundle_proration_basis: null
                    product:
                      id: 42
                      sku: WIDGET-001
                      name: Premium Widget
                      barcode: 012345678901
                      weight: 1.5
                      weight_unit: lb
                    warehouse:
                      id: 1
                      name: Main Warehouse
                    inventory_allocations: []
                    sales_order_fulfillment_lines_count: 1
                    sales_credit_lines_count: 0
                    allocation_locked: false
                    allocation_locked_reason: null
                  - id: 3002
                    product_id: null
                    channel_product_external_id: null
                    sales_channel_product_id: null
                    quantity: 2
                    amount: '19.99'
                    description: JGR Japanese Go 2-Pack
                    product: null
                    listing:
                      seller-sku: JGR-JAPANESE-GO_2PK
                      item-name: JGR Japanese Go 2-Pack
                      asin1: B0DFZJXP6C
                      QuantityOrdered: 2
                      ConditionId: New
                      ConditionSubtypeId: New
                      id: 88123
                      integration_instance_id: 7
                      unique_sales_channel_product_id: JGR-JAPANESE-GO_2PK
                      skuAlias: JGR-2PK
                      PartNumber: JGR-2PK
                      item-condition: New
                      Model: GO-2PK
                      image_url: https://m.media-amazon.com/images/I/example.jpg
                      brand: JGR
                      manufacturer: JGR
                      product_type: TOYS_AND_GAMES
                      color: Multicolor
                      size: 2-Pack
                      style: Standard
                      fulfillment_channel: AFN
                      item_description: Two-pack of Japanese Go board game sets.
                    warehouse: null
                    inventory_allocations: []
                    sales_order_fulfillment_lines_count: 0
                    sales_credit_lines_count: 0
                    allocation_locked: false
                    allocation_locked_reason: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:read
      operationId: get-api-v2-sales-orders-salesorder-line-items
  /api/v2/sales-orders/{salesOrder}/customer-details:
    get:
      tags:
      - Sales Orders
      summary: Get Customer Details
      description: 'Returns customer details for the customer drawer. Includes total
        orders, lifetime value, recent orders, and all addresses. Loaded on-demand
        when the user clicks the customer name.


        :::info[Required scope: `orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: salesOrder
        in: path
        schema:
          type: integer
        required: true
        description: Sales order ID
        example: '500'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      email:
                        type: string
                      phone:
                        type: string
                      company:
                        type: string
                      customer_since:
                        type: string
                      total_orders:
                        type: integer
                      lifetime_value:
                        type: number
                      recent_orders:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            order_number:
                              type: string
                            date:
                              type: string
                            total:
                              type: integer
                      addresses:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            label:
                              type: string
                            name:
                              type: string
                            address1:
                              type: string
                            city:
                              type: string
                            province:
                              type: string
                            zip:
                              type: string
                            country:
                              type: string
                example:
                  data:
                    id: 10
                    name: Acme Corp
                    email: orders@acme.com
                    phone: +1-555-1234
                    company: Acme Corp
                    customer_since: '2023-06-01T00:00:00.000000Z'
                    total_orders: 42
                    lifetime_value: 15234.5
                    recent_orders:
                    - id: 499
                      order_number: SO-20240110-499
                      date: '2024-01-10'
                      total: 156
                    addresses:
                    - id: 1
                      label: billing
                      name: Acme Corp
                      address1: 123 Main St
                      city: New York
                      province: New York
                      zip: '10001'
                      country: United States
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:read
      operationId: get-api-v2-sales-orders-salesorder-customer-details
  /api/v2/sales-orders/{salesOrder}/activity-log:
    get:
      tags:
      - Sales Orders
      summary: Get Activity Log
      description: 'Returns paginated activity log for the sales order, including
        activities on the order, its lines, and fulfillments.


        :::info[Required scope: `orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: per_page
        in: query
        schema:
          type: integer
        description: 'Items per page (default: 15)'
        example: '15'
      - name: salesOrder
        in: path
        schema:
          type: integer
        required: true
        description: Sales order ID
        example: '500'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        description:
                          type: string
                        event:
                          type: string
                        subject_type:
                          type: string
                        subject_id:
                          type: integer
                        properties:
                          type: object
                          properties:
                            old:
                              type: object
                              properties:
                                order_status:
                                  type: string
                            attributes:
                              type: object
                              properties:
                                order_status:
                                  type: string
                        causer_name:
                          type: string
                        created_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 8001
                    description: updated
                    event: updated
                    subject_type: SalesOrder
                    subject_id: 500
                    properties:
                      old:
                        order_status: open
                      attributes:
                        order_status: fulfilled
                    causer_name: Jane Smith
                    created_at: '2024-01-18T14:00:00.000000Z'
                  current_page: 1
                  last_page: 1
                  per_page: 15
                  total: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:read
      operationId: get-api-v2-sales-orders-salesorder-activity-log
  /api/v2/sales-orders/{salesOrder}/inventory-movements:
    get:
      tags:
      - Sales Orders
      summary: Get Inventory Movements
      description: 'Returns paginated inventory movements for the sales order. Includes
        movements from order lines, fulfillments, fulfillment lines, and related adjustments.


        :::info[Required scope: `orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: per_page
        in: query
        schema:
          type: integer
        description: 'Items per page (default: 15)'
        example: '15'
      - name: salesOrder
        in: path
        schema:
          type: integer
        required: true
        description: Sales order ID
        example: '500'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        type:
                          type: string
                        inventory_status:
                          type: string
                        quantity:
                          type: integer
                        reference:
                          type: string
                        inventory_movement_date:
                          type: string
                        product_sku:
                          type: string
                        product_name:
                          type: string
                        warehouse_name:
                          type: string
                        unit_cost:
                          type: string
                        unit_cost_provisional:
                          type: boolean
                        created_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 9001
                    type: sale
                    inventory_status: available
                    quantity: -3
                    reference: SO-20240115-500.1
                    inventory_movement_date: '2024-01-18'
                    product_sku: WIDGET-001
                    product_name: Premium Widget
                    warehouse_name: Main Warehouse
                    unit_cost: '15.00'
                    unit_cost_provisional: false
                    created_at: '2024-01-18T14:00:00.000000Z'
                  current_page: 1
                  last_page: 1
                  per_page: 15
                  total: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:read
      operationId: get-api-v2-sales-orders-salesorder-inventory-movements
  /api/v2/sales-orders/{salesOrder}/allocations:
    get:
      tags:
      - Sales Orders
      summary: Get Allocations
      description: 'Returns paginated inventory allocations for all lines in the sales
        order.


        :::info[Required scope: `orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Status filter values:

        - active: planned + awaiting_receipt + allocated (excludes cancelled/fulfilled)

        - all: all statuses

        - planned, awaiting_receipt, allocated, fulfilled, cancelled: specific status


        Authentication: Requires Bearer token.'
      parameters:
      - name: per_page
        in: query
        schema:
          type: integer
        description: 'Items per page (default: 10)'
        example: '10'
      - name: salesOrder
        in: path
        schema:
          type: integer
        required: true
        description: Sales order ID
        example: '500'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        status:
                          type: string
                        quantity:
                          type: integer
                        product:
                          type: object
                          properties:
                            id:
                              type: integer
                            sku:
                              type: string
                            name:
                              type: string
                        warehouse:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        supplier:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        created_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 4001
                    status: allocated
                    quantity: 3
                    product:
                      id: 42
                      sku: WIDGET-001
                      name: Premium Widget
                    warehouse:
                      id: 1
                      name: Main Warehouse
                    supplier:
                      id: 7
                      name: Widget Co
                    created_at: '2024-01-15T08:00:00.000000Z'
                  current_page: 1
                  last_page: 1
                  per_page: 10
                  total: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:read
      operationId: get-api-v2-sales-orders-salesorder-allocations
  /api/v2/sales-orders/{salesOrder}/channel-items:
    get:
      tags:
      - Sales Orders
      summary: Get Channel Items
      description: 'Fetches raw marketplace order item data for the channel tab. Returns
        original order item data from the sales channel (Amazon order items, Shopify
        line items, etc.) keyed by marketplace order item ID.


        :::info[Required scope: `orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: salesOrder
        in: path
        schema:
          type: integer
        required: true
        description: Sales order ID
        example: '500'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      '12345':
                        type: object
                        properties:
                          title:
                            type: string
                          sku:
                            type: string
                          quantity:
                            type: integer
                          price:
                            type: string
                example:
                  data:
                    '12345':
                      title: Premium Widget
                      sku: WIDGET-001
                      quantity: 3
                      price: '29.99'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:read
      operationId: get-api-v2-sales-orders-salesorder-channel-items
  /api/v2/sales-orders/{salesOrder}/channel-mappings:
    put:
      tags:
      - Sales Orders
      summary: Update Channel Mappings
      description: "Updates the sales channel line ID mappings for sales order lines.\
        \ Set sales_channel_line_id to null to unlink a line from its channel item.\n\
        \n:::info[Required scope: `orders:write`]\nGrant this scope to your token\
        \ under [Settings → Developer → Personal Access Tokens](https://app.sku.io/settings/api).\n\
        :::\n\nAuthentication: Requires Bearer token.\n\nRequest Body:\n- mappings\
        \ (required, array): Array of mapping objects\n  - mappings.*.line_id (required,\
        \ integer): Sales order line ID (must belong to this order)\n  - mappings.*.sales_channel_line_id\
        \ (nullable, string): Marketplace order item ID to link, or null to unlink"
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                mappings:
                  type: array
                  items:
                    type: object
                    properties:
                      line_id:
                        type: integer
                      sales_channel_line_id:
                        type: string
              example:
                mappings:
                - line_id: 3001
                  sales_channel_line_id: '12345'
                - line_id: 3002
                  sales_channel_line_id: null
      parameters:
      - name: salesOrder
        in: path
        schema:
          type: integer
        required: true
        description: Sales order ID
        example: '500'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Channel mappings updated successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: orders:write
      operationId: put-api-v2-sales-orders-salesorder-channel-mappings
  /api/sales-orders/{salesOrder}/financials:
    get:
      tags:
      - Sales Orders
      summary: Get Sales Order Financials (Proforma)
      description: "Recalculates and returns proforma (on-the-fly) line-level financials\
        \ for a single sales order. The endpoint runs the API::calculate for the order\
        \ before responding, so figures always reflect current FIFO cost assignments\
        \ — including the bundle cost-based revenue correction.\n\n:::info[Required\
        \ scope: `orders:read`]\nGrant this scope to your token under [Settings →\
        \ Developer → Personal Access Tokens](https://app.sku.io/settings/api).\n\
        :::\n\nAuthentication: Requires Bearer token.\n\nResponse (wrapped in {data}):\n\
        - id: Sales order ID\n- is_tax_included, currency (code cached at time of\
        \ sale), currency_rate\n- sales_order_lines[]: per-line proforma P&L:\n  -\
        \ product: {id, sku, name} (present when the line is a product line)\n  -\
        \ description, quantity, price (per-unit amount in tenant currency), tax_allocation,\
        \ tax_rate_id\n  - revenue: recognized revenue for the line (after any bundle\
        \ cost-based correction)\n  - revenue_allocation_basis: \"document\" (revenue\
        \ follows the order document) or \"cost_corrected\" (bundle-group revenue\
        \ re-allocated in proportion to actual COGS so no component shows a phantom\
        \ line-level loss)\n  - document_revenue: pre-correction revenue computed\
        \ from the order document (quantity × amount − included tax); equals revenue\
        \ unless revenue_allocation_basis is cost_corrected\n  - bundle_id: parent\
        \ bundle product ID when the line was expanded from a bundle (null otherwise)\n\
        \  - bundle_proration_basis: how the bundle's price was prorated across components\
        \ at order entry — \"cost\", \"price\", or \"quantity\" (null for non-bundle\
        \ or legacy lines)\n  - bundle: {id, sku, name} (present when bundle_id is\
        \ set)\n  - revenue_allocated, credits, discount, total_revenue\n  - cogs,\
        \ cost_allocated, cogs_returned, total_cost\n  - profit, profit_margin\n \
        \ - per_unit: {revenue, revenue_allocated, credits, discount, total_revenue,\
        \ cogs, cost_allocated, cogs_returned, total_cost, profit}\n  - cost_breakdown:\
        \ cost category → amount map\n  - cost_breakdown_layers[]: FIFO layer-level\
        \ cost detail (layer_kind, fifo_layer_id, fifo_layer_date, quantity, source_type,\
        \ source_label, source_id, breakdown, total, unit_cost)\n  - fifo_layers[]:\
        \ {id, name, quantity, unit_cost, total_cost, layer_date}\n\n**Returns-pending\
        \ COGS:** each line splits returned cost into `cogs_returned_realized` (cost\
        \ reversed by physical return receipts) and `cogs_returned_pending` (imputed\
        \ expected cost of refunded units still awaiting return), with a `return_pending`\
        \ boolean; the same split is available under `per_unit.*`. The order-level\
        \ `has_return_pending` flag is true when any line has a return still in flight.\
        \ A refunded-but-un-received order nets to ~0 while `return_pending` is true;\
        \ closing or canceling the RMA without receiving the goods clears the pending\
        \ imputation and reveals the real loss.\n\nEach line includes indirect_cost_allocated\
        \ (the line's revenue-weighted share of cost-entry / overhead allocations),\
        \ contribution_profit (profit minus that share) and contribution_margin (a\
        \ fraction of revenue), plus their per_unit variants. These are standalone\
        \ — profit, total_cost and profit_margin are unchanged by them."
      parameters:
      - name: salesOrder
        in: path
        schema:
          type: integer
        required: true
        description: Sales order ID
        example: '7760'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      sales_order_lines:
                        type: array
                        items:
                          type: object
                          properties:
                            product:
                              type: object
                              properties:
                                id:
                                  type: integer
                                sku:
                                  type: string
                                name:
                                  type: string
                            description:
                              type: string
                            quantity:
                              type: integer
                            price:
                              type: number
                            revenue:
                              type: number
                            total_revenue:
                              type: number
                            cogs:
                              type: number
                            cost_allocated:
                              type: number
                            cogs_returned:
                              type: integer
                            total_cost:
                              type: number
                            profit:
                              type: number
                            profit_margin:
                              type: number
                            indirect_cost_allocated:
                              type: number
                            contribution_profit:
                              type: number
                            contribution_margin:
                              type: number
                            per_unit.revenue:
                              type: number
                            per_unit.total_cost:
                              type: number
                            per_unit.profit:
                              type: number
                            per_unit.indirect_cost_allocated:
                              type: number
                            per_unit.contribution_profit:
                              type: number
                      is_tax_included:
                        type: boolean
                      currency:
                        type: string
                      currency_rate:
                        type: integer
                example:
                  data:
                    id: 123
                    sales_order_lines:
                    - product:
                        id: 88
                        sku: WGT-001
                        name: Widget A
                      description: Widget A
                      quantity: 3
                      price: 50.0
                      revenue: 150.0
                      total_revenue: 150.0
                      cogs: 60.0
                      cost_allocated: 12.0
                      cogs_returned: 0
                      total_cost: 72.0
                      profit: 78.0
                      profit_margin: 0.52
                      indirect_cost_allocated: 9.5
                      contribution_profit: 68.5
                      contribution_margin: 0.4567
                      per_unit.revenue: 50.0
                      per_unit.total_cost: 24.0
                      per_unit.profit: 26.0
                      per_unit.indirect_cost_allocated: 3.17
                      per_unit.contribution_profit: 22.83
                    is_tax_included: false
                    currency: USD
                    currency_rate: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:read
      operationId: get-api-sales-orders-salesorder-financials
  /api/v2/sales-orders/sales-order-lines/{salesOrderLine}/backorder-detail:
    get:
      tags:
      - Sales Orders
      summary: Get Backorder Detail for Line
      description: 'Returns lazy-loaded backorder detail for a sales order line. Includes
        release sources (what freed up stock), PO coverage info, and remaining backorder
        breakdown. Called on badge click — not on list load.


        :::info[Required scope: `orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: salesOrderLine
        in: path
        schema:
          type: integer
        required: true
        description: Sales order line ID
        example: '3001'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      released:
                        type: object
                        properties:
                          total:
                            type: integer
                          sources:
                            type: array
                            items:
                              type: object
                              properties:
                                quantity:
                                  type: integer
                                source_type:
                                  type: string
                                source_id:
                                  type: integer
                                source_label:
                                  type: string
                                released_at:
                                  type: string
                      covered:
                        type: object
                        properties:
                          total:
                            type: integer
                          sources:
                            type: array
                            items:
                              type: object
                              properties:
                                quantity:
                                  type: integer
                                purchase_order_id:
                                  type: integer
                                purchase_order_number:
                                  type: string
                                is_tight_coverage:
                                  type: boolean
                      uncovered:
                        type: object
                        properties:
                          total:
                            type: integer
                      supplier:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          next_schedule:
                            type: string
                            nullable: true
                example:
                  data:
                    released:
                      total: 2
                      sources:
                      - quantity: 2
                        source_type: App\Models\PurchaseOrderShipmentReceiptLine
                        source_id: 100
                        source_label: PO PO-2024-001 receipt
                        released_at: '2024-01-18T00:00:00.000000Z'
                    covered:
                      total: 1
                      sources:
                      - quantity: 1
                        purchase_order_id: 55
                        purchase_order_number: PO-2024-002
                        is_tight_coverage: false
                    uncovered:
                      total: 0
                    supplier:
                      id: 7
                      name: Widget Co
                      next_schedule: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:read
      operationId: get-api-v2-sales-orders-sales-order-lines-salesorderline-backorder-detail
  /api/v2/sales-orders/backorder/next-schedule:
    get:
      tags:
      - Sales Orders
      summary: Get Next Backorder Schedule
      description: 'Returns the next scheduled fill_backorders runs (up to 3) for
        countdown display. Optionally filtered by supplier to find schedules relevant
        to a specific product''s supplier.


        :::info[Required scope: `orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        next_run_at:
                          type: string
                        schedule_time:
                          type: string
                        auto_create_po:
                          type: boolean
                        po_status:
                          type: string
                        last_run_at:
                          type: string
                example:
                  data:
                  - id: 1
                    name: Daily Backorder Fill
                    next_run_at: '2024-01-21T02:00:00+00:00'
                    schedule_time: 02:00
                    auto_create_po: false
                    po_status: draft
                    last_run_at: '2024-01-20T02:00:00+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: orders:read
      operationId: get-api-v2-sales-orders-backorder-next-schedule
  /api/v2/sales-orders/backorder/create-po:
    post:
      tags:
      - Sales Orders
      summary: Create PO from Backorder
      description: 'Creates a draft purchase order from a backordered sales order
        line. Uses the line''s product''s primary supplier and the shortage quantity
        (planned allocations without PO coverage).


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Request Body:

        - sales_order_line_id (required, integer): The sales order line with the backorder
        shortage'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                sales_order_line_id:
                  type: integer
              example:
                sales_order_line_id: 3001
      parameters: []
      responses:
        '201':
          description: Created
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      purchase_order_number:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 55
                    purchase_order_number: PO-2024-055
                  message: Draft PO created successfully
        '422':
          description: Unprocessable Entity
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: This line does not have an active backorder
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: orders:write
      operationId: post-api-v2-sales-orders-backorder-create-po
  /api/sales-orders/list:
    get:
      tags:
      - Sales Orders
      summary: List Sales Orders
      description: 'Paginated sales order listing for the list view (Spatie QueryBuilder).


        :::info[Required scope: `orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Each row includes `ship_by_date` (the ship-by deadline / ceiling), `deliver_by_date`,
        and `hold_until_date` (the earliest date the order may ship — a release floor
        used for preorders / held orders). Held orders also expose `opens_at` and
        `hold_reason` when reserved via a Shopify channel.


        The response is standard Laravel pagination with an extra top-level `unfiltered_total`
        (total count ignoring filters).


        Authentication: Requires Bearer token. Scope: orders (read).


        Filtering (API integrations — start here): use flat `filter[...]` params.
        Any listed column works as `filter[<column>]=<value>` (implicit `is`) or `filter[<column>.<operator>]=<value>`
        for an explicit operator; e.g. `filter[to_fulfill_warehouse_id]=1`, `filter[order_status.is]=open`,
        `filter[total.greater_than]=100`, `filter[order_date.between]=2026-04-01,2026-04-30`.
        Multiple flat filters AND together, and `.is_one_of`/`.between` take a comma-separated
        value. These params are individually documented (see the disabled query params
        below). The `filter_groups` param is a base64 JSON tree used by the web UI''s
        Advanced Filters and is only needed for OR / nested groups — avoid it for
        API use.


        Related-record id filters (for support/debugging — trace a sales order by
        any id in the fulfillment chain): filter[sales_order_line_id] (SOL), filter[fulfillment_order_id]
        (FO), filter[fulfillment_order_line_id] (FOL), filter[sales_order_fulfillment_id]
        (SOF), filter[sales_order_fulfillment_line_id] (SOFL). All numeric, optional,
        and support operators (.is_one_of, etc.) plus comma-separated multi-match.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        sales_order_number:
                          type: string
                        customer_po_number:
                          type: string
                          nullable: true
                        order_status:
                          type: string
                        canceled_at:
                          type: string
                          nullable: true
                        approved_at:
                          type: string
                          nullable: true
                        reserved_at:
                          type: string
                          nullable: true
                        fulfilled_at:
                          type: string
                          nullable: true
                        ship_by_date:
                          type: string
                        deliver_by_date:
                          type: string
                        hold_until_date:
                          type: string
                        fulfillment_status:
                          type: string
                        payment_status:
                          type: string
                        customer_name:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        customer_email:
                          type: string
                        customer_company:
                          type: string
                        customer_phone:
                          type: string
                        sales_rep_name:
                          type: string
                          nullable: true
                        currency_rate:
                          type: integer
                        requested_shipping_method:
                          type: string
                        shipping_name:
                          type: string
                        shipping_company:
                          type: string
                        shipping_address:
                          type: string
                        shipping_address2:
                          type: string
                        shipping_address3:
                          type: string
                        shipping_overridden_at:
                          type: string
                          nullable: true
                        is_shipping_overridden:
                          type: boolean
                        shipping_city:
                          type: string
                        shipping_province:
                          type: string
                        shipping_zip:
                          type: string
                        shipping_country:
                          type: string
                        billing_name:
                          type: string
                        billing_company:
                          type: string
                        billing_address:
                          type: string
                        billing_address2:
                          type: string
                        billing_address3:
                          type: string
                        billing_city:
                          type: string
                        billing_province:
                          type: string
                        billing_zip:
                          type: string
                        billing_country:
                          type: string
                        store:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        sales_channel_name:
                          type: string
                        sub_sales_channel_name:
                          type: string
                          nullable: true
                        integration:
                          type: string
                          nullable: true
                        is_fba:
                          type: boolean
                        order_date:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                        archived_at:
                          type: string
                          nullable: true
                        total:
                          type: number
                        subtotal:
                          type: number
                        tax_total:
                          type: number
                        discount_total:
                          type: integer
                        currency_code:
                          type: string
                        shipping_method:
                          type: string
                        tags:
                          type: array
                          items:
                            type: string
                        warehouse_names:
                          type: string
                        warehouse_count:
                          type: integer
                        line_item_count:
                          type: integer
                        total_quantity:
                          type: integer
                        is_quote:
                          type: boolean
                        has_dropship:
                          type: boolean
                        has_submitted_dropship_po:
                          type: boolean
                        unmapped_line_count:
                          type: integer
                        allocation_required_quantity:
                          type: integer
                        allocation_covered_quantity:
                          type: integer
                        allocation_percentage:
                          type: integer
                        opens_at:
                          type: string
                          nullable: true
                        hold_reason:
                          type: string
                          nullable: true
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                  unfiltered_total:
                    type: integer
                example:
                  data:
                  - id: 186408
                    sales_order_number: GML426864
                    customer_po_number: null
                    order_status: open
                    canceled_at: null
                    approved_at: null
                    reserved_at: null
                    fulfilled_at: null
                    ship_by_date: '2026-04-10'
                    deliver_by_date: '2026-04-15'
                    hold_until_date: '2026-04-01'
                    fulfillment_status: unfulfilled
                    payment_status: paid
                    customer_name:
                      id: 1234
                      name: Jane Smith
                    customer_email: jane@example.com
                    customer_company: Acme Corp
                    customer_phone: +1 555 123 4567
                    sales_rep_name: null
                    currency_rate: 1
                    requested_shipping_method: UPS Ground
                    shipping_name: Jane Doe
                    shipping_company: Acme Retail LLC
                    shipping_address: 123 Main St
                    shipping_address2: Suite 200
                    shipping_address3: Building C
                    shipping_overridden_at: null
                    is_shipping_overridden: false
                    shipping_city: Brooklyn
                    shipping_province: NY
                    shipping_zip: '11201'
                    shipping_country: United States
                    billing_name: Jane Doe
                    billing_company: Acme Retail LLC
                    billing_address: 123 Main St
                    billing_address2: Suite 200
                    billing_address3: Building C
                    billing_city: Brooklyn
                    billing_province: NY
                    billing_zip: '11201'
                    billing_country: United States
                    store:
                      id: 1
                      name: Main Store
                    sales_channel_name: Manual
                    sub_sales_channel_name: null
                    integration: null
                    is_fba: false
                    order_date: '2026-03-28T00:00:00.000000Z'
                    created_at: '2026-03-28T14:02:11.000000Z'
                    updated_at: '2026-03-29T09:15:00.000000Z'
                    archived_at: null
                    total: 219.88
                    subtotal: 199.9
                    tax_total: 19.98
                    discount_total: 0
                    currency_code: USD
                    shipping_method: UPS Ground
                    tags:
                    - priority
                    - b2b
                    warehouse_names: Main Warehouse
                    warehouse_count: 1
                    line_item_count: 2
                    total_quantity: 10
                    is_quote: false
                    has_dropship: false
                    has_submitted_dropship_po: false
                    unmapped_line_count: 0
                    allocation_required_quantity: 10
                    allocation_covered_quantity: 10
                    allocation_percentage: 100
                    opens_at: null
                    hold_reason: null
                  current_page: 1
                  last_page: 5
                  per_page: 10
                  total: 47
                  from: 1
                  to: 10
                  unfiltered_total: 1203
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: orders:read
      operationId: get-api-sales-orders-list
  /api/sales-orders/list/export:
    get:
      tags:
      - Sales Orders
      summary: Export Sales Orders
      description: 'Exports the sales order list view as an XLSX or CSV file download.


        :::info[Required scope: `orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Accepts the same `filter`, `filter_groups`, and `sort` query params as the
        List endpoint (the active list view filters). The `Hold Until Date` column
        is included in the export (alongside `Ship By Date` and `Deliver By Date`);
        date columns are converted from UTC to the tenant timezone.


        Response: a binary file download (Content-Type `application/vnd.openxmlformats-officedocument.spreadsheetml.sheet`
        for xlsx, `text/csv` for csv) — not JSON.


        Authentication: Requires Bearer token. Scope: orders (read).


        **Requires permission:** `sales_orders.export`'
      parameters:
      - name: format
        in: query
        schema:
          type: string
        description: 'Export file format: xlsx (default) or csv.'
        example: xlsx
      - name: content_mode
        in: query
        schema:
          type: string
        description: summary = one row per sales order (default); line_items = one
          row per line item.
        example: summary
      - name: scope
        in: query
        schema:
          type: string
        description: 'Which orders to export: filtered (default — current filters/sort),
          all (ignores filters), current_page, or selected.'
        example: filtered
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: orders:read
      operationId: get-api-sales-orders-list-export
  /api/sales-orders/import/template:
    get:
      tags:
      - Sales Orders
      summary: Download Import Template
      description: 'Downloads an XLSX import template with headers, sample data, a
        field guide, and reference data from the tenant''s account.


        :::info[Required scope: `orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        The template''s `Import Here` sheet and `Field Guide` sheet both include the
        `hold_until_date` column — the earliest date an order is allowed to ship (held
        until this date, e.g. for preorders). Format: YYYY-MM-DD.


        Response: a binary XLSX file download — not JSON.


        Authentication: Requires Bearer token. Scope: orders (read/write).


        **Requires permission:** `sales_orders.import`'
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: orders:read
      operationId: get-api-sales-orders-import-template
  /api/sales-orders/import/validate:
    post:
      tags:
      - Sales Orders
      summary: Validate Import
      description: 'Validates mapped import rows and returns a grouped preview. No
        side effects — safe to call repeatedly.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Request body: `rows` (array, 1–50000). Each row accepts these nullable string
        fields: id, sales_order_number, order_date, customer_email, customer_id, customer_name,
        customer_company, customer_phone, customer_po_number, sales_channel_name,
        sub_sales_channel_name, store_name, currency_code, requested_shipping_method,
        ship_by_date, deliver_by_date, hold_until_date, tags, order_discount_amount,
        order_discount_rate, shipping_amount, shipping_address/city/province/zip/country,
        billing_address/city/province/zip/country, sku, description, quantity, unit_price,
        discount, tax_rate, warehouse_name, nominal_code.


        `hold_until_date` is the earliest ship date — the order is held until this
        date (preorders). Format: YYYY-MM-DD.


        Rows sharing an order number + customer are grouped into one sales order in
        the preview.


        Authentication: Requires Bearer token. Scope: orders (read/write).


        **Requires permission:** `sales_orders.import`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                rows:
                  type: array
                  items:
                    type: object
                    properties:
                      id:
                        type: string
                        nullable: true
                      sales_order_number:
                        type: string
                      order_date:
                        type: string
                      customer_email:
                        type: string
                      sales_channel_name:
                        type: string
                      ship_by_date:
                        type: string
                      deliver_by_date:
                        type: string
                      hold_until_date:
                        type: string
                      sku:
                        type: string
                      quantity:
                        type: string
                      unit_price:
                        type: string
              example:
                rows:
                - id: null
                  sales_order_number: SO-001
                  order_date: '2026-04-01'
                  customer_email: jane@example.com
                  sales_channel_name: Manual
                  ship_by_date: '2026-04-10'
                  deliver_by_date: '2026-04-15'
                  hold_until_date: '2026-04-01'
                  sku: WIDGET-001
                  quantity: '2'
                  unit_price: '19.99'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  sales_orders:
                    type: array
                    items:
                      type: object
                      properties:
                        group_key:
                          type: string
                        action:
                          type: string
                        match_reason:
                          type: string
                          nullable: true
                        sales_order_number:
                          type: string
                        order_date:
                          type: string
                        ship_by_date:
                          type: string
                        deliver_by_date:
                          type: string
                        hold_until_date:
                          type: string
                        customer:
                          type: object
                          properties:
                            email:
                              type: string
                            name:
                              type: string
                              nullable: true
                        sales_channel:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        lines:
                          type: array
                          items:
                            type: object
                            properties:
                              sku:
                                type: string
                              product_id:
                                type: integer
                              quantity:
                                type: integer
                              unit_price:
                                type: number
                        errors:
                          type: array
                        warnings:
                          type: array
                  summary:
                    type: object
                    properties:
                      total_rows:
                        type: integer
                      valid_orders:
                        type: integer
                      orders_with_errors:
                        type: integer
                example:
                  sales_orders:
                  - group_key: SO-001|jane@example.com
                    action: create
                    match_reason: null
                    sales_order_number: SO-001
                    order_date: '2026-04-01'
                    ship_by_date: '2026-04-10'
                    deliver_by_date: '2026-04-15'
                    hold_until_date: '2026-04-01'
                    customer:
                      email: jane@example.com
                      name: null
                    sales_channel:
                      id: 5
                      name: Manual
                    lines:
                    - sku: WIDGET-001
                      product_id: 88
                      quantity: 2
                      unit_price: 19.99
                    errors: []
                    warnings: []
                  summary:
                    total_rows: 1
                    valid_orders: 1
                    orders_with_errors: 0
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: orders:write
      operationId: post-api-sales-orders-import-validate
  /api/sales-orders/import:
    post:
      tags:
      - Sales Orders
      summary: Import Sales Orders
      description: 'Executes the import — creates or updates sales orders from validated/grouped
        data (the output of the Validate Import endpoint).


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Request body: `sales_orders` (array, min 1) and optional `continue_on_error`
        (boolean). Each sales order accepts: group_key, id, action (create|update|blocked),
        sales_order_number, order_date, customer{id,email,name,company,phone}, sales_channel{id}
        (required), sub_sales_channel, store, currency, shipping_method, requested_shipping_method,
        customer_po_number, ship_by_date, deliver_by_date, hold_until_date, tags,
        order_discount_amount, order_discount_rate, shipping_amount, shipping_address,
        billing_address, and lines[] {sku, product_id, product_name, description,
        quantity, unit_price, discount, tax_rate, warehouse_id, nominal_code_id}.


        `hold_until_date` (YYYY-MM-DD) sets the earliest ship date — the order is
        held until this date. Incoming dates are treated as tenant-timezone and stored
        as UTC.


        Returns 201 when anything was newly created, 200 when the import only updated
        existing records.


        Authentication: Requires Bearer token. Scope: orders (read/write).


        **Requires permission:** `sales_orders.import`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                continue_on_error:
                  type: boolean
                sales_orders:
                  type: array
                  items:
                    type: object
                    properties:
                      group_key:
                        type: string
                      action:
                        type: string
                      sales_order_number:
                        type: string
                      order_date:
                        type: string
                      customer:
                        type: object
                        properties:
                          email:
                            type: string
                          name:
                            type: string
                      sales_channel:
                        type: object
                        properties:
                          id:
                            type: integer
                      ship_by_date:
                        type: string
                      deliver_by_date:
                        type: string
                      hold_until_date:
                        type: string
                      lines:
                        type: array
                        items:
                          type: object
                          properties:
                            sku:
                              type: string
                            product_id:
                              type: integer
                            quantity:
                              type: integer
                            unit_price:
                              type: number
              example:
                continue_on_error: false
                sales_orders:
                - group_key: SO-001|jane@example.com
                  action: create
                  sales_order_number: SO-001
                  order_date: '2026-04-01'
                  customer:
                    email: jane@example.com
                    name: Jane Smith
                  sales_channel:
                    id: 5
                  ship_by_date: '2026-04-10'
                  deliver_by_date: '2026-04-15'
                  hold_until_date: '2026-04-01'
                  lines:
                  - sku: WIDGET-001
                    product_id: 88
                    quantity: 2
                    unit_price: 19.99
      parameters: []
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  created:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        sales_order_number:
                          type: string
                  updated:
                    type: array
                  failed:
                    type: array
                  summary:
                    type: object
                    properties:
                      created_count:
                        type: integer
                      updated_count:
                        type: integer
                      failed_count:
                        type: integer
                example:
                  created:
                  - id: 186500
                    sales_order_number: SO-001
                  updated: []
                  failed: []
                  summary:
                    created_count: 1
                    updated_count: 0
                    failed_count: 0
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 'Import failed: <reason>'
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: orders:write
      operationId: post-api-sales-orders-import
  /api/sales-orders/close:
    post:
      tags:
      - Sales Orders
      summary: Bulk Close Sales Orders
      description: 'Bulk closes one or more sales orders by transitioning their order_status
        to `closed`.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Request body (one of `ids` or `filters` is required):

        - `ids` (array of integers, required without `filters`): Sales order IDs to
        close.

        - `filters` (object, required without `ids`): Filter set that resolves to
        a list of sales order IDs (same shape used by the V2 sales-orders listing
        endpoint). It accepts the grouped `filter_groups` shape (`{ \"filter_groups\":
        \"<base64 JSON>\" }`, same as the V2 list) as well as the legacy JSON-string
        filter set.

        - `archived` (integer, optional, default 0): Used with `filters` — set to
        1 to include archived orders when resolving IDs.


        Behavior:

        - Each order is closed individually via `SalesOrder::close`.

        - Orders with active backorders (Planned or AwaitingReceipt allocations) or
        unmapped product lines are skipped and returned as warnings.

        - Returns 200 if all orders close, 200/warning if some are skipped, 400 if
        none can close.


        **Requires permission:** `sales_orders.cancel`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 7116
                - 7117
                - 7118
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 All Closed
                  value:
                    data:
                      '7116': Successfully closed sales order SO-7116.
                      '7117': Successfully closed sales order SO-7117.
                      '7118': Successfully closed sales order SO-7118.
                    message: Successfully closed all sales orders.
                example-1:
                  summary: 200 Partial Success (some skipped)
                  value:
                    message: Successfully closed 2 of 3 sales orders.
                    warnings:
                      '7118':
                      - message: 'Failed to close sales order SO-7118: Cannot close:
                          order has active backorders or unmapped product lines.'
                        code: SalesOrder.UNEXPECTED
                        field: id
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No sales orders found to close.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: orders:write
      operationId: post-api-sales-orders-close
  /api/sales-orders/tracked:
    delete:
      tags:
      - Sales Orders
      summary: Bulk Delete Sales Orders (Tracked)
      description: "Bulk deletes sales orders with progress tracking. Dispatches a\
        \ background job and returns a `tracked_job_log_id` to poll via the tracked\
        \ job log endpoints.\n\n:::info[Required scope: `orders:write`]\nGrant this\
        \ scope to your token under [Settings → Developer → Personal Access Tokens](https://app.sku.io/settings/api).\n\
        :::\n\nAuthentication: Requires Bearer token.\n\nRequest body (scope: one\
        \ of `ids` or `filters` is required):\n- `ids` (array of int, required without\
        \ `filters`): Explicit sales order IDs to delete.\n- `filters` (object, required\
        \ without `ids`): Resolves to a list of sales order IDs via the same Spatie\
        \ QueryBuilder pipeline the V2 sales-orders list/export use. Two shapes are\
        \ accepted:\n  - Grouped filters (current list): `{ \\\"filter_groups\\\"\
        : \\\"<base64-encoded JSON tree>\\\" }`. The decoded tree looks like `{\\\"\
        conjunction\\\":\\\"and\\\",\\\"children\\\":[{\\\"type\\\":\\\"condition\\\
        \",\\\"condition\\\":{\\\"column\\\":\\\"order_status\\\",\\\"operator\\\"\
        :\\\"is\\\",\\\"value\\\":\\\"open\\\"}}]}`.\n  - legacy filter set (JSON\
        \ string) for older clients.\n- `apply_to_all` (bool, optional): When true\
        \ the action targets every order matching the active `filters` rather than\
        \ an explicit `ids` list.\n\nBehavior:\n- Returns the tracked job log ID immediately;\
        \ deletion runs asynchronously.\n- Sending `filters` as the grouped `filter_groups`\
        \ object is fully supported (previously returned a 500).\n\n**Requires permission:**\
        \ `sales_orders.delete`"
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 84213
                  message: Bulk delete started. Track progress using the returned
                    ID.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: orders:write
      operationId: delete-api-sales-orders-tracked
  /api/sales-orders:
    delete:
      tags:
      - Sales Orders
      summary: Bulk Delete Sales Orders
      description: "Bulk deletes sales orders in the background. IDs are resolved\
        \ either from an explicit `ids` array or from a `filters` payload, then chunked\
        \ (1000 per job) and dispatched as a job batch. Orders without return receipts\
        \ are deleted first; orders with return receipts are deleted in a second batch.\n\
        \n:::info[Required scope: `orders:write`]\nGrant this scope to your token\
        \ under [Settings → Developer → Personal Access Tokens](https://app.sku.io/settings/api).\n\
        :::\n\nAuthentication: Requires Bearer token.\n\nRequest body (scope: one\
        \ of `ids` or `filters` is required):\n- `ids` (array of int, required without\
        \ `filters`): Explicit sales order IDs to delete.\n- `filters` (object, required\
        \ without `ids`): Resolves to a list of sales order IDs via the same Spatie\
        \ QueryBuilder pipeline the V2 sales-orders list/export use. Two shapes are\
        \ accepted:\n  - Grouped filters (current list): `{ \\\"filter_groups\\\"\
        : \\\"<base64-encoded JSON tree>\\\" }`. The decoded tree looks like `{\\\"\
        conjunction\\\":\\\"and\\\",\\\"children\\\":[{\\\"type\\\":\\\"condition\\\
        \",\\\"condition\\\":{\\\"column\\\":\\\"order_status\\\",\\\"operator\\\"\
        :\\\"is\\\",\\\"value\\\":\\\"open\\\"}}]}`.\n  - legacy filter set (JSON\
        \ string) for older clients.\n- `apply_to_all` (bool, optional): When true\
        \ the action targets every order matching the active `filters` rather than\
        \ an explicit `ids` list.\n\nBehavior:\n- Returns 200 immediately; deletion\
        \ runs asynchronously via a background job batches.\n- Sending `filters` as\
        \ the grouped `filter_groups` object is fully supported (previously returned\
        \ a 500).\n\n**Requires permission:** `sales_orders.delete`"
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Sales orders are being deleted in the background.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: orders:write
      operationId: delete-api-sales-orders
    post:
      tags:
      - Sales Orders
      summary: Create Sales Order
      description: 'Creates a sales order, optionally with an embedded customer, shipping/billing
        addresses, line items, line-level discounts, and financial lines (shipping,
        fees, etc.). Orders can be created as drafts and approved later, or opened
        immediately.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Request body fields:

        - order_status (string, required): One of `draft`, `reserved`, `open`, `closed`.
        Line items are required unless the status is `draft`. When `closed`, `fulfilled_at`
        becomes required.

        - order_date (date-time, required): Order placement date. If the value parses
        to today''s date (a date-only value from a date picker), it is replaced with
        the exact current timestamp so the order reflects when it was actually placed.
        Back-dated or forward-dated values are kept as sent.

        - currency_id (integer, required without currency_code): Currency record ID.

        - currency_code (string, required without currency_id): ISO currency code,
        e.g. `USD`.

        - sales_order_number (string, optional, max 255): Must be unique within the
        sales channel. Auto-generated from your order-number settings when omitted.

        - customer_po_number (string, optional, max 255): The customer''s own purchase-order
        reference.

        - store_id (integer, optional) / store_name (string, optional): Store to attribute
        the order to.

        - sales_channel_id (integer, optional): Sales channel the order belongs to;
        defaults to the local channel.

        - shipping_method_id (integer, optional), requested_shipping_method (string,
        optional, max 255).

        - customer_id (integer, optional): Existing customer ID. Alternatively send
        the `customer` object below.

        - sales_rep_id (integer, optional) / sales_rep_name (string, optional, max
        255): Provide at most one; a new sales rep is created from the name if it
        doesn''t exist.

        - shipping_address_id / billing_address_id (integer, optional): Existing address
        IDs; each must belong to the order''s customer.

        - payment_status (string, optional): `unpaid`, `partially_paid`, `paid`, `refunded`.

        - payment_date, ship_by_date, hold_until_date (do-not-ship-before release
        date), deliver_by_date, packing_slip_printed_at (dates, optional).

        - fulfilled_at (date, required when order_status is `closed`), tracking_number
        (string, optional, max 255; only accepted when order_status is `closed`).

        - discount (number, optional, < 1,000,000): Order-level discount amount.

        - is_tax_included (boolean, optional): Whether line amounts already include
        tax.

        - tax_rate_id (number, optional).

        - tags (array of strings, optional).

        - memo_for_customer (string, optional, max 65,535).

        - custom_field_values (array, optional): Custom field values keyed by custom
        field.


        sales_order_lines (array; required unless order_status is `draft`). Duplicate
        lines are rejected — every line must be unique by product/SKU + sales_channel_line_id
        + description + quantity + amount + bundle_id; provide a `sales_channel_line_id`
        per line for channel-sourced orders. Each line:

        - description (string, required, max 255)

        - product_id (integer, optional) or sku (string, optional): Identifies the
        product; omit both for a non-product line.

        - amount (number, required, < 100,000,000): Unit price.

        - quantity (number, required, >= 0 and < 100,000)

        - canceled_quantity (number, required when quantity is 0)

        - externally_fulfilled_quantity (number, optional)

        - tax_rate_id (number, optional)

        - sales_channel_line_id (optional): The channel''s own line identifier.

        - nominal_code_id / nominal_code_name / nominal_code (optional): Ledger code
        by ID, name, or code.

        - is_product (boolean, optional)

        - warehouse_routing_method (string, optional): `dropship`, `warehouse`, `advanced`,
        or `unassigned`.

        - warehouse_id (integer, optional; required when warehouse_routing_method
        is `warehouse`)

        - bundle_id (integer, optional): Parent bundle product ID when the line is
        a bundle component.

        - subscription_edition_id (integer, optional): Subscription edition to allocate
        from; edition allocation limits are enforced.

        - line_discounts (array, optional): Each with name (string, required, max
        255), type (required: `percentage` or `fixed_amount`), rate (number 0-100,
        optional), amount (number >= 0, optional), scope (optional, `line`).


        financial_lines (array, optional). Each line:

        - financial_line_type_id (integer, optional), nominal_code_id (integer, optional),
        description (string, optional), quantity (number, optional, >= 0), amount
        (number, optional), tax_allocation (number, optional), allocate_to_products
        (boolean, optional), proration_strategy (string, optional: `revenue_based`,
        `cost_based`, `weight_based`, `volume_based`, `quantity_based`, `specific_line`,
        `manual`), allocate_to_id (integer, optional: sales order line ID to allocate
        to), allocate_to_type (string, optional).


        discount_lines (array, optional): Each with name (string, required, max 255),
        rate (number, optional), amount (number, optional).


        tax_lines (array, optional): Each with name (string, required, max 255), rate
        (number, optional).


        customer (object, optional): company, name, email, phone, fax, address1, address2,
        address3, city, province, province_code, zip, country, country_code (valid
        ISO country code), label — all optional strings (max 255).


        shipping_address / billing_address (objects, optional): company, name, email,
        phone, fax, address1, address2, address3, city, province, province_code, zip,
        county, country_code (valid ISO country code), label — all optional strings
        (max 255).


        Returns the complete created order, including lines, fulfillment state, totals,
        and addresses. Returns 400 when a line''s warehouse routing cannot resolve
        a valid warehouse for the product.


        **Requires permission:** `sales_orders.create`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                order_status:
                  type: string
                order_date:
                  type: string
                currency_code:
                  type: string
                customer_po_number:
                  type: string
                store_id:
                  type: integer
                shipping_method_id:
                  type: integer
                ship_by_date:
                  type: string
                is_tax_included:
                  type: boolean
                tags:
                  type: array
                  items:
                    type: string
                memo_for_customer:
                  type: string
                customer:
                  type: object
                  properties:
                    name:
                      type: string
                    email:
                      type: string
                    phone:
                      type: string
                    company:
                      type: string
                      nullable: true
                shipping_address:
                  type: object
                  properties:
                    name:
                      type: string
                    phone:
                      type: string
                    address1:
                      type: string
                    address2:
                      type: string
                    city:
                      type: string
                    province:
                      type: string
                    province_code:
                      type: string
                    zip:
                      type: string
                    country_code:
                      type: string
                billing_address:
                  type: object
                  properties:
                    name:
                      type: string
                    phone:
                      type: string
                    address1:
                      type: string
                    address2:
                      type: string
                    city:
                      type: string
                    province:
                      type: string
                    province_code:
                      type: string
                    zip:
                      type: string
                    country_code:
                      type: string
                sales_order_lines:
                  type: array
                  items:
                    type: object
                    properties:
                      description:
                        type: string
                      sku:
                        type: string
                      quantity:
                        type: integer
                      amount:
                        type: number
                      is_product:
                        type: boolean
                      warehouse_routing_method:
                        type: string
                financial_lines:
                  type: array
                  items:
                    type: object
                    properties:
                      description:
                        type: string
                      financial_line_type_id:
                        type: integer
                      quantity:
                        type: integer
                      amount:
                        type: number
                incoterm_id:
                  type: integer
                incoterm_place:
                  type: string
                incoterm_version:
                  type: integer
              example:
                order_status: open
                order_date: '2026-07-06 10:15:00'
                currency_code: USD
                customer_po_number: PO-88213
                store_id: 1
                shipping_method_id: 7
                ship_by_date: '2026-07-07'
                is_tax_included: false
                tags:
                - wholesale
                memo_for_customer: Thank you for your order!
                customer:
                  name: Jane Cooper
                  email: jane.cooper@example.com
                  phone: +1 555-201-4477
                  company: null
                shipping_address:
                  name: Jane Cooper
                  phone: +1 555-201-4477
                  address1: 982 Maple Avenue
                  address2: Apt 4B
                  city: Portland
                  province: Oregon
                  province_code: OR
                  zip: '97205'
                  country_code: US
                billing_address:
                  name: Jane Cooper
                  phone: +1 555-201-4477
                  address1: 982 Maple Avenue
                  address2: Apt 4B
                  city: Portland
                  province: Oregon
                  province_code: OR
                  zip: '97205'
                  country_code: US
                sales_order_lines:
                - description: Stainless Steel Water Bottle 32oz - Ocean Blue
                  sku: WB-32-BLU
                  quantity: 2
                  amount: 25.99
                  is_product: true
                  warehouse_routing_method: advanced
                - description: Bottle Cleaning Brush Kit
                  sku: BR-KIT-01
                  quantity: 1
                  amount: 9.5
                  is_product: true
                  line_discounts:
                  - name: Bundle discount
                    type: percentage
                    rate: 10
                financial_lines:
                - description: Shipping
                  financial_line_type_id: 2
                  quantity: 1
                  amount: 6.99
                incoterm_id: 12
                incoterm_place: Port of Los Angeles, CA
                incoterm_version: 2020
      parameters: []
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      sales_order_number:
                        type: string
                      customer_po_number:
                        type: string
                      sales_channel_id:
                        type: integer
                      sales_channel_name:
                        type: string
                      sub_sales_channel_id:
                        type: string
                        nullable: true
                      sub_sales_channel:
                        type: string
                        nullable: true
                      sub_sales_channel_name:
                        type: string
                        nullable: true
                      integration_instance_id:
                        type: integer
                      integration:
                        type: string
                      integration_id:
                        type: integer
                      integration_image:
                        type: string
                      can_submit_fulfillments_to_channel:
                        type: boolean
                      store:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      sales_rep_id:
                        type: string
                        nullable: true
                      sales_rep:
                        type: string
                        nullable: true
                      accounting:
                        type: object
                        properties:
                          transaction:
                            type: string
                            nullable: true
                      order_date:
                        type: string
                      payment_date:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                      canceled_at:
                        type: string
                        nullable: true
                      currency:
                        type: string
                      currency_rate:
                        type: integer
                      discount_lines:
                        type: string
                        nullable: true
                      discounts:
                        type: array
                      order_discounts:
                        type: string
                        nullable: true
                      line_discount_total:
                        type: integer
                      order_discount_total:
                        type: integer
                      total_discount_amount:
                        type: integer
                      apply_order_discount_on:
                        type: string
                        nullable: true
                      tax_lines:
                        type: string
                        nullable: true
                      packing_slip_printed_at:
                        type: string
                        nullable: true
                      is_fba:
                        type: boolean
                      is_replacement_order:
                        type: boolean
                      need_mapping:
                        type: boolean
                      memo_for_customer:
                        type: string
                        nullable: true
                      reserved_at:
                        type: string
                        nullable: true
                      payment_hold_status:
                        type: string
                        nullable: true
                      reservation_expires_at:
                        type: string
                        nullable: true
                      ship_by_date:
                        type: string
                      hold_until_date:
                        type: string
                        nullable: true
                      is_held:
                        type: boolean
                      deliver_by_date:
                        type: string
                        nullable: true
                      fulfilled_at:
                        type: string
                        nullable: true
                      shipping_method_id:
                        type: integer
                      shipping_method:
                        type: string
                      is_pickup:
                        type: boolean
                      shipped_is_pickup:
                        type: boolean
                      address_check:
                        type: object
                        properties:
                          has_warning:
                            type: boolean
                          has_block:
                            type: boolean
                          highest_severity:
                            type: string
                          warnings:
                            type: array
                            items:
                              type: object
                              properties:
                                rule_id:
                                  type: string
                                severity:
                                  type: string
                                message:
                                  type: string
                      requested_shipping_method:
                        type: string
                      mapped_shipping_method:
                        type: string
                      has_backorder:
                        type: boolean
                      fulfillment:
                        type: array
                      fulfillment_channel:
                        type: string
                        nullable: true
                      customer_name:
                        type: object
                        properties:
                          id:
                            type: string
                            nullable: true
                          name:
                            type: string
                      customer_email:
                        type: string
                      customer_company:
                        type: string
                        nullable: true
                      customer_phone:
                        type: string
                      sales_order_shipping_address:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          email:
                            type: string
                          company:
                            type: string
                            nullable: true
                          phone:
                            type: string
                          address1:
                            type: string
                          address2:
                            type: string
                          address3:
                            type: string
                            nullable: true
                          city:
                            type: string
                          province:
                            type: string
                          province_code:
                            type: string
                          zip:
                            type: string
                          country:
                            type: string
                          country_code:
                            type: string
                      shipping_overridden_at:
                        type: string
                        nullable: true
                      is_shipping_overridden:
                        type: boolean
                      sales_order_billing_address:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          email:
                            type: string
                          company:
                            type: string
                            nullable: true
                          phone:
                            type: string
                          address1:
                            type: string
                          address2:
                            type: string
                          address3:
                            type: string
                            nullable: true
                          city:
                            type: string
                          province:
                            type: string
                          province_code:
                            type: string
                          zip:
                            type: string
                          country:
                            type: string
                          country_code:
                            type: string
                      item_info:
                        type: array
                        items:
                          type: object
                          properties:
                            sales_order_line_id:
                              type: integer
                            sales_channel_line_id:
                              type: string
                              nullable: true
                            bundle_quantity_cache:
                              type: string
                              nullable: true
                            unit_cost:
                              type: number
                            tax_rate:
                              type: integer
                            tax_rate_id:
                              type: string
                              nullable: true
                            item_tax_value:
                              type: integer
                            fifo_layer_id:
                              type: string
                              nullable: true
                            item_quantity:
                              type: integer
                            item_canceled_quantity:
                              type: integer
                            item_allocated_quantity:
                              type: integer
                            item_on_hand_allocated_quantity:
                              type: integer
                            item_unallocated_quantity:
                              type: integer
                            sales_channel_fulfillment_out_of_sync:
                              type: boolean
                            item_externally_fulfilled_quantity:
                              type: integer
                            fulfilled_quantity:
                              type: integer
                            submitted_quantity:
                              type: integer
                            item_dropshipped_quantity:
                              type: integer
                            item_sku:
                              type: object
                              properties:
                                id:
                                  type: integer
                                sku:
                                  type: string
                            item_bundle_sku:
                              type: string
                              nullable: true
                            item_barcode:
                              type: string
                            item_weight:
                              type: number
                            item_weight_unit:
                              type: string
                            item_brand:
                              type: object
                              properties:
                                id:
                                  type: integer
                                name:
                                  type: string
                            bundle:
                              type: string
                              nullable: true
                            bundle_proration_basis:
                              type: string
                              nullable: true
                            item_price:
                              type: number
                            item_price_with_tax:
                              type: number
                            item_name:
                              type: string
                            item_nominal_code_id:
                              type: string
                              nullable: true
                            item_nominal_code:
                              type: string
                              nullable: true
                            item_nominal_code_code:
                              type: string
                              nullable: true
                            item_discount:
                              type: integer
                            item_line_discounts:
                              type: array
                            item_line_discount_total:
                              type: integer
                            item_net_total:
                              type: number
                            price_after_line_discount:
                              type: number
                            line_discount_total:
                              type: integer
                            allocated_order_discount:
                              type: integer
                            net_total:
                              type: number
                            item_has_backorder:
                              type: boolean
                            allocation_locked:
                              type: boolean
                            allocation_locked_reason:
                              type: string
                              nullable: true
                            is_product:
                              type: boolean
                            is_bundle:
                              type: boolean
                            is_variation:
                              type: boolean
                            credited_quantity:
                              type: integer
                            credit_sources:
                              type: array
                              items:
                                type: object
                                properties:
                                  vendor_credit_id:
                                    type: integer
                                  vendor_credit_number:
                                    type: string
                                  quantity:
                                    type: integer
                                  credit_status:
                                    type: string
                                  restock_inventory:
                                    type: boolean
                            warehouse_routing_method:
                              type: string
                            warehouse:
                              type: object
                              properties:
                                id:
                                  type: integer
                                name:
                                  type: string
                                supplier_id:
                                  type: string
                                  nullable: true
                                supplier_name:
                                  type: string
                                  nullable: true
                            is_fulfilled:
                              type: boolean
                            no_audit_trail:
                              type: boolean
                            unfulfilled_quantity:
                              type: integer
                            remaining_to_fulfill_quantity:
                              type: integer
                            available_to_fulfill:
                              type: integer
                            committed_to_fulfillment_quantity:
                              type: integer
                            returnable_quantity:
                              type: integer
                            inventory_allocation_id:
                              type: integer
                            backordered_quantity:
                              type: integer
                            listing:
                              type: string
                              nullable: true
                            channel_product_external_id:
                              type: string
                              nullable: true
                            sales_channel_product_id:
                              type: string
                              nullable: true
                            subscription_edition_id:
                              type: string
                              nullable: true
                            subscription_edition:
                              type: string
                              nullable: true
                            subscription_offering:
                              type: string
                              nullable: true
                            created_at:
                              type: string
                            updated_at:
                              type: string
                            cogs:
                              type: string
                              nullable: true
                            estimated_decoration_cost:
                              type: integer
                            actual_decoration_cost:
                              type: integer
                            decoration_cost_breakdown:
                              type: string
                              nullable: true
                            is_taxable:
                              type: boolean
                            default_tax_rate_id:
                              type: string
                              nullable: true
                            item_img_url:
                              type: string
                            item_inventory:
                              type: object
                              properties:
                                total:
                                  type: object
                                  properties:
                                    inbound:
                                      type: integer
                                    stock:
                                      type: integer
                                    allocated:
                                      type: integer
                                    on_hold:
                                      type: integer
                                    available:
                                      type: integer
                                    in_transit:
                                      type: integer
                                warehouses:
                                  type: object
                                  properties:
                                    Main Warehouse:
                                      type: object
                                      properties:
                                        inbound:
                                          type: integer
                                        stock:
                                          type: integer
                                        allocated:
                                          type: integer
                                        on_hold:
                                          type: integer
                                        available:
                                          type: integer
                                        supplier_in_stock:
                                          type: string
                                          nullable: true
                                        in_transit:
                                          type: integer
                                        warehouse_id:
                                          type: integer
                                        warehouse_name:
                                          type: string
                                        warehouse_type:
                                          type: string
                                        supplier:
                                          type: string
                                          nullable: true
                                        country_code:
                                          type: string
                            item_stock:
                              type: integer
                      purchase_orders:
                        type: array
                      adjustments:
                        type: array
                      financial_lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            description:
                              type: string
                            quantity:
                              type: integer
                            amount:
                              type: number
                            extended_amount:
                              type: number
                            discount_rate:
                              type: integer
                            amount_in_tenant_currency:
                              type: number
                            tax_allocation:
                              type: integer
                            tax_allocation_in_tenant_currency:
                              type: integer
                            tax_rate_id:
                              type: string
                              nullable: true
                            tax_rate:
                              type: string
                              nullable: true
                            allocate_to_products:
                              type: boolean
                            proration_strategy:
                              type: string
                              nullable: true
                            allocate_to_id:
                              type: string
                              nullable: true
                            allocate_to_type:
                              type: string
                              nullable: true
                            link_type:
                              type: string
                              nullable: true
                            link_id:
                              type: string
                              nullable: true
                            financial_line_type:
                              type: object
                              properties:
                                id:
                                  type: integer
                                name:
                                  type: string
                                classification:
                                  type: string
                                nominal_code_id:
                                  type: integer
                            nominal_code:
                              type: object
                              properties:
                                id:
                                  type: integer
                                name:
                                  type: string
                                code:
                                  type: string
                            credited_amount:
                              type: integer
                            remaining_amount:
                              type: number
                      custom_field_values:
                        type: array
                      order_status:
                        type: string
                      fulfillment_status:
                        type: string
                      fulfillment_sequence:
                        type: string
                        nullable: true
                      payment_status:
                        type: string
                      tax_revenue:
                        type: number
                      product_total:
                        type: number
                      total:
                        type: number
                      discount_total:
                        type: number
                      currency_code:
                        type: string
                      tags:
                        type: array
                        items:
                          type: string
                      warehouses:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            supplier_id:
                              type: string
                              nullable: true
                            supplier_name:
                              type: string
                              nullable: true
                      can_fulfill:
                        type: boolean
                      exact_discount_total:
                        type: number
                      is_tax_included:
                        type: boolean
                      tax_total:
                        type: number
                      calculated_tax_total:
                        type: number
                      exact_tax_total:
                        type: number
                      tax_rate_id:
                        type: string
                        nullable: true
                      tax_rate:
                        type: string
                        nullable: true
                      payments:
                        type: array
                      notes:
                        type: array
                      earliest_covered_ship_by_date:
                        type: string
                        nullable: true
                      latest_covered_ship_by_date:
                        type: string
                        nullable: true
                      has_backorder_lines:
                        type: boolean
                example:
                  message: The sales order created successfully
                  data:
                    id: 612
                    sales_order_number: SO-01043
                    customer_po_number: PO-88213
                    sales_channel_id: 3
                    sales_channel_name: Shopify - Main Store
                    sub_sales_channel_id: null
                    sub_sales_channel: null
                    sub_sales_channel_name: null
                    integration_instance_id: 2
                    integration: Shopify
                    integration_id: 4
                    integration_image: https://cdn.sku.io/integrations/shopify.png
                    can_submit_fulfillments_to_channel: true
                    store:
                      id: 1
                      name: Main Store
                    sales_rep_id: null
                    sales_rep: null
                    accounting:
                      transaction: null
                    order_date: '2026-07-06T10:15:00.000000Z'
                    payment_date: null
                    created_at: '2026-07-06T10:15:01.000000Z'
                    updated_at: '2026-07-06T10:15:01.000000Z'
                    archived_at: null
                    canceled_at: null
                    currency: USD
                    currency_rate: 1
                    discount_lines: null
                    discounts: []
                    order_discounts: null
                    line_discount_total: 0
                    order_discount_total: 0
                    total_discount_amount: 0
                    apply_order_discount_on: null
                    tax_lines: null
                    packing_slip_printed_at: null
                    is_fba: false
                    is_replacement_order: false
                    need_mapping: false
                    memo_for_customer: null
                    reserved_at: null
                    payment_hold_status: null
                    reservation_expires_at: null
                    ship_by_date: '2026-06-19T00:00:00.000000Z'
                    hold_until_date: null
                    is_held: false
                    deliver_by_date: null
                    fulfilled_at: null
                    shipping_method_id: 7
                    shipping_method: USPS Priority Mail
                    is_pickup: false
                    shipped_is_pickup: false
                    address_check:
                      has_warning: true
                      has_block: false
                      highest_severity: warning
                      warnings:
                      - rule_id: missing-required
                        severity: warning
                        message: Shipping address is missing required fields (name,
                          street, city, postcode or country).
                    requested_shipping_method: Standard Shipping
                    mapped_shipping_method: USPS Priority Mail
                    has_backorder: false
                    fulfillment: []
                    fulfillment_channel: null
                    customer_name:
                      id: null
                      name: Jane Cooper
                    customer_email: jane.cooper@example.com
                    customer_company: null
                    customer_phone: +1 555-201-4477
                    sales_order_shipping_address:
                      id: 1201
                      name: Jane Cooper
                      email: jane.cooper@example.com
                      company: null
                      phone: +1 555-201-4477
                      address1: 982 Maple Avenue
                      address2: Apt 4B
                      address3: null
                      city: Portland
                      province: Oregon
                      province_code: OR
                      zip: '97205'
                      country: United States
                      country_code: US
                    shipping_overridden_at: null
                    is_shipping_overridden: false
                    sales_order_billing_address:
                      id: 1202
                      name: Jane Cooper
                      email: jane.cooper@example.com
                      company: null
                      phone: +1 555-201-4477
                      address1: 982 Maple Avenue
                      address2: Apt 4B
                      address3: null
                      city: Portland
                      province: Oregon
                      province_code: OR
                      zip: '97205'
                      country: United States
                      country_code: US
                    item_info:
                    - sales_order_line_id: 2310
                      sales_channel_line_id: null
                      bundle_quantity_cache: null
                      unit_cost: 11.42
                      tax_rate: 0
                      tax_rate_id: null
                      item_tax_value: 0
                      fifo_layer_id: null
                      item_quantity: 2
                      item_canceled_quantity: 0
                      item_allocated_quantity: 2
                      item_on_hand_allocated_quantity: 2
                      item_unallocated_quantity: 0
                      sales_channel_fulfillment_out_of_sync: false
                      item_externally_fulfilled_quantity: 0
                      fulfilled_quantity: 0
                      submitted_quantity: 0
                      item_dropshipped_quantity: 0
                      item_sku:
                        id: 812
                        sku: WB-32-BLU
                      item_bundle_sku: null
                      item_barcode: 0812345678905
                      item_weight: 1.2
                      item_weight_unit: lb
                      item_brand:
                        id: 14
                        name: HydraPeak
                      bundle: null
                      bundle_proration_basis: null
                      item_price: 25.99
                      item_price_with_tax: 25.99
                      item_name: Stainless Steel Water Bottle 32oz - Ocean Blue
                      item_nominal_code_id: null
                      item_nominal_code: null
                      item_nominal_code_code: null
                      item_discount: 0
                      item_line_discounts: []
                      item_line_discount_total: 0
                      item_net_total: 51.98
                      price_after_line_discount: 25.99
                      line_discount_total: 0
                      allocated_order_discount: 0
                      net_total: 51.98
                      item_has_backorder: false
                      allocation_locked: false
                      allocation_locked_reason: null
                      is_product: true
                      is_bundle: false
                      is_variation: false
                      credited_quantity: 0
                      credit_sources:
                      - vendor_credit_id: 42
                        vendor_credit_number: VC-1001
                        quantity: 5
                        credit_status: open
                        restock_inventory: false
                      warehouse_routing_method: advanced
                      warehouse:
                        id: 3
                        name: Main Warehouse
                        supplier_id: null
                        supplier_name: null
                      is_fulfilled: false
                      no_audit_trail: false
                      unfulfilled_quantity: 2
                      remaining_to_fulfill_quantity: 2
                      available_to_fulfill: 2
                      committed_to_fulfillment_quantity: 0
                      returnable_quantity: 0
                      inventory_allocation_id: 5120
                      backordered_quantity: 0
                      listing: null
                      channel_product_external_id: null
                      sales_channel_product_id: null
                      subscription_edition_id: null
                      subscription_edition: null
                      subscription_offering: null
                      created_at: '2026-06-18T14:23:15.000000Z'
                      updated_at: '2026-06-19T16:40:21.000000Z'
                      cogs: null
                      estimated_decoration_cost: 0
                      actual_decoration_cost: 0
                      decoration_cost_breakdown: null
                      is_taxable: true
                      default_tax_rate_id: null
                      item_img_url: https://cdn.sku.io/products/wb-32-blu.jpg
                      item_inventory:
                        total:
                          inbound: 24
                          stock: 150
                          allocated: 2
                          on_hold: 0
                          available: 148
                          in_transit: 0
                        warehouses:
                          Main Warehouse:
                            inbound: 24
                            stock: 150
                            allocated: 2
                            on_hold: 0
                            available: 148
                            supplier_in_stock: null
                            in_transit: 0
                            warehouse_id: 3
                            warehouse_name: Main Warehouse
                            warehouse_type: standard
                            supplier: null
                            country_code: US
                      item_stock: 148
                    - sales_order_line_id: 2102
                      sales_channel_line_id: null
                      bundle_quantity_cache: null
                      unit_cost: 3.8
                      tax_rate: 0
                      tax_rate_id: null
                      item_tax_value: 0
                      fifo_layer_id: null
                      item_quantity: 1
                      item_canceled_quantity: 0
                      item_allocated_quantity: 1
                      item_on_hand_allocated_quantity: 1
                      item_unallocated_quantity: 0
                      sales_channel_fulfillment_out_of_sync: false
                      item_externally_fulfilled_quantity: 0
                      fulfilled_quantity: 1
                      submitted_quantity: 0
                      item_dropshipped_quantity: 0
                      item_sku:
                        id: 954
                        sku: BR-KIT-01
                      item_bundle_sku: null
                      item_barcode: 0812345671231
                      item_weight: 0.3
                      item_weight_unit: lb
                      item_brand:
                        id: 14
                        name: HydraPeak
                      bundle: null
                      bundle_proration_basis: null
                      item_price: 9.5
                      item_price_with_tax: 9.5
                      item_name: Bottle Cleaning Brush Kit
                      item_nominal_code_id: null
                      item_nominal_code: null
                      item_nominal_code_code: null
                      item_discount: 0
                      item_line_discounts: []
                      item_line_discount_total: 0
                      item_net_total: 9.5
                      price_after_line_discount: 9.5
                      line_discount_total: 0
                      allocated_order_discount: 0
                      net_total: 9.5
                      item_has_backorder: false
                      allocation_locked: false
                      allocation_locked_reason: null
                      is_product: true
                      is_bundle: false
                      is_variation: false
                      credited_quantity: 0
                      credit_sources:
                      - vendor_credit_id: 42
                        vendor_credit_number: VC-1001
                        quantity: 5
                        credit_status: open
                        restock_inventory: false
                      warehouse_routing_method: advanced
                      warehouse:
                        id: 3
                        name: Main Warehouse
                        supplier_id: null
                        supplier_name: null
                      is_fulfilled: true
                      no_audit_trail: false
                      unfulfilled_quantity: 0
                      remaining_to_fulfill_quantity: 0
                      available_to_fulfill: 0
                      committed_to_fulfillment_quantity: 0
                      returnable_quantity: 1
                      inventory_allocation_id: 5121
                      backordered_quantity: 0
                      listing: null
                      channel_product_external_id: null
                      sales_channel_product_id: null
                      subscription_edition_id: null
                      subscription_edition: null
                      subscription_offering: null
                      created_at: '2026-06-18T14:23:15.000000Z'
                      updated_at: '2026-06-19T16:40:21.000000Z'
                      cogs:
                        base_unit_cost: 3.8
                        cost_lines_total: 0
                        cost_lines: []
                        landed_costs_total: 0
                        landed_costs: []
                        unallocated_total: 0
                        unallocated: []
                        fifo_layers:
                        - fifo_layer_id: 3312
                          fifo_layer_date: '2026-05-02'
                          quantity: 1
                          source_label: PO Receipt
                          source_id: 1207
                          unit_cost: 3.8
                        total_cost: 3.8
                        unit_cost: 3.8
                        is_finalized: true
                      estimated_decoration_cost: 0
                      actual_decoration_cost: 0
                      decoration_cost_breakdown: null
                      is_taxable: true
                      default_tax_rate_id: null
                      item_img_url: https://cdn.sku.io/products/br-kit-01.jpg
                      item_inventory:
                        total:
                          inbound: 0
                          stock: 61
                          allocated: 1
                          on_hold: 0
                          available: 60
                          in_transit: 0
                        warehouses:
                          Main Warehouse:
                            inbound: 0
                            stock: 61
                            allocated: 1
                            on_hold: 0
                            available: 60
                            supplier_in_stock: null
                            in_transit: 0
                            warehouse_id: 3
                            warehouse_name: Main Warehouse
                            warehouse_type: standard
                            supplier: null
                            country_code: US
                      item_stock: 60
                    purchase_orders: []
                    adjustments: []
                    financial_lines:
                    - id: 610
                      description: Shipping
                      quantity: 1
                      amount: 6.99
                      extended_amount: 6.99
                      discount_rate: 0
                      amount_in_tenant_currency: 6.99
                      tax_allocation: 0
                      tax_allocation_in_tenant_currency: 0
                      tax_rate_id: null
                      tax_rate: null
                      allocate_to_products: false
                      proration_strategy: null
                      allocate_to_id: null
                      allocate_to_type: null
                      link_type: null
                      link_id: null
                      financial_line_type:
                        id: 2
                        name: Shipping
                        classification: revenue
                        nominal_code_id: 12
                      nominal_code:
                        id: 12
                        name: Shipping Income
                        code: '4020'
                      credited_amount: 0
                      remaining_amount: 6.99
                    custom_field_values: []
                    order_status: open
                    fulfillment_status: unfulfilled
                    fulfillment_sequence: null
                    payment_status: unpaid
                    tax_revenue: 4.11
                    product_total: 61.48
                    total: 63.08
                    discount_total: 0.95
                    currency_code: USD
                    tags:
                    - wholesale
                    warehouses:
                    - id: 3
                      name: Main Warehouse
                      supplier_id: null
                      supplier_name: null
                    can_fulfill: true
                    exact_discount_total: 0.95
                    is_tax_included: false
                    tax_total: 4.11
                    calculated_tax_total: 4.11
                    exact_tax_total: 4.11
                    tax_rate_id: null
                    tax_rate: null
                    payments: []
                    notes: []
                    earliest_covered_ship_by_date: null
                    latest_covered_ship_by_date: null
                    has_backorder_lines: false
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      resource:
                        type: string
                      sku:
                        type: string
                example:
                  message: No valid warehouse could be routed for product WB-32-BLU.
                  errors:
                    resource: product
                    sku: WB-32-BLU
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      order_date:
                        type: array
                        items:
                          type: string
                      sales_order_lines.0.description:
                        type: array
                        items:
                          type: string
                example:
                  message: The given data was invalid.
                  errors:
                    order_date:
                    - The order date field is required.
                    sales_order_lines.0.description:
                    - The sales_order_lines.0.description field is required.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: orders:write
      operationId: post-api-sales-orders
  /api/sales-orders/bulk-email:
    post:
      tags:
      - Sales Orders
      summary: Bulk Email Customers About Orders
      description: 'Dispatches a tracked background job that emails customers about
        their selected sales orders. Multiple orders for the same customer (same store
        + email, case-insensitive) are grouped into a single email (Cin7 Omni model).
        Recipients without a resolvable email and opted-out customers are suppressed.
        The send is capped at `config(''mail.bulk_sales_order_recipient_cap'')` distinct
        recipients (default 5000); overflow recipients are reported via the job''s
        `skipped_overflow` result and a warning log — never silently dropped. Every
        send is written to the order''s activity log under one batch.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Request body (scope: one of `ids` or `filters` is required):

        - `ids` (array of int, required without `filters`): Sales order IDs to email
        about.

        - `filters` (object, required without `ids`): Filter set that resolves to
        a list of sales order IDs (same shape used by the V2 sales-orders listing
        endpoint). It accepts the grouped `filter_groups` shape (`{ \"filter_groups\":
        \"<base64 JSON>\" }`, same as the V2 list) as well as the legacy JSON-string
        filter set. Combine with `apply_to_all`.

        - `apply_to_all` (bool, optional): When true, the action targets every order
        matching the active `filters` rather than an explicit `ids` list.

        - `template_id` (int|null, optional): The `bulk_sales_order` store email template
        the content was loaded from. Null when the body was composed ad hoc.

        - `subject` (string, required, max 998): Email subject. Supports `{{customer_name}}`,
        `{{order_count}}`, `{{store_name}}` tokens.

        - `html_body` (string, required): Email body HTML. Supports the same tokens
        plus `{{orders_table}}` (renders the customer''s grouped orders as a table).

        - `cc` (array of email, optional, max 25): CC addresses added to every email.

        - `attachments` (array of string, optional, max 25): Attachable-document keys
        to include (e.g. `["invoice_pdf"]`).

        - `group_by_customer` (bool, optional, default true): Group every selected
        order for one customer (same store + email) into a single email (Cin7 Omni
        model). When false, one email per order.

        - `skip_without_email` (bool, optional, default true): Orders with no resolvable
        email are always skipped. Must be true — sending `false` is rejected (422).

        - `respect_opt_out` (bool, optional, default true): Skip customers flagged
        `email_opt_out`.


        Behavior:

        - Returns immediately with the tracked job log ID; poll job progress via the
        tracked job log endpoints (job name `Bulk Email Sales Orders`).

        - The job records per-recipient sent/skipped/failed counts and an `activity_batch_uuid`
        in its results.

        - The job has `tries = 1` and never auto-retries (prevents double-sends).


        **Requires permission:** `sales_orders.update`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
                template_id:
                  type: integer
                subject:
                  type: string
                html_body:
                  type: string
                cc:
                  type: array
                  items:
                    type: string
                attachments:
                  type: array
                  items:
                    type: string
                group_by_customer:
                  type: boolean
                skip_without_email:
                  type: boolean
                respect_opt_out:
                  type: boolean
              example:
                ids:
                - 7116
                - 7117
                - 7118
                template_id: 42
                subject: An update on your orders, {{customer_name}}
                html_body: <p>Hi {{customer_name}},</p><p>Here is a summary of your
                  recent orders:</p>{{orders_table}}
                cc:
                - ops@acme.com
                attachments:
                - invoice_pdf
                group_by_customer: true
                skip_without_email: true
                respect_opt_out: true
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 90210
                  message: Bulk email started for 2 customers (3 orders).
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      subject:
                        type: array
                        items:
                          type: string
                      skip_without_email:
                        type: array
                        items:
                          type: string
                example:
                  message: Orders without an email address are always skipped and
                    cannot be force-sent.
                  errors:
                    subject:
                    - An email subject is required.
                    skip_without_email:
                    - Orders without an email address are always skipped and cannot
                      be force-sent.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: orders:write
      operationId: post-api-sales-orders-bulk-email
  /api/sales-orders/bulk-email/preview:
    post:
      tags:
      - Sales Orders
      summary: Preview Bulk Customer Email
      description: 'Resolves and groups a bulk-email selection without sending anything,
        powering the confirmation dialog''s recipient summary and a masked sample
        render. Accepts the exact same body as `POST /sales-orders/bulk-email`.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Request body (scope: one of `ids` or `filters` is required):

        - `ids` (array of int, required without `filters`): Sales order IDs to email
        about.

        - `filters` (object, required without `ids`): Filter set that resolves to
        a list of sales order IDs (same shape used by the V2 sales-orders listing
        endpoint). Combine with `apply_to_all`.

        - `apply_to_all` (bool, optional): When true, the action targets every order
        matching the active `filters` rather than an explicit `ids` list.

        - `template_id` (int|null, optional): The `bulk_sales_order` store email template
        the content was loaded from. Null when the body was composed ad hoc.

        - `subject` (string, required, max 998): Email subject. Supports `{{customer_name}}`,
        `{{order_count}}`, `{{store_name}}` tokens.

        - `html_body` (string, required): Email body HTML. Supports the same tokens
        plus `{{orders_table}}` (renders the customer''s grouped orders as a table).

        - `cc` (array of email, optional, max 25): CC addresses added to every email.

        - `attachments` (array of string, optional, max 25): Attachable-document keys
        to include (e.g. `["invoice_pdf"]`).

        - `group_by_customer` (bool, optional, default true): Group every selected
        order for one customer (same store + email) into a single email (Cin7 Omni
        model). When false, one email per order.

        - `skip_without_email` (bool, optional, default true): Orders with no resolvable
        email are always skipped. Must be true — sending `false` is rejected (422).

        - `respect_opt_out` (bool, optional, default true): Skip customers flagged
        `email_opt_out`.


        Response data:

        - `order_count` (int): Total orders resolved from the selection.

        - `email_count` (int): Distinct emails that will be sent (after grouping +
        cap).

        - `skipped_no_email` (array of int): Order IDs with no resolvable email.

        - `skipped_opted_out` (array of int): Order IDs whose customer opted out.

        - `skipped_overflow` (int): Recipients beyond the cap that would be dropped.

        - `groups_preview` (array, max 50): Per-recipient summary with a masked `email`,
        `order_count`, and `order_numbers`.

        - `sample` (object|null): First group''s masked `recipient` plus the rendered
        `subject` and `body` HTML; null when no group is emailable.


        **Requires permission:** `sales_orders.update`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
                template_id:
                  type: integer
                subject:
                  type: string
                html_body:
                  type: string
                cc:
                  type: array
                  items:
                    type: string
                attachments:
                  type: array
                  items:
                    type: string
                group_by_customer:
                  type: boolean
                skip_without_email:
                  type: boolean
                respect_opt_out:
                  type: boolean
              example:
                ids:
                - 7116
                - 7117
                - 7118
                template_id: 42
                subject: An update on your orders, {{customer_name}}
                html_body: <p>Hi {{customer_name}},</p><p>Here is a summary of your
                  recent orders:</p>{{orders_table}}
                cc:
                - ops@acme.com
                attachments:
                - invoice_pdf
                group_by_customer: true
                skip_without_email: true
                respect_opt_out: true
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      order_count:
                        type: integer
                      email_count:
                        type: integer
                      skipped_no_email:
                        type: array
                        items:
                          type: integer
                      skipped_opted_out:
                        type: array
                        items:
                          type: integer
                      skipped_overflow:
                        type: integer
                      groups_preview:
                        type: array
                        items:
                          type: object
                          properties:
                            email:
                              type: string
                            order_count:
                              type: integer
                            order_numbers:
                              type: array
                              items:
                                type: string
                      sample:
                        type: object
                        properties:
                          recipient:
                            type: string
                          subject:
                            type: string
                          body:
                            type: string
                example:
                  data:
                    order_count: 3
                    email_count: 2
                    skipped_no_email:
                    - 7119
                    skipped_opted_out:
                    - 7120
                    skipped_overflow: 0
                    groups_preview:
                    - email: j***@acme.com
                      order_count: 2
                      order_numbers:
                      - SO-7116
                      - SO-7117
                    - email: s***@globex.com
                      order_count: 1
                      order_numbers:
                      - SO-7118
                    sample:
                      recipient: j***@acme.com
                      subject: An update on your orders, Jane Doe
                      body: <p>Hi Jane Doe,</p><p>Here is a summary of your recent
                        orders:</p><table class='et-sales-order-table'>...</table>
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: orders:write
      operationId: post-api-sales-orders-bulk-email-preview
  /api/sales-orders/{salesOrder}/fulfillments:
    get:
      tags:
      - Sales Orders
      summary: List Order Shipments
      description: 'Lists ALL shipments (SalesOrderFulfillments) for a sales order,
        used by the order''s Fulfillment tab. Includes VOIDED shipments: a voided
        shipment carries a non-null `voided_at` (plus `void_reason` and `voided_by`)
        and `status=canceled` — it was reversed and its fulfillment order reopened,
        but is kept for history. The UI buckets voided shipments into a read-only
        "Voided" filter and excludes them from the active lifecycle counts. Each shipment
        exposes its `fulfillment_lines`, warehouse, shipping method, tracking, and
        provider-sync timestamps.


        :::info[Required scope: `orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Sales-channel cross-links: each shipment exposes `sales_channel_fulfillment_link`
        — non-null only when the shipment originated from a sales channel (Shopify
        or Faire), discriminated by `channel`. For `channel: "shopify"` it carries
        a `fulfillment` object (deep-link to the Shopify Fulfillment detail page)
        and a `fulfillment_orders` array (deep-links to each related Shopify Fulfillment
        Order detail page); its `link_route` already includes the required `?filter[integration_instance_ids]=N`
        query param. For `channel: "faire"` it carries an `order` object (deep-link
        to the Faire order detail page) and a `shipments` array — one entry per package,
        since Faire splits an order into one label per box, each with its own `carrier`,
        `tracking_number`, and `shipping_type`. Every link object has `link_id`, `link_reference`,
        `link_type_label`, and a `link_route`. Manual / 3PL / FBA shipments return
        `null` for this field.


        Multi-parcel shipments: each shipment also exposes a `parcels` array — one
        entry per shipped carton. A single shipment can span multiple boxes, each
        with its own carrier tracking number; `tracking_number` is only the primary
        (first) carton, while `parcels` is the full deduped list with the primary
        first. Each entry has `tracking_number`, plus `delivery_status` and `carrier`
        when live delivery tracking is connected (otherwise null). Only the tracking
        numbers are exposed — there is no per-carton line-item breakdown, since carriers
        return tracking numbers with no item-to-carton mapping. Single-parcel shipments
        return a one-element `parcels` array.'
      parameters:
      - name: salesOrder
        in: path
        schema:
          type: integer
        required: true
        description: Sales order ID
        example: '123'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        fulfillment_number:
                          type: string
                        sales_order_id:
                          type: integer
                        fulfillment_order_id:
                          type: integer
                        fulfillment_type:
                          type: string
                        fulfillment_status:
                          type: string
                        status:
                          type: string
                        requested_shipping_method:
                          type: string
                        fulfilled_date:
                          type: string
                        tracking_number:
                          type: string
                        tracking_link:
                          type: string
                        warehouse:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            type:
                              type: string
                            supplier_id:
                              type: string
                              nullable: true
                            is_dropship:
                              type: boolean
                        warehouse_id:
                          type: integer
                        fulfilled_by:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        fulfilled_quantity:
                          type: integer
                        cost:
                          type: integer
                        voided_at:
                          type: string
                          nullable: true
                        void_reason:
                          type: string
                          nullable: true
                        voided_by:
                          type: string
                          nullable: true
                        fulfillment_lines:
                          type: array
                          items:
                            type: object
                            properties:
                              id:
                                type: integer
                              sales_order_line_id:
                                type: integer
                              quantity:
                                type: integer
                        sales_channel_fulfillment_link:
                          type: object
                          properties:
                            channel:
                              type: string
                            fulfillment:
                              type: object
                              properties:
                                link_id:
                                  type: integer
                                link_reference:
                                  type: string
                                link_type_label:
                                  type: string
                                link_route:
                                  type: string
                                status:
                                  type: string
                                status_label:
                                  type: string
                                tracking_company:
                                  type: string
                                tracking_number:
                                  type: string
                                tracking_url:
                                  type: string
                                items:
                                  type: array
                                  items:
                                    type: object
                                    properties:
                                      sku:
                                        type: string
                                      name:
                                        type: string
                                      quantity:
                                        type: integer
                                item_match:
                                  type: object
                                  properties:
                                    matches:
                                      type: boolean
                                    lines:
                                      type: array
                                      items:
                                        type: object
                                        properties:
                                          sku:
                                            type: string
                                          name:
                                            type: string
                                          our_qty:
                                            type: integer
                                          channel_qty:
                                            type: integer
                                          state:
                                            type: string
                            fulfillment_orders:
                              type: array
                              items:
                                type: object
                                properties:
                                  link_id:
                                    type: integer
                                  link_reference:
                                    type: string
                                  link_type_label:
                                    type: string
                                  link_route:
                                    type: string
                                  status:
                                    type: string
                                  status_label:
                                    type: string
                                  tracking_company:
                                    type: string
                                    nullable: true
                                  tracking_number:
                                    type: string
                                    nullable: true
                                  tracking_url:
                                    type: string
                                    nullable: true
                                  items:
                                    type: array
                                    items:
                                      type: object
                                      properties:
                                        sku:
                                          type: string
                                        name:
                                          type: string
                                        quantity:
                                          type: integer
                                  item_match:
                                    type: object
                                    properties:
                                      matches:
                                        type: boolean
                                      lines:
                                        type: array
                                        items:
                                          type: object
                                          properties:
                                            sku:
                                              type: string
                                            name:
                                              type: string
                                            our_qty:
                                              type: integer
                                            channel_qty:
                                              type: integer
                                            state:
                                              type: string
                        parcels:
                          type: array
                          items:
                            type: object
                            properties:
                              tracking_number:
                                type: string
                              delivery_status:
                                type: string
                              carrier:
                                type: string
                example:
                  data:
                  - id: 1002
                    fulfillment_number: SO-0123.2
                    sales_order_id: 123
                    fulfillment_order_id: 452
                    fulfillment_type: sales_channel
                    fulfillment_status: fulfilled
                    status: fulfilled
                    requested_shipping_method: Standard
                    fulfilled_date: '2026-06-10T14:22:00+00:00'
                    tracking_number: '9400100000000000000000'
                    tracking_link: https://tools.usps.com/go/TrackConfirmAction?tLabels=9400100000000000000000
                    warehouse:
                      id: 7
                      name: Main Warehouse
                      type: direct
                      supplier_id: null
                      is_dropship: false
                    warehouse_id: 7
                    fulfilled_by:
                      id: 5
                      name: John Smith
                    fulfilled_quantity: 1
                    cost: 0
                    voided_at: null
                    void_reason: null
                    voided_by: null
                    fulfillment_lines:
                    - id: 9002
                      sales_order_line_id: 55348
                      quantity: 1
                    sales_channel_fulfillment_link:
                      channel: shopify
                      fulfillment:
                        link_id: 8841
                        link_reference: '#63756.1'
                        link_type_label: Shopify Fulfillment
                        link_route: /integrations/shopify/fulfillments/8841?filter[integration_instance_ids]=2
                        status: success
                        status_label: Success
                        tracking_company: USPS
                        tracking_number: '9400111899223817365534'
                        tracking_url: https://tools.usps.com/go/TrackConfirmAction?tLabels=9400111899223817365534
                        items:
                        - sku: RWS20Z
                          name: Royal White Sturgeon Caviar - 2.0 oz
                          quantity: 1
                        item_match:
                          matches: true
                          lines:
                          - sku: RWS20Z
                            name: Royal White Sturgeon Caviar - 2.0 oz
                            our_qty: 1
                            channel_qty: 1
                            state: ok
                      fulfillment_orders:
                      - link_id: 14040
                        link_reference: '#6189571510390'
                        link_type_label: Shopify Fulfillment Order
                        link_route: /integrations/shopify/fulfillment-orders/14040?filter[integration_instance_ids]=2
                        status: closed
                        status_label: Closed
                        tracking_company: null
                        tracking_number: null
                        tracking_url: null
                        items:
                        - sku: RWS20Z
                          name: Royal White Sturgeon Caviar - 2.0 oz
                          quantity: 1
                        item_match:
                          matches: true
                          lines:
                          - sku: GIFTBOX-VARIETY
                            name: Variety Flight Gift Box
                            our_qty: 10
                            channel_qty: 1
                            state: bundle
                    parcels:
                    - tracking_number: '9400100000000000000000'
                      delivery_status: in_transit
                      carrier: USPS
                    - tracking_number: '9400100000000000000017'
                      delivery_status: delivered
                      carrier: USPS
                  - id: 1001
                    fulfillment_number: SO-0123.1
                    sales_order_id: 123
                    fulfillment_order_id: 451
                    fulfillment_type: starshipit
                    fulfillment_status: submitted
                    status: submitted
                    requested_shipping_method: UPS Ground
                    fulfilled_date: null
                    tracking_number: null
                    tracking_link: null
                    warehouse:
                      id: 7
                      name: Main Warehouse
                      type: direct
                      supplier_id: null
                      is_dropship: false
                    warehouse_id: 7
                    fulfilled_by:
                      id: 5
                      name: John Smith
                    fulfilled_quantity: 2
                    cost: 0
                    voided_at: null
                    void_reason: null
                    voided_by: null
                    fulfillment_lines:
                    - id: 9001
                      sales_order_line_id: 55347
                      quantity: 2
                    sales_channel_fulfillment_link: null
                    parcels:
                    - tracking_number: '9400100000000000000000'
                      delivery_status: in_transit
                      carrier: USPS
                    - tracking_number: '9400100000000000000017'
                      delivery_status: delivered
                      carrier: USPS
                  - id: 1000
                    fulfillment_number: SO-0123.0
                    sales_order_id: 123
                    fulfillment_order_id: 451
                    fulfillment_type: starshipit
                    fulfillment_status: canceled
                    status: canceled
                    requested_shipping_method: UPS Ground
                    fulfilled_date: null
                    tracking_number: null
                    tracking_link: null
                    warehouse:
                      id: 7
                      name: Main Warehouse
                      type: direct
                      supplier_id: null
                      is_dropship: false
                    warehouse_id: 7
                    fulfilled_by:
                      id: 5
                      name: John Smith
                    fulfilled_quantity: 2
                    cost: 0
                    voided_at: '2026-06-02T20:45:00+00:00'
                    void_reason: wrong warehouse selected
                    voided_by:
                      id: 5
                      name: John Smith
                    fulfillment_lines:
                    - id: 9000
                      sales_order_line_id: 55347
                      quantity: 2
                    sales_channel_fulfillment_link: null
                    parcels:
                    - tracking_number: '9400100000000000000000'
                      delivery_status: in_transit
                      carrier: USPS
                    - tracking_number: '9400100000000000000017'
                      delivery_status: delivered
                      carrier: USPS
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:read
      operationId: get-api-sales-orders-salesorder-fulfillments
  /api/sales-orders/{salesOrder}/backorders:
    get:
      tags:
      - Sales Orders
      summary: Get Sales Order Backorder Coverage
      description: 'Gets backorder coverage data for a sales order — whether any of
        its lines are backordered, and the expected-arrival window of the incoming
        purchase orders that cover those backorders.


        :::info[Required scope: `orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Response fields:

        - earliest_covered_ship_by_date (date|null): The earliest resolved arrival
        date (ETA) among the purchase order lines allocated to the order''s backordered
        lines. Null when no backordered line is covered by a purchase order.

        - latest_covered_ship_by_date (date|null): The latest such ETA — the date
        by which all covered backordered lines are expected to be shippable.

        - has_backorder_lines (boolean): True when the order has at least one backordered
        line.


        Path parameters:

        - salesOrder (required): Sales order ID.'
      parameters:
      - name: salesOrder
        in: path
        schema:
          type: integer
        required: true
        description: Sales order ID
        example: '500'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 Success
                  value:
                    data:
                      earliest_covered_ship_by_date: '2026-07-18'
                      latest_covered_ship_by_date: '2026-08-02'
                      has_backorder_lines: true
                example-1:
                  summary: 200 No Backorders
                  value:
                    data:
                      earliest_covered_ship_by_date: null
                      latest_covered_ship_by_date: null
                      has_backorder_lines: false
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:read
      operationId: get-api-sales-orders-salesorder-backorders
  /api/sales-orders/{salesOrder}/document:
    get:
      tags:
      - Sales Orders
      summary: Get Sales Order Channel Document
      description: 'Gets the original sales-channel order document for a sales order
        — the raw order snapshot imported from the connected marketplace or cart (Shopify,
        Amazon, etc.).


        :::info[Required scope: `orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Behavior:

        - The document''s shape varies by sales channel: it is the channel-specific
        order record as stored at import time (order identifiers, financial/fulfillment
        statuses, totals, addresses, and channel metadata). The example below shows
        a Shopify-shaped document; other channels return their own field sets.

        - For documents from channels that expose a connected shop, the `integration_instance`
        relation is included so the document can be tied back to the specific store
        connection.

        - Returns `data: null` for manually created orders (orders with no sales-channel
        origin).


        Path parameters:

        - salesOrder (required): Sales order ID.'
      parameters:
      - name: salesOrder
        in: path
        schema:
          type: integer
        required: true
        description: Sales order ID
        example: '500'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 Success (Shopify-shaped document)
                  value:
                    data:
                      id: 8123
                      integration_instance_id: 3
                      shopify_customer_id: 4471
                      legacy_resource_id: 5723198862
                      name: '#1042'
                      email: buyer@example.com
                      currency: USD
                      financial_status: paid
                      fulfillment_status: unfulfilled
                      risk_level: low
                      test: false
                      subtotal_price: 225
                      total_discounts: 0
                      total_price: 258.9
                      total_tax: 18.9
                      total_shipping_price: 15
                      taxes_included: false
                      tags: wholesale
                      note: null
                      source_name: web
                      source_identifier: null
                      shopify_created_at: '2026-07-05T18:12:44.000000Z'
                      shopify_updated_at: '2026-07-05T18:14:02.000000Z'
                      shopify_processed_at: '2026-07-05T18:12:45.000000Z'
                      shopify_cancelled_at: null
                      cancel_reason: null
                      shopify_closed_at: null
                      billing_address_json:
                        name: Riley Chen
                        address1: 310 Harbor Way
                        city: Oakland
                        province_code: CA
                        zip: '94607'
                        country_code: US
                      shipping_address_json:
                        name: Riley Chen
                        address1: 310 Harbor Way
                        city: Oakland
                        province_code: CA
                        zip: '94607'
                        country_code: US
                      custom_attributes: []
                      metafields: null
                      archived_at: null
                      created_at: '2026-07-05T18:15:10.000000Z'
                      updated_at: '2026-07-05T18:15:10.000000Z'
                      integration_instance:
                        id: 3
                        name: Acme Shopify Store
                        shop_url: acme-store.myshopify.com
                example-1:
                  summary: 200 Manual Order (no channel document)
                  value:
                    data: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:read
      operationId: get-api-sales-orders-salesorder-document
  /api/sales-orders/list/export/download:
    get:
      tags:
      - Sales Orders
      summary: Download Sales Orders Export
      description: 'Downloads a completed background export produced by Export Sales
        Orders (queued path). The filename is the one reported in the tracked job
        log''s results.file field.


        Authentication: Requires Bearer token. Scope: orders (read).


        Response is the binary file (CSV or XLSX) with an attachment Content-Disposition
        header. Returns 404 if the file param is empty or the file no longer exists.


        **Requires permission:** `sales_orders.export`'
      parameters:
      - name: file
        in: query
        schema:
          type: string
        description: Filename returned in the completed tracked job's results.file.
          The server basenames this value and serves the stored export; unknown filenames
          yield 404.
        example: sales-orders-2026-07-10-13-00-00.xlsx
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
            Content-Disposition:
              schema:
                type: string
                example: attachment; filename="sales-orders-2026-07-10-13-00-00.xlsx"
          content:
            text/plain:
              schema:
                type: string
                example: <binary file>
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Not Found
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-sales-orders-list-export-download
  /api/sales-order-lines/{salesOrderLineId}:
    get:
      tags:
      - Sales Order Lines
      summary: Get Sales Order Line
      description: 'Get detailed information for a single sales order line. Includes
        inventory allocation details with purchase order coverage and release sources.


        :::info[Required scope: `orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: salesOrderLineId
        in: path
        schema:
          type: integer
        required: true
        description: Sales order line ID
        example: '1001'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      next_scheduled_po:
                        type: object
                        properties:
                          date:
                            type: string
                          purchase_order_id:
                            type: integer
                      active_coverages:
                        type: array
                        items:
                          type: object
                          properties:
                            purchase_order_id:
                              type: integer
                            purchase_order_number:
                              type: string
                            quantity:
                              type: number
                            date:
                              type: string
                            eta:
                              type: string
                      releases:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            link:
                              type: object
                              properties:
                                id:
                                  type: integer
                                type:
                                  type: string
                                parent_type:
                                  type: string
                            reference:
                              type: string
                            quantity:
                              type: number
                            release_date:
                              type: string
                example:
                  data:
                    next_scheduled_po:
                      date: '2024-04-01'
                      purchase_order_id: 55
                    active_coverages:
                    - purchase_order_id: 55
                      purchase_order_number: PO-2024-001
                      quantity: 10.0
                      date: '2024-03-01'
                      eta: '2024-04-15'
                    releases:
                    - id: 201
                      link:
                        id: 55
                        type: App\Models\PurchaseOrderLine
                        parent_type: App\Models\PurchaseOrder
                      reference: PO-2024-001
                      quantity: 10.0
                      release_date: '2024-03-10T08:00:00Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:read
      operationId: get-api-sales-order-lines-salesorderlineid
  /api/sales-order-lines:
    delete:
      tags:
      - Sales Order Lines
      summary: Delete Sales Order Line
      description: '**Deletes a SINGLE sales order line**, identified by `line_id`
        in the request BODY — despite the collection-level path (`DELETE /api/sales-order-lines`),
        this is not a bulk or delete-all operation. For multi-line deletes use `DELETE
        /api/sales-order-lines/bulk`.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Delete a single sales order line. Recalculates order discounts if any were
        applied.


        Authentication: Requires Bearer token.


        Restrictions:

        - Cannot delete if the line has associated fulfillment lines

        - Cannot delete the last line on a sales order


        Body:

        - line_id (required): ID of the sales order line to delete'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                example:
                  status: success
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 422 Cannot Delete (Fulfilled)
                  value:
                    status: failed
                    message: Sales order line fully/partially fulfilled. You can't
                      delete it.
                example-1:
                  summary: 422 Cannot Delete (Last Line)
                  value:
                    status: failed
                    message: Can't delete last line of the sales order.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: orders:write
      operationId: delete-api-sales-order-lines
  /api/sales-order-lines/bulk:
    delete:
      tags:
      - Sales Order Lines
      summary: Bulk Delete Sales Order Lines
      description: 'Bulk delete multiple sales order lines. Handles partial success
        and returns details of each line''s outcome.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Body:

        - ids (required): Array of integer sales order line IDs (min 1)'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 Partial Success
                  value:
                    status: partial
                    deleted:
                    - 1001
                    - 1002
                    failed:
                    - id: 1003
                      message: Line is fully/partially fulfilled.
                    deleted_count: 2
                example-1:
                  summary: 200 Full Success
                  value:
                    status: success
                    deleted:
                    - 1001
                    - 1002
                    failed: []
                    deleted_count: 2
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: orders:write
      operationId: delete-api-sales-order-lines-bulk
  /api/sales-order-lines/{salesOrderLine}/nominal-code:
    put:
      tags:
      - Sales Order Lines
      summary: Update Line Nominal Code
      description: 'Set or clear the nominal code override for a single sales order
        line. Used by the line-level nominal code editor on the V2 sales order detail
        page (only visible when the `accounting.use_sales_order_line_nominal_codes`
        config flag is true).


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        When `nominal_code_id` is null, the explicit override is cleared. The line''s
        `getNominalCodeId` resolution chain (line → product → sales channel → global)
        still applies on save, so the field may auto-snapshot a resolved code afterwards.


        Authentication: Requires Bearer token with `orders:write` scope.


        Body:

        - nominal_code_id (nullable, integer): existing nominal code ID, or null to
        clear the override.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                nominal_code_id:
                  type: integer
              example:
                nominal_code_id: 42
      parameters:
      - name: salesOrderLine
        in: path
        schema:
          type: integer
        required: true
        description: Sales order line ID
        example: '1001'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      sales_order_line_id:
                        type: integer
                      item_nominal_code_id:
                        type: integer
                      item_nominal_code:
                        type: string
                      item_nominal_code_code:
                        type: string
                example:
                  status: success
                  message: Nominal code updated successfully
                  data:
                    sales_order_line_id: 1001
                    item_nominal_code_id: 42
                    item_nominal_code: Sales
                    item_nominal_code_code: '4000'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      nominal_code_id:
                        type: array
                        items:
                          type: string
                example:
                  message: The selected nominal code id is invalid.
                  errors:
                    nominal_code_id:
                    - The selected nominal code id is invalid.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:write
      operationId: put-api-sales-order-lines-salesorderline-nominal-code
  /api/sales-orders/{salesOrder}/lines/reorder:
    post:
      tags:
      - Sales Order Lines
      summary: Reorder Sales Order Lines
      description: 'Persist a new top-to-bottom ordering for a sales order''s product
        lines.


        Authentication: Requires Bearer token.


        Body:

        - ordered_ids (required, integer array): sales order line ids in the desired
        order. A partial list is allowed — any line not listed keeps its relative
        order after the listed set. Every id must belong to this sales order (otherwise
        422).


        Returns the resulting line ids in their new order under data.ids.


        **Requires permission:** `sales_orders.update`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ordered_ids:
                  type: array
                  items:
                    type: integer
              example:
                ordered_ids:
                - 104
                - 102
                - 103
      parameters:
      - name: salesOrder
        in: path
        schema:
          type: integer
        required: true
        example: '55'
        description: The sales order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      ids:
                        type: array
                        items:
                          type: integer
                example:
                  data:
                    ids:
                    - 104
                    - 102
                    - 103
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-sales-orders-salesorder-lines-reorder
  /api/sales-order-lines/{sales_order_line}/map:
    put:
      tags:
      - Sales Order Lines
      summary: Map Line to Product
      description: 'Map a sales order line to an existing product. Used to link unmapped
        channel order lines to SKU products.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Body:

        - product_id (required): ID of the product to map to'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                product_id:
                  type: integer
              example:
                product_id: 42
      parameters:
      - name: sales_order_line
        in: path
        schema:
          type: integer
        required: true
        description: Sales order line ID
        example: '1001'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: The sales order line has been mapped to the product
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: orders:write
      operationId: put-api-sales-order-lines-sales-order-line-map
  /api/sales-order-lines/bulk-map:
    post:
      tags:
      - Sales Order Lines
      summary: Bulk Map Lines to Product
      description: 'Map multiple unmapped sales order lines to the same product at
        once.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Body:

        - product_id (required): ID of the product to map all lines to

        - line_ids (required): Array of sales order line IDs to map (min 1)


        Only maps lines that are currently unmapped (product_id is null).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                product_id:
                  type: integer
                line_ids:
                  type: array
                  items:
                    type: integer
              example:
                product_id: 42
                line_ids:
                - 1001
                - 1002
                - 1003
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      mapped_count:
                        type: integer
                example:
                  message: Mapped 3 line(s) to product
                  data:
                    mapped_count: 3
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: orders:write
      operationId: post-api-sales-order-lines-bulk-map
  /api/sales-order-lines/{sales_order_line}/make-as-non-product:
    put:
      tags:
      - Sales Order Lines
      summary: Mark Line as Non-Product
      description: 'Mark an unmapped sales order line as a non-product line (e.g.
        shipping fee, gift wrapping). Only applicable to lines with no product_id.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: sales_order_line
        in: path
        schema:
          type: integer
        required: true
        description: Sales order line ID
        example: '1001'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: The sales order line has been marked as a non-product line
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: orders:write
      operationId: put-api-sales-order-lines-sales-order-line-make-as-non-product
  /api/sales-order-lines/{salesOrderLine}/matching-unmapped:
    get:
      tags:
      - Sales Order Lines
      summary: Get Matching Unmapped Lines
      description: 'Find other unmapped sales order lines across all orders that have
        the same product description as the given line. Useful for bulk mapping suggestions.


        :::info[Required scope: `orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: salesOrderLine
        in: path
        schema:
          type: integer
        required: true
        description: Sales order line ID
        example: '1001'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        sales_order_id:
                          type: integer
                        sales_order_number:
                          type: string
                        order_status:
                          type: string
                        order_date:
                          type: string
                        quantity:
                          type: number
                        amount:
                          type: number
                example:
                  data:
                  - id: 1005
                    sales_order_id: 305
                    sales_order_number: SO-2024-305
                    order_status: open
                    order_date: '2024-03-10'
                    quantity: 2.0
                    amount: 29.99
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:read
      operationId: get-api-sales-order-lines-salesorderline-matching-unmapped
  /api/sales-order-lines/{salesOrderLine}/replace:
    post:
      tags:
      - Sales Order Lines
      summary: Replace Line Product(s)
      description: "Replace a single sales order line with one or more SKUs, preserving\
        \ the line's total amount and the order ↔ sales-channel tie.\n\n:::info[Required\
        \ scope: `orders:write`]\nGrant this scope to your token under [Settings →\
        \ Developer → Personal Access Tokens](https://app.sku.io/settings/api).\n\
        :::\n\nAuthentication: Requires Bearer token.\n\nPath params:\n- `salesOrderLine`\
        \ (required): id of the sales order line to replace.\n\nBody:\n- `replacements`\
        \ (required, array, min 1): the target SKUs. Each item:\n    - `product_id`\
        \ (required, int, must exist in products)\n    - `quantity` (required, number\
        \ > 0)\n    - `amount` (optional, number >= 0): per-unit price. When omitted\
        \ on ALL items, the original line total is prorated across the replacements\
        \ by catalog price; when provided, the explicit amounts must reconcile to\
        \ the original total (else 422).\n- `mapping_mode` (optional, `one_time` |\
        \ `permanent`, default `one_time`): only meaningful for a SINGLE-SKU replacement\
        \ at the original quantity that resolves to a channel listing. `permanent`\
        \ remaps the channel listing so every FUTURE order maps to the new SKU (sets\
        \ product_mapping_overridden so the line survives a channel resync); `one_time`\
        \ changes only this order. Multi-SKU replacements are always one-time.\n\n\
        Returns the refreshed sales order.\n\nErrors:\n- 409: the line is committed\
        \ to fulfillment (has a fulfillment line or an in-flight/submitted fulfillment\
        \ order) — void/cancel the fulfillment first.\n- 422: explicit replacement\
        \ amounts don't reconcile to the line total, or validation failed (unknown\
        \ product, quantity <= 0, missing replacements)."
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                replacements:
                  type: array
                  items:
                    type: object
                    properties:
                      product_id:
                        type: integer
                      quantity:
                        type: integer
                      amount:
                        type: number
                mapping_mode:
                  type: string
              example:
                replacements:
                - product_id: 4567
                  quantity: 2
                  amount: 19.99
                - product_id: 8901
                  quantity: 1
                mapping_mode: one_time
      parameters:
      - name: salesOrderLine
        in: path
        schema:
          type: integer
        required: true
        description: Sales order line id to replace
        example: '33421'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      sales_order_number:
                        type: string
                      order_status:
                        type: string
                      fulfillment_status:
                        type: string
                      item_info:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            product_id:
                              type: integer
                            sku:
                              type: string
                            quantity:
                              type: integer
                            amount:
                              type: number
                            product_mapping_overridden:
                              type: boolean
                example:
                  data:
                    id: 33188
                    sales_order_number: '#63676'
                    order_status: open
                    fulfillment_status: unfulfilled
                    item_info:
                    - id: 99001
                      product_id: 4567
                      sku: REPL-A
                      quantity: 2
                      amount: 19.99
                      product_mapping_overridden: false
                    - id: 99002
                      product_id: 8901
                      sku: REPL-B
                      quantity: 1
                      amount: 9.62
                      product_mapping_overridden: false
        '409':
          description: Conflict
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: This line is committed to fulfillment. Void the fulfillment
                    before replacing it.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: Replacement amounts must add up to the original line total.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:write
      operationId: post-api-sales-order-lines-salesorderline-replace
  /api/sales-order-lines/reservations:
    post:
      tags:
      - Sales Order Lines
      summary: Manage Reservations
      description: 'Reserve or reverse-reserve inventory for specific sales order
        lines. Returns the updated sales order.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Body:

        - sales_order_id (required): ID of the parent sales order

        - sales_order_lines (required): Array of line reservation actions

        - sales_order_lines[].id (required): Sales order line ID

        - sales_order_lines[].quantity (required): Quantity to reserve/reverse (>
        0, < 100,000)

        - sales_order_lines[].action (required): One of `reserve` or `reverse_reservation`


        Validation:

        - Returns 422 when a `reserve` action targets a line where `sales_channel_fulfillment_out_of_sync
        = true`. These lines are auto-allocated by the inventory pipeline once stock
        arrives, so manual reservation is rejected by design. The error key is `sales_order_lines.{index}.id`.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                sales_order_id:
                  type: integer
                sales_order_lines:
                  type: array
                  items:
                    type: object
                    properties:
                      id:
                        type: integer
                      quantity:
                        type: integer
                      action:
                        type: string
              example:
                sales_order_id: 300
                sales_order_lines:
                - id: 1001
                  quantity: 5
                  action: reserve
                - id: 1002
                  quantity: 3
                  action: unreserve
      parameters: []
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      sales_order_number:
                        type: string
                      order_status:
                        type: string
                      sales_order_lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            quantity:
                              type: integer
                            reserved_quantity:
                              type: integer
                            product_id:
                              type: integer
                example:
                  message: sales order has been successfully created
                  data:
                    id: 300
                    sales_order_number: SO-2024-300
                    order_status: open
                    sales_order_lines:
                    - id: 1001
                      quantity: 5
                      reserved_quantity: 5
                      product_id: 42
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      sales_order_lines.0.id:
                        type: array
                        items:
                          type: string
                example:
                  message: The sales order lines.0.id field is invalid.
                  errors:
                    sales_order_lines.0.id:
                    - 'Cannot manually reserve inventory for sales order line #1001
                      because the sales channel fulfillment is out of sync. Stock
                      will be automatically allocated when sufficient inventory is
                      available.'
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: orders:write
      operationId: post-api-sales-order-lines-reservations
  /api/sales-order-lines/{salesOrderLine}/{financialLineType}/convert-to-financial-line:
    post:
      tags:
      - Sales Order Lines
      summary: Convert to Financial Line
      description: 'Convert a sales order line to a specific financial line type (e.g.,
        revenue, adjustment).


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: salesOrderLine
        in: path
        schema:
          type: integer
        required: true
        description: Sales order line ID
        example: '1001'
      - name: financialLineType
        in: path
        schema:
          type: string
        required: true
        description: Financial line type slug
        example: revenue
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Sales order line successfully converted to revenue line
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: orders:write
      operationId: post-api-sales-order-lines-salesorderline-financiallinetype-convert-to-financial-line
  /api/sales-order-lines/{salesOrderLine}/suggest-warehouse:
    get:
      tags:
      - Sales Order Lines
      summary: Suggest Fulfillment Warehouse
      description: 'Read-only fulfillment-routing suggestion for an UNALLOCATED line.
        Runs the same warehouse priority + on-hand check the real routing uses to
        pick a default warehouse, and returns the ordered candidates with per-warehouse
        availability so the Allocate dialog can explain WHY a warehouse won and offer
        an override. Allocation itself is then performed via the split-across-warehouses
        endpoint with a single slice. Authenticate with a Personal Access Token (PAT).


        :::info[Required scope: `orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: salesOrderLine
        in: path
        schema:
          type: integer
        required: true
        description: SalesOrderLine ID
        example: '55347'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      sales_order_line_id:
                        type: integer
                      quantity_needed:
                        type: integer
                      chosen_warehouse_id:
                        type: integer
                      chosen_warehouse_name:
                        type: string
                      strategy:
                        type: string
                      strategy_label:
                        type: string
                      candidates:
                        type: array
                        items:
                          type: object
                          properties:
                            warehouse_id:
                              type: integer
                            warehouse_name:
                              type: string
                            warehouse_type:
                              type: string
                            priority_rank:
                              type: integer
                            available:
                              type: integer
                            has_stock:
                              type: boolean
                            fully_covers:
                              type: boolean
                            chosen:
                              type: boolean
                example:
                  data:
                    sales_order_line_id: 55347
                    quantity_needed: 4
                    chosen_warehouse_id: 9
                    chosen_warehouse_name: Main Warehouse
                    strategy: priority
                    strategy_label: Configured warehouse priority order
                    candidates:
                    - warehouse_id: 1
                      warehouse_name: Default Warehouse
                      warehouse_type: direct
                      priority_rank: 1
                      available: 0
                      has_stock: false
                      fully_covers: false
                      chosen: false
                    - warehouse_id: 9
                      warehouse_name: Main Warehouse
                      warehouse_type: direct
                      priority_rank: 2
                      available: 50
                      has_stock: true
                      fully_covers: true
                      chosen: true
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:read
      operationId: get-api-sales-order-lines-salesorderline-suggest-warehouse
  /api/sales-order-lines/{salesOrderLine}/split-across-warehouses:
    post:
      tags:
      - Sales Order Lines
      summary: Split Line Across Warehouses
      description: 'Redistribute a sales order line''s **pre-dispatch** fulfillment
        across multiple warehouses WITHOUT duplicating the line (Pattern C). The channel
        line stays 1:1 with upstream; the split materialises as **one InventoryAllocation
        + one FulfillmentOrder per warehouse** (`1 SOL → N allocations → N FOs`).
        Each slice allocates on-hand up to availability at that warehouse, with the
        remainder planned (backorder).


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        **Pre-dispatch only.** Allowed while every fulfillment order for the line
        is still `open + unsubmitted`. Once any FO has been submitted to a carrier
        the line can no longer be redistributed — returns **409**.


        **Body fields:**

        - `slices` (required, array, min 1) — the target distribution.

        - `slices[].warehouse_id` (required, integer, must exist) — destination warehouse
        for this slice.

        - `slices[].quantity` (required, integer, min 1) — units to fulfil from that
        warehouse.


        The slice total must not exceed the line''s unfulfilled quantity (**422**
        otherwise). Duplicate warehouses are merged. Returns the refreshed sales order.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                slices:
                  type: array
                  items:
                    type: object
                    properties:
                      warehouse_id:
                        type: integer
                      quantity:
                        type: integer
              example:
                slices:
                - warehouse_id: 9
                  quantity: 3
                - warehouse_id: 11
                  quantity: 2
      parameters:
      - name: salesOrderLine
        in: path
        schema:
          type: integer
        required: true
        description: SalesOrderLine ID
        example: '55347'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      sales_order_number:
                        type: string
                      order_status:
                        type: string
                      item_info:
                        type: array
                        items:
                          type: object
                          properties:
                            sales_order_line_id:
                              type: integer
                            item_quantity:
                              type: integer
                            fulfilled_quantity:
                              type: integer
                            submitted_quantity:
                              type: integer
                            allocated_quantity:
                              type: integer
                            on_hand_allocated_quantity:
                              type: integer
                            planned_quantity:
                              type: integer
                            awaiting_receipt_quantity:
                              type: integer
                            backorder_warehouses:
                              type: array
                              items:
                                type: object
                                properties:
                                  warehouse_id:
                                    type: integer
                                  quantity:
                                    type: integer
                                  status:
                                    type: string
                            warehouse:
                              type: object
                              properties:
                                id:
                                  type: integer
                                name:
                                  type: string
                example:
                  data:
                    id: 1234
                    sales_order_number: SO-0123
                    order_status: open
                    item_info:
                    - sales_order_line_id: 55347
                      item_quantity: 5
                      fulfilled_quantity: 0
                      submitted_quantity: 0
                      allocated_quantity: 5
                      on_hand_allocated_quantity: 3
                      planned_quantity: 1
                      awaiting_receipt_quantity: 1
                      backorder_warehouses:
                      - warehouse_id: 9
                        quantity: 1
                        status: planned
                      - warehouse_id: 12
                        quantity: 1
                        status: awaiting_receipt
                      warehouse:
                        id: 9
                        name: Default Warehouse
        '409':
          description: Conflict
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: 'SalesOrderLine #55347 cannot be split across warehouses:
                    it has a fulfillment order beyond open+unsubmitted (already submitted
                    to a carrier). Splitting is a pre-dispatch operation.'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: Split total (12) exceeds the line's unfulfilled quantity
                    (10).
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:write
      operationId: post-api-sales-order-lines-salesorderline-split-across-warehouses
  /api/sales-order-lines/{salesOrderLine}/cancel-quantity:
    post:
      tags:
      - Sales Order Lines
      summary: Cancel Line Quantity
      description: 'Cancel part (or all) of a sales order line''s remaining quantity
        **without changing the ordered quantity** — the line keeps its original `quantity`
        as a permanent record and `canceled_quantity` rises, so the net quantity to
        fulfill drops. Cancelling everything nets the line to zero: allocations are
        released, backorder demand clears, and any open (not yet submitted) fulfillment
        orders shrink to match.


        Units already shipped, externally fulfilled, committed to a live fulfillment
        (submitted / picked / packed, a staged pickup, or an order already handed
        to a shipping provider), or already cancelled cannot be cancelled — cancel
        or void that fulfillment first. Exceeding the cancellable quantity returns
        **409**.


        **Body fields:**

        - `quantity` (required, integer, min 1) — units to cancel.

        - `reason` (optional, string, max 1000) — recorded on the order''s notes for
        the audit trail.


        Returns the refreshed sales order.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                quantity:
                  type: integer
                reason:
                  type: string
              example:
                quantity: 1
                reason: Item out of stock — replacement line added
      parameters:
      - name: salesOrderLine
        in: path
        schema:
          type: integer
        required: true
        description: SalesOrderLine ID
        example: '55347'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      sales_order_number:
                        type: string
                      order_status:
                        type: string
                      fulfillment_status:
                        type: string
                      item_info:
                        type: array
                        items:
                          type: object
                          properties:
                            sales_order_line_id:
                              type: integer
                            item_quantity:
                              type: integer
                            item_canceled_quantity:
                              type: integer
                            fulfilled_quantity:
                              type: integer
                            submitted_quantity:
                              type: integer
                            allocated_quantity:
                              type: integer
                            warehouse:
                              type: object
                              properties:
                                id:
                                  type: integer
                                name:
                                  type: string
                example:
                  data:
                    id: 1234
                    sales_order_number: SO-0123
                    order_status: open
                    fulfillment_status: unfulfilled
                    item_info:
                    - sales_order_line_id: 55347
                      item_quantity: 1
                      item_canceled_quantity: 1
                      fulfilled_quantity: 0
                      submitted_quantity: 0
                      allocated_quantity: 0
                      warehouse:
                        id: 9
                        name: Default Warehouse
        '409':
          description: Conflict
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: Only 1 unit(s) can be cancelled on this line — the rest are
                    fulfilled or committed to a fulfillment. Cancel or void the fulfillment
                    first.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      quantity:
                        type: array
                        items:
                          type: string
                example:
                  message: The quantity to cancel must be at least 1.
                  errors:
                    quantity:
                    - The quantity to cancel must be at least 1.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-sales-order-lines-salesorderline-cancel-quantity
  /api/sales-order-lines/import:
    post:
      tags:
      - Sales Order Lines
      summary: Import Lines from CSV
      description: 'Import sales order lines from a CSV file or raw CSV string. Required
        CSV columns: sku. Optional columns: description, quantity, price, pricing_tier,
        warehouse_id, warehouse_name.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        If sales_order_id is provided, lines are added to that order. Otherwise, returns
        a preview of parsed lines (useful for the import UI).'
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                file:
                  type: string
                  description: CSV file to import. Required if csvString not provided.
                  format: binary
                csvString:
                  type: string
                  description: Raw CSV string. Required if file not provided.
                sales_order_id:
                  type: integer
                  description: 'Optional: Sales order ID to add lines to. If omitted,
                    returns preview data without saving.'
                  example: '300'
                replace:
                  type: boolean
                  description: 'Boolean: If true, replaces existing product lines.
                    Default: false'
                  example: 'false'
                separator:
                  type: string
                  description: 'CSV column separator. Default: comma (,)'
                  example: ','
                escape:
                  type: string
                  description: 'CSV escape character. Default: double-quote'
                  example: '"'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        product_id:
                          type: integer
                        description:
                          type: string
                        quantity:
                          type: integer
                        amount:
                          type: number
                        is_product:
                          type: boolean
                        warehouse:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                example:
                  message: sales order lines have been successfully imported
                  data:
                  - product_id: 42
                    description: Blue Widget 500ml
                    quantity: 5
                    amount: 29.99
                    is_product: true
                    warehouse:
                      id: 1
                      name: Main Warehouse
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: array
                    items:
                      type: object
                      properties:
                        message:
                          type: string
                        code:
                          type: string
                        field:
                          type: string
                example:
                  errors:
                  - message: The CSV file does not match the expected template
                    code: INVALID_TEMPLATE
                    field: file
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: orders:write
      operationId: post-api-sales-order-lines-import
  /api/sales-order-lines/{sales_order_line}/override-edition:
    post:
      tags:
      - Sales Order Lines
      summary: Override Edition
      description: 'Override the subscription edition for a sales order line. Assigns
        a specific edition instead of the automatically resolved one.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Body:

        - subscription_edition_id (required): ID of the subscription edition to apply

        - reason (optional): Reason for the override, max 500 characters'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                subscription_edition_id:
                  type: integer
                reason:
                  type: string
              example:
                subscription_edition_id: 7
                reason: Customer requested upgrade to premium edition
      parameters:
      - name: sales_order_line
        in: path
        schema:
          type: integer
        required: true
        description: Sales order line ID
        example: '1001'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      sales_order_line_id:
                        type: integer
                      subscription_edition_id:
                        type: integer
                      product_id:
                        type: integer
                      edition_name:
                        type: string
                example:
                  message: Edition override applied successfully
                  data:
                    sales_order_line_id: 1001
                    subscription_edition_id: 7
                    product_id: 42
                    edition_name: Premium Annual
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: orders:write
      operationId: post-api-sales-order-lines-sales-order-line-override-edition
  /api/sales-order-lines/{sales_order_line}/clear-edition-override:
    post:
      tags:
      - Sales Order Lines
      summary: Clear Edition Override
      description: 'Clear the edition override on a sales order line, reverting to
        automatic edition resolution.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: sales_order_line
        in: path
        schema:
          type: integer
        required: true
        description: Sales order line ID
        example: '1001'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Edition override cleared
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: orders:write
      operationId: post-api-sales-order-lines-sales-order-line-clear-edition-override
  /api/v2/sales-order-fulfillments:
    get:
      tags:
      - Fulfillments
      summary: List Fulfillments
      description: 'Returns paginated sales order fulfillments for the V2 fulfillments
        list page. Supports GroupedFilterSupport filter_groups tree for advanced filtering.


        :::info[Required scope: `orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Default behavior: excludes archived fulfillments unless filter[archived] is
        provided.


        Filter columns (all support operator suffix, e.g. filter[column.contains]):

        • Basic: id (numeric), fulfillment_number, fulfillment_sequence (numeric),
        tracking_number, status, fulfillment_type, requested_shipping_method, fulfilled_shipping_method,
        backordered, warehouse

        • Sales Order: customer_reference, store, sales_channel_type_name, sales_order_shipping_method,
        sales_order_tags

        • Customer: customer_name, customer_email, customer_phone, customer_company,
        customer_address, customer_city, customer_province, customer_province_code,
        customer_zip, customer_country, customer_country_code

        • Items: item_name, item_sku, item_quantity (numeric), item_price (numeric),
        item_nominal_code

        • Financial: cost (numeric)

        • Dates: fulfilled_at, packing_slip_printed_at, created_at, updated_at, archived_at


        Text operators: is, is_not, contains, does_not_contain, is_one_of, starts_with,
        does_not_start_with, ends_with, does_not_end_with, is_empty, is_not_empty
        (negative ops use whereDoesntHave for relationships).

        Numeric operators: is, is_not, is_one_of, greater_than, less_than, greater_than_or_equal,
        less_than_or_equal, between, is_empty, is_not_empty.

        Datetime operators: same as numeric plus relative ranges.


        Available sorts: id, status, fulfillment_type, tracking_number, cost, fulfilled_at,
        packing_slip_printed_at, created_at, updated_at (default: -id)


        The response also includes `unfiltered_total`, the count of rows in the base
        scope before any user filters are applied — used by the frontend to show export
        totals.


        Each row''s sales_order includes customer_id (links the customer column to
        its detail page), and sales_channel returns name (integration TYPE, e.g. Shopify)
        plus integration_name (the connection/instance, e.g. "Curvy AU").'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        description: 'Page number (default: 1)'
        example: '1'
      - name: per_page
        in: query
        schema:
          type: integer
        description: 'Items per page (default: 10)'
        example: '10'
      - name: sort
        in: query
        schema:
          type: string
        description: 'Sort field. Prefix - for descending. Allowed: id, status, fulfillment_type,
          tracking_number, cost, fulfilled_at, packing_slip_printed_at, created_at,
          updated_at'
        example: -id
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        fulfillment_number:
                          type: string
                        fulfillment_sequence:
                          type: integer
                        status:
                          type: string
                        fulfillment_type:
                          type: string
                        tracking_number:
                          type: string
                        tracking_link:
                          type: string
                        cost:
                          type: string
                        fulfilled_at:
                          type: string
                        packing_slip_printed_at:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                        updated_at:
                          type: string
                        archived_at:
                          type: string
                          nullable: true
                        is_parent:
                          type: boolean
                        parent_id:
                          type: string
                          nullable: true
                        sales_order:
                          type: object
                          properties:
                            id:
                              type: integer
                            sales_order_number:
                              type: string
                            order_date:
                              type: string
                            order_status:
                              type: string
                            customer_name:
                              type: string
                            customer_reference:
                              type: string
                            customer_id:
                              type: integer
                        warehouse:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        requested_shipping_method:
                          type: string
                        is_pickup:
                          type: boolean
                        requested_shipping_method_text:
                          type: string
                          nullable: true
                        fulfilled_shipping_method:
                          type: string
                        fulfilled_shipping_method_text:
                          type: string
                          nullable: true
                        sales_channel:
                          type: object
                          properties:
                            name:
                              type: string
                            integration_name:
                              type: string
                        store:
                          type: string
                        item_count:
                          type: integer
                        total_quantity:
                          type: integer
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  unfiltered_total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - id: 1001
                    fulfillment_number: FF-1001
                    fulfillment_sequence: 1
                    status: submitted
                    fulfillment_type: shipstation
                    tracking_number: 1Z999AA10123456784
                    tracking_link: https://www.ups.com/track?tracknum=1Z999AA10123456784
                    cost: '12.50'
                    fulfilled_at: '2024-01-18T14:00:00.000000Z'
                    packing_slip_printed_at: null
                    created_at: '2024-01-15T10:00:00.000000Z'
                    updated_at: '2024-01-18T14:00:00.000000Z'
                    archived_at: null
                    is_parent: false
                    parent_id: null
                    sales_order:
                      id: 500
                      sales_order_number: SO-20240115-500
                      order_date: '2024-01-15'
                      order_status: fulfilled
                      customer_name: Acme Corp
                      customer_reference: PO-2024-001
                      customer_id: 281384
                    warehouse:
                      id: 1
                      name: Main Warehouse
                    requested_shipping_method: UPS Ground
                    is_pickup: false
                    requested_shipping_method_text: null
                    fulfilled_shipping_method: UPS Ground
                    fulfilled_shipping_method_text: null
                    sales_channel:
                      name: shopify
                      integration_name: Curvy AU
                    store: My Shopify Store
                    item_count: 2
                    total_quantity: 5
                  current_page: 1
                  last_page: 10
                  per_page: 10
                  total: 95
                  unfiltered_total: 1247
                  from: 1
                  to: 10
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: orders:read
      operationId: get-api-v2-sales-order-fulfillments
  /api/v2/sales-order-fulfillments/export:
    get:
      tags:
      - Fulfillments
      summary: Export Fulfillments
      description: 'Exports sales order fulfillments as XLSX or CSV.


        :::info[Required scope: `orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Summary mode columns: ID, Fulfillment #, Status, Type, Order #, Customer,
        Warehouse, Tracking #, Req. Method, Req. Method (Manual), Ful. Method, Ful.
        Method (Manual), Items, Qty, Cost, Fulfilled At, Packing Slip Printed At,
        Created At, Updated At.


        Line items mode also includes per-line: Item SKU, Item Name, Item Description,
        Item Qty, Unit Price, Line Total.


        Authentication: Requires Bearer token.


        Response: File download (binary), not JSON.'
      parameters:
      - name: format
        in: query
        schema:
          type: string
        description: 'Export format: xlsx (default) or csv'
        example: xlsx
      - name: content_mode
        in: query
        schema:
          type: string
        description: 'Export mode: summary (one row per fulfillment, default) or line_items
          (one row per line item)'
        example: summary
      - name: scope
        in: query
        schema:
          type: string
        description: 'Export scope: filtered (default, uses active filters), all (ignore
          filters), current_page, or selected'
        example: filtered
      responses:
        '200':
          description: OK
          content:
            text/plain:
              schema:
                type: string
                example: '[Binary XLSX file download — fulfillments-2024-01-20-10-30-00.xlsx]'
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: orders:read
      operationId: get-api-v2-sales-order-fulfillments-export
  /api/v2/sales-order-fulfillments/{salesOrderFulfillment}/detail:
    get:
      tags:
      - Fulfillments
      summary: Get Fulfillment Detail
      description: 'Returns full fulfillment detail including all related data: lines
        with products, sales order with addresses, warehouse, shipping methods, shipping
        provider orders (Shipstation, Shipfusion, etc.).


        :::info[Required scope: `orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: salesOrderFulfillment
        in: path
        schema:
          type: integer
        required: true
        description: Sales order fulfillment ID
        example: '1001'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      fulfillment_order_id:
                        type: integer
                      fulfillment_number:
                        type: string
                      status:
                        type: string
                      fulfillment_type:
                        type: string
                      tracking_number:
                        type: string
                      cost:
                        type: string
                      fulfilled_at:
                        type: string
                      sales_order:
                        type: object
                        properties:
                          id:
                            type: integer
                          sales_order_number:
                            type: string
                          billing_address:
                            type: object
                            properties:
                              name:
                                type: string
                              address1:
                                type: string
                          shipping_address:
                            type: object
                            properties:
                              name:
                                type: string
                              address1:
                                type: string
                      warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      sales_order_fulfillment_lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            quantity:
                              type: integer
                            sales_order_line:
                              type: object
                              properties:
                                id:
                                  type: integer
                                product:
                                  type: object
                                  properties:
                                    id:
                                      type: integer
                                    sku:
                                      type: string
                                    name:
                                      type: string
                example:
                  data:
                    id: 1001
                    fulfillment_order_id: 42
                    fulfillment_number: FF-1001
                    status: submitted
                    fulfillment_type: shipstation
                    tracking_number: 1Z999AA10123456784
                    cost: '12.50'
                    fulfilled_at: '2024-01-18T14:00:00.000000Z'
                    sales_order:
                      id: 500
                      sales_order_number: SO-20240115-500
                      billing_address:
                        name: Acme Corp
                        address1: 123 Main St
                      shipping_address:
                        name: Acme Corp
                        address1: 456 Ship Lane
                    warehouse:
                      id: 1
                      name: Main Warehouse
                    sales_order_fulfillment_lines:
                    - id: 2001
                      quantity: 3
                      sales_order_line:
                        id: 3001
                        product:
                          id: 42
                          sku: WIDGET-001
                          name: Premium Widget
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:read
      operationId: get-api-v2-sales-order-fulfillments-salesorderfulfillment-detail
  /api/v2/sales-order-fulfillments/{salesOrderFulfillment}/line-items:
    get:
      tags:
      - Fulfillments
      summary: Get Fulfillment Line Items
      description: 'Returns lightweight line items for a fulfillment''s expandable
        row. Each item includes id, quantity, unit_cost, sku, product_name, and product_id.
        `unit_cost` is the per-unit cost of goods sold (FIFO-derived, prorated to
        the fulfilled quantity) — NOT the sale price; it is 0 when the line has no
        financial cost record.


        :::info[Required scope: `orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: salesOrderFulfillment
        in: path
        schema:
          type: integer
        required: true
        description: Sales order fulfillment ID
        example: '1001'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        quantity:
                          type: integer
                        unit_cost:
                          type: number
                        sku:
                          type: string
                        product_name:
                          type: string
                        product_id:
                          type: integer
                example:
                  data:
                  - id: 2001
                    quantity: 3
                    unit_cost: 12.5
                    sku: WIDGET-001
                    product_name: Premium Widget
                    product_id: 42
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:read
      operationId: get-api-v2-sales-order-fulfillments-salesorderfulfillment-line-items
  /api/v2/sales-order-fulfillments/{salesOrderFulfillment}/activity-log:
    get:
      tags:
      - Fulfillments
      summary: Get Activity Log
      description: 'Returns paginated activity log for a fulfillment, including activities
        on the fulfillment itself and all its child records (lines, etc.).


        :::info[Required scope: `orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: per_page
        in: query
        schema:
          type: integer
        description: 'Items per page (default: 15)'
        example: '15'
      - name: salesOrderFulfillment
        in: path
        schema:
          type: integer
        required: true
        description: Sales order fulfillment ID
        example: '1001'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        description:
                          type: string
                        event:
                          type: string
                        subject_type:
                          type: string
                        subject_id:
                          type: integer
                        properties:
                          type: object
                          properties:
                            old:
                              type: object
                              properties:
                                status:
                                  type: string
                            attributes:
                              type: object
                              properties:
                                status:
                                  type: string
                        causer_name:
                          type: string
                        created_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 8001
                    description: updated
                    event: updated
                    subject_type: SalesOrderFulfillment
                    subject_id: 1001
                    properties:
                      old:
                        status: pending
                      attributes:
                        status: submitted
                    causer_name: Jane Smith
                    created_at: '2024-01-18T14:00:00.000000Z'
                  current_page: 1
                  last_page: 1
                  per_page: 15
                  total: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:read
      operationId: get-api-v2-sales-order-fulfillments-salesorderfulfillment-activity-log
  /api/v2/sales-order-fulfillments/{salesOrderFulfillment}/inventory-movements:
    get:
      tags:
      - Fulfillments
      summary: Get Inventory Movements
      description: 'Returns paginated inventory movements linked to the fulfillment
        or any of its fulfillment lines.


        :::info[Required scope: `orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: per_page
        in: query
        schema:
          type: integer
        description: 'Items per page (default: 15)'
        example: '15'
      - name: salesOrderFulfillment
        in: path
        schema:
          type: integer
        required: true
        description: Sales order fulfillment ID
        example: '1001'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        type:
                          type: string
                        inventory_status:
                          type: string
                        quantity:
                          type: integer
                        reference:
                          type: string
                        inventory_movement_date:
                          type: string
                        product_id:
                          type: integer
                        product_sku:
                          type: string
                        product_name:
                          type: string
                        warehouse_id:
                          type: integer
                        warehouse_name:
                          type: string
                        unit_cost:
                          type: string
                        unit_cost_provisional:
                          type: boolean
                        link_type:
                          type: string
                        link_id:
                          type: integer
                        parent_link_id:
                          type: integer
                        detail_link_id:
                          type: string
                          nullable: true
                        layer:
                          type: object
                          properties:
                            fifo_layer_id:
                              type: integer
                            name:
                              type: string
                        created_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 9001
                    type: sale
                    inventory_status: available
                    quantity: -3
                    reference: SO-20240115-500.1
                    inventory_movement_date: '2024-01-18'
                    product_id: 42
                    product_sku: WIDGET-001
                    product_name: Premium Widget
                    warehouse_id: 1
                    warehouse_name: Main Warehouse
                    unit_cost: '15.00'
                    unit_cost_provisional: false
                    link_type: App\Models\SalesOrderFulfillmentLine
                    link_id: 2001
                    parent_link_id: 1001
                    detail_link_id: null
                    layer:
                      fifo_layer_id: 55
                      name: fifo
                    created_at: '2024-01-18T14:00:00.000000Z'
                  current_page: 1
                  last_page: 1
                  per_page: 15
                  total: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:read
      operationId: get-api-v2-sales-order-fulfillments-salesorderfulfillment-inventory-movements
  /api/v2/sales-order-fulfillments/{salesOrderFulfillment}/clear-channel-submission:
    post:
      tags:
      - Fulfillments
      summary: Clear Channel Submission
      description: 'Clears the submitted_to_sales_channel_at timestamp so the fulfillment
        will be resubmitted on the next sync. Works regardless of sales order status.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: salesOrderFulfillment
        in: path
        schema:
          type: integer
        required: true
        description: Sales order fulfillment ID
        example: '1001'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Channel submission cleared — will be resubmitted
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: orders:write
      operationId: post-api-v2-sales-order-fulfillments-salesorderfulfillment-clear-channel-submission
  /api/v2/sales-order-fulfillments/{salesOrderFulfillment}/submit-to-channel:
    post:
      tags:
      - Fulfillments
      summary: Submit to Sales Channel
      description: 'Submits (or resubmits) fulfillment tracking info to the sales
        channel (e.g. Shopify) synchronously. Only sends tracking to the sales channel
        — NOT to the shipping provider.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: salesOrderFulfillment
        in: path
        schema:
          type: integer
        required: true
        description: Sales order fulfillment ID
        example: '1001'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Fulfillment submitted to sales channel
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: orders:write
      operationId: post-api-v2-sales-order-fulfillments-salesorderfulfillment-submit-to-channel
  /api/v2/sales-order-fulfillments/{salesOrderFulfillment}/resync-to-provider:
    post:
      tags:
      - Fulfillments
      summary: Resync to Provider
      description: 'Re-syncs the fulfillment to the shipping provider by sending the
        current line state. Only available for update-capable providers (Shipfusion,
        ShipHero, etc.) with submitted fulfillments.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: salesOrderFulfillment
        in: path
        schema:
          type: integer
        required: true
        description: Sales order fulfillment ID
        example: '1001'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Fulfillment re-synced to provider successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: orders:write
      operationId: post-api-v2-sales-order-fulfillments-salesorderfulfillment-resync-to-provider
  /api/v2/sales-order-fulfillments/{salesOrderFulfillment}/resync-from-provider:
    post:
      tags:
      - Fulfillments
      summary: Resync from Provider
      description: 'Fetches the latest data FROM the shipping provider (tracking,
        status, etc.) and updates the local fulfillment record. Supported providers:
        Shipstation, Starshipit, Shipfusion, ShipHero, Trackstar, Veracore.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: salesOrderFulfillment
        in: path
        schema:
          type: integer
        required: true
        description: Sales order fulfillment ID
        example: '1001'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  shipment_status:
                    type: string
                  tracking_pipeline_ran:
                    type: boolean
                example:
                  message: Fetched and updated from provider
                  shipment_status: delivered
                  tracking_pipeline_ran: true
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: orders:write
      operationId: post-api-v2-sales-order-fulfillments-salesorderfulfillment-resync-from-provider
  /api/v2/sales-order-fulfillments/{salesOrderFulfillment}/cancel-provider-order:
    post:
      tags:
      - Fulfillments
      summary: Cancel Provider Order
      description: 'Cancels the provider-side fulfillment order. Supported providers:
        Amazon MCF (FBA), Shipfusion, ShipHero, Trackstar, Veracore.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: salesOrderFulfillment
        in: path
        schema:
          type: integer
        required: true
        description: Sales order fulfillment ID
        example: '1001'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Provider order cancelled successfully
        '422':
          description: Unprocessable Entity
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 'Failed to cancel: Cancel not supported for provider: manual'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:write
      operationId: post-api-v2-sales-order-fulfillments-salesorderfulfillment-cancel-provider-order
  /api/v2/sales-order-fulfillments/{salesOrderFulfillment}/shipping-details:
    patch:
      tags:
      - Fulfillments
      summary: Edit Shipping Details
      description: 'Edit an existing fulfillment''s shipping details — tracking number
        and shipping cost. A narrow, guard-free update: unlike the fulfill flow it
        does NOT require an open sales order or fulfillment lines, so a tracking number
        can be corrected after the order has shipped/closed. Never changes the warehouse
        (Stage 0 lock untouched).


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Body fields (all optional — send only what changes):

        - tracking_number (string, nullable, max 255)

        - cost (numeric, nullable, >= 0, < 100000)


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                tracking_number:
                  type: string
                cost:
                  type: number
              example:
                tracking_number: 1Z999AA10123456784
                cost: 12.5
      parameters:
      - name: salesOrderFulfillment
        in: path
        schema:
          type: integer
        required: true
        description: Sales order fulfillment ID
        example: '1001'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Shipping details updated
        '422':
          description: Unprocessable Entity
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      cost:
                        type: array
                        items:
                          type: string
                example:
                  message: The cost must be less than 100000.
                  errors:
                    cost:
                    - The cost must be less than 100000.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:write
      operationId: patch-api-v2-sales-order-fulfillments-salesorderfulfillment-shipping-details
  /api/sales-order-fulfillments/{salesOrderFulfillment}:
    delete:
      tags:
      - Fulfillments
      summary: Void Shipment
      description: 'Voids a shipment (SalesOrderFulfillment) — a SOFT, reversible
        cancel that does NOT hard-delete the record (''A1''). Voiding: reverses the
        shipment''s inventory movements, reverts Fulfilled→Allocated allocations,
        restores the parent FulfillmentOrder budget and reopens the SAME FO to Open/Unsubmitted
        so it can be re-fulfilled, cancels the carrier order, and flips the SOF to
        status=canceled with voided_at/voided_by_user_id/void_reason set. The SOF
        + its lines are RETAINED for history; voided shipments are excluded from the
        active fulfillment tab (voided_at IS NULL filter).


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Not voidable (returns 400): an already-shipped shipment (status fulfilled
        / fulfilled_awaiting_info — use a return/RMA), an already-voided shipment,
        or a multi-channel (MCF / merge-group) submission (void individual standalone
        shipments only).


        Request body (optional):

        - void_reason (string, optional): reason recorded on the void + FO activity
        entry. Falls back to `reason` if absent.


        Query params:

        - check-deletable (0|1, default 1): when 1, runs the carrier-side ''already
        shipped at provider'' guard before voiding.


        Authentication: Requires Bearer token.'
      parameters:
      - name: salesOrderFulfillment
        in: path
        schema:
          type: integer
        required: true
        description: Sales order fulfillment (shipment) ID
        example: '1001'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: array
                example:
                  message: The sales order fulfillment SO-0123.2 voided successfully
                  data: []
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: array
                    items:
                      type: object
                      properties:
                        message:
                          type: string
                        code:
                          type: string
                        field:
                          type: string
                example:
                  errors:
                  - message: 'Shipment SO-0123.2 cannot be voided: status=fulfilled.
                      Shipped shipments (fulfilled, fulfilled_awaiting_info) are not
                      voidable — use a return/RMA instead.'
                    code: DeleteShippingProviderOrder422
                    field: id
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:write
      operationId: delete-api-sales-order-fulfillments-salesorderfulfillment
    put:
      tags:
      - Fulfillments
      summary: Fulfill or Update Shipment
      description: "Create or update a shipment (fulfillment) for a sales order. Uses\
        \ FulfillSalesOrderRequest. Authenticate with a Personal Access Token, passed\
        \ in the `Authorization` header as a bearer token.\n\nPUT updates the bound\
        \ fulfillment; the same body shape is used when creating via POST /api/sales-orders/{salesOrder}/fulfillments.\n\
        \nBody fields:\n- fulfillment_type (required): one of the SalesOrderFulfillment::TYPES\
        \ (e.g. manual, fba, pickup).\n- warehouse_id (nullable on PUT; required on\
        \ POST when the order spans multiple warehouses — auto-selected when single).\n\
        - requested_shipping_method_id / requested_shipping_method (nullable).\n-\
        \ fulfilled_shipping_method_id / manual_fulfilled_shipping_method (nullable\
        \ — for manual fulfillment).\n- fulfilled_at (required when fulfillment_type=manual;\
        \ date).\n- cost (nullable, numeric < 100000).\n- tracking_number (nullable,\
        \ max 255).\n- fulfillment_sequence (nullable, integer, unique per sales order).\n\
        - fulfillment_lines (array, min 1): each line has\n - sales_order_line_id\
        \ (required, exists)\n - quantity (required, numeric, 0..<100000)\n - id (PUT\
        \ only — required_without sales_order_line_id; the SOFL id)\n - metadata.fba_seller_sku\
        \ (optional string)\n - lot_allocation (optional, array): user-chosen lot\
        \ allocation (FEFO override) for a lot-tracked product. Each entry { fifo_layer_id\
        \ (exists), quantity (>0) }. The entries MUST sum to the line's quantity,\
        \ reference active FIFO layers of the line's product + warehouse with enough\
        \ available quantity, and respect the tenant lot override policy (under 'enforce',\
        \ consuming expired stock or a later-expiry lot for FEFO products is rejected).\
        \ Omit it to consume by automatic FEFO/FIFO.\n- metadata.* (optional shipment-level\
        \ flags: signature_required, saturday_delivery, shipping_speed, comments,\
        \ veracore_*).\n- submit_to_shipping_provider / submit_to_sales_channel (optional\
        \ bool).\n\nPer-line 422 lot validation errors are keyed fulfillment_lines.{index}.lot_allocation\
        \ and fulfillment_lines.{index}.lot_allocation.{i}.{field}.\n\n:::info[Required\
        \ scope: `orders:write`]\nGrant this scope to your token under [Settings →\
        \ Developer → Personal Access Tokens](https://app.sku.io/settings/api).\n\
        :::"
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                fulfillment_type:
                  type: string
                warehouse_id:
                  type: integer
                requested_shipping_method_id:
                  type: integer
                fulfilled_shipping_method_id:
                  type: integer
                manual_fulfilled_shipping_method:
                  type: string
                fulfilled_at:
                  type: string
                cost:
                  type: number
                tracking_number:
                  type: string
                fulfillment_sequence:
                  type: integer
                fulfillment_lines:
                  type: array
                  items:
                    type: object
                    properties:
                      sales_order_line_id:
                        type: integer
                      quantity:
                        type: integer
                      metadata:
                        type: object
                        properties:
                          fba_seller_sku:
                            type: string
                      lot_allocation:
                        type: array
                        items:
                          type: object
                          properties:
                            fifo_layer_id:
                              type: integer
                            quantity:
                              type: integer
                metadata:
                  type: object
                  properties:
                    signature_required:
                      type: boolean
                    saturday_delivery:
                      type: boolean
                    shipping_speed:
                      type: string
                    comments:
                      type: string
                submit_to_shipping_provider:
                  type: boolean
                submit_to_sales_channel:
                  type: boolean
              example:
                fulfillment_type: manual
                warehouse_id: 7
                requested_shipping_method_id: 12
                fulfilled_shipping_method_id: 12
                manual_fulfilled_shipping_method: UPS Ground
                fulfilled_at: '2026-06-20 14:30:00'
                cost: 8.5
                tracking_number: 1Z999AA10123456784
                fulfillment_sequence: 1
                fulfillment_lines:
                - sales_order_line_id: 55347
                  quantity: 3
                  metadata:
                    fba_seller_sku: WIDGET-LOT-001
                  lot_allocation:
                  - fifo_layer_id: 90211
                    quantity: 2
                  - fifo_layer_id: 90217
                    quantity: 1
                - sales_order_line_id: 55348
                  quantity: 1
                metadata:
                  signature_required: true
                  saturday_delivery: false
                  shipping_speed: standard
                  comments: Leave at front door
                submit_to_shipping_provider: true
                submit_to_sales_channel: true
      parameters:
      - name: salesOrderFulfillment
        in: path
        schema:
          type: integer
        required: true
        description: Sales order fulfillment (shipment) id
        example: '7781'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      fulfillment_number:
                        type: string
                      sales_order_id:
                        type: integer
                      fulfillment_order_id:
                        type: integer
                      fulfillment_type:
                        type: string
                      fulfillment_status:
                        type: string
                      shipping_method_id:
                        type: integer
                      requested_shipping_method:
                        type: string
                        nullable: true
                      requested_shipping_method_id:
                        type: integer
                      fulfilled_shipping_method:
                        type: string
                      fulfilled_shipping_method_id:
                        type: integer
                      fulfilled_date:
                        type: string
                      tracking_number:
                        type: string
                      tracking_url:
                        type: string
                        nullable: true
                      tracking_link:
                        type: string
                        nullable: true
                      warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          type:
                            type: string
                          supplier_id:
                            type: string
                            nullable: true
                          is_dropship:
                            type: boolean
                      warehouse_id:
                        type: integer
                      fulfilled_by:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      fulfilled_quantity:
                        type: integer
                      fulfillment_lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            sales_order_line_id:
                              type: integer
                            sales_order_fulfillment_id:
                              type: integer
                            quantity:
                              type: integer
                            unit_cost:
                              type: integer
                            metadata:
                              type: object
                              properties:
                                lot_allocation:
                                  type: array
                                  items:
                                    type: object
                                    properties:
                                      fifo_layer_id:
                                        type: integer
                                      quantity:
                                        type: integer
                            item_inventory:
                              type: object
                              properties: {}
                            sales_order_line:
                              type: object
                              properties:
                                id:
                                  type: integer
                                product_id:
                                  type: integer
                                quantity:
                                  type: integer
                                amount:
                                  type: number
                                description:
                                  type: string
                                warehouse_id:
                                  type: integer
                                product:
                                  type: object
                                  properties:
                                    id:
                                      type: integer
                                    sku:
                                      type: string
                                    name:
                                      type: string
                                    weight:
                                      type: number
                                    weight_unit:
                                      type: string
                                    height:
                                      type: string
                                      nullable: true
                                    width:
                                      type: string
                                      nullable: true
                                    length:
                                      type: string
                                      nullable: true
                                    dimension_unit:
                                      type: string
                                      nullable: true
                                    is_lot_tracked:
                                      type: boolean
                                    lot_tracking_method:
                                      type: string
                                    shelf_life_days:
                                      type: integer
                                    near_expiry_threshold_days:
                                      type: integer
                                    min_remaining_shelf_life_days:
                                      type: integer
                      cost:
                        type: number
                      status:
                        type: string
                      voided_at:
                        type: string
                        nullable: true
                      void_reason:
                        type: string
                        nullable: true
                      voided_by:
                        type: string
                        nullable: true
                      fulfilled_at:
                        type: string
                      fulfillment_sequence:
                        type: integer
                      is_parent:
                        type: boolean
                      parent_id:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      provider_order_id:
                        type: string
                        nullable: true
                      metadata:
                        type: object
                        properties:
                          signature_required:
                            type: boolean
                example:
                  data:
                    id: 7781
                    fulfillment_number: SO-1042.1
                    sales_order_id: 1042
                    fulfillment_order_id: 451
                    fulfillment_type: manual
                    fulfillment_status: fulfilled
                    shipping_method_id: 12
                    requested_shipping_method: null
                    requested_shipping_method_id: 12
                    fulfilled_shipping_method: UPS Ground
                    fulfilled_shipping_method_id: 12
                    fulfilled_date: '2026-06-20T14:30:00+00:00'
                    tracking_number: 1Z999AA10123456784
                    tracking_url: null
                    tracking_link: null
                    warehouse:
                      id: 7
                      name: Main Warehouse
                      type: standard
                      supplier_id: null
                      is_dropship: false
                    warehouse_id: 7
                    fulfilled_by:
                      id: 3
                      name: Warehouse Operator
                    fulfilled_quantity: 4
                    fulfillment_lines:
                    - id: 99001
                      sales_order_line_id: 55347
                      sales_order_fulfillment_id: 7781
                      quantity: 3
                      unit_cost: 5
                      metadata:
                        lot_allocation:
                        - fifo_layer_id: 90211
                          quantity: 2
                        - fifo_layer_id: 90217
                          quantity: 1
                      item_inventory: {}
                      sales_order_line:
                        id: 55347
                        product_id: 8842
                        quantity: 3
                        amount: 19.99
                        description: Lot-Tracked Widget
                        warehouse_id: 7
                        product:
                          id: 8842
                          sku: WIDGET-LOT-001
                          name: Lot-Tracked Widget
                          weight: 0.5
                          weight_unit: kg
                          height: null
                          width: null
                          length: null
                          dimension_unit: null
                          is_lot_tracked: true
                          lot_tracking_method: fefo
                          shelf_life_days: 365
                          near_expiry_threshold_days: 30
                          min_remaining_shelf_life_days: 60
                    - id: 99002
                      sales_order_line_id: 55348
                      sales_order_fulfillment_id: 7781
                      quantity: 1
                      unit_cost: 3
                      metadata: null
                      item_inventory: {}
                      sales_order_line:
                        id: 55348
                        product_id: 8843
                        quantity: 1
                        amount: 9.99
                        description: Standard Gadget
                        warehouse_id: 7
                        product:
                          id: 8843
                          sku: GADGET-200
                          name: Standard Gadget
                          weight: 0.2
                          weight_unit: kg
                          height: null
                          width: null
                          length: null
                          dimension_unit: null
                          is_lot_tracked: false
                          lot_tracking_method: null
                          shelf_life_days: null
                          near_expiry_threshold_days: null
                          min_remaining_shelf_life_days: null
                    cost: 8.5
                    status: fulfilled
                    voided_at: null
                    void_reason: null
                    voided_by: null
                    fulfilled_at: '2026-06-20T14:30:00+00:00'
                    fulfillment_sequence: 1
                    is_parent: false
                    parent_id: null
                    created_at: '2026-06-20T14:30:00+00:00'
                    provider_order_id: null
                    metadata:
                      signature_required: true
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: object
                    properties:
                      fulfillment_lines.0.lot_allocation:
                        type: array
                        items:
                          type: string
                      fulfillment_lines.0.lot_allocation.1.fifo_layer_id:
                        type: array
                        items:
                          type: string
                      fulfillment_lines.0.lot_allocation.0.quantity:
                        type: array
                        items:
                          type: string
                example:
                  errors:
                    fulfillment_lines.0.lot_allocation:
                    - The lot allocation must sum to the quantity (3).
                    fulfillment_lines.0.lot_allocation.1.fifo_layer_id:
                    - Your lot policy requires consuming the earliest-expiry lot first
                      (FEFO).
                    fulfillment_lines.0.lot_allocation.0.quantity:
                    - Cannot allocate more than the lot's available quantity (2).
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:write
      operationId: put-api-sales-order-fulfillments-salesorderfulfillment
    get:
      tags:
      - Fulfillments
      summary: Get Fulfillment
      description: 'Get a single fulfillment (shipment) with its lines, parent sales
        order summary, warehouse, tracking, and void audit fields.


        :::info[Required scope: `orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Each fulfillment line includes the linked sales order line and product (with
        lot-tracking configuration) plus a live `item_inventory` breakdown per warehouse
        (stock, allocated, available, inbound, in transit).


        Key fields:

        - `status` / `fulfillment_status` — `submitted`, `acknowledged`, `picked`,
        `packed`, `fulfilled`, `canceled`, or `awaiting_pickup`

        - `fulfillment_type` — `manual`, `shipstation`, `starshipit`, `shipmyorders`,
        `fba`, `walmart_wfs`, `veracore`, `shiphero`, `shipfusion`, `d3`, `trackstar`,
        `pickup`, or `sales_channel`

        - `fulfillment_number` — `{sales_order_number}.{sequence}`, e.g. `SO-10412.1`

        - `voided_at` / `void_reason` / `voided_by` — set when the shipment has been
        voided


        Archived fulfillments are still returned. Requires the `orders:read` token
        scope.'
      parameters:
      - name: salesOrderFulfillment
        in: path
        schema:
          type: integer
        required: true
        description: Fulfillment (shipment) ID
        example: '4821'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      fulfillment_number:
                        type: string
                      sales_order_id:
                        type: integer
                      fulfillment_order_id:
                        type: integer
                      fulfillment_type:
                        type: string
                      fulfillment_status:
                        type: string
                      shipping_method_id:
                        type: integer
                      requested_shipping_method_id:
                        type: integer
                      fulfilled_shipping_method_id:
                        type: integer
                      fulfilled_date:
                        type: string
                      tracking_number:
                        type: string
                      tracking_url:
                        type: string
                      tracking_link:
                        type: string
                      warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          type:
                            type: string
                          supplier_id:
                            type: string
                            nullable: true
                          is_dropship:
                            type: boolean
                      warehouse_id:
                        type: integer
                      fulfilled_by:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      fulfilled_quantity:
                        type: integer
                      fulfillment_lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            sales_order_line_id:
                              type: integer
                            sales_order_fulfillment_id:
                              type: integer
                            quantity:
                              type: integer
                            unit_cost:
                              type: number
                            metadata:
                              type: string
                              nullable: true
                            item_inventory:
                              type: object
                              properties:
                                total:
                                  type: object
                                  properties:
                                    inbound:
                                      type: integer
                                    stock:
                                      type: integer
                                    allocated:
                                      type: integer
                                    on_hold:
                                      type: integer
                                    available:
                                      type: integer
                                    in_transit:
                                      type: integer
                                warehouses:
                                  type: object
                                  properties:
                                    Main Warehouse:
                                      type: object
                                      properties:
                                        inbound:
                                          type: integer
                                        stock:
                                          type: integer
                                        allocated:
                                          type: integer
                                        on_hold:
                                          type: integer
                                        available:
                                          type: integer
                                        supplier_in_stock:
                                          type: string
                                          nullable: true
                                        in_transit:
                                          type: integer
                                        warehouse_id:
                                          type: integer
                                        warehouse_name:
                                          type: string
                                        warehouse_type:
                                          type: string
                                        supplier:
                                          type: string
                                          nullable: true
                                        country_code:
                                          type: string
                            sales_order_line:
                              type: object
                              properties:
                                id:
                                  type: integer
                                product_id:
                                  type: integer
                                quantity:
                                  type: integer
                                amount:
                                  type: number
                                description:
                                  type: string
                                warehouse_id:
                                  type: integer
                                product:
                                  type: object
                                  properties:
                                    id:
                                      type: integer
                                    sku:
                                      type: string
                                    name:
                                      type: string
                                    weight:
                                      type: number
                                    weight_unit:
                                      type: string
                                    height:
                                      type: integer
                                    width:
                                      type: number
                                    length:
                                      type: number
                                    dimension_unit:
                                      type: string
                                    is_lot_tracked:
                                      type: boolean
                                    lot_tracking_method:
                                      type: string
                                      nullable: true
                                    shelf_life_days:
                                      type: string
                                      nullable: true
                                    near_expiry_threshold_days:
                                      type: string
                                      nullable: true
                                    min_remaining_shelf_life_days:
                                      type: string
                                      nullable: true
                      cost:
                        type: number
                      status:
                        type: string
                      voided_at:
                        type: string
                        nullable: true
                      void_reason:
                        type: string
                        nullable: true
                      voided_by:
                        type: string
                        nullable: true
                      fulfilled_at:
                        type: string
                      marked_for_pickup_at:
                        type: string
                        nullable: true
                      marked_for_pickup_by:
                        type: string
                        nullable: true
                      expected_pickup_at:
                        type: string
                        nullable: true
                      packing_slip_printed_at:
                        type: string
                      submitted_to_sales_channel_at:
                        type: string
                      last_synced_to_provider_at:
                        type: string
                      last_synced_from_provider_at:
                        type: string
                      metadata:
                        type: object
                        properties:
                          shipping_speed:
                            type: string
                      fulfillment_sequence:
                        type: integer
                      is_parent:
                        type: boolean
                      parent_id:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      provider_order_id:
                        type: string
                        nullable: true
                      sales_channel_fulfillment_link:
                        type: string
                        nullable: true
                      sales_order:
                        type: object
                        properties:
                          id:
                            type: integer
                          sales_order_number:
                            type: string
                          order_date:
                            type: string
                          order_status:
                            type: string
                          fulfillment_status:
                            type: string
                          customer_reference:
                            type: string
                          requested_shipping_method:
                            type: string
                          billing_address:
                            type: object
                            properties:
                              id:
                                type: integer
                              first_name:
                                type: string
                              last_name:
                                type: string
                              address1:
                                type: string
                              address2:
                                type: string
                                nullable: true
                              city:
                                type: string
                              province_code:
                                type: string
                              zip:
                                type: string
                              country_code:
                                type: string
                              phone:
                                type: string
                          shipping_address:
                            type: object
                            properties:
                              id:
                                type: integer
                              first_name:
                                type: string
                              last_name:
                                type: string
                              address1:
                                type: string
                              address2:
                                type: string
                                nullable: true
                              city:
                                type: string
                              province_code:
                                type: string
                              zip:
                                type: string
                              country_code:
                                type: string
                              phone:
                                type: string
                example:
                  status: success
                  data:
                    id: 4821
                    fulfillment_number: SO-10412.1
                    sales_order_id: 10412
                    fulfillment_order_id: 3377
                    fulfillment_type: shipstation
                    fulfillment_status: fulfilled
                    shipping_method_id: 12
                    requested_shipping_method_id: 12
                    fulfilled_shipping_method_id: 14
                    fulfilled_date: '2026-06-28T14:03:22.000000Z'
                    tracking_number: '9400111899223197428490'
                    tracking_url: https://tools.usps.com/go/TrackConfirmAction?tLabels=9400111899223197428490
                    tracking_link: https://tools.usps.com/go/TrackConfirmAction?tLabels=9400111899223197428490
                    warehouse:
                      id: 3
                      name: Main Warehouse
                      type: standard
                      supplier_id: null
                      is_dropship: false
                    warehouse_id: 3
                    fulfilled_by:
                      id: 7
                      name: Jane Operator
                    fulfilled_quantity: 3
                    fulfillment_lines:
                    - id: 9932
                      sales_order_line_id: 55340
                      sales_order_fulfillment_id: 4821
                      quantity: 3
                      unit_cost: 4.25
                      metadata: null
                      item_inventory:
                        total:
                          inbound: 120
                          stock: 458
                          allocated: 36
                          on_hold: 0
                          available: 422
                          in_transit: 0
                        warehouses:
                          Main Warehouse:
                            inbound: 120
                            stock: 458
                            allocated: 36
                            on_hold: 0
                            available: 422
                            supplier_in_stock: null
                            in_transit: 0
                            warehouse_id: 3
                            warehouse_name: Main Warehouse
                            warehouse_type: standard
                            supplier: null
                            country_code: US
                      sales_order_line:
                        id: 55340
                        product_id: 2210
                        quantity: 3
                        amount: 19.99
                        description: Stainless Steel Water Bottle 750ml
                        warehouse_id: 3
                        product:
                          id: 2210
                          sku: WB-750-SS
                          name: Stainless Steel Water Bottle 750ml
                          weight: 0.42
                          weight_unit: kg
                          height: 27
                          width: 7.5
                          length: 7.5
                          dimension_unit: cm
                          is_lot_tracked: false
                          lot_tracking_method: null
                          shelf_life_days: null
                          near_expiry_threshold_days: null
                          min_remaining_shelf_life_days: null
                    cost: 8.45
                    status: fulfilled
                    voided_at: null
                    void_reason: null
                    voided_by: null
                    fulfilled_at: '2026-06-28T14:03:22.000000Z'
                    marked_for_pickup_at: null
                    marked_for_pickup_by: null
                    expected_pickup_at: null
                    packing_slip_printed_at: '2026-06-27T18:20:11.000000Z'
                    submitted_to_sales_channel_at: '2026-06-28T14:05:01.000000Z'
                    last_synced_to_provider_at: '2026-06-28T14:03:25.000000Z'
                    last_synced_from_provider_at: '2026-06-28T16:00:02.000000Z'
                    metadata:
                      shipping_speed: standard
                    fulfillment_sequence: 1
                    is_parent: false
                    parent_id: null
                    created_at: '2026-06-27T16:40:09.000000Z'
                    provider_order_id: null
                    sales_channel_fulfillment_link: null
                    sales_order:
                      id: 10412
                      sales_order_number: SO-10412
                      order_date: '2026-06-27'
                      order_status: open
                      fulfillment_status: fulfilled
                      customer_reference: AMZ-114-2298711
                      requested_shipping_method: Standard Shipping
                      billing_address:
                        id: 8811
                        first_name: Dana
                        last_name: Whitfield
                        address1: 88 Elm St
                        address2: null
                        city: Austin
                        province_code: TX
                        zip: '78701'
                        country_code: US
                        phone: +1 512 555 0138
                      shipping_address:
                        id: 8812
                        first_name: Dana
                        last_name: Whitfield
                        address1: 88 Elm St
                        address2: null
                        city: Austin
                        province_code: TX
                        zip: '78701'
                        country_code: US
                        phone: +1 512 555 0138
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:read
      operationId: get-api-sales-order-fulfillments-salesorderfulfillment
  /api/sales-order-fulfillments:
    delete:
      tags:
      - Fulfillments
      summary: Bulk Void Shipments
      description: 'Bulk-voids shipments. The DELETE verb is retained for backwards
        compatibility, but it now performs a soft VOID (not a hard delete): each shipment''s
        inventory is reversed, its parent FulfillmentOrder is reopened, the carrier
        order is cancelled, and the SOF row is kept for history (status=canceled +
        void audit columns).


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Request body:

        • ids (`array<int>`, required without apply_to_all): fulfillment IDs to void.

        • apply_to_all (bool, optional): when true, voids every shipment matching
        `filters` instead of `ids`.

        • filters (object, optional): the V2 list filter set used to resolve IDs when
        apply_to_all=true.

        • force (bool, optional, default false): when false, shipments already shipped
        at the provider are NOT voided — they land in the `needs_confirmation` bucket.
        Re-submit those with force=true to void the local copy anyway (inventory reversed,
        carrier order left as-is).

        • void_reason (string, optional, max 1000): reason recorded on each void +
        FO activity entry.


        Selection size routing:

        • ≤ 30 shipments: voided synchronously; the response `data` carries per-shipment
        result buckets.

        • > 30 shipments: dispatched to a background tracked job; the response `data`
        carries `tracked_job_log_id` for the tracked job log endpoints.


        Result buckets (synchronous):

        • voided[]: { id, fulfillment_number } — successfully voided.

        • needs_confirmation[]: { id, fulfillment_number, reason } — shipped at the
        provider; re-submit with force=true.

        • skipped[]: { id, fulfillment_number, reason } — already voided or otherwise
        not voidable.

        • errors[]: { id, fulfillment_number, error } — unexpected failures.


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 Voided (synchronous, ≤ 30)
                  value:
                    message: Voided 2 shipment(s). 1 shipped shipment(s) need confirmation
                      to void the local copy.
                    data:
                      voided:
                      - id: 1001
                        fulfillment_number: SO-0123.1
                      - id: 1002
                        fulfillment_number: SO-0123.2
                      needs_confirmation:
                      - id: 1003
                        fulfillment_number: SO-0124.1
                        reason: shipped
                      skipped: []
                      errors: []
                example-1:
                  summary: 200 Dispatched to Background (> 30)
                  value:
                    message: Voiding shipments in the background — track progress
                      in the job tray.
                    data:
                      tracked_job_log_id: 8842
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      ids:
                        type: array
                        items:
                          type: string
                example:
                  message: The ids field is required when apply to all is not present.
                  errors:
                    ids:
                    - The ids field is required when apply to all is not present.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: orders:write
      operationId: delete-api-sales-order-fulfillments
  /api/export/sales-order-fulfillments/{salesOrderFulfillment}/packing-slip/cache-status:
    get:
      tags:
      - Fulfillments
      summary: Get Shipment Packing Slip Cache Status
      description: 'Reports whether a rendered packing-slip PDF is currently cached
        for this shipment (SalesOrderFulfillment), and when it was generated. The
        packing-slip export serves the stored `{id}.pdf` as-is whenever it exists,
        so a cached slip can lag the FO''s current lines or sequence. The UI uses
        this to show a "cached" indicator and offer a one-click clear.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Requires a Bearer token (Personal Access Token).'
      parameters:
      - name: salesOrderFulfillment
        in: path
        schema:
          type: integer
        required: true
        description: Sales order fulfillment (shipment) ID
        example: '123'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 Cached
                  value:
                    data:
                      cached: true
                      generated_at: '2026-06-23T22:24:20+00:00'
                example-1:
                  summary: 200 Not Cached
                  value:
                    data:
                      cached: false
                      generated_at: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-export-sales-order-fulfillments-salesorderfulfillment-packing-slip-cache-status
  /api/export/sales-order-fulfillments/{salesOrderFulfillment}/packing-slip/cache:
    delete:
      tags:
      - Fulfillments
      summary: Clear Shipment Packing Slip Cache
      description: 'Clears (deletes) the cached packing-slip PDF for this shipment
        (SalesOrderFulfillment) so the next print regenerates from current data. Idempotent
        — clearing a slip that was never cached is a no-op.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Requires a Bearer token (Personal Access Token).'
      parameters:
      - name: salesOrderFulfillment
        in: path
        schema:
          type: integer
        required: true
        description: Sales order fulfillment (shipment) ID
        example: '123'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Cached packing slip cleared — the next print will regenerate
                    from current data.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-export-sales-order-fulfillments-salesorderfulfillment-packing-slip-cache
  /api/sales-orders/{salesOrder}/provider-fulfillment-snapshots:
    get:
      tags:
      - Fulfillments
      summary: Get Provider Fulfillment Snapshots
      description: 'Read-only provider order/shipment visibility & reconciliation
        for the Sales Order Fulfillments tab.


        :::info[Required scope: `orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Returns each connected shipping provider''s cached order/shipment (Starshipit
        + ShipStation pilots), matched to this sales order by the `{sales_order_number}.{fulfillment_sequence}`
        reference, and classified into a reconciliation state:

        - `matched` — attached to an FO/SOF on this order and items agree

        - `item_mismatch` — attached, but provider items differ from our lines

        - `orphan_linkable` — unattached, but a matching FO/SOF exists (repair target)

        - `orphan_importable` — unattached and no matching FO/SOF (import candidate)

        - `orphan_duplicate` — unattached, but its products are already fulfilled
        by an FO that has an active provider order (a duplicate at the carrier; resolve
        by voiding it there and recording a voided FO)


        `snapshots[]` are attached to an FO/SOF (see `attached_to`); `orphans[]` are
        unattached provider records; `summary` carries per-state counts.


        Authentication: requires a Bearer token (Personal Access Token).

        Read-only — no query parameters. Cache-only (no live provider call); `last_synced_at`
        reflects staleness.

        Gated by the `fulfillment.provider_snapshots_enabled` flag — returns 404 when
        disabled so the UI degrades gracefully.


        Each orphan carries a `suggested_action`: `link`, `import_fo`, `import_fo_and_sof`,
        `void_and_import` (live duplicate), or `import_voided_fo` (already-cancelled
        duplicate). `summary` includes per-state counts, including `orphan_duplicate`.


        Each snapshot/orphan entry includes `marked_shipped_without_label` (boolean):
        true when the provider order reports shipped but no label was ever purchased
        and no tracking exists anywhere (the ShipStation "Mark as Shipped" fingerprint).
        Such orphans get `suggested_action: import_voided_fo` — importing records
        a terminal voided mirror fulfillment order instead of a live FO/SOF.


        `marked_shipped_without_label` also covers hand-typed trackings: a "Mark as
        Shipped" order (ShipStation payload externallyFulfilled=true) with a typed
        tracking is flagged only when that tracking matches a shipment already recorded
        on the order. Shipped orphans sharing a tracking with a recorded shipment
        classify as orphan_linkable (free shipment) or orphan_duplicate with import_voided_fo
        (shipment already provider-backed).


        Each attached snapshot may carry a `discrepancy` object when a shipping provider
        shipped a fulfillment order whose line SKU cannot fulfill from on-hand stock:
        `{ fulfillment_order_id, can_accept, accepted, discrepant_lines[], fulfillable_lines[]
        }`. When `can_accept` is true, POST the fulfillment order''s accept-discrepancy
        endpoint to ship the fulfillable lines and park the rest. Null when there
        is no discrepancy to surface.'
      parameters:
      - name: salesOrder
        in: path
        schema:
          type: integer
        required: true
        description: Sales order ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      snapshots:
                        type: array
                        items:
                          type: object
                          properties:
                            provider:
                              type: string
                            provider_label:
                              type: string
                            integration_instance_id:
                              type: integer
                            integration_instance_name:
                              type: string
                            external_order_id:
                              type: string
                            order_reference:
                              type: string
                            status:
                              type: string
                            status_label:
                              type: string
                            deep_link_url:
                              type: string
                            external_url:
                              type: string
                            last_synced_at:
                              type: string
                            shipped:
                              type: boolean
                            marked_shipped_without_label:
                              type: boolean
                            attached_to:
                              type: object
                              properties:
                                type:
                                  type: string
                                id:
                                  type: integer
                            link_state:
                              type: string
                            link_state_label:
                              type: string
                            link_state_color:
                              type: string
                            suggested_action:
                              type: string
                              nullable: true
                            items:
                              type: array
                              items:
                                type: object
                                properties:
                                  sku:
                                    type: string
                                  name:
                                    type: string
                                  quantity:
                                    type: integer
                                  product_id:
                                    type: integer
                            shipments:
                              type: array
                              items:
                                type: object
                                properties:
                                  external_shipment_id:
                                    type: string
                                  tracking_number:
                                    type: string
                                  tracking_url:
                                    type: string
                                  carrier:
                                    type: string
                                  service:
                                    type: string
                                  shipped_at:
                                    type: string
                                  delivery_status:
                                    type: string
                                  voided:
                                    type: boolean
                            item_match:
                              type: object
                              properties:
                                matches:
                                  type: boolean
                                lines:
                                  type: array
                                  items:
                                    type: object
                                    properties:
                                      sku:
                                        type: string
                                      name:
                                        type: string
                                      our_qty:
                                        type: integer
                                      provider_qty:
                                        type: integer
                                      state:
                                        type: string
                            discrepancy:
                              type: object
                              properties:
                                fulfillment_order_id:
                                  type: integer
                                can_accept:
                                  type: boolean
                                accepted:
                                  type: boolean
                                discrepant_lines:
                                  type: array
                                  items:
                                    type: object
                                    properties:
                                      sku:
                                        type: string
                                      name:
                                        type: string
                                      quantity:
                                        type: integer
                                fulfillable_lines:
                                  type: array
                                  items:
                                    type: object
                                    properties:
                                      sku:
                                        type: string
                                      name:
                                        type: string
                                      quantity:
                                        type: integer
                      orphans:
                        type: array
                        items:
                          type: object
                          properties:
                            provider:
                              type: string
                            provider_label:
                              type: string
                            integration_instance_id:
                              type: integer
                            integration_instance_name:
                              type: string
                            external_order_id:
                              type: integer
                            order_reference:
                              type: string
                            status:
                              type: string
                            status_label:
                              type: string
                            deep_link_url:
                              type: string
                            external_url:
                              type: string
                            last_synced_at:
                              type: string
                            shipped:
                              type: boolean
                            marked_shipped_without_label:
                              type: boolean
                            attached_to:
                              type: string
                              nullable: true
                            link_state:
                              type: string
                            link_state_label:
                              type: string
                            link_state_color:
                              type: string
                            suggested_action:
                              type: string
                            items:
                              type: array
                              items:
                                type: object
                                properties:
                                  sku:
                                    type: string
                                  name:
                                    type: string
                                  quantity:
                                    type: integer
                                  product_id:
                                    type: integer
                            shipments:
                              type: array
                              items:
                                type: object
                                properties:
                                  external_shipment_id:
                                    type: integer
                                  tracking_number:
                                    type: string
                                  tracking_url:
                                    type: string
                                  carrier:
                                    type: string
                                  service:
                                    type: string
                                  shipped_at:
                                    type: string
                                  delivery_status:
                                    type: string
                                    nullable: true
                                  voided:
                                    type: boolean
                            item_match:
                              type: object
                              properties:
                                matches:
                                  type: string
                                  nullable: true
                                lines:
                                  type: array
                            discrepancy:
                              type: string
                              nullable: true
                      summary:
                        type: object
                        properties:
                          matched:
                            type: integer
                          item_mismatch:
                            type: integer
                          orphan_linkable:
                            type: integer
                          orphan_importable:
                            type: integer
                example:
                  data:
                    snapshots:
                    - provider: starshipit
                      provider_label: Starshipit
                      integration_instance_id: 12
                      integration_instance_name: AU Warehouse
                      external_order_id: '987654'
                      order_reference: C604018.1
                      status: shipped
                      status_label: Shipped
                      deep_link_url: /integrations/starshipit/12/orders/987654
                      external_url: https://app2.starshipit.com/orders/new/987654
                      last_synced_at: '2026-06-24T03:11:00+00:00'
                      shipped: true
                      marked_shipped_without_label: false
                      attached_to:
                        type: fulfillment_order
                        id: 4471
                      link_state: matched
                      link_state_label: Matched
                      link_state_color: success
                      suggested_action: null
                      items:
                      - sku: WIDGET-RED
                        name: Red Widget
                        quantity: 2
                        product_id: 55
                      shipments:
                      - external_shipment_id: PKG-1
                        tracking_number: ABX123
                        tracking_url: https://track.aus/ABX123
                        carrier: Australia Post
                        service: Express
                        shipped_at: '2026-06-24T02:55:00+00:00'
                        delivery_status: In Transit
                        voided: false
                      item_match:
                        matches: true
                        lines:
                        - sku: WIDGET-RED
                          name: Red Widget
                          our_qty: 2
                          provider_qty: 2
                          state: ok
                      discrepancy:
                        fulfillment_order_id: 4471
                        can_accept: true
                        accepted: false
                        discrepant_lines:
                        - sku: '195093200861'
                          name: Mis-tagged item
                          quantity: 1
                        fulfillable_lines:
                        - sku: ABC-1
                          name: In-stock item
                          quantity: 1
                    - provider: shipstation
                      provider_label: ShipStation
                      integration_instance_id: 7
                      integration_instance_name: US Warehouse
                      external_order_id: 3320
                      order_reference: C604018.2
                      status: shipped
                      status_label: Shipped
                      deep_link_url: /integrations/shipstation/7/orders/3310
                      external_url: https://ship.shipstation.com/orders/all-orders-search-result?quickSearch=C604018.2
                      last_synced_at: '2026-06-24T02:40:00+00:00'
                      shipped: true
                      marked_shipped_without_label: false
                      attached_to:
                        type: sales_order_fulfillment
                        id: 9912
                      link_state: item_mismatch
                      link_state_label: Items differ
                      link_state_color: error
                      suggested_action: null
                      items:
                      - sku: WIDGET-RED
                        name: Red Widget
                        quantity: 2
                        product_id: 55
                      - sku: GIZMO-9
                        name: Gizmo 9
                        quantity: 1
                        product_id: 61
                      shipments:
                      - external_shipment_id: 88810
                        tracking_number: 1Z111
                        tracking_url: https://ups.com/track?1Z111
                        carrier: ups
                        service: ups_ground
                        shipped_at: '2026-06-24T02:30:00+00:00'
                        delivery_status: null
                        voided: false
                      item_match:
                        matches: false
                        lines:
                        - sku: WIDGET-RED
                          name: Red Widget
                          our_qty: 2
                          provider_qty: 2
                          state: ok
                        - sku: GIZMO-9
                          name: Gizmo 9
                          our_qty: 3
                          provider_qty: 1
                          state: qty_diff
                      discrepancy: null
                    orphans:
                    - provider: shipstation
                      provider_label: ShipStation
                      integration_instance_id: 7
                      integration_instance_name: US Warehouse
                      external_order_id: 3321
                      order_reference: C604018.3
                      status: shipped
                      status_label: Shipped
                      deep_link_url: /integrations/shipstation/7/orders/3321
                      external_url: https://ship.shipstation.com/orders/all-orders-search-result?quickSearch=C604018.3
                      last_synced_at: '2026-06-24T01:00:00+00:00'
                      shipped: true
                      marked_shipped_without_label: false
                      attached_to: null
                      link_state: orphan_importable
                      link_state_label: Importable
                      link_state_color: purple
                      suggested_action: import_fo_and_sof
                      items:
                      - sku: WIDGET-RED
                        name: Red Widget
                        quantity: 1
                        product_id: 55
                      shipments:
                      - external_shipment_id: 88812
                        tracking_number: 1Z999
                        tracking_url: https://ups.com/track?1Z999
                        carrier: ups
                        service: ups_ground
                        shipped_at: '2026-06-23T20:00:00+00:00'
                        delivery_status: null
                        voided: false
                      item_match:
                        matches: null
                        lines: []
                      discrepancy: null
                    summary:
                      matched: 1
                      item_mismatch: 1
                      orphan_linkable: 0
                      orphan_importable: 1
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: ''
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: orders:read
      operationId: get-api-sales-orders-salesorder-provider-fulfillment-snapshots
  /api/sales-orders/{salesOrder}/provider-fulfillment-snapshots/repair:
    post:
      tags:
      - Fulfillments
      summary: Repair Provider Fulfillment Orphan
      description: 'Link an orphan shipping-provider order (link_state `orphan_linkable`,
        suggested_action `link`) to an existing FulfillmentOrder / SalesOrderFulfillment
        already on this sales order whose lines cover the same products (Phase 2).
        Only links to an FO/SOF that does NOT already have an active (non-cancelled)
        provider order — two active provider orders on one FO is invalid. An orphan
        whose only match is already taken is classified `orphan_duplicate` (use Import)
        instead of `orphan_linkable`, and a repair attempt against it is rejected
        with 422. Use the `provider`, `integration_instance_id`, and `external_order_id`
        from the orphan returned by GET provider-fulfillment-snapshots.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Returns the refreshed reconciliation bundle (`snapshots`, `orphans`, `summary`)
        plus a `message` describing the link. The previously-orphaned record now appears
        under `snapshots[]` attached to its FO/SOF.


        Request body:

        - `provider` (string, required) — the carrier that owns the order (e.g. `starshipit`).

        - `integration_instance_id` (integer, optional) — the provider integration
        instance the order belongs to.

        - `external_order_id` (string, required) — the carrier-side order id.


        Authentication: Bearer token. Requires the `sales_orders.fulfill` permission.

        Gated by the `fulfillment.provider_snapshots_enabled` flag — 404 when disabled.

        Returns 422 when no matching FO/SOF exists to link to, the order is already
        linked, the order belongs to a different sales order, or the orphan can no
        longer be found.


        A tracking-based fallback supplements the SKU-set shipment matcher: when the
        orphan''s label/tracking matches a recorded fulfilled shipment that has no
        active provider order, the orphan links to that shipment even if their item
        sets differ (e.g. post-repair consolidated shipments).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                provider:
                  type: string
                integration_instance_id:
                  type: integer
                external_order_id:
                  type: string
              example:
                provider: starshipit
                integration_instance_id: 12
                external_order_id: '987654'
      parameters:
      - name: salesOrder
        in: path
        schema:
          type: integer
        required: true
        description: Sales order ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      snapshots:
                        type: array
                        items:
                          type: object
                          properties:
                            provider:
                              type: string
                            provider_label:
                              type: string
                            integration_instance_id:
                              type: integer
                            integration_instance_name:
                              type: string
                            external_order_id:
                              type: string
                            order_reference:
                              type: string
                            status:
                              type: string
                            status_label:
                              type: string
                            deep_link_url:
                              type: string
                            external_url:
                              type: string
                            last_synced_at:
                              type: string
                            shipped:
                              type: boolean
                            attached_to:
                              type: object
                              properties:
                                type:
                                  type: string
                                id:
                                  type: integer
                            link_state:
                              type: string
                            link_state_label:
                              type: string
                            link_state_color:
                              type: string
                            suggested_action:
                              type: string
                              nullable: true
                            items:
                              type: array
                              items:
                                type: object
                                properties:
                                  sku:
                                    type: string
                                  name:
                                    type: string
                                  quantity:
                                    type: integer
                                  product_id:
                                    type: integer
                            shipments:
                              type: array
                              items:
                                type: object
                                properties:
                                  external_shipment_id:
                                    type: string
                                  tracking_number:
                                    type: string
                                  tracking_url:
                                    type: string
                                  carrier:
                                    type: string
                                  service:
                                    type: string
                                  shipped_at:
                                    type: string
                                  delivery_status:
                                    type: string
                                  voided:
                                    type: boolean
                            item_match:
                              type: object
                              properties:
                                matches:
                                  type: boolean
                                lines:
                                  type: array
                                  items:
                                    type: object
                                    properties:
                                      sku:
                                        type: string
                                      name:
                                        type: string
                                      our_qty:
                                        type: integer
                                      provider_qty:
                                        type: integer
                                      state:
                                        type: string
                      orphans:
                        type: array
                      summary:
                        type: object
                        properties:
                          matched:
                            type: integer
                          item_mismatch:
                            type: integer
                          orphan_linkable:
                            type: integer
                          orphan_importable:
                            type: integer
                  message:
                    type: string
                example:
                  data:
                    snapshots:
                    - provider: starshipit
                      provider_label: Starshipit
                      integration_instance_id: 12
                      integration_instance_name: AU Warehouse
                      external_order_id: '987654'
                      order_reference: C604018.1
                      status: shipped
                      status_label: Shipped
                      deep_link_url: /integrations/starshipit/12/orders/987654
                      external_url: https://app2.starshipit.com/orders/new/987654
                      last_synced_at: '2026-06-24T03:11:00+00:00'
                      shipped: true
                      attached_to:
                        type: sales_order_fulfillment
                        id: 9920
                      link_state: matched
                      link_state_label: Matched
                      link_state_color: success
                      suggested_action: null
                      items:
                      - sku: WIDGET-RED
                        name: Red Widget
                        quantity: 1
                        product_id: 55
                      shipments:
                      - external_shipment_id: PKG-9
                        tracking_number: ABX900
                        tracking_url: https://track.aus/ABX900
                        carrier: Australia Post
                        service: Express
                        shipped_at: '2026-06-24T02:55:00+00:00'
                        delivery_status: In Transit
                        voided: false
                      item_match:
                        matches: true
                        lines:
                        - sku: WIDGET-RED
                          name: Red Widget
                          our_qty: 1
                          provider_qty: 1
                          state: ok
                    orphans: []
                    summary:
                      matched: 1
                      item_mismatch: 0
                      orphan_linkable: 0
                      orphan_importable: 0
                  message: 'Linked Starshipit order C604018.1 to fulfillment #9920.'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 422 Reconciliation Failed
                  value:
                    error: No matching fulfillment order or shipment found to link
                      this provider order to.
                example-1:
                  summary: 422 Validation Error
                  value:
                    message: The external order id field is required.
                    errors:
                      external_order_id:
                      - The external order id field is required.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:write
      operationId: post-api-sales-orders-salesorder-provider-fulfillment-snapshots-repair
  /api/sales-orders/{salesOrder}/provider-fulfillment-snapshots/import:
    post:
      tags:
      - Fulfillments
      summary: Import Provider Fulfillment Orphan
      description: 'Create the SKU fulfillment entities for an orphan shipping-provider
        order with no counterpart (link_state `orphan_importable`) (Phase 3). When
        the provider order is not yet shipped (suggested_action `import_fo`) a FulfillmentOrder
        is created; when it is already shipped (suggested_action `import_fo_and_sof`)
        a FulfillmentOrder plus a SalesOrderFulfillment ship event with tracking is
        created. Provider item SKUs are matched against the sales order''s unfulfilled
        lines.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Import also resolves an `orphan_duplicate` (its products already fulfilled
        by an FO that has an active provider order). If the duplicate is still live
        at the carrier (suggested_action `void_and_import`) it is first voided there;
        then — or if it was already cancelled (suggested_action `import_voided_fo`)
        — it is recorded as a terminal voided "mirror" FulfillmentOrder linked to
        it, reserving no stock, so SKU mirrors the carrier 1:1.


        Returns the refreshed reconciliation bundle (`snapshots`, `orphans`, `summary`)
        plus a `message`; the imported record now appears under `snapshots[]` attached
        to the new FO/SOF.


        Request body:

        - `provider` (string, required) — the carrier that owns the order (e.g. `starshipit`).

        - `integration_instance_id` (integer, optional) — the provider integration
        instance the order belongs to.

        - `external_order_id` (string, required) — the carrier-side order id.


        Authentication: Bearer token. Requires the `sales_orders.fulfill` permission.

        Gated by the `fulfillment.provider_snapshots_enabled` flag — 404 when disabled.

        Returns 422 when the provider items cannot be matched to unfulfilled sales
        order lines, the order is already linked, the order belongs to a different
        sales order, or the orphan can no longer be found.


        Orphans flagged `marked_shipped_without_label` (shipped at the provider with
        no label purchased and no tracking) are imported as a terminal voided mirror
        fulfillment order (`external_type: provider_reconciliation_void_mirror`) with
        no carrier call, no shipment, and no inventory impact — message: "Recorded
        the {Provider} order (marked shipped, no label purchased) as voided fulfillment
        order #N on {order}."


        Tracking-match handling: a shipped orphan sharing a tracking number with a
        shipment already recorded on the order is never live-imported. If that shipment
        has no active provider order, the orphan is linked to it (response message:
        "Linked ... (same tracking)"); if the shipment is already provider-backed,
        the orphan is recorded as a voided mirror FO. A hand-typed "Mark as Shipped"
        tracking (payload externallyFulfilled=true) only counts as covered when it
        matches a recorded shipment — a unique typed tracking stays a live import.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                provider:
                  type: string
                integration_instance_id:
                  type: integer
                external_order_id:
                  type: string
              example:
                provider: starshipit
                integration_instance_id: 12
                external_order_id: '987654'
      parameters:
      - name: salesOrder
        in: path
        schema:
          type: integer
        required: true
        description: Sales order ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      snapshots:
                        type: array
                        items:
                          type: object
                          properties:
                            provider:
                              type: string
                            provider_label:
                              type: string
                            integration_instance_id:
                              type: integer
                            integration_instance_name:
                              type: string
                            external_order_id:
                              type: string
                            order_reference:
                              type: string
                            status:
                              type: string
                            status_label:
                              type: string
                            deep_link_url:
                              type: string
                            external_url:
                              type: string
                            last_synced_at:
                              type: string
                            shipped:
                              type: boolean
                            attached_to:
                              type: object
                              properties:
                                type:
                                  type: string
                                id:
                                  type: integer
                            link_state:
                              type: string
                            link_state_label:
                              type: string
                            link_state_color:
                              type: string
                            suggested_action:
                              type: string
                              nullable: true
                            items:
                              type: array
                              items:
                                type: object
                                properties:
                                  sku:
                                    type: string
                                  name:
                                    type: string
                                  quantity:
                                    type: integer
                                  product_id:
                                    type: integer
                            shipments:
                              type: array
                              items:
                                type: object
                                properties:
                                  external_shipment_id:
                                    type: string
                                  tracking_number:
                                    type: string
                                  tracking_url:
                                    type: string
                                  carrier:
                                    type: string
                                  service:
                                    type: string
                                  shipped_at:
                                    type: string
                                  delivery_status:
                                    type: string
                                  voided:
                                    type: boolean
                            item_match:
                              type: object
                              properties:
                                matches:
                                  type: boolean
                                lines:
                                  type: array
                                  items:
                                    type: object
                                    properties:
                                      sku:
                                        type: string
                                      name:
                                        type: string
                                      our_qty:
                                        type: integer
                                      provider_qty:
                                        type: integer
                                      state:
                                        type: string
                      orphans:
                        type: array
                      summary:
                        type: object
                        properties:
                          matched:
                            type: integer
                          item_mismatch:
                            type: integer
                          orphan_linkable:
                            type: integer
                          orphan_importable:
                            type: integer
                  message:
                    type: string
                example:
                  data:
                    snapshots:
                    - provider: starshipit
                      provider_label: Starshipit
                      integration_instance_id: 12
                      integration_instance_name: AU Warehouse
                      external_order_id: '987654'
                      order_reference: C604018.1
                      status: shipped
                      status_label: Shipped
                      deep_link_url: /integrations/starshipit/12/orders/987654
                      external_url: https://app2.starshipit.com/orders/new/987654
                      last_synced_at: '2026-06-24T03:11:00+00:00'
                      shipped: true
                      attached_to:
                        type: sales_order_fulfillment
                        id: 9920
                      link_state: matched
                      link_state_label: Matched
                      link_state_color: success
                      suggested_action: null
                      items:
                      - sku: WIDGET-RED
                        name: Red Widget
                        quantity: 1
                        product_id: 55
                      shipments:
                      - external_shipment_id: PKG-9
                        tracking_number: ABX900
                        tracking_url: https://track.aus/ABX900
                        carrier: Australia Post
                        service: Express
                        shipped_at: '2026-06-24T02:55:00+00:00'
                        delivery_status: In Transit
                        voided: false
                      item_match:
                        matches: true
                        lines:
                        - sku: WIDGET-RED
                          name: Red Widget
                          our_qty: 1
                          provider_qty: 1
                          state: ok
                    orphans: []
                    summary:
                      matched: 1
                      item_mismatch: 0
                      orphan_linkable: 0
                      orphan_importable: 0
                  message: 'Imported Starshipit order C604018.1 as fulfillment #9920.'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 422 Reconciliation Failed
                  value:
                    error: No matching fulfillment order or shipment found to link
                      this provider order to.
                example-1:
                  summary: 422 Validation Error
                  value:
                    message: The external order id field is required.
                    errors:
                      external_order_id:
                      - The external order id field is required.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:write
      operationId: post-api-sales-orders-salesorder-provider-fulfillment-snapshots-import
  /api/sales-order-fulfillments/deletable:
    post:
      tags:
      - Fulfillments
      summary: Check Fulfillments Deletable
      description: 'Check whether fulfillments can be voided (deleted). A fulfillment
        is not deletable when its linked shipping-provider order is already marked
        as shipped at the provider.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Body:

        - `ids` (array of integers, required, min 1) — fulfillment IDs to check. Unknown
        IDs fail validation with 422.


        Returns one entry per fulfillment with `deletable` and, when not deletable,
        a human-readable `reason`. Use before calling the void (DELETE) endpoint.


        Read-only — no external calls and no changes. Requires the `orders:write`
        token scope.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 4821
                - 4977
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        fulfillment_number:
                          type: string
                        deletable:
                          type: boolean
                        reason:
                          type: string
                          nullable: true
                example:
                  status: success
                  data:
                  - id: 4821
                    fulfillment_number: SO-10412.1
                    deletable: true
                    reason: null
                  - id: 4977
                    fulfillment_number: SO-10501.2
                    deletable: false
                    reason: The shipstation order marked as shipped, you can not delete
                      shipped fulfillment order
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      ids:
                        type: array
                        items:
                          type: string
                example:
                  message: The ids field is required.
                  errors:
                    ids:
                    - The ids field is required.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: orders:write
      operationId: post-api-sales-order-fulfillments-deletable
  /api/sales-order-fulfillments/{salesOrderFulfillmentId}/restore:
    post:
      tags:
      - Fulfillments
      summary: Restore Voided Shipment
      description: 'Restore (un-void) a previously voided shipment. No request body.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        The shipment returns to its pre-void status (typically `submitted`), and the
        void audit fields (`voided_at`, `voided_by`, `void_reason`) are cleared.


        Side effects:

        - Restoring back to a shipped status re-creates the inventory movements and
        cost-layer consumption that the void reversed, and re-marks allocations as
        fulfilled.

        - If the shipment''s sales-channel fulfillment (e.g. Shopify) was cancelled
        during the void, the channel submission is reset so a fresh fulfillment is
        pushed to the channel on the next sync.

        - Product inventory and average-cost figures are recalculated in the background.


        Errors (422):

        - the shipment is not voided (nothing to restore)

        - the shipment is part of a multi-shipment merge group and cannot be restored
        individually

        - insufficient allocation to restore a shipped fulfillment (the error names
        the SKU and quantities)


        Requires the `orders:write` token scope.'
      requestBody:
        content: {}
      parameters:
      - name: salesOrderFulfillmentId
        in: path
        schema:
          type: integer
        required: true
        description: Fulfillment (shipment) ID
        example: '4821'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                example:
                  status: success
                  message: The sales order fulfillment SO-10412.1 restored successfully
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      id:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: array
                example:
                  status: failure
                  message: Shipment SO-10412.1 is not voided, so there is nothing
                    to restore.
                  errors:
                    id:
                    - message: Shipment SO-10412.1 is not voided, so there is nothing
                        to restore.
                      code: RestoreShipmentIsUnacceptable
                      data: []
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:write
      operationId: post-api-sales-order-fulfillments-salesorderfulfillmentid-restore
  /api/sales-order-fulfillments/archive:
    put:
      tags:
      - Fulfillments
      summary: Bulk Archive Fulfillments
      description: 'Archive multiple fulfillments at once. Archived fulfillments are
        hidden from default list results but remain retrievable.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Body — either:

        - `ids` (array of integers) — explicit fulfillment IDs; or

        - `apply_to_all: true` with an optional `filters` object — archives every
        fulfillment matching the filters. The `filters` object accepts the same keys
        as the fulfillment list filters, e.g. `{"fulfillment_type": "manual", "voided":
        "exclude", "packing_slip_printed": "no", "integration_instance_ids": "1,2",
        "search": "SO-10412"}`.


        The response is always HTTP 200; check the JSON `status` field. Already-archived
        records are reported per ID under `warnings` and the overall `status` becomes
        `warning`.


        Requires the `orders:write` token scope.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 4821
                - 4977
                - 5010
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 OK
                  value:
                    status: success
                    message: 3/3 sales order fulfillments had been archived successfully
                example-1:
                  summary: 200 OK (some already archived)
                  value:
                    status: warning
                    message: 1/2 sales order fulfillments had been archived successfully
                    warnings:
                      ids.4977.id:
                      - message: The sales order fulfillment '4977' is already archived
                        code: SalesOrderFulfillmentIsAlreadyArchived
                        data: []
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: orders:write
      operationId: put-api-sales-order-fulfillments-archive
  /api/sales-order-fulfillments/unarchive:
    put:
      tags:
      - Fulfillments
      summary: Bulk Unarchive Fulfillments
      description: 'Unarchive multiple fulfillments at once, restoring them to default
        list results.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Body — either `ids` (array of integers) or `apply_to_all: true` with an optional
        `filters` object (same filter keys as Bulk Archive Fulfillments; include `"archived":
        "only"` to target archived records).


        The response is always HTTP 200; check the JSON `status` field. Records that
        are not archived are reported per ID under `warnings` and the overall `status`
        becomes `warning`.


        Requires the `orders:write` token scope.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 4821
                - 4977
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                example:
                  status: success
                  message: 2/2 sales order fulfillments had been un archived successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: orders:write
      operationId: put-api-sales-order-fulfillments-unarchive
  /api/sales-order-fulfillments/tracking-updates:
    put:
      tags:
      - Fulfillments
      summary: Bulk Request Fulfillment Tracking Updates
      description: 'Request fresh tracking information from shipping providers for
        the selected fulfillments.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Body:

        - `ids` (optional) — array of fulfillment IDs or a comma-separated string
        (`"4821,4977"`). Unknown IDs are ignored.


        Only fulfillments of type `starshipit`, `shipstation`, or `fba` that are not
        yet in `fulfilled` status are processed; all others are skipped silently.


        **May run asynchronously** — when more than 10 fulfillments match for a provider,
        the sync is queued as a background job and the response says so; smaller selections
        are polled inline against the provider before responding.


        Side effects: tracking numbers and URLs are written back, and a shipment found
        shipped/delivered at the provider transitions to `fulfilled` — which records
        inventory movements, consumes cost layers, and submits the fulfillment to
        the sales channel.


        Errors: 400 when the required shipping-provider integration is not connected,
        or when the provider API returns an error.


        Requires the `orders:write` token scope.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 4821
                - 4977
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 OK (processed inline)
                  value:
                    status: success
                    message: The tracking data of the selected fulfillments has been
                      updated
                example-1:
                  summary: 200 OK (queued)
                  value:
                    status: success
                    message: Added to the Queue, it will be processed shortly
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      request:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: array
                example:
                  status: failure
                  message: The system does not integrate with Starshipit
                  errors:
                    request:
                    - message: The system does not integrate with Starshipit
                      code: NotIntegrated
                      data: []
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: orders:write
      operationId: put-api-sales-order-fulfillments-tracking-updates
  /api/sales-order-fulfillments/{salesOrderFulfillmentId}/archive:
    put:
      tags:
      - Fulfillments
      summary: Archive Fulfillment
      description: 'Archive a single fulfillment. No request body. Archived fulfillments
        are hidden from default list results but remain retrievable.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        The response is always HTTP 200; if the fulfillment is already archived, the
        JSON `status` is `warning` with a per-field entry under `warnings`.


        Returns 404 for an unknown ID. Requires the `orders:write` token scope.'
      requestBody:
        content: {}
      parameters:
      - name: salesOrderFulfillmentId
        in: path
        schema:
          type: integer
        required: true
        description: Fulfillment (shipment) ID
        example: '4821'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 OK
                  value:
                    status: success
                    message: The sales order fulfillment 'SO-10412.1' archived successfully
                example-1:
                  summary: 200 OK (already archived)
                  value:
                    status: warning
                    message: The sales order fulfillment 'SO-10412.1' is already archived
                    warnings:
                      id:
                      - message: The sales order fulfillment 'SO-10412.1' is already
                          archived
                        code: SalesOrderFulfillmentIsAlreadyArchived
                        data:
                          id: '4821'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: orders:write
      operationId: put-api-sales-order-fulfillments-salesorderfulfillmentid-archive
  /api/sales-order-fulfillments/{salesOrderFulfillmentId}/unarchived:
    put:
      tags:
      - Fulfillments
      summary: Unarchive Fulfillment
      description: 'Unarchive a single fulfillment, restoring it to default list results.
        No request body.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Note the path segment is `unarchived` (the bulk endpoint uses `unarchive`).


        The response is always HTTP 200; if the fulfillment is not archived, the JSON
        `status` is `warning` with a per-field entry under `warnings`.


        Returns 404 for an unknown ID. Requires the `orders:write` token scope.'
      requestBody:
        content: {}
      parameters:
      - name: salesOrderFulfillmentId
        in: path
        schema:
          type: integer
        required: true
        description: Fulfillment (shipment) ID
        example: '4821'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                example:
                  status: success
                  message: The sales order fulfillment 'SO-10412.1' unarchived successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: orders:write
      operationId: put-api-sales-order-fulfillments-salesorderfulfillmentid-unarchived
  /api/sales-order-fulfillments/{salesOrderFulfillmentId}/mark-as-printed:
    put:
      tags:
      - Fulfillments
      summary: Mark Fulfillment as Printed
      description: 'Mark a fulfillment''s packing slip as printed by stamping `packing_slip_printed_at`
        with the current time. No request body.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Exporting a packing slip sets this stamp automatically; use this endpoint
        to set it manually (e.g. after printing through your own system).


        Note: the endpoint responds with success even if the ID does not exist (no
        404 is returned; zero rows are updated).


        Requires the `orders:write` token scope.'
      requestBody:
        content: {}
      parameters:
      - name: salesOrderFulfillmentId
        in: path
        schema:
          type: integer
        required: true
        description: Fulfillment (shipment) ID
        example: '4821'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                example:
                  status: success
                  message: The selected sales order fulfillment marked as printed
                    successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: orders:write
      operationId: put-api-sales-order-fulfillments-salesorderfulfillmentid-mark-as-printed
  /api/sales-orders/{salesOrderId}/payments/{payment}:
    delete:
      tags:
      - Merged Shipments
      summary: Delete Sales Order Payment
      description: 'Delete a payment from a sales order. Recalculates the order''s
        payment_status afterward.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Guard: When the payment was created by applying a store credit (Credit-type
        payment) and a matching SalesCreditAllocation row exists (same sales_order_id
        and amount), this endpoint returns 422. Use the Unallocate Sales Credit endpoint
        under Customers instead — it reverses both the allocation and the corresponding
        payment atomically.


        Authentication: Requires Bearer token.


        **Requires permission:** `sales_orders.manage_payments`'
      parameters:
      - name: salesOrderId
        in: path
        schema:
          type: integer
        required: true
        description: Sales Order ID
        example: '500'
      - name: payment
        in: path
        schema:
          type: integer
        required: true
        description: Payment ID
        example: '88'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      payments:
                        type: array
                  message:
                    type: string
                example:
                  data:
                    id: 500
                    payments: []
                  message: payment deleted successfully
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      payment:
                        type: array
                        items:
                          type: string
                example:
                  message: This payment was created by applying a store credit. Use
                    Unapply on the credit row to reverse it.
                  errors:
                    payment:
                    - This payment was created by applying a store credit. Use Unapply
                      on the credit row to reverse it.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:write
      operationId: delete-api-sales-orders-salesorderid-payments-payment
    put:
      tags:
      - Merged Shipments
      summary: Update Sales Order Payment
      description: 'Updates a payment on a sales order and recalculates the order''s
        payment status (unpaid / partially paid / paid) afterward.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Request body fields (all optional on update):

        - payment_type_id (integer): Must exist in payment types. Ignored when the
        payment is a system-created store-credit (`Credit`) payment — its type cannot
        be changed.

        - amount (number, < 100,000,000): A positive amount must not exceed the order''s
        remaining balance (the payment''s current amount is credited back before this
        check, so re-sending the same amount always passes). A negative amount is
        a refund and must not exceed the total already paid on the order.

        - payment_date (date): Payment date.

        - external_reference (string, max 255): External reference such as a cheque
        or transaction number.

        - currency_id (integer): Must exist in currencies.


        Behavior:

        - The payment must belong to the sales order in the path; otherwise a 422
        is returned.

        - The response `data` is the stored payment record (including its payment
        type), which is a fuller shape than the entries returned by the list endpoint.


        Path parameters:

        - salesOrderId (required): Sales Order ID.

        - payment (required): Payment ID.


        **Requires permission:** `sales_orders.manage_payments`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                amount:
                  type: integer
                payment_date:
                  type: string
                payment_type_id:
                  type: integer
                external_reference:
                  type: string
                currency_id:
                  type: integer
              example:
                amount: 120
                payment_date: '2026-07-01'
                payment_type_id: 3
                external_reference: 'CHECK # 039281'
                currency_id: 1
      parameters:
      - name: salesOrderId
        in: path
        schema:
          type: integer
        required: true
        description: Sales Order ID
        example: '500'
      - name: payment
        in: path
        schema:
          type: integer
        required: true
        description: Payment ID
        example: '88'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      link_type:
                        type: string
                      link_id:
                        type: integer
                      payment_date:
                        type: string
                      payment_type_id:
                        type: integer
                      external_reference:
                        type: string
                      type:
                        type: string
                      amount:
                        type: integer
                      cost:
                        type: string
                        nullable: true
                      currency_id:
                        type: integer
                      currency_rate:
                        type: integer
                      currency_id_tenant_snapshot:
                        type: integer
                      accounting_integration_id:
                        type: string
                        nullable: true
                      accounting_integration_type:
                        type: string
                        nullable: true
                      last_sync_error:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      payment_type:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          user_id:
                            type: string
                            nullable: true
                          accounting_integration_id:
                            type: string
                            nullable: true
                          accounting_integration_type:
                            type: string
                            nullable: true
                          archived_at:
                            type: string
                            nullable: true
                          created_at:
                            type: string
                          updated_at:
                            type: string
                  message:
                    type: string
                example:
                  data:
                    id: 88
                    link_type: App\Models\SalesOrder
                    link_id: 500
                    payment_date: '2026-07-01T00:00:00.000000Z'
                    payment_type_id: 3
                    external_reference: 'CHECK # 039281'
                    type: direct
                    amount: 120
                    cost: null
                    currency_id: 1
                    currency_rate: 1
                    currency_id_tenant_snapshot: 1
                    accounting_integration_id: null
                    accounting_integration_type: null
                    last_sync_error: null
                    created_at: '2026-06-28T16:40:12.000000Z'
                    updated_at: '2026-07-06T09:15:33.000000Z'
                    payment_type:
                      id: 3
                      name: Check
                      user_id: null
                      accounting_integration_id: null
                      accounting_integration_type: null
                      archived_at: null
                      created_at: '2025-11-02T10:00:00.000000Z'
                      updated_at: '2025-11-02T10:00:00.000000Z'
                  message: The sales order payment '88' updated successfully
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 422 Amount Exceeds Remaining Balance
                  value:
                    message: The provided amount is more than the remaining payment
                      on the sales order.
                    errors:
                      amount:
                      - The provided amount is more than the remaining payment on
                        the sales order.
                example-1:
                  summary: 422 Payment Does Not Belong to Order
                  value:
                    message: The sales order payment does not belong to the selected
                      sales order.
                    errors:
                      payment_id:
                      - The sales order payment does not belong to the selected sales
                        order.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:write
      operationId: put-api-sales-orders-salesorderid-payments-payment
  /api/sales-orders/{salesOrderId}/payments:
    post:
      tags:
      - Merged Shipments
      summary: Record Sales Order Payment
      description: 'Record a manual payment against a sales order and recalculate
        the order''s payment_status.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        **Request body:**

        - `payment_type_id` (integer, required) — must exist in payment_types.

        - `amount` (numeric, required, < 100,000,000) — positive records a payment;
        **negative** records a refund (creates a Refund sales credit and a matching
        positive payment against it); an amount exceeding the order balance creates
        an Overpayment sales credit for the excess.

        - `payment_date` (date, optional) — defaults to today (Y-m-d) when omitted.

        - `external_reference` (string, optional, max 255) — e.g. a cheque or transaction
        number.

        - `currency_id` (integer, optional) — defaults to the sales order''s currency
        when omitted.


        **Duplicate handling:** payments are unique on (payment_type_id, external_reference).
        Re-submitting an identical payment for the **same** order is idempotent (the
        existing payment is returned, no duplicate created). Reusing the same type+reference
        for a **different** payment (different owner/amount/date) returns **422**
        with an `external_reference` error — it no longer 500s.


        **Validation:** returns 422 if the order is already fully paid (positive amount),
        or if a refund exceeds the amount already paid.


        Authentication: Requires Bearer token.


        **Requires permission:** `sales_orders.manage_payments`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                payment_type_id:
                  type: integer
                amount:
                  type: number
                payment_date:
                  type: string
                external_reference:
                  type: string
                currency_id:
                  type: integer
              example:
                payment_type_id: 3
                amount: 149.99
                payment_date: '2026-07-06'
                external_reference: 'CHECK # 039281'
                currency_id: 1
      parameters:
      - name: salesOrderId
        in: path
        schema:
          type: integer
        required: true
        description: Sales Order ID
        example: '500'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      link_type:
                        type: string
                      link_id:
                        type: integer
                      payment_type_id:
                        type: integer
                      amount:
                        type: number
                      currency_id:
                        type: integer
                      payment_date:
                        type: string
                      external_reference:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 88
                    link_type: App\Models\SalesOrder
                    link_id: 500
                    payment_type_id: 3
                    amount: 149.99
                    currency_id: 1
                    payment_date: '2026-07-06'
                    external_reference: 'CHECK # 039281'
                  message: sales order payment created successfully
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 422 Duplicate Reference
                  value:
                    message: A payment with this type and reference already exists.
                      Please use a different reference.
                    errors:
                      external_reference:
                      - A payment with this type and reference already exists. Please
                        use a different reference.
                example-1:
                  summary: 422 Order Fully Paid
                  value:
                    message: The sales order is already fully paid.
                    errors:
                      amount:
                      - The sales order is already fully paid.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:write
      operationId: post-api-sales-orders-salesorderid-payments
    get:
      tags:
      - Merged Shipments
      summary: List Sales Order Payments
      description: 'Lists all payments recorded against a sales order.


        :::info[Required scope: `orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Response fields (per payment):

        - id (integer): Payment ID.

        - amount (number): Payment amount in the payment currency.

        - cost (number|null): Processing cost associated with the payment, when tracked.

        - payment_date (string): Payment date as a UTC datetime.

        - payment_type (object): `{id, name}` of the payment type (e.g. Check, Credit
        Card).

        - external_reference (string|null): External reference such as a cheque or
        transaction number.

        - type (string|null): `direct`, `overpayment`, `prepayment`, or null.

        - currency_code (string): ISO currency code of the payment.

        - sales_credit_allocation (object|null): `{id, sales_credit_id, sales_credit_number}`
        — set only on payments that were created by applying a store credit to the
        order. Such payments cannot be deleted directly; reverse them by unallocating
        the linked sales credit.


        Path parameters:

        - salesOrderId (required): Sales Order ID.


        Returns 404 when the sales order does not exist.'
      parameters:
      - name: salesOrderId
        in: path
        schema:
          type: integer
        required: true
        description: Sales Order ID
        example: '500'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        amount:
                          type: number
                        cost:
                          type: string
                          nullable: true
                        payment_date:
                          type: string
                        payment_type:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        external_reference:
                          type: string
                        type:
                          type: string
                        currency_code:
                          type: string
                        sales_credit_allocation:
                          type: string
                          nullable: true
                example:
                  data:
                  - id: 88
                    amount: 149.99
                    cost: null
                    payment_date: '2026-06-28T00:00:00.000000Z'
                    payment_type:
                      id: 3
                      name: Check
                    external_reference: 'CHECK # 039281'
                    type: direct
                    currency_code: USD
                    sales_credit_allocation: null
                  - id: 91
                    amount: 25
                    cost: null
                    payment_date: '2026-07-02T00:00:00.000000Z'
                    payment_type:
                      id: 7
                      name: Credit
                    external_reference: null
                    type: null
                    currency_code: USD
                    sales_credit_allocation:
                      id: 41
                      sales_credit_id: 205
                      sales_credit_number: SC-0205
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No query results for model.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: orders:read
      operationId: get-api-sales-orders-salesorderid-payments
  /api/v2/merged-shipments:
    get:
      tags:
      - Merged Shipments
      summary: List Merged Shipments
      description: 'Returns a paginated list of merged shipments (sales-order merge
        groups).


        :::info[Required scope: `orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Query Parameters:

        - page (integer): Page number (default 1)

        - per_page (integer): Items per page (default 10)

        - sort (string): One of id, merged_shipment_number, status, created_at, shipped_at.
        Prefix with - for descending. Default -id.

        - filter[id]: Exact match

        - filter[status]: Exact match on status enum (awaiting_pack, awaiting_label,
        awaiting_ship, shipped, cancelled, unmerged)

        - filter[warehouse_id]: Exact match

        - filter[merged_shipment_number]: Partial match

        - filter[open_only]: Boolean — restricts to in-progress merge groups (excludes
        cancelled/unmerged/shipped)'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        description: 'Page number (default: 1)'
        example: '1'
      - name: per_page
        in: query
        schema:
          type: integer
        description: 'Items per page (default: 10)'
        example: '10'
      - name: sort
        in: query
        schema:
          type: string
        description: 'Sort field. Prefix - for descending. Allowed: id, merged_shipment_number,
          status, created_at, shipped_at. Default: -id'
        example: -id
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        merged_shipment_number:
                          type: string
                        status:
                          type: string
                        status_label:
                          type: string
                        integration_instance_id:
                          type: integer
                        primary_sales_order_id:
                          type: integer
                        warehouse_id:
                          type: integer
                        tracking_number:
                          type: string
                          nullable: true
                        tracking_url:
                          type: string
                          nullable: true
                        fulfilled_shipping_method_id:
                          type: string
                          nullable: true
                        package_weight:
                          type: string
                          nullable: true
                        package_length:
                          type: string
                          nullable: true
                        package_width:
                          type: string
                          nullable: true
                        package_height:
                          type: string
                          nullable: true
                        notes:
                          type: string
                        metadata:
                          type: string
                          nullable: true
                        label_purchased_at:
                          type: string
                          nullable: true
                        shipped_at:
                          type: string
                          nullable: true
                        cancelled_at:
                          type: string
                          nullable: true
                        unmerged_at:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                        updated_at:
                          type: string
                        is_label_purchased:
                          type: boolean
                        is_shipped:
                          type: boolean
                        primary_sales_order:
                          type: object
                          properties:
                            id:
                              type: integer
                            sales_order_number:
                              type: string
                            order_date:
                              type: string
                            customer_name:
                              type: string
                        warehouse:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        creator:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        fulfilled_shipping_method:
                          type: string
                          nullable: true
                        fulfillments:
                          type: array
                          items:
                            type: object
                            properties:
                              id:
                                type: integer
                              fulfillment_number:
                                type: string
                              status:
                                type: string
                              sales_order_id:
                                type: integer
                              sales_order:
                                type: object
                                properties:
                                  id:
                                    type: integer
                                  sales_order_number:
                                    type: string
                                  order_status:
                                    type: string
                                  fulfillment_status:
                                    type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                  first_page_url:
                    type: string
                  last_page_url:
                    type: string
                  next_page_url:
                    type: string
                    nullable: true
                  prev_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  links:
                    type: array
                example:
                  data:
                  - id: 12
                    merged_shipment_number: MS-000012
                    status: awaiting_pack
                    status_label: Awaiting Pack
                    integration_instance_id: 3
                    primary_sales_order_id: 5501
                    warehouse_id: 1
                    tracking_number: null
                    tracking_url: null
                    fulfilled_shipping_method_id: null
                    package_weight: null
                    package_length: null
                    package_width: null
                    package_height: null
                    notes: Merged at customer's request
                    metadata: null
                    label_purchased_at: null
                    shipped_at: null
                    cancelled_at: null
                    unmerged_at: null
                    created_at: '2026-05-04T15:23:11.000000Z'
                    updated_at: '2026-05-04T15:23:11.000000Z'
                    is_label_purchased: false
                    is_shipped: false
                    primary_sales_order:
                      id: 5501
                      sales_order_number: SO-2026-5501
                      order_date: '2026-05-04'
                      customer_name: Jane Doe
                    warehouse:
                      id: 1
                      name: Main Warehouse
                    creator:
                      id: 7
                      name: Kalvin Mizzi
                    fulfilled_shipping_method: null
                    fulfillments:
                    - id: 9001
                      fulfillment_number: F-9001
                      status: submitted
                      sales_order_id: 5501
                      sales_order:
                        id: 5501
                        sales_order_number: SO-2026-5501
                        order_status: open
                        fulfillment_status: pending
                    - id: 9002
                      fulfillment_number: F-9002
                      status: submitted
                      sales_order_id: 5502
                      sales_order:
                        id: 5502
                        sales_order_number: SO-2026-5502
                        order_status: open
                        fulfillment_status: pending
                  current_page: 1
                  last_page: 1
                  per_page: 10
                  total: 1
                  from: 1
                  to: 1
                  first_page_url: '{{protocol}}{{domain}}/api/v2/merged-shipments?page=1'
                  last_page_url: '{{protocol}}{{domain}}/api/v2/merged-shipments?page=1'
                  next_page_url: null
                  prev_page_url: null
                  path: '{{protocol}}{{domain}}/api/v2/merged-shipments'
                  links: []
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: orders:read
      operationId: get-api-v2-merged-shipments
    post:
      tags:
      - Merged Shipments
      summary: Create Merged Shipment
      description: 'Merges two or more sales orders into a single physical shipment
        (merge group). Each underlying sales order remains intact; one fulfillment
        per SO is created and linked to the new merge group. The lowest-ID order is
        the primary.


        Authentication: Requires Bearer token.


        Request Body:

        - sales_order_ids (required, integer[]): Two or more sales order IDs to merge

        - notes (optional, string, max 2000): Free-form notes attached to the merge
        group

        - acknowledge_warnings (optional, boolean): If true, allows merging despite
        warnings (e.g. ship-by date variance). Blockers always prevent merging.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                sales_order_ids:
                  type: array
                  items:
                    type: integer
                notes:
                  type: string
                acknowledge_warnings:
                  type: boolean
              example:
                sales_order_ids:
                - 5501
                - 5502
                notes: Merged at customer's request
                acknowledge_warnings: false
      parameters: []
      responses:
        '201':
          description: Created
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      merged_shipment_number:
                        type: string
                      status:
                        type: string
                      status_label:
                        type: string
                      integration_instance_id:
                        type: integer
                      primary_sales_order_id:
                        type: integer
                      warehouse_id:
                        type: integer
                      tracking_number:
                        type: string
                        nullable: true
                      tracking_url:
                        type: string
                        nullable: true
                      fulfilled_shipping_method_id:
                        type: string
                        nullable: true
                      package_weight:
                        type: string
                        nullable: true
                      package_length:
                        type: string
                        nullable: true
                      package_width:
                        type: string
                        nullable: true
                      package_height:
                        type: string
                        nullable: true
                      notes:
                        type: string
                      metadata:
                        type: string
                        nullable: true
                      label_purchased_at:
                        type: string
                        nullable: true
                      shipped_at:
                        type: string
                        nullable: true
                      cancelled_at:
                        type: string
                        nullable: true
                      unmerged_at:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      is_label_purchased:
                        type: boolean
                      is_shipped:
                        type: boolean
                      primary_sales_order:
                        type: object
                        properties:
                          id:
                            type: integer
                          sales_order_number:
                            type: string
                          order_date:
                            type: string
                          customer_name:
                            type: string
                      warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      creator:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      fulfilled_shipping_method:
                        type: string
                        nullable: true
                      fulfillments:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            fulfillment_number:
                              type: string
                            status:
                              type: string
                            sales_order_id:
                              type: integer
                            sales_order:
                              type: object
                              properties:
                                id:
                                  type: integer
                                sales_order_number:
                                  type: string
                                order_status:
                                  type: string
                                fulfillment_status:
                                  type: string
                example:
                  data:
                    id: 12
                    merged_shipment_number: MS-000012
                    status: awaiting_pack
                    status_label: Awaiting Pack
                    integration_instance_id: 3
                    primary_sales_order_id: 5501
                    warehouse_id: 1
                    tracking_number: null
                    tracking_url: null
                    fulfilled_shipping_method_id: null
                    package_weight: null
                    package_length: null
                    package_width: null
                    package_height: null
                    notes: Merged at customer's request
                    metadata: null
                    label_purchased_at: null
                    shipped_at: null
                    cancelled_at: null
                    unmerged_at: null
                    created_at: '2026-05-04T15:23:11.000000Z'
                    updated_at: '2026-05-04T15:23:11.000000Z'
                    is_label_purchased: false
                    is_shipped: false
                    primary_sales_order:
                      id: 5501
                      sales_order_number: SO-2026-5501
                      order_date: '2026-05-04'
                      customer_name: Jane Doe
                    warehouse:
                      id: 1
                      name: Main Warehouse
                    creator:
                      id: 7
                      name: Kalvin Mizzi
                    fulfilled_shipping_method: null
                    fulfillments:
                    - id: 9001
                      fulfillment_number: F-9001
                      status: submitted
                      sales_order_id: 5501
                      sales_order:
                        id: 5501
                        sales_order_number: SO-2026-5501
                        order_status: open
                        fulfillment_status: pending
                    - id: 9002
                      fulfillment_number: F-9002
                      status: submitted
                      sales_order_id: 5502
                      sales_order:
                        id: 5502
                        sales_order_number: SO-2026-5502
                        order_status: open
                        fulfillment_status: pending
        '422':
          description: Unprocessable Entity
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 422 Not Eligible
                  value:
                    message: Sales orders are not eligible to be merged.
                    eligibility:
                      is_eligible: false
                      primary_sales_order_id: 5501
                      warehouse_id: null
                      integration_instance_id: 3
                      shipping_address_signature: null
                      member_sales_order_ids:
                      - 5501
                      - 5502
                      has_blockers: true
                      has_warnings: false
                      blockers:
                      - code: shipping_address_mismatch
                        message: Sales orders have different shipping addresses.
                        sales_order_id: 5502
                      warnings: []
                example-1:
                  summary: 422 Validation Failed
                  value:
                    message: At least two sales orders are required to create a merged
                      shipment.
                    errors:
                      sales_order_ids:
                      - At least two sales orders are required to create a merged
                        shipment.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-v2-merged-shipments
  /api/v2/merged-shipments/eligibility:
    post:
      tags:
      - Merged Shipments
      summary: Check Merge Eligibility
      description: 'Evaluates whether a set of sales orders can be merged into a single
        physical shipment. Returns blockers (hard failures) and warnings (acknowledgeable
        issues). Does not perform the merge.


        Authentication: Requires Bearer token.


        Request Body:

        - sales_order_ids (required, integer[]): Two or more sales order IDs to evaluate

        - proposed_warehouse_id (optional, integer): Override the inferred fulfilling
        warehouse'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                sales_order_ids:
                  type: array
                  items:
                    type: integer
                proposed_warehouse_id:
                  type: integer
              example:
                sales_order_ids:
                - 5501
                - 5502
                proposed_warehouse_id: 1
      parameters: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 Eligible
                  value:
                    data:
                      is_eligible: true
                      primary_sales_order_id: 5501
                      warehouse_id: 1
                      integration_instance_id: 3
                      shipping_address_signature: a3f9c1d8b2e7...
                      member_sales_order_ids:
                      - 5501
                      - 5502
                      has_blockers: false
                      has_warnings: false
                      blockers: []
                      warnings: []
                example-1:
                  summary: 200 Has Blockers
                  value:
                    data:
                      is_eligible: false
                      primary_sales_order_id: 5501
                      warehouse_id: null
                      integration_instance_id: 3
                      shipping_address_signature: null
                      member_sales_order_ids:
                      - 5501
                      - 5502
                      has_blockers: true
                      has_warnings: false
                      blockers:
                      - code: shipping_address_mismatch
                        message: Sales orders have different shipping addresses.
                        sales_order_id: 5502
                      warnings: []
        '422':
          description: Unprocessable Entity
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      sales_order_ids:
                        type: array
                        items:
                          type: string
                example:
                  message: At least two sales orders are required to check merge eligibility.
                  errors:
                    sales_order_ids:
                    - At least two sales orders are required to check merge eligibility.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-v2-merged-shipments-eligibility
  /api/v2/merged-shipments/{mergedShipment}:
    get:
      tags:
      - Merged Shipments
      summary: Get Merged Shipment
      description: 'Returns a single merged shipment with primary sales order, warehouse,
        creator, shipping method, and per-SO fulfillments eager-loaded.


        :::info[Required scope: `orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Path Parameters:

        - mergedShipment (integer): ID of the merge group'
      parameters:
      - name: mergedShipment
        in: path
        schema:
          type: string
        required: true
        description: The merged shipment ID.
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      merged_shipment_number:
                        type: string
                      status:
                        type: string
                      status_label:
                        type: string
                      integration_instance_id:
                        type: integer
                      primary_sales_order_id:
                        type: integer
                      warehouse_id:
                        type: integer
                      tracking_number:
                        type: string
                        nullable: true
                      tracking_url:
                        type: string
                        nullable: true
                      fulfilled_shipping_method_id:
                        type: string
                        nullable: true
                      package_weight:
                        type: string
                        nullable: true
                      package_length:
                        type: string
                        nullable: true
                      package_width:
                        type: string
                        nullable: true
                      package_height:
                        type: string
                        nullable: true
                      notes:
                        type: string
                      metadata:
                        type: string
                        nullable: true
                      label_purchased_at:
                        type: string
                        nullable: true
                      shipped_at:
                        type: string
                        nullable: true
                      cancelled_at:
                        type: string
                        nullable: true
                      unmerged_at:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      is_label_purchased:
                        type: boolean
                      is_shipped:
                        type: boolean
                      primary_sales_order:
                        type: object
                        properties:
                          id:
                            type: integer
                          sales_order_number:
                            type: string
                          order_date:
                            type: string
                          customer_name:
                            type: string
                      warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      creator:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      fulfilled_shipping_method:
                        type: string
                        nullable: true
                      fulfillments:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            fulfillment_number:
                              type: string
                            status:
                              type: string
                            sales_order_id:
                              type: integer
                            sales_order:
                              type: object
                              properties:
                                id:
                                  type: integer
                                sales_order_number:
                                  type: string
                                order_status:
                                  type: string
                                fulfillment_status:
                                  type: string
                example:
                  data:
                    id: 12
                    merged_shipment_number: MS-000012
                    status: awaiting_pack
                    status_label: Awaiting Pack
                    integration_instance_id: 3
                    primary_sales_order_id: 5501
                    warehouse_id: 1
                    tracking_number: null
                    tracking_url: null
                    fulfilled_shipping_method_id: null
                    package_weight: null
                    package_length: null
                    package_width: null
                    package_height: null
                    notes: Merged at customer's request
                    metadata: null
                    label_purchased_at: null
                    shipped_at: null
                    cancelled_at: null
                    unmerged_at: null
                    created_at: '2026-05-04T15:23:11.000000Z'
                    updated_at: '2026-05-04T15:23:11.000000Z'
                    is_label_purchased: false
                    is_shipped: false
                    primary_sales_order:
                      id: 5501
                      sales_order_number: SO-2026-5501
                      order_date: '2026-05-04'
                      customer_name: Jane Doe
                    warehouse:
                      id: 1
                      name: Main Warehouse
                    creator:
                      id: 7
                      name: Kalvin Mizzi
                    fulfilled_shipping_method: null
                    fulfillments:
                    - id: 9001
                      fulfillment_number: F-9001
                      status: submitted
                      sales_order_id: 5501
                      sales_order:
                        id: 5501
                        sales_order_number: SO-2026-5501
                        order_status: open
                        fulfillment_status: pending
                    - id: 9002
                      fulfillment_number: F-9002
                      status: submitted
                      sales_order_id: 5502
                      sales_order:
                        id: 5502
                        sales_order_number: SO-2026-5502
                        order_status: open
                        fulfillment_status: pending
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No query results for model
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: orders:read
      operationId: get-api-v2-merged-shipments-mergedshipment
  /api/v2/merged-shipments/{mergedShipment}/unmerge:
    post:
      tags:
      - Merged Shipments
      summary: Unmerge Merged Shipment
      description: 'Reverses a merge group, restoring each sales order to its pre-merge
        state. Only allowed before a label is purchased / the shipment is shipped.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Path Parameters:

        - mergedShipment (integer): ID of the merge group


        Request Body:

        - reason (optional, string, max 1000): Audit-trail reason for the unmerge'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                reason:
                  type: string
              example:
                reason: Customer requested separate shipments
      parameters:
      - name: mergedShipment
        in: path
        schema:
          type: string
        required: true
        description: The merged shipment ID.
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      merged_shipment_number:
                        type: string
                      status:
                        type: string
                      status_label:
                        type: string
                      integration_instance_id:
                        type: integer
                      primary_sales_order_id:
                        type: integer
                      warehouse_id:
                        type: integer
                      tracking_number:
                        type: string
                        nullable: true
                      tracking_url:
                        type: string
                        nullable: true
                      fulfilled_shipping_method_id:
                        type: string
                        nullable: true
                      package_weight:
                        type: string
                        nullable: true
                      package_length:
                        type: string
                        nullable: true
                      package_width:
                        type: string
                        nullable: true
                      package_height:
                        type: string
                        nullable: true
                      notes:
                        type: string
                      metadata:
                        type: string
                        nullable: true
                      label_purchased_at:
                        type: string
                        nullable: true
                      shipped_at:
                        type: string
                        nullable: true
                      cancelled_at:
                        type: string
                        nullable: true
                      unmerged_at:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      is_label_purchased:
                        type: boolean
                      is_shipped:
                        type: boolean
                      primary_sales_order:
                        type: object
                        properties:
                          id:
                            type: integer
                          sales_order_number:
                            type: string
                          order_date:
                            type: string
                          customer_name:
                            type: string
                      warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      creator:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      fulfilled_shipping_method:
                        type: string
                        nullable: true
                      fulfillments:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            fulfillment_number:
                              type: string
                            status:
                              type: string
                            sales_order_id:
                              type: integer
                            sales_order:
                              type: object
                              properties:
                                id:
                                  type: integer
                                sales_order_number:
                                  type: string
                                order_status:
                                  type: string
                                fulfillment_status:
                                  type: string
                example:
                  data:
                    id: 12
                    merged_shipment_number: MS-000012
                    status: unmerged
                    status_label: Unmerged
                    integration_instance_id: 3
                    primary_sales_order_id: 5501
                    warehouse_id: 1
                    tracking_number: null
                    tracking_url: null
                    fulfilled_shipping_method_id: null
                    package_weight: null
                    package_length: null
                    package_width: null
                    package_height: null
                    notes: Merged at customer's request
                    metadata: null
                    label_purchased_at: null
                    shipped_at: null
                    cancelled_at: null
                    unmerged_at: '2026-05-04T17:11:02.000000Z'
                    created_at: '2026-05-04T15:23:11.000000Z'
                    updated_at: '2026-05-04T15:23:11.000000Z'
                    is_label_purchased: false
                    is_shipped: false
                    primary_sales_order:
                      id: 5501
                      sales_order_number: SO-2026-5501
                      order_date: '2026-05-04'
                      customer_name: Jane Doe
                    warehouse:
                      id: 1
                      name: Main Warehouse
                    creator:
                      id: 7
                      name: Kalvin Mizzi
                    fulfilled_shipping_method: null
                    fulfillments:
                    - id: 9001
                      fulfillment_number: F-9001
                      status: submitted
                      sales_order_id: 5501
                      sales_order:
                        id: 5501
                        sales_order_number: SO-2026-5501
                        order_status: open
                        fulfillment_status: pending
                    - id: 9002
                      fulfillment_number: F-9002
                      status: submitted
                      sales_order_id: 5502
                      sales_order:
                        id: 5502
                        sales_order_number: SO-2026-5502
                        order_status: open
                        fulfillment_status: pending
        '422':
          description: Unprocessable Entity
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: This merge group can no longer be unmerged because a shipping
                    label has already been purchased.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:write
      operationId: post-api-v2-merged-shipments-mergedshipment-unmerge
  /api/v2/sales-orders/{salesOrder}/merge-candidates:
    get:
      tags:
      - Merged Shipments
      summary: List Merge Candidates for Sales Order
      description: 'Returns a list of open sales orders eligible to be merged into
        a single shipment with the anchor sales order.


        **Eligibility rules** — a candidate is included only if it:

        - Is not the anchor itself.

        - Has order_status of `open` or `reserved`.

        - Ships from the same single warehouse as the anchor (across all of its lines).

        - Has the same shipping address signature (name + company + address1 + address2
        + city + province + zip + country_code) as the anchor.

        - Is not already a member of any open SalesOrderMergeGroup.

        - Has no in-progress SalesOrderFulfillment (submitted, processing, or shipped).


        If the anchor itself has no shipping address, an empty list is returned.


        **Response shape** — `data[]` is an array of `MergeCandidateData`:

        - `sales_order_id` (int)

        - `sales_order_number` (string)

        - `order_status` (string — typically `open` or `reserved`)

        - `customer_name` (string | null)

        - `integration_instance_name` (string | null) — name of the sales channel''s
        integration instance, when applicable

        - `integration_instance_id` (int | null)

        - `line_count` (int)

        - `total_quantity` (int)

        - `integration_matches_anchor` (bool) — `false` when the candidate is from
        a different sales channel/integration than the anchor; the UI should warn
        before merging.


        **Auth:** Bearer token (scope `rw:orders`).'
      parameters:
      - name: limit
        in: query
        schema:
          type: integer
        description: 'Max candidates to return. Clamped to range 1-50. Default: 25.'
        example: '25'
      - name: salesOrder
        in: path
        schema:
          type: integer
        required: true
        description: ID of the anchor sales order. Returns other open sales orders
          that share its warehouse and shipping address signature.
        example: '5501'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: Success - Two Mergeable Candidates
                  value:
                    data:
                    - sales_order_id: 5502
                      sales_order_number: SO-2026-5502
                      order_status: open
                      customer_name: Jane Doe
                      integration_instance_name: Acme Shopify
                      integration_instance_id: 3
                      line_count: 2
                      total_quantity: 5
                      integration_matches_anchor: true
                    - sales_order_id: 5503
                      sales_order_number: SO-2026-5503
                      order_status: open
                      customer_name: Jane Doe
                      integration_instance_name: Acme Amazon US
                      integration_instance_id: 7
                      line_count: 1
                      total_quantity: 1
                      integration_matches_anchor: false
                example-1:
                  summary: Success - No Mergeable Candidates
                  value:
                    data: []
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No query results for model [App\Models\SalesOrder] 9999999.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-v2-sales-orders-salesorder-merge-candidates
  /api/v2/sales-orders/{salesOrder}/active-merge-group:
    get:
      tags:
      - Merged Shipments
      summary: Get Active Merge Group for Sales Order
      description: 'Returns the open merged shipment (not yet shipped, cancelled,
        or unmerged) that the sales order currently belongs to, with primary sales
        order, warehouse, creator, shipping method, and per-order fulfillments (including
        lines) eager-loaded. Returns `null` data when the order is not part of an
        active merge group.


        :::info[Required scope: `orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Path Parameters:

        - salesOrder (integer): ID of the sales order'
      parameters:
      - name: salesOrder
        in: path
        schema:
          type: integer
        required: true
        description: Sales order ID
        example: '5501'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 Active Merge Group
                  value:
                    data:
                      id: 12
                      merged_shipment_number: MS-000012
                      derived_status: submitted
                      derived_status_label: Submitted
                      integration_instance_id: 3
                      primary_sales_order_id: 5501
                      warehouse_id: 1
                      tracking_number: null
                      tracking_url: null
                      fulfilled_shipping_method_id: null
                      package_weight: null
                      package_length: null
                      package_width: null
                      package_height: null
                      notes: Merged at customer's request
                      metadata: null
                      label_purchased_at: null
                      shipped_at: null
                      cancelled_at: null
                      unmerged_at: null
                      created_at: '2026-07-04T15:23:11.000000Z'
                      updated_at: '2026-07-04T15:23:11.000000Z'
                      is_label_purchased: false
                      is_shipped: false
                      is_cancelled: false
                      is_unmerged: false
                      primary_sales_order:
                        id: 5501
                        sales_order_number: SO-2026-5501
                        order_date: '2026-07-04'
                        customer_name: Jane Doe
                      warehouse:
                        id: 1
                        name: Main Warehouse
                      creator:
                        id: 7
                        name: Kalvin Mizzi
                      fulfilled_shipping_method: null
                      fulfillments:
                      - id: 9001
                        fulfillment_number: F-9001
                        status: submitted
                        sales_order_id: 5501
                        sales_order:
                          id: 5501
                          sales_order_number: SO-2026-5501
                          order_status: open
                          fulfillment_status: unfulfilled
                        lines:
                        - id: 15601
                          sales_order_line_id: 8912
                          quantity: 2
                          sku: WIDGET-BLUE
                          product_name: Blue Widget
                          product_id: 341
                      - id: 9002
                        fulfillment_number: F-9002
                        status: submitted
                        sales_order_id: 5502
                        sales_order:
                          id: 5502
                          sales_order_number: SO-2026-5502
                          order_status: open
                          fulfillment_status: unfulfilled
                        lines:
                        - id: 15602
                          sales_order_line_id: 8955
                          quantity: 1
                          sku: WIDGET-RED
                          product_name: Red Widget
                          product_id: 355
                example-1:
                  summary: 200 No Active Merge Group
                  value:
                    data: null
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No query results for model
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: orders:read
      operationId: get-api-v2-sales-orders-salesorder-active-merge-group
  /api/sales-credits:
    get:
      tags:
      - Sales Credits
      summary: List Sales Credits
      description: 'Returns a paginated list of sales credits with standard list query
        parameters. Supports search, archiving filter, and column selection.


        Authentication: Requires Bearer token.


        This endpoint uses standard list query parameters. Common filters are passed
        as query parameters directly.


        Response is wrapped with table_specifications metadata when table_specifications
        parameter is provided.


        Totals fields:

        - total: total credit amount

        - refund_payments_total: sum of cash/card refunds against the credit (always
        positive)

        - applied_to_other_total: sum of credit consumed by Loop Returns EXC-* exchange
        orders (always positive)

        - fees_retained_total: sum of fees Loop withheld out of the customer''s credit
        — return shipping, restocking, etc. (always positive)

        - outstanding_amount: total minus (refund_payments_total + applied_to_other_total
        + fees_retained_total), clamped to zero (i.e., the unrefunded, unapplied balance
        still owed back to the customer)'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        description: 'Page number (default: 1)'
        example: '1'
      - name: limit
        in: query
        schema:
          type: integer
        description: 'Items per page (default: 10)'
        example: '10'
      - name: sort
        in: query
        schema:
          type: string
        description: 'Sort field and direction (prefix with - for descending). Common
          fields: id, credit_date, sales_credit_number, created_at, updated_at, archived_at'
      - name: search
        in: query
        schema:
          type: string
        description: Full-text search across sales credit number, customer name, order
          number, SKU
      - name: archived
        in: query
        schema:
          type: integer
        description: 0 = active only (default), 1 = archived only
        example: '0'
      - name: included[]
        in: query
        schema:
          type: string
        description: IDs to force include in results
      - name: excluded[]
        in: query
        schema:
          type: string
        description: IDs to force exclude from results
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        sales_credit_number:
                          type: string
                        credit_date:
                          type: string
                        is_for_overpayment:
                          type: boolean
                        created_at:
                          type: string
                        updated_at:
                          type: string
                        archived_at:
                          type: string
                          nullable: true
                        statuses:
                          type: object
                          properties:
                            credit_status:
                              type: string
                            return_status:
                              type: string
                        additional_credit:
                          type: number
                        tax_credit:
                          type: number
                        product_total:
                          type: number
                        total:
                          type: number
                        refund_payments_total:
                          type: number
                        applied_to_other_total:
                          type: number
                        fees_retained_total:
                          type: number
                        outstanding_amount:
                          type: number
                        currency_code:
                          type: string
                        sales_order_id:
                          type: integer
                        has_products:
                          type: boolean
                        has_rma:
                          type: boolean
                        payments:
                          type: array
                        exchange_orders:
                          type: array
                  per_page:
                    type: integer
                  total:
                    type: integer
                  last_page:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 55
                    sales_credit_number: SC-00055
                    credit_date: '2025-04-10'
                    is_for_overpayment: false
                    created_at: '2025-04-10T09:00:00.000000Z'
                    updated_at: '2025-04-10T09:00:00.000000Z'
                    archived_at: null
                    statuses:
                      credit_status: open
                      return_status: pending
                    additional_credit: 0.0
                    tax_credit: 0.0
                    product_total: 150.0
                    total: 150.0
                    refund_payments_total: 0.0
                    applied_to_other_total: 0.0
                    fees_retained_total: 0.0
                    outstanding_amount: 150.0
                    currency_code: USD
                    sales_order_id: 100
                    has_products: true
                    has_rma: false
                    payments: []
                    exchange_orders: []
                  per_page: 10
                  total: 5
                  last_page: 1
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-sales-credits
    post:
      tags:
      - Sales Credits
      summary: Create Sales Credit
      description: 'Creates a new sales credit. Must be linked to either a sales_order_id
        or a customer_id.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Fields:

        - sales_order_id (required if no customer_id): Sales order ID to credit against

        - customer_id (required if no sales_order_id): Customer ID for non-order credits

        - sales_credit_number (optional, max 255): Custom credit number (auto-generated
        if omitted)

        - credit_date (optional, date): Credit date

        - store_id (optional): Store ID

        - to_warehouse_id (optional): Return destination warehouse ID

        - sales_credit_note (optional): Free-form note

        - currency_id (optional): Currency ID (defaults to account default)

        - currency_code (optional): Currency code (alternative to currency_id)

        - tax_rate_id (optional): Tax rate ID

        - is_tax_included (optional, boolean): Whether prices include tax. Default:
        false

        - is_product (optional, boolean): Whether this is a product return. Default:
        false

        - tax_lines (optional): Array of tax line objects

        - sales_credit_lines (optional): Array of credit lines — each with sales_order_line_id,
        quantity, and price'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                sales_order_id:
                  type: integer
                sales_credit_number:
                  type: string
                credit_date:
                  type: string
                store_id:
                  type: integer
                to_warehouse_id:
                  type: integer
                sales_credit_note:
                  type: string
                currency_id:
                  type: integer
                tax_rate_id:
                  type: string
                  nullable: true
                is_tax_included:
                  type: boolean
                is_product:
                  type: boolean
                tax_lines:
                  type: array
                sales_credit_lines:
                  type: array
                  items:
                    type: object
                    properties:
                      sales_order_line_id:
                        type: integer
                      quantity:
                        type: integer
                      price:
                        type: integer
                      financial_line_id:
                        type: string
                        nullable: true
              example:
                sales_order_id: 100
                sales_credit_number: SC-MANUAL-001
                credit_date: '2025-04-10'
                store_id: 3
                to_warehouse_id: 1
                sales_credit_note: Customer returned damaged item
                currency_id: 1
                tax_rate_id: null
                is_tax_included: false
                is_product: true
                tax_lines: []
                sales_credit_lines:
                - sales_order_line_id: 201
                  quantity: 2
                  price: 75
                  financial_line_id: null
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      sales_credit_number:
                        type: string
                      total:
                        type: number
                      currency_code:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 56
                    sales_credit_number: SC-MANUAL-001
                    total: 150.0
                    currency_code: USD
                  message: sales credit created successfully
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      sales_order_id:
                        type: array
                        items:
                          type: string
                example:
                  message: The sales order id field is required when customer id is
                    not present.
                  errors:
                    sales_order_id:
                    - The sales order id field is required when customer id is not
                      present.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: orders:write
      operationId: post-api-sales-credits
    delete:
      tags:
      - Sales Credits
      summary: Bulk Delete Sales Credits
      description: 'Bulk deletes sales credits by IDs or by applying current filters.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Fields:

        - ids (required if apply_to_all is false): Array of sales credit IDs to delete

        - apply_to_all (optional, boolean): If true, deletes all records matching
        the current filters instead of specific IDs

        - filters (optional): Filter set to apply when apply_to_all is true'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: sales credits bulk deleted successfully
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: orders:write
      operationId: delete-api-sales-credits
  /api/sales-credits/{sales_credit}:
    get:
      tags:
      - Sales Credits
      summary: Get Sales Credit
      description: 'Returns a single sales credit with all relations: lines, store
        with address, sales order, RMA with receipts, payments, allocations, and accounting
        transaction.


        :::info[Required scope: `orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Totals fields:

        - total: total credit amount

        - refund_payments_total: sum of cash/card refunds against the credit (always
        positive)

        - applied_to_other_total: sum of credit consumed by Loop Returns EXC-* exchange
        orders (always positive)

        - fees_retained_total: sum of fees Loop withheld out of the customer''s credit
        — return shipping, restocking, etc. (always positive)

        - outstanding_amount: total minus (refund_payments_total + applied_to_other_total
        + fees_retained_total), clamped to zero (i.e., the unrefunded, unapplied balance
        still owed back to the customer)


        Response field `metadata` (object|null): minimal credit-source metadata for
        channel-synced credits - `source` (e.g. `ebay`, `shopify`, `woocommerce`)
        and `sales_channel_refund_id` (the channel refund ID). `null` for manually
        created credits. Used by the UI for the source chip on the sales order Credits
        tab.'
      parameters:
      - name: sales_credit
        in: path
        schema:
          type: integer
        required: true
        example: '55'
        description: The sales credit ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      sales_credit_number:
                        type: string
                      store:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          email:
                            type: string
                          address:
                            type: object
                            properties:
                              address1:
                                type: string
                              city:
                                type: string
                              province:
                                type: string
                              zip:
                                type: string
                              country:
                                type: string
                              country_code:
                                type: string
                      credit_date:
                        type: string
                      is_for_overpayment:
                        type: boolean
                      integration:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                      to_warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      returns_receipt_date:
                        type: string
                        nullable: true
                      returns_receipt_quantity:
                        type: integer
                      statuses:
                        type: object
                        properties:
                          credit_status:
                            type: string
                          return_status:
                            type: string
                      additional_credit:
                        type: number
                      tax_credit:
                        type: number
                      product_total:
                        type: number
                      total:
                        type: number
                      refund_payments_total:
                        type: number
                      applied_to_other_total:
                        type: number
                      fees_retained_total:
                        type: number
                      outstanding_amount:
                        type: number
                      currency_code:
                        type: string
                      tags:
                        type: array
                        items:
                          type: string
                      sales_order_id:
                        type: integer
                      sales_order:
                        type: object
                        properties:
                          id:
                            type: integer
                          sales_order_number:
                            type: string
                      sales_credit_lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            product_id:
                              type: integer
                            quantity:
                              type: integer
                            price:
                              type: number
                      line_item_count:
                        type: integer
                      total_quantity:
                        type: integer
                      first_line_sku:
                        type: string
                      exchange_orders:
                        type: array
                      payments:
                        type: array
                      has_products:
                        type: boolean
                      has_rma:
                        type: boolean
                      rma:
                        type: string
                        nullable: true
                      tax_lines:
                        type: array
                      tax_rate:
                        type: string
                        nullable: true
                      calculated_tax_total:
                        type: number
                      sales_credit_note:
                        type: string
                      metadata:
                        type: object
                        properties:
                          source:
                            type: string
                          sales_channel_refund_id:
                            type: string
                      is_tax_included:
                        type: boolean
                      tax_rate_id:
                        type: string
                        nullable: true
                example:
                  data:
                    id: 55
                    sales_credit_number: SC-00055
                    store:
                      id: 3
                      name: Main Store
                      email: store@example.com
                      address:
                        address1: 123 Main St
                        city: New York
                        province: NY
                        zip: '10001'
                        country: United States
                        country_code: US
                    credit_date: '2025-04-10'
                    is_for_overpayment: false
                    integration: Shopify
                    created_at: '2025-04-10T09:00:00.000000Z'
                    updated_at: '2025-04-10T09:00:00.000000Z'
                    archived_at: null
                    to_warehouse:
                      id: 1
                      name: Main Warehouse
                    returns_receipt_date: null
                    returns_receipt_quantity: 0
                    statuses:
                      credit_status: open
                      return_status: pending
                    additional_credit: 0.0
                    tax_credit: 5.0
                    product_total: 150.0
                    total: 155.0
                    refund_payments_total: 143.49
                    applied_to_other_total: 0.0
                    fees_retained_total: 0.0
                    outstanding_amount: 11.51
                    currency_code: USD
                    tags:
                    - returns
                    sales_order_id: 100
                    sales_order:
                      id: 100
                      sales_order_number: SO-00100
                    sales_credit_lines:
                    - id: 201
                      product_id: 12
                      quantity: 2
                      price: 75.0
                    line_item_count: 1
                    total_quantity: 2
                    first_line_sku: WIDGET-A
                    exchange_orders: []
                    payments: []
                    has_products: true
                    has_rma: false
                    rma: null
                    tax_lines: []
                    tax_rate: null
                    calculated_tax_total: 5.0
                    sales_credit_note: Customer damaged item
                    metadata:
                      source: ebay
                      sales_channel_refund_id: '5012345678'
                    is_tax_included: false
                    tax_rate_id: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:read
      operationId: get-api-sales-credits-sales-credit
    put:
      tags:
      - Sales Credits
      summary: Update Sales Credit
      description: 'Updates a sales credit including its lines. Lines array replaces
        all existing lines when provided; omit lines to leave them unchanged.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Fields:

        - sales_credit_number (optional, max 255): Custom credit number

        - credit_date (optional, date): Credit date

        - store_id (optional): Store ID

        - to_warehouse_id (optional): Return destination warehouse ID

        - customer_id (optional): Customer ID

        - sales_credit_note (optional): Free-form note

        - currency_id (optional): Currency ID

        - currency_code (optional): Currency code

        - tax_rate_id (optional): Tax rate ID

        - is_tax_included (optional, boolean): Whether prices include tax

        - is_product (optional, boolean): Whether this is a product return

        - tax_lines (optional): Array of tax line objects

        - sales_credit_lines (optional): Array of credit lines to sync'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                credit_date:
                  type: string
                sales_credit_note:
                  type: string
                to_warehouse_id:
                  type: integer
                tax_rate_id:
                  type: integer
                is_tax_included:
                  type: boolean
                sales_credit_lines:
                  type: array
                  items:
                    type: object
                    properties:
                      sales_order_line_id:
                        type: integer
                      quantity:
                        type: integer
                      price:
                        type: integer
              example:
                credit_date: '2025-04-12'
                sales_credit_note: 'Updated note: partial return'
                to_warehouse_id: 2
                tax_rate_id: 3
                is_tax_included: false
                sales_credit_lines:
                - sales_order_line_id: 201
                  quantity: 1
                  price: 75
      parameters:
      - name: sales_credit
        in: path
        schema:
          type: integer
        required: true
        example: '55'
        description: The sales credit ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      sales_credit_number:
                        type: string
                      credit_date:
                        type: string
                      total:
                        type: number
                  message:
                    type: string
                example:
                  data:
                    id: 55
                    sales_credit_number: SC-00055
                    credit_date: '2025-04-12'
                    total: 75.0
                  message: sales credit SC-00055 updated successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: orders:write
      operationId: put-api-sales-credits-sales-credit
    delete:
      tags:
      - Sales Credits
      summary: Delete Sales Credit
      description: 'Deletes a single sales credit.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: sales_credit
        in: path
        schema:
          type: integer
        required: true
        example: '55'
        description: The sales credit ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: sales credit SC-00055 deleted successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:write
      operationId: delete-api-sales-credits-sales-credit
  /api/sales-credits/archive:
    put:
      tags:
      - Sales Credits
      summary: Bulk Archive Sales Credits
      description: 'Bulk archives sales credits by IDs or by applying current filters.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Fields:

        - ids (required if apply_to_all is false): Array of sales credit IDs to archive

        - apply_to_all (optional, boolean): If true, archives all records matching
        current filters

        - filters (optional): Filter set to apply when apply_to_all is true'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
                apply_to_all:
                  type: boolean
                filters:
                  type: object
                  properties: {}
              example:
                ids:
                - 55
                - 56
                apply_to_all: false
                filters: {}
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: sales credits bulk archived successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: orders:write
      operationId: put-api-sales-credits-archive
  /api/sales-credits/unarchive:
    put:
      tags:
      - Sales Credits
      summary: Bulk Unarchive Sales Credits
      description: 'Bulk unarchives sales credits by IDs or by applying current filters.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Fields:

        - ids (required if apply_to_all is false): Array of sales credit IDs to unarchive

        - apply_to_all (optional, boolean): If true, unarchives all records matching
        current filters

        - filters (optional): Filter set to apply when apply_to_all is true'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
                apply_to_all:
                  type: boolean
                filters:
                  type: object
                  properties: {}
              example:
                ids:
                - 55
                - 56
                apply_to_all: false
                filters: {}
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: sales credits bulk unarchived successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: orders:write
      operationId: put-api-sales-credits-unarchive
  /api/sales-credits/deletable:
    post:
      tags:
      - Sales Credits
      summary: Check Sales Credits Deletable
      description: 'Checks whether each specified sales credit can be deleted (i.e.,
        is not used/linked to payments or other records). Returns deletability status
        and reason for each.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Fields:

        - ids (required): Array of sales credit IDs to check (min 1)'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 55
                - 56
                - 57
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        sales_credit_number:
                          type: string
                        deletable:
                          type: boolean
                        reason:
                          type: string
                          nullable: true
                example:
                  data:
                  - id: 55
                    sales_credit_number: SC-00055
                    deletable: true
                    reason: null
                  - id: 56
                    sales_credit_number: SC-00056
                    deletable: false
                    reason: Has associated payments
                  - id: 57
                    sales_credit_number: SC-00057
                    deletable: true
                    reason: null
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: orders:write
      operationId: post-api-sales-credits-deletable
  /api/sales-credits/{sales_credit}/archive:
    put:
      tags:
      - Sales Credits
      summary: Archive Sales Credit
      description: 'Archives a single sales credit. Returns a warning if already archived.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: sales_credit
        in: path
        schema:
          type: integer
        required: true
        example: '55'
        description: The sales credit ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: sales credit SC-00055 archived successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: orders:write
      operationId: put-api-sales-credits-sales-credit-archive
  /api/sales-credits/{sales_credit}/unarchived:
    put:
      tags:
      - Sales Credits
      summary: Unarchive Sales Credit
      description: 'Unarchives a single sales credit. Returns a warning if not archived.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: sales_credit
        in: path
        schema:
          type: integer
        required: true
        example: '55'
        description: The sales credit ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      sales_credit_number:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                  message:
                    type: string
                example:
                  data:
                    id: 55
                    sales_credit_number: SC-00055
                    archived_at: null
                  message: sales credit SC-00055 unarchived successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: orders:write
      operationId: put-api-sales-credits-sales-credit-unarchived
  /api/sales-credits/paid:
    post:
      tags:
      - Sales Credits
      summary: Record Sales Credit Payment
      description: 'Records a payment against a sales credit, marking it as paid.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Fields:

        - sales_credit_id (required): Sales credit ID to record payment for

        - payment_type_id (required): Payment type ID

        - payment_date (optional, date): Date of payment

        - amount (required, numeric, > 0): Payment amount — must not exceed remaining
        balance

        - external_reference (optional, max 255): External reference number

        - currency_id (optional): Currency ID'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                sales_credit_id:
                  type: integer
                payment_type_id:
                  type: integer
                payment_date:
                  type: string
                amount:
                  type: integer
                external_reference:
                  type: string
                currency_id:
                  type: integer
              example:
                sales_credit_id: 55
                payment_type_id: 2
                payment_date: '2025-04-15'
                amount: 150
                external_reference: REF-123456
                currency_id: 1
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      sales_credit_number:
                        type: string
                      statuses:
                        type: object
                        properties:
                          credit_status:
                            type: string
                      payments:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            amount:
                              type: number
                            payment_date:
                              type: string
                            external_reference:
                              type: string
                  message:
                    type: string
                example:
                  data:
                    id: 55
                    sales_credit_number: SC-00055
                    statuses:
                      credit_status: paid
                    payments:
                    - id: 88
                      amount: 150.0
                      payment_date: '2025-04-15'
                      external_reference: REF-123456
                  message: payment created successfully
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      amount:
                        type: array
                        items:
                          type: string
                example:
                  message: The amount must not be greater than the remaining balance.
                  errors:
                    amount:
                    - 'Max: 75.00'
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: orders:write
      operationId: post-api-sales-credits-paid
  /api/sales-credits/{salesCredit}/payments/{payment}:
    put:
      tags:
      - Sales Credits
      summary: Update Payment
      description: 'Updates an existing payment on a sales credit. All fields are
        optional (uses sometimes validation).


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Fields:

        - payment_date (optional, date): Updated payment date

        - amount (optional, numeric, > 0): Updated payment amount

        - external_reference (optional, max 255): External reference number

        - currency_id (optional): Currency ID'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                payment_date:
                  type: string
                amount:
                  type: integer
                external_reference:
                  type: string
                currency_id:
                  type: integer
              example:
                payment_date: '2025-04-16'
                amount: 120
                external_reference: REF-UPDATED
                currency_id: 1
      parameters:
      - name: salesCredit
        in: path
        schema:
          type: integer
        required: true
        example: '55'
        description: The sales credit ID.
      - name: payment
        in: path
        schema:
          type: integer
        required: true
        example: '88'
        description: The payment ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      payments:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            amount:
                              type: number
                            payment_date:
                              type: string
                  message:
                    type: string
                example:
                  data:
                    id: 55
                    payments:
                    - id: 88
                      amount: 120.0
                      payment_date: '2025-04-16'
                  message: payment created successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: orders:write
      operationId: put-api-sales-credits-salescredit-payments-payment
    delete:
      tags:
      - Sales Credits
      summary: Delete Payment
      description: 'Deletes a payment from a sales credit and recalculates the payment
        status.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: salesCredit
        in: path
        schema:
          type: integer
        required: true
        example: '55'
        description: The sales credit ID.
      - name: payment
        in: path
        schema:
          type: integer
        required: true
        example: '88'
        description: The payment ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      payments:
                        type: array
                  message:
                    type: string
                example:
                  data:
                    id: 55
                    payments: []
                  message: payment deleted successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:write
      operationId: delete-api-sales-credits-salescredit-payments-payment
  /api/sales-credits/{salesCredit}/notes:
    get:
      tags:
      - Sales Credits
      summary: List Notes
      description: 'Returns a paginated list of notes for a sales credit, ordered
        by created_at descending. Includes the note author.


        :::info[Required scope: `orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: salesCredit
        in: path
        schema:
          type: integer
        required: true
        example: '55'
        description: The sales credit ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        note:
                          type: string
                        created_at:
                          type: string
                        user:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 33
                    note: Customer confirmed return shipment sent
                    created_at: '2025-04-11T10:00:00.000000Z'
                    user:
                      id: 1
                      name: Admin User
                  per_page: 15
                  total: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:read
      operationId: get-api-sales-credits-salescredit-notes
    post:
      tags:
      - Sales Credits
      summary: Add Note
      description: 'Adds a note to a sales credit.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Fields:

        - note (required): Note text'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                note:
                  type: string
              example:
                note: Customer confirmed return shipment sent
      parameters:
      - name: salesCredit
        in: path
        schema:
          type: integer
        required: true
        example: '55'
        description: The sales credit ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      note:
                        type: string
                      created_at:
                        type: string
                      user:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                  message:
                    type: string
                example:
                  data:
                    id: 34
                    note: Customer confirmed return shipment sent
                    created_at: '2025-04-23T10:00:00.000000Z'
                    user:
                      id: 1
                      name: Admin User
                  message: note created successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: orders:write
      operationId: post-api-sales-credits-salescredit-notes
  /api/sales-credits/{salesCredit}/notes/{noteId}:
    delete:
      tags:
      - Sales Credits
      summary: Delete Note
      description: 'Deletes a note from a sales credit.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: salesCredit
        in: path
        schema:
          type: integer
        required: true
        example: '55'
        description: The sales credit ID.
      - name: noteId
        in: path
        schema:
          type: integer
        required: true
        example: '33'
        description: The note ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: note 33 deleted successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:write
      operationId: delete-api-sales-credits-salescredit-notes-noteid
  /api/sales-credits/{salesCredit}/generate-accounting-transaction:
    post:
      tags:
      - Sales Credits
      summary: Generate Accounting Transaction
      description: 'Generates an accounting transaction for the sales credit (e.g.,
        for syncing to accounting software like QuickBooks Online).


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: salesCredit
        in: path
        schema:
          type: integer
        required: true
        example: '55'
        description: The sales credit ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      reference:
                        type: string
                      amount:
                        type: number
                  message:
                    type: string
                example:
                  data:
                    id: 78
                    reference: SC-00055
                    amount: 150.0
                  message: Accounting transaction generated successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: orders:write
      operationId: post-api-sales-credits-salescredit-generate-accounting-transaction
  /api/sales-credits/{sales_credit}/invoice/preview:
    get:
      tags:
      - Sales Credits
      summary: Preview Invoice
      description: 'Generates a PDF invoice preview for the sales credit and returns
        the URL to the generated file.


        :::info[Required scope: `orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: sales_credit
        in: path
        schema:
          type: integer
        required: true
        example: '55'
        description: The sales credit ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      path:
                        type: string
                example:
                  data:
                    path: https://sku2.test/storage/reports/sales-credit-55-invoice.pdf
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:read
      operationId: get-api-sales-credits-sales-credit-invoice-preview
  /api/sales-credits/list/export:
    get:
      tags:
      - Sales Credits
      summary: Export Sales Credits
      description: 'Download an Excel/CSV export of sales credits.


        :::info[Required scope: `orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token (scope.rw:orders).


        Response: a binary file download (xlsx or csv), NOT JSON. Columns: ID, Credit
        #, Sales Order #, Store, Customer, Customer Email, Credit Date, Status, Payment
        Status, Currency, Tax Total, Total Credit, Refunded, Note, Created At.


        Query params:

        - format: xlsx (default) or csv

        - scope: ''filtered'' (default) or ''selected''

        - ids: comma-separated IDs (only when scope=selected)'
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: orders:read
      operationId: get-api-sales-credits-list-export
  /api/sales-credits/import/template:
    get:
      tags:
      - Sales Credits
      summary: Download Import Template
      description: 'Download a multi-sheet XLSX import template pre-filled with sample
        rows, a field guide, and reference data (stores, currencies, warehouses, tax
        rates, nominal codes) from your account.


        :::info[Required scope: `orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token (scope.rw:orders).


        Response: a binary XLSX file download, NOT JSON. Fill the ''Import Here''
        sheet, then upload it in the import wizard.'
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: orders:read
      operationId: get-api-sales-credits-import-template
  /api/sales-credits/import/validate:
    post:
      tags:
      - Sales Credits
      summary: Validate Import
      description: 'Validate and preview mapped import rows BEFORE importing. No database
        writes occur — safe to call repeatedly.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token (scope.rw:orders).


        Resolves customer / sales order / store / currency / warehouse / SKU / nominal
        code / tax rate names to IDs, groups flat rows into credits (by id, then sales_credit_number,
        then sales_order_number), and computes an upsert action per credit (create
        / update / blocked). Customers that don''t exist are auto-created on import.


        Each row accepts all template columns: id, sales_credit_number, credit_date,
        sales_order_number, customer_email, customer_id, customer_name, customer_company,
        customer_phone, store_name, currency_code, to_warehouse_name, sales_credit_note,
        sku, sales_order_line_id, description, quantity, amount, unit_cost, nominal_code,
        tax_rate, is_product.


        Max 50000 rows per call.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                rows:
                  type: array
                  items:
                    type: object
                    properties:
                      id:
                        type: string
                      sales_credit_number:
                        type: string
                      credit_date:
                        type: string
                      sales_order_number:
                        type: string
                      customer_email:
                        type: string
                      customer_id:
                        type: string
                      customer_name:
                        type: string
                      customer_company:
                        type: string
                      customer_phone:
                        type: string
                      store_name:
                        type: string
                      currency_code:
                        type: string
                      to_warehouse_name:
                        type: string
                      sales_credit_note:
                        type: string
                      sku:
                        type: string
                      sales_order_line_id:
                        type: string
                      description:
                        type: string
                      quantity:
                        type: string
                      amount:
                        type: string
                      unit_cost:
                        type: string
                      nominal_code:
                        type: string
                      tax_rate:
                        type: string
                      is_product:
                        type: string
              example:
                rows:
                - id: ''
                  sales_credit_number: SC-001
                  credit_date: '2026-04-01'
                  sales_order_number: ''
                  customer_email: jane@example.com
                  customer_id: ''
                  customer_name: Jane Doe
                  customer_company: ''
                  customer_phone: ''
                  store_name: ''
                  currency_code: USD
                  to_warehouse_name: Main Warehouse
                  sales_credit_note: Returned item
                  sku: WIDGET-001
                  sales_order_line_id: ''
                  description: Blue Widget - Large
                  quantity: '1'
                  amount: '19.99'
                  unit_cost: ''
                  nominal_code: ''
                  tax_rate: ''
                  is_product: 'true'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  sales_credits:
                    type: array
                    items:
                      type: object
                      properties:
                        group_key:
                          type: string
                        id:
                          type: string
                          nullable: true
                        sales_credit_number:
                          type: string
                        credit_date:
                          type: string
                        sales_credit_note:
                          type: string
                        action:
                          type: string
                        match_reason:
                          type: string
                          nullable: true
                        block_reason:
                          type: string
                          nullable: true
                        existing_sales_credit:
                          type: string
                          nullable: true
                        sales_order:
                          type: string
                          nullable: true
                        customer:
                          type: object
                          properties:
                            id:
                              type: string
                              nullable: true
                            email:
                              type: string
                            name:
                              type: string
                            will_create:
                              type: boolean
                        store:
                          type: string
                          nullable: true
                        currency:
                          type: object
                          properties:
                            id:
                              type: integer
                            code:
                              type: string
                        warehouse:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        errors:
                          type: array
                        lines:
                          type: array
                          items:
                            type: object
                            properties:
                              sku:
                                type: string
                              product_id:
                                type: integer
                              product_name:
                                type: string
                              sales_order_line_id:
                                type: string
                                nullable: true
                              description:
                                type: string
                              quantity:
                                type: integer
                              amount:
                                type: number
                              unit_cost:
                                type: string
                                nullable: true
                              nominal_code_id:
                                type: string
                                nullable: true
                              tax_rate_id:
                                type: string
                                nullable: true
                              is_product:
                                type: boolean
                              line_total:
                                type: number
                              errors:
                                type: array
                        total_quantity:
                          type: integer
                        total_amount:
                          type: number
                  summary:
                    type: object
                    properties:
                      total_sales_credits:
                        type: integer
                      total_line_items:
                        type: integer
                      total_errors:
                        type: integer
                      total_will_create:
                        type: integer
                      total_will_update:
                        type: integer
                      total_blocked:
                        type: integer
                      customers_created:
                        type: integer
                example:
                  sales_credits:
                  - group_key: scn:sc-001
                    id: null
                    sales_credit_number: SC-001
                    credit_date: '2026-04-01'
                    sales_credit_note: Returned item
                    action: create
                    match_reason: null
                    block_reason: null
                    existing_sales_credit: null
                    sales_order: null
                    customer:
                      id: null
                      email: jane@example.com
                      name: Jane Doe
                      will_create: true
                    store: null
                    currency:
                      id: 1
                      code: USD
                    warehouse:
                      id: 3
                      name: Main Warehouse
                    errors: []
                    lines:
                    - sku: WIDGET-001
                      product_id: 845
                      product_name: Blue Widget - Large
                      sales_order_line_id: null
                      description: Blue Widget - Large
                      quantity: 1
                      amount: 19.99
                      unit_cost: null
                      nominal_code_id: null
                      tax_rate_id: null
                      is_product: true
                      line_total: 19.99
                      errors: []
                    total_quantity: 1
                    total_amount: 19.99
                  summary:
                    total_sales_credits: 1
                    total_line_items: 1
                    total_errors: 0
                    total_will_create: 1
                    total_will_update: 0
                    total_blocked: 0
                    customers_created: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: orders:write
      operationId: post-api-sales-credits-import-validate
  /api/sales-credits/import:
    post:
      tags:
      - Sales Credits
      summary: Import Sales Credits
      description: 'Execute the import — upsert sales credits from validated data
        (typically the output of the Validate Import endpoint).


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token (scope.rw:orders).


        Upsert behavior:

        - Rows with no matched existing credit are CREATED (customers are auto-created
        when needed).

        - Rows matching an existing editable credit are UPDATED.

        - Rows with action=blocked are rejected (paid / allocated / closed / Shopify-origin
        credits cannot be updated via import).


        continue_on_error (default false): when true, each credit is imported in its
        own transaction and failures are collected into ''skipped''. When false, the
        entire import runs in one transaction.


        Returns 201 when any credit was created, otherwise 200.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                continue_on_error:
                  type: boolean
                sales_credits:
                  type: array
                  items:
                    type: object
                    properties:
                      group_key:
                        type: string
                      id:
                        type: string
                        nullable: true
                      action:
                        type: string
                      match_reason:
                        type: string
                        nullable: true
                      block_reason:
                        type: string
                        nullable: true
                      existing_sales_credit:
                        type: string
                        nullable: true
                      sales_credit_number:
                        type: string
                      credit_date:
                        type: string
                      sales_credit_note:
                        type: string
                      sales_order:
                        type: string
                        nullable: true
                      customer:
                        type: object
                        properties:
                          id:
                            type: string
                            nullable: true
                          email:
                            type: string
                          name:
                            type: string
                      store:
                        type: string
                        nullable: true
                      currency:
                        type: object
                        properties:
                          id:
                            type: integer
                          code:
                            type: string
                      warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      lines:
                        type: array
                        items:
                          type: object
                          properties:
                            sku:
                              type: string
                            product_id:
                              type: integer
                            product_name:
                              type: string
                            sales_order_line_id:
                              type: string
                              nullable: true
                            description:
                              type: string
                            quantity:
                              type: integer
                            amount:
                              type: number
                            unit_cost:
                              type: string
                              nullable: true
                            nominal_code_id:
                              type: string
                              nullable: true
                            tax_rate_id:
                              type: string
                              nullable: true
                            is_product:
                              type: boolean
              example:
                continue_on_error: false
                sales_credits:
                - group_key: scn:sc-001
                  id: null
                  action: create
                  match_reason: null
                  block_reason: null
                  existing_sales_credit: null
                  sales_credit_number: SC-001
                  credit_date: '2026-04-01'
                  sales_credit_note: Returned item
                  sales_order: null
                  customer:
                    id: null
                    email: jane@example.com
                    name: Jane Doe
                  store: null
                  currency:
                    id: 1
                    code: USD
                  warehouse:
                    id: 3
                    name: Main Warehouse
                  lines:
                  - sku: WIDGET-001
                    product_id: 845
                    product_name: Blue Widget - Large
                    sales_order_line_id: null
                    description: Blue Widget - Large
                    quantity: 1
                    amount: 19.99
                    unit_cost: null
                    nominal_code_id: null
                    tax_rate_id: null
                    is_product: true
      parameters: []
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  created:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        sales_credit_number:
                          type: string
                  updated:
                    type: array
                  skipped:
                    type: array
                  customers_created:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        email:
                          type: string
                  summary:
                    type: object
                    properties:
                      total:
                        type: integer
                      created:
                        type: integer
                      updated:
                        type: integer
                      skipped:
                        type: integer
                      customers_created:
                        type: integer
                example:
                  created:
                  - id: 301
                    sales_credit_number: SC-001
                  updated: []
                  skipped: []
                  customers_created:
                  - id: 99
                    name: Jane Doe
                    email: jane@example.com
                  summary:
                    total: 1
                    created: 1
                    updated: 0
                    skipped: 0
                    customers_created: 1
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 'Import failed: Sales credit #SC-009 is paid and cannot
                    be updated via import.'
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: orders:write
      operationId: post-api-sales-credits-import
  /api/sales-orders/{salesOrder}/channel-refund/context:
    get:
      tags:
      - Channel Refunds
      summary: Get Channel Refund Context
      description: 'Returns the refund capabilities and current refundable state for
        a sales order''s channel: per-line refundable quantities and amounts (net
        of refunds already recorded on the channel), refundable shipping, supported
        restock options and locations, required reason codes, and whether the channel
        processes refunds asynchronously.


        When the channel does not support API refunds, `supported` is false and `deep_link`
        (when available) points to the channel''s own refund page.


        Requires a Bearer token.

        - `capabilities.notice` (string|null) — channel-specific caveat rendered as
        an info alert in the refund dialog (e.g. Magento 1 credit memos are offline
        — no money moves on the channel).'
      parameters:
      - name: salesOrder
        in: path
        schema:
          type: integer
        required: true
        description: The sales order ID
        example: '500'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 Supported (Shopify)
                  value:
                    data:
                      supported: true
                      channel: shopify
                      instance_id: 3
                      currency_code: USD
                      async: false
                      capabilities:
                        supported: true
                        async: false
                        line_items: true
                        shipping: true
                        custom_amount: false
                        restock_options:
                        - return
                        - cancel
                        - no_restock
                        restock_locations:
                        - id: gid://shopify/Location/1
                          name: Main Warehouse
                        reasons: []
                        notify_customer: true
                        reason_required: false
                        deep_link: null
                        unsupported_reason: null
                        notice: null
                      previously_refunded_total: 0
                      pending_request_total: 0
                      shipping:
                        charged: 4.9
                        refunded: 0
                        refundable: 4.9
                      lines:
                      - sales_order_line_id: 991
                        channel_line_id: gid://shopify/LineItem/222
                        sku: BLU-W
                        description: Blue Widget
                        unit_price: 25.0
                        quantity_ordered: 2
                        quantity_refunded: 0
                        quantity_refundable: 2
                        tax_per_unit: 2.06
                        product_id: 42
                      deep_link: null
                      unsupported_reason: null
                example-1:
                  summary: 200 Unsupported (deep link fallback)
                  value:
                    data:
                      supported: false
                      channel: amazon
                      instance_id: null
                      currency_code: null
                      async: false
                      capabilities: null
                      previously_refunded_total: 0
                      pending_request_total: 0
                      shipping: null
                      lines: null
                      deep_link: https://sellercentral.amazon.com/orders-v3/order/111-2223334-5556667/refund
                      unsupported_reason: Amazon does not allow refunds through its
                        API. Issue the refund in Seller Central; the resulting credit
                        is imported automatically from settlement data.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-sales-orders-salesorder-channel-refund-context
  /api/sales-orders/{salesOrder}/channel-refunds:
    get:
      tags:
      - Channel Refunds
      summary: List Channel Refund Requests
      description: 'Lists every channel refund request recorded for the sales order,
        newest first, including status, amounts, the channel-side refund ID, and the
        linked sales credit once the refund has been confirmed and imported.


        Requires a Bearer token.'
      parameters:
      - name: salesOrder
        in: path
        schema:
          type: integer
        required: true
        description: The sales order ID
        example: '500'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        sales_order_id:
                          type: integer
                        channel:
                          type: string
                        status:
                          type: string
                        total_amount:
                          type: number
                        currency_code:
                          type: string
                        channel_refund_id:
                          type: string
                        sales_credit_id:
                          type: integer
                        sales_credit_number:
                          type: string
                        requested_by:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        request_payload:
                          type: object
                          properties:
                            lines:
                              type: array
                              items:
                                type: object
                                properties:
                                  sales_order_line_id:
                                    type: integer
                                  quantity:
                                    type: integer
                                  amount:
                                    type: number
                                  restock:
                                    type: string
                                  restock_location_id:
                                    type: string
                            shipping_amount:
                              type: number
                            custom_amount:
                              type: integer
                            reason:
                              type: string
                              nullable: true
                            note:
                              type: string
                            notify_customer:
                              type: boolean
                        error:
                          type: string
                          nullable: true
                        submitted_at:
                          type: string
                        completed_at:
                          type: string
                        created_at:
                          type: string
                example:
                  data:
                  - id: 17
                    sales_order_id: 500
                    channel: shopify
                    status: completed
                    total_amount: 31.9
                    currency_code: USD
                    channel_refund_id: '987654321'
                    sales_credit_id: 4521
                    sales_credit_number: SC-00231
                    requested_by:
                      id: 8
                      name: Jane Operator
                    request_payload:
                      lines:
                      - sales_order_line_id: 991
                        quantity: 1
                        amount: 25.0
                        restock: return
                        restock_location_id: gid://shopify/Location/1
                      shipping_amount: 4.9
                      custom_amount: 0
                      reason: null
                      note: Customer emailed photos of damage
                      notify_customer: true
                    error: null
                    submitted_at: '2026-07-10T18:22:04+00:00'
                    completed_at: '2026-07-10T18:22:09+00:00'
                    created_at: '2026-07-10T18:22:03+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-sales-orders-salesorder-channel-refunds
    post:
      tags:
      - Channel Refunds
      summary: Issue Channel Refund
      description: 'Creates and submits a refund to the order''s sales channel. Amounts
        are validated server-side against the channel''s refundable state: line quantities
        may not exceed the refundable quantity, line amounts may not exceed quantity
        times unit price, and the shipping amount may not exceed the refundable shipping.
        Line tax is added automatically to the total sent to the channel.


        Fields:

        - `lines` (array, required, may be empty when only shipping or a custom amount
        is refunded)

        - `lines[].sales_order_line_id` (integer, required) — must belong to the order

        - `lines[].quantity` (number, required, min 0)

        - `lines[].amount` (number, required, min 0) — product amount excluding tax

        - `lines[].restock` (string, optional: return | cancel | no_restock) — channels
        with restock support only

        - `lines[].restock_location_id` (string, optional) — channel location for
        restocking

        - `shipping_amount` (number, optional, min 0)

        - `custom_amount` (number, optional, min 0) — only on channels whose capabilities
        report `custom_amount: true`

        - `reason` (string, optional; required when capabilities report `reason_required:
        true` — use a value from `capabilities.reasons`)

        - `note` (string, optional, max 1000)

        - `notify_customer` (boolean, optional)


        Only one refund request may be in flight per order at a time; a second submission
        returns 409 until the first reaches a terminal state.


        Asynchronous channels (eBay) return `status: awaiting_channel`; the status
        updates automatically once the channel finishes processing.


        Requires a Bearer token and refund permission.

        - Each `lines[].sales_order_line_id` must be unique within the request (`distinct`
        validation) — duplicate entries are rejected with a 422 because their summed
        quantity could exceed the line''s refundable quantity.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                lines:
                  type: array
                  items:
                    type: object
                    properties:
                      sales_order_line_id:
                        type: integer
                      quantity:
                        type: integer
                      amount:
                        type: integer
                      restock:
                        type: string
                      restock_location_id:
                        type: string
                shipping_amount:
                  type: number
                custom_amount:
                  type: integer
                reason:
                  type: string
                note:
                  type: string
                notify_customer:
                  type: boolean
              example:
                lines:
                - sales_order_line_id: 991
                  quantity: 1
                  amount: 25
                  restock: return
                  restock_location_id: gid://shopify/Location/1
                shipping_amount: 4.9
                custom_amount: 0
                reason: damaged
                note: Customer emailed photos of damage
                notify_customer: true
      parameters:
      - name: salesOrder
        in: path
        schema:
          type: integer
        required: true
        description: The sales order ID
        example: '500'
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      sales_order_id:
                        type: integer
                      channel:
                        type: string
                      status:
                        type: string
                      total_amount:
                        type: number
                      currency_code:
                        type: string
                      channel_refund_id:
                        type: string
                      sales_credit_id:
                        type: integer
                      sales_credit_number:
                        type: string
                      requested_by:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      request_payload:
                        type: object
                        properties:
                          lines:
                            type: array
                            items:
                              type: object
                              properties:
                                sales_order_line_id:
                                  type: integer
                                quantity:
                                  type: integer
                                amount:
                                  type: number
                                restock:
                                  type: string
                                restock_location_id:
                                  type: string
                          shipping_amount:
                            type: number
                          custom_amount:
                            type: integer
                          reason:
                            type: string
                            nullable: true
                          note:
                            type: string
                          notify_customer:
                            type: boolean
                      error:
                        type: string
                        nullable: true
                      submitted_at:
                        type: string
                      completed_at:
                        type: string
                      created_at:
                        type: string
                example:
                  data:
                    id: 17
                    sales_order_id: 500
                    channel: shopify
                    status: completed
                    total_amount: 31.9
                    currency_code: USD
                    channel_refund_id: '987654321'
                    sales_credit_id: 4521
                    sales_credit_number: SC-00231
                    requested_by:
                      id: 8
                      name: Jane Operator
                    request_payload:
                      lines:
                      - sales_order_line_id: 991
                        quantity: 1
                        amount: 25.0
                        restock: return
                        restock_location_id: gid://shopify/Location/1
                      shipping_amount: 4.9
                      custom_amount: 0
                      reason: null
                      note: Customer emailed photos of damage
                      notify_customer: true
                    error: null
                    submitted_at: '2026-07-10T18:22:04+00:00'
                    completed_at: '2026-07-10T18:22:09+00:00'
                    created_at: '2026-07-10T18:22:03+00:00'
        '409':
          description: Conflict
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: A refund request is already in progress for this order.
                    Wait for it to finish before submitting another.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      lines.0:
                        type: array
                        items:
                          type: string
                example:
                  message: 'Refund quantity exceeds the refundable quantity for BLU-W
                    (refundable: 2).'
                  errors:
                    lines.0:
                    - 'Refund quantity exceeds the refundable quantity for BLU-W (refundable:
                      2).'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-sales-orders-salesorder-channel-refunds
  /api/channel-refund-requests/{channelRefundRequest}/retry:
    post:
      tags:
      - Channel Refunds
      summary: Retry Channel Refund Request
      description: 'Re-submits a failed refund request to the channel after re-validating
        it against the current refundable state. Only requests with status `failed`
        can be retried.


        Requires a Bearer token and refund permission.'
      requestBody:
        content: {}
      parameters:
      - name: channelRefundRequest
        in: path
        schema:
          type: integer
        required: true
        description: The channel refund request ID
        example: '17'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      sales_order_id:
                        type: integer
                      channel:
                        type: string
                      status:
                        type: string
                      total_amount:
                        type: number
                      currency_code:
                        type: string
                      channel_refund_id:
                        type: string
                      sales_credit_id:
                        type: integer
                      sales_credit_number:
                        type: string
                      requested_by:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      request_payload:
                        type: object
                        properties:
                          lines:
                            type: array
                            items:
                              type: object
                              properties:
                                sales_order_line_id:
                                  type: integer
                                quantity:
                                  type: integer
                                amount:
                                  type: number
                                restock:
                                  type: string
                                restock_location_id:
                                  type: string
                          shipping_amount:
                            type: number
                          custom_amount:
                            type: integer
                          reason:
                            type: string
                            nullable: true
                          note:
                            type: string
                          notify_customer:
                            type: boolean
                      error:
                        type: string
                        nullable: true
                      submitted_at:
                        type: string
                      completed_at:
                        type: string
                      created_at:
                        type: string
                example:
                  data:
                    id: 17
                    sales_order_id: 500
                    channel: shopify
                    status: completed
                    total_amount: 31.9
                    currency_code: USD
                    channel_refund_id: '987654321'
                    sales_credit_id: 4521
                    sales_credit_number: SC-00231
                    requested_by:
                      id: 8
                      name: Jane Operator
                    request_payload:
                      lines:
                      - sales_order_line_id: 991
                        quantity: 1
                        amount: 25.0
                        restock: return
                        restock_location_id: gid://shopify/Location/1
                      shipping_amount: 4.9
                      custom_amount: 0
                      reason: null
                      note: Customer emailed photos of damage
                      notify_customer: true
                    error: null
                    submitted_at: '2026-07-10T18:22:04+00:00'
                    completed_at: '2026-07-10T18:22:09+00:00'
                    created_at: '2026-07-10T18:22:03+00:00'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      status:
                        type: array
                        items:
                          type: string
                example:
                  message: Only failed refund requests can be retried.
                  errors:
                    status:
                    - Only failed refund requests can be retried.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-channel-refund-requests-channelrefundrequest-retry
  /api/channel-refund-requests/{channelRefundRequest}/check-status:
    post:
      tags:
      - Channel Refunds
      summary: Check Channel Refund Status
      description: 'Polls the sales channel for the outcome of an asynchronous refund
        request (for example an eBay refund still in `awaiting_channel`), updates
        the stored status, and links the resulting sales credit when the refund has
        been imported. Terminal requests are returned unchanged.


        Requires a Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: channelRefundRequest
        in: path
        schema:
          type: integer
        required: true
        description: The channel refund request ID
        example: '17'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      sales_order_id:
                        type: integer
                      channel:
                        type: string
                      status:
                        type: string
                      total_amount:
                        type: number
                      currency_code:
                        type: string
                      channel_refund_id:
                        type: string
                      sales_credit_id:
                        type: string
                        nullable: true
                      sales_credit_number:
                        type: string
                        nullable: true
                      requested_by:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      request_payload:
                        type: object
                        properties:
                          lines:
                            type: array
                            items:
                              type: object
                              properties:
                                sales_order_line_id:
                                  type: integer
                                quantity:
                                  type: integer
                                amount:
                                  type: number
                                restock:
                                  type: string
                                restock_location_id:
                                  type: string
                          shipping_amount:
                            type: number
                          custom_amount:
                            type: integer
                          reason:
                            type: string
                            nullable: true
                          note:
                            type: string
                          notify_customer:
                            type: boolean
                      error:
                        type: string
                        nullable: true
                      submitted_at:
                        type: string
                      completed_at:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                example:
                  data:
                    id: 17
                    sales_order_id: 500
                    channel: shopify
                    status: awaiting_channel
                    total_amount: 31.9
                    currency_code: USD
                    channel_refund_id: '987654321'
                    sales_credit_id: null
                    sales_credit_number: null
                    requested_by:
                      id: 8
                      name: Jane Operator
                    request_payload:
                      lines:
                      - sales_order_line_id: 991
                        quantity: 1
                        amount: 25.0
                        restock: return
                        restock_location_id: gid://shopify/Location/1
                      shipping_amount: 4.9
                      custom_amount: 0
                      reason: null
                      note: Customer emailed photos of damage
                      notify_customer: true
                    error: null
                    submitted_at: '2026-07-10T18:22:04+00:00'
                    completed_at: null
                    created_at: '2026-07-10T18:22:03+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-channel-refund-requests-channelrefundrequest-check-status
  /api/rmas:
    get:
      tags:
      - Returns & RMAs
      summary: List RMAs
      description: 'List all RMAs with pagination, filtering, and sorting via Spatie
        QueryBuilder.


        :::info[Required scope: `returns:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Filter system: Uses Spatie QueryBuilder filter syntax.

        - filter[search]: Searches rma_number and related sales_order_number

        - filter[status]: draft | approved | in_transit | received | closed | canceled

        - filter[customer_id]: Filters via associated sales order

        - filter[sales_order_id]: Exact match

        - Advanced text filters: filter[rma_number][is], [is_not], [contains], [does_not_contain],
        [starts_with], [ends_with], [is_empty], [is_not_empty]

        - Advanced date filters: filter[rma_date][from], [to], filter[created_at][from],
        [to]


        Allowed sorts: rma_number, status, rma_date, created_at. Default sort: -created_at.'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        description: 'Page number (default: 1)'
        example: '1'
      - name: per_page
        in: query
        schema:
          type: integer
        description: 'Items per page (default: 10)'
        example: '10'
      - name: sort
        in: query
        schema:
          type: string
        description: 'Sort field. Prefix with - for descending. Allowed: rma_number,
          status, rma_date, created_at'
        example: -created_at
      - name: filter[search]
        in: query
        schema:
          type: string
        description: Search by RMA number or sales order number
      - name: filter[status]
        in: query
        schema:
          type: string
        description: 'Filter by status: draft, approved, in_transit, received, closed,
          canceled'
      - name: filter[customer_id]
        in: query
        schema:
          type: string
        description: Filter by customer ID (searches via sales order)
      - name: filter[sales_order_id]
        in: query
        schema:
          type: string
        description: Filter by exact sales order ID
      - name: filter[rma_number][is]
        in: query
        schema:
          type: string
        description: Filter by exact RMA number
      - name: filter[rma_number][contains]
        in: query
        schema:
          type: string
        description: Filter RMA number containing value
      - name: filter[rma_date][from]
        in: query
        schema:
          type: string
        description: Filter RMA date from (Y-m-d)
      - name: filter[rma_date][to]
        in: query
        schema:
          type: string
        description: Filter RMA date to (Y-m-d)
      - name: filter[created_at][from]
        in: query
        schema:
          type: string
        description: Filter created_at from (Y-m-d)
      - name: filter[created_at][to]
        in: query
        schema:
          type: string
        description: Filter created_at to (Y-m-d)
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        rma_number:
                          type: string
                        status:
                          type: string
                        sales_order_id:
                          type: integer
                        sales_order:
                          type: object
                          properties:
                            id:
                              type: integer
                            sales_order_number:
                              type: string
                            order_date:
                              type: string
                        is_orphaned:
                          type: boolean
                        orphan_info:
                          type: string
                          nullable: true
                        customer_id:
                          type: integer
                        warehouse_id:
                          type: integer
                        warehouse:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            address:
                              type: string
                              nullable: true
                        notes:
                          type: string
                        tracking_number:
                          type: string
                          nullable: true
                        carrier:
                          type: string
                          nullable: true
                        shipped_at:
                          type: string
                          nullable: true
                        expected_at:
                          type: string
                          nullable: true
                        approved_at:
                          type: string
                        approved_by_user_id:
                          type: integer
                        rma_date:
                          type: string
                        is_amazon_fba_return:
                          type: boolean
                        rma_lines:
                          type: array
                          items:
                            type: object
                            properties:
                              id:
                                type: integer
                              product_id:
                                type: integer
                              product:
                                type: object
                                properties:
                                  id:
                                    type: integer
                                  sku:
                                    type: string
                                  name:
                                    type: string
                              expected_quantity:
                                type: integer
                              received_quantity:
                                type: integer
                              remaining_quantity:
                                type: integer
                              return_reason_id:
                                type: integer
                              notes:
                                type: string
                                nullable: true
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 1
                    rma_number: RMA-0001
                    status: approved
                    sales_order_id: 10
                    sales_order:
                      id: 10
                      sales_order_number: SO-0010
                      order_date: '2024-01-10'
                    is_orphaned: false
                    orphan_info: null
                    customer_id: 5
                    warehouse_id: 2
                    warehouse:
                      id: 2
                      name: Main Warehouse
                      address: null
                    notes: Customer returning defective unit
                    tracking_number: null
                    carrier: null
                    shipped_at: null
                    expected_at: null
                    approved_at: '2024-01-15T10:00:00.000000Z'
                    approved_by_user_id: 1
                    rma_date: '2024-01-14'
                    is_amazon_fba_return: false
                    rma_lines:
                    - id: 1
                      product_id: 20
                      product:
                        id: 20
                        sku: WIDGET-A
                        name: Widget A
                      expected_quantity: 2
                      received_quantity: 0
                      remaining_quantity: 2
                      return_reason_id: 1
                      notes: null
                    created_at: '2024-01-14T08:00:00.000000Z'
                    updated_at: '2024-01-15T10:00:00.000000Z'
                  current_page: 1
                  last_page: 3
                  per_page: 10
                  total: 27
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: returns:read
      operationId: get-api-rmas
    post:
      tags:
      - Returns & RMAs
      summary: Create RMA
      description: "Create a new RMA for a fulfilled sales order.\n\n:::info[Required\
        \ scope: `returns:write`]\nGrant this scope to your token under [Settings\
        \ → Developer → Personal Access Tokens](https://app.sku.io/settings/api).\n\
        :::\n\nAuthentication: Requires Bearer token.\n\nValidation rules:\n- sales_order_id:\
        \ required, must be an order that has been fulfilled (unless sales_credit_id\
        \ is provided)\n- warehouse_id: required\n- status: optional, allowed values:\
        \ draft, approved\n- notes: optional, max 1000 chars\n- sales_credit_id: optional,\
        \ if provided skips fulfillment and quantity validation\n- rma_lines: required\
        \ array with at least 1 line\n  - product_id: required\n  - expected_quantity:\
        \ required, min 1, cannot exceed fulfilled minus already RMA'd quantity\n\
        \  - sales_order_line_id: optional, must belong to the specified sales order\
        \ and match the product\n  - return_reason_id: optional\n  - notes: optional,\
        \ max 500 chars\n\n**Requires permission:** `returns.create`"
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                sales_order_id:
                  type: integer
                warehouse_id:
                  type: integer
                status:
                  type: string
                notes:
                  type: string
                sales_credit_id:
                  type: string
                  nullable: true
                rma_lines:
                  type: array
                  items:
                    type: object
                    properties:
                      product_id:
                        type: integer
                      expected_quantity:
                        type: integer
                      sales_order_line_id:
                        type: integer
                      return_reason_id:
                        type: integer
                      notes:
                        type: string
              example:
                sales_order_id: 10
                warehouse_id: 2
                status: draft
                notes: Customer returning 2 units of Widget A due to defect
                sales_credit_id: null
                rma_lines:
                - product_id: 20
                  expected_quantity: 2
                  sales_order_line_id: 55
                  return_reason_id: 1
                  notes: Unit arrived damaged
      parameters: []
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      rma_number:
                        type: string
                      status:
                        type: string
                      sales_order_id:
                        type: integer
                      sales_order:
                        type: object
                        properties:
                          id:
                            type: integer
                          sales_order_number:
                            type: string
                          order_date:
                            type: string
                      is_orphaned:
                        type: boolean
                      warehouse_id:
                        type: integer
                      warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          address:
                            type: string
                            nullable: true
                      notes:
                        type: string
                      rma_lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            product_id:
                              type: integer
                            product:
                              type: object
                              properties:
                                id:
                                  type: integer
                                sku:
                                  type: string
                                name:
                                  type: string
                            expected_quantity:
                              type: integer
                            received_quantity:
                              type: integer
                            remaining_quantity:
                              type: integer
                            return_reason_id:
                              type: integer
                            notes:
                              type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 15
                    rma_number: RMA-0015
                    status: draft
                    sales_order_id: 10
                    sales_order:
                      id: 10
                      sales_order_number: SO-0010
                      order_date: '2024-01-10'
                    is_orphaned: false
                    warehouse_id: 2
                    warehouse:
                      id: 2
                      name: Main Warehouse
                      address: null
                    notes: Customer returning 2 units of Widget A due to defect
                    rma_lines:
                    - id: 20
                      product_id: 20
                      product:
                        id: 20
                        sku: WIDGET-A
                        name: Widget A
                      expected_quantity: 2
                      received_quantity: 0
                      remaining_quantity: 2
                      return_reason_id: 1
                      notes: Unit arrived damaged
                    created_at: '2024-01-20T10:00:00.000000Z'
                    updated_at: '2024-01-20T10:00:00.000000Z'
                  message: RMA created successfully
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      rma_lines.0.expected_quantity:
                        type: array
                        items:
                          type: string
                example:
                  message: 'Cannot return more than 3 units for this line (fulfilled:
                    3, already in RMAs: 0).'
                  errors:
                    rma_lines.0.expected_quantity:
                    - 'Cannot return more than 3 units for this line (fulfilled: 3,
                      already in RMAs: 0).'
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: returns:write
      operationId: post-api-rmas
  /api/rmas/{rma}:
    get:
      tags:
      - Returns & RMAs
      summary: Get RMA
      description: 'Get a single RMA with full detail including lines, return receipts,
        sales credits, and approved-by user.


        :::info[Required scope: `returns:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Loads: salesOrder.customer, warehouse.address, approvedBy, rmaLines.product,
        rmaLines.returnReason, rmaLines.salesOrderLine, rmaLines.amazonFbaCustomerReturns,
        returnReceipts.receivedBy, returnReceipts.returnReceiptLines.product, returnReceipts.returnReceiptLines.returnReason,
        salesCredits.'
      parameters:
      - name: rma
        in: path
        schema:
          type: integer
        required: true
        description: RMA ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      rma_number:
                        type: string
                      status:
                        type: string
                      sales_order_id:
                        type: integer
                      sales_order:
                        type: object
                        properties:
                          id:
                            type: integer
                          sales_order_number:
                            type: string
                          order_date:
                            type: string
                      is_orphaned:
                        type: boolean
                      orphan_info:
                        type: string
                        nullable: true
                      customer_id:
                        type: integer
                      customer:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          email:
                            type: string
                          company:
                            type: string
                          phone:
                            type: string
                          address1:
                            type: string
                          city:
                            type: string
                          zip:
                            type: string
                          country:
                            type: string
                      warehouse_id:
                        type: integer
                      warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          address:
                            type: object
                            properties:
                              address1:
                                type: string
                              city:
                                type: string
                              zip:
                                type: string
                              country:
                                type: string
                              country_code:
                                type: string
                      notes:
                        type: string
                      tracking_number:
                        type: string
                      carrier:
                        type: string
                      shipped_at:
                        type: string
                      expected_at:
                        type: string
                      approved_at:
                        type: string
                      approved_by_user_id:
                        type: integer
                      approved_by:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      rma_date:
                        type: string
                      is_amazon_fba_return:
                        type: boolean
                      rma_lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            rma_id:
                              type: integer
                            product_id:
                              type: integer
                            product:
                              type: object
                              properties:
                                id:
                                  type: integer
                                sku:
                                  type: string
                                name:
                                  type: string
                            sales_order_line_id:
                              type: integer
                            sales_order_line:
                              type: object
                              properties:
                                id:
                                  type: integer
                                quantity:
                                  type: integer
                                amount:
                                  type: number
                            return_reason_id:
                              type: integer
                            return_reason:
                              type: object
                              properties:
                                id:
                                  type: integer
                                name:
                                  type: string
                            expected_quantity:
                              type: integer
                            received_quantity:
                              type: integer
                            remaining_quantity:
                              type: integer
                            notes:
                              type: string
                            amazon_fba_return:
                              type: string
                              nullable: true
                      return_receipts:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            rma_id:
                              type: integer
                            warehouse_id:
                              type: integer
                            warehouse:
                              type: object
                              properties:
                                id:
                                  type: integer
                                name:
                                  type: string
                            received_at:
                              type: string
                            received_by_user_id:
                              type: integer
                            received_by:
                              type: object
                              properties:
                                id:
                                  type: integer
                                name:
                                  type: string
                            notes:
                              type: string
                            return_receipt_lines:
                              type: array
                              items:
                                type: object
                                properties:
                                  id:
                                    type: integer
                                  product_id:
                                    type: integer
                                  product:
                                    type: object
                                    properties:
                                      id:
                                        type: integer
                                      sku:
                                        type: string
                                      name:
                                        type: string
                                  quantity:
                                    type: integer
                                  action:
                                    type: string
                                  return_reason:
                                    type: object
                                    properties:
                                      id:
                                        type: integer
                                      name:
                                        type: string
                            created_at:
                              type: string
                      sales_credits:
                        type: array
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 1
                    rma_number: RMA-0001
                    status: approved
                    sales_order_id: 10
                    sales_order:
                      id: 10
                      sales_order_number: SO-0010
                      order_date: '2024-01-10'
                    is_orphaned: false
                    orphan_info: null
                    customer_id: 5
                    customer:
                      id: 5
                      name: John Doe
                      email: john@example.com
                      company: Acme Corp
                      phone: +1-555-0100
                      address1: 123 Main St
                      city: Beverly Hills
                      zip: '90210'
                      country: US
                    warehouse_id: 2
                    warehouse:
                      id: 2
                      name: Main Warehouse
                      address:
                        address1: 500 Industrial Way
                        city: Glendale
                        zip: '91201'
                        country: United States
                        country_code: US
                    notes: Customer returning defective unit
                    tracking_number: 1Z999AA10123456784
                    carrier: UPS
                    shipped_at: '2024-01-16'
                    expected_at: '2024-01-20'
                    approved_at: '2024-01-15T10:00:00.000000Z'
                    approved_by_user_id: 1
                    approved_by:
                      id: 1
                      name: Admin User
                    rma_date: '2024-01-14'
                    is_amazon_fba_return: false
                    rma_lines:
                    - id: 1
                      rma_id: 1
                      product_id: 20
                      product:
                        id: 20
                        sku: WIDGET-A
                        name: Widget A
                      sales_order_line_id: 55
                      sales_order_line:
                        id: 55
                        quantity: 5
                        amount: 49.99
                      return_reason_id: 1
                      return_reason:
                        id: 1
                        name: Defective
                      expected_quantity: 2
                      received_quantity: 0
                      remaining_quantity: 2
                      notes: Unit arrived damaged
                      amazon_fba_return: null
                    return_receipts:
                    - id: 5
                      rma_id: 1
                      warehouse_id: 2
                      warehouse:
                        id: 2
                        name: Main Warehouse
                      received_at: '2024-01-21T09:00:00.000000Z'
                      received_by_user_id: 1
                      received_by:
                        id: 1
                        name: Admin User
                      notes: Received in good condition
                      return_receipt_lines:
                      - id: 8
                        product_id: 20
                        product:
                          id: 20
                          sku: WIDGET-A
                          name: Widget A
                        quantity: 2
                        action: added_to_stock
                        return_reason:
                          id: 1
                          name: Defective
                      created_at: '2024-01-21T09:00:00.000000Z'
                    sales_credits: []
                    created_at: '2024-01-14T08:00:00.000000Z'
                    updated_at: '2024-01-16T09:00:00.000000Z'
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No query results for model [App\Models\Rma] 999
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: returns:read
      operationId: get-api-rmas-rma
    put:
      tags:
      - Returns & RMAs
      summary: Update RMA
      description: 'Update an RMA''s warehouse and/or notes.


        :::info[Required scope: `returns:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Only warehouse_id (optional) and notes (optional, max 1000 chars) can be updated
        via this endpoint. Use the /approve, /shipping, etc. endpoints for status
        transitions.


        **Requires permission:** `returns.update`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                warehouse_id:
                  type: integer
                notes:
                  type: string
              example:
                warehouse_id: 3
                notes: Updated return notes — item is scratched, not broken
      parameters:
      - name: rma
        in: path
        schema:
          type: integer
        required: true
        description: RMA ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      rma_number:
                        type: string
                      status:
                        type: string
                      warehouse_id:
                        type: integer
                      notes:
                        type: string
                      updated_at:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 1
                    rma_number: RMA-0001
                    status: draft
                    warehouse_id: 3
                    notes: Updated return notes — item is scratched, not broken
                    updated_at: '2024-01-20T11:00:00.000000Z'
                  message: RMA updated successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: returns:write
      operationId: put-api-rmas-rma
    delete:
      tags:
      - Returns & RMAs
      summary: Delete RMA
      description: 'Delete an RMA. Only draft RMAs can typically be deleted. Returns
        422 if the RMA cannot be deleted.


        :::info[Required scope: `returns:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `returns.delete`'
      parameters:
      - name: rma
        in: path
        schema:
          type: integer
        required: true
        description: RMA ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: RMA deleted successfully
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Cannot delete a closed RMA.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: returns:write
      operationId: delete-api-rmas-rma
  /api/rmas/{rma}/approve:
    post:
      tags:
      - Returns & RMAs
      summary: Approve RMA
      description: 'Approve a draft RMA. Records the approving user and approval timestamp.


        :::info[Required scope: `returns:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Status transition: draft → approved


        **Requires permission:** `returns.approve`'
      requestBody:
        content: {}
      parameters:
      - name: rma
        in: path
        schema:
          type: integer
        required: true
        description: RMA ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      rma_number:
                        type: string
                      status:
                        type: string
                      approved_at:
                        type: string
                      approved_by:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                  message:
                    type: string
                example:
                  data:
                    id: 1
                    rma_number: RMA-0001
                    status: approved
                    approved_at: '2024-01-15T10:00:00.000000Z'
                    approved_by:
                      id: 1
                      name: Admin User
                  message: RMA approved successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: returns:write
      operationId: post-api-rmas-rma-approve
  /api/rmas/{rma}/cancel:
    post:
      tags:
      - Returns & RMAs
      summary: Cancel RMA
      description: 'Cancel an RMA and keep it on record (the RMA is not deleted).
        Only RMAs in a cancellable status (draft, approved, in_transit) with zero
        return receipts can be canceled — `can_be_canceled` on the resource reflects
        this.


        :::info[Required scope: `returns:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token. **Requires permission:** `returns.cancel`.


        Status transition: draft / approved / in_transit → canceled


        **Request body (optional):**

        - `cancellation_reason` (string, nullable, max 500) — audit note recorded
        alongside `canceled_at` and `canceled_by_user_id`.


        The response resource exposes the cancellation audit fields (`canceled_at`,
        `canceled_by_user_id`, `canceled_by`, `cancellation_reason`) and the capability
        flags (`can_be_canceled`, `can_be_deleted`).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                cancellation_reason:
                  type: string
              example:
                cancellation_reason: Customer decided to keep the item
      parameters:
      - name: rma
        in: path
        schema:
          type: integer
        required: true
        description: RMA ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      rma_number:
                        type: string
                      status:
                        type: string
                      canceled_at:
                        type: string
                      canceled_by_user_id:
                        type: integer
                      canceled_by:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      cancellation_reason:
                        type: string
                      can_be_canceled:
                        type: boolean
                      can_be_deleted:
                        type: boolean
                  message:
                    type: string
                example:
                  data:
                    id: 1
                    rma_number: RMA-0001
                    status: canceled
                    canceled_at: '2026-06-29T14:32:00.000000Z'
                    canceled_by_user_id: 7
                    canceled_by:
                      id: 7
                      name: Jane Operator
                    cancellation_reason: Customer decided to keep the item
                    can_be_canceled: false
                    can_be_deleted: true
                  message: RMA canceled successfully.
        '422':
          description: Unprocessable Content
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      cancellation_reason:
                        type: array
                        items:
                          type: string
                example:
                  message: The cancellation reason must not be greater than 500 characters.
                  errors:
                    cancellation_reason:
                    - The cancellation reason must not be greater than 500 characters.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: returns:write
      operationId: post-api-rmas-rma-cancel
  /api/rmas/{rma}/close:
    post:
      tags:
      - Returns & RMAs
      summary: Close RMA
      description: 'Close an approved or received RMA.


        :::info[Required scope: `returns:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Status transition: approved/in_transit/received → closed


        **Requires permission:** `returns.update`'
      requestBody:
        content: {}
      parameters:
      - name: rma
        in: path
        schema:
          type: integer
        required: true
        description: RMA ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      rma_number:
                        type: string
                      status:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 1
                    rma_number: RMA-0001
                    status: closed
                  message: RMA closed successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: returns:write
      operationId: post-api-rmas-rma-close
  /api/rmas/{rma}/reopen:
    post:
      tags:
      - Returns & RMAs
      summary: Reopen RMA
      description: 'Reopen a closed RMA.


        :::info[Required scope: `returns:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Status transition: closed → approved


        **Requires permission:** `returns.update`'
      requestBody:
        content: {}
      parameters:
      - name: rma
        in: path
        schema:
          type: integer
        required: true
        description: RMA ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      rma_number:
                        type: string
                      status:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 1
                    rma_number: RMA-0001
                    status: approved
                  message: RMA reopened successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: returns:write
      operationId: post-api-rmas-rma-reopen
  /api/rmas/{rma}/uncancel:
    post:
      tags:
      - Returns & RMAs
      summary: Uncancel RMA
      description: 'Restore a canceled RMA back to draft status.


        :::info[Required scope: `returns:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Status transition: canceled → draft


        **Requires permission:** `returns.cancel`'
      requestBody:
        content: {}
      parameters:
      - name: rma
        in: path
        schema:
          type: integer
        required: true
        description: RMA ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      rma_number:
                        type: string
                      status:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 1
                    rma_number: RMA-0001
                    status: draft
                  message: RMA restored successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: returns:write
      operationId: post-api-rmas-rma-uncancel
  /api/rmas/{rma}/revert-to-draft:
    post:
      tags:
      - Returns & RMAs
      summary: Revert to Draft
      description: 'Revert an approved RMA back to draft status. Clears approved_at
        and approved_by_user_id.


        :::info[Required scope: `returns:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Status transition: approved → draft


        **Requires permission:** `returns.update`'
      requestBody:
        content: {}
      parameters:
      - name: rma
        in: path
        schema:
          type: integer
        required: true
        description: RMA ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      rma_number:
                        type: string
                      status:
                        type: string
                      approved_at:
                        type: string
                        nullable: true
                      approved_by_user_id:
                        type: string
                        nullable: true
                      approved_by:
                        type: string
                        nullable: true
                  message:
                    type: string
                example:
                  data:
                    id: 1
                    rma_number: RMA-0001
                    status: draft
                    approved_at: null
                    approved_by_user_id: null
                    approved_by: null
                  message: RMA reverted to draft.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: returns:write
      operationId: post-api-rmas-rma-revert-to-draft
  /api/rmas/{rma}/ship:
    post:
      tags:
      - Returns & RMAs
      summary: Mark as Shipped
      description: 'Mark an RMA as shipped by the customer.


        :::info[Required scope: `returns:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Status transition: approved → in_transit


        **Requires permission:** `returns.update`'
      requestBody:
        content: {}
      parameters:
      - name: rma
        in: path
        schema:
          type: integer
        required: true
        description: RMA ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      rma_number:
                        type: string
                      status:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 1
                    rma_number: RMA-0001
                    status: in_transit
                  message: RMA marked as shipped.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: returns:write
      operationId: post-api-rmas-rma-ship
  /api/rmas/{rma}/shipping:
    put:
      tags:
      - Returns & RMAs
      summary: Update Shipping Details
      description: 'Update shipping details for an RMA. Automatically transitions
        status based on whether shipping info is added or removed:

        - Adding shipping info: APPROVED → IN_TRANSIT

        - Clearing all shipping info (when no receipts exist): IN_TRANSIT → APPROVED


        :::info[Required scope: `returns:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        All fields are nullable — pass null to clear a field.


        **Requires permission:** `returns.update`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                carrier:
                  type: string
                tracking_number:
                  type: string
                shipped_at:
                  type: string
                expected_at:
                  type: string
              example:
                carrier: UPS
                tracking_number: 1Z999AA10123456784
                shipped_at: '2024-01-16'
                expected_at: '2024-01-20'
      parameters:
      - name: rma
        in: path
        schema:
          type: integer
        required: true
        description: RMA ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      rma_number:
                        type: string
                      status:
                        type: string
                      carrier:
                        type: string
                      tracking_number:
                        type: string
                      shipped_at:
                        type: string
                      expected_at:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 1
                    rma_number: RMA-0001
                    status: in_transit
                    carrier: UPS
                    tracking_number: 1Z999AA10123456784
                    shipped_at: '2024-01-16'
                    expected_at: '2024-01-20'
                  message: Shipping details updated.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: returns:write
      operationId: put-api-rmas-rma-shipping
    delete:
      tags:
      - Returns & RMAs
      summary: Clear Shipping Details
      description: 'Clear all shipping information from an RMA. If no receipts exist
        and the RMA is in IN_TRANSIT, it transitions back to APPROVED.


        :::info[Required scope: `returns:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `returns.update`'
      parameters:
      - name: rma
        in: path
        schema:
          type: integer
        required: true
        description: RMA ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      rma_number:
                        type: string
                      status:
                        type: string
                      carrier:
                        type: string
                        nullable: true
                      tracking_number:
                        type: string
                        nullable: true
                      shipped_at:
                        type: string
                        nullable: true
                      expected_at:
                        type: string
                        nullable: true
                  message:
                    type: string
                example:
                  data:
                    id: 1
                    rma_number: RMA-0001
                    status: approved
                    carrier: null
                    tracking_number: null
                    shipped_at: null
                    expected_at: null
                  message: Shipping information cleared.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: returns:write
      operationId: delete-api-rmas-rma-shipping
  /api/rmas/{rma}/lines:
    post:
      tags:
      - Returns & RMAs
      summary: Add Line to RMA
      description: 'Add a new line to an existing RMA. Cannot add lines to terminal
        (closed/canceled) RMAs.


        :::info[Required scope: `returns:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Validation: Same quantity rules as creating an RMA — cannot exceed fulfilled
        minus already RMA''d.


        **Requires permission:** `returns.update`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                product_id:
                  type: integer
                expected_quantity:
                  type: integer
                sales_order_line_id:
                  type: integer
                return_reason_id:
                  type: integer
                notes:
                  type: string
              example:
                product_id: 25
                expected_quantity: 1
                sales_order_line_id: 60
                return_reason_id: 2
                notes: Additional defective unit
      parameters:
      - name: rma
        in: path
        schema:
          type: integer
        required: true
        description: RMA ID
        example: '1'
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      rma_number:
                        type: string
                      rma_lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            product_id:
                              type: integer
                            expected_quantity:
                              type: integer
                  message:
                    type: string
                example:
                  data:
                    id: 1
                    rma_number: RMA-0001
                    rma_lines:
                    - id: 1
                      product_id: 20
                      expected_quantity: 2
                    - id: 21
                      product_id: 25
                      expected_quantity: 1
                  message: RMA Line created successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: returns:write
      operationId: post-api-rmas-rma-lines
  /api/rmas/{rma}/lines/{rmaLine}:
    put:
      tags:
      - Returns & RMAs
      summary: Update RMA Line
      description: 'Update an RMA line. Cannot update lines on closed or canceled
        RMAs.


        :::info[Required scope: `returns:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        All fields are optional (sometimes rule):

        - expected_quantity: min 1, cannot exceed fulfilled minus existing RMAs (excluding
        current line)

        - return_reason_id: nullable

        - notes: nullable, max 500 chars


        **Requires permission:** `returns.update`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                expected_quantity:
                  type: integer
                return_reason_id:
                  type: integer
                notes:
                  type: string
              example:
                expected_quantity: 1
                return_reason_id: 3
                notes: Customer changed mind — only 1 unit is defective
      parameters:
      - name: rma
        in: path
        schema:
          type: integer
        required: true
        description: RMA ID
        example: '1'
      - name: rmaLine
        in: path
        schema:
          type: integer
        required: true
        description: RMA Line ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      rma_number:
                        type: string
                      rma_lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            product_id:
                              type: integer
                            expected_quantity:
                              type: integer
                            return_reason_id:
                              type: integer
                            notes:
                              type: string
                  message:
                    type: string
                example:
                  data:
                    id: 1
                    rma_number: RMA-0001
                    rma_lines:
                    - id: 1
                      product_id: 20
                      expected_quantity: 1
                      return_reason_id: 3
                      notes: Customer changed mind — only 1 unit is defective
                  message: RMA Line updated successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: returns:write
      operationId: put-api-rmas-rma-lines-rmaline
    delete:
      tags:
      - Returns & RMAs
      summary: Remove Line from RMA
      description: 'Remove a line from an RMA. Returns 422 if the RMA is in a terminal
        state or if the line doesn''t belong to the RMA.


        :::info[Required scope: `returns:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `returns.update`'
      parameters:
      - name: rma
        in: path
        schema:
          type: integer
        required: true
        description: RMA ID
        example: '1'
      - name: rmaLine
        in: path
        schema:
          type: integer
        required: true
        description: RMA Line ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      rma_number:
                        type: string
                      rma_lines:
                        type: array
                  message:
                    type: string
                example:
                  data:
                    id: 1
                    rma_number: RMA-0001
                    rma_lines: []
                  message: RMA Line deleted successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: returns:write
      operationId: delete-api-rmas-rma-lines-rmaline
  /api/rmas/{rma}/receipts:
    post:
      tags:
      - Returns & RMAs
      summary: Create Return Receipt from RMA
      description: 'Record a return receipt against an RMA (items physically received
        at the warehouse).


        :::info[Required scope: `returns:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Action values: added_to_stock, discarded, new_blemished_sku

        - For new_blemished_sku: provide blemished_configurations array with sku,
        condition, and reference fields

        - product_id: the product being received back (can differ from original if
        substituted)

        - original_product_id: the original product (if product_id differs)


        Lot / batch capture (optional per line - only meaningful for added_to_stock
        on lot-tracked products):

        - lots[]: { batch_number, manufacture_date, expiry_date, quantity, lot_notes
        }. Each lot becomes its own FIFO layer; the lot quantities must sum to the
        line quantity.

        - Batch number + expiry date are REQUIRED on each lot only when the return
        is traceable to its original sale (the RMA is linked to a sales order). For
        a blind/untraceable RMA (no sales order link), a blank batch is auto-generated
        (AUTO-...) at persistence and an undated lot is valid - the receiver is never
        forced to invent a lot id.


        **Requires permission:** `returns.receive` rma_line_id is OPTIONAL — omit
        it (supply product_id) to receive an item NOT on the RMA; it is stored and
        flagged unexpected_item=true rather than dropped.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                received_at:
                  type: string
                notes:
                  type: string
                lines:
                  type: array
                  items:
                    type: object
                    properties:
                      rma_line_id:
                        type: integer
                      quantity:
                        type: integer
                      action:
                        type: string
                      product_id:
                        type: integer
                      original_product_id:
                        type: string
                        nullable: true
                      return_reason_id:
                        type: integer
                      notes:
                        type: string
                      blemished_configurations:
                        type: string
                        nullable: true
                      lots:
                        type: array
                        items:
                          type: object
                          properties:
                            batch_number:
                              type: string
                            manufacture_date:
                              type: string
                            expiry_date:
                              type: string
                            quantity:
                              type: integer
                            lot_notes:
                              type: string
                      unexpected_item:
                        type: boolean
              example:
                received_at: '2024-01-21'
                notes: Received in good condition
                lines:
                - rma_line_id: 1
                  quantity: 5
                  action: added_to_stock
                  product_id: 20
                  original_product_id: null
                  return_reason_id: 1
                  notes: Units tested and in working order
                  blemished_configurations: null
                  lots:
                  - batch_number: LOT-2026-A
                    manufacture_date: '2026-01-01'
                    expiry_date: '2030-01-31'
                    quantity: 5
                    lot_notes: Original shipped lot
                  unexpected_item: false
                - rma_line_id: null
                  product_id: 44
                  quantity: 1
                  action: added_to_stock
                  unexpected_item: true
                  notes: Customer returned a different item than declared
      parameters:
      - name: rma
        in: path
        schema:
          type: integer
        required: true
        description: RMA ID
        example: '1'
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      rma_id:
                        type: integer
                      rma:
                        type: object
                        properties:
                          id:
                            type: integer
                          rma_number:
                            type: string
                          status:
                            type: string
                      warehouse_id:
                        type: integer
                      warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      received_at:
                        type: string
                      received_by_user_id:
                        type: integer
                      received_by:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      notes:
                        type: string
                      return_receipt_lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            product_id:
                              type: integer
                            product:
                              type: object
                              properties:
                                id:
                                  type: integer
                                sku:
                                  type: string
                                name:
                                  type: string
                            quantity:
                              type: integer
                            action:
                              type: string
                      created_at:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 5
                    rma_id: 1
                    rma:
                      id: 1
                      rma_number: RMA-0001
                      status: received
                    warehouse_id: 2
                    warehouse:
                      id: 2
                      name: Main Warehouse
                    received_at: '2024-01-21T00:00:00.000000Z'
                    received_by_user_id: 1
                    received_by:
                      id: 1
                      name: Admin User
                    notes: Received in good condition
                    return_receipt_lines:
                    - id: 8
                      product_id: 20
                      product:
                        id: 20
                        sku: WIDGET-A
                        name: Widget A
                      quantity: 2
                      action: return_to_stock
                    created_at: '2024-01-21T09:00:00.000000Z'
                  message: Return Receipt created successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: returns:write
      operationId: post-api-rmas-rma-receipts
  /api/rmas/bulk/approve:
    post:
      tags:
      - Returns & RMAs
      summary: Bulk Approve RMAs
      description: 'Bulk approve multiple RMAs. Returns success and failed counts.


        :::info[Required scope: `returns:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Use apply_to_all=true with filters to operate on all matching RMAs.


        **Requires permission:** `returns.approve`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
                apply_to_all:
                  type: boolean
                filters:
                  type: object
                  properties: {}
              example:
                ids:
                - 1
                - 2
                - 3
                apply_to_all: false
                filters: {}
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      success:
                        type: array
                        items:
                          type: integer
                      failed:
                        type: object
                        properties: {}
                  message:
                    type: string
                example:
                  data:
                    success:
                    - 1
                    - 2
                    - 3
                    failed: {}
                  message: 3 RMA(s) approved successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: returns:write
      operationId: post-api-rmas-bulk-approve
  /api/rmas/bulk/cancel:
    post:
      tags:
      - Returns & RMAs
      summary: Bulk Cancel RMAs
      description: 'Bulk cancel multiple RMAs.


        :::info[Required scope: `returns:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `returns.cancel`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
                apply_to_all:
                  type: boolean
                filters:
                  type: object
                  properties: {}
              example:
                ids:
                - 4
                - 5
                apply_to_all: false
                filters: {}
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      success:
                        type: array
                        items:
                          type: integer
                      failed:
                        type: object
                        properties: {}
                  message:
                    type: string
                example:
                  data:
                    success:
                    - 4
                    - 5
                    failed: {}
                  message: 2 RMA(s) canceled successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: returns:write
      operationId: post-api-rmas-bulk-cancel
  /api/rmas/bulk/close:
    post:
      tags:
      - Returns & RMAs
      summary: Bulk Close RMAs
      description: 'Bulk close multiple RMAs.


        :::info[Required scope: `returns:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `returns.update`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
                apply_to_all:
                  type: boolean
                filters:
                  type: object
                  properties: {}
              example:
                ids:
                - 6
                - 7
                apply_to_all: false
                filters: {}
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      success:
                        type: array
                        items:
                          type: integer
                      failed:
                        type: object
                        properties: {}
                  message:
                    type: string
                example:
                  data:
                    success:
                    - 6
                    - 7
                    failed: {}
                  message: 2 RMA(s) closed successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: returns:write
      operationId: post-api-rmas-bulk-close
  /api/rmas/bulk/delete:
    post:
      tags:
      - Returns & RMAs
      summary: Bulk Delete RMAs
      description: 'Bulk delete multiple RMAs.


        :::info[Required scope: `returns:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `returns.delete`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
                apply_to_all:
                  type: boolean
                filters:
                  type: object
                  properties: {}
              example:
                ids:
                - 8
                - 9
                apply_to_all: false
                filters: {}
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      success:
                        type: array
                        items:
                          type: integer
                      failed:
                        type: object
                        properties: {}
                  message:
                    type: string
                example:
                  data:
                    success:
                    - 8
                    - 9
                    failed: {}
                  message: 2 RMA(s) deleted successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: returns:write
      operationId: post-api-rmas-bulk-delete
  /api/rmas/bulk/revert-to-draft:
    post:
      tags:
      - Returns & RMAs
      summary: Bulk Revert RMAs to Draft
      description: 'Bulk revert approved RMAs back to draft status.


        :::info[Required scope: `returns:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `returns.update`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
                apply_to_all:
                  type: boolean
                filters:
                  type: object
                  properties: {}
              example:
                ids:
                - 10
                - 11
                apply_to_all: false
                filters: {}
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      success:
                        type: array
                        items:
                          type: integer
                      failed:
                        type: object
                        properties: {}
                  message:
                    type: string
                example:
                  data:
                    success:
                    - 10
                    - 11
                    failed: {}
                  message: 2 RMA(s) reverted to draft successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: returns:write
      operationId: post-api-rmas-bulk-revert-to-draft
  /api/rmas/bulk/generate-from-orders:
    post:
      tags:
      - Returns & RMAs
      summary: Bulk Generate RMAs from Orders
      description: 'Dispatch a tracked background job that creates one RMA per selected
        (or all-matching) sales order, from each order''s fulfilled, not-already-RMA''d
        lines. Returns a tracked_job_log_id immediately; progress shows via the tracked
        job log endpoints.


        :::info[Required scope: `returns:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Fields:

        - sales_order_ids (required without apply_to_all): explicit list of sales
        order IDs

        - apply_to_all (optional bool): when true, resolve target orders from the
        sales-orders list filters instead of an explicit list

        - filters (optional): the sales-orders list filters to resolve when apply_to_all
        is true

        - warehouse_id (optional): default warehouse for generated RMAs; per order,
        the order''s fulfillment warehouse is preferred when resolvable

        - status (optional): draft | approved (default draft) — when approved, each
        generated RMA is approved

        - rma_date (optional date): date for the generated RMAs

        - skip_existing_open (optional bool, default true): skip orders that already
        have a non-terminal (open) RMA


        Per-order outcomes (created / skipped / failed) and the created RMA list are
        stored on the tracked job log for the details dialog. The completion watcher
        matches the job name "Generate RMAs from Orders".'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                sales_order_ids:
                  type: array
                  items:
                    type: integer
                apply_to_all:
                  type: boolean
                filters:
                  type: object
                  properties: {}
                warehouse_id:
                  type: integer
                status:
                  type: string
                rma_date:
                  type: string
                skip_existing_open:
                  type: boolean
              example:
                sales_order_ids:
                - 42
                - 43
                - 44
                apply_to_all: false
                filters: {}
                warehouse_id: 1
                status: draft
                rma_date: '2026-06-09'
                skip_existing_open: true
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 1234
                  message: Generating RMAs from orders — track progress in the job
                    tray.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      sales_order_ids:
                        type: array
                        items:
                          type: string
                example:
                  message: Select at least one sales order, or apply to all matching
                    orders.
                  errors:
                    sales_order_ids:
                    - Select at least one sales order, or apply to all matching orders.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: returns:write
      operationId: post-api-rmas-bulk-generate-from-orders
  /api/rmas/{rma}/activity-log:
    get:
      tags:
      - Returns & RMAs
      summary: Get RMA Activity Log
      description: 'Get the activity log for an RMA — every recorded change on the
        RMA itself, its lines, and its return receipts, newest first.


        :::info[Required scope: `returns:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Each entry includes the event, the record type it applies to (`Rma`, `RmaLine`,
        or `ReturnReceipt`), the changed attributes with old values, and the acting
        user (`causer_name` is null for system-generated changes).


        Standard paginated response. Requires the `returns:read` token scope.'
      parameters:
      - name: rma
        in: path
        schema:
          type: integer
        required: true
        description: RMA ID
        example: '512'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        description:
                          type: string
                        event:
                          type: string
                        subject_type:
                          type: string
                        subject_id:
                          type: integer
                        properties:
                          type: object
                          properties:
                            attributes:
                              type: object
                              properties:
                                status:
                                  type: string
                            old:
                              type: object
                              properties:
                                status:
                                  type: string
                            source:
                              type: string
                        causer_name:
                          type: string
                        created_at:
                          type: string
                  current_page:
                    type: integer
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                  next_page_url:
                    type: string
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 48213
                    description: updated
                    event: updated
                    subject_type: Rma
                    subject_id: 512
                    properties:
                      attributes:
                        status: approved
                      old:
                        status: draft
                      source: manual
                    causer_name: Jane Smith
                    created_at: '2026-07-01T14:22:05.000000Z'
                  - id: 48120
                    description: created
                    event: created
                    subject_type: ReturnReceipt
                    subject_id: 88
                    properties:
                      attributes:
                        warehouse_id: 3
                    causer_name: Jane Smith
                    created_at: '2026-07-01T13:10:41.000000Z'
                  current_page: 1
                  first_page_url: https://acme.sku.io/api/rmas/512/activity-log?page=1
                  from: 1
                  last_page: 3
                  last_page_url: https://acme.sku.io/api/rmas/512/activity-log?page=3
                  links: []
                  next_page_url: https://acme.sku.io/api/rmas/512/activity-log?page=2
                  path: https://acme.sku.io/api/rmas/512/activity-log
                  per_page: 15
                  prev_page_url: null
                  to: 15
                  total: 34
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: returns:read
      operationId: get-api-rmas-rma-activity-log
  /api/rmas/{rma}/inventory-movements:
    get:
      tags:
      - Returns & RMAs
      summary: List RMA Inventory Movements
      description: 'List the inventory movements created by an RMA''s return receipts
        — the stock re-entering inventory as returned units are received.


        :::info[Required scope: `returns:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Each movement carries the product, warehouse, quantity, and unit cost. When
        the movement is tied to a cost layer, `unit_cost` comes from that layer and
        `unit_cost_provisional` is false; movements not yet tied to a layer use the
        product''s current unit cost with `unit_cost_provisional: true`.


        Standard paginated response (default 15 per page, sorted by movement date
        descending). Requires the `returns:read` token scope.'
      parameters:
      - name: rma
        in: path
        schema:
          type: integer
        required: true
        description: RMA ID
        example: '512'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        type:
                          type: string
                        inventory_status:
                          type: string
                        quantity:
                          type: integer
                        reference:
                          type: string
                        link_type:
                          type: string
                        link_id:
                          type: integer
                        parent_link_id:
                          type: integer
                        detail_link_id:
                          type: string
                          nullable: true
                        product_id:
                          type: integer
                        product_sku:
                          type: string
                        product_name:
                          type: string
                        warehouse_id:
                          type: integer
                        warehouse_name:
                          type: string
                        unit_cost:
                          type: number
                        unit_cost_provisional:
                          type: boolean
                        layer:
                          type: object
                          properties:
                            name:
                              type: string
                            fifo_layer_id:
                              type: integer
                        inventory_movement_date:
                          type: string
                        created_at:
                          type: string
                  current_page:
                    type: integer
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 77120
                    type: return
                    inventory_status: active
                    quantity: 2
                    reference: 'RMA-00042: Receipt 88'
                    link_type: App\Models\ReturnReceiptLine
                    link_id: 1440
                    parent_link_id: 88
                    detail_link_id: null
                    product_id: 341
                    product_sku: WIDGET-BLK
                    product_name: Widget - Black
                    warehouse_id: 3
                    warehouse_name: Main Warehouse
                    unit_cost: 12.5
                    unit_cost_provisional: false
                    layer:
                      name: fifo
                      fifo_layer_id: 9021
                    inventory_movement_date: '2026-06-28T16:40:12.000000Z'
                    created_at: '2026-06-28T16:40:12.000000Z'
                  current_page: 1
                  first_page_url: https://acme.sku.io/api/rmas/512/inventory-movements?page=1
                  from: 1
                  last_page: 1
                  last_page_url: https://acme.sku.io/api/rmas/512/inventory-movements?page=1
                  links: []
                  next_page_url: null
                  path: https://acme.sku.io/api/rmas/512/inventory-movements
                  per_page: 15
                  prev_page_url: null
                  to: 1
                  total: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: returns:read
      operationId: get-api-rmas-rma-inventory-movements
  /api/rmas/{rma}/fifo-layers:
    get:
      tags:
      - Returns & RMAs
      summary: List RMA FIFO Layers
      description: 'List the inventory cost layers created by receiving this RMA''s
        returned stock. Each layer records the received quantity, its unit cost, remaining
        availability, and lot details (batch number, expiry) when the product is lot-tracked.


        :::info[Required scope: `returns:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        `origin` identifies the return receipt line the layer came from; `available_quantity`
        is `original_quantity - fulfilled_quantity`; `days_to_expiry` is a signed
        day count (negative when expired, null when no expiry).


        Standard paginated response, sorted newest first. Requires the `returns:read`
        token scope.'
      parameters:
      - name: rma
        in: path
        schema:
          type: integer
        required: true
        description: RMA ID
        example: '512'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        product_id:
                          type: integer
                        fifo_layer_date:
                          type: string
                        sku:
                          type: string
                        product_name:
                          type: string
                        product_barcode:
                          type: string
                        stock_uom_code:
                          type: string
                        batch_number:
                          type: string
                          nullable: true
                        manufacture_date:
                          type: string
                          nullable: true
                        expiry_date:
                          type: string
                          nullable: true
                        days_to_expiry:
                          type: string
                          nullable: true
                        lot_notes:
                          type: string
                          nullable: true
                        original_quantity:
                          type: integer
                        fulfilled_quantity:
                          type: integer
                        avg_cost:
                          type: string
                        total_cost:
                          type: string
                        cost_breakdown:
                          type: string
                          nullable: true
                        origin:
                          type: object
                          properties:
                            link_type:
                              type: string
                            link_id:
                              type: integer
                            name:
                              type: string
                            parent_link_id:
                              type: integer
                            detail_link_id:
                              type: string
                              nullable: true
                            reference:
                              type: string
                            parent_reference:
                              type: string
                        warehouse:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        is_fba:
                          type: boolean
                        condition:
                          type: string
                        integration_unique_id:
                          type: string
                          nullable: true
                        allocated_quantity:
                          type: integer
                        available_quantity:
                          type: integer
                        archived_at:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 9021
                    product_id: 341
                    fifo_layer_date: '2026-06-28T16:40:12.000000Z'
                    sku: WIDGET-BLK
                    product_name: Widget - Black
                    product_barcode: 0812345678901
                    stock_uom_code: EA
                    batch_number: null
                    manufacture_date: null
                    expiry_date: null
                    days_to_expiry: null
                    lot_notes: null
                    original_quantity: 2
                    fulfilled_quantity: 0
                    avg_cost: '12.5000'
                    total_cost: '25.0000'
                    cost_breakdown: null
                    origin:
                      link_type: App\Models\ReturnReceiptLine
                      link_id: 1440
                      name: return_receipt
                      parent_link_id: 88
                      detail_link_id: null
                      reference: 'RMA-00042: Receipt 88'
                      parent_reference: 'RMA-00042: Receipt 88'
                    warehouse:
                      id: 3
                      name: Main Warehouse
                    is_fba: false
                    condition: sellable
                    integration_unique_id: null
                    allocated_quantity: 0
                    available_quantity: 2
                    archived_at: null
                    created_at: '2026-06-28T16:40:12.000000Z'
                    updated_at: '2026-06-28T16:40:12.000000Z'
                  current_page: 1
                  first_page_url: https://acme.sku.io/api/rmas/512/fifo-layers?page=1
                  from: 1
                  last_page: 1
                  last_page_url: https://acme.sku.io/api/rmas/512/fifo-layers?page=1
                  links: []
                  next_page_url: null
                  path: https://acme.sku.io/api/rmas/512/fifo-layers
                  per_page: 15
                  prev_page_url: null
                  to: 1
                  total: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: returns:read
      operationId: get-api-rmas-rma-fifo-layers
  /api/return-receipts:
    get:
      tags:
      - Returns & RMAs
      summary: List Return Receipts
      description: 'List all return receipts with pagination. Supports filtering by
        RMA, warehouse, blind receipts (no RMA), and search by ID or RMA number.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        rma_id:
                          type: integer
                        rma:
                          type: object
                          properties:
                            id:
                              type: integer
                            rma_number:
                              type: string
                            status:
                              type: string
                        warehouse_id:
                          type: integer
                        warehouse:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        received_at:
                          type: string
                        received_by_user_id:
                          type: integer
                        received_by:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        notes:
                          type: string
                        return_receipt_lines:
                          type: array
                          items:
                            type: object
                            properties:
                              id:
                                type: integer
                              return_receipt_id:
                                type: integer
                              rma_line_id:
                                type: integer
                              product_id:
                                type: integer
                              product:
                                type: object
                                properties:
                                  id:
                                    type: integer
                                  sku:
                                    type: string
                                  name:
                                    type: string
                              original_product_id:
                                type: string
                                nullable: true
                              quantity:
                                type: integer
                              action:
                                type: string
                              return_reason_id:
                                type: integer
                              notes:
                                type: string
                                nullable: true
                              created_at:
                                type: string
                              updated_at:
                                type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - id: 1
                    rma_id: 5
                    rma:
                      id: 5
                      rma_number: RMA-2024-0001
                      status: received
                    warehouse_id: 1
                    warehouse:
                      id: 1
                      name: Main Warehouse
                    received_at: '2024-01-15T10:30:00.000000Z'
                    received_by_user_id: 2
                    received_by:
                      id: 2
                      name: Jane Smith
                    notes: All items received in good condition.
                    return_receipt_lines:
                    - id: 1
                      return_receipt_id: 1
                      rma_line_id: 3
                      product_id: 10
                      product:
                        id: 10
                        sku: PROD-001
                        name: Widget A
                      original_product_id: null
                      quantity: 2
                      action: return_to_stock
                      return_reason_id: 1
                      notes: null
                      created_at: '2024-01-15T10:30:00.000000Z'
                      updated_at: '2024-01-15T10:30:00.000000Z'
                    created_at: '2024-01-15T10:30:00.000000Z'
                    updated_at: '2024-01-15T10:30:00.000000Z'
                  current_page: 1
                  last_page: 3
                  per_page: 10
                  total: 25
                  from: 1
                  to: 10
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: get-api-return-receipts
    post:
      tags:
      - Returns & RMAs
      summary: Create Return Receipt
      description: "Create a new return receipt (blind or RMA-linked). Adjusts inventory\
        \ based on each line's action.\n\n:::warning[Not yet available to API tokens]\n\
        This endpoint currently requires session authentication; Personal Access Token\
        \ scope support is in progress.\n:::\n\nAuthentication: Requires Bearer token.\n\
        \nFields:\n- warehouse_id (required): Warehouse where items are being received\n\
        - rma_id (optional): Link to an RMA; omit for blind receipts\n- received_at\
        \ (optional): ISO 8601 datetime; defaults to now\n- notes (optional): General\
        \ notes for the receipt\n- return_receipt_lines (required): Array of line\
        \ items\n  - product_id (required): Product being returned\n  - original_product_id\
        \ (optional): If different from product_id (e.g., substituted product)\n \
        \ - rma_line_id (optional): Link to specific RMA line\n  - quantity (required):\
        \ Quantity received (min: 1)\n  - action (required): One of: return_to_stock,\
        \ dispose, refurbish\n  - return_reason_id (optional): ID of return reason\n\
        \  - notes (optional): Line-level notes (max 500 chars)\n\n**Requires permission:**\
        \ `returns.receive`"
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                warehouse_id:
                  type: integer
                rma_id:
                  type: integer
                received_at:
                  type: string
                notes:
                  type: string
                return_receipt_lines:
                  type: array
                  items:
                    type: object
                    properties:
                      product_id:
                        type: integer
                      original_product_id:
                        type: string
                        nullable: true
                      rma_line_id:
                        type: integer
                      quantity:
                        type: integer
                      action:
                        type: string
                      return_reason_id:
                        type: integer
                      notes:
                        type: string
              example:
                warehouse_id: 1
                rma_id: 5
                received_at: '2024-01-15T10:30:00'
                notes: All items received in good condition.
                return_receipt_lines:
                - product_id: 10
                  original_product_id: null
                  rma_line_id: 3
                  quantity: 2
                  action: return_to_stock
                  return_reason_id: 1
                  notes: Minor cosmetic damage.
      parameters: []
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      rma_id:
                        type: integer
                      rma:
                        type: object
                        properties:
                          id:
                            type: integer
                          rma_number:
                            type: string
                          status:
                            type: string
                      warehouse_id:
                        type: integer
                      warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      received_at:
                        type: string
                      received_by_user_id:
                        type: integer
                      received_by:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      notes:
                        type: string
                      return_receipt_lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            return_receipt_id:
                              type: integer
                            rma_line_id:
                              type: integer
                            product_id:
                              type: integer
                            product:
                              type: object
                              properties:
                                id:
                                  type: integer
                                sku:
                                  type: string
                                name:
                                  type: string
                            quantity:
                              type: integer
                            action:
                              type: string
                            return_reason_id:
                              type: integer
                            created_at:
                              type: string
                            updated_at:
                              type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                  message:
                    type: string
                  status:
                    type: string
                example:
                  data:
                    id: 12
                    rma_id: 5
                    rma:
                      id: 5
                      rma_number: RMA-2024-0001
                      status: received
                    warehouse_id: 1
                    warehouse:
                      id: 1
                      name: Main Warehouse
                    received_at: '2024-01-15T10:30:00.000000Z'
                    received_by_user_id: 2
                    received_by:
                      id: 2
                      name: Jane Smith
                    notes: All items received in good condition.
                    return_receipt_lines:
                    - id: 15
                      return_receipt_id: 12
                      rma_line_id: 3
                      product_id: 10
                      product:
                        id: 10
                        sku: PROD-001
                        name: Widget A
                      quantity: 2
                      action: return_to_stock
                      return_reason_id: 1
                      created_at: '2024-01-15T10:30:00.000000Z'
                      updated_at: '2024-01-15T10:30:00.000000Z'
                    created_at: '2024-01-15T10:30:00.000000Z'
                    updated_at: '2024-01-15T10:30:00.000000Z'
                  message: Return Receipt created successfully.
                  status: success
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      warehouse_id:
                        type: array
                        items:
                          type: string
                      return_receipt_lines:
                        type: array
                        items:
                          type: string
                example:
                  message: The given data was invalid.
                  errors:
                    warehouse_id:
                    - The warehouse id field is required.
                    return_receipt_lines:
                    - At least one return receipt line is required.
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: post-api-return-receipts
  /api/return-receipts/{return_receipt}:
    get:
      tags:
      - Returns & RMAs
      summary: Get Return Receipt
      description: 'Get a single return receipt with full detail, including RMA and
        sales order, warehouse, received-by user, and all receipt lines with products,
        original products, RMA lines, and return reasons.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: return_receipt
        in: path
        schema:
          type: integer
        required: true
        description: Return receipt ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      rma_id:
                        type: integer
                      rma:
                        type: object
                        properties:
                          id:
                            type: integer
                          rma_number:
                            type: string
                          status:
                            type: string
                      warehouse_id:
                        type: integer
                      warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      received_at:
                        type: string
                      received_by_user_id:
                        type: integer
                      received_by:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      notes:
                        type: string
                      return_receipt_lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            return_receipt_id:
                              type: integer
                            rma_line_id:
                              type: integer
                            rma_line:
                              type: object
                              properties:
                                id:
                                  type: integer
                                expected_quantity:
                                  type: integer
                                product_id:
                                  type: integer
                            product_id:
                              type: integer
                            product:
                              type: object
                              properties:
                                id:
                                  type: integer
                                sku:
                                  type: string
                                name:
                                  type: string
                            original_product_id:
                              type: string
                              nullable: true
                            original_product:
                              type: string
                              nullable: true
                            quantity:
                              type: integer
                            action:
                              type: string
                            return_reason_id:
                              type: integer
                            return_reason:
                              type: object
                              properties:
                                id:
                                  type: integer
                                name:
                                  type: string
                            notes:
                              type: string
                            fifo_layer_id:
                              type: integer
                            created_at:
                              type: string
                            updated_at:
                              type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                  status:
                    type: string
                example:
                  data:
                    id: 1
                    rma_id: 5
                    rma:
                      id: 5
                      rma_number: RMA-2024-0001
                      status: received
                    warehouse_id: 1
                    warehouse:
                      id: 1
                      name: Main Warehouse
                    received_at: '2024-01-15T10:30:00.000000Z'
                    received_by_user_id: 2
                    received_by:
                      id: 2
                      name: Jane Smith
                    notes: All items received in good condition.
                    return_receipt_lines:
                    - id: 1
                      return_receipt_id: 1
                      rma_line_id: 3
                      rma_line:
                        id: 3
                        expected_quantity: 2
                        product_id: 10
                      product_id: 10
                      product:
                        id: 10
                        sku: PROD-001
                        name: Widget A
                      original_product_id: null
                      original_product: null
                      quantity: 2
                      action: return_to_stock
                      return_reason_id: 1
                      return_reason:
                        id: 1
                        name: Defective
                      notes: Minor cosmetic damage.
                      fifo_layer_id: 42
                      created_at: '2024-01-15T10:30:00.000000Z'
                      updated_at: '2024-01-15T10:30:00.000000Z'
                    created_at: '2024-01-15T10:30:00.000000Z'
                    updated_at: '2024-01-15T10:30:00.000000Z'
                  status: success
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No query results for model [App\Models\ReturnReceipt] 999
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: get-api-return-receipts-return-receipt
    delete:
      tags:
      - Returns & RMAs
      summary: Delete Return Receipt
      description: 'Delete a return receipt and all its lines. Reverses inventory
        adjustments.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `returns.receive`'
      parameters:
      - name: return_receipt
        in: path
        schema:
          type: integer
        required: true
        description: Return receipt ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  status:
                    type: string
                example:
                  message: Return Receipt deleted successfully.
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-session-only: true
      operationId: delete-api-return-receipts-return-receipt
  /api/return-receipts/{returnReceipt}/lines:
    post:
      tags:
      - Returns & RMAs
      summary: Add Line to Return Receipt
      description: 'Add a new line to an existing return receipt. Creates an inventory
        movement for the specified action.


        :::info[Required scope: `returns:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Fields:

        - product_id (required): Product being returned

        - original_product_id (optional): Original product if different (e.g., substituted)

        - rma_line_id (optional): Link to specific RMA line

        - quantity (required): Quantity received (min: 1)

        - action (required): One of: return_to_stock, dispose, refurbish

        - return_reason_id (optional): ID of return reason

        - notes (optional): Notes (max 500 chars)


        **Requires permission:** `returns.receive`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                product_id:
                  type: integer
                original_product_id:
                  type: string
                  nullable: true
                rma_line_id:
                  type: integer
                quantity:
                  type: integer
                action:
                  type: string
                return_reason_id:
                  type: integer
                notes:
                  type: string
              example:
                product_id: 10
                original_product_id: null
                rma_line_id: 3
                quantity: 1
                action: dispose
                return_reason_id: 2
                notes: Item is not suitable for resale.
      parameters:
      - name: returnReceipt
        in: path
        schema:
          type: integer
        required: true
        description: Return receipt ID
        example: '1'
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      rma_id:
                        type: integer
                      warehouse_id:
                        type: integer
                      return_receipt_lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            product_id:
                              type: integer
                            quantity:
                              type: integer
                            action:
                              type: string
                      created_at:
                        type: string
                  message:
                    type: string
                  status:
                    type: string
                example:
                  data:
                    id: 1
                    rma_id: 5
                    warehouse_id: 1
                    return_receipt_lines:
                    - id: 15
                      product_id: 10
                      quantity: 2
                      action: return_to_stock
                    - id: 16
                      product_id: 10
                      quantity: 1
                      action: dispose
                    created_at: '2024-01-15T10:30:00.000000Z'
                  message: Return Receipt Line created successfully.
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: returns:write
      operationId: post-api-return-receipts-returnreceipt-lines
  /api/return-receipts/{returnReceipt}/lines/{returnReceiptLine}:
    put:
      tags:
      - Returns & RMAs
      summary: Update Return Receipt Line
      description: 'Update non-inventory-impacting fields on a return receipt line.
        Only notes and return_reason_id can be changed after creation. Fields that
        affect inventory (quantity, action, product_id) cannot be updated — delete
        and recreate the line to correct those.


        :::info[Required scope: `returns:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `returns.receive`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                return_reason_id:
                  type: integer
                notes:
                  type: string
              example:
                return_reason_id: 2
                notes: 'Updated note: item was cosmetically damaged.'
      parameters:
      - name: returnReceipt
        in: path
        schema:
          type: integer
        required: true
        description: Return receipt ID
        example: '1'
      - name: returnReceiptLine
        in: path
        schema:
          type: integer
        required: true
        description: Return receipt line ID
        example: '15'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      rma_id:
                        type: integer
                      return_receipt_lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            product_id:
                              type: integer
                            quantity:
                              type: integer
                            action:
                              type: string
                            return_reason_id:
                              type: integer
                            notes:
                              type: string
                  message:
                    type: string
                  status:
                    type: string
                example:
                  data:
                    id: 1
                    rma_id: 5
                    return_receipt_lines:
                    - id: 15
                      product_id: 10
                      quantity: 2
                      action: return_to_stock
                      return_reason_id: 2
                      notes: 'Updated note: item was cosmetically damaged.'
                  message: Return Receipt Line updated successfully.
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: returns:write
      operationId: put-api-return-receipts-returnreceipt-lines-returnreceiptline
    delete:
      tags:
      - Returns & RMAs
      summary: Remove Line from Return Receipt
      description: 'Remove a specific line from a return receipt. Reverses the inventory
        adjustment for that line. The line must belong to the specified return receipt.


        :::info[Required scope: `returns:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `returns.receive`'
      parameters:
      - name: returnReceipt
        in: path
        schema:
          type: integer
        required: true
        description: Return receipt ID
        example: '1'
      - name: returnReceiptLine
        in: path
        schema:
          type: integer
        required: true
        description: Return receipt line ID
        example: '15'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      return_receipt_lines:
                        type: array
                  message:
                    type: string
                  status:
                    type: string
                example:
                  data:
                    id: 1
                    return_receipt_lines: []
                  message: Return Receipt Line deleted successfully.
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: returns:write
      operationId: delete-api-return-receipts-returnreceipt-lines-returnreceiptline
  /api/return-receipts/lines/{returnReceiptLine}:
    delete:
      tags:
      - Returns & RMAs
      summary: Delete Return Receipt Line (standalone)
      description: 'Delete a return receipt line directly by its ID (without specifying
        the parent receipt). If this is the last line on the return receipt, the entire
        return receipt is deleted automatically.


        :::info[Required scope: `returns:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `returns.receive`'
      parameters:
      - name: returnReceiptLine
        in: path
        schema:
          type: integer
        required: true
        description: Return receipt line ID
        example: '15'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  status:
                    type: string
                example:
                  message: return receipt line deleted successfully.
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: returns:write
      operationId: delete-api-return-receipts-lines-returnreceiptline
  /api/return-receipts/{returnReceipt}/lines/bulk-disposition:
    post:
      tags:
      - Returns & RMAs
      summary: Bulk Set Disposition on Lines
      description: 'Set the disposition (action + optional condition grade) on multiple
        lines of a return receipt at once. When a line''s action changes, its prior
        inventory effect is reversed and the new action is re-applied so inventory
        stays consistent.


        Authentication: Requires Bearer token.


        Fields:

        - line_ids (array of integers, required, min 1) — return receipt line IDs
        to update; each must exist

        - action (string, required) — disposition to apply. Bulk disposition only
        supports: added_to_stock, discarded. (Use the per-line blemished SKU flow
        for new_blemished_sku.)

        - condition_grade (string, optional, nullable) — condition grade to set on
        the lines. One of: A, B, C, unsellable


        :::info[Required scope: `returns:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        **Requires permission:** `returns.receive`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                line_ids:
                  type: array
                  items:
                    type: integer
                action:
                  type: string
                condition_grade:
                  type: string
              example:
                line_ids:
                - 8
                - 9
                action: added_to_stock
                condition_grade: A
      parameters:
      - name: returnReceipt
        in: path
        schema:
          type: integer
        required: true
        description: Return Receipt ID
        example: '5'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      rma_id:
                        type: integer
                      rma:
                        type: object
                        properties:
                          id:
                            type: integer
                          rma_number:
                            type: string
                          status:
                            type: string
                      warehouse_id:
                        type: integer
                      warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      received_at:
                        type: string
                      received_by_user_id:
                        type: integer
                      received_by:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      notes:
                        type: string
                        nullable: true
                      return_receipt_lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            product_id:
                              type: integer
                            product:
                              type: object
                              properties:
                                id:
                                  type: integer
                                sku:
                                  type: string
                                name:
                                  type: string
                            quantity:
                              type: integer
                            action:
                              type: string
                            condition_grade:
                              type: string
                            condition_grade_label:
                              type: string
                            disposition_policy_id:
                              type: string
                              nullable: true
                            return_reason_id:
                              type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 5
                    rma_id: 1
                    rma:
                      id: 1
                      rma_number: RMA-0001
                      status: received
                    warehouse_id: 2
                    warehouse:
                      id: 2
                      name: Main Warehouse
                    received_at: '2026-06-09T00:00:00.000000Z'
                    received_by_user_id: 1
                    received_by:
                      id: 1
                      name: Dev User
                    notes: null
                    return_receipt_lines:
                    - id: 8
                      product_id: 20
                      product:
                        id: 20
                        sku: WIDGET-A
                        name: Widget A
                      quantity: 2
                      action: added_to_stock
                      condition_grade: A
                      condition_grade_label: Grade A — Like New
                      disposition_policy_id: null
                      return_reason_id: 1
                    - id: 9
                      product_id: 21
                      product:
                        id: 21
                        sku: WIDGET-B
                        name: Widget B
                      quantity: 1
                      action: added_to_stock
                      condition_grade: A
                      condition_grade_label: Grade A — Like New
                      disposition_policy_id: null
                      return_reason_id: 1
                    created_at: '2026-06-09T09:00:00.000000Z'
                    updated_at: '2026-06-09T09:30:00.000000Z'
                  message: Disposition applied to 2 line(s).
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      action:
                        type: array
                        items:
                          type: string
                example:
                  message: Bulk disposition only supports adding to stock or discarding.
                    Use the blemished SKU flow for individual lines.
                  errors:
                    action:
                    - Bulk disposition only supports adding to stock or discarding.
                      Use the blemished SKU flow for individual lines.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: returns:write
      operationId: post-api-return-receipts-returnreceipt-lines-bulk-disposition
  /api/return-receipts/scan-resolve:
    post:
      tags:
      - Returns & RMAs
      summary: Resolve Scan
      description: 'Resolve a scanned token for the Receive Returns Station. Resolution
        order: open RMA by number → open RMA by tracking number → sales order by number
        → product by SKU/barcode. Returns the match type plus staged lines whose dispositions
        are defaulted by the active return disposition policies (the matching policy
        id is included so the UI can show a ''policy applied'' badge). Closed/canceled
        RMAs are excluded and fall through to ''none''.


        :::info[Required scope: `returns:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Fields:

        - token (required): The raw scanned value (RMA #, tracking #, order #, SKU,
        or barcode)

        - warehouse_id (required): Warehouse the operator is receiving into (used
        for warehouse-scoped policy matching)


        When the token matches an RMA or a sales order, the response includes `sales_order_notes`
        — the notes on the sales order being returned (pinned notes first, then newest
        first), each with `id`, `note`, `user_name`, `created_at`, and `is_pinned`.
        An RMA match also includes the linked `sales_order_id`, `sales_order_number`,
        and the RMA''s own free-text `notes`.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                token:
                  type: string
                warehouse_id:
                  type: integer
              example:
                token: RMA-2026-00012
                warehouse_id: 1
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 OK (product match)
                  value:
                    data:
                      match_type: product
                      rma: null
                      order: null
                      staged_lines:
                      - product_id: 10
                        sku: WIDGET-BLK
                        name: Widget - Black
                        rma_line_id: null
                        suggested_quantity: 1
                        suggested_action: added_to_stock
                        policy_id: 4
                        policy_name: Main Warehouse Grade A → Restock
                        return_reason_id: null
                      sales_order_notes: []
                example-1:
                  summary: 200 OK (rma match)
                  value:
                    data:
                      match_type: rma
                      rma:
                        id: 5
                        rma_number: RMA-2026-00012
                        status: approved
                        customer_name: Acme Co
                        remaining_quantity: 3
                        sales_order_id: 10
                        sales_order_number: SO-0010
                        notes: Inspect on arrival
                      order: null
                      staged_lines:
                      - product_id: 10
                        sku: WIDGET-BLK
                        name: Widget - Black
                        rma_line_id: 3
                        suggested_quantity: 2
                        suggested_action: added_to_stock
                        policy_id: null
                        policy_name: null
                        return_reason_id: 1
                      sales_order_notes:
                      - id: 44
                        note: Fragile item — handle with care
                        user_name: Admin User
                        created_at: '2026-01-10T14:03:00.000000Z'
                        is_pinned: true
                      - id: 41
                        note: Customer reports the box arrived damaged
                        user_name: Admin User
                        created_at: '2026-01-09T09:21:00.000000Z'
                        is_pinned: false
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      token:
                        type: array
                        items:
                          type: string
                example:
                  message: A scanned value is required.
                  errors:
                    token:
                    - A scanned value is required.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: returns:write
      operationId: post-api-return-receipts-scan-resolve
  /api/return-receipts/resolve-line-disposition:
    post:
      tags:
      - Returns & RMAs
      summary: Resolve Line Disposition
      description: 'Re-resolve the policy-defaulted disposition for a single staged
        line once more criteria are known (e.g. after the operator selects a condition
        grade), so grade-specific disposition policies apply at the Receive Station.


        :::info[Required scope: `returns:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Fields:

        - product_id (required)

        - warehouse_id (required)

        - return_reason_id (optional)

        - condition_grade (optional): A|B|C|unsellable'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                product_id:
                  type: integer
                warehouse_id:
                  type: integer
                return_reason_id:
                  type: string
                  nullable: true
                condition_grade:
                  type: string
              example:
                product_id: 10
                warehouse_id: 1
                return_reason_id: null
                condition_grade: C
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      action:
                        type: string
                      policy_id:
                        type: integer
                      policy_name:
                        type: string
                example:
                  data:
                    action: new_blemished_sku
                    policy_id: 2
                    policy_name: Grade C electronics → Open Box SKU
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: returns:write
      operationId: post-api-return-receipts-resolve-line-disposition
  /api/return-receipts/session-summary:
    get:
      tags:
      - Returns & RMAs
      summary: Get Session Summary
      description: 'Aggregate the return receipts the current authenticated user has
        committed since a timestamp, powering the station''s running ''this session''
        totals (receipts, units, and units by disposition).


        :::info[Required scope: `returns:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Query parameters:

        - since (optional): ISO 8601 datetime; defaults to the start of today'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      receipt_count:
                        type: integer
                      unit_count:
                        type: integer
                      restocked_units:
                        type: integer
                      discarded_units:
                        type: integer
                      blemished_units:
                        type: integer
                example:
                  data:
                    receipt_count: 7
                    unit_count: 23
                    restocked_units: 18
                    discarded_units: 3
                    blemished_units: 2
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: returns:read
      operationId: get-api-return-receipts-session-summary
  /api/return-receipts/{returnReceipt}/delete-impact:
    get:
      tags:
      - Returns & RMAs
      summary: Preview Return Receipt Delete Impact
      description: 'Read-only preview of the allocation-demotion impact of deleting
        this return receipt. Because deleting it removes the stock it added, this
        behaves like a manual negative adjustment and returns one row per affected
        product: how much of the removed quantity is unallocated vs soft-allocated
        vs hard-allocated, plus every sales-order allocation and fulfillment (printed
        shipping label) the removal would disturb. Use it to decide which fulfillments
        to authorize voiding via `void_confirmations` on the deleting call. Nothing
        is mutated. A removal that only re-adds stock returns an empty `data` array.


        Authentication: Requires Bearer token.'
      parameters:
      - name: returnReceipt
        in: path
        schema:
          type: integer
        required: true
        description: Return receipt ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        product_id:
                          type: integer
                        product_sku:
                          type: string
                        product_name:
                          type: string
                        shortfall_quantity:
                          type: integer
                        unallocated_quantity:
                          type: integer
                        soft_allocated_quantity:
                          type: integer
                        hard_allocated_quantity:
                          type: integer
                        affected_allocations:
                          type: array
                          items:
                            type: object
                            properties:
                              allocation_id:
                                type: integer
                              allocation_type:
                                type: string
                              sales_order_id:
                                type: integer
                              order_number:
                                type: string
                              customer_name:
                                type: string
                              fulfillment_id:
                                type: string
                                nullable: true
                              carrier:
                                type: string
                                nullable: true
                              carrier_void_supported:
                                type: string
                                nullable: true
                              voidable_status:
                                type: string
                                nullable: true
                              voidable_detail:
                                type: string
                                nullable: true
                              quantity:
                                type: integer
                example:
                  data:
                  - product_id: 5567
                    product_sku: WIDGET-BLUE
                    product_name: Blue Widget
                    shortfall_quantity: 0
                    unallocated_quantity: 10
                    soft_allocated_quantity: 6
                    hard_allocated_quantity: 4
                    affected_allocations:
                    - allocation_id: 88201
                      allocation_type: soft
                      sales_order_id: 3120
                      order_number: SO-3120
                      customer_name: Acme Co.
                      fulfillment_id: null
                      carrier: null
                      carrier_void_supported: null
                      voidable_status: null
                      voidable_detail: null
                      quantity: 6
                    - allocation_id: 88205
                      allocation_type: hard
                      sales_order_id: 3125
                      order_number: SO-3125
                      customer_name: Beta LLC
                      fulfillment_id: 90142
                      carrier: ups
                      carrier_void_supported: true
                      voidable_status: voidable
                      voidable_detail: null
                      quantity: 4
                      allocation_ids:
                      - 88205
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-return-receipts-returnreceipt-delete-impact
  /api/return-receipts/preview-release-impact:
    post:
      tags:
      - Returns & RMAs
      summary: Preview Return Receipt Release Impact
      description: 'Read-only preview of which back-ordered sales orders this return
        receipt would release, per restock-to-sellable line. Send the same payload
        you would POST to create the receipt; each line that restocks sellable stock
        is resolved to its product and the receive warehouse and evaluated against
        waiting back-ordered demand. Nothing is written.


        Each row describes one product the receive would restock. `releasable_quantity`
        is the number of incoming units that can be released to back-ordered demand;
        `orders[]` are the back-ordered sales orders that would be filled; `held_back[]`
        is demand that stays back-ordered, with `reason_kept` explaining why (e.g.
        "Insufficient supply").


        Body: the same shape as Create Return Receipt. Minimum: `warehouse_id` and
        one `return_receipt_lines` entry with `product_id`, `quantity`, and `action`.
        `release_backorders` (true/false/null) mirrors the receive call''s release
        control.


        Authentication: Requires Bearer token. Requires the returns.receive permission.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                warehouse_id:
                  type: integer
                release_backorders:
                  type: boolean
                return_receipt_lines:
                  type: array
                  items:
                    type: object
                    properties:
                      product_id:
                        type: integer
                      rma_line_id:
                        type: integer
                      quantity:
                        type: integer
                      action:
                        type: string
                      return_reason_id:
                        type: integer
              example:
                warehouse_id: 1
                release_backorders: true
                return_receipt_lines:
                - product_id: 123
                  rma_line_id: 3
                  quantity: 8
                  action: return_to_stock
                  return_reason_id: 1
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        product_id:
                          type: integer
                        product_sku:
                          type: string
                        product_name:
                          type: string
                        releasable_quantity:
                          type: integer
                        orders:
                          type: array
                          items:
                            type: object
                            properties:
                              sales_order_id:
                                type: integer
                              order_number:
                                type: string
                              customer_name:
                                type: string
                              quantity:
                                type: integer
                        held_back:
                          type: array
                          items:
                            type: object
                            properties:
                              allocation_id:
                                type: integer
                              product_id:
                                type: integer
                              sales_order_id:
                                type: integer
                              sales_order_line_id:
                                type: integer
                              sales_order_number:
                                type: string
                              customer_name:
                                type: string
                              quantity:
                                type: integer
                              from_status:
                                type: string
                              to_status:
                                type: string
                              reason_kept:
                                type: string
                  status:
                    type: string
                example:
                  data:
                  - product_id: 123
                    product_sku: WIDGET-001
                    product_name: Blue Widget 500ml
                    releasable_quantity: 8
                    orders:
                    - sales_order_id: 4602
                      order_number: SO-10501
                      customer_name: Acme Retail
                      quantity: 5
                    - sales_order_id: 4610
                      order_number: SO-10509
                      customer_name: Gamma Foods
                      quantity: 3
                    held_back:
                    - allocation_id: 90311
                      product_id: 123
                      sales_order_id: 4620
                      sales_order_line_id: 55123
                      sales_order_number: SO-10518
                      customer_name: Delta Mart
                      quantity: 4
                      from_status: planned
                      to_status: allocated
                      reason_kept: Insufficient supply
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-return-receipts-preview-release-impact
  /api/return-reasons:
    get:
      tags:
      - Returns & RMAs
      summary: List Return Reasons
      description: 'List all return reasons with standard list query parameters. Supports
        filtering, sorting, search and pagination.


        Authentication: Requires Bearer token.


        Sort fields: id, name, created_at, updated_at.'
      parameters:
      - name: archived
        in: query
        schema:
          type: integer
        description: 'Filter by archived status: 0 (active) or 1 (archived). Default:
          0'
        example: '0'
      - name: search
        in: query
        schema:
          type: string
        description: Search return reasons by name
      - name: sort
        in: query
        schema:
          type: string
        description: 'Sort field. Prefix with - for descending. Allowed: id, name,
          created_at, updated_at'
        example: name
      - name: page
        in: query
        schema:
          type: integer
        description: Page number for pagination
        example: '1'
      - name: limit
        in: query
        schema:
          type: integer
        description: Records per page
        example: '25'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                        archived_at:
                          type: string
                          nullable: true
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 1
                    name: Defective Item
                    created_at: '2024-01-01T00:00:00Z'
                    updated_at: '2024-01-01T00:00:00Z'
                    archived_at: null
                  - id: 2
                    name: Wrong Item Shipped
                    created_at: '2024-01-01T00:00:00Z'
                    updated_at: '2024-01-01T00:00:00Z'
                    archived_at: null
                  current_page: 1
                  last_page: 1
                  per_page: 25
                  total: 2
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-return-reasons
    post:
      tags:
      - Returns & RMAs
      summary: Create Return Reason
      description: 'Create a new return reason.


        :::info[Required scope: `returns:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Fields:

        - name (required): Unique return reason name, max 255 characters


        **Requires permission:** `return_reasons.create`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
              example:
                name: Customer Changed Mind
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                example:
                  message: return reason has been successfully created
                  data:
                    id: 5
                    name: Customer Changed Mind
                    created_at: '2024-03-15T14:30:00Z'
                    updated_at: '2024-03-15T14:30:00Z'
                    archived_at: null
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      name:
                        type: array
                        items:
                          type: string
                example:
                  message: The given data was invalid.
                  errors:
                    name:
                    - The name has already been taken.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: returns:write
      operationId: post-api-return-reasons
    delete:
      tags:
      - Returns & RMAs
      summary: Bulk Delete Return Reasons
      description: 'Bulk delete multiple return reasons by ID.


        :::info[Required scope: `returns:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `return_reasons.delete`'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 2 return reasons deleted successfully
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: returns:write
      operationId: delete-api-return-reasons
  /api/return-reasons/{return_reason}:
    get:
      tags:
      - Returns & RMAs
      summary: Get Return Reason
      description: 'Retrieve a single return reason by ID.


        :::info[Required scope: `returns:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: return_reason
        in: path
        schema:
          type: integer
        required: true
        description: Return reason ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                example:
                  data:
                    id: 1
                    name: Defective Item
                    created_at: '2024-01-01T00:00:00Z'
                    updated_at: '2024-01-01T00:00:00Z'
                    archived_at: null
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No query results for model [App\Models\ReturnReason] 9999
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: returns:read
      operationId: get-api-return-reasons-return-reason
    put:
      tags:
      - Returns & RMAs
      summary: Update Return Reason
      description: 'Update an existing return reason.


        :::info[Required scope: `returns:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Fields:

        - name (required): New unique return reason name, max 255 characters


        **Requires permission:** `return_reasons.update`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
              example:
                name: Changed Mind / No Longer Needed
      parameters:
      - name: return_reason
        in: path
        schema:
          type: integer
        required: true
        description: Return reason ID
        example: '5'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                example:
                  message: return reason Changed Mind / No Longer Needed has been
                    successfully updated
                  data:
                    id: 5
                    name: Changed Mind / No Longer Needed
                    created_at: '2024-03-15T14:30:00Z'
                    updated_at: '2024-03-15T15:00:00Z'
                    archived_at: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: returns:write
      operationId: put-api-return-reasons-return-reason
    delete:
      tags:
      - Returns & RMAs
      summary: Delete Return Reason
      description: 'Delete a return reason. Will fail if reason is linked to existing
        return receipt lines.


        :::info[Required scope: `returns:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `return_reasons.delete`'
      parameters:
      - name: return_reason
        in: path
        schema:
          type: integer
        required: true
        description: Return reason ID
        example: '5'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: return reason Changed Mind / No Longer Needed has been
                    successfully deleted
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: array
                    items:
                      type: object
                      properties:
                        message:
                          type: string
                        code:
                          type: string
                        field:
                          type: string
                example:
                  message: Failed to delete return reason Defective Item
                  errors:
                  - message: This return reason is linked to existing return receipt
                      lines
                    code: ReturnReceiptLineLinked
                    field: return_receipt_lines
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: returns:write
      operationId: delete-api-return-reasons-return-reason
  /api/return-reasons/deletable:
    post:
      tags:
      - Returns & RMAs
      summary: Check Return Reasons Deletable
      description: 'Check which return reasons can be safely deleted. Returns deletability
        status per ID.


        :::info[Required scope: `returns:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Body:

        - ids (required): Array of integer return reason IDs


        **Requires permission:** `return_reasons.delete`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1
                - 2
                - 5
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        deletable:
                          type: boolean
                        reason:
                          type: string
                example:
                  data:
                  - id: 1
                    name: Defective Item
                    deletable: false
                    reason: In use by 12 return receipts
                  - id: 2
                    name: Wrong Item Shipped
                    deletable: false
                    reason: In use by 5 return receipts
                  - id: 5
                    name: Changed Mind
                    deletable: true
                    reason: null
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: returns:write
      operationId: post-api-return-reasons-deletable
  /api/return-reasons/{return_reason}/archive:
    put:
      tags:
      - Returns & RMAs
      summary: Archive Return Reason
      description: 'Archive a single return reason.


        :::info[Required scope: `returns:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `return_reasons.archive`'
      requestBody:
        content: {}
      parameters:
      - name: return_reason
        in: path
        schema:
          type: integer
        required: true
        description: Return reason ID
        example: '5'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      archived_at:
                        type: string
                example:
                  message: return reason Changed Mind has been archived
                  data:
                    id: 5
                    name: Changed Mind
                    archived_at: '2024-03-16T10:00:00Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: returns:write
      operationId: put-api-return-reasons-return-reason-archive
  /api/return-reasons/{return_reason}/unarchived:
    put:
      tags:
      - Returns & RMAs
      summary: Unarchive Return Reason
      description: 'Unarchive a single return reason.


        :::info[Required scope: `returns:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `return_reasons.archive`'
      requestBody:
        content: {}
      parameters:
      - name: return_reason
        in: path
        schema:
          type: integer
        required: true
        description: Return reason ID
        example: '5'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                example:
                  message: return reason Changed Mind has been unarchived
                  data:
                    id: 5
                    name: Changed Mind
                    archived_at: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: returns:write
      operationId: put-api-return-reasons-return-reason-unarchived
  /api/return-reasons/archive:
    put:
      tags:
      - Returns & RMAs
      summary: Bulk Archive Return Reasons
      description: 'Bulk archive multiple return reasons.


        :::info[Required scope: `returns:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `return_reasons.archive`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 5
                - 6
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 2 return reasons archived successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: returns:write
      operationId: put-api-return-reasons-archive
  /api/return-reasons/unarchive:
    put:
      tags:
      - Returns & RMAs
      summary: Bulk Unarchive Return Reasons
      description: 'Bulk unarchive multiple return reasons.


        :::info[Required scope: `returns:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `return_reasons.archive`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 5
                - 6
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 2 return reasons unarchived successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: returns:write
      operationId: put-api-return-reasons-unarchive
  /api/return-disposition-policies:
    get:
      tags:
      - Returns & RMAs
      summary: List Disposition Policies
      description: 'List all return disposition policies, ordered by precedence (priority
        ascending, then id ascending).


        Authentication: Requires Bearer token.


        Disposition policies are evaluated top-to-bottom at return-receiving time
        to auto-assign a line''s disposition (added to stock, discarded, or new blemished
        SKU). The first active policy whose match_* criteria all match wins; if none
        match, the default is added_to_stock.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        is_active:
                          type: boolean
                        priority:
                          type: integer
                        match_product_id:
                          type: string
                          nullable: true
                        match_product_category_id:
                          type: string
                          nullable: true
                        match_return_reason_id:
                          type: string
                          nullable: true
                        match_warehouse_id:
                          type: string
                          nullable: true
                        match_condition_grade:
                          type: string
                        match_condition_grade_label:
                          type: string
                        action:
                          type: string
                        action_label:
                          type: string
                        blemished_condition:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                        updated_at:
                          type: string
                example:
                  data:
                  - id: 1
                    name: Like-new returns → restock
                    is_active: true
                    priority: 0
                    match_product_id: null
                    match_product_category_id: null
                    match_return_reason_id: null
                    match_warehouse_id: null
                    match_condition_grade: A
                    match_condition_grade_label: Grade A — Like New
                    action: added_to_stock
                    action_label: Added to Stock
                    blemished_condition: null
                    created_at: '2026-06-09T09:00:00.000000Z'
                    updated_at: '2026-06-09T09:00:00.000000Z'
                  - id: 2
                    name: Grade B → blemished SKU
                    is_active: true
                    priority: 1
                    match_product_id: null
                    match_product_category_id: null
                    match_return_reason_id: null
                    match_warehouse_id: null
                    match_condition_grade: B
                    match_condition_grade_label: Grade B — Good
                    action: new_blemished_sku
                    action_label: New Blemished SKU
                    blemished_condition: Open box — good condition
                    created_at: '2026-06-09T09:00:00.000000Z'
                    updated_at: '2026-06-09T09:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: get-api-return-disposition-policies
    post:
      tags:
      - Returns & RMAs
      summary: Create Disposition Policy
      description: 'Create a new return disposition policy.


        Authentication: Requires Bearer token.


        Fields:

        - name (string, required, max 255) — human-readable policy name

        - action (string, required) — disposition to apply when this policy matches.
        One of: added_to_stock, discarded, new_blemished_sku

        - is_active (boolean, optional, default true) — only active policies are evaluated
        at resolve time

        - priority (integer, optional, min 0) — lower numbers are evaluated first;
        ties broken by id

        - match_product_id (integer, optional, nullable) — restrict to a single product

        - match_product_category_id (integer, optional, nullable) — restrict to a
        product category (matches the product''s category and any ancestor category)

        - match_return_reason_id (integer, optional, nullable) — restrict to a return
        reason

        - match_warehouse_id (integer, optional, nullable) — restrict to a warehouse

        - match_condition_grade (string, optional, nullable) — restrict to a condition
        grade. One of: A, B, C, unsellable

        - blemished_condition (string, optional, nullable, max 255) — condition note
        applied when action is new_blemished_sku


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                action:
                  type: string
                is_active:
                  type: boolean
                priority:
                  type: integer
                match_product_id:
                  type: string
                  nullable: true
                match_product_category_id:
                  type: integer
                match_return_reason_id:
                  type: integer
                match_warehouse_id:
                  type: string
                  nullable: true
                match_condition_grade:
                  type: string
                blemished_condition:
                  type: string
                  nullable: true
              example:
                name: Damaged electronics → discard
                action: discarded
                is_active: true
                priority: 0
                match_product_id: null
                match_product_category_id: 12
                match_return_reason_id: 4
                match_warehouse_id: null
                match_condition_grade: unsellable
                blemished_condition: null
      parameters: []
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      is_active:
                        type: boolean
                      priority:
                        type: integer
                      match_product_id:
                        type: string
                        nullable: true
                      match_product_category_id:
                        type: integer
                      match_product_category:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      match_return_reason_id:
                        type: integer
                      match_return_reason:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      match_warehouse_id:
                        type: string
                        nullable: true
                      match_condition_grade:
                        type: string
                      match_condition_grade_label:
                        type: string
                      action:
                        type: string
                      action_label:
                        type: string
                      blemished_condition:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 3
                    name: Damaged electronics → discard
                    is_active: true
                    priority: 0
                    match_product_id: null
                    match_product_category_id: 12
                    match_product_category:
                      id: 12
                      name: Electronics
                    match_return_reason_id: 4
                    match_return_reason:
                      id: 4
                      name: Arrived damaged
                    match_warehouse_id: null
                    match_condition_grade: unsellable
                    match_condition_grade_label: Unsellable
                    action: discarded
                    action_label: Discarded
                    blemished_condition: null
                    created_at: '2026-06-09T09:00:00.000000Z'
                    updated_at: '2026-06-09T09:00:00.000000Z'
                  message: Disposition Policy created successfully
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      action:
                        type: array
                        items:
                          type: string
                example:
                  message: The action field is required.
                  errors:
                    action:
                    - The action field is required.
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: post-api-return-disposition-policies
  /api/return-disposition-policies/{returnDispositionPolicy}:
    get:
      tags:
      - Returns & RMAs
      summary: Get Disposition Policy
      description: 'Get a single disposition policy with its matched product, category,
        return reason, and warehouse summaries.


        Authentication: Requires Bearer token.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::'
      parameters:
      - name: returnDispositionPolicy
        in: path
        schema:
          type: integer
        required: true
        description: Disposition policy ID
        example: '3'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      is_active:
                        type: boolean
                      priority:
                        type: integer
                      match_product_id:
                        type: string
                        nullable: true
                      match_product_category_id:
                        type: integer
                      match_product_category:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      match_return_reason_id:
                        type: integer
                      match_return_reason:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      match_warehouse_id:
                        type: string
                        nullable: true
                      match_condition_grade:
                        type: string
                      match_condition_grade_label:
                        type: string
                      action:
                        type: string
                      action_label:
                        type: string
                      blemished_condition:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 3
                    name: Damaged electronics → discard
                    is_active: true
                    priority: 0
                    match_product_id: null
                    match_product_category_id: 12
                    match_product_category:
                      id: 12
                      name: Electronics
                    match_return_reason_id: 4
                    match_return_reason:
                      id: 4
                      name: Arrived damaged
                    match_warehouse_id: null
                    match_condition_grade: unsellable
                    match_condition_grade_label: Unsellable
                    action: discarded
                    action_label: Discarded
                    blemished_condition: null
                    created_at: '2026-06-09T09:00:00.000000Z'
                    updated_at: '2026-06-09T09:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-session-only: true
      operationId: get-api-return-disposition-policies-returndispositionpolicy
    put:
      tags:
      - Returns & RMAs
      summary: Update Disposition Policy
      description: 'Update an existing disposition policy. Send the full set of fields
        (same shape as create).


        Authentication: Requires Bearer token.


        Fields:

        - name (string, required, max 255) — human-readable policy name

        - action (string, required) — disposition to apply when this policy matches.
        One of: added_to_stock, discarded, new_blemished_sku

        - is_active (boolean, optional, default true) — only active policies are evaluated
        at resolve time

        - priority (integer, optional, min 0) — lower numbers are evaluated first;
        ties broken by id

        - match_product_id (integer, optional, nullable) — restrict to a single product

        - match_product_category_id (integer, optional, nullable) — restrict to a
        product category (matches the product''s category and any ancestor category)

        - match_return_reason_id (integer, optional, nullable) — restrict to a return
        reason

        - match_warehouse_id (integer, optional, nullable) — restrict to a warehouse

        - match_condition_grade (string, optional, nullable) — restrict to a condition
        grade. One of: A, B, C, unsellable

        - blemished_condition (string, optional, nullable, max 255) — condition note
        applied when action is new_blemished_sku


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                action:
                  type: string
                is_active:
                  type: boolean
                priority:
                  type: integer
                match_product_id:
                  type: string
                  nullable: true
                match_product_category_id:
                  type: integer
                match_return_reason_id:
                  type: integer
                match_warehouse_id:
                  type: string
                  nullable: true
                match_condition_grade:
                  type: string
                blemished_condition:
                  type: string
                  nullable: true
              example:
                name: Damaged electronics → discard
                action: discarded
                is_active: true
                priority: 0
                match_product_id: null
                match_product_category_id: 12
                match_return_reason_id: 4
                match_warehouse_id: null
                match_condition_grade: unsellable
                blemished_condition: null
      parameters:
      - name: returnDispositionPolicy
        in: path
        schema:
          type: integer
        required: true
        description: Disposition policy ID
        example: '3'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      is_active:
                        type: boolean
                      priority:
                        type: integer
                      match_product_id:
                        type: string
                        nullable: true
                      match_product_category_id:
                        type: integer
                      match_product_category:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      match_return_reason_id:
                        type: integer
                      match_return_reason:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      match_warehouse_id:
                        type: string
                        nullable: true
                      match_condition_grade:
                        type: string
                      match_condition_grade_label:
                        type: string
                      action:
                        type: string
                      action_label:
                        type: string
                      blemished_condition:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 3
                    name: Damaged electronics → discard
                    is_active: true
                    priority: 0
                    match_product_id: null
                    match_product_category_id: 12
                    match_product_category:
                      id: 12
                      name: Electronics
                    match_return_reason_id: 4
                    match_return_reason:
                      id: 4
                      name: Arrived damaged
                    match_warehouse_id: null
                    match_condition_grade: unsellable
                    match_condition_grade_label: Unsellable
                    action: discarded
                    action_label: Discarded
                    blemished_condition: null
                    created_at: '2026-06-09T09:00:00.000000Z'
                    updated_at: '2026-06-09T09:00:00.000000Z'
                  message: Disposition Policy updated successfully
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      action:
                        type: array
                        items:
                          type: string
                example:
                  message: The action field is required.
                  errors:
                    action:
                    - The action field is required.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-session-only: true
      operationId: put-api-return-disposition-policies-returndispositionpolicy
    delete:
      tags:
      - Returns & RMAs
      summary: Delete Disposition Policy
      description: 'Delete a disposition policy. Already-received receipt lines retain
        their assigned disposition; only future return-receiving evaluation is affected.


        Authentication: Requires Bearer token.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::'
      parameters:
      - name: returnDispositionPolicy
        in: path
        schema:
          type: integer
        required: true
        description: Disposition policy ID
        example: '3'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Disposition Policy deleted successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-session-only: true
      operationId: delete-api-return-disposition-policies-returndispositionpolicy
  /api/return-disposition-policies/reorder:
    post:
      tags:
      - Returns & RMAs
      summary: Reorder Disposition Policies
      description: 'Persist a new precedence order for the disposition policies. The
        position of each id in the ordered_ids array becomes its priority (first =
        priority 0, evaluated first).


        Authentication: Requires Bearer token.


        Fields:

        - ordered_ids (array of integers, required, min 1) — policy IDs in the desired
        evaluation order. Must be distinct and each must exist.


        :::info[Required scope: `returns:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ordered_ids:
                  type: array
                  items:
                    type: integer
              example:
                ordered_ids:
                - 2
                - 1
                - 3
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        is_active:
                          type: boolean
                        priority:
                          type: integer
                        match_product_id:
                          type: string
                          nullable: true
                        match_product_category_id:
                          type: string
                          nullable: true
                        match_return_reason_id:
                          type: string
                          nullable: true
                        match_warehouse_id:
                          type: string
                          nullable: true
                        match_condition_grade:
                          type: string
                        match_condition_grade_label:
                          type: string
                        action:
                          type: string
                        action_label:
                          type: string
                        blemished_condition:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  message:
                    type: string
                example:
                  data:
                  - id: 1
                    name: Like-new returns → restock
                    is_active: true
                    priority: 0
                    match_product_id: null
                    match_product_category_id: null
                    match_return_reason_id: null
                    match_warehouse_id: null
                    match_condition_grade: A
                    match_condition_grade_label: Grade A — Like New
                    action: added_to_stock
                    action_label: Added to Stock
                    blemished_condition: null
                    created_at: '2026-06-09T09:00:00.000000Z'
                    updated_at: '2026-06-09T09:00:00.000000Z'
                  - id: 2
                    name: Grade B → blemished SKU
                    is_active: true
                    priority: 1
                    match_product_id: null
                    match_product_category_id: null
                    match_return_reason_id: null
                    match_warehouse_id: null
                    match_condition_grade: B
                    match_condition_grade_label: Grade B — Good
                    action: new_blemished_sku
                    action_label: New Blemished SKU
                    blemished_condition: Open box — good condition
                    created_at: '2026-06-09T09:00:00.000000Z'
                    updated_at: '2026-06-09T09:00:00.000000Z'
                  message: Disposition policy order updated.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      ordered_ids:
                        type: array
                        items:
                          type: string
                example:
                  message: A list of policy IDs is required to reorder.
                  errors:
                    ordered_ids:
                    - A list of policy IDs is required to reorder.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: returns:write
      operationId: post-api-return-disposition-policies-reorder
  /api/returns/analytics/summary:
    get:
      tags:
      - Returns & RMAs
      summary: Get Returns Summary KPIs
      description: 'KPI summary: return rate, returned/shipped units, RMA count, restock
        recovery rate, recovered COGS value, discard rate, and average days to disposition.


        :::info[Required scope: `returns:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token. All query params are optional; dates
        are app-timezone and converted to UTC. warehouse_ids / product_ids are comma-separated.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      return_rate:
                        type: number
                      returned_units:
                        type: integer
                      shipped_units:
                        type: integer
                      rma_count:
                        type: integer
                      restock_recovery_rate:
                        type: number
                      recovered_value:
                        type: number
                      discard_rate:
                        type: number
                      avg_days_to_disposition:
                        type: number
                example:
                  data:
                    return_rate: 0.084
                    returned_units: 412
                    shipped_units: 4904
                    rma_count: 118
                    restock_recovery_rate: 0.74
                    recovered_value: 12480.5
                    discard_rate: 0.18
                    avg_days_to_disposition: 6.2
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: returns:read
      operationId: get-api-returns-analytics-summary
  /api/returns/analytics/by-reason:
    get:
      tags:
      - Returns & RMAs
      summary: Get Returns by Reason
      description: 'Counts and units grouped by return reason, ordered by units desc.


        :::info[Required scope: `returns:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token. All query params are optional; dates
        are app-timezone and converted to UTC. warehouse_ids / product_ids are comma-separated.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        reason_id:
                          type: integer
                        reason:
                          type: string
                        line_count:
                          type: integer
                        units:
                          type: integer
                example:
                  data:
                  - reason_id: 3
                    reason: Defective
                    line_count: 48
                    units: 169
                  - reason_id: 1
                    reason: Wrong size
                    line_count: 31
                    units: 107
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: returns:read
      operationId: get-api-returns-analytics-by-reason
  /api/returns/analytics/by-disposition:
    get:
      tags:
      - Returns & RMAs
      summary: Get Returns by Disposition
      description: 'Units grouped by disposition action (added_to_stock / discarded
        / new_blemished_sku).


        :::info[Required scope: `returns:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token. All query params are optional; dates
        are app-timezone and converted to UTC. warehouse_ids / product_ids are comma-separated.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        action:
                          type: string
                        label:
                          type: string
                        line_count:
                          type: integer
                        units:
                          type: integer
                example:
                  data:
                  - action: added_to_stock
                    label: Add to Stock
                    line_count: 210
                    units: 305
                  - action: discarded
                    label: Discard
                    line_count: 60
                    units: 74
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: returns:read
      operationId: get-api-returns-analytics-by-disposition
  /api/returns/analytics/by-product:
    get:
      tags:
      - Returns & RMAs
      summary: Get Top Returned Products
      description: 'Top returned products by units (limit 20).


        :::info[Required scope: `returns:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token. All query params are optional; dates
        are app-timezone and converted to UTC. warehouse_ids / product_ids are comma-separated.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        product_id:
                          type: integer
                        sku:
                          type: string
                        name:
                          type: string
                        line_count:
                          type: integer
                        units:
                          type: integer
                example:
                  data:
                  - product_id: 10
                    sku: WIDGET-BLK
                    name: Widget - Black
                    line_count: 40
                    units: 88
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: returns:read
      operationId: get-api-returns-analytics-by-product
  /api/returns/analytics/trend:
    get:
      tags:
      - Returns & RMAs
      summary: Get Returns Trend
      description: 'Returns over time, grouped by week (Monday-start) or month.


        :::info[Required scope: `returns:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token. All query params are optional; dates
        are app-timezone and converted to UTC. warehouse_ids / product_ids are comma-separated.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        period:
                          type: string
                        units:
                          type: integer
                        receipt_count:
                          type: integer
                example:
                  data:
                  - period: '2026-05-04'
                    units: 61
                    receipt_count: 22
                  - period: '2026-05-11'
                    units: 58
                    receipt_count: 19
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: returns:read
      operationId: get-api-returns-analytics-trend
  /api/returns/inbox:
    get:
      tags:
      - Returns & RMAs
      summary: List Returns Inbox
      description: 'Paginated, enriched marketplace returns across channels. Each
        row has link status (an RMA already linked via external_source/external_return_id)
        and, when unlinked, a suggested order match.


        :::info[Required scope: `returns:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token. All filters optional.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        source:
                          type: string
                        integration_instance_id:
                          type: integer
                        external_return_id:
                          type: string
                        channel_order_id:
                          type: string
                        status:
                          type: string
                        customer_name:
                          type: string
                        returned_at:
                          type: string
                        is_linked:
                          type: boolean
                        linked_rma_id:
                          type: string
                          nullable: true
                        linked_rma_number:
                          type: string
                          nullable: true
                        suggested_order_id:
                          type: integer
                        suggested_order_number:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - source: trackstar
                    integration_instance_id: 4
                    external_return_id: TS-10293
                    channel_order_id: SO-10293
                    status: requested
                    customer_name: Acme Co
                    returned_at: '2026-06-01T10:00:00.000000Z'
                    is_linked: false
                    linked_rma_id: null
                    linked_rma_number: null
                    suggested_order_id: 42
                    suggested_order_number: SO-10293
                  current_page: 1
                  last_page: 1
                  per_page: 15
                  total: 1
                  from: 1
                  to: 1
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: returns:read
      operationId: get-api-returns-inbox
  /api/returns/inbox/bulk-link:
    post:
      tags:
      - Returns & RMAs
      summary: Bulk Link Returns
      description: 'Link the selected marketplace returns to RMAs (creating/linking
        per the match service; idempotent and conflict-safe).


        :::info[Required scope: `returns:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Fields:

        - returns[] (required): { source (shopify|walmart|trackstar), external_return_id,
        channel_order_id? }'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                returns:
                  type: array
                  items:
                    type: object
                    properties:
                      source:
                        type: string
                      external_return_id:
                        type: string
                      channel_order_id:
                        type: string
              example:
                returns:
                - source: trackstar
                  external_return_id: TS-10293
                  channel_order_id: SO-10293
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      created:
                        type: integer
                      linked:
                        type: integer
                      conflict:
                        type: integer
                      no_match:
                        type: integer
                      already_linked:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    created: 1
                    linked: 0
                    conflict: 0
                    no_match: 0
                    already_linked: 0
                  message: 'Linked 1 return(s): 1 new RMA(s), 0 existing, 0 unmatched,
                    0 conflicts.'
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: returns:write
      operationId: post-api-returns-inbox-bulk-link
  /api/returns/inbox/match-now:
    post:
      tags:
      - Returns & RMAs
      summary: Match Returns Now
      description: 'Dispatch the tracked auto-match job for unlinked marketplace returns
        (optionally scoped to a source / integration). Returns a tracked_job_log_id;
        progress shows via the tracked job log endpoints. Job name: "Match Marketplace
        Returns".


        :::info[Required scope: `returns:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token. source and integration_instance_id
        are optional (omit for all).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                source:
                  type: string
                integration_instance_id:
                  type: integer
              example:
                source: trackstar
                integration_instance_id: 4
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 4310
                  message: Matching marketplace returns — track progress in the job
                    tray.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: returns:write
      operationId: post-api-returns-inbox-match-now
  /api/returns/reconciliation/unmatched:
    get:
      tags:
      - Returns & RMAs
      summary: List Unmatched Returns
      description: 'Paginated list of received returns that are not yet linked to
        a return authorization (RMA) — returns received without a matching authorization,
        plus ambiguous matches flagged for review. Use it to reconcile or write off
        aged, unmatched returns. Filter by warehouse, reconciliation status, aging,
        received date, or product, and search by SKU/name.


        Requires a Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        received_at:
                          type: string
                        age_days:
                          type: integer
                        reconciliation_status:
                          type: object
                          properties:
                            value:
                              type: string
                            label:
                              type: string
                        needs_review:
                          type: boolean
                        is_blind:
                          type: boolean
                        notes:
                          type: string
                          nullable: true
                        warehouse:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        received_by:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        rma:
                          type: string
                          nullable: true
                        lines:
                          type: array
                          items:
                            type: object
                            properties:
                              id:
                                type: integer
                              product_id:
                                type: integer
                              sku:
                                type: string
                              product_name:
                                type: string
                              quantity:
                                type: integer
                              unexpected_item:
                                type: boolean
                  current_page:
                    type: integer
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 4821
                    received_at: '2026-07-21T02:14:00.000000Z'
                    age_days: 0
                    reconciliation_status:
                      value: blind_unmatched
                      label: Unmatched
                    needs_review: false
                    is_blind: true
                    notes: null
                    warehouse:
                      id: 12
                      name: Returns Warehouse
                    received_by:
                      id: 3
                      name: Warehouse Operator
                    rma: null
                    lines:
                    - id: 9901
                      product_id: 55
                      sku: BRIEF-BUR-M
                      product_name: Burgundy Brief M
                      quantity: 1
                      unexpected_item: false
                  current_page: 1
                  first_page_url: '{{protocol}}{{domain}}/api/returns/reconciliation/unmatched?page=1'
                  from: 1
                  last_page: 1
                  last_page_url: '{{protocol}}{{domain}}/api/returns/reconciliation/unmatched?page=1'
                  next_page_url: null
                  path: '{{protocol}}{{domain}}/api/returns/reconciliation/unmatched'
                  per_page: 10
                  prev_page_url: null
                  to: 1
                  total: 1
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-returns-reconciliation-unmatched
  /api/returns/reconciliation/recent:
    get:
      tags:
      - Returns & RMAs
      summary: List Recently Received Returns
      description: 'Returns committed in a warehouse within the given window (today,
        or the last 7 days), across all operators — for confirming what has been received.
        Read-only.


        Requires a Bearer token.'
      parameters:
      - name: warehouse_id
        in: query
        schema:
          type: integer
        description: Warehouse to list recent returns for (required).
        example: '12'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        received_at:
                          type: string
                        age_days:
                          type: integer
                        reconciliation_status:
                          type: object
                          properties:
                            value:
                              type: string
                            label:
                              type: string
                        needs_review:
                          type: boolean
                        is_blind:
                          type: boolean
                        notes:
                          type: string
                          nullable: true
                        warehouse:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        received_by:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        rma:
                          type: string
                          nullable: true
                        lines:
                          type: array
                          items:
                            type: object
                            properties:
                              id:
                                type: integer
                              product_id:
                                type: integer
                              sku:
                                type: string
                              product_name:
                                type: string
                              quantity:
                                type: integer
                              unexpected_item:
                                type: boolean
                example:
                  data:
                  - id: 4821
                    received_at: '2026-07-21T02:14:00.000000Z'
                    age_days: 0
                    reconciliation_status:
                      value: blind_unmatched
                      label: Unmatched
                    needs_review: false
                    is_blind: true
                    notes: null
                    warehouse:
                      id: 12
                      name: Returns Warehouse
                    received_by:
                      id: 3
                      name: Warehouse Operator
                    rma: null
                    lines:
                    - id: 9901
                      product_id: 55
                      sku: BRIEF-BUR-M
                      product_name: Burgundy Brief M
                      quantity: 1
                      unexpected_item: false
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-returns-reconciliation-recent
  /api/returns/reconciliation/{returnReceipt}/link:
    post:
      tags:
      - Returns & RMAs
      summary: Link Return Receipt to RMA
      description: 'Link an unmatched return receipt to a return authorization (RMA),
        recording its received quantity without adding inventory a second time (the
        goods were already received). Provide exactly one of rma_id or sales_order_id;
        with sales_order_id the single open, unreceived RMA on that order is used.
        Fails with 422 if the target RMA is already received (which would double-count)
        or the order has zero/multiple open RMAs.


        Requires a Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                rma_id:
                  type: integer
              example:
                rma_id: 812
      parameters:
      - name: returnReceipt
        in: path
        schema:
          type: string
        required: true
        description: The return receipt ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      received_at:
                        type: string
                      age_days:
                        type: integer
                      reconciliation_status:
                        type: object
                        properties:
                          value:
                            type: string
                          label:
                            type: string
                      needs_review:
                        type: boolean
                      is_blind:
                        type: boolean
                      notes:
                        type: string
                        nullable: true
                      warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      received_by:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      rma:
                        type: object
                        properties:
                          id:
                            type: integer
                          rma_number:
                            type: string
                          sales_order_id:
                            type: integer
                          link_route:
                            type: string
                          link_type_label:
                            type: string
                          link_reference:
                            type: string
                      lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            product_id:
                              type: integer
                            sku:
                              type: string
                            product_name:
                              type: string
                            quantity:
                              type: integer
                            unexpected_item:
                              type: boolean
                example:
                  message: Return receipt linked.
                  data:
                    id: 4821
                    received_at: '2026-07-21T02:14:00.000000Z'
                    age_days: 0
                    reconciliation_status:
                      value: matched
                      label: Matched
                    needs_review: false
                    is_blind: false
                    notes: null
                    warehouse:
                      id: 12
                      name: Returns Warehouse
                    received_by:
                      id: 3
                      name: Warehouse Operator
                    rma:
                      id: 812
                      rma_number: RMA-2026-15452
                      sales_order_id: 7781
                      link_route: /rma/812
                      link_type_label: RMA
                      link_reference: RMA-2026-15452
                    lines:
                    - id: 9901
                      product_id: 55
                      sku: BRIEF-BUR-M
                      product_name: Burgundy Brief M
                      quantity: 1
                      unexpected_item: false
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      rma_id:
                        type: array
                        items:
                          type: string
                example:
                  message: This RMA has already been received; linking would double-count
                    inventory.
                  errors:
                    rma_id:
                    - This RMA has already been received; linking would double-count
                      inventory.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-returns-reconciliation-returnreceipt-link
  /api/suppliers:
    get:
      tags:
      - Suppliers
      summary: List Suppliers
      description: 'List all suppliers with list view support. Supports filtering,
        sorting, and pagination.


        Authentication: Requires Bearer token. Requires IsPowerUserAccess middleware.


        Sort fields: name, email, company_name, leadtime, created_at, updated_at,
        archived_at.'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        description: 'Page number (default: 1)'
        example: '1'
      - name: limit
        in: query
        schema:
          type: integer
        description: 'Items per page (default: 10)'
        example: '10'
      - name: search
        in: query
        schema:
          type: string
        description: Search by supplier name, email, company name
      - name: sort
        in: query
        schema:
          type: string
        description: Sort field. Prefix with - for descending (e.g. -name, created_at,
          leadtime)
      - name: archived
        in: query
        schema:
          type: integer
        description: 0 = active only, 1 = archived only
        example: '0'
      - name: included[]
        in: query
        schema:
          type: string
        description: Columns to include in response
      - name: excluded[]
        in: query
        schema:
          type: string
        description: Columns to exclude from response
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        company_name:
                          type: string
                        email:
                          type: string
                        primary_contact_name:
                          type: string
                        purchase_order_email:
                          type: string
                        messaging_phone:
                          type: string
                        website:
                          type: string
                        leadtime:
                          type: integer
                        minimum_order_quantity:
                          type: integer
                        target_stock_days:
                          type: integer
                        minimum_purchase_order:
                          type: number
                        purchase_order_format:
                          type: string
                          nullable: true
                        po_processing_method:
                          type: string
                        auto_fulfill_dropship:
                          type: boolean
                        auto_submit_dropship_po:
                          type: boolean
                        auto_generate_backorder_po:
                          type: boolean
                        auto_submit_backorder_po:
                          type: boolean
                        auto_split_backorder_po_by_brand:
                          type: boolean
                        auto_receive_backorder_po:
                          type: boolean
                        default_warehouse_id:
                          type: integer
                        default_store_id:
                          type: string
                          nullable: true
                        default_tax_rate_id:
                          type: string
                          nullable: true
                        default_payment_term_id:
                          type: string
                          nullable: true
                        timezone:
                          type: string
                        products_count:
                          type: integer
                        address:
                          type: object
                          properties:
                            id:
                              type: integer
                            label:
                              type: string
                            address1:
                              type: string
                            city:
                              type: string
                            zip:
                              type: string
                            country:
                              type: string
                            country_code:
                              type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                        archived_at:
                          type: string
                          nullable: true
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 1
                    name: Acme Supplier
                    company_name: Acme Wholesale Co
                    email: orders@acmewholesale.com
                    primary_contact_name: Bob Johnson
                    purchase_order_email: po@acmewholesale.com
                    messaging_phone: '+15551234567'
                    website: https://acmewholesale.com
                    leadtime: 7
                    minimum_order_quantity: 10
                    target_stock_days: 30
                    minimum_purchase_order: 500.0
                    purchase_order_format: null
                    po_processing_method: email
                    auto_fulfill_dropship: false
                    auto_submit_dropship_po: false
                    auto_generate_backorder_po: false
                    auto_submit_backorder_po: false
                    auto_split_backorder_po_by_brand: false
                    auto_receive_backorder_po: false
                    default_warehouse_id: 2
                    default_store_id: null
                    default_tax_rate_id: null
                    default_payment_term_id: null
                    timezone: Australia/Sydney
                    products_count: 45
                    address:
                      id: 3
                      label: Default
                      address1: 100 Supplier Lane
                      city: Sydney
                      zip: '2000'
                      country: Australia
                      country_code: AU
                    created_at: '2024-01-01T00:00:00.000000Z'
                    updated_at: '2024-01-15T09:00:00.000000Z'
                    archived_at: null
                  current_page: 1
                  last_page: 3
                  per_page: 10
                  total: 28
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-suppliers
    post:
      tags:
      - Suppliers
      summary: Create Supplier
      description: 'Create a new supplier. Automatically creates a default warehouse
        for the supplier and attaches default pricing tiers.


        :::info[Required scope: `suppliers:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token. Requires IsPowerUserAccess middleware.


        Notes:

        - email and purchase_order_email accept comma-separated multiple email addresses

        - messaging_phone: the supplier''s WhatsApp/SMS number in international format
        (E.164, e.g. +15551234567), used to message them from a purchase order

        - name must be unique

        - po_processing_method: email, ftp, direct

        - po_batch_schedule.days: monday, tuesday, wednesday, thursday, friday, saturday,
        sunday

        - default_stock_level: normal, low, critical


        **Requires permission:** `suppliers.create`


        Clearing `default_incoterm_id` (sending it as null/empty) also clears `default_incoterm_place`
        — a default named place is never kept without a default term.


        **Custom fields:** `custom_field_values` (optional array) sets values for
        supplier custom fields. Each entry takes `custom_field_id` (required — must
        reference a custom field defined for suppliers) and `value` (nullable); `id`
        is prohibited on create (value ids only exist once the supplier does). The
        response echoes each value with its field metadata: `name`, `slug`, `field_type`
        (`text` | `long_text` | `number` | `decimal` | `date` | `datetime` | `checkbox`
        | `dropdown`), `options`, `description`, and `is_visible_in_details`.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                company_name:
                  type: string
                primary_contact_name:
                  type: string
                email:
                  type: string
                purchase_order_email:
                  type: string
                messaging_phone:
                  type: string
                website:
                  type: string
                leadtime:
                  type: integer
                minimum_order_quantity:
                  type: integer
                target_stock_days:
                  type: integer
                minimum_purchase_order:
                  type: integer
                po_processing_method:
                  type: string
                po_batch_schedule:
                  type: array
                  items:
                    type: object
                    properties:
                      time:
                        type: string
                      days:
                        type: array
                        items:
                          type: string
                auto_fulfill_dropship:
                  type: boolean
                auto_submit_dropship_po:
                  type: boolean
                auto_generate_backorder_po:
                  type: boolean
                auto_submit_backorder_po:
                  type: boolean
                auto_split_backorder_po_by_brand:
                  type: boolean
                auto_receive_backorder_po:
                  type: boolean
                backorder_po_schedule:
                  type: array
                default_stock_level:
                  type: string
                default_tax_rate_id:
                  type: string
                  nullable: true
                default_payment_term_id:
                  type: integer
                timezone:
                  type: string
                address:
                  type: object
                  properties:
                    name:
                      type: string
                    company:
                      type: string
                    email:
                      type: string
                    phone:
                      type: string
                    address1:
                      type: string
                    city:
                      type: string
                    province:
                      type: string
                    province_code:
                      type: string
                    zip:
                      type: string
                    country:
                      type: string
                    country_code:
                      type: string
                    label:
                      type: string
                pricing:
                  type: array
                  items:
                    type: object
                    properties:
                      id:
                        type: integer
                default_incoterm_id:
                  type: integer
                default_incoterm_place:
                  type: string
                custom_field_values:
                  type: array
                  items:
                    type: object
                    properties:
                      custom_field_id:
                        type: integer
                      value:
                        type: string
              example:
                name: New Supplier
                company_name: New Supplier Co Pty Ltd
                primary_contact_name: Alice Brown
                email: alice@newsupplier.com,billing@newsupplier.com
                purchase_order_email: po@newsupplier.com
                messaging_phone: '+15551234567'
                website: https://newsupplier.com
                leadtime: 14
                minimum_order_quantity: 5
                target_stock_days: 45
                minimum_purchase_order: 200
                po_processing_method: email
                po_batch_schedule:
                - time: 09:00
                  days:
                  - monday
                  - wednesday
                  - friday
                auto_fulfill_dropship: false
                auto_submit_dropship_po: false
                auto_generate_backorder_po: true
                auto_submit_backorder_po: false
                auto_split_backorder_po_by_brand: false
                auto_receive_backorder_po: false
                backorder_po_schedule: []
                default_stock_level: normal
                default_tax_rate_id: null
                default_payment_term_id: 1
                timezone: Australia/Sydney
                address:
                  name: Alice Brown
                  company: New Supplier Co
                  email: info@newsupplier.com
                  phone: +61-2-9000-0000
                  address1: 200 Supplier Road
                  city: Melbourne
                  province: Victoria
                  province_code: VIC
                  zip: '3000'
                  country: Australia
                  country_code: AU
                  label: Default
                pricing:
                - id: 1
                default_incoterm_id: 12
                default_incoterm_place: Shanghai Port, CN
                custom_field_values:
                - custom_field_id: 3
                  value: Gold
                - custom_field_id: 5
                  value: '2026-01-15'
      parameters: []
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      company_name:
                        type: string
                      email:
                        type: string
                      leadtime:
                        type: integer
                      minimum_order_quantity:
                        type: integer
                      address:
                        type: object
                        properties:
                          id:
                            type: integer
                          label:
                            type: string
                          address1:
                            type: string
                          city:
                            type: string
                          zip:
                            type: string
                          country:
                            type: string
                          country_code:
                            type: string
                      pricing:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            currency_code:
                              type: string
                      custom_field_values:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            custom_field_id:
                              type: integer
                            value:
                              type: string
                            name:
                              type: string
                            slug:
                              type: string
                            field_type:
                              type: string
                            options:
                              type: array
                              items:
                                type: string
                            description:
                              type: string
                            is_visible_in_details:
                              type: boolean
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                  message:
                    type: string
                example:
                  data:
                    id: 10
                    name: New Supplier
                    company_name: New Supplier Co Pty Ltd
                    email: alice@newsupplier.com,billing@newsupplier.com
                    leadtime: 14
                    minimum_order_quantity: 5
                    address:
                      id: 8
                      label: Default
                      address1: 200 Supplier Road
                      city: Melbourne
                      zip: '3000'
                      country: Australia
                      country_code: AU
                    pricing:
                    - id: 1
                      name: Standard
                      currency_code: AUD
                    custom_field_values:
                    - id: 21
                      custom_field_id: 3
                      value: Gold
                      name: Preferred Tier
                      slug: preferred_tier
                      field_type: dropdown
                      options:
                      - Gold
                      - Silver
                      - Bronze
                      description: Negotiated service tier
                      is_visible_in_details: true
                    - id: 22
                      custom_field_id: 5
                      value: '2026-01-15'
                      name: Contract Renewal Date
                      slug: contract_renewal_date
                      field_type: date
                      options: null
                      description: null
                      is_visible_in_details: true
                    created_at: '2024-01-20T10:00:00.000000Z'
                    updated_at: '2024-01-20T10:00:00.000000Z'
                    archived_at: null
                  message: supplier created successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: suppliers:write
      operationId: post-api-suppliers
    delete:
      tags:
      - Suppliers
      summary: Bulk Delete Suppliers
      description: 'Bulk delete suppliers by IDs or by applying to all filtered results.


        :::info[Required scope: `suppliers:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token. Requires IsPowerUserAccess middleware.


        **Requires permission:** `suppliers.delete`'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 2 suppliers deleted successfully.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: suppliers:write
      operationId: delete-api-suppliers
  /api/suppliers/{supplier}:
    get:
      tags:
      - Suppliers
      summary: Get Supplier (with Warehouses)
      description: 'Get a single supplier with warehouses loaded.


        :::info[Required scope: `suppliers:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token. Requires IsPowerUserAccess middleware.


        The response includes the supplier''s `default_incoterm` (the full incoterm
        object, or null when no default is set).


        The response also includes `custom_field_values` — each entry pairs the stored
        value with its field metadata (`custom_field_id`, `name`, `slug`, `field_type`,
        `options`, `description`, `is_visible_in_details`).'
      parameters:
      - name: supplier
        in: path
        schema:
          type: integer
        required: true
        description: Supplier ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      company_name:
                        type: string
                      email:
                        type: string
                      primary_contact_name:
                        type: string
                      purchase_order_email:
                        type: string
                      messaging_phone:
                        type: string
                      website:
                        type: string
                      leadtime:
                        type: integer
                      minimum_order_quantity:
                        type: integer
                      target_stock_days:
                        type: integer
                      minimum_purchase_order:
                        type: number
                      po_processing_method:
                        type: string
                      auto_fulfill_dropship:
                        type: boolean
                      auto_generate_backorder_po:
                        type: boolean
                      auto_submit_backorder_po:
                        type: boolean
                      auto_split_backorder_po_by_brand:
                        type: boolean
                      auto_receive_backorder_po:
                        type: boolean
                      default_warehouse_id:
                        type: integer
                      default_store_id:
                        type: string
                        nullable: true
                      default_payment_term:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          generated_description:
                            type: string
                      timezone:
                        type: string
                      address:
                        type: object
                        properties:
                          id:
                            type: integer
                          label:
                            type: string
                          address1:
                            type: string
                          city:
                            type: string
                          zip:
                            type: string
                          country:
                            type: string
                          country_code:
                            type: string
                      warehouses:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            type:
                              type: string
                      warehouse_lead_times:
                        type: array
                        items:
                          type: object
                          properties:
                            warehouse_id:
                              type: integer
                            warehouse_name:
                              type: string
                            leadtime:
                              type: integer
                      custom_field_values:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            custom_field_id:
                              type: integer
                            value:
                              type: string
                            name:
                              type: string
                            slug:
                              type: string
                            field_type:
                              type: string
                            options:
                              type: array
                              items:
                                type: string
                            description:
                              type: string
                            is_visible_in_details:
                              type: boolean
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                example:
                  data:
                    id: 1
                    name: Acme Supplier
                    company_name: Acme Wholesale Co
                    email: orders@acmewholesale.com
                    primary_contact_name: Bob Johnson
                    purchase_order_email: po@acmewholesale.com
                    messaging_phone: '+15551234567'
                    website: https://acmewholesale.com
                    leadtime: 7
                    minimum_order_quantity: 10
                    target_stock_days: 30
                    minimum_purchase_order: 500.0
                    po_processing_method: email
                    auto_fulfill_dropship: false
                    auto_generate_backorder_po: false
                    auto_submit_backorder_po: false
                    auto_split_backorder_po_by_brand: false
                    auto_receive_backorder_po: false
                    default_warehouse_id: 2
                    default_store_id: null
                    default_payment_term:
                      id: 1
                      name: Net 30
                      generated_description: Payment due within 30 days
                    timezone: Australia/Sydney
                    address:
                      id: 3
                      label: Default
                      address1: 100 Supplier Lane
                      city: Sydney
                      zip: '2000'
                      country: Australia
                      country_code: AU
                    warehouses:
                    - id: 2
                      name: Acme Warehouse
                      type: supplier
                    warehouse_lead_times:
                    - warehouse_id: 2
                      warehouse_name: Main DC
                      leadtime: 20
                    custom_field_values:
                    - id: 21
                      custom_field_id: 3
                      value: Gold
                      name: Preferred Tier
                      slug: preferred_tier
                      field_type: dropdown
                      options:
                      - Gold
                      - Silver
                      - Bronze
                      description: Negotiated service tier
                      is_visible_in_details: true
                    - id: 22
                      custom_field_id: 5
                      value: '2026-01-15'
                      name: Contract Renewal Date
                      slug: contract_renewal_date
                      field_type: date
                      options: null
                      description: null
                      is_visible_in_details: true
                    created_at: '2024-01-01T00:00:00.000000Z'
                    updated_at: '2024-01-15T09:00:00.000000Z'
                    archived_at: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: suppliers:read
      operationId: get-api-suppliers-supplier
    put:
      tags:
      - Suppliers
      summary: Update Supplier
      description: 'Update an existing supplier. All fields are optional.


        :::info[Required scope: `suppliers:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        - `messaging_phone` — the supplier''s WhatsApp/SMS number in international
        format (E.164, e.g. +15551234567), used to message them from a purchase order.


        - `purchase_order_format` — only allowed on PUT.

        - `purchase_order_csv_columns` — optional array of column keys controlling
        which columns appear in this supplier''s outgoing PO email CSV attachment.
        Each entry must be one of the keys returned by `GET /api/purchase-orders/csv-columns`.
        Set to `null` (or omit) to fall back to the tenant default. Set to an empty
        array to fall back to the tenant default. Order of the array determines column
        order in the CSV. Use the `POST /api/suppliers/:supplier/csv-sample` endpoint
        to preview the layout.


        Authentication: Requires Bearer token. Requires IsPowerUserAccess middleware.


        **Requires permission:** `suppliers.update`


        Clearing `default_incoterm_id` (sending it as null/empty) also clears `default_incoterm_place`
        — a default named place is never kept without a default term.


        **Custom fields:** `custom_field_values` (optional array) fully replaces the
        supplier''s stored custom field values when present — entries with an `id`
        update that existing value (the id must reference a custom-field value belonging
        to THIS supplier; a value id from another supplier is rejected with a 422),
        entries without one create a new value (`custom_field_id` required, must reference
        a custom field defined for suppliers), and any stored value row omitted from
        the array is deleted. Omit the key entirely to leave stored values untouched.


        **Advanced lead times:** `warehouse_lead_times` (optional array of `{ warehouse_id,
        leadtime }`) sets supplier-level per-warehouse lead-time overrides. Rows with
        a `warehouse_id` and a numeric `leadtime` are upserted; a warehouse omitted
        from the array has its override removed. Omit the key to leave overrides untouched.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                company_name:
                  type: string
                primary_contact_name:
                  type: string
                email:
                  type: string
                purchase_order_email:
                  type: string
                messaging_phone:
                  type: string
                leadtime:
                  type: integer
                warehouse_lead_times:
                  type: array
                  items:
                    type: object
                    properties:
                      warehouse_id:
                        type: integer
                      leadtime:
                        type: integer
                minimum_order_quantity:
                  type: integer
                target_stock_days:
                  type: integer
                po_processing_method:
                  type: string
                auto_fulfill_dropship:
                  type: boolean
                auto_generate_backorder_po:
                  type: boolean
                purchase_order_format:
                  type: string
                  nullable: true
                purchase_order_csv_columns:
                  type: array
                  items:
                    type: string
                address:
                  type: object
                  properties:
                    address1:
                      type: string
                    city:
                      type: string
                    zip:
                      type: string
                    country:
                      type: string
                    country_code:
                      type: string
                    label:
                      type: string
                pricing:
                  type: array
                  items:
                    type: object
                    properties:
                      id:
                        type: integer
                default_incoterm_id:
                  type: integer
                default_incoterm_place:
                  type: string
                custom_field_values:
                  type: array
                  items:
                    type: object
                    properties:
                      id:
                        type: integer
                      custom_field_id:
                        type: integer
                      value:
                        type: string
              example:
                name: Acme Supplier Updated
                company_name: Acme Wholesale International
                primary_contact_name: Bob Johnson
                email: orders@acmewholesale.com
                purchase_order_email: po@acmewholesale.com
                messaging_phone: '+15551234567'
                leadtime: 10
                warehouse_lead_times:
                - warehouse_id: 2
                  leadtime: 20
                - warehouse_id: 5
                  leadtime: 45
                minimum_order_quantity: 15
                target_stock_days: 45
                po_processing_method: email
                auto_fulfill_dropship: true
                auto_generate_backorder_po: true
                purchase_order_format: null
                purchase_order_csv_columns:
                - sku
                - barcode
                - name
                - qty_ordered
                - unit_cost
                - extended_cost
                address:
                  address1: 100 Supplier Lane Updated
                  city: Sydney
                  zip: '2000'
                  country: Australia
                  country_code: AU
                  label: Default
                pricing:
                - id: 1
                - id: 2
                default_incoterm_id: 12
                default_incoterm_place: Shanghai Port, CN
                custom_field_values:
                - id: 21
                  custom_field_id: 3
                  value: Silver
                - custom_field_id: 5
                  value: '2027-01-15'
      parameters:
      - name: supplier
        in: path
        schema:
          type: integer
        required: true
        description: Supplier ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      leadtime:
                        type: integer
                      warehouse_lead_times:
                        type: array
                        items:
                          type: object
                          properties:
                            warehouse_id:
                              type: integer
                            warehouse_name:
                              type: string
                            leadtime:
                              type: integer
                      custom_field_values:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            custom_field_id:
                              type: integer
                            value:
                              type: string
                            name:
                              type: string
                            slug:
                              type: string
                            field_type:
                              type: string
                            options:
                              type: array
                              items:
                                type: string
                            description:
                              type: string
                            is_visible_in_details:
                              type: boolean
                      updated_at:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 1
                    name: Acme Supplier Updated
                    leadtime: 10
                    warehouse_lead_times:
                    - warehouse_id: 2
                      warehouse_name: Main DC
                      leadtime: 20
                    - warehouse_id: 5
                      warehouse_name: West Coast Store
                      leadtime: 45
                    custom_field_values:
                    - id: 21
                      custom_field_id: 3
                      value: Silver
                      name: Preferred Tier
                      slug: preferred_tier
                      field_type: dropdown
                      options:
                      - Gold
                      - Silver
                      - Bronze
                      description: Negotiated service tier
                      is_visible_in_details: true
                    - id: 23
                      custom_field_id: 5
                      value: '2027-01-15'
                      name: Contract Renewal Date
                      slug: contract_renewal_date
                      field_type: date
                      options: null
                      description: null
                      is_visible_in_details: true
                    updated_at: '2024-01-20T11:00:00.000000Z'
                  message: supplier Acme Supplier Updated updated successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: suppliers:write
      operationId: put-api-suppliers-supplier
    delete:
      tags:
      - Suppliers
      summary: Delete Supplier
      description: 'Delete a supplier. Returns 400 if the supplier is linked to purchase
        orders or other records. Deleting a supplier also removes its owned records,
        including its custom field values.


        :::info[Required scope: `suppliers:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token. Requires IsPowerUserAccess middleware.


        **Requires permission:** `suppliers.delete`'
      parameters:
      - name: supplier
        in: path
        schema:
          type: integer
        required: true
        description: Supplier ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: supplier deleted successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: suppliers:write
      operationId: delete-api-suppliers-supplier
  /api/v2/suppliers/{supplier}/messaging-contact:
    put:
      tags:
      - Suppliers
      summary: Set Supplier WhatsApp Contact
      description: 'Designate which of the supplier''s contacts is its WhatsApp/SMS
        contact. The supplier''s messaging number is synced to that contact''s phone.
        Send `contact_id: null` to clear the designation (the stored number is kept).
        Returns the updated supplier.


        Requires the `suppliers.update` permission. Returns 404 when the contact does
        not belong to the supplier.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                contact_id:
                  type: integer
              example:
                contact_id: 5012
      parameters:
      - name: supplier
        in: path
        schema:
          type: integer
        required: true
        example: '41'
        description: The supplier ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      messaging_phone:
                        type: string
                example:
                  data:
                    id: 41
                    name: Acme Corp
                    messaging_phone: '+15551234567'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-v2-suppliers-supplier-messaging-contact
  /api/suppliers/{supplier}/merge:
    post:
      tags:
      - Suppliers
      summary: Merge Suppliers
      description: 'Merge one supplier into another. The supplier in the URL is the
        **source**: all of its records are re-pointed to the target, and the source
        is then **permanently deleted**. **This operation is irreversible — there
        is no undo.**


        :::info[Required scope: `suppliers:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Body:

        - `target_supplier_id` (integer, required) — the surviving supplier that absorbs
        everything.


        What gets transferred to the target: purchase orders, purchase invoices, bills,
        vendor credits, vendor deposits, inbound shipments, supplier warehouses, inventory
        allocations, manufacturing/contractor references, cost entries, and forecast
        configurations. Supplier-product links, pricing-tier attachments, supplier
        inventory, and metric snapshots move too — where the target already has an
        equivalent record (e.g. the same product), the source''s duplicate is dropped
        in favor of the target''s. If the source was a product''s default supplier
        and the target also supplies that product, the target becomes the default.
        Custom field values move to the target as well — where the target already
        has a value for the same custom field, the target''s value is kept and the
        source''s is dropped.


        Errors (422):

        - merging a supplier into itself

        - the target supplier does not exist

        - source and target are different types (a product supplier cannot merge with
        a service provider)

        - the target supplier is archived (unarchive it first)


        Synchronous — completes in one transaction. Requires the `suppliers:write`
        token scope and permission to delete suppliers.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                target_supplier_id:
                  type: integer
              example:
                target_supplier_id: 41
      parameters:
      - name: supplier
        in: path
        schema:
          type: integer
        required: true
        description: Source supplier ID — this supplier is merged away and permanently
          deleted
        example: '58'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      name:
                        type: string
                      id:
                        type: integer
                      type:
                        type: string
                      type_label:
                        type: string
                      company_name:
                        type: string
                      email:
                        type: string
                      primary_contact_name:
                        type: string
                      purchase_order_email:
                        type: string
                      messaging_phone:
                        type: string
                      website:
                        type: string
                      leadtime:
                        type: integer
                      minimum_order_quantity:
                        type: integer
                      target_stock_days:
                        type: integer
                      minimum_purchase_order:
                        type: string
                      minimum_purchase_order_quantity:
                        type: integer
                      purchase_order_format:
                        type: string
                      purchase_order_csv_columns:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                      address:
                        type: object
                        properties:
                          id:
                            type: integer
                          label:
                            type: string
                            nullable: true
                          name:
                            type: string
                          phone:
                            type: string
                          company:
                            type: string
                          address1:
                            type: string
                          address2:
                            type: string
                            nullable: true
                          address3:
                            type: string
                            nullable: true
                          city:
                            type: string
                          province:
                            type: string
                          province_code:
                            type: string
                          zip:
                            type: string
                          country:
                            type: string
                          country_code:
                            type: string
                          fax:
                            type: string
                            nullable: true
                          redacted:
                            type: boolean
                      warehouses:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            dropship_enabled:
                              type: boolean
                            direct_returns:
                              type: boolean
                            customer_returns:
                              type: boolean
                      default_pricing_tier:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          currency_code:
                            type: string
                      default_warehouse_id:
                        type: integer
                      default_store_id:
                        type: string
                        nullable: true
                      po_processing_method:
                        type: string
                        nullable: true
                      po_batch_schedule:
                        type: string
                        nullable: true
                      default_shipping_method:
                        type: string
                        nullable: true
                      auto_fulfill_dropship:
                        type: boolean
                      auto_submit_dropship_po:
                        type: boolean
                      auto_generate_backorder_po:
                        type: boolean
                      auto_submit_backorder_po:
                        type: boolean
                      auto_split_backorder_po_by_brand:
                        type: boolean
                      auto_receive_backorder_po:
                        type: boolean
                      backorder_po_schedule:
                        type: string
                        nullable: true
                      default_stock_level:
                        type: string
                        nullable: true
                      default_tax_rate_id:
                        type: string
                        nullable: true
                      default_payment_term_id:
                        type: integer
                      default_deposit_percentage:
                        type: string
                        nullable: true
                      auto_apply_deposits:
                        type: boolean
                      wire_instructions:
                        type: string
                        nullable: true
                      default_payment_term:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          generated_description:
                            type: string
                      timezone:
                        type: string
                        nullable: true
                      products_count:
                        type: string
                        nullable: true
                example:
                  message: The supplier merged into 'Acme Corp' successfully
                  data:
                    name: Acme Corp
                    id: 41
                    type: goods
                    type_label: Product Supplier
                    company_name: Acme Corporation
                    email: orders@acme.com
                    primary_contact_name: John Doe
                    purchase_order_email: po@acme.com
                    messaging_phone: '+15551234567'
                    website: https://acme.com
                    leadtime: 14
                    minimum_order_quantity: 50
                    target_stock_days: 60
                    minimum_purchase_order: '500.00'
                    minimum_purchase_order_quantity: 100
                    purchase_order_format: pdf
                    purchase_order_csv_columns: null
                    created_at: '2025-11-02T09:15:22.000000Z'
                    updated_at: '2026-07-06T18:40:00.000000Z'
                    archived_at: null
                    address:
                      id: 913
                      label: null
                      name: Acme Corp
                      phone: +1 555 0100
                      company: Acme Corporation
                      address1: 100 Main St
                      address2: null
                      address3: null
                      city: Austin
                      province: Texas
                      province_code: TX
                      zip: '78701'
                      country: United States
                      country_code: US
                      fax: null
                      redacted: false
                    warehouses:
                    - id: 12
                      name: Acme Dropship WH
                      dropship_enabled: true
                      direct_returns: false
                      customer_returns: false
                    default_pricing_tier:
                      id: 3
                      name: Wholesale
                      currency_code: USD
                    default_warehouse_id: 12
                    default_store_id: null
                    po_processing_method: null
                    po_batch_schedule: null
                    default_shipping_method: null
                    auto_fulfill_dropship: false
                    auto_submit_dropship_po: false
                    auto_generate_backorder_po: false
                    auto_submit_backorder_po: false
                    auto_split_backorder_po_by_brand: false
                    auto_receive_backorder_po: false
                    backorder_po_schedule: null
                    default_stock_level: null
                    default_tax_rate_id: null
                    default_payment_term_id: 2
                    default_deposit_percentage: null
                    auto_apply_deposits: false
                    wire_instructions: null
                    default_payment_term:
                      id: 2
                      name: Net 30
                      generated_description: Net 30
                    timezone: null
                    products_count: null
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      target_supplier_id:
                        type: array
                        items:
                          type: string
                example:
                  message: A supplier cannot be merged into itself.
                  errors:
                    target_supplier_id:
                    - A supplier cannot be merged into itself.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: suppliers:write
      operationId: post-api-suppliers-supplier-merge
  /api/suppliers/{supplier}/activity-log:
    get:
      tags:
      - Suppliers
      summary: Get Supplier Activity Log
      description: 'Rolled-up activity timeline for a single supplier. Returns the
        supplier''s own field changes plus related activity across its purchase orders
        (and their lines and invoices), vendor credits (and their lines and shipments),
        vendor deposits, bills, and supplier products (and pricing). Results are paginated
        and ordered newest-first.


        :::info[Required scope: `suppliers:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token and the suppliers.show permission.


        Filters: filter[event] (created, updated, deleted, bulk_upsert), filter[source]
        (the origin of the change), filter[batch_uuid] (a single bulk batch), and
        filter[search] (matches actor name, event, changed properties, and related
        record type). Pagination: per_page (default 15).'
      parameters:
      - name: supplier
        in: path
        schema:
          type: integer
        required: true
        description: Supplier ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        description:
                          type: string
                        event:
                          type: string
                        subject_type:
                          type: string
                        subject_id:
                          type: integer
                        properties:
                          type: object
                          properties:
                            source:
                              type: string
                            attributes:
                              type: object
                              properties:
                                leadtime:
                                  type: integer
                            old:
                              type: object
                              properties:
                                leadtime:
                                  type: integer
                            metadata:
                              type: object
                              properties:
                                name:
                                  type: string
                                type:
                                  type: string
                                company_name:
                                  type: string
                        causer_name:
                          type: string
                        created_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                  path:
                    type: string
                  first_page_url:
                    type: string
                  last_page_url:
                    type: string
                  next_page_url:
                    type: string
                  prev_page_url:
                    type: string
                    nullable: true
                example:
                  data:
                  - id: 48213
                    description: updated
                    event: updated
                    subject_type: Supplier
                    subject_id: 35
                    properties:
                      source: manual
                      attributes:
                        leadtime: 10
                      old:
                        leadtime: 7
                      metadata:
                        name: HOGTUNES
                        type: service
                        company_name: Hogtunes Inc
                    causer_name: Kelly McKeown
                    created_at: '2026-07-06T14:22:11.000000Z'
                  - id: 48190
                    description: created
                    event: created
                    subject_type: PurchaseOrder
                    subject_id: 9021
                    properties:
                      source: manual
                      attributes:
                        status: draft
                        supplier_id: 35
                      metadata:
                        purchase_order_number: PO-9021
                    causer_name: Kelly McKeown
                    created_at: '2026-07-05T09:10:03.000000Z'
                  - id: 48001
                    description: created
                    event: created
                    subject_type: Bill
                    subject_id: 412
                    properties:
                      source: manual
                      metadata:
                        invoice_number: INV-412
                        supplier_id: 35
                        invoice_date: '2026-07-01'
                    causer_name: System
                    created_at: '2026-07-01T00:05:44.000000Z'
                  current_page: 1
                  last_page: 4
                  per_page: 15
                  total: 52
                  from: 1
                  to: 15
                  path: '{{protocol}}{{domain}}/api/suppliers/35/activity-log'
                  first_page_url: '{{protocol}}{{domain}}/api/suppliers/35/activity-log?page=1'
                  last_page_url: '{{protocol}}{{domain}}/api/suppliers/35/activity-log?page=4'
                  next_page_url: '{{protocol}}{{domain}}/api/suppliers/35/activity-log?page=2'
                  prev_page_url: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: suppliers:read
      operationId: get-api-suppliers-supplier-activity-log
  /api/suppliers/{supplier}/archive:
    put:
      tags:
      - Suppliers
      summary: Archive Supplier
      description: 'Archive a single supplier.


        :::info[Required scope: `suppliers:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token. Requires IsPowerUserAccess middleware.


        **Requires permission:** `suppliers.update`'
      requestBody:
        content: {}
      parameters:
      - name: supplier
        in: path
        schema:
          type: integer
        required: true
        description: Supplier ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 1
                    name: Acme Supplier
                  message: supplier Acme Supplier archived successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: suppliers:write
      operationId: put-api-suppliers-supplier-archive
  /api/suppliers/{supplier}/unarchived:
    put:
      tags:
      - Suppliers
      summary: Unarchive Supplier
      description: 'Unarchive a previously archived supplier.


        :::info[Required scope: `suppliers:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token. Requires IsPowerUserAccess middleware.


        **Requires permission:** `suppliers.update`'
      requestBody:
        content: {}
      parameters:
      - name: supplier
        in: path
        schema:
          type: integer
        required: true
        description: Supplier ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                  message:
                    type: string
                example:
                  data:
                    id: 1
                    name: Acme Supplier
                    archived_at: null
                  message: supplier Acme Supplier unarchived successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: suppliers:write
      operationId: put-api-suppliers-supplier-unarchived
  /api/suppliers/{supplier}/csv-sample:
    post:
      tags:
      - Suppliers
      summary: Download PO CSV Sample
      description: '**Legacy proxy.** Generate and download a 3-row sample CSV showing
        exactly which columns will be included in this supplier''s outgoing PO email
        attachment.


        :::info[Required scope: `suppliers:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        This endpoint is kept for backward compatibility — new clients should call
        `POST /api/suppliers/:supplier/po-sample` instead, which supports both CSV
        and XLSX (`format=xlsx`). Internally this route forwards to `po-sample` with
        `format=csv` forced.


        Used by the per-supplier CSV column picker so users can preview the layout
        before saving.


        Request body (all optional):

        - `columns` (array of strings) — Unsaved column selection to preview. If omitted,
        the saved supplier preference is used; if that is also empty, the tenant default
        falls through, then the system default (every registered column).


        Valid column keys (current registry): `purchase_order`, `sku`, `barcode`,
        `supplier_sku`, `name`, `qty_ordered`, `unit_cost`, `extended_cost`. Unknown
        keys are silently dropped.


        The response is a CSV file download (`Content-Type: text/csv`), not JSON.


        Authentication: Requires Bearer token. Scope: `suppliers:rw`.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                columns:
                  type: array
                  items:
                    type: string
              example:
                columns:
                - sku
                - barcode
                - name
                - qty_ordered
                - unit_cost
                - extended_cost
      parameters:
      - name: supplier
        in: path
        schema:
          type: integer
        required: true
        description: Supplier ID
        example: '1'
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: suppliers:write
      operationId: post-api-suppliers-supplier-csv-sample
  /api/suppliers/{supplier}/po-sample:
    post:
      tags:
      - Suppliers
      summary: Download PO Sample (CSV/XLSX)
      description: 'Generate and download a 3-row sample of the file the supplier
        will receive when this PO is submitted. Supports both CSV and XLSX (controlled
        by `format`). Backs the per-supplier PO file attachment column picker so users
        can preview the layout before saving.


        :::info[Required scope: `suppliers:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Request body (all optional):

        - `format` (string, `csv` | `xlsx`) — Output format. Defaults to `csv`. Use
        `xlsx` to preview the spreadsheet with text-typed cells (no scientific-notation
        corruption of long barcodes/SKUs).

        - `columns` (array of strings) — Unsaved column selection to preview. If omitted,
        the saved supplier preference is used; if that is also empty, the tenant default
        falls through, then the system default (every registered column).


        Valid column keys (current registry): `purchase_order`, `sku`, `barcode`,
        `supplier_sku`, `name`, `qty_ordered`, `unit_cost`, `extended_cost`. Unknown
        keys are silently dropped.


        **CSV behavior:** Values are written as plain CSV strings — quoted when they
        contain commas, quotes, or newlines per RFC 4180. No formula-prefix escaping
        is applied; long numeric-text columns (barcode, SKU) may be coerced to scientific
        notation by Excel on open. Use XLSX format to avoid that.


        **XLSX behavior:** Numeric-text columns are written with `t="inlineStr"` cells
        (force text), quantities as integers, costs with the `#,##0.00` price format.


        The response is a binary file download — `text/csv` for CSV, `application/vnd.openxmlformats-officedocument.spreadsheetml.sheet`
        for XLSX. Not JSON.


        Validation:

        - `format` must be one of `csv`, `xlsx` (any other value returns 422).


        Authentication: Requires Bearer token. Scope: `suppliers:rw`.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                format:
                  type: string
                columns:
                  type: array
                  items:
                    type: string
              example:
                format: xlsx
                columns:
                - sku
                - barcode
                - name
                - qty_ordered
                - unit_cost
                - extended_cost
      parameters:
      - name: supplier
        in: path
        schema:
          type: integer
        required: true
        description: Supplier ID
        example: '1'
      responses:
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      format:
                        type: array
                        items:
                          type: string
                example:
                  message: The selected format is invalid.
                  errors:
                    format:
                    - The selected format is invalid.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: suppliers:write
      operationId: post-api-suppliers-supplier-po-sample
  /api/suppliers/archive:
    put:
      tags:
      - Suppliers
      summary: Bulk Archive Suppliers
      description: 'Bulk archive suppliers by IDs or by applying to all filtered results.


        :::info[Required scope: `suppliers:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token. Requires IsPowerUserAccess middleware.


        **Requires permission:** `suppliers.update`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
                apply_to_all:
                  type: boolean
                filters:
                  type: object
                  properties: {}
              example:
                ids:
                - 2
                - 3
                apply_to_all: false
                filters: {}
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 2 suppliers archived successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: suppliers:write
      operationId: put-api-suppliers-archive
  /api/suppliers/unarchive:
    put:
      tags:
      - Suppliers
      summary: Bulk Unarchive Suppliers
      description: 'Bulk unarchive suppliers by IDs or by applying to all filtered
        results.


        :::info[Required scope: `suppliers:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token. Requires IsPowerUserAccess middleware.


        **Requires permission:** `suppliers.update`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
                apply_to_all:
                  type: boolean
                filters:
                  type: object
                  properties: {}
              example:
                ids:
                - 2
                - 3
                apply_to_all: false
                filters: {}
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 2 suppliers unarchived successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: suppliers:write
      operationId: put-api-suppliers-unarchive
  /api/suppliers/{supplier}/products:
    get:
      tags:
      - Suppliers
      summary: List Supplier Products
      description: 'Retrieve all products linked to a supplier. Supports search by
        supplier SKU, product SKU, or name (using Typesense with SQL fallback).


        :::info[Required scope: `suppliers:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token. Requires IsPowerUserAccess middleware.


        Pass a negative limit to return all products without pagination.'
      parameters:
      - name: query
        in: query
        schema:
          type: string
        description: Search by supplier SKU, product SKU, or product name
      - name: limit
        in: query
        schema:
          type: integer
        description: Items per page. Pass negative value to return all.
        example: '15'
      - name: page
        in: query
        schema:
          type: integer
        description: Page number
        example: '1'
      - name: supplier
        in: path
        schema:
          type: integer
        required: true
        description: Supplier ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        supplier_sku:
                          type: string
                        product_id:
                          type: integer
                        product:
                          type: object
                          properties:
                            id:
                              type: integer
                            sku:
                              type: string
                            name:
                              type: string
                        supplier_id:
                          type: integer
                        cost:
                          type: number
                        minimum_order_quantity:
                          type: integer
                  status:
                    type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 5
                    supplier_sku: ACM-001
                    product_id: 12
                    product:
                      id: 12
                      sku: PROD-001
                      name: Widget A
                    supplier_id: 1
                    cost: 9.99
                    minimum_order_quantity: 10
                  status: success
                  current_page: 1
                  last_page: 3
                  total: 25
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: suppliers:read
      operationId: get-api-suppliers-supplier-products
  /api/suppliers/{supplier}/products-stocks:
    post:
      tags:
      - Suppliers
      summary: Get Supplier Products Stock
      description: 'Get stock levels for specific products from a supplier''s perspective.


        :::info[Required scope: `suppliers:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token. Requires IsPowerUserAccess middleware.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 12
                - 15
                - 20
      parameters:
      - name: supplier
        in: path
        schema:
          type: integer
        required: true
        description: Supplier ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        product_id:
                          type: integer
                        sku:
                          type: string
                        supplier_stock:
                          type: integer
                        available_stock:
                          type: integer
                example:
                  data:
                  - product_id: 12
                    sku: PROD-001
                    supplier_stock: 500
                    available_stock: 450
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: suppliers:write
      operationId: post-api-suppliers-supplier-products-stocks
  /api/suppliers/{supplier}/pricing-tiers:
    get:
      tags:
      - Suppliers
      summary: Get Supplier Pricing Tiers
      description: 'List pricing tiers attached to a supplier using Spatie QueryBuilder
        (filter[key]=value bracket format).


        :::info[Required scope: `suppliers:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        The legacy table_specifications flag is now ignored. Response is a standard
        Laravel paginator (top-level data, current_page, last_page, per_page, total,
        links — not resource meta).


        Authentication: Requires Bearer token. Requires IsPowerUserAccess middleware.


        Query params: page, per_page (default 10; -1 = all rows), filter[search],
        filter[name], filter[currency_code], filter[pricing_type], filter[is_default],
        filter[archived], filter_groups (base64-encoded advanced filter tree), sort
        (default -is_default,-created_at).'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        description: Page number
        example: '1'
      - name: per_page
        in: query
        schema:
          type: integer
        description: Items per page (default 10). -1 returns all rows on one page
          (the legacy `limit` param is accepted as an alias)
        example: '10'
      - name: supplier
        in: path
        schema:
          type: integer
        required: true
        description: Supplier ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        currency_code:
                          type: string
                        pricing_type:
                          type: string
                        is_default:
                          type: boolean
                        base_pricing_tier_id:
                          type: string
                          nullable: true
                        archived_at:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 1
                    name: Standard
                    currency_code: AUD
                    pricing_type: fixed_price
                    is_default: true
                    base_pricing_tier_id: null
                    archived_at: null
                    created_at: '2024-01-15T10:00:00.000000Z'
                    updated_at: '2024-06-01T08:00:00.000000Z'
                  first_page_url: https://example.sku.io/api/suppliers/1/pricing-tiers?page=1
                  from: 1
                  last_page: 1
                  last_page_url: https://example.sku.io/api/suppliers/1/pricing-tiers?page=1
                  links: []
                  next_page_url: null
                  path: https://example.sku.io/api/suppliers/1/pricing-tiers
                  per_page: 10
                  prev_page_url: null
                  to: 1
                  total: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: suppliers:read
      operationId: get-api-suppliers-supplier-pricing-tiers
  /api/suppliers/{supplier}/pricing-tiers/{supplierPricingTier}/attach:
    post:
      tags:
      - Suppliers
      summary: Attach Pricing Tier to Supplier
      description: 'Attach an existing pricing tier to a supplier.


        :::info[Required scope: `suppliers:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token. Requires IsPowerUserAccess middleware.'
      requestBody:
        content: {}
      parameters:
      - name: supplier
        in: path
        schema:
          type: integer
        required: true
        description: Supplier ID
        example: '1'
      - name: supplierPricingTier
        in: path
        schema:
          type: integer
        required: true
        description: Supplier Pricing Tier ID to attach
        example: '2'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties: {}
                  message:
                    type: string
                example:
                  data: {}
                  message: Pricing tier attached successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: suppliers:write
      operationId: post-api-suppliers-supplier-pricing-tiers-supplierpricingtier-attach
  /api/suppliers/{supplier}/pricing-tiers/{tierId}:
    delete:
      tags:
      - Suppliers
      summary: Detach Pricing Tier from Supplier
      description: 'Delete a pricing tier from a supplier. Cannot delete default or
        linked pricing tiers.


        :::info[Required scope: `suppliers:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token. Requires IsPowerUserAccess middleware.'
      parameters:
      - name: supplier
        in: path
        schema:
          type: integer
        required: true
        description: Supplier ID
        example: '1'
      - name: tierId
        in: path
        schema:
          type: integer
        required: true
        description: Pricing Tier ID to remove
        example: '2'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Pricing tier deleted successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: suppliers:write
      operationId: delete-api-suppliers-supplier-pricing-tiers-tierid
  /api/suppliers/{supplier}/warehouses:
    get:
      tags:
      - Suppliers
      summary: Get Supplier Warehouses
      description: 'Get all warehouses associated with a supplier, with list view
        support.


        :::info[Required scope: `suppliers:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token. Requires IsPowerUserAccess middleware.'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        description: Page number
        example: '1'
      - name: included[]
        in: query
        schema:
          type: string
        description: Columns to include
      - name: excluded[]
        in: query
        schema:
          type: string
        description: Columns to exclude
      - name: supplier
        in: path
        schema:
          type: integer
        required: true
        description: Supplier ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        type:
                          type: string
                        supplier_id:
                          type: integer
                        address:
                          type: object
                          properties:
                            address1:
                              type: string
                            city:
                              type: string
                            country_code:
                              type: string
                example:
                  data:
                  - id: 2
                    name: Acme Warehouse
                    type: supplier
                    supplier_id: 1
                    address:
                      address1: 100 Supplier Lane
                      city: Sydney
                      country_code: AU
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: suppliers:read
      operationId: get-api-suppliers-supplier-warehouses
    post:
      tags:
      - Suppliers
      summary: Create Supplier Warehouse
      description: 'Create a new warehouse for a supplier. Automatically initializes
        supplier inventory for the new warehouse. If this is the supplier''s first
        warehouse (or is_default is true), it becomes the default warehouse.


        :::info[Required scope: `suppliers:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token. Requires IsPowerUserAccess middleware.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                is_default:
                  type: boolean
                address:
                  type: object
                  properties:
                    label:
                      type: string
                    address1:
                      type: string
                    city:
                      type: string
                    province:
                      type: string
                    province_code:
                      type: string
                    zip:
                      type: string
                    country:
                      type: string
                    country_code:
                      type: string
              example:
                name: Sydney Warehouse
                is_default: false
                address:
                  label: Main
                  address1: 500 Warehouse Rd
                  city: Sydney
                  province: New South Wales
                  province_code: NSW
                  zip: '2000'
                  country: Australia
                  country_code: AU
      parameters:
      - name: supplier
        in: path
        schema:
          type: integer
        required: true
        description: Supplier ID
        example: '1'
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      type:
                        type: string
                      supplier_id:
                        type: integer
                      address:
                        type: object
                        properties:
                          address1:
                            type: string
                          city:
                            type: string
                          country_code:
                            type: string
                  message:
                    type: string
                example:
                  data:
                    id: 5
                    name: Sydney Warehouse
                    type: supplier
                    supplier_id: 1
                    address:
                      address1: 500 Warehouse Rd
                      city: Sydney
                      country_code: AU
                  message: warehouse created successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: suppliers:write
      operationId: post-api-suppliers-supplier-warehouses
  /api/suppliers/warehouses/{warehouse}/linked-orders:
    post:
      tags:
      - Suppliers
      summary: Get Warehouse Linked Orders
      description: 'Get the count of open purchase orders linked to a warehouse. Used
        before deleting a warehouse to check for dependencies.


        :::info[Required scope: `suppliers:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token. Requires IsPowerUserAccess middleware.'
      requestBody:
        content: {}
      parameters:
      - name: warehouse
        in: path
        schema:
          type: integer
        required: true
        description: Warehouse ID
        example: '2'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      linked_orders:
                        type: integer
                example:
                  data:
                    linked_orders: 3
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: suppliers:write
      operationId: post-api-suppliers-warehouses-warehouse-linked-orders
  /api/suppliers/import/preview:
    post:
      tags:
      - Suppliers
      summary: Preview Supplier Import
      description: 'Preview a supplier import from a CSV file.


        :::info[Required scope: `suppliers:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token. Requires IsPowerUserAccess middleware.


        **Requires permission:** `suppliers.import`'
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                file:
                  type: string
                  description: CSV file containing suppliers to import
                  format: binary
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      total:
                        type: integer
                      valid:
                        type: integer
                      errors:
                        type: integer
                example:
                  data:
                    total: 20
                    valid: 18
                    errors: 2
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: suppliers:write
      operationId: post-api-suppliers-import-preview
  /api/suppliers/import:
    post:
      tags:
      - Suppliers
      summary: Import Suppliers
      description: 'Import suppliers from a CSV file.


        :::info[Required scope: `suppliers:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token. Requires IsPowerUserAccess middleware.


        **Requires permission:** `suppliers.import`'
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                file:
                  type: string
                  description: CSV file containing suppliers to import
                  format: binary
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      imported:
                        type: integer
                      skipped:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    imported: 18
                    skipped: 2
                  message: Import completed
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: suppliers:write
      operationId: post-api-suppliers-import
  /api/suppliers/{supplier}/import/preview:
    post:
      tags:
      - Suppliers
      summary: Preview Supplier Inventory Import
      description: 'Preview supplier inventory import from a CSV file.


        :::info[Required scope: `suppliers:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token. Requires IsPowerUserAccess middleware.'
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                file:
                  type: string
                  description: CSV file containing supplier inventory to import
                  format: binary
      parameters:
      - name: supplier
        in: path
        schema:
          type: integer
        required: true
        description: Supplier ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      total:
                        type: integer
                      valid:
                        type: integer
                      errors:
                        type: integer
                example:
                  data:
                    total: 100
                    valid: 98
                    errors: 2
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: suppliers:write
      operationId: post-api-suppliers-supplier-import-preview
  /api/suppliers/{supplier}/import:
    post:
      tags:
      - Suppliers
      summary: Import Supplier Inventory
      description: 'Import inventory levels for a specific supplier from a CSV file.


        :::info[Required scope: `suppliers:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token. Requires IsPowerUserAccess middleware.'
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                file:
                  type: string
                  description: CSV file containing supplier inventory levels
                  format: binary
      parameters:
      - name: supplier
        in: path
        schema:
          type: integer
        required: true
        description: Supplier ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      imported:
                        type: integer
                      skipped:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    imported: 98
                    skipped: 2
                  message: Inventory imported successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: suppliers:write
      operationId: post-api-suppliers-supplier-import
  /api/v2/suppliers/export:
    get:
      tags:
      - Suppliers
      summary: Export Suppliers
      description: 'Export the supplier list as a spreadsheet file. Synchronous —
        the response body is the file itself (`text/csv` or, with `format=xlsx`, an
        Excel workbook) named `suppliers-{timestamp}.{format}`.


        :::info[Required scope: `suppliers:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Accepts the same filters as the supplier list, so you can export a filtered
        subset. Every matching supplier is included (no pagination), ordered by ID
        ascending, with a fixed column set: ID, Name, Company Name, Email, Contact
        Name, Lead Time, Min Order Qty, Created At, Updated At, PO Email, Website,
        Minimum PO $, Minimum PO Qty, Fax, address fields (lines 1-3, city, state/province
        and code, zip, country and code, label), Default Pricing Tier ID, Default
        Warehouse ID, and Default Store ID.


        By default only non-archived suppliers are exported; use `filter[archived]=all`
        or `filter[archived]=only` to change that.


        Requires the `suppliers:read` token scope.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: text/csv
            Content-Disposition:
              schema:
                type: string
                example: attachment; filename=suppliers-2026-07-06-10-30-00.csv
          content:
            text/plain:
              schema:
                type: string
                example: 'ID,Name,Company Name,Email,Contact Name,Lead Time,Min Order
                  Qty,Created At,Updated At,PO Email,Website,"Minimum PO $","Minimum
                  PO Qty",Fax,Address Line 1,Address Line 2,Address Line 3,City,State/Province,State/Province
                  Code,Zip/Postal Code,Country,Country Code,Address Label,Default
                  Pricing Tier ID,Default Warehouse ID,Default Store ID

                  41,Acme Corp,Acme Corporation,orders@acme.com,John Doe,14,50,2025-11-02
                  09:15:22,2026-06-30 11:03:10,po@acme.com,https://acme.com,500.00,100,,100
                  Main St,,,Austin,Texas,TX,78701,United States,US,,3,12,'
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: suppliers:read
      operationId: get-api-v2-suppliers-export
  /api/suppliers/{supplier}/request-invoices:
    post:
      tags:
      - Suppliers
      summary: Request Invoices (Consolidated)
      description: 'Send a supplier one consolidated email requesting the outstanding
        invoices for several purchase orders at once. Each selected PO is re-validated
        server-side: it must belong to this supplier AND still be awaiting its invoice
        — ineligible ids are skipped and reported back (not emailed). Every PO that
        IS sent is stamped (invoice_requested_at, invoice_request_count++, invoice_last_requested_by).


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        If none of the selected POs are eligible, returns 422.


        Authentication: Requires Bearer token.

        **Requires permission:** `purchase_orders.update`. Throttled: 60 requests/min.


        **Body fields:**

        - to (string, required) — recipient email

        - subject (string, required, max 255)

        - purchase_order_ids (array of ints, required, min 1) — POs to include

        - note (string, optional, max 2000)

        - cc (array of emails, optional, max 10)


        Requires both the suppliers and purchase-orders token scopes (it mutates purchase
        orders by stamping invoice-request tracking), plus the purchase_orders.update
        permission.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                to:
                  type: string
                subject:
                  type: string
                purchase_order_ids:
                  type: array
                  items:
                    type: integer
                note:
                  type: string
                cc:
                  type: array
                  items:
                    type: string
              example:
                to: ap@acme.example
                subject: Outstanding invoices — 3 purchase orders
                purchase_order_ids:
                - 4521
                - 4530
                - 4544
                note: Please send the invoices for the orders listed below; several
                  are already prepaid.
                cc:
                - buyer@ourcompany.example
      parameters:
      - name: supplier
        in: path
        schema:
          type: integer
        required: true
        description: Supplier ID
        example: '12'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  sent_count:
                    type: integer
                  skipped:
                    type: array
                    items:
                      type: object
                      properties:
                        purchase_order_id:
                          type: integer
                        reason:
                          type: string
                example:
                  sent_count: 2
                  skipped:
                  - purchase_order_id: 4544
                    reason: Not awaiting an invoice for this supplier.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: None of the selected purchase orders are awaiting an invoice
                    for this supplier.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:write
      operationId: post-api-suppliers-supplier-request-invoices
  /api/purchase-orders/{purchase_order}/invoice-reminders:
    patch:
      tags:
      - Suppliers
      summary: Manage Invoice Reminders
      description: 'Set the automated invoice-reminder mode for a purchase order:
        inherit (use the supplier/tenant setting), on, or off. Setting on arms the
        recurring chase when the PO is still awaiting its invoice; off stops it.


        Authentication: Requires Bearer token.

        Requires permission: purchase_orders.update. Throttled: 60 requests/min.


        Body fields:

        - mode (string, required) — one of: inherit, on, off'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                mode:
                  type: string
              example:
                mode: 'on'
      parameters:
      - name: purchase_order
        in: path
        schema:
          type: integer
        required: true
        description: Purchase Order ID
        example: '4521'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: integer
                  purchase_order_number:
                    type: string
                  invoice_status:
                    type: string
                  invoice_requested_at:
                    type: string
                  invoice_request_count:
                    type: integer
                  invoice_reminder_state:
                    type: string
                  invoice_reminder_next_at:
                    type: string
                  invoice_reminder_paused_reason:
                    type: string
                    nullable: true
                  invoice_reply_received_at:
                    type: string
                    nullable: true
                  invoice_reminders_enabled:
                    type: boolean
                  invoice_reminders_mode:
                    type: string
                example:
                  id: 4521
                  purchase_order_number: PO-004521
                  invoice_status: uninvoiced
                  invoice_requested_at: '2026-07-09T09:30:00+00:00'
                  invoice_request_count: 1
                  invoice_reminder_state: active
                  invoice_reminder_next_at: '2026-07-16T09:30:00+00:00'
                  invoice_reminder_paused_reason: null
                  invoice_reply_received_at: null
                  invoice_reminders_enabled: true
                  invoice_reminders_mode: 'on'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: patch-api-purchase-orders-purchase-order-invoice-reminders
  /api/suppliers/{supplier}/invoice-reminders:
    put:
      tags:
      - Suppliers
      summary: Update Supplier Invoice Reminders
      description: 'Update a supplier''s automated invoice-reminder settings — the
        mode plus optional cadence overrides. These resolve above the tenant default
        and below any per-PO override.


        Authentication: Requires Bearer token.

        Requires permission: purchase_orders.update.


        Body fields:

        - invoice_reminders_mode (string, required) — inherit | on | off

        - invoice_reminder_interval_days (int, nullable, 1-90) — days between reminders
        (blank = tenant default)

        - invoice_reminder_max_count (int, nullable, 1-12) — total requests (blank
        = tenant default)

        - invoice_reminder_start_after_days (int, nullable, 0-90) — delay before the
        first reminder (blank = tenant default)'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                invoice_reminders_mode:
                  type: string
                invoice_reminder_interval_days:
                  type: integer
                invoice_reminder_max_count:
                  type: integer
                invoice_reminder_start_after_days:
                  type: integer
              example:
                invoice_reminders_mode: 'on'
                invoice_reminder_interval_days: 10
                invoice_reminder_max_count: 4
                invoice_reminder_start_after_days: 3
      parameters:
      - name: supplier
        in: path
        schema:
          type: integer
        required: true
        description: Supplier ID
        example: '12'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: integer
                  name:
                    type: string
                  invoice_reminders_mode:
                    type: string
                  invoice_reminder_interval_days:
                    type: integer
                  invoice_reminder_max_count:
                    type: integer
                  invoice_reminder_start_after_days:
                    type: integer
                example:
                  id: 12
                  name: Acme Co
                  invoice_reminders_mode: 'on'
                  invoice_reminder_interval_days: 10
                  invoice_reminder_max_count: 4
                  invoice_reminder_start_after_days: 3
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-suppliers-supplier-invoice-reminders
  /api/suppliers/{supplier}/verify-bank-details:
    put:
      tags:
      - Suppliers
      summary: Verify Supplier Bank Details
      description: 'Mark this supplier''s wire instructions as verified out-of-band
        (for example, confirmed by phone with a known contact). Records who verified
        them and when, and clears the non-blocking bank-details warning shown when
        authorizing payment on the supplier''s bills.


        Editing a supplier''s wire instructions afterwards automatically clears this
        verification, so changed payee details must be re-verified.


        Authentication: Requires Bearer token.

        Requires permission: suppliers.update.


        Returns 422 if the supplier has no wire instructions to verify.'
      requestBody:
        content: {}
      parameters:
      - name: supplier
        in: path
        schema:
          type: integer
        required: true
        description: Supplier ID
        example: '12'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      type:
                        type: string
                      wire_instructions:
                        type: string
                      wire_instructions_verified_at:
                        type: string
                      wire_instructions_verified_by:
                        type: integer
                      wire_instructions_verified_by_name:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 12
                    name: Acme Manufacturing Co.
                    type: goods
                    wire_instructions: 'Beneficiary: Acme Manufacturing Co.

                      Bank: HSBC Hong Kong

                      SWIFT: HSBCHKHH

                      IBAN: HK29 2000 0000 0000 4821'
                    wire_instructions_verified_at: '2026-07-11T14:32:00+00:00'
                    wire_instructions_verified_by: 7
                    wire_instructions_verified_by_name: Jane Cooper
                  message: supplier Acme Manufacturing Co. updated successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-suppliers-supplier-verify-bank-details
  /api/suppliers/{supplier}/unverify-bank-details:
    put:
      tags:
      - Suppliers
      summary: Unverify Supplier Bank Details
      description: 'Clear a previous out-of-band verification of this supplier''s
        wire instructions. The bank-details warning reappears on the supplier''s bills
        until the details are verified again.


        Authentication: Requires Bearer token.

        Requires permission: suppliers.update.'
      requestBody:
        content: {}
      parameters:
      - name: supplier
        in: path
        schema:
          type: integer
        required: true
        description: Supplier ID
        example: '12'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      type:
                        type: string
                      wire_instructions:
                        type: string
                      wire_instructions_verified_at:
                        type: string
                        nullable: true
                      wire_instructions_verified_by:
                        type: string
                        nullable: true
                      wire_instructions_verified_by_name:
                        type: string
                        nullable: true
                  message:
                    type: string
                example:
                  data:
                    id: 12
                    name: Acme Manufacturing Co.
                    type: goods
                    wire_instructions: 'Beneficiary: Acme Manufacturing Co.

                      Bank: HSBC Hong Kong

                      SWIFT: HSBCHKHH

                      IBAN: HK29 2000 0000 0000 4821'
                    wire_instructions_verified_at: null
                    wire_instructions_verified_by: null
                    wire_instructions_verified_by_name: null
                  message: supplier Acme Manufacturing Co. updated successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-suppliers-supplier-unverify-bank-details
  /api/v2/suppliers/{supplier}/contacts:
    get:
      tags:
      - API
      summary: List Supplier Contacts
      description: 'List all contacts attached to a supplier, paginated. Supports
        search (title/notes), role/primary/has-email filters, advanced per-column
        filters, and sorting.


        Authentication: Requires Bearer token.'
      parameters:
      - name: supplier
        in: path
        schema:
          type: integer
        required: true
        description: Supplier ID
        example: '12'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        email:
                          type: string
                        phone:
                          type: string
                        role:
                          type: string
                        role_label:
                          type: string
                        title:
                          type: string
                        is_primary:
                          type: boolean
                        notes:
                          type: string
                        link_type:
                          type: string
                        link_id:
                          type: integer
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - id: 42
                    name: Jane Buyer
                    email: jane.buyer@example.com
                    phone: +1 415-555-0100
                    role: accounts_payable
                    role_label: Accounts Payable
                    title: AP Specialist
                    is_primary: true
                    notes: Prefers email over phone.
                    link_type: supplier
                    link_id: 12
                    created_at: '2026-07-13T14:22:05+00:00'
                    updated_at: '2026-07-13T14:22:05+00:00'
                  - id: 43
                    name: Sam Sales
                    email: sam.sales@example.com
                    phone: +1 415-555-0100
                    role: sales_rep
                    role_label: Sales Rep
                    title: Account Executive
                    is_primary: false
                    notes: Prefers email over phone.
                    link_type: supplier
                    link_id: 12
                    created_at: '2026-07-13T14:22:05+00:00'
                    updated_at: '2026-07-13T14:22:05+00:00'
                  current_page: 1
                  last_page: 1
                  per_page: 10
                  total: 2
                  from: 1
                  to: 2
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-v2-suppliers-supplier-contacts
    post:
      tags:
      - API
      summary: Create Supplier Contact
      description: 'Add a new contact to a supplier. Fields: name (required), email,
        phone, role (default general), title, is_primary, notes (max 500). The first
        contact added to a supplier automatically becomes primary; setting is_primary
        demotes the previous primary.


        Role options: general, sales_rep, account_manager, customer_service, accounts_payable,
        accounts_receivable, purchasing, shipping_receiving, warehouse_manager, operations,
        billing, owner, other.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                email:
                  type: string
                phone:
                  type: string
                role:
                  type: string
                title:
                  type: string
                is_primary:
                  type: boolean
                notes:
                  type: string
              example:
                name: Jane Buyer
                email: jane.buyer@example.com
                phone: +1 415-555-0100
                role: accounts_payable
                title: AP Specialist
                is_primary: true
                notes: Prefers email over phone.
      parameters:
      - name: supplier
        in: path
        schema:
          type: integer
        required: true
        description: Supplier ID
        example: '12'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      email:
                        type: string
                      phone:
                        type: string
                      role:
                        type: string
                      role_label:
                        type: string
                      title:
                        type: string
                      is_primary:
                        type: boolean
                      notes:
                        type: string
                      link_type:
                        type: string
                      link_id:
                        type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 42
                    name: Jane Buyer
                    email: jane.buyer@example.com
                    phone: +1 415-555-0100
                    role: accounts_payable
                    role_label: Accounts Payable
                    title: AP Specialist
                    is_primary: true
                    notes: Prefers email over phone.
                    link_type: supplier
                    link_id: 12
                    created_at: '2026-07-13T14:22:05+00:00'
                    updated_at: '2026-07-13T14:22:05+00:00'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      name:
                        type: array
                        items:
                          type: string
                example:
                  message: The name field is required.
                  errors:
                    name:
                    - A contact name (or inbox label) is required.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-v2-suppliers-supplier-contacts
  /api/v2/suppliers/{supplier}/contacts/export:
    get:
      tags:
      - API
      summary: Export Contacts
      description: 'Download all contacts belonging to the supplier as a CSV or XLSX
        file. Columns: Contact ID, Name, Email, Phone, Role, Title, Primary, Notes,
        Created At, Updated At. The file mirrors the contacts bulk-import template,
        so an exported file can be edited and re-imported (rows with a Contact ID
        or a matching email update the existing contact; others are created).


        Optional comma-separated column keys (`name,role,title,email,phone,notes,created_at`)
        to narrow the exported fields; `Contact ID` is always included so the file
        can round-trip as an update. Omit for the full field set.


        Optional. `filtered` applies the request''s filter/sort parameters (same syntax
        as the list endpoint) instead of exporting every contact.'
      parameters:
      - name: format
        in: query
        schema:
          type: string
        description: 'Export format: csv (default) or xlsx'
        example: csv
      - name: supplier
        in: path
        schema:
          type: integer
        required: true
        description: Supplier ID
        example: '1'
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-v2-suppliers-supplier-contacts-export
  /api/v2/suppliers/{supplier}/contacts/{contact}:
    get:
      tags:
      - API
      summary: Get Supplier Contact
      description: 'Get a single contact belonging to the supplier. A contact id that
        belongs to a different supplier returns 404.


        Authentication: Requires Bearer token.'
      parameters:
      - name: supplier
        in: path
        schema:
          type: integer
        required: true
        description: Supplier ID
        example: '12'
      - name: contact
        in: path
        schema:
          type: integer
        required: true
        description: Contact ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      email:
                        type: string
                      phone:
                        type: string
                      role:
                        type: string
                      role_label:
                        type: string
                      title:
                        type: string
                      is_primary:
                        type: boolean
                      notes:
                        type: string
                      link_type:
                        type: string
                      link_id:
                        type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 42
                    name: Jane Buyer
                    email: jane.buyer@example.com
                    phone: +1 415-555-0100
                    role: accounts_payable
                    role_label: Accounts Payable
                    title: AP Specialist
                    is_primary: true
                    notes: Prefers email over phone.
                    link_type: supplier
                    link_id: 12
                    created_at: '2026-07-13T14:22:05+00:00'
                    updated_at: '2026-07-13T14:22:05+00:00'
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Contact not found.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-v2-suppliers-supplier-contacts-contact
    put:
      tags:
      - API
      summary: Update Supplier Contact
      description: 'Update a contact belonging to the supplier. Full update — name
        is required. Setting is_primary promotes this contact and demotes the previous
        primary.


        Role options: general, sales_rep, account_manager, customer_service, accounts_payable,
        accounts_receivable, purchasing, shipping_receiving, warehouse_manager, operations,
        billing, owner, other.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                email:
                  type: string
                phone:
                  type: string
                role:
                  type: string
                title:
                  type: string
                is_primary:
                  type: boolean
                notes:
                  type: string
              example:
                name: Jane Buyer
                email: jane.buyer@example.com
                phone: +1 415-555-0100
                role: accounts_payable
                title: AP Specialist
                is_primary: true
                notes: Prefers email over phone.
      parameters:
      - name: supplier
        in: path
        schema:
          type: integer
        required: true
        description: Supplier ID
        example: '12'
      - name: contact
        in: path
        schema:
          type: integer
        required: true
        description: Contact ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      email:
                        type: string
                      phone:
                        type: string
                      role:
                        type: string
                      role_label:
                        type: string
                      title:
                        type: string
                      is_primary:
                        type: boolean
                      notes:
                        type: string
                      link_type:
                        type: string
                      link_id:
                        type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 42
                    name: Jane Buyer
                    email: jane.buyer@example.com
                    phone: +1 415-555-0100
                    role: accounts_payable
                    role_label: Accounts Payable
                    title: AP Specialist
                    is_primary: true
                    notes: Prefers email over phone.
                    link_type: supplier
                    link_id: 12
                    created_at: '2026-07-13T14:22:05+00:00'
                    updated_at: '2026-07-13T14:22:05+00:00'
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Contact not found.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      name:
                        type: array
                        items:
                          type: string
                example:
                  message: The name field is required.
                  errors:
                    name:
                    - A contact name (or inbox label) is required.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: put-api-v2-suppliers-supplier-contacts-contact
    delete:
      tags:
      - API
      summary: Delete Supplier Contact
      description: 'Delete a contact from the supplier. If the deleted contact was
        primary and other contacts remain, the oldest remaining contact is promoted
        to primary.


        Authentication: Requires Bearer token.'
      parameters:
      - name: supplier
        in: path
        schema:
          type: integer
        required: true
        description: Supplier ID
        example: '12'
      - name: contact
        in: path
        schema:
          type: integer
        required: true
        description: Contact ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                example:
                  success: true
                  message: Contact deleted.
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Contact not found.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: delete-api-v2-suppliers-supplier-contacts-contact
  /api/v2/suppliers/{supplier}/contacts/{contact}/make-primary:
    post:
      tags:
      - API
      summary: Set Supplier Contact as Primary
      description: 'Promote a contact to be the supplier''s primary contact, demoting
        the previous primary.


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: supplier
        in: path
        schema:
          type: integer
        required: true
        description: Supplier ID
        example: '12'
      - name: contact
        in: path
        schema:
          type: integer
        required: true
        description: Contact ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      email:
                        type: string
                      phone:
                        type: string
                      role:
                        type: string
                      role_label:
                        type: string
                      title:
                        type: string
                      is_primary:
                        type: boolean
                      notes:
                        type: string
                      link_type:
                        type: string
                      link_id:
                        type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 42
                    name: Jane Buyer
                    email: jane.buyer@example.com
                    phone: +1 415-555-0100
                    role: accounts_payable
                    role_label: Accounts Payable
                    title: AP Specialist
                    is_primary: true
                    notes: Prefers email over phone.
                    link_type: supplier
                    link_id: 12
                    created_at: '2026-07-13T14:22:05+00:00'
                    updated_at: '2026-07-13T14:22:05+00:00'
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Contact not found.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-v2-suppliers-supplier-contacts-contact-make-primary
  /api/suppliers/deletable:
    post:
      tags:
      - Suppliers
      summary: Check Suppliers Deletable
      description: 'Check which suppliers can be deleted before performing bulk delete.


        :::info[Required scope: `suppliers:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token. Requires IsPowerUserAccess middleware.


        **Requires permission:** `suppliers.delete`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
                scope:
                  type: string
              example:
                ids:
                - 1
                - 2
                scope: ids
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        deletable:
                          type: boolean
                        reason:
                          type: string
                        reason_details:
                          type: object
                          properties: {}
                example:
                  data:
                  - id: 1
                    name: Acme Supplier
                    deletable: false
                    reason: Linked to purchase orders
                    reason_details: {}
                  - id: 2
                    name: Beta Supplier
                    deletable: true
                    reason: null
                    reason_details: null
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: suppliers:write
      operationId: post-api-suppliers-deletable
  /api/supplier-products:
    post:
      tags:
      - Suppliers
      summary: Create Supplier Product
      description: 'Creates a new supplier product relationship (a product sold by
        a specific supplier).

        Authentication: Requires Bearer token.


        :::info[Required scope: `suppliers:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Fields:

        - supplier_id (required): Supplier ID (must exist in suppliers table)

        - product_id (required): Product ID (must be unique per supplier; must exist
        in products table)

        - supplier_sku (nullable, max:255): Supplier''s own SKU — must be unique per
        supplier

        - leadtime (nullable, integer): Lead time in days

        - minimum_order_quantity (nullable, numeric): Minimum order quantity (max
        999,999)

        - target_stock_days (nullable, integer): Target stock days (1-365)

        - is_default (boolean): Whether this is the default supplier for this product

        - default_tax_rate_id (nullable): Tax rate ID for this supplier product'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                supplier_id:
                  type: integer
                product_id:
                  type: integer
                supplier_sku:
                  type: string
                leadtime:
                  type: integer
                minimum_order_quantity:
                  type: integer
                target_stock_days:
                  type: integer
                is_default:
                  type: boolean
                default_tax_rate_id:
                  type: integer
              example:
                supplier_id: 3
                product_id: 42
                supplier_sku: ACM-WIDGET-001
                leadtime: 7
                minimum_order_quantity: 50
                target_stock_days: 30
                is_default: true
                default_tax_rate_id: 1
      parameters: []
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      product_id:
                        type: integer
                      supplier_id:
                        type: integer
                      supplier_sku:
                        type: string
                      leadtime:
                        type: integer
                      minimum_order_quantity:
                        type: integer
                      target_stock_days:
                        type: integer
                      is_default:
                        type: boolean
                      default_tax_rate_id:
                        type: integer
                      product_leadtime:
                        type: integer
                      product_minimum_order_quantity:
                        type: integer
                      product_target_stock_days:
                        type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                  message:
                    type: string
                  status:
                    type: string
                example:
                  data:
                    id: 15
                    product_id: 42
                    supplier_id: 3
                    supplier_sku: ACM-WIDGET-001
                    leadtime: 7
                    minimum_order_quantity: 50
                    target_stock_days: 30
                    is_default: true
                    default_tax_rate_id: 1
                    product_leadtime: 7
                    product_minimum_order_quantity: 50
                    product_target_stock_days: 30
                    created_at: '2024-01-15T10:00:00Z'
                    updated_at: '2024-01-15T10:00:00Z'
                  message: supplier product created successfully.
                  status: success
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      product_id:
                        type: array
                        items:
                          type: string
                example:
                  message: The given data was invalid.
                  errors:
                    product_id:
                    - This product already exists for this supplier.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: suppliers:write
      operationId: post-api-supplier-products
  /api/supplier-products/{supplier_product}:
    get:
      tags:
      - Suppliers
      summary: Get Supplier Product
      description: 'Returns full details for a supplier product including product,
        supplier, pricing tiers, and inventory levels per warehouse.

        Authentication: Requires Bearer token.


        :::info[Required scope: `suppliers:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: supplier_product
        in: path
        schema:
          type: integer
        required: true
        description: Supplier product ID
        example: '15'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      product_id:
                        type: integer
                      supplier_id:
                        type: integer
                      supplier_sku:
                        type: string
                      leadtime:
                        type: integer
                      minimum_order_quantity:
                        type: integer
                      target_stock_days:
                        type: integer
                      is_default:
                        type: boolean
                      default_tax_rate_id:
                        type: integer
                      supplier:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          default_tax_rate_id:
                            type: integer
                      supplier_default_tax_rate_id:
                        type: integer
                      product:
                        type: object
                        properties:
                          id:
                            type: integer
                          sku:
                            type: string
                          name:
                            type: string
                          average_cost:
                            type: number
                          leadtime:
                            type: integer
                      supplier_stock:
                        type: object
                        properties:
                          id:
                            type: integer
                          quantity:
                            type: integer
                          warehouse_id:
                            type: integer
                      pricing:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            supplier_pricing_tier_id:
                              type: integer
                            price:
                              type: number
                            min_quantity:
                              type: integer
                      inventories:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            warehouse_id:
                              type: integer
                            warehouse_name:
                              type: string
                            quantity:
                              type: integer
                            in_stock:
                              type: boolean
                            discontinued:
                              type: boolean
                            eta:
                              type: string
                              nullable: true
                            source:
                              type: string
                            updated_at:
                              type: string
                      product_leadtime:
                        type: integer
                      product_minimum_order_quantity:
                        type: integer
                      product_target_stock_days:
                        type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                  status:
                    type: string
                example:
                  data:
                    id: 15
                    product_id: 42
                    supplier_id: 3
                    supplier_sku: ACM-WIDGET-001
                    leadtime: 7
                    minimum_order_quantity: 50
                    target_stock_days: 30
                    is_default: true
                    default_tax_rate_id: 1
                    supplier:
                      id: 3
                      name: Acme Supplies Co.
                      default_tax_rate_id: 1
                    supplier_default_tax_rate_id: 1
                    product:
                      id: 42
                      sku: WIDGET-001
                      name: Blue Widget
                      average_cost: 12.5
                      leadtime: 7
                    supplier_stock:
                      id: 8
                      quantity: 500
                      warehouse_id: 1
                    pricing:
                    - id: 20
                      supplier_pricing_tier_id: 1
                      price: 10.0
                      min_quantity: 1
                    inventories:
                    - id: 8
                      warehouse_id: 1
                      warehouse_name: Main Warehouse
                      quantity: 500
                      in_stock: true
                      discontinued: false
                      eta: null
                      source: manual
                      updated_at: '2024-01-10T08:00:00Z'
                    product_leadtime: 7
                    product_minimum_order_quantity: 50
                    product_target_stock_days: 30
                    created_at: '2024-01-15T10:00:00Z'
                    updated_at: '2024-01-15T10:00:00Z'
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: suppliers:read
      operationId: get-api-supplier-products-supplier-product
    put:
      tags:
      - Suppliers
      summary: Update Supplier Product
      description: 'Updates an existing supplier product.

        Authentication: Requires Bearer token.

        Note: If supplier_id or product_id changes, supplier inventories are cleared
        and re-initialized. A warning is included in the response.


        :::info[Required scope: `suppliers:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                supplier_sku:
                  type: string
                leadtime:
                  type: integer
                minimum_order_quantity:
                  type: integer
                target_stock_days:
                  type: integer
                is_default:
                  type: boolean
                default_tax_rate_id:
                  type: integer
              example:
                supplier_sku: ACM-WIDGET-001-V2
                leadtime: 10
                minimum_order_quantity: 100
                target_stock_days: 45
                is_default: true
                default_tax_rate_id: 2
      parameters:
      - name: supplier_product
        in: path
        schema:
          type: integer
        required: true
        description: Supplier product ID
        example: '15'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      supplier_sku:
                        type: string
                      leadtime:
                        type: integer
                      minimum_order_quantity:
                        type: integer
                      target_stock_days:
                        type: integer
                      updated_at:
                        type: string
                  message:
                    type: string
                  status:
                    type: string
                example:
                  data:
                    id: 15
                    supplier_sku: ACM-WIDGET-001-V2
                    leadtime: 10
                    minimum_order_quantity: 100
                    target_stock_days: 45
                    updated_at: '2024-01-16T09:00:00Z'
                  message: supplier product ACM-WIDGET-001-V2 updated successfully.
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: suppliers:write
      operationId: put-api-supplier-products-supplier-product
    delete:
      tags:
      - Suppliers
      summary: Delete Supplier Product
      description: 'Deletes a supplier product and its associated inventories.

        Authentication: Requires Bearer token.


        :::info[Required scope: `suppliers:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: supplier_product
        in: path
        schema:
          type: integer
        required: true
        description: Supplier product ID
        example: '15'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  status:
                    type: string
                example:
                  message: supplier product deleted.
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: suppliers:write
      operationId: delete-api-supplier-products-supplier-product
  /api/supplier-products/{supplier_product}/activity-log:
    get:
      tags:
      - Suppliers
      summary: Get Supplier Product Activity Log
      description: 'Returns paginated activity log for a supplier product.

        Authentication: Requires Bearer token.


        :::info[Required scope: `suppliers:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: per_page
        in: query
        schema:
          type: integer
        description: 'Items per page (default: 15)'
        example: '15'
      - name: filter[search]
        in: query
        schema:
          type: string
        description: Search across causer name, properties, event
      - name: supplier_product
        in: path
        schema:
          type: integer
        required: true
        description: Supplier product ID
        example: '15'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        description:
                          type: string
                        event:
                          type: string
                        subject_type:
                          type: string
                        subject_id:
                          type: integer
                        properties:
                          type: object
                          properties:
                            old:
                              type: object
                              properties:
                                leadtime:
                                  type: integer
                            attributes:
                              type: object
                              properties:
                                leadtime:
                                  type: integer
                        causer_name:
                          type: string
                        created_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 300
                    description: updated
                    event: updated
                    subject_type: SupplierProduct
                    subject_id: 15
                    properties:
                      old:
                        leadtime: 7
                      attributes:
                        leadtime: 10
                    causer_name: Jane Doe
                    created_at: '2024-01-16T09:00:00Z'
                  current_page: 1
                  last_page: 1
                  per_page: 15
                  total: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: suppliers:read
      operationId: get-api-supplier-products-supplier-product-activity-log
  /api/supplier-products/{supplier_product}/notes:
    get:
      tags:
      - Suppliers
      summary: Get Supplier Product Notes
      description: 'Returns paginated notes for a supplier product, most recent first.

        Authentication: Requires Bearer token.


        :::info[Required scope: `suppliers:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: supplier_product
        in: path
        schema:
          type: integer
        required: true
        description: Supplier product ID
        example: '15'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      data:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            note:
                              type: string
                            is_pinned:
                              type: boolean
                            user:
                              type: object
                              properties:
                                id:
                                  type: integer
                                name:
                                  type: string
                            created_at:
                              type: string
                      current_page:
                        type: integer
                      total:
                        type: integer
                  status:
                    type: string
                example:
                  data:
                    data:
                    - id: 25
                      note: Lead time confirmed by supplier.
                      is_pinned: true
                      user:
                        id: 5
                        name: John Smith
                      created_at: '2024-01-15T10:00:00Z'
                    current_page: 1
                    total: 1
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: suppliers:read
      operationId: get-api-supplier-products-supplier-product-notes
    post:
      tags:
      - Suppliers
      summary: Add Supplier Product Note
      description: 'Adds a note to a supplier product.

        Authentication: Requires Bearer token.


        :::info[Required scope: `suppliers:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Fields:

        - note (required): Note text content

        - is_pinned (optional, boolean): Whether to pin the note'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                note:
                  type: string
                is_pinned:
                  type: boolean
              example:
                note: Lead time confirmed by supplier via email on 2024-01-15.
                is_pinned: false
      parameters:
      - name: supplier_product
        in: path
        schema:
          type: integer
        required: true
        description: Supplier product ID
        example: '15'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      note:
                        type: string
                      is_pinned:
                        type: boolean
                      user:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      created_at:
                        type: string
                  message:
                    type: string
                  status:
                    type: string
                example:
                  data:
                    id: 26
                    note: Lead time confirmed by supplier via email on 2024-01-15.
                    is_pinned: false
                    user:
                      id: 5
                      name: John Smith
                    created_at: '2024-01-15T11:00:00Z'
                  message: note created successfully.
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: suppliers:write
      operationId: post-api-supplier-products-supplier-product-notes
  /api/supplier-products/{supplier_product}/notes/{note}:
    delete:
      tags:
      - Suppliers
      summary: Delete Supplier Product Note
      description: 'Deletes a note from a supplier product.

        Authentication: Requires Bearer token.


        :::info[Required scope: `suppliers:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: supplier_product
        in: path
        schema:
          type: integer
        required: true
        description: Supplier product ID
        example: '15'
      - name: note
        in: path
        schema:
          type: integer
        required: true
        description: Note ID to delete
        example: '26'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  status:
                    type: string
                example:
                  message: note 26 deleted successfully.
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: suppliers:write
      operationId: delete-api-supplier-products-supplier-product-notes-note
  /api/supplier-products/{supplier_product}/pricing:
    put:
      tags:
      - Suppliers
      summary: Update Pricing Tiers
      description: "Updates pricing tiers for a supplier product.\nAuthentication:\
        \ Requires Bearer token.\n\n:::info[Required scope: `suppliers:write`]\nGrant\
        \ this scope to your token under [Settings → Developer → Personal Access Tokens](https://app.sku.io/settings/api).\n\
        :::\n\nFields:\n- pricing (required, array): Array of pricing tier entries\n\
        \  - pricing.*.supplier_pricing_tier_id (required, integer): Must exist in\
        \ supplier_pricing_tiers table\n  - pricing.*.price (required, numeric, min:0):\
        \ Price for this tier"
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                pricing:
                  type: array
                  items:
                    type: object
                    properties:
                      supplier_pricing_tier_id:
                        type: integer
                      price:
                        type: integer
              example:
                pricing:
                - supplier_pricing_tier_id: 1
                  price: 10
                - supplier_pricing_tier_id: 2
                  price: 9.5
                - supplier_pricing_tier_id: 3
                  price: 9
      parameters:
      - name: supplier_product
        in: path
        schema:
          type: integer
        required: true
        description: Supplier product ID
        example: '15'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      pricing:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            supplier_pricing_tier_id:
                              type: integer
                            price:
                              type: number
                  message:
                    type: string
                  status:
                    type: string
                example:
                  data:
                    id: 15
                    pricing:
                    - id: 20
                      supplier_pricing_tier_id: 1
                      price: 10.0
                    - id: 21
                      supplier_pricing_tier_id: 2
                      price: 9.5
                    - id: 22
                      supplier_pricing_tier_id: 3
                      price: 9.0
                  message: pricing 15 updated successfully.
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: suppliers:write
      operationId: put-api-supplier-products-supplier-product-pricing
  /api/supplier-pricing-tiers:
    get:
      tags:
      - Suppliers
      summary: List Supplier Pricing Tiers
      description: 'Returns a paginated list of supplier pricing tiers.


        Authentication: Requires Bearer token.


        Uses the list view trait supporting search, sort, pagination, and archived
        filtering.


        Response fields: id, name, pricing_type (absolute|relative), base_pricing_tier_id,
        base_pricing_tier_name, adjustment_percentage, adjustment_fixed_amount, rounding_value,
        display_name, currency_code, is_default, dependent_tier_count, chain_depth,
        created_at, updated_at, archived_at.'
      parameters:
      - name: search
        in: query
        schema:
          type: string
        description: General text search across searchable columns (name, currency_code)
        example: retail
      - name: sort
        in: query
        schema:
          type: string
        description: 'Sort column. Prefix with - for descending. Sortable: name, currency_code,
          is_default, created_at, updated_at.'
        example: name
      - name: page
        in: query
        schema:
          type: integer
        description: 'Page number (default: 1)'
        example: '1'
      - name: limit
        in: query
        schema:
          type: integer
        description: Results per page
        example: '25'
      - name: archived
        in: query
        schema:
          type: integer
        description: 0 = active only (default), 1 = archived only
        example: '0'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        pricing_type:
                          type: string
                        base_pricing_tier_id:
                          type: string
                          nullable: true
                        base_pricing_tier_name:
                          type: string
                          nullable: true
                        adjustment_percentage:
                          type: string
                          nullable: true
                        adjustment_fixed_amount:
                          type: string
                          nullable: true
                        rounding_value:
                          type: string
                          nullable: true
                        display_name:
                          type: string
                        currency_code:
                          type: string
                        is_default:
                          type: boolean
                        dependent_tier_count:
                          type: integer
                        chain_depth:
                          type: integer
                        created_at:
                          type: string
                        updated_at:
                          type: string
                        archived_at:
                          type: string
                          nullable: true
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 1
                    name: Retail USD
                    pricing_type: absolute
                    base_pricing_tier_id: null
                    base_pricing_tier_name: null
                    adjustment_percentage: null
                    adjustment_fixed_amount: null
                    rounding_value: null
                    display_name: Retail USD (USD)
                    currency_code: USD
                    is_default: true
                    dependent_tier_count: 2
                    chain_depth: 0
                    created_at: '2024-01-10T08:00:00.000000Z'
                    updated_at: '2024-03-15T10:00:00.000000Z'
                    archived_at: null
                  - id: 2
                    name: Wholesale USD
                    pricing_type: relative
                    base_pricing_tier_id: 1
                    base_pricing_tier_name: Retail USD
                    adjustment_percentage: '-15.0000'
                    adjustment_fixed_amount: null
                    rounding_value: '0.0500'
                    display_name: Wholesale USD (USD)
                    currency_code: USD
                    is_default: false
                    dependent_tier_count: 0
                    chain_depth: 1
                    created_at: '2024-01-12T09:00:00.000000Z'
                    updated_at: '2024-03-20T11:00:00.000000Z'
                    archived_at: null
                  current_page: 1
                  last_page: 2
                  per_page: 25
                  total: 8
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-supplier-pricing-tiers
    post:
      tags:
      - Suppliers
      summary: Create Supplier Pricing Tier
      description: 'Creates a new supplier pricing tier.


        :::info[Required scope: `suppliers:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Validation:

        - `name` (required, max:255, unique in supplier_pricing_tiers)

        - `currency_code` (required, exists:currencies,code)

        - `pricing_type` (required, in:absolute,relative; defaults to ''absolute''
        if omitted)

        - `base_pricing_tier_id` (required_if:pricing_type,relative; nullable, integer,
        exists:supplier_pricing_tiers)

        - `adjustment_percentage` (required_if:pricing_type,relative; nullable, numeric,
        between:-99.9999,999.9999)

        - `adjustment_fixed_amount` (nullable, numeric, between:-999999.9999,999999.9999)

        - `rounding_value` (nullable, numeric, gt:0, max:999999.9999)


        Business rules:

        - Relative tiers inherit the currency of their root absolute tier

        - Circular references are rejected

        - A tier cannot reference itself as the base tier


        **Requires permission:** `supplier_pricing_tiers.create`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                currency_code:
                  type: string
                pricing_type:
                  type: string
                base_pricing_tier_id:
                  type: integer
                adjustment_percentage:
                  type: integer
                adjustment_fixed_amount:
                  type: string
                  nullable: true
                rounding_value:
                  type: number
              example:
                name: Wholesale USD
                currency_code: USD
                pricing_type: relative
                base_pricing_tier_id: 1
                adjustment_percentage: -15
                adjustment_fixed_amount: null
                rounding_value: 0.05
      parameters: []
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      pricing_type:
                        type: string
                      base_pricing_tier_id:
                        type: integer
                      base_pricing_tier_name:
                        type: string
                        nullable: true
                      adjustment_percentage:
                        type: string
                      adjustment_fixed_amount:
                        type: string
                        nullable: true
                      rounding_value:
                        type: string
                      display_name:
                        type: string
                      currency_code:
                        type: string
                      is_default:
                        type: boolean
                      dependent_tier_count:
                        type: integer
                      chain_depth:
                        type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                  message:
                    type: string
                example:
                  data:
                    id: 3
                    name: Wholesale USD
                    pricing_type: relative
                    base_pricing_tier_id: 1
                    base_pricing_tier_name: null
                    adjustment_percentage: '-15.0000'
                    adjustment_fixed_amount: null
                    rounding_value: '0.0500'
                    display_name: Wholesale USD (USD)
                    currency_code: USD
                    is_default: false
                    dependent_tier_count: 0
                    chain_depth: 1
                    created_at: '2024-04-01T12:00:00.000000Z'
                    updated_at: '2024-04-01T12:00:00.000000Z'
                    archived_at: null
                  message: Supplier pricing tier has been created successfully
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      name:
                        type: array
                        items:
                          type: string
                      base_pricing_tier_id:
                        type: array
                        items:
                          type: string
                example:
                  message: The name has already been taken.
                  errors:
                    name:
                    - The name has already been taken.
                    base_pricing_tier_id:
                    - A pricing tier cannot reference itself as a base tier.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: suppliers:write
      operationId: post-api-supplier-pricing-tiers
    delete:
      tags:
      - Suppliers
      summary: Bulk Delete Pricing Tiers
      description: 'Bulk deletes multiple supplier pricing tiers by ID.


        :::info[Required scope: `suppliers:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `supplier_pricing_tiers.delete`'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 3 supplier pricing tiers have been deleted successfully
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: suppliers:write
      operationId: delete-api-supplier-pricing-tiers
  /api/supplier-pricing-tiers/{id}:
    get:
      tags:
      - Suppliers
      summary: Get Supplier Pricing Tier
      description: 'Returns a single supplier pricing tier by ID.


        :::info[Required scope: `suppliers:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      pricing_type:
                        type: string
                      base_pricing_tier_id:
                        type: string
                        nullable: true
                      base_pricing_tier_name:
                        type: string
                        nullable: true
                      adjustment_percentage:
                        type: string
                        nullable: true
                      adjustment_fixed_amount:
                        type: string
                        nullable: true
                      rounding_value:
                        type: string
                        nullable: true
                      display_name:
                        type: string
                      currency_code:
                        type: string
                      is_default:
                        type: boolean
                      dependent_tier_count:
                        type: integer
                      chain_depth:
                        type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                example:
                  data:
                    id: 1
                    name: Retail USD
                    pricing_type: absolute
                    base_pricing_tier_id: null
                    base_pricing_tier_name: null
                    adjustment_percentage: null
                    adjustment_fixed_amount: null
                    rounding_value: null
                    display_name: Retail USD (USD)
                    currency_code: USD
                    is_default: true
                    dependent_tier_count: 2
                    chain_depth: 0
                    created_at: '2024-01-10T08:00:00.000000Z'
                    updated_at: '2024-03-15T10:00:00.000000Z'
                    archived_at: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: suppliers:read
      operationId: get-api-supplier-pricing-tiers-id
    put:
      tags:
      - Suppliers
      summary: Update Supplier Pricing Tier
      description: 'Updates an existing supplier pricing tier.


        :::info[Required scope: `suppliers:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Validation (PUT — currency_code cannot be changed; all other fields are sometimes/optional):

        - `name` (required, max:255, unique ignoring current record)

        - `pricing_type` (sometimes, in:absolute,relative)

        - `base_pricing_tier_id` (sometimes, required_if:pricing_type,relative; nullable,
        integer)

        - `adjustment_percentage` (sometimes, required_if:pricing_type,relative; nullable,
        numeric, between:-99.9999,999.9999)

        - `adjustment_fixed_amount` (sometimes, nullable, numeric, between:-999999.9999,999999.9999)

        - `rounding_value` (sometimes, nullable, numeric, gt:0)


        Note: currency_code is immutable — excluded from PUT validation.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                pricing_type:
                  type: string
                base_pricing_tier_id:
                  type: integer
                adjustment_percentage:
                  type: integer
                adjustment_fixed_amount:
                  type: string
                  nullable: true
                rounding_value:
                  type: number
              example:
                name: Wholesale USD Updated
                pricing_type: relative
                base_pricing_tier_id: 1
                adjustment_percentage: -20
                adjustment_fixed_amount: null
                rounding_value: 0.05
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      pricing_type:
                        type: string
                      base_pricing_tier_id:
                        type: integer
                      base_pricing_tier_name:
                        type: string
                        nullable: true
                      adjustment_percentage:
                        type: string
                      adjustment_fixed_amount:
                        type: string
                        nullable: true
                      rounding_value:
                        type: string
                      display_name:
                        type: string
                      currency_code:
                        type: string
                      is_default:
                        type: boolean
                      dependent_tier_count:
                        type: integer
                      chain_depth:
                        type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                  message:
                    type: string
                example:
                  data:
                    id: 2
                    name: Wholesale USD Updated
                    pricing_type: relative
                    base_pricing_tier_id: 1
                    base_pricing_tier_name: null
                    adjustment_percentage: '-20.0000'
                    adjustment_fixed_amount: null
                    rounding_value: '0.0500'
                    display_name: Wholesale USD Updated (USD)
                    currency_code: USD
                    is_default: false
                    dependent_tier_count: 0
                    chain_depth: 1
                    created_at: '2024-01-12T09:00:00.000000Z'
                    updated_at: '2024-04-01T13:00:00.000000Z'
                    archived_at: null
                  message: Supplier pricing tier Wholesale USD Updated has been updated
                    successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: suppliers:write
      operationId: put-api-supplier-pricing-tiers-id
    delete:
      tags:
      - Suppliers
      summary: Delete Supplier Pricing Tier
      description: 'Deletes a supplier pricing tier. Will fail if:

        - The tier is the default tier

        - The tier has active supplier product prices

        - The tier is used in integration instance import mappings

        - The tier has active dependent relative tiers


        :::info[Required scope: `suppliers:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Supplier pricing tier Wholesale USD has been deleted successfully
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: array
                    items:
                      type: object
                      properties:
                        message:
                          type: string
                        code:
                          type: string
                        key:
                          type: string
                example:
                  message: Failed to delete supplier pricing tier Retail USD
                  errors:
                  - message: Cannot delete default supplier pricing tier (Retail USD)
                    code: is_defaultRESOURCE_LINKED
                    key: is_default
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: suppliers:write
      operationId: delete-api-supplier-pricing-tiers-id
  /api/supplier-pricing-tiers/{id}/archive:
    put:
      tags:
      - Suppliers
      summary: Archive Pricing Tier
      description: 'Archives a supplier pricing tier. Cannot archive the default tier
        or a tier that is the base for active dependent tiers.


        :::info[Required scope: `suppliers:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Supplier pricing tier Wholesale USD has been archived successfully
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 400 Cannot Archive Default
                  value:
                    message: ''
                    errors:
                    - message: Cannot archive the default supplier pricing tier (Retail
                        USD)
                      code: SupplierPricingTierUNACCEPTABLE
                      key: id
                example-1:
                  summary: 400 Has Active Dependent Tiers
                  value:
                    message: ''
                    errors:
                    - message: 'Cannot archive: this tier is used as a base for: Wholesale
                        USD, VIP USD'
                      code: SupplierPricingTierUNACCEPTABLE
                      key: id
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: suppliers:write
      operationId: put-api-supplier-pricing-tiers-id-archive
  /api/supplier-pricing-tiers/{id}/unarchived:
    put:
      tags:
      - Suppliers
      summary: Unarchive Pricing Tier
      description: 'Unarchives a supplier pricing tier.


        :::info[Required scope: `suppliers:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      pricing_type:
                        type: string
                      base_pricing_tier_id:
                        type: integer
                      base_pricing_tier_name:
                        type: string
                        nullable: true
                      adjustment_percentage:
                        type: string
                      adjustment_fixed_amount:
                        type: string
                        nullable: true
                      rounding_value:
                        type: string
                      display_name:
                        type: string
                      currency_code:
                        type: string
                      is_default:
                        type: boolean
                      dependent_tier_count:
                        type: integer
                      chain_depth:
                        type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                  message:
                    type: string
                example:
                  data:
                    id: 2
                    name: Wholesale USD
                    pricing_type: relative
                    base_pricing_tier_id: 1
                    base_pricing_tier_name: null
                    adjustment_percentage: '-15.0000'
                    adjustment_fixed_amount: null
                    rounding_value: '0.0500'
                    display_name: Wholesale USD (USD)
                    currency_code: USD
                    is_default: false
                    dependent_tier_count: 0
                    chain_depth: 1
                    created_at: '2024-01-12T09:00:00.000000Z'
                    updated_at: '2024-04-01T14:00:00.000000Z'
                    archived_at: null
                  message: Supplier pricing tier Wholesale USD has been unarchived
                    successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: suppliers:write
      operationId: put-api-supplier-pricing-tiers-id-unarchived
  /api/supplier-pricing-tiers/archive:
    put:
      tags:
      - Suppliers
      summary: Bulk Archive Pricing Tiers
      description: 'Bulk archives multiple supplier pricing tiers. Default tiers and
        tiers with active dependents are skipped with warnings.


        :::info[Required scope: `suppliers:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `supplier_pricing_tiers.archive`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 3
                - 4
                - 5
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 3 supplier pricing tiers have been archived successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: suppliers:write
      operationId: put-api-supplier-pricing-tiers-archive
  /api/supplier-pricing-tiers/unarchive:
    put:
      tags:
      - Suppliers
      summary: Bulk Unarchive Pricing Tiers
      description: 'Bulk unarchives multiple supplier pricing tiers.


        :::info[Required scope: `suppliers:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `supplier_pricing_tiers.archive`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 3
                - 4
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 2 supplier pricing tiers have been unarchived successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: suppliers:write
      operationId: put-api-supplier-pricing-tiers-unarchive
  /api/supplier-pricing-tiers/deletable:
    post:
      tags:
      - Suppliers
      summary: Check Supplier Pricing Tiers Deletable
      description: 'Checks whether each pricing tier can be safely deleted.


        :::info[Required scope: `suppliers:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Validation:

        - `ids` (required, array of integers, each must exist in supplier_pricing_tiers)

        - `ids.*` (integer)


        **Requires permission:** `supplier_pricing_tiers.delete`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1
                - 2
                - 3
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        deletable:
                          type: boolean
                        reason:
                          type: object
                          properties:
                            is_default:
                              type: string
                example:
                  data:
                  - id: 1
                    name: Retail USD
                    deletable: false
                    reason:
                      is_default: Cannot delete default supplier pricing tier (Retail
                        USD)
                  - id: 2
                    name: Wholesale USD
                    deletable: false
                    reason:
                      supplierProducts: Supplier pricing tier(Wholesale USD) is currently
                        used by 8 supplier product(s)
                  - id: 3
                    name: Unused Tier
                    deletable: true
                    reason: null
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: suppliers:write
      operationId: post-api-supplier-pricing-tiers-deletable
  /api/supplier-pricing-tiers/archivable:
    post:
      tags:
      - Suppliers
      summary: Check Supplier Pricing Tiers Archivable
      description: 'Checks whether each pricing tier can be archived. Default tiers
        cannot be archived.


        :::info[Required scope: `suppliers:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Validation:

        - `ids` (required, array of integers, each must exist in supplier_pricing_tiers)

        - `ids.*` (integer)


        **Requires permission:** `supplier_pricing_tiers.archive`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1
                - 2
                - 3
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        is_default:
                          type: boolean
                        archivable:
                          type: boolean
                        reason:
                          type: object
                          properties:
                            is_default:
                              type: string
                example:
                  data:
                  - id: 1
                    name: Retail USD
                    is_default: true
                    archivable: false
                    reason:
                      is_default: Cannot archive the default supplier pricing tier
                        (Retail USD)
                  - id: 2
                    name: Wholesale USD
                    is_default: false
                    archivable: true
                    reason: null
                  - id: 3
                    name: VIP USD
                    is_default: false
                    archivable: true
                    reason: null
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: suppliers:write
      operationId: post-api-supplier-pricing-tiers-archivable
  /api/supplier-pricing-tiers/{id}/default:
    put:
      tags:
      - Suppliers
      summary: Set as Default
      description: 'Sets the specified pricing tier as the system default. Clears
        the is_default flag from the previously default tier.


        :::info[Required scope: `suppliers:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Business rules:

        - Archived tiers cannot be set as default

        - Relative (non-absolute) tiers cannot be set as default'
      requestBody:
        content: {}
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      pricing_type:
                        type: string
                      base_pricing_tier_id:
                        type: string
                        nullable: true
                      base_pricing_tier_name:
                        type: string
                        nullable: true
                      adjustment_percentage:
                        type: string
                        nullable: true
                      adjustment_fixed_amount:
                        type: string
                        nullable: true
                      rounding_value:
                        type: string
                        nullable: true
                      display_name:
                        type: string
                      currency_code:
                        type: string
                      is_default:
                        type: boolean
                      dependent_tier_count:
                        type: integer
                      chain_depth:
                        type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                  message:
                    type: string
                example:
                  data:
                    id: 2
                    name: Wholesale USD
                    pricing_type: absolute
                    base_pricing_tier_id: null
                    base_pricing_tier_name: null
                    adjustment_percentage: null
                    adjustment_fixed_amount: null
                    rounding_value: null
                    display_name: Wholesale USD (USD)
                    currency_code: USD
                    is_default: true
                    dependent_tier_count: 0
                    chain_depth: 0
                    created_at: '2024-01-12T09:00:00.000000Z'
                    updated_at: '2024-04-01T15:00:00.000000Z'
                    archived_at: null
                  message: Supplier pricing tier Wholesale USD has been set as default
                    successfully
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: array
                    items:
                      type: object
                      properties:
                        message:
                          type: string
                        code:
                          type: string
                        key:
                          type: string
                example:
                  message: ''
                  errors:
                  - message: A relative pricing tier cannot be set as the default.
                    code: SupplierPricingTierUNACCEPTABLE
                    key: id
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: suppliers:write
      operationId: put-api-supplier-pricing-tiers-id-default
  /api/supplier-pricing-tiers/import/preview:
    post:
      tags:
      - Suppliers
      summary: Preview Pricing Tier Import
      description: 'Preview the result of importing supplier pricing tiers from a
        CSV/Excel file without committing.


        :::info[Required scope: `suppliers:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Content-Type: multipart/form-data


        **Requires permission:** `supplier_pricing_tiers.import`'
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                file:
                  type: string
                  description: CSV or Excel file with supplier pricing tier data
                  format: binary
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      headers:
                        type: array
                        items:
                          type: string
                      rows:
                        type: array
                        items:
                          type: object
                          properties:
                            name:
                              type: string
                            currency_code:
                              type: string
                            status:
                              type: string
                      total:
                        type: integer
                      errors:
                        type: array
                example:
                  data:
                    headers:
                    - name
                    - currency_code
                    rows:
                    - name: New Tier
                      currency_code: AUD
                      status: create
                    - name: Retail USD
                      currency_code: USD
                      status: update
                    total: 2
                    errors: []
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: suppliers:write
      operationId: post-api-supplier-pricing-tiers-import-preview
  /api/supplier-pricing-tiers/import:
    post:
      tags:
      - Suppliers
      summary: Import Pricing Tiers
      description: 'Imports supplier pricing tiers from a CSV or Excel file.


        :::info[Required scope: `suppliers:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Content-Type: multipart/form-data


        **Requires permission:** `supplier_pricing_tiers.import`'
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                file:
                  type: string
                  description: CSV or Excel file with supplier pricing tier data (name,
                    currency_code columns required)
                  format: binary
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 'Import completed: 3 created, 1 updated, 0 errors'
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: suppliers:write
      operationId: post-api-supplier-pricing-tiers-import
  /api/supplier-inventories:
    get:
      tags:
      - Suppliers
      summary: List Supplier Inventories
      description: 'Returns a paginated list of supplier inventory records using Spatie
        QueryBuilder.


        Authentication: Requires Bearer token.


        Filters (Spatie QueryBuilder):

        - filter[id]: Exact match on ID

        - filter[supplier_id]: Exact match on supplier ID

        - filter[warehouse_id]: Exact match on warehouse ID

        - filter[product_id]: Exact match on product ID

        - filter[sku]: Partial match on product SKU

        - filter[search]: Advanced search on product SKU


        Sort fields: id, quantity, eta, in_stock, discontinued, created_at, updated_at
        (default: -updated_at)


        Pagination: page + per_page (default 10)'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        description: Page number (Spatie QueryBuilder)
        example: '1'
      - name: sort
        in: query
        schema:
          type: string
        description: 'Sort field. Allowed: id, quantity, eta, in_stock, discontinued,
          created_at, updated_at. Prefix with - for descending (default: -updated_at)'
        example: -updated_at
      - name: filter[supplier_id]
        in: query
        schema:
          type: integer
        description: Filter by exact supplier ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        quantity:
                          type: integer
                        in_stock:
                          type: string
                          nullable: true
                        discontinued:
                          type: boolean
                        eta:
                          type: string
                          nullable: true
                        source:
                          type: string
                        product_id:
                          type: integer
                        sku:
                          type: string
                        product_name:
                          type: string
                        warehouse:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        supplier_sku:
                          type: string
                        supplier_id:
                          type: integer
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - id: 1
                    quantity: 500
                    in_stock: null
                    discontinued: false
                    eta: null
                    source: user
                    product_id: 42
                    sku: WIDGET-001
                    product_name: Blue Widget
                    warehouse:
                      id: 2
                      name: Main Warehouse
                    supplier_sku: ACME-W001
                    supplier_id: 5
                    created_at: '2024-01-15T10:00:00.000000Z'
                    updated_at: '2024-06-01T14:30:00.000000Z'
                  current_page: 1
                  last_page: 5
                  per_page: 10
                  total: 48
                  from: 1
                  to: 10
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-supplier-inventories
  /api/supplier-inventories/{id}/our-inventory:
    get:
      tags:
      - Suppliers
      summary: List Our Inventory for Supplier
      description: 'Returns a paginated list of OUR internal warehouse inventory rows
        for products supplied by the given supplier.


        :::info[Required scope: `suppliers:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Returns one row per (product, our_warehouse). Excludes the per-product totals
        row (warehouse_id = 0) and supplier-type warehouses.


        Authentication: Requires Bearer token.


        Filters (Spatie QueryBuilder):

        - filter[warehouse_id]: Exact match on warehouse ID

        - filter[product_id]: Exact match on product ID

        - filter[sku]: Partial match on product SKU

        - filter[search]: Partial match on product SKU or name

        - filter[stock_status]: Computed status filter (in_stock, low_stock, out_of_stock,
        incoming, allocated)


        Sort fields: inventory_total, inventory_available, inventory_allocated, inventory_on_hold,
        inventory_in_transit, inventory_stock_value, updated_at, sku, product_name,
        warehouse_name (default: -inventory_total)


        Pagination: page + per_page (default 10)'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        product_id:
                          type: integer
                        sku:
                          type: string
                        product_name:
                          type: string
                        warehouse:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            type:
                              type: string
                        inventory_total:
                          type: number
                        inventory_available:
                          type: number
                        inventory_allocated:
                          type: number
                        inventory_on_hold:
                          type: number
                        inventory_in_transit:
                          type: number
                        inventory_stock_value:
                          type: number
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - id: 101
                    product_id: 42
                    sku: WIDGET-001
                    product_name: Blue Widget
                    warehouse:
                      id: 2
                      name: Main Warehouse
                      type: internal
                    inventory_total: 500.0
                    inventory_available: 420.0
                    inventory_allocated: 50.0
                    inventory_on_hold: 10.0
                    inventory_in_transit: 20.0
                    inventory_stock_value: 1250.5
                    updated_at: '2024-01-15T10:00:00.000000Z'
                  current_page: 1
                  last_page: 5
                  per_page: 10
                  total: 47
                  from: 1
                  to: 10
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: suppliers:read
      operationId: get-api-supplier-inventories-id-our-inventory
  /api/supplier-inventories/{id}/our-inventory/stats:
    get:
      tags:
      - Suppliers
      summary: Get Our Inventory Stats for Supplier
      description: 'Returns aggregate stats for OUR internal warehouse inventory of
        products supplied by the given supplier.


        :::info[Required scope: `suppliers:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Honors the same filters as the index endpoint so stats reflect the active
        filter set.


        Authentication: Requires Bearer token.


        Response fields:

        - total_skus: Distinct product count

        - warehouses_count: Distinct internal warehouse count

        - total_available: Sum of available units across all rows

        - total_allocated: Sum of allocated units

        - total_on_hold: Sum of on-hold units

        - total_in_transit: Sum of in-transit units

        - total_units: Sum of total units (available + allocated + on_hold + in_transit)

        - total_stock_value: Sum of stock value (in account currency)'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      total_skus:
                        type: integer
                      warehouses_count:
                        type: integer
                      total_available:
                        type: number
                      total_allocated:
                        type: number
                      total_on_hold:
                        type: number
                      total_in_transit:
                        type: number
                      total_units:
                        type: number
                      total_stock_value:
                        type: number
                example:
                  data:
                    total_skus: 47
                    warehouses_count: 3
                    total_available: 12450.0
                    total_allocated: 320.0
                    total_on_hold: 85.0
                    total_in_transit: 540.0
                    total_units: 13395.0
                    total_stock_value: 24613.27
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: suppliers:read
      operationId: get-api-supplier-inventories-id-our-inventory-stats
  /api/supplier-inventories/list:
    get:
      tags:
      - Suppliers
      summary: List Supplier Inventories (Lookup)
      description: 'Returns a paginated list of supplier inventories via Spatie QueryBuilder.
        Same filter/sort support as the list view index.


        :::info[Required scope: `suppliers:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: per_page
        in: query
        schema:
          type: integer
        description: Records per page
        example: '20'
      - name: filter[supplier_id]
        in: query
        schema:
          type: integer
        description: Filter by supplier ID
        example: '5'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        quantity:
                          type: integer
                        in_stock:
                          type: string
                          nullable: true
                        discontinued:
                          type: boolean
                        eta:
                          type: string
                          nullable: true
                        source:
                          type: string
                        product_id:
                          type: integer
                        sku:
                          type: string
                        product_name:
                          type: string
                        supplier_id:
                          type: integer
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 1
                    quantity: 500
                    in_stock: null
                    discontinued: false
                    eta: null
                    source: api
                    product_id: 42
                    sku: WIDGET-001
                    product_name: Blue Widget
                    supplier_id: 5
                    updated_at: '2024-06-01T14:30:00.000000Z'
                  current_page: 1
                  per_page: 20
                  total: 35
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: suppliers:read
      operationId: get-api-supplier-inventories-list
  /api/supplier-inventories/{id}:
    get:
      tags:
      - Suppliers
      summary: Get Supplier Inventory
      description: 'Returns a single supplier inventory record with related product
        and warehouse data.


        :::info[Required scope: `suppliers:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      quantity:
                        type: integer
                      in_stock:
                        type: string
                        nullable: true
                      discontinued:
                        type: boolean
                      eta:
                        type: string
                      source:
                        type: string
                      product_id:
                        type: integer
                      sku:
                        type: string
                      product_name:
                        type: string
                      warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      supplier_sku:
                        type: string
                      supplier_id:
                        type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  status: success
                  data:
                    id: 1
                    quantity: 500
                    in_stock: null
                    discontinued: false
                    eta: '2024-09-01T00:00:00.000000Z'
                    source: user
                    product_id: 42
                    sku: WIDGET-001
                    product_name: Blue Widget
                    warehouse:
                      id: 2
                      name: Main Warehouse
                    supplier_sku: ACME-W001
                    supplier_id: 5
                    created_at: '2024-01-15T10:00:00.000000Z'
                    updated_at: '2024-06-01T14:30:00.000000Z'
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                example:
                  status: error
                  message: Not Found
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: suppliers:read
      operationId: get-api-supplier-inventories-id
    put:
      tags:
      - Suppliers
      summary: Update Supplier Inventory
      description: 'Updates a supplier inventory record. Sets source to ''user''.
        Provide either quantity OR in_stock (not both). On update every field is optional,
        so you can send a partial update — for example only `discontinued` or `eta`
        — without re-sending quantity/in_stock; the existing stock value is preserved.


        :::info[Required scope: `suppliers:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Fields:

        - supplier_id (required on create, optional on update): ID of the supplier

        - product_id (required on create, optional on update): ID of the product

        - warehouse_id (required on create, optional on update): ID of the warehouse

        - quantity (required on create if in_stock not provided; optional on update):
        Stock quantity (must be non-negative number). Sending quantity clears in_stock.

        - in_stock (required on create if quantity not provided; optional on update):
        Boolean stock flag — true means in stock with unspecified quantity. Sending
        in_stock clears quantity.

        - discontinued (optional): Boolean, marks item as discontinued

        - eta (optional): Expected availability date (ISO date)

        - source (required on create, optional on update): One of: user, api'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                supplier_id:
                  type: integer
                product_id:
                  type: integer
                warehouse_id:
                  type: integer
                quantity:
                  type: integer
                discontinued:
                  type: boolean
                eta:
                  type: string
                source:
                  type: string
              example:
                supplier_id: 5
                product_id: 42
                warehouse_id: 2
                quantity: 750
                discontinued: false
                eta: '2024-09-15'
                source: user
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      quantity:
                        type: integer
                      in_stock:
                        type: string
                        nullable: true
                      discontinued:
                        type: boolean
                      eta:
                        type: string
                      source:
                        type: string
                      product_id:
                        type: integer
                      sku:
                        type: string
                      product_name:
                        type: string
                      warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      supplier_id:
                        type: integer
                      updated_at:
                        type: string
                example:
                  status: success
                  message: supplier inventory updated successfully
                  data:
                    id: 1
                    quantity: 750
                    in_stock: null
                    discontinued: false
                    eta: '2024-09-15T00:00:00.000000Z'
                    source: user
                    product_id: 42
                    sku: WIDGET-001
                    product_name: Blue Widget
                    warehouse:
                      id: 2
                      name: Main Warehouse
                    supplier_id: 5
                    updated_at: '2024-06-15T14:00:00.000000Z'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      quantity:
                        type: array
                        items:
                          type: string
                example:
                  message: quantity must be non-negative number
                  errors:
                    quantity:
                    - quantity must be non-negative number
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: suppliers:write
      operationId: put-api-supplier-inventories-id
  /api/supplier-inventories/{id}/export:
    get:
      tags:
      - Suppliers
      summary: Export Supplier Inventories
      description: 'Exports all supplier inventory records for a specific supplier
        as a CSV or Excel file download. The supplier_id filter is automatically applied.


        :::info[Required scope: `suppliers:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Path params:

        - supplier: Supplier ID


        Response: File download'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: text/csv
            Content-Disposition:
              schema:
                type: string
                example: attachment; filename="supplier_inventories.csv"
          content:
            text/plain:
              schema:
                type: string
                example: '"SKU","Product Name","Warehouse","Quantity","In Stock","Discontinued","ETA","Source"

                  "WIDGET-001","Blue Widget","Main Warehouse","500","","No","","user"'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: suppliers:read
      operationId: get-api-supplier-inventories-id-export
  /api/supplier-inventories/{id}/archive:
    put:
      tags:
      - Suppliers
      summary: Archive Supplier Inventory
      description: 'Archives a single supplier inventory record. Idempotent — returns
        a warning if already archived.


        :::info[Required scope: `suppliers:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      quantity:
                        type: integer
                example:
                  status: success
                  message: supplier inventory 1 archived successfully
                  data:
                    id: 1
                    quantity: 500
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: suppliers:write
      operationId: put-api-supplier-inventories-id-archive
  /api/supplier-inventories/{id}/unarchived:
    put:
      tags:
      - Suppliers
      summary: Unarchive Supplier Inventory
      description: 'Unarchives a single supplier inventory record.


        :::info[Required scope: `suppliers:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                example:
                  status: success
                  message: supplier inventory 1 unarchived successfully
                  data:
                    id: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: suppliers:write
      operationId: put-api-supplier-inventories-id-unarchived
  /api/supplier-inventories/archive:
    put:
      tags:
      - Suppliers
      summary: Bulk Archive Supplier Inventories
      description: 'Bulk archives multiple supplier inventory records by ID array
        or current list view filters.


        :::info[Required scope: `suppliers:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1
                - 2
                - 3
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                example:
                  status: success
                  message: Supplier inventories archived successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: suppliers:write
      operationId: put-api-supplier-inventories-archive
  /api/supplier-inventories/unarchive:
    put:
      tags:
      - Suppliers
      summary: Bulk Unarchive Supplier Inventories
      description: 'Bulk unarchives multiple supplier inventory records by ID array
        or current list view filters.


        :::info[Required scope: `suppliers:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1
                - 2
                - 3
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  message:
                    type: string
                example:
                  status: success
                  message: Supplier inventories unarchived successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: suppliers:write
      operationId: put-api-supplier-inventories-unarchive
  /api/supplier-inventories/archivable:
    post:
      tags:
      - Suppliers
      summary: Check Supplier Inventories Archivable
      description: 'Checks whether each provided supplier inventory ID can be safely
        archived.


        :::info[Required scope: `suppliers:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1
                - 2
                - 3
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        archivable:
                          type: boolean
                        reason:
                          type: string
                          nullable: true
                example:
                  status: success
                  data:
                  - id: 1
                    archivable: true
                    reason: null
                  - id: 2
                    archivable: false
                    reason: Already archived
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: suppliers:write
      operationId: post-api-supplier-inventories-archivable
  /api/supplier-inventories/deletable:
    post:
      tags:
      - Suppliers
      summary: Check Supplier Inventories Deletable
      description: 'Checks whether each provided supplier inventory ID can be safely
        deleted.


        :::info[Required scope: `suppliers:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1
                - 2
                - 3
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        deletable:
                          type: boolean
                        reason:
                          type: string
                          nullable: true
                example:
                  status: success
                  data:
                  - id: 1
                    deletable: true
                    reason: null
                  - id: 2
                    deletable: false
                    reason: Linked to active purchase orders
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: suppliers:write
      operationId: post-api-supplier-inventories-deletable
  /api/supplier-inventories/{id}/import/template:
    get:
      tags:
      - Suppliers
      summary: Download Import Template
      description: 'Downloads an XLSX import template for a specific supplier, pre-populated
        with headers, sample data, field guide, and reference data (products, warehouses)
        for the tenant''s account.


        :::info[Required scope: `suppliers:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Path params:

        - supplier: Supplier ID


        Response: XLSX file download'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
            Content-Disposition:
              schema:
                type: string
                example: attachment; filename="supplier_inventory_template.xlsx"
          content:
            text/plain:
              schema:
                type: string
                example: '[Binary XLSX file content]'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: suppliers:read
      operationId: get-api-supplier-inventories-id-import-template
  /api/supplier-inventories/{id}/import/validate:
    post:
      tags:
      - Suppliers
      summary: Validate Import
      description: "Validates import data rows for a supplier without creating any\
        \ records. Safe to call repeatedly for UI previewing. Resolves SKU and warehouse\
        \ names against the tenant's catalogue and returns a per-row preview alongside\
        \ an aggregate summary.\n\n:::info[Required scope: `suppliers:write`]\nGrant\
        \ this scope to your token under [Settings → Developer → Personal Access Tokens](https://app.sku.io/settings/api).\n\
        :::\n\nThere is no hard row cap on this endpoint — SKU and warehouse lookups\
        \ are chunked internally so large files can be submitted in one request. Per-request\
        \ execution time and memory limits are raised for the duration of the call.\n\
        \nAuthentication: Requires Bearer token.\n\nPath params:\n- supplier: Supplier\
        \ ID\n\nBody fields:\n- rows (required): Array of raw import rows (1+).\n\
        \  - rows.*.sku (optional): Product SKU. Resolved case-insensitively.\n  -\
        \ rows.*.quantity (optional): Stock quantity (numeric string)\n  - rows.*.eta\
        \ (optional): ETA date string\n  - rows.*.in_stock (optional): Stock flag\
        \ (1/0/true/false/yes/y)\n  - rows.*.discontinued (optional): Discontinued\
        \ flag (1/0/true/false/yes/y)\n  - rows.*.warehouse (optional): Warehouse\
        \ name. Falls back to the supplier's default warehouse when omitted.\n\nErrors:\n\
        - 422 when standard validation fails (e.g. empty rows array).\n- 422 when\
        \ the manager raises an exception during lookup (translated from a 500 so\
        \ the client gets an actionable message)."
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                rows:
                  type: array
                  items:
                    type: object
                    properties:
                      sku:
                        type: string
                      quantity:
                        type: string
                      eta:
                        type: string
                      in_stock:
                        type: string
                        nullable: true
                      discontinued:
                        type: string
                      warehouse:
                        type: string
              example:
                rows:
                - sku: WIDGET-001
                  quantity: '500'
                  eta: '2024-09-01'
                  in_stock: null
                  discontinued: '0'
                  warehouse: Main Warehouse
                - sku: GADGET-XL
                  quantity: null
                  eta: null
                  in_stock: '1'
                  discontinued: '0'
                  warehouse: East Warehouse
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  items:
                    type: array
                    items:
                      type: object
                      properties:
                        row_index:
                          type: integer
                        sku:
                          type: string
                        product_id:
                          type: integer
                        product_name:
                          type: string
                        warehouse:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        quantity:
                          type: integer
                        eta:
                          type: string
                        in_stock:
                          type: boolean
                        discontinued:
                          type: boolean
                        errors:
                          type: array
                  summary:
                    type: object
                    properties:
                      total_items:
                        type: integer
                      total_errors:
                        type: integer
                      total_valid:
                        type: integer
                example:
                  items:
                  - row_index: 0
                    sku: WIDGET-001
                    product_id: 42
                    product_name: Widget 001
                    warehouse:
                      id: 2
                      name: Main Warehouse
                    quantity: 500
                    eta: '2024-09-01'
                    in_stock: false
                    discontinued: false
                    errors: []
                  - row_index: 1
                    sku: UNKNOWN-SKU
                    product_id: null
                    product_name: null
                    warehouse:
                      id: 2
                      name: Main Warehouse
                    quantity: null
                    eta: null
                    in_stock: false
                    discontinued: false
                    errors:
                    - SKU 'UNKNOWN-SKU' not found.
                  summary:
                    total_items: 2
                    total_errors: 1
                    total_valid: 1
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 'Validation failed: Supplier not found'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: suppliers:write
      operationId: post-api-supplier-inventories-id-import-validate
  /api/supplier-inventories/{id}/import:
    post:
      tags:
      - Suppliers
      summary: Execute Import
      description: "Queues a supplier inventory import — creates or updates inventory\
        \ records for a specific supplier in the background.\n\n:::info[Required scope:\
        \ `suppliers:write`]\nGrant this scope to your token under [Settings → Developer\
        \ → Personal Access Tokens](https://app.sku.io/settings/api).\n:::\n\nThis\
        \ endpoint is asynchronous. The HTTP response returns immediately (202 Accepted)\
        \ with a `tracked_job_log_id` that the client polls via the tracked job log\
        \ endpoints for progress and completion status. There is no hard row cap on\
        \ the payload — the queued job processes items in chunks of 500 in its own\
        \ transaction per chunk, so payloads of any size complete cleanly without\
        \ holding a long-running transaction open.\n\nAuthentication: Requires Bearer\
        \ token.\n\nPath params:\n- supplier: Supplier ID\n\nBody fields:\n- items\
        \ (required): Array of inventory items (1+). Only the top-level `items` array\
        \ is validated at the HTTP layer; each row is validated inside the queued\
        \ job and any per-row problems are surfaced as failures in the tracked job\
        \ results rather than as a 422. (Per-row `exists` validation was intentionally\
        \ removed from the request layer to avoid an N+1 that timed out large payloads.)\n\
        \  - items.*.product_id (required): Product ID\n  - items.*.warehouse_id (optional):\
        \ Warehouse ID\n  - items.*.quantity (optional): Stock quantity, integer >=\
        \ 0\n  - items.*.eta (optional): Expected availability date\n  - items.*.in_stock\
        \ (optional): Boolean stock flag\n  - items.*.discontinued (optional): Boolean\
        \ discontinued flag\n\nErrors:\n- 422 only when the top-level `items` array\
        \ is missing or empty.\n- 404 when the supplier does not exist.\n- Invalid\
        \ rows (e.g. unknown product_id) do NOT return 422 — the import is queued\
        \ and those rows are reported as failures in the tracked job results.\n\n\
        Note: Use the validate endpoint first to preview and catch row-level errors\
        \ before importing."
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                items:
                  type: array
                  items:
                    type: object
                    properties:
                      product_id:
                        type: integer
                      warehouse_id:
                        type: integer
                      quantity:
                        type: integer
                      eta:
                        type: string
                      in_stock:
                        type: string
                        nullable: true
                      discontinued:
                        type: boolean
              example:
                items:
                - product_id: 42
                  warehouse_id: 2
                  quantity: 500
                  eta: '2024-09-01'
                  in_stock: null
                  discontinued: false
                - product_id: 78
                  warehouse_id: 3
                  quantity: null
                  eta: null
                  in_stock: true
                  discontinued: false
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '202':
          description: Accepted
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 12345
                  message: Import queued — track progress in the job tray.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      items:
                        type: array
                        items:
                          type: string
                example:
                  message: The given data was invalid.
                  errors:
                    items:
                    - The items field is required.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: suppliers:write
      operationId: post-api-supplier-inventories-id-import
  /api/purchase-orders:
    get:
      tags:
      - Purchase Orders
      summary: List Purchase Orders (list view)
      description: 'Paginated purchase orders list using the list view trait. Supports
        full-text search, filters, sorting, and archival state.


        Authentication: Requires Bearer token.


        Filter scopes available:

        - filter[order_status]: draft, open, closed

        - filter[arriving_this_week]: 1

        - filter[overdue]: 1

        - filter[submission_status]: pending, sent

        - filter[receipt_status]: unreceived, partial, received, dropship

        - filter[shipment_status]: pending, shipped

        - filter[invoice_status]: uninvoiced, partial, invoiced


        Allowed sorts: id, purchase_order_number, purchase_order_date, estimated_delivery_date,
        order_status, submission_status, receipt_status, shipment_status, invoice_status,
        total, total_quantity, supplier_id, created_at, updated_at


        The response also includes `unfiltered_total`, the count of rows in the base
        scope before any user filters are applied — used by the frontend to show export
        totals.'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        description: Page number
        example: '1'
      - name: limit
        in: query
        schema:
          type: integer
        description: Items per page
        example: '15'
      - name: sort
        in: query
        schema:
          type: string
        description: 'Sort field. Prefix with - for descending (e.g. -created_at).
          Allowed: id, purchase_order_number, purchase_order_date, estimated_delivery_date,
          order_status, submission_status, receipt_status, shipment_status, invoice_status,
          total, total_quantity, supplier_id, created_at, updated_at'
        example: created_at
      - name: search
        in: query
        schema:
          type: string
        description: Full-text search across PO number, supplier name, item SKU, invoice
          number, tracking number
      - name: filter[order_status]
        in: query
        schema:
          type: string
        description: 'Filter by order status: draft, open, closed'
        example: open
      - name: filter[arriving_this_week]
        in: query
        schema:
          type: integer
        description: Filter POs arriving this week (1=true)
        example: '1'
      - name: filter[overdue]
        in: query
        schema:
          type: integer
        description: Filter overdue POs (1=true)
        example: '1'
      - name: archived
        in: query
        schema:
          type: integer
        description: 'Include archived: 0=exclude (default), 1=include, only=archived
          only'
        example: '0'
      - name: included[]
        in: query
        schema:
          type: string
        description: Relationships to include
      - name: excluded[]
        in: query
        schema:
          type: string
        description: Fields to exclude from response
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        po_number:
                          type: string
                        purchase_order_date:
                          type: string
                        supplier_id:
                          type: integer
                        supplier_name:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        destination_warehouse_id:
                          type: integer
                        order_status:
                          type: string
                        submission_status:
                          type: string
                        submission_blocked_no_email:
                          type: boolean
                        receipt_status:
                          type: string
                        shipment_status:
                          type: string
                        invoice_status:
                          type: string
                        total:
                          type: number
                        total_quantity:
                          type: integer
                        estimated_delivery_date:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  unfiltered_total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - id: 101
                    po_number: PO-00101
                    purchase_order_date: '2024-01-15'
                    supplier_id: 5
                    supplier_name:
                      id: 5
                      name: Acme Supplies
                    destination_warehouse_id: 2
                    order_status: open
                    submission_status: sent
                    submission_blocked_no_email: false
                    receipt_status: unreceived
                    shipment_status: pending
                    invoice_status: uninvoiced
                    total: 1500.0
                    total_quantity: 100
                    estimated_delivery_date: '2024-02-01'
                    created_at: '2024-01-15T10:00:00Z'
                    updated_at: '2024-01-15T10:00:00Z'
                  current_page: 1
                  last_page: 5
                  per_page: 15
                  total: 72
                  unfiltered_total: 1843
                  from: 1
                  to: 15
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-purchase-orders
    post:
      tags:
      - Purchase Orders
      summary: Create Purchase Order
      description: 'Create a new purchase order with optional line items.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Required fields:

        - purchase_order_date (date)

        - supplier_id OR supplier_name

        - currency_id OR currency_code

        - destination_warehouse_id: warehouse the stock will be received into (required
        for standard purchase orders; omit for dropship purchase orders, which ship
        directly to the customer)


        Optional fields:

        - purchase_order_number: custom PO number (auto-generated if omitted)

        - approval_status: pending (default) or approved

        - order_status: draft (only allowed value; omit for open)

        - shipment_id: required when destination_warehouse is Amazon FBA


        Line item fields:

        - product_id OR sku (required if not a cost line)

        - quantity (required, min:0)

        - amount (required, min:0) — unit cost

        - description, discount, tax_rate_id, estimated_delivery_date, nominal_code_id,
        is_free_of_charge, free_of_charge_reason, linked_backorders all optional


        **Requires permission:** `purchase_orders.create`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                purchase_order_date:
                  type: string
                supplier_id:
                  type: integer
                currency_id:
                  type: integer
                destination_warehouse_id:
                  type: integer
                purchase_order_number:
                  type: string
                submission_format:
                  type: string
                payment_term_id:
                  type: integer
                incoterm_id:
                  type: string
                  nullable: true
                store_id:
                  type: integer
                estimated_delivery_date:
                  type: string
                other_date:
                  type: string
                  nullable: true
                supplier_notes:
                  type: string
                tracking_number:
                  type: string
                  nullable: true
                is_tax_included:
                  type: boolean
                tax_rate_id:
                  type: string
                  nullable: true
                currency_rate:
                  type: integer
                approval_status:
                  type: string
                tags:
                  type: array
                  items:
                    type: string
                shipment_id:
                  type: string
                  nullable: true
                purchase_order_lines:
                  type: array
                  items:
                    type: object
                    properties:
                      product_id:
                        type: integer
                      description:
                        type: string
                      quantity:
                        type: integer
                      amount:
                        type: integer
                      discount:
                        type: integer
                      tax_rate_id:
                        type: string
                        nullable: true
                      estimated_delivery_date:
                        type: string
                        nullable: true
                      nominal_code_id:
                        type: string
                        nullable: true
                      is_free_of_charge:
                        type: boolean
                      linked_backorders:
                        type: array
                financial_lines:
                  type: array
                  items:
                    type: object
                    properties:
                      description:
                        type: string
                      quantity:
                        type: integer
                      amount:
                        type: integer
                      financial_line_type_id:
                        type: integer
                      allocate_to_products:
                        type: boolean
                      proration_strategy:
                        type: string
                incoterm_place:
                  type: string
                incoterm_version:
                  type: integer
              example:
                purchase_order_date: '2024-01-15'
                supplier_id: 5
                currency_id: 1
                destination_warehouse_id: 2
                purchase_order_number: PO-CUSTOM-001
                submission_format: email
                payment_term_id: 1
                incoterm_id: null
                store_id: 1
                estimated_delivery_date: '2024-02-01'
                other_date: null
                supplier_notes: Please ship ASAP
                tracking_number: null
                is_tax_included: false
                tax_rate_id: null
                currency_rate: 1
                approval_status: pending
                tags:
                - urgent
                shipment_id: null
                purchase_order_lines:
                - product_id: 10
                  description: Widget A
                  quantity: 100
                  amount: 15
                  discount: 0
                  tax_rate_id: null
                  estimated_delivery_date: null
                  nominal_code_id: null
                  is_free_of_charge: false
                  linked_backorders: []
                financial_lines:
                - description: Freight
                  quantity: 1
                  amount: 50
                  financial_line_type_id: 1
                  allocate_to_products: true
                  proration_strategy: quantity
                incoterm_place: Port of Los Angeles, CA
                incoterm_version: 2020
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      po_number:
                        type: string
                      order_status:
                        type: string
                      total:
                        type: number
                  message:
                    type: string
                example:
                  data:
                    id: 102
                    po_number: PO-CUSTOM-001
                    order_status: open
                    total: 1550.0
                  message: Purchase order created successfully
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      purchase_order_date:
                        type: array
                        items:
                          type: string
                      supplier_id:
                        type: array
                        items:
                          type: string
                      purchase_order_lines.0.quantity:
                        type: array
                        items:
                          type: string
                example:
                  message: The given data was invalid.
                  errors:
                    purchase_order_date:
                    - The purchase order date field is required.
                    supplier_id:
                    - The supplier id field is required when supplier name is not
                      present.
                    purchase_order_lines.0.quantity:
                    - The purchase order lines.0.quantity field is required.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: purchase-orders:write
      operationId: post-api-purchase-orders
    delete:
      tags:
      - Purchase Orders
      summary: Bulk Delete Purchase Orders
      description: 'Bulk delete purchase orders by IDs or by filter criteria.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Pass either ids[] or filters{} (Spatie filter params — same as list endpoint).
        Filters are resolved to IDs before deletion.


        **Requires permission:** `purchase_orders.delete`'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Purchase orders deleted successfully
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: purchase-orders:write
      operationId: delete-api-purchase-orders
  /api/purchase-orders/list:
    get:
      tags:
      - Purchase Orders
      summary: List Purchase Orders (List)
      description: 'Paginated purchase order list for the list view. Uses Spatie QueryBuilder
        with advanced grouped filter support.


        :::info[Required scope: `purchase-orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Supports both simple filters (filter[field]=value) and advanced grouped filter
        trees (filter_groups). The advanced system supports AND/OR conjunctions with
        nested groups.


        Available text filter columns: purchase_order_number, order_status, submission_status,
        confirmation_status (derived supplier-confirmation state; values: awaiting,
        confirmed, changes_requested, rejected), receipt_status, shipment_status,
        invoice_status, tracking_number, supplier_notes, submission_format, requested_shipping_method,
        po_type (standard/dropship/fba_inbound/awd_inbound), supplier_name, destination_warehouse_name,
        currency_code, payment_term, incoterm, shipping_method, supplier_email, supplier_po_email,
        supplier_company, supplier_contact, supplier_phone, supplier_address, supplier_city,
        supplier_province, supplier_zip, supplier_country, destination_email, destination_company,
        destination_phone, destination_address, destination_city, destination_province,
        destination_zip, destination_country, item_sku, item_name, item_nominal_code,
        item_supplier_sku, shipment_tracking, shipment_shipping_method, tag, invoice_number


        Available numeric filter columns: supplier_id, destination_warehouse_id, id,
        total_quantity, total, tax_cost, product_total, additional_cost, discount,
        line_item_count, item_quantity, item_price, item_received, item_tax_rate,
        shipment_quantity, shipment_received, irr, sell_through


        Available date filter columns: purchase_order_date, other_date, estimated_delivery_date,
        created_at, updated_at, fully_received_at, asn_last_sent_at, item_eta, shipment_date


        Logistics tracking date filter columns: `logistics_<slug>`_estimate, `logistics_<slug>`_actual
        — where &lt;slug> is the slug of any active LogisticsTrackingField (e.g. logistics_port-arrived_estimate,
        logistics_customs-cleared_actual). Each PO row in the response includes a
        logistics_tracking_field_values array with { slug, name, estimate_date, actual_date
        } entries for every active logistics tracking field configured for the tenant.


        The irr and sell_through numeric filters match against the purchase order''s
        annualized internal rate of return and sell-through, entered as whole percentages
        (e.g. irr greater_than 50 = an IRR above 50%, sell_through less_than 25 =
        under 25% sold through). They filter on the persisted product-variant return
        metrics; purchase orders without computed return metrics are excluded when
        either filter is used.


        Return metrics (per PO, whole percentages; null until computed / not meaningful):
        `sell_through` = product-variant sell-through (units sold ÷ received × 100),
        `irr` = annualized internal rate of return (× 100). Filter on them with the
        `irr` / `sell_through` numeric filters above.'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        description: Page number
        example: '1'
      - name: per_page
        in: query
        schema:
          type: integer
        description: Items per page (default 15)
        example: '15'
      - name: sort
        in: query
        schema:
          type: string
        description: 'Sort field. Prefix - for descending. Allowed: id, purchase_order_number,
          purchase_order_date, other_date, order_status, submission_status, receipt_status,
          shipment_status, invoice_status, estimated_delivery_date, tracking_number,
          total, total_quantity, tax_total, supplier_notes, supplier_name, destination_warehouse_name,
          currency_code, product_total, additional_cost, discount, line_item_count,
          payment_term_name, incoterm_description, created_at, updated_at, fully_received_at,
          asn_last_sent_at, submission_format, requested_shipping_method, currency_rate'
        example: -created_at
      - name: filter[search]
        in: query
        schema:
          type: string
        description: Full-text search across PO number (exact ID), tracking number,
          order status, submission format, supplier name, item SKU, invoice number
        example: PO-001
      - name: filter[archived]
        in: query
        schema:
          type: string
        description: 'Archival filter: omit=non-archived only, ''only''=archived only.
          Also supports advanced: filter[archived.is]=true'
      - name: filter[asn_sent]
        in: query
        schema:
          type: string
        description: 'ASN sent filter: true/false'
      - name: filter[is_tax_included]
        in: query
        schema:
          type: string
        description: 'Tax included filter: true/false'
      - name: filter[arriving_this_week]
        in: query
        schema:
          type: string
        description: Arriving this week scope filter
      - name: filter[overdue]
        in: query
        schema:
          type: string
        description: Overdue scope filter
      - name: filter[order_status][is]
        in: query
        schema:
          type: string
        description: 'Advanced text filter operators: is, is_not, contains, does_not_contain,
          starts_with, ends_with, is_empty, is_not_empty, is_one_of'
        example: open
      - name: filter[supplier_id][equals]
        in: query
        schema:
          type: string
        description: 'Numeric filter by supplier_id. Operators: equals, not_equals,
          greater_than, less_than, between'
      - name: filter[destination_warehouse_id][equals]
        in: query
        schema:
          type: string
        description: Numeric filter by destination_warehouse_id
      - name: filter[purchase_order_date][on_or_after]
        in: query
        schema:
          type: string
        description: 'Date filter. Operators: on, before, after, on_or_before, on_or_after,
          between, is_empty, is_not_empty'
      - name: filter[total][greater_than]
        in: query
        schema:
          type: string
        description: Numeric filter on total cost
      - name: filter[logistics_<slug>_estimate][on_or_after]
        in: query
        schema:
          type: string
        description: 'Date filter on a logistics tracking field estimate date. Replace
          &lt;slug> with the logistics field slug (e.g. logistics_port-arrived_estimate).
          Operators: on, before, after, on_or_before, on_or_after, between, is_empty,
          is_not_empty, is.'
      - name: filter[logistics_<slug>_actual][on_or_before]
        in: query
        schema:
          type: string
        description: Date filter on a logistics tracking field actual date (e.g. logistics_customs-cleared_actual).
          Same operators as the estimate filter.
      - name: filter_groups[conjunction]
        in: query
        schema:
          type: string
        description: 'GroupedFilterSupport tree root conjunction: and/or'
        example: and
      - name: filter_groups[children][0][type]
        in: query
        schema:
          type: string
        description: 'Filter tree node: condition or group'
        example: condition
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        purchase_order_number:
                          type: string
                        purchase_order_date:
                          type: string
                        other_date:
                          type: string
                          nullable: true
                        order_status:
                          type: string
                        submission_status:
                          type: string
                        submission_blocked_no_email:
                          type: boolean
                        receipt_status:
                          type: string
                        shipment_status:
                          type: string
                        invoice_status:
                          type: string
                        submission_format:
                          type: string
                        is_tax_included:
                          type: boolean
                        currency_rate:
                          type: number
                        supplier_name:
                          type: string
                        supplier_id:
                          type: integer
                        destination_warehouse_name:
                          type: string
                        destination_warehouse_id:
                          type: integer
                        estimated_delivery_date:
                          type: string
                        tracking_number:
                          type: string
                          nullable: true
                        requested_shipping_method:
                          type: string
                          nullable: true
                        total:
                          type: number
                        total_quantity:
                          type: integer
                        product_total:
                          type: number
                        additional_cost:
                          type: number
                        tax_total:
                          type: number
                        discount:
                          type: number
                        sell_through:
                          type: number
                        irr:
                          type: number
                        currency_code:
                          type: string
                        payment_term_name:
                          type: string
                        incoterm_description:
                          type: string
                          nullable: true
                        tags:
                          type: array
                        supplier_notes:
                          type: string
                          nullable: true
                        fully_received_at:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                        updated_at:
                          type: string
                        archived_at:
                          type: string
                          nullable: true
                        is_dropship:
                          type: boolean
                        po_type:
                          type: string
                        line_item_count:
                          type: integer
                        first_line_sku:
                          type: string
                        asn_last_sent_at:
                          type: string
                          nullable: true
                        invoices:
                          type: array
                        logistics_tracking_field_values:
                          type: array
                          items:
                            type: object
                            properties:
                              slug:
                                type: string
                              name:
                                type: string
                              estimate_date:
                                type: string
                              actual_date:
                                type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - id: 101
                    purchase_order_number: PO-00101
                    purchase_order_date: '2024-01-15T00:00:00.000000Z'
                    other_date: null
                    order_status: open
                    submission_status: sent
                    submission_blocked_no_email: false
                    receipt_status: unreceived
                    shipment_status: pending
                    invoice_status: uninvoiced
                    submission_format: email
                    is_tax_included: false
                    currency_rate: 1.0
                    supplier_name: Acme Supplies
                    supplier_id: 5
                    destination_warehouse_name: Main Warehouse
                    destination_warehouse_id: 2
                    estimated_delivery_date: '2024-02-01T00:00:00.000000Z'
                    tracking_number: null
                    requested_shipping_method: null
                    total: 1500.0
                    total_quantity: 100
                    product_total: 1500.0
                    additional_cost: 0.0
                    tax_total: 0.0
                    discount: 0.0
                    sell_through: 53.3
                    irr: 13.4
                    currency_code: USD
                    payment_term_name: Net 30
                    incoterm_description: null
                    tags: []
                    supplier_notes: null
                    fully_received_at: null
                    created_at: '2024-01-15T10:00:00.000000Z'
                    updated_at: '2024-01-15T10:00:00.000000Z'
                    archived_at: null
                    is_dropship: false
                    po_type: standard
                    line_item_count: 3
                    first_line_sku: SKU-001
                    asn_last_sent_at: null
                    invoices: []
                    logistics_tracking_field_values:
                    - slug: port-arrived
                      name: Port Arrived
                      estimate_date: '2026-06-01'
                      actual_date: '2026-06-03'
                    - slug: customs-cleared
                      name: Customs Cleared
                      estimate_date: '2026-06-10'
                      actual_date: null
                  current_page: 1
                  last_page: 4
                  per_page: 15
                  total: 56
                  from: 1
                  to: 15
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: purchase-orders:read
      operationId: get-api-purchase-orders-list
  /api/purchase-orders/list/export:
    get:
      tags:
      - Purchase Orders
      summary: Export Purchase Orders
      description: 'Export purchase orders as XLSX or CSV. Supports summary (one row
        per PO) and line_items (one row per line item with PO fields repeated) modes.


        :::info[Required scope: `purchase-orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Response: Binary file download (XLSX or CSV).


        Scope options:

        - filtered: Apply active filters (default)

        - all: Export all POs ignoring filters

        - current_page: Export current page only

        - selected: Export specific IDs (pass ids=1,2,3)


        Line item columns (always included in line_items mode): item_sku, item_barcode,
        item_name, item_description, item_quantity, item_received_qty, item_price,
        item_discount_rate, item_tax_rate, item_line_total, item_eta.


        **Requires permission:** `purchase_orders.export`'
      parameters:
      - name: format
        in: query
        schema:
          type: string
        description: 'Export format: xlsx (default) or csv'
        example: xlsx
      - name: content_mode
        in: query
        schema:
          type: string
        description: 'Content mode: summary (one row per PO, default) or line_items
          (one row per line item)'
        example: summary
      - name: scope
        in: query
        schema:
          type: string
        description: 'Export scope: filtered (default), all, current_page, selected'
        example: filtered
      - name: ids
        in: query
        schema:
          type: string
        description: Comma-separated PO IDs (required when scope=selected)
      - name: columns
        in: query
        schema:
          type: string
        description: 'Comma-separated column keys to export. Available: id, purchase_order_number,
          purchase_order_date, supplier_name, destination_warehouse_name, order_status,
          submission_status, receipt_status, shipment_status, invoice_status, estimated_delivery_date,
          tracking_number, total_quantity, product_total, additional_cost, tax_total,
          discount, total, currency_code, payment_term_name, incoterm_description,
          supplier_notes, tags, invoices, is_dropship, po_type, other_date, fully_received_at,
          asn_last_sent_at, created_at, updated_at, submission_format, is_tax_included,
          currency_rate, requested_shipping_method_name, supplier_email, supplier_po_email,
          supplier_company, supplier_contact, supplier_phone, supplier_address, supplier_city,
          supplier_province, supplier_country, destination_email, destination_company,
          destination_address, destination_city, destination_province, destination_country.
          Also accepts logistics tracking columns: `logistics_<slug>`_estimate and
          `logistics_<slug>`_actual for any active LogisticsTrackingField (e.g. logistics_port-arrived_estimate,
          logistics_customs-cleared_actual).'
        example: id,purchase_order_number,supplier_name,order_status
      - name: sort
        in: query
        schema:
          type: string
        description: Sort field (same as list endpoint)
        example: -created_at
      - name: filter[order_status][is]
        in: query
        schema:
          type: string
        description: Filters carry over from list endpoint
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
          content:
            text/plain:
              schema:
                type: string
                example: (Binary XLSX file)
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: purchase-orders:read
      operationId: get-api-purchase-orders-list-export
  /api/purchase-orders/csv-columns:
    get:
      tags:
      - Purchase Orders
      summary: List Export Columns
      description: 'Returns the master registry of supported PO email CSV columns
        and the tenant-wide default selection. Used by the per-supplier CSV column
        picker, the supplier preferences panel, and the PO settings page.


        :::info[Required scope: `purchase-orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        The registry is **append-only and position-stable** — column ordering and
        keys are part of a public contract that supplier intake pipelines rely on.
        Removing or renaming a key is a breaking change.


        Response fields:

        - `data.columns[]` — array of `{ key, label }` in canonical order

        - `data.tenant_default` — array of column keys representing the tenant-wide
        default, or `null` if no override is set (means: use system default = every
        column)


        Authentication: Requires Bearer token. Scope: `purchase-orders:rw`.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      columns:
                        type: array
                        items:
                          type: object
                          properties:
                            key:
                              type: string
                            label:
                              type: string
                      tenant_default:
                        type: string
                        nullable: true
                example:
                  data:
                    columns:
                    - key: purchase_order
                      label: Purchase Order
                    - key: sku
                      label: SKU
                    - key: barcode
                      label: Barcode
                    - key: supplier_sku
                      label: Supplier SKU
                    - key: name
                      label: Name
                    - key: qty_ordered
                      label: Qty Ordered
                    - key: unit_cost
                      label: Unit Cost
                    - key: extended_cost
                      label: Extended Cost
                    tenant_default: null
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: purchase-orders:read
      operationId: get-api-purchase-orders-csv-columns
  /api/purchase-orders/{purchase_order}:
    get:
      tags:
      - Purchase Orders
      summary: Get Purchase Order
      description: 'Get a single purchase order with all relations loaded: lines,
        products, inventory, shipments, receipts, invoices, bills, notes, financial
        lines, Amazon inbound data, and more.


        :::info[Required scope: `purchase-orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: purchase_order
        in: path
        schema:
          type: integer
        required: true
        description: Purchase order ID
        example: '101'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      po_number:
                        type: string
                      purchase_order_date:
                        type: string
                      other_date:
                        type: string
                        nullable: true
                      payment_term_id:
                        type: integer
                      payment_term:
                        type: string
                      incoterm_id:
                        type: integer
                      incoterm_place:
                        type: string
                      incoterm_version:
                        type: integer
                      incoterm_code:
                        type: string
                      incoterm_display:
                        type: string
                      importer_of_record:
                        type: string
                      seller_must_insure:
                        type: boolean
                      incoterm_description:
                        type: string
                      incoterm:
                        type: object
                        properties:
                          id:
                            type: integer
                          code:
                            type: string
                          name:
                            type: string
                          transport_mode:
                            type: string
                          family:
                            type: string
                          seller_pays_main_carriage:
                            type: boolean
                          export_cleared_by:
                            type: string
                          import_cleared_by:
                            type: string
                          seller_insurance:
                            type: string
                          risk_transfer_point:
                            type: string
                          is_standard:
                            type: boolean
                          is_deprecated:
                            type: boolean
                          sort_order:
                            type: integer
                      submission_format:
                        type: string
                      currency_id:
                        type: integer
                      currency:
                        type: string
                      currency_rate:
                        type: number
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      created_by:
                        type: string
                      last_updated_by:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                      is_dropship:
                        type: boolean
                      is_supplier_pickup:
                        type: boolean
                      expected_pickup_at:
                        type: string
                        nullable: true
                      tracking_number:
                        type: string
                        nullable: true
                      supplier_id:
                        type: integer
                      supplier_name:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      supplier_email:
                        type: string
                      destination_warehouse_id:
                        type: integer
                      destination_warehouse_type:
                        type: string
                      order_status:
                        type: string
                      submission_status:
                        type: string
                      submission_blocked_no_email:
                        type: boolean
                      receipt_status:
                        type: string
                      resolution:
                        type: object
                        properties:
                          type:
                            type: string
                          label:
                            type: string
                          quantity:
                            type: integer
                          cost_impact:
                            type: number
                          date:
                            type: string
                          reference:
                            type: string
                            nullable: true
                      needs_shortfall_reconciliation:
                        type: boolean
                      shipment_status:
                        type: string
                      invoice_status:
                        type: string
                      additional_cost:
                        type: integer
                      discount:
                        type: integer
                      product_total:
                        type: number
                      total:
                        type: number
                      subtotal:
                        type: number
                      tax_cost:
                        type: integer
                      is_tax_included:
                        type: boolean
                      total_quantity:
                        type: integer
                      supplier_notes:
                        type: string
                        nullable: true
                      estimated_delivery_date:
                        type: string
                      fully_received_at:
                        type: string
                        nullable: true
                      tags:
                        type: array
                        items:
                          type: string
                      store_id:
                        type: integer
                      items:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            product_id:
                              type: integer
                            description:
                              type: string
                            quantity:
                              type: integer
                            amount:
                              type: number
                            received_quantity:
                              type: integer
                      summary_info:
                        type: object
                        properties:
                          total_lines:
                            type: integer
                          total_product_lines:
                            type: integer
                          total_units:
                            type: integer
                          total_quantity_pending_receipt:
                            type: integer
                      financial_lines:
                        type: array
                      bills:
                        type: array
                      invoices:
                        type: array
                      amazon_pending_inbound:
                        type: string
                        nullable: true
                      has_active_allocations:
                        type: boolean
                      walmart_wfs_inbound_shipment:
                        type: string
                        nullable: true
                      settlement_summary:
                        type: object
                        properties:
                          total_product_lines:
                            type: integer
                          matched:
                            type: integer
                          credited:
                            type: integer
                          settled:
                            type: integer
                          outstanding:
                            type: integer
                          outstanding_quantity:
                            type: number
                          credited_quantity:
                            type: number
                          credit_sources:
                            type: array
                            items:
                              type: object
                              properties:
                                vendor_credit_id:
                                  type: integer
                                vendor_credit_number:
                                  type: string
                                quantity:
                                  type: number
                                credit_status:
                                  type: string
                                restock_inventory:
                                  type: boolean
                      is_outsourced_manufacturing:
                        type: boolean
                      manufacturing_order_id:
                        type: string
                        nullable: true
                example:
                  data:
                    id: 101
                    po_number: PO-00101
                    purchase_order_date: '2024-01-15'
                    other_date: null
                    payment_term_id: 1
                    payment_term: Net 30
                    incoterm_id: 4
                    incoterm_place: Shenzhen Port
                    incoterm_version: 2020
                    incoterm_code: FOB
                    incoterm_display: FOB Shenzhen Port, Incoterms 2020
                    importer_of_record: Buyer
                    seller_must_insure: false
                    incoterm_description: Sea and inland-waterway transport only.
                      The seller clears the goods for export and loads them onto the
                      vessel; risk passes once they are on board.
                    incoterm:
                      id: 4
                      code: FOB
                      name: Free On Board
                      transport_mode: sea_inland
                      family: F
                      seller_pays_main_carriage: false
                      export_cleared_by: seller
                      import_cleared_by: buyer
                      seller_insurance: none
                      risk_transfer_point: Goods on board the vessel at the named
                        port of shipment.
                      is_standard: true
                      is_deprecated: false
                      sort_order: 4
                    submission_format: email
                    currency_id: 1
                    currency: USD
                    currency_rate: 1.0
                    created_at: '2024-01-15T10:00:00Z'
                    updated_at: '2024-01-15T10:00:00Z'
                    created_by: John Doe
                    last_updated_by: Jane Smith
                    archived_at: null
                    is_dropship: false
                    is_supplier_pickup: false
                    expected_pickup_at: null
                    tracking_number: null
                    supplier_id: 5
                    supplier_name:
                      id: 5
                      name: Acme Supplies
                    supplier_email: orders@acme.com
                    destination_warehouse_id: 2
                    destination_warehouse_type: standard
                    order_status: open
                    submission_status: sent
                    submission_blocked_no_email: false
                    receipt_status: unreceived
                    resolution:
                      type: inbound_shortage
                      label: Inbound Shortage
                      quantity: 16
                      cost_impact: 1002.94
                      date: '2025-12-17'
                      reference: null
                    needs_shortfall_reconciliation: false
                    shipment_status: pending
                    invoice_status: uninvoiced
                    additional_cost: 0
                    discount: 0
                    product_total: 1500.0
                    total: 1500.0
                    subtotal: 1500.0
                    tax_cost: 0
                    is_tax_included: false
                    total_quantity: 100
                    supplier_notes: null
                    estimated_delivery_date: '2024-02-01'
                    fully_received_at: null
                    tags:
                    - urgent
                    store_id: 1
                    items:
                    - id: 201
                      product_id: 10
                      description: Widget A
                      quantity: 100
                      amount: 15.0
                      received_quantity: 0
                    summary_info:
                      total_lines: 1
                      total_product_lines: 1
                      total_units: 100
                      total_quantity_pending_receipt: 100
                    financial_lines: []
                    bills: []
                    invoices: []
                    amazon_pending_inbound: null
                    has_active_allocations: false
                    walmart_wfs_inbound_shipment: null
                    settlement_summary:
                      total_product_lines: 3
                      matched: 1
                      credited: 1
                      settled: 1
                      outstanding: 0
                      outstanding_quantity: 0.0
                      credited_quantity: 5.0
                      credit_sources:
                      - vendor_credit_id: 42
                        vendor_credit_number: VC-1001
                        quantity: 5.0
                        credit_status: open
                        restock_inventory: false
                    is_outsourced_manufacturing: false
                    manufacturing_order_id: null
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  settlement_summary:
                    type: object
                    properties:
                      total_product_lines:
                        type: integer
                      matched:
                        type: integer
                      credited:
                        type: integer
                      settled:
                        type: integer
                      outstanding:
                        type: integer
                      outstanding_quantity:
                        type: number
                      credited_quantity:
                        type: number
                      credit_sources:
                        type: array
                        items:
                          type: object
                          properties:
                            vendor_credit_id:
                              type: integer
                            vendor_credit_number:
                              type: string
                            quantity:
                              type: number
                            credit_status:
                              type: string
                            restock_inventory:
                              type: boolean
                example:
                  message: No query results for model [App\Models\PurchaseOrder] 999
                  settlement_summary:
                    total_product_lines: 3
                    matched: 1
                    credited: 1
                    settled: 1
                    outstanding: 0
                    outstanding_quantity: 0.0
                    credited_quantity: 5.0
                    credit_sources:
                    - vendor_credit_id: 42
                      vendor_credit_number: VC-1001
                      quantity: 5.0
                      credit_status: open
                      restock_inventory: false
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: purchase-orders:read
      operationId: get-api-purchase-orders-purchase-order
    put:
      tags:
      - Purchase Orders
      summary: Update Purchase Order
      description: 'Update an existing purchase order. All fields are optional (sometimes).


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Note: Updates acquire a Redis lock to serialize concurrent edits to the same
        PO. The request blocks for up to 10 seconds waiting for the lock; if the lock
        still cannot be acquired it returns 409 Conflict.


        Update-only fields:

        - po_number: alias for purchase_order_number

        - purchase_order_lines[].id: ID of existing line to update (omit line from
        array to delete it)

        - financial_lines[].id: ID of existing financial line to update


        Cannot reduce line quantity below received or invoiced quantity.


        **Requires permission:** `purchase_orders.update`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                purchase_order_date:
                  type: string
                estimated_delivery_date:
                  type: string
                supplier_notes:
                  type: string
                tracking_number:
                  type: string
                approval_status:
                  type: string
                tags:
                  type: array
                  items:
                    type: string
                purchase_order_lines:
                  type: array
                  items:
                    type: object
                    properties:
                      id:
                        type: integer
                      product_id:
                        type: integer
                      quantity:
                        type: integer
                      amount:
                        type: number
                incoterm_id:
                  type: integer
                incoterm_place:
                  type: string
                incoterm_version:
                  type: integer
              example:
                purchase_order_date: '2024-01-15'
                estimated_delivery_date: '2024-02-15'
                supplier_notes: Updated notes
                tracking_number: TRACK123
                approval_status: approved
                tags:
                - urgent
                - priority
                purchase_order_lines:
                - id: 201
                  product_id: 10
                  quantity: 120
                  amount: 14.5
                incoterm_id: 12
                incoterm_place: Port of Los Angeles, CA
                incoterm_version: 2020
      parameters:
      - name: purchase_order
        in: path
        schema:
          type: integer
        required: true
        description: Purchase order ID
        example: '101'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      po_number:
                        type: string
                      order_status:
                        type: string
                      total:
                        type: number
                  message:
                    type: string
                example:
                  data:
                    id: 101
                    po_number: PO-00101
                    order_status: open
                    total: 1740.0
                  message: Purchase order PO-00101 updated successfully
        '409':
          description: Conflict
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Your previous change is still saving — please try again
                    in a moment.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: purchase-orders:write
      operationId: put-api-purchase-orders-purchase-order
    delete:
      tags:
      - Purchase Orders
      summary: Delete Purchase Order
      description: 'Delete a single purchase order. Fails with 400 if the PO has invoices
        (delete the invoices first) or has received inventory that has been used in
        FIFO layers.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `purchase_orders.delete`'
      parameters:
      - name: purchase_order
        in: path
        schema:
          type: integer
        required: true
        description: Purchase order ID
        example: '101'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Purchase order PO-00101 deleted successfully
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 400 Bad Request - Cannot Delete
                  value:
                    message: This purchase order cannot be deleted because it is received
                      and the receipts were used.
                example-1:
                  summary: 400 Bad Request - Has Invoices
                  value:
                    message: Cannot delete purchase order PO-22829 because it has
                      invoices. Please delete the invoices first.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:write
      operationId: delete-api-purchase-orders-purchase-order
  /api/purchase-orders/approve:
    post:
      tags:
      - Purchase Orders
      summary: Bulk Approve Purchase Orders
      description: 'Bulk approve purchase orders by IDs or filters.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Returns warnings if some POs fail to approve, error if all fail.


        Body:

        - ids[]: Array of purchase order IDs (required without filters)

        - filters: Spatie filter params to resolve IDs (required without ids)


        **Requires permission:** `purchase_orders.approve`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 101
                - 102
                - 103
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: array
                      items:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                  - - 101
                    - 102
                    - 103
                  message: Purchase orders approved successfully
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  warnings:
                    type: object
                    properties:
                      PO-00103:
                        type: string
                example:
                  message: 2 of 3 purchase orders approved successfully
                  warnings:
                    PO-00103: Could not approve — no supplier default warehouse
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: purchase-orders:write
      operationId: post-api-purchase-orders-approve
  /api/purchase-orders/submit:
    post:
      tags:
      - Purchase Orders
      summary: Bulk Submit Purchase Orders
      description: 'Bulk submit (send to supplier) purchase orders.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Body:

        - ids[]: Array of purchase order IDs (required without filters)

        - filters: Spatie filter params (required without ids)


        **Requires permission:** `purchase_orders.approve`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 101
                - 102
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Purchase orders submitted successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: purchase-orders:write
      operationId: post-api-purchase-orders-submit
  /api/purchase-orders/archive:
    put:
      tags:
      - Purchase Orders
      summary: Bulk Archive Purchase Orders
      description: 'Bulk archive purchase orders.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `purchase_orders.update`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 101
                - 102
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Purchase orders archived successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: purchase-orders:write
      operationId: put-api-purchase-orders-archive
  /api/purchase-orders/unarchive:
    put:
      tags:
      - Purchase Orders
      summary: Bulk Unarchive Purchase Orders
      description: 'Bulk unarchive purchase orders.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `purchase_orders.update`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 101
                - 102
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Purchase orders unarchived successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: purchase-orders:write
      operationId: put-api-purchase-orders-unarchive
  /api/purchase-orders/deletable:
    post:
      tags:
      - Purchase Orders
      summary: Check Purchase Orders Deletable
      description: 'Check whether each purchase order can be deleted. Returns a list
        with deletable flag and reason if not.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Body:

        - ids[]: Required array of integer purchase order IDs (min:1, each must exist)


        **Requires permission:** `purchase_orders.delete`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 101
                - 102
                - 103
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        purchase_order_number:
                          type: string
                        deletable:
                          type: boolean
                        reason:
                          type: string
                          nullable: true
                example:
                  data:
                  - id: 101
                    purchase_order_number: PO-00101
                    deletable: true
                    reason: null
                  - id: 102
                    purchase_order_number: PO-00102
                    deletable: false
                    reason:
                      usedFifoLayers: Purchase order PO-00102 has used FIFO layers
                        in its lines and cannot be deleted.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: purchase-orders:write
      operationId: post-api-purchase-orders-deletable
  /api/purchase-orders/{purchase_order}/submit:
    put:
      tags:
      - Purchase Orders
      summary: Submit PO to Supplier
      description: 'Submit (send) a draft purchase order to the supplier. Triggers
        PO sent notification.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `purchase_orders.approve` Optionally include supplier_message
        to set the vendor-facing note (saved before the PO is emailed); omit it to
        keep the saved message, or send an empty string to clear it.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                supplier_message:
                  type: string
              example:
                supplier_message: Please ship in original cartons.
      parameters:
      - name: purchase_order
        in: path
        schema:
          type: integer
        required: true
        example: '101'
        description: The purchase order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      submission_status:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 101
                    submission_status: sent
                  message: Purchase order PO-00101 submitted to supplier
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: purchase-orders:write
      operationId: put-api-purchase-orders-purchase-order-submit
  /api/purchase-orders/{purchase_order}/close:
    put:
      tags:
      - Purchase Orders
      summary: Close Purchase Order
      description: 'Manually close an open purchase order.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Body:

        - reason (optional, string, max:500): Reason for closing


        **Requires permission:** `purchase_orders.cancel`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                reason:
                  type: string
              example:
                reason: Fulfilled by alternate means
      parameters:
      - name: purchase_order
        in: path
        schema:
          type: integer
        required: true
        example: '101'
        description: The purchase order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      order_status:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 101
                    order_status: closed
                  message: Purchase order closed.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: purchase-orders:write
      operationId: put-api-purchase-orders-purchase-order-close
  /api/purchase-orders/{purchase_order}/reopen:
    put:
      tags:
      - Purchase Orders
      summary: Reopen Purchase Order
      description: 'Reopen a closed purchase order.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `purchase_orders.cancel`'
      requestBody:
        content: {}
      parameters:
      - name: purchase_order
        in: path
        schema:
          type: integer
        required: true
        example: '101'
        description: The purchase order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      order_status:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 101
                    order_status: open
                  message: Purchase order reopened.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: purchase-orders:write
      operationId: put-api-purchase-orders-purchase-order-reopen
  /api/purchase-orders/{purchase_order}/duplicate:
    post:
      tags:
      - Purchase Orders
      summary: Duplicate Purchase Order
      description: 'Duplicate a purchase order (creates a new draft with the same
        lines).


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `purchase_orders.create`'
      requestBody:
        content: {}
      parameters:
      - name: purchase_order
        in: path
        schema:
          type: integer
        required: true
        example: '101'
        description: The purchase order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      po_number:
                        type: string
                      order_status:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 200
                    po_number: PO-00200
                    order_status: draft
                  message: Purchase order duplicated successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: purchase-orders:write
      operationId: post-api-purchase-orders-purchase-order-duplicate
  /api/purchase-orders/{purchase_order}/cover-backorders:
    post:
      tags:
      - Purchase Orders
      summary: Cover Backorders
      description: 'Sync inventory allocation coverages for all lines in this purchase
        order.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `purchase_orders.update`'
      requestBody:
        content: {}
      parameters:
      - name: purchase_order
        in: path
        schema:
          type: integer
        required: true
        example: '101'
        description: The purchase order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Successfully updated backorder coverage
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: purchase-orders:write
      operationId: post-api-purchase-orders-purchase-order-cover-backorders
  /api/purchase-orders/{purchase_order}/generate-accounting-transaction:
    post:
      tags:
      - Purchase Orders
      summary: Generate Accounting Transaction
      description: 'Generate (or regenerate) the accounting transaction for a purchase
        order.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `purchase_orders.update`'
      requestBody:
        content: {}
      parameters:
      - name: purchase_order
        in: path
        schema:
          type: integer
        required: true
        example: '101'
        description: The purchase order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      status:
                        type: string
                      total:
                        type: number
                      reference:
                        type: string
                      transaction_date:
                        type: string
                      type:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 500
                    status: draft
                    total: 1500.0
                    reference: PO-00101
                    transaction_date: '2024-01-15T00:00:00Z'
                    type: purchase_order
                  message: Accounting transaction generated successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: purchase-orders:write
      operationId: post-api-purchase-orders-purchase-order-generate-accounting-transaction
  /api/purchase-orders/{purchase_order}/receiving-discrepancy:
    post:
      tags:
      - Purchase Orders
      summary: Create Receiving Discrepancy
      description: 'Create an accounting transaction for the receiving discrepancy
        on this purchase order.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Fails if nominal code mapping is missing or a discrepancy already exists.


        **Requires permission:** `purchase_orders.receive`'
      requestBody:
        content: {}
      parameters:
      - name: purchase_order
        in: path
        schema:
          type: integer
        required: true
        example: '101'
        description: The purchase order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Successfully closed with receiving discrepancy
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: array
                    items:
                      type: object
                      properties:
                        message:
                          type: string
                        code:
                          type: string
                        key:
                          type: string
                example:
                  errors:
                  - message: Missing nominal code mapping for receiving discrepancy
                    code: ReceivingDiscrepancyMissingNominalCodeMapping
                    key: nominal_code_id
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: purchase-orders:write
      operationId: post-api-purchase-orders-purchase-order-receiving-discrepancy
  /api/purchase-orders/{purchase_order}/receiving-discrepancy/undo:
    post:
      tags:
      - Purchase Orders
      summary: Undo Receiving Discrepancy
      description: 'Reverse a previous "close with receiving discrepancy" on a purchase
        order. No request body.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        What it does (all in one transaction, synchronous):

        - deletes the discrepancy accounting entry and its lines

        - reopens the purchase order (`order_status: open`) and recomputes its receipt
        status from actual received quantities (it may land on `partially_received`,
        `unreceived`, or auto-close again as `received` if everything was in fact
        received)


        Errors:

        - 404 — the purchase order has no receiving discrepancy to undo

        - 400 — the discrepancy has already been posted to your accounting provider;
        it cannot be undone and a reversing entry must be made manually


        Requires the `purchase-orders:write` token scope and receiving permission
        on purchase orders.'
      requestBody:
        content: {}
      parameters:
      - name: purchase_order
        in: path
        schema:
          type: integer
        required: true
        description: Purchase order ID
        example: '812'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  status:
                    type: string
                example:
                  message: Successfully undone close with receiving discrepancy
                  status: success
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: object
                    properties:
                      purchase_order_id:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: array
                  message:
                    type: string
                  status:
                    type: string
                example:
                  errors:
                    purchase_order_id:
                    - message: The receiving discrepancy has already been posted to
                        accounting and cannot be undone. A reversing entry must be
                        created manually.
                      code: ReceivingDiscrepancyAlreadyPosted
                      data: []
                  message: The receiving discrepancy has already been posted to accounting
                    and cannot be undone. A reversing entry must be created manually.
                  status: failure
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: object
                    properties:
                      purchase_order_id:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: array
                  message:
                    type: string
                  status:
                    type: string
                example:
                  errors:
                    purchase_order_id:
                    - message: No receiving discrepancy exists for purchase order
                        PO-00812
                      code: ReceivingDiscrepancyNotFound
                      data: []
                  message: No receiving discrepancy exists for purchase order PO-00812
                  status: failure
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: purchase-orders:write
      operationId: post-api-purchase-orders-purchase-order-receiving-discrepancy-undo
  /api/purchase-orders/{purchase_order}/opening-balance:
    post:
      tags:
      - Purchase Orders
      summary: Mark as Opening-Balance Purchase Order
      description: 'Mark a purchase order as an opening-balance ("transition") order.
        Use this for a purchase order whose stock was received before your inventory
        start date, so it was loaded as an opening balance rather than as tracked
        receipts. No request body.


        What it does (synchronous):

        - closes the purchase order as fully received with no receiving loss, regardless
        of how many units the tracked ledger shows

        - stops its receipt status from later recomputing back to partially/unreceived
        off the (empty) ledger

        - its pre-inventory-start invoices are treated as opening balances and are
        not posted to your accounting provider (posting them would double-count the
        balances loaded at go-live)


        Requires the `purchase-orders:write` token scope and receiving permission
        on purchase orders.'
      requestBody:
        content: {}
      parameters:
      - name: purchase_order
        in: path
        schema:
          type: integer
        required: true
        description: Purchase order ID
        example: '682'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  status:
                    type: string
                example:
                  message: Marked as an opening-balance purchase order
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-purchase-orders-purchase-order-opening-balance
    delete:
      tags:
      - Purchase Orders
      summary: Remove Opening-Balance Mark
      description: 'Remove the opening-balance mark from a purchase order and reopen
        it so its receipt status recomputes normally from actual received quantities.
        No request body.


        Requires the `purchase-orders:write` token scope and receiving permission
        on purchase orders.'
      parameters:
      - name: purchase_order
        in: path
        schema:
          type: integer
        required: true
        description: Purchase order ID
        example: '682'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  status:
                    type: string
                example:
                  message: Removed the opening-balance mark
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-purchase-orders-purchase-order-opening-balance
  /api/purchase-orders/{purchase_order}/lines:
    get:
      tags:
      - Purchase Orders
      summary: Get PO Lines
      description: 'Purchase order lines for the PO grid (POGridView), plus the vendor-credit
        / lookup callers that pass limit=-1 to fetch every line. Includes per-line
        COGS breakdown data.


        :::info[Required scope: `purchase-orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Canonical params (the legacy table_specifications flag has been removed):

        - query — search across line description, product SKU, product barcode

        - filter[receipt_status] — fully_received / partially_received / not_received
        / not_fully_received

        - filter[shipment_status] — fully_shipped / partially_shipped / not_shipped

        - page / limit / total — pagination (limit=-1 returns ALL rows, un-paginated;
        the response is then a plain resource collection without pagination meta)


        Authentication: Requires Bearer token.'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        description: Page number
        example: '1'
      - name: limit
        in: query
        schema:
          type: integer
        description: Items per page (default 10). -1 returns ALL lines un-paginated
          (vendor-credit / lookup callers)
        example: '10'
      - name: purchase_order
        in: path
        schema:
          type: integer
        required: true
        description: Purchase order ID
        example: '101'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        quantity:
                          type: integer
                        sku:
                          type: object
                          properties:
                            id:
                              type: integer
                            sku:
                              type: string
                        barcode:
                          type: string
                        name:
                          type: string
                        price:
                          type: number
                        received:
                          type: integer
                        shipped_quantity:
                          type: integer
                        invoiced_quantity:
                          type: integer
                        unfulfilled_quantity:
                          type: integer
                  links:
                    type: object
                    properties:
                      first:
                        type: string
                      last:
                        type: string
                        nullable: true
                      prev:
                        type: string
                        nullable: true
                      next:
                        type: string
                  meta:
                    type: object
                    properties:
                      current_page:
                        type: integer
                      from:
                        type: integer
                      path:
                        type: string
                      per_page:
                        type: integer
                      to:
                        type: integer
                  status:
                    type: string
                example:
                  data:
                  - id: 201
                    quantity: 100
                    sku:
                      id: 10
                      sku: SKU-001
                    barcode: 0123456789012
                    name: Widget A
                    price: 15.0
                    received: 25
                    shipped_quantity: 25
                    invoiced_quantity: 0
                    unfulfilled_quantity: 75
                  links:
                    first: https://example.sku.io/api/purchase-orders/101/lines?page=1
                    last: null
                    prev: null
                    next: https://example.sku.io/api/purchase-orders/101/lines?page=2
                  meta:
                    current_page: 1
                    from: 1
                    path: https://example.sku.io/api/purchase-orders/101/lines
                    per_page: 10
                    to: 10
                  status: Success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:read
      operationId: get-api-purchase-orders-purchase-order-lines
  /api/purchase-orders/{purchase_order}/lines-for-invoice:
    get:
      tags:
      - Purchase Orders
      summary: Get PO Lines for Invoice
      description: 'Get purchase order lines optimised for invoice creation. Returns
        only essential invoice-relevant fields with minimal N+1 overhead.


        :::info[Required scope: `purchase-orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: purchase_order
        in: path
        schema:
          type: integer
        required: true
        example: '101'
        description: The purchase order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        product_id:
                          type: integer
                        description:
                          type: string
                        quantity:
                          type: integer
                        received_quantity:
                          type: integer
                        amount:
                          type: number
                        discount_rate:
                          type: integer
                example:
                  data:
                  - id: 201
                    product_id: 10
                    description: Widget A
                    quantity: 100
                    received_quantity: 0
                    amount: 15.0
                    discount_rate: 0
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:read
      operationId: get-api-purchase-orders-purchase-order-lines-for-invoice
  /api/purchase-orders/{purchase_order}/lines-for-receiving:
    get:
      tags:
      - Purchase Orders
      summary: Get PO Lines for Receiving
      description: 'Lean endpoint for the Receive drawer. Returns only the 8 fields
        the UI consumes (id, sku, name, barcode, img_url, quantity, received) — no
        COGS, no allocations, no inventory snapshots, no resource transformation.


        :::info[Required scope: `purchase-orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        For POs with ~1000 lines this is ~9× faster than `/lines` (~100ms vs ~900ms)
        and returns ~5× smaller payloads.


        Authentication: Requires Bearer token.'
      parameters:
      - name: purchase_order
        in: path
        schema:
          type: integer
        required: true
        example: '101'
        description: The purchase order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        sku:
                          type: object
                          properties:
                            id:
                              type: integer
                            sku:
                              type: string
                        name:
                          type: string
                        barcode:
                          type: string
                        img_url:
                          type: string
                        quantity:
                          type: integer
                        received:
                          type: integer
                example:
                  data:
                  - id: 201
                    sku:
                      id: 10
                      sku: WIDGET-A
                    name: Widget A
                    barcode: 0123456789012
                    img_url: https://cdn.sku.io/products/10/primary.jpg
                    quantity: 100
                    received: 0
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:read
      operationId: get-api-purchase-orders-purchase-order-lines-for-receiving
  /api/purchase-orders/{purchase_order}/shipment-line-options:
    get:
      tags:
      - Purchase Orders
      summary: Get PO Shipment Line Options
      description: 'Lines for the Create Shipment / Add to Existing Shipment pickers
        on the PO Shipments tab.


        :::info[Required scope: `purchase-orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Returns every unreceived line on the PO with server-computed `assigned_quantity`
        (units already claimed by live inbound shipments — InTransit, PartiallyReceived,
        Received) and `available_quantity` (what the user can still add). Draft, Cancelled,
        and Closed shipments do NOT count toward `assigned_quantity`.


        Fully-received lines (effective_received >= quantity) are excluded. AWD /
        FBA receipts are honoured via `getEffectiveReceivedQuantity` so received quantity
        is correct even when the `received_quantity` column is not directly updated.


        There is intentionally no pagination cap — a single PO can have hundreds of
        lines and silent truncation hid line items from users (Freshdesk #1892).


        Authentication: Requires Bearer token.'
      parameters:
      - name: purchase_order
        in: path
        schema:
          type: integer
        required: true
        example: '101'
        description: The purchase order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        purchase_order_line_id:
                          type: integer
                        product_id:
                          type: integer
                        sku:
                          type: string
                        product_name:
                          type: string
                        img_url:
                          type: string
                        ordered_quantity:
                          type: integer
                        received_quantity:
                          type: integer
                        unreceived_quantity:
                          type: integer
                        assigned_quantity:
                          type: integer
                        available_quantity:
                          type: integer
                        already_on_shipment:
                          type: boolean
                example:
                  data:
                  - purchase_order_line_id: 201
                    product_id: 10
                    sku: WIDGET-A
                    product_name: Widget A
                    img_url: https://cdn.sku.io/products/10/primary.jpg
                    ordered_quantity: 100
                    received_quantity: 0
                    unreceived_quantity: 100
                    assigned_quantity: 40
                    available_quantity: 60
                    already_on_shipment: true
                  - purchase_order_line_id: 202
                    product_id: 11
                    sku: WIDGET-B
                    product_name: Widget B
                    img_url: null
                    ordered_quantity: 50
                    received_quantity: 0
                    unreceived_quantity: 50
                    assigned_quantity: 0
                    available_quantity: 50
                    already_on_shipment: false
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:read
      operationId: get-api-purchase-orders-purchase-order-shipment-line-options
  /api/purchase-orders/{purchase_order}/line-items:
    get:
      tags:
      - Purchase Orders
      summary: Get PO Line Items (Lightweight)
      description: 'Lightweight line items for the expandable row in the list view.
        Returns id, product SKU, barcode, product_name, quantity, received_quantity,
        amount, discount_rate, and line_total.


        :::info[Required scope: `purchase-orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: purchase_order
        in: path
        schema:
          type: integer
        required: true
        example: '101'
        description: The purchase order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        sku:
                          type: string
                        barcode:
                          type: string
                        product_name:
                          type: string
                        product_id:
                          type: integer
                        quantity:
                          type: integer
                        received_quantity:
                          type: integer
                        amount:
                          type: number
                        discount_rate:
                          type: integer
                        line_total:
                          type: number
                example:
                  data:
                  - id: 201
                    sku: SKU-001
                    barcode: 0123456789012
                    product_name: Widget A
                    product_id: 10
                    quantity: 100
                    received_quantity: 0
                    amount: 15.0
                    discount_rate: 0
                    line_total: 1500.0
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:read
      operationId: get-api-purchase-orders-purchase-order-line-items
  /api/purchase-orders/import-lines:
    post:
      tags:
      - Purchase Orders
      summary: Import Lines from CSV
      description: 'Import purchase order line items from a CSV file. CSV must have
        a ''sku'' column. Optional columns: quantity, unit_cost, description, discount_rate,
        tax_rate_id, pricing_tier, barcode.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        If purchase_order_id is provided, lines are added/merged into that PO.

        If only supplier_id is provided, returns parsed line resources without saving.


        **Requires permission:** `purchase_orders.import`'
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                file:
                  type: string
                  description: CSV file (required without csvString)
                  format: binary
                csvString:
                  type: string
                  description: CSV content as string (required without file)
                purchase_order_id:
                  type: integer
                  description: Target PO ID (required without supplier_id)
                  example: '101'
                supplier_id:
                  type: string
                  description: Supplier ID for new lines without a PO (required without
                    purchase_order_id)
                replace:
                  type: boolean
                  description: If true, replaces all existing lines; if false (default),
                    merges/adds
                  example: 'false'
                separator:
                  type: string
                  description: 'CSV column separator (default: comma)'
                  example: ','
                escape:
                  type: string
                  description: 'CSV escape character (default: double-quote)'
                  example: '"'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Purchase order lines imported successfully
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Product not found for UNKNOWN-SKU
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: purchase-orders:write
      operationId: post-api-purchase-orders-import-lines
  /api/purchase-orders/import-lines/template:
    get:
      tags:
      - Purchase Orders
      summary: Download Lines Import Template
      description: 'Download an XLSX import template for PO line items with headers
        (sku, quantity, unit_cost) and sample data.


        :::info[Required scope: `purchase-orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Response: Binary XLSX file download.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
          content:
            text/plain:
              schema:
                type: string
                example: (Binary XLSX file)
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: purchase-orders:read
      operationId: get-api-purchase-orders-import-lines-template
  /api/purchase-orders/{purchaseOrder}/apply-discount-rate:
    post:
      tags:
      - Purchase Orders
      summary: Apply Discount Rate to Lines
      description: 'Apply a discount rate to all lines of a purchase order.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Body:

        - discount (required, numeric, min:0, max:100): Discount percentage (e.g.
        10 = 10%)


        **Requires permission:** `purchase_orders.update`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                discount:
                  type: integer
              example:
                discount: 10
      parameters:
      - name: purchaseOrder
        in: path
        schema:
          type: integer
        required: true
        example: '101'
        description: The purchase order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      po_number:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 101
                    po_number: PO-00101
                  message: Discount rate successfully applied.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: purchase-orders:write
      operationId: post-api-purchase-orders-purchaseorder-apply-discount-rate
  /api/purchase-orders/{purchaseOrder}/apply-pricing-tier/{supplierPricingTier}:
    post:
      tags:
      - Purchase Orders
      summary: Apply Pricing Tier to Lines
      description: 'Apply a supplier pricing tier to all (or specified) lines of a
        purchase order.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Body (optional):

        - line_ids[]: Array of specific line IDs to apply pricing to. If omitted,
        applies to all lines.


        **Requires permission:** `purchase_orders.update`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                line_ids:
                  type: array
                  items:
                    type: integer
              example:
                line_ids:
                - 201
                - 202
      parameters:
      - name: purchaseOrder
        in: path
        schema:
          type: integer
        required: true
        example: '101'
        description: The purchase order ID.
      - name: supplierPricingTier
        in: path
        schema:
          type: integer
        required: true
        example: '3'
        description: The supplier pricing tier ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    id: 101
                  message: Pricing tier successfully applied.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: purchase-orders:write
      operationId: post-api-purchase-orders-purchaseorder-apply-pricing-tier-supplierpricingtier
  /api/purchase-orders/{purchaseOrder}/apply-tax-rate/{taxRate}:
    post:
      tags:
      - Purchase Orders
      summary: Apply Tax Rate to Lines
      description: 'Apply a tax rate to all lines of a purchase order.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Body:

        - include_cost_lines (boolean, default false): Whether to also apply to non-product
        (cost) lines


        **Requires permission:** `purchase_orders.update`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                include_cost_lines:
                  type: boolean
              example:
                include_cost_lines: false
      parameters:
      - name: purchaseOrder
        in: path
        schema:
          type: integer
        required: true
        example: '101'
        description: The purchase order ID.
      - name: taxRate
        in: path
        schema:
          type: integer
        required: true
        example: '2'
        description: The tax rate ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    id: 101
                  message: Tax rate successfully applied to all lines.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: purchase-orders:write
      operationId: post-api-purchase-orders-purchaseorder-apply-tax-rate-taxrate
  /api/purchase-orders/{purchaseOrder}/clear-tax-rate:
    post:
      tags:
      - Purchase Orders
      summary: Clear Tax Rate from Lines
      description: 'Clear tax rates from all lines of a purchase order.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Body:

        - include_cost_lines (boolean, default false): Whether to also clear from
        non-product (cost) lines


        **Requires permission:** `purchase_orders.update`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                include_cost_lines:
                  type: boolean
              example:
                include_cost_lines: false
      parameters:
      - name: purchaseOrder
        in: path
        schema:
          type: integer
        required: true
        example: '101'
        description: The purchase order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    id: 101
                  message: Tax rates cleared from all lines.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: purchase-orders:write
      operationId: post-api-purchase-orders-purchaseorder-clear-tax-rate
  /api/purchase-order-lines/{purchase_order_line}:
    patch:
      tags:
      - Purchase Orders
      summary: Update PO Line
      description: 'Update a single purchase order line. Designed for the PO grid''s
        inline-edit interactions (tax rate, quantity, unit cost, discount, description,
        FOC toggle, nominal code).


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Concurrency: Shares the per-PO Redis lock used by `PATCH /api/purchase-orders/:purchase_order`
        so concurrent edits on the same purchase order serialize rather than collide.
        The endpoint will wait up to 10 seconds for the lock; if it cannot acquire
        it, returns 409.


        Request body (all fields optional — only sent fields are touched):

        - `quantity` (numeric, min 0, < 10000000): new ordered quantity. Validated
        against `received_quantity` and `invoice_total` — cannot drop below either.

        - `amount` (numeric, min 0, < 10000000): unit cost.

        - `description` (nullable string, max 255): free-text override for the product
        name on this line.

        - `tax_rate_id` (nullable integer, exists in `tax_rates`): set or clear the
        tax rate. When cleared, `tax_allocation` is reset to 0.

        - `discount` (nullable numeric, 0–100): percentage discount. Stored as `discount_rate`
        (e.g. 25 → 0.25).

        - `nominal_code_id` (nullable integer, exists in `nominal_codes`).

        - `is_free_of_charge` (boolean): toggle the FOC flag.

        - `free_of_charge_reason` (nullable enum, required when `is_free_of_charge=true`):
        one of the `FreeOfChargeReasonEnum` cases.


        Side effects:

        - Recomputes `tax_allocation` whenever the tax rate or any subtotal input
        (quantity/amount/discount) changes.

        - Recomputes the parent PO''s `total_cost` and `total_quantity`.

        - Refreshes the PO''s `receipt_status` when the quantity changes.

        - When the quantity is reduced, excess awaiting-receipt inventory allocations
        on this line are reverted so the next coverage sync can rebalance them.


        Returns the refreshed purchase order line object.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                quantity:
                  type: integer
                amount:
                  type: number
                description:
                  type: string
                tax_rate_id:
                  type: integer
                discount:
                  type: integer
                nominal_code_id:
                  type: integer
                is_free_of_charge:
                  type: boolean
                free_of_charge_reason:
                  type: string
                  nullable: true
              example:
                quantity: 12
                amount: 9.95
                description: Optional override of the line description
                tax_rate_id: 5
                discount: 10
                nominal_code_id: 42
                is_free_of_charge: false
                free_of_charge_reason: null
      parameters:
      - name: purchase_order_line
        in: path
        schema:
          type: integer
        required: true
        description: Purchase order line ID to update
        example: '101'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      quantity:
                        type: integer
                      sku:
                        type: object
                        properties:
                          id:
                            type: integer
                          sku:
                            type: string
                      barcode:
                        type: string
                      sales_channel_unique_id:
                        type: string
                        nullable: true
                      is_variation:
                        type: boolean
                      img_url:
                        type: string
                        nullable: true
                      supplier_sku:
                        type: string
                      supplier_product_id:
                        type: integer
                      price:
                        type: number
                      is_free_of_charge:
                        type: boolean
                      free_of_charge_reason:
                        type: string
                        nullable: true
                      free_of_charge_reason_label:
                        type: string
                        nullable: true
                      name:
                        type: string
                      nominal_code_id:
                        type: integer
                      nominal_code:
                        type: string
                      nominal_code_code:
                        type: string
                      received:
                        type: integer
                      effective_ordered:
                        type: integer
                      invoiced_quantity:
                        type: string
                        nullable: true
                      uninvoiced_quantity:
                        type: string
                        nullable: true
                      unfulfilled_quantity:
                        type: string
                        nullable: true
                      shipped_quantity:
                        type: string
                        nullable: true
                      weight:
                        type: number
                      weight_unit:
                        type: string
                      length:
                        type: string
                        nullable: true
                      width:
                        type: string
                        nullable: true
                      height:
                        type: string
                        nullable: true
                      dimension_unit:
                        type: string
                        nullable: true
                      tax_rate:
                        type: integer
                      tax_rate_id:
                        type: integer
                      tax_rate_name:
                        type: string
                      tax_allocation:
                        type: number
                      discount:
                        type: integer
                      discount_rate:
                        type: number
                      discount_amount:
                        type: number
                      discount_amount_extended:
                        type: number
                      item_tax_value:
                        type: number
                      line_total:
                        type: number
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 101
                    quantity: 12
                    sku:
                      id: 4421
                      sku: ACME-WIDGET-BLU
                    barcode: '5012345678900'
                    sales_channel_unique_id: null
                    is_variation: false
                    img_url: null
                    supplier_sku: SUP-WIDGET-001
                    supplier_product_id: 882
                    price: 9.95
                    is_free_of_charge: false
                    free_of_charge_reason: null
                    free_of_charge_reason_label: null
                    name: Acme Widget, Blue
                    nominal_code_id: 42
                    nominal_code: Cost of Goods Sold
                    nominal_code_code: '5000'
                    received: 0
                    effective_ordered: 12
                    invoiced_quantity: null
                    uninvoiced_quantity: null
                    unfulfilled_quantity: null
                    shipped_quantity: null
                    weight: 1.2
                    weight_unit: kg
                    length: null
                    width: null
                    height: null
                    dimension_unit: null
                    tax_rate: 20
                    tax_rate_id: 5
                    tax_rate_name: Standard 20%
                    tax_allocation: 21.49
                    discount: 10
                    discount_rate: 0.1
                    discount_amount: 0.995
                    discount_amount_extended: 11.94
                    item_tax_value: 21.49
                    line_total: 128.94
                    created_at: '2026-05-10T14:22:01.000000Z'
                    updated_at: '2026-05-21T09:31:44.000000Z'
        '409':
          description: Conflict
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Your previous change is still saving — please try again
                    in a moment.
        '422':
          description: Unprocessable Entity
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 422 Quantity Below Received
                  value:
                    message: Quantity (4) cannot be less than the already-received
                      quantity (6).
                example-1:
                  summary: 422 Validation Error
                  value:
                    message: Discount must be between 0 and 100.
                    errors:
                      discount:
                      - Discount must be between 0 and 100.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:write
      operationId: patch-api-purchase-order-lines-purchase-order-line
  /api/purchase-order-lines/{purchase_order_line}/short-close:
    post:
      tags:
      - Purchase Orders
      summary: Short-Close PO Line
      description: 'Short-close a PO line at a smaller `closed_quantity` than originally
        ordered. Records an audit event (PurchaseOrderLineShortCloseEvent) and mutates
        the line''s `quantity` to the new effective ordered amount. The line''s own
        `save` propagates the change into demand-planning coverages.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Request body fields:

        - `closed_quantity` (required, numeric, min 0): the new effective ordered
        quantity. Must be less than the original ordered quantity AND greater than
        or equal to the already-received quantity.

        - `reason` (optional, nullable, max 500): free-text reason for the short-close,
        recorded on the event.


        Validation rules (422):

        - A PO line can only have one active short-close at a time — undo the existing
        one first.

        - `closed_quantity` must be less than the original ordered quantity.

        - `closed_quantity` cannot be less than the already-received quantity.


        Returns the created PurchaseOrderLineShortCloseEvent (eager-loaded with `closedBy`
        and `followUpPurchaseOrder`).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                closed_quantity:
                  type: integer
                reason:
                  type: string
              example:
                closed_quantity: 89
                reason: Supplier short-shipped; closing line at received qty and creating
                  a follow-up PO.
      parameters:
      - name: purchase_order_line
        in: path
        schema:
          type: integer
        required: true
        description: Purchase order line ID to short-close
        example: '101'
      responses:
        '201':
          description: Created
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      purchase_order_line_id:
                        type: integer
                      original_quantity:
                        type: integer
                      closed_quantity:
                        type: integer
                      released_quantity:
                        type: integer
                      reason:
                        type: string
                      closed_at:
                        type: string
                      closed_by:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      follow_up_purchase_order:
                        type: string
                        nullable: true
                      undone_at:
                        type: string
                        nullable: true
                      undone_by:
                        type: string
                        nullable: true
                      is_active:
                        type: boolean
                example:
                  data:
                    id: 55
                    purchase_order_line_id: 101
                    original_quantity: 91
                    closed_quantity: 89
                    released_quantity: 2
                    reason: Supplier short-shipped; closing line at received qty and
                      creating a follow-up PO.
                    closed_at: '2026-05-14T10:30:00.000000Z'
                    closed_by:
                      id: 3
                      name: Kalvin Mizzi
                    follow_up_purchase_order: null
                    undone_at: null
                    undone_by: null
                    is_active: true
        '422':
          description: Unprocessable Entity
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 422 Already Short-Closed
                  value:
                    message: This purchase order line is already short-closed. Undo
                      the existing short-close before creating a new one.
                example-1:
                  summary: 422 Below Received Qty
                  value:
                    message: Closed quantity (50) cannot be less than the already-received
                      quantity (89).
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:write
      operationId: post-api-purchase-order-lines-purchase-order-line-short-close
  /api/purchase-order-line-short-close-events/{short_close_event}:
    delete:
      tags:
      - Purchase Orders
      summary: Undo Short-Close
      description: 'Reverse a prior short-close event, restoring the PO line''s original
        ordered quantity.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        The event is marked as undone (with `undone_at` / `undone_by`) rather than
        deleted, preserving the audit trail. The associated PurchaseOrderLine''s `quantity`
        is restored to its `original_quantity` from the event.


        Validation errors (422):

        - The event must currently be active. Re-reversing an already-undone event
        is rejected.


        Returns the updated PurchaseOrderLineShortCloseEvent (now with `is_active:
        false`, eager-loaded with `closedBy`, `undoneBy`, and `followUpPurchaseOrder`).'
      parameters:
      - name: short_close_event
        in: path
        schema:
          type: integer
        required: true
        description: Short-close event ID to reverse
        example: '55'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      purchase_order_line_id:
                        type: integer
                      original_quantity:
                        type: integer
                      closed_quantity:
                        type: integer
                      released_quantity:
                        type: integer
                      reason:
                        type: string
                      closed_at:
                        type: string
                      closed_by:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      follow_up_purchase_order:
                        type: string
                        nullable: true
                      undone_at:
                        type: string
                      undone_by:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      is_active:
                        type: boolean
                example:
                  data:
                    id: 55
                    purchase_order_line_id: 101
                    original_quantity: 91
                    closed_quantity: 89
                    released_quantity: 2
                    reason: Supplier short-shipped; closing line at received qty and
                      creating a follow-up PO.
                    closed_at: '2026-05-14T10:30:00.000000Z'
                    closed_by:
                      id: 3
                      name: Kalvin Mizzi
                    follow_up_purchase_order: null
                    undone_at: '2026-05-14T11:45:00.000000Z'
                    undone_by:
                      id: 3
                      name: Kalvin Mizzi
                    is_active: false
        '422':
          description: Unprocessable Entity
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Short-close event has already been reversed.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:write
      operationId: delete-api-purchase-order-line-short-close-events-short-close-event
  /api/purchase-order-lines/{purchase_order_line}/settle-billing:
    post:
      tags:
      - Purchase Orders
      summary: Settle PO Line Billing (Final Invoice)
      description: 'Mark a PO line as billing-settled — the SAP EREKZ "final invoice"
        axis. A billing-settled line counts as fully invoiced for reconciliation regardless
        of any residual short-billed quantity; use it when the supplier confirms this
        is the final bill for the line even though it was under-billed.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token. Requires the `purchase_orders.update`
        permission.


        Request body fields:

        - `reason` (optional, nullable, string, max 500): free-text note recorded
        on the settlement and shown in the audit trail.


        Stamps `billing_settled_at`, `billing_settled_reason`, and `billing_settled_by`
        (the acting user) on the line, then re-derives the parent purchase order''s
        `invoice_status`.


        Validation errors (422, DomainException): returned when the line cannot be
        settled — e.g. it is already billing-settled, or it is already fully invoiced
        through quantity/credit so settlement is unnecessary.


        Returns the updated PurchaseOrderLine billing-settlement view (eager-loaded
        with `billingSettledBy` and `purchaseOrder`).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                reason:
                  type: string
              example:
                reason: SAP EREKZ final-invoice indicator received; treat line as
                  fully billed despite short-billed residual.
      parameters:
      - name: purchase_order_line
        in: path
        schema:
          type: integer
        required: true
        description: Purchase order line ID to mark billing-settled
        example: '101'
      responses:
        '201':
          description: Created
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: integer
                  billing_settled_at:
                    type: string
                  billing_settled_reason:
                    type: string
                  billing_settled_by:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                  fully_invoiced:
                    type: boolean
                  purchase_order:
                    type: object
                    properties:
                      id:
                        type: integer
                      invoice_status:
                        type: string
                      fully_invoiced:
                        type: boolean
                example:
                  id: 101
                  billing_settled_at: '2026-07-07T14:20:00.000000Z'
                  billing_settled_reason: SAP EREKZ final-invoice indicator received;
                    treat line as fully billed despite short-billed residual.
                  billing_settled_by:
                    id: 3
                    name: Kalvin Mizzi
                  fully_invoiced: true
                  purchase_order:
                    id: 715
                    invoice_status: invoiced
                    fully_invoiced: true
        '422':
          description: Unprocessable Entity
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: This purchase order line is already marked as billing-settled.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:write
      operationId: post-api-purchase-order-lines-purchase-order-line-settle-billing
  /api/purchase-order-line-billing-settlements/{purchase_order_line}:
    delete:
      tags:
      - Purchase Orders
      summary: Unsettle PO Line Billing
      description: 'Reverse a prior billing settlement on a PO line, clearing the
        SAP EREKZ "final invoice" flag. The line reverts to normal quantity/credit
        reconciliation, so it may flip back to partially-invoiced if it was short-billed.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token. Requires the `purchase_orders.update`
        permission.


        Clears `billing_settled_at`, `billing_settled_reason`, and `billing_settled_by`
        on the line, then re-derives the parent purchase order''s `invoice_status`.


        Validation errors (422, DomainException): returned when the line is not currently
        billing-settled.


        Returns the updated PurchaseOrderLine billing-settlement view (eager-loaded
        with `billingSettledBy` and `purchaseOrder`).'
      parameters:
      - name: purchase_order_line
        in: path
        schema:
          type: integer
        required: true
        description: Purchase order line ID whose billing settlement to clear
        example: '101'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: integer
                  billing_settled_at:
                    type: string
                    nullable: true
                  billing_settled_reason:
                    type: string
                    nullable: true
                  billing_settled_by:
                    type: string
                    nullable: true
                  fully_invoiced:
                    type: boolean
                  purchase_order:
                    type: object
                    properties:
                      id:
                        type: integer
                      invoice_status:
                        type: string
                      fully_invoiced:
                        type: boolean
                example:
                  id: 101
                  billing_settled_at: null
                  billing_settled_reason: null
                  billing_settled_by: null
                  fully_invoiced: false
                  purchase_order:
                    id: 715
                    invoice_status: partially_invoiced
                    fully_invoiced: false
        '422':
          description: Unprocessable Entity
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: This purchase order line is not billing-settled.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:write
      operationId: delete-api-purchase-order-line-billing-settlements-purchase-order-line
  /api/purchase-orders/{purchase_order}/settle-billing:
    post:
      tags:
      - Purchase Orders
      summary: Settle Whole PO Billing (Final Invoice)
      description: 'Bulk-settle the billing axis for every eligible line on a purchase
        order in one call — the whole-PO equivalent of the per-line settle endpoint.
        Each still-open, short-billed line is stamped billing-settled; lines already
        fully invoiced or already settled are left untouched.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token. Requires the `purchase_orders.update`
        permission.


        Request body fields:

        - `reason` (optional, nullable, string, max 500): free-text note recorded
        on every line settled by this call.


        After settling, the purchase order''s `invoice_status` is re-derived and returned.


        Response fields:

        - `settled_count`: number of lines newly billing-settled by this call.

        - `purchase_order`: `{ id, invoice_status, fully_invoiced }` after re-derivation.

        - `lines[]`: the billing-settlement view of each line that was settled (each
        eager-loaded with `billingSettledBy` and `purchaseOrder`).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                reason:
                  type: string
              example:
                reason: Final invoice received for the whole PO; settle all short-billed
                  lines.
      parameters:
      - name: purchase_order
        in: path
        schema:
          type: integer
        required: true
        description: Purchase order ID whose eligible lines to bulk billing-settle
        example: '715'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  settled_count:
                    type: integer
                  purchase_order:
                    type: object
                    properties:
                      id:
                        type: integer
                      invoice_status:
                        type: string
                      fully_invoiced:
                        type: boolean
                  lines:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        billing_settled_at:
                          type: string
                        billing_settled_reason:
                          type: string
                        billing_settled_by:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        fully_invoiced:
                          type: boolean
                        purchase_order:
                          type: object
                          properties:
                            id:
                              type: integer
                            invoice_status:
                              type: string
                            fully_invoiced:
                              type: boolean
                example:
                  settled_count: 2
                  purchase_order:
                    id: 715
                    invoice_status: invoiced
                    fully_invoiced: true
                  lines:
                  - id: 101
                    billing_settled_at: '2026-07-07T14:20:00.000000Z'
                    billing_settled_reason: Final invoice received for the whole PO;
                      settle all short-billed lines.
                    billing_settled_by:
                      id: 3
                      name: Kalvin Mizzi
                    fully_invoiced: true
                    purchase_order:
                      id: 715
                      invoice_status: invoiced
                      fully_invoiced: true
                  - id: 102
                    billing_settled_at: '2026-07-07T14:20:00.000000Z'
                    billing_settled_reason: Final invoice received for the whole PO;
                      settle all short-billed lines.
                    billing_settled_by:
                      id: 3
                      name: Kalvin Mizzi
                    fully_invoiced: true
                    purchase_order:
                      id: 715
                      invoice_status: invoiced
                      fully_invoiced: true
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: purchase-orders:write
      operationId: post-api-purchase-orders-purchase-order-settle-billing
  /api/purchase-orders/{purchaseOrder}/lines/reorder:
    post:
      tags:
      - Purchase Orders
      summary: Reorder Purchase Order Lines
      description: 'Persist a new top-to-bottom ordering for a purchase order''s lines.


        Authentication: Requires Bearer token.


        Body:

        - ordered_ids (required, integer array): purchase order line ids in the desired
        order. A partial list is allowed — any line not listed keeps its relative
        order after the listed set. Every id must belong to this purchase order (otherwise
        422).


        Returns the resulting line ids in their new order under data.ids.


        **Requires permission:** `purchase_orders.update`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ordered_ids:
                  type: array
                  items:
                    type: integer
              example:
                ordered_ids:
                - 305
                - 304
                - 306
      parameters:
      - name: purchaseOrder
        in: path
        schema:
          type: integer
        required: true
        example: '101'
        description: The purchase order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      ids:
                        type: array
                        items:
                          type: integer
                example:
                  data:
                    ids:
                    - 305
                    - 304
                    - 306
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-purchase-orders-purchaseorder-lines-reorder
  /api/purchase-orders/{purchase_order}/receipts:
    get:
      tags:
      - Purchase Orders
      summary: Get PO Receipts
      description: 'Get all shipment receipts for a purchase order.


        :::info[Required scope: `purchase-orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: purchase_order
        in: path
        schema:
          type: integer
        required: true
        example: '101'
        description: The purchase order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        inbound_shipment_id:
                          type: integer
                        warehouse_id:
                          type: integer
                        warehouse:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        received_at:
                          type: string
                        notes:
                          type: string
                        received_by:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        inbound_shipment_receipt_lines:
                          type: array
                          items:
                            type: object
                            properties:
                              id:
                                type: integer
                              purchase_order_line_id:
                                type: integer
                              quantity:
                                type: integer
                        purchase_orders:
                          type: array
                          items:
                            type: object
                            properties:
                              id:
                                type: integer
                              purchase_order_number:
                                type: string
                example:
                  data:
                  - id: 301
                    inbound_shipment_id: 401
                    warehouse_id: 3
                    warehouse:
                      id: 3
                      name: East Coast Fulfillment
                    received_at: '2024-02-05T14:00:00Z'
                    notes: Pallet 2 of 3 received
                    received_by:
                      id: 12
                      name: Dana Receiving
                    inbound_shipment_receipt_lines:
                    - id: 501
                      purchase_order_line_id: 601
                      quantity: 100
                    purchase_orders:
                    - id: 88
                      purchase_order_number: PO-000088
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:read
      operationId: get-api-purchase-orders-purchase-order-receipts
  /api/purchase-orders/{purchase_order}/receipts/{receipt}:
    get:
      tags:
      - Purchase Orders
      summary: Get Single PO Receipt
      description: 'Get a single receipt for a purchase order.


        :::info[Required scope: `purchase-orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Path params:

        - purchase_order: Purchase order ID

        - receipt: InboundShipmentReceipt (ISR) ID — this is the canonical wire id
        since Phase 4.4g.6a (the same id returned by `/api/purchase-orders/{po}/receipts`).


        Returns the canonical InboundShipmentReceipt with `inbound_shipment_receipt_lines`;
        line `id`s within that array are InboundShipmentReceiptLine (ISRL) ids.'
      parameters:
      - name: purchase_order
        in: path
        schema:
          type: integer
        required: true
        example: '101'
        description: The purchase order ID.
      - name: receipt
        in: path
        schema:
          type: integer
        required: true
        description: InboundShipmentReceipt (ISR) ID — canonical wire id (Phase 4.4g.6a)
        example: '9001'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      received_at:
                        type: string
                      fulfilled_by:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      inbound_shipment_receipt_lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            quantity:
                              type: integer
                            purchase_order_line:
                              type: object
                              properties:
                                id:
                                  type: integer
                                product:
                                  type: object
                                  properties:
                                    id:
                                      type: integer
                                    sku:
                                      type: string
                                    supplier_sku:
                                      type: string
                                description:
                                  type: string
                                received_quantity:
                                  type: integer
                                quantity:
                                  type: integer
                example:
                  data:
                    id: 9001
                    received_at: '2024-02-05T14:00:00Z'
                    fulfilled_by:
                      id: 1
                      name: Jane Smith
                    inbound_shipment_receipt_lines:
                    - id: 8101
                      quantity: 10
                      purchase_order_line:
                        id: 501
                        product:
                          id: 42
                          sku: WIDGET-001
                          supplier_sku: SUP-WIDG-001
                        description: Widget
                        received_quantity: 10
                        quantity: 25
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:read
      operationId: get-api-purchase-orders-purchase-order-receipts-receipt
  /api/purchase-orders/{purchase_order}/dropship-shipments:
    get:
      tags:
      - Purchase Orders
      summary: Get Dropship Shipments
      description: 'Get dropship fulfillment shipments for a dropship purchase order.
        Returns empty array for non-dropship POs.


        :::info[Required scope: `purchase-orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: purchase_order
        in: path
        schema:
          type: integer
        required: true
        example: '101'
        description: The purchase order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        warehouse_id:
                          type: integer
                        tracking_number:
                          type: string
                        sales_order_fulfillment_lines:
                          type: array
                example:
                  data:
                  - id: 700
                    warehouse_id: 3
                    tracking_number: TRACK456
                    sales_order_fulfillment_lines: []
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:read
      operationId: get-api-purchase-orders-purchase-order-dropship-shipments
  /api/purchase-orders/{purchase_order}/mark-as-shipped:
    put:
      tags:
      - Purchase Orders
      summary: Mark as Shipped (FBA/AWD)
      description: 'Mark an FBA or AWD purchase order as shipped. Processes through
        Amazon inbound management (creates pending inbound record).


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Only works for Amazon FBA or AWD destination warehouses.


        Body:

        - shipment_date (optional, date Y-m-d, must be on or before today)

        - tracking_number (optional, string, max:255)


        **Requires permission:** `purchase_orders.update`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                shipment_date:
                  type: string
                tracking_number:
                  type: string
              example:
                shipment_date: '2024-01-20'
                tracking_number: AMZN-TRACK-123
      parameters:
      - name: purchase_order
        in: path
        schema:
          type: integer
        required: true
        example: '101'
        description: The purchase order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      shipment_status:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 101
                    shipment_status: shipped
                  message: Purchase order marked as shipped successfully.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: This purchase order is not an Amazon FBA or AWD inbound.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:write
      operationId: put-api-purchase-orders-purchase-order-mark-as-shipped
  /api/purchase-orders/{purchase_order}/update-shipment:
    put:
      tags:
      - Purchase Orders
      summary: Update Shipment Details (FBA)
      description: 'Update shipment details (shipped date and tracking number) for
        an already-shipped FBA purchase order.


        Authentication: Requires Bearer token.


        Body:

        - shipment_date (optional, date Y-m-d, on or before today)

        - tracking_number (optional, string, max:255)'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                shipment_date:
                  type: string
                tracking_number:
                  type: string
              example:
                shipment_date: '2024-01-22'
                tracking_number: AMZN-TRACK-456
      parameters:
      - name: purchase_order
        in: path
        schema:
          type: integer
        required: true
        example: '101'
        description: The purchase order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    id: 101
                  message: Purchase order shipment details updated successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-purchase-orders-purchase-order-update-shipment
  /api/purchase-orders/{purchase_order}/notes:
    get:
      tags:
      - Purchase Orders
      summary: Get Notes
      description: 'Get paginated notes for a purchase order (most recent first).


        :::info[Required scope: `purchase-orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: purchase_order
        in: path
        schema:
          type: integer
        required: true
        example: '101'
        description: The purchase order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        note:
                          type: string
                        is_pinned:
                          type: boolean
                        created_at:
                          type: string
                        user:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                  current_page:
                    type: integer
                example:
                  data:
                  - id: 1
                    note: Called supplier to confirm ETA.
                    is_pinned: false
                    created_at: '2024-01-16T09:00:00Z'
                    user:
                      id: 1
                      name: John Doe
                  current_page: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:read
      operationId: get-api-purchase-orders-purchase-order-notes
    post:
      tags:
      - Purchase Orders
      summary: Add Note
      description: 'Add a note to a purchase order.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Body:

        - note (required): Note text

        - is_pinned (optional, boolean): Pin note to top


        **Requires permission:** `purchase_orders.update`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                note:
                  type: string
                is_pinned:
                  type: boolean
              example:
                note: Supplier confirmed shipment for Feb 1.
                is_pinned: false
      parameters:
      - name: purchase_order
        in: path
        schema:
          type: integer
        required: true
        example: '101'
        description: The purchase order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      note:
                        type: string
                      is_pinned:
                        type: boolean
                      created_at:
                        type: string
                      user:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                  message:
                    type: string
                example:
                  data:
                    id: 2
                    note: Supplier confirmed shipment for Feb 1.
                    is_pinned: false
                    created_at: '2024-01-17T10:00:00Z'
                    user:
                      id: 1
                      name: John Doe
                  message: Note created successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: purchase-orders:write
      operationId: post-api-purchase-orders-purchase-order-notes
  /api/purchase-orders/{purchase_order}/notes/{noteId}/toggle-pin:
    put:
      tags:
      - Purchase Orders
      summary: Toggle Note Pin
      description: 'Toggle the pinned state of a note on a purchase order.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `purchase_orders.update`'
      requestBody:
        content: {}
      parameters:
      - name: purchase_order
        in: path
        schema:
          type: integer
        required: true
        example: '101'
        description: The purchase order ID.
      - name: noteId
        in: path
        schema:
          type: integer
        required: true
        example: '2'
        description: The note ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      is_pinned:
                        type: boolean
                  message:
                    type: string
                example:
                  data:
                    id: 2
                    is_pinned: true
                  message: Note pinned
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: purchase-orders:write
      operationId: put-api-purchase-orders-purchase-order-notes-noteid-toggle-pin
  /api/purchase-orders/{purchase_order}/notes/{noteId}:
    delete:
      tags:
      - Purchase Orders
      summary: Delete Note
      description: 'Delete a note from a purchase order.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `purchase_orders.update`'
      parameters:
      - name: purchase_order
        in: path
        schema:
          type: integer
        required: true
        example: '101'
        description: The purchase order ID.
      - name: noteId
        in: path
        schema:
          type: integer
        required: true
        example: '2'
        description: The note ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Note 2 deleted successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:write
      operationId: delete-api-purchase-orders-purchase-order-notes-noteid
  /api/purchase-orders/{purchase_order}/communications/threads:
    get:
      tags:
      - Purchase Orders
      summary: List Purchase Order Communication Threads
      description: 'List the topic threads on a purchase order (e.g. "Ship date",
        "Invoice"), most-recent first. Each thread includes its primary channel, unread
        count, and latest message for the sidebar preview.


        Authentication: Requires Bearer token.'
      parameters:
      - name: purchase_order
        in: path
        schema:
          type: integer
        required: true
        example: '101'
        description: The purchase order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        subject:
                          type: string
                        channel:
                          type: string
                        channel_label:
                          type: string
                        unread_count:
                          type: integer
                        last_message_at:
                          type: string
                        last_message:
                          type: object
                          properties:
                            id:
                              type: integer
                            channel:
                              type: string
                            channel_label:
                              type: string
                            direction:
                              type: string
                            direction_label:
                              type: string
                            author_name:
                              type: string
                            author_type:
                              type: string
                            from_address:
                              type: string
                            to_addresses:
                              type: string
                              nullable: true
                            subject:
                              type: string
                              nullable: true
                            body_html:
                              type: string
                              nullable: true
                            body_text:
                              type: string
                            attachments:
                              type: array
                            is_read:
                              type: boolean
                            external_message_id:
                              type: string
                            meta:
                              type: object
                              properties:
                                delivery:
                                  type: string
                            link_reference:
                              type: string
                            link_type_label:
                              type: string
                            link_id:
                              type: integer
                            link_route:
                              type: string
                            created_at:
                              type: string
                        created_at:
                          type: string
                example:
                  data:
                  - id: 12
                    subject: Ship date & delivery
                    channel: whatsapp
                    channel_label: WhatsApp
                    unread_count: 2
                    last_message_at: '2026-07-22T12:28:00+00:00'
                    last_message:
                      id: 842
                      channel: whatsapp
                      channel_label: WhatsApp
                      direction: inbound
                      direction_label: Inbound
                      author_name: Acme Supplies
                      author_type: supplier
                      from_address: '+15551234567'
                      to_addresses: null
                      subject: null
                      body_html: null
                      body_text: Great, we'll lock the 480-unit ship date and send
                        confirmation shortly.
                      attachments: []
                      is_read: false
                      external_message_id: SMabc123
                      meta:
                        delivery: sent
                      link_reference: PO-2942
                      link_type_label: Purchase Order
                      link_id: 101
                      link_route: /orders/purchase-orders/101
                      created_at: '2026-07-22T12:28:00+00:00'
                    created_at: '2026-07-18T09:00:00+00:00'
                  - id: 11
                    subject: Invoice & payment
                    channel: email
                    channel_label: Email
                    unread_count: 0
                    last_message_at: '2026-07-22T12:28:00+00:00'
                    last_message: null
                    created_at: '2026-07-18T09:00:00+00:00'
                  - id: 1
                    subject: General
                    channel: email
                    channel_label: Email
                    unread_count: 0
                    last_message_at: '2026-07-22T12:28:00+00:00'
                    last_message: null
                    created_at: '2026-07-18T09:00:00+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-purchase-orders-purchase-order-communications-threads
    post:
      tags:
      - Purchase Orders
      summary: Create Purchase Order Communication Thread
      description: 'Start a new topic thread on a purchase order and post its first
        message. For email threads the subject doubles as the email subject sent to
        the supplier. Attach files by sending the request as multipart/form-data with
        attachments[] parts.


        Fields: subject (required), channel (required — email, internal_note, whatsapp,
        or sms), body (required).


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                subject:
                  type: string
                channel:
                  type: string
                body:
                  type: string
              example:
                subject: Packaging & labeling requirements
                channel: email
                body: Hi — before this ships, can you confirm the labeling spec for
                  the 480 units?
      parameters:
      - name: purchase_order
        in: path
        schema:
          type: integer
        required: true
        example: '101'
        description: The purchase order ID.
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      subject:
                        type: string
                      channel:
                        type: string
                      channel_label:
                        type: string
                      unread_count:
                        type: integer
                      last_message_at:
                        type: string
                      last_message:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                example:
                  data:
                    id: 13
                    subject: Packaging & labeling requirements
                    channel: email
                    channel_label: Email
                    unread_count: 0
                    last_message_at: '2026-07-22T12:28:00+00:00'
                    last_message: null
                    created_at: '2026-07-18T09:00:00+00:00'
        '422':
          description: Unprocessable Content
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      subject:
                        type: array
                        items:
                          type: string
                      body:
                        type: array
                        items:
                          type: string
                example:
                  message: The subject field is required.
                  errors:
                    subject:
                    - Give the thread a subject.
                    body:
                    - Write the first message.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-purchase-orders-purchase-order-communications-threads
  /api/purchase-orders/{purchase_order}/communications:
    get:
      tags:
      - Purchase Orders
      summary: List Purchase Order Communications
      description: 'List the vendor communication thread for a purchase order, newest
        first. The thread interleaves outbound emails, inbound supplier replies, internal
        notes, and system events.


        Authentication: Requires Bearer token.'
      parameters:
      - name: purchase_order
        in: path
        schema:
          type: integer
        required: true
        example: '101'
        description: The purchase order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        channel:
                          type: string
                        channel_label:
                          type: string
                        direction:
                          type: string
                        direction_label:
                          type: string
                        author_name:
                          type: string
                        author_type:
                          type: string
                        from_address:
                          type: string
                        to_addresses:
                          type: string
                          nullable: true
                        subject:
                          type: string
                        body_html:
                          type: string
                          nullable: true
                        body_text:
                          type: string
                        attachments:
                          type: array
                          items:
                            type: object
                            properties:
                              filename:
                                type: string
                              mime_type:
                                type: string
                              size:
                                type: integer
                              url:
                                type: string
                        is_read:
                          type: boolean
                        external_message_id:
                          type: string
                        meta:
                          type: string
                          nullable: true
                        link_reference:
                          type: string
                        link_type_label:
                          type: string
                        link_route:
                          type: string
                        created_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                  first_page_url:
                    type: string
                  last_page_url:
                    type: string
                  next_page_url:
                    type: string
                    nullable: true
                  prev_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                example:
                  data:
                  - id: 5012
                    channel: email
                    channel_label: Email
                    direction: inbound
                    direction_label: Inbound
                    author_name: Acme Supplies
                    author_type: supplier
                    from_address: sales@acme-supplies.com
                    to_addresses: null
                    subject: 'Re: Purchase Order PO-10293'
                    body_html: null
                    body_text: Confirmed — shipping Friday, qty 480 (2 short).
                    attachments:
                    - filename: packing-slip.pdf
                      mime_type: application/pdf
                      size: 48213
                      url: /api/purchase-orders/101/communications/5012/attachments/0
                    is_read: false
                    external_message_id: <CAF7a2@mail.acme-supplies.com>
                    meta: null
                    link_reference: PO-10293
                    link_type_label: Purchase Order
                    link_route: /orders/purchase-orders/101
                    created_at: '2026-07-16T18:22:04+00:00'
                  - id: 5014
                    channel: internal_note
                    channel_label: Internal Note
                    direction: internal
                    direction_label: Internal
                    author_name: Jordan Buyer
                    author_type: user
                    from_address: null
                    to_addresses: null
                    subject: null
                    body_html: null
                    body_text: Backfill the 2 short units from WH-2.
                    attachments: []
                    is_read: true
                    external_message_id: null
                    meta: null
                    link_reference: PO-10293
                    link_type_label: Purchase Order
                    link_route: /orders/purchase-orders/101
                    created_at: '2026-07-16T18:45:00+00:00'
                  current_page: 1
                  last_page: 1
                  per_page: 15
                  total: 2
                  from: 1
                  to: 2
                  first_page_url: '{{protocol}}://{{domain}}/api/purchase-orders/101/communications?page=1'
                  last_page_url: '{{protocol}}://{{domain}}/api/purchase-orders/101/communications?page=1'
                  next_page_url: null
                  prev_page_url: null
                  path: '{{protocol}}://{{domain}}/api/purchase-orders/101/communications'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-purchase-orders-purchase-order-communications
    post:
      tags:
      - Purchase Orders
      summary: Create Purchase Order Communication
      description: 'Post a message onto the purchase order''s communication thread.


        Fields:

        - channel (required): one of email, internal_note, whatsapp, sms. WhatsApp/SMS
        are only accepted when a messaging provider is configured for the workspace
        and the supplier has a messaging phone number; otherwise a 422 is returned.

        - subject (required for email, ignored for notes): the email subject line.

        - body (required): the message text.


        When channel is email the message is sent to the supplier''s purchase-order
        email address and logged as an outbound entry; the supplier''s reply threads
        back onto this order automatically. An internal_note is only visible to your
        team and is never sent externally.


        Authentication: Requires Bearer token.


        File attachments: send the request as multipart/form-data with one or more
        attachments[] file parts (max 10 files, 20 MB each; pdf/office/image/csv/text).
        Attached files are stored on the thread and, for emails, attached to the outbound
        message.


        Set thread_id to post into a specific thread; omit it to post into the purchase
        order''s default "General" thread.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                thread_id:
                  type: integer
                channel:
                  type: string
                subject:
                  type: string
                body:
                  type: string
              example:
                thread_id: 12
                channel: email
                subject: Ship date confirmation
                body: Hi, could you please confirm the ship date for this order?
      parameters:
      - name: purchase_order
        in: path
        schema:
          type: integer
        required: true
        example: '101'
        description: The purchase order ID.
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      channel:
                        type: string
                      channel_label:
                        type: string
                      direction:
                        type: string
                      direction_label:
                        type: string
                      author_name:
                        type: string
                      author_type:
                        type: string
                      from_address:
                        type: string
                        nullable: true
                      to_addresses:
                        type: array
                        items:
                          type: string
                      subject:
                        type: string
                      body_html:
                        type: string
                        nullable: true
                      body_text:
                        type: string
                      attachments:
                        type: array
                      is_read:
                        type: boolean
                      external_message_id:
                        type: string
                        nullable: true
                      meta:
                        type: object
                        properties:
                          delivery:
                            type: string
                      link_reference:
                        type: string
                      link_type_label:
                        type: string
                      link_route:
                        type: string
                      created_at:
                        type: string
                example:
                  data:
                    id: 5013
                    channel: email
                    channel_label: Email
                    direction: outbound
                    direction_label: Outbound
                    author_name: Jordan Buyer
                    author_type: user
                    from_address: null
                    to_addresses:
                    - sales@acme-supplies.com
                    subject: Ship date confirmation
                    body_html: null
                    body_text: Hi, could you please confirm the ship date for this
                      order?
                    attachments: []
                    is_read: true
                    external_message_id: null
                    meta:
                      delivery: queued
                    link_reference: PO-10293
                    link_type_label: Purchase Order
                    link_route: /orders/purchase-orders/101
                    created_at: '2026-07-16T18:40:11+00:00'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: The supplier has no purchase-order email address, so this
                    message cannot be emailed. Add one on the supplier, or post an
                    internal note instead.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-purchase-orders-purchase-order-communications
  /api/purchase-orders/{purchase_order}/communications/supplier-phone:
    put:
      tags:
      - Purchase Orders
      summary: Set Supplier WhatsApp/SMS Number
      description: 'Set the linked supplier''s WhatsApp/SMS number (E.164, e.g. +15551234567)
        so the messaging channels become usable on this purchase order without opening
        the supplier record. Send a blank value to clear the stored number. Returns
        the updated channel availability for this purchase order.


        Requires the `purchase_orders.update` permission. Returns 422 when the purchase
        order has no linked supplier.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                messaging_phone:
                  type: string
              example:
                messaging_phone: '+15551234567'
      parameters:
      - name: purchase_order
        in: path
        schema:
          type: integer
        required: true
        example: '101'
        description: The purchase order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: string
                  messaging:
                    type: object
                    properties:
                      has_supplier:
                        type: boolean
                      supplier_has_phone:
                        type: boolean
                      channels:
                        type: object
                        properties:
                          whatsapp:
                            type: object
                            properties:
                              available:
                                type: boolean
                              provider_ready:
                                type: boolean
                          sms:
                            type: object
                            properties:
                              available:
                                type: boolean
                              provider_ready:
                                type: boolean
                example:
                  data:
                  - email
                  - internal_note
                  - whatsapp
                  - sms
                  messaging:
                    has_supplier: true
                    supplier_has_phone: true
                    channels:
                      whatsapp:
                        available: true
                        provider_ready: true
                      sms:
                        available: true
                        provider_ready: true
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: This purchase order has no supplier to add a number to.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: put-api-purchase-orders-purchase-order-communications-supplier-phone
  /api/purchase-orders/{purchase_order}/communications/{communication}/read:
    post:
      tags:
      - Purchase Orders
      summary: Mark Communication as Read
      description: 'Mark an inbound communication entry as read, clearing it from
        the unread count.


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: purchase_order
        in: path
        schema:
          type: integer
        required: true
        example: '101'
        description: The purchase order ID.
      - name: communication
        in: path
        schema:
          type: integer
        required: true
        example: '5012'
        description: The communication ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      channel:
                        type: string
                      channel_label:
                        type: string
                      direction:
                        type: string
                      direction_label:
                        type: string
                      author_name:
                        type: string
                      author_type:
                        type: string
                      from_address:
                        type: string
                      to_addresses:
                        type: string
                        nullable: true
                      subject:
                        type: string
                      body_html:
                        type: string
                        nullable: true
                      body_text:
                        type: string
                      attachments:
                        type: array
                        items:
                          type: object
                          properties:
                            filename:
                              type: string
                            mime_type:
                              type: string
                            size:
                              type: integer
                            url:
                              type: string
                      is_read:
                        type: boolean
                      external_message_id:
                        type: string
                      meta:
                        type: string
                        nullable: true
                      link_reference:
                        type: string
                      link_type_label:
                        type: string
                      link_route:
                        type: string
                      created_at:
                        type: string
                example:
                  data:
                    id: 5012
                    channel: email
                    channel_label: Email
                    direction: inbound
                    direction_label: Inbound
                    author_name: Acme Supplies
                    author_type: supplier
                    from_address: sales@acme-supplies.com
                    to_addresses: null
                    subject: 'Re: Purchase Order PO-10293'
                    body_html: null
                    body_text: Confirmed — shipping Friday, qty 480 (2 short).
                    attachments:
                    - filename: packing-slip.pdf
                      mime_type: application/pdf
                      size: 48213
                      url: /api/purchase-orders/101/communications/5012/attachments/0
                    is_read: true
                    external_message_id: <CAF7a2@mail.acme-supplies.com>
                    meta: null
                    link_reference: PO-10293
                    link_type_label: Purchase Order
                    link_route: /orders/purchase-orders/101
                    created_at: '2026-07-16T18:22:04+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-purchase-orders-purchase-order-communications-communication-read
  /api/v2/suppliers/{supplier}/communications:
    get:
      tags:
      - Purchase Orders
      summary: List Supplier Communications (Cross-PO)
      description: 'List every vendor communication for a supplier across all of their
        purchase orders, newest first. Read-only aggregate view; each item links to
        the purchase order it belongs to via link_route.


        Authentication: Requires Bearer token.'
      parameters:
      - name: supplier
        in: path
        schema:
          type: integer
        required: true
        example: '55'
        description: The supplier ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        channel:
                          type: string
                        channel_label:
                          type: string
                        direction:
                          type: string
                        direction_label:
                          type: string
                        author_name:
                          type: string
                        author_type:
                          type: string
                        from_address:
                          type: string
                        to_addresses:
                          type: string
                          nullable: true
                        subject:
                          type: string
                        body_html:
                          type: string
                          nullable: true
                        body_text:
                          type: string
                        attachments:
                          type: array
                        is_read:
                          type: boolean
                        external_message_id:
                          type: string
                          nullable: true
                        meta:
                          type: string
                          nullable: true
                        link_reference:
                          type: string
                        link_type_label:
                          type: string
                        link_id:
                          type: integer
                        link_route:
                          type: string
                        created_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                  first_page_url:
                    type: string
                  last_page_url:
                    type: string
                  next_page_url:
                    type: string
                    nullable: true
                  prev_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                example:
                  data:
                  - id: 6002
                    channel: email
                    channel_label: Email
                    direction: inbound
                    direction_label: Inbound
                    author_name: Acme Supplies
                    author_type: supplier
                    from_address: sales@acme-supplies.com
                    to_addresses: null
                    subject: 'Re: Purchase Order PO-10311'
                    body_html: null
                    body_text: Confirmed for the second order too.
                    attachments: []
                    is_read: false
                    external_message_id: null
                    meta: null
                    link_reference: PO-10311
                    link_type_label: Purchase Order
                    link_id: 118
                    link_route: /orders/purchase-orders/118
                    created_at: '2026-07-16T19:02:00+00:00'
                  - id: 6001
                    channel: email
                    channel_label: Email
                    direction: outbound
                    direction_label: Outbound
                    author_name: Jordan Buyer
                    author_type: user
                    from_address: null
                    to_addresses:
                    - sales@acme-supplies.com
                    subject: Purchase Order PO-10293
                    body_html: null
                    body_text: Please confirm the ship date.
                    attachments: []
                    is_read: true
                    external_message_id: null
                    meta: null
                    link_reference: PO-10293
                    link_type_label: Purchase Order
                    link_id: 101
                    link_route: /orders/purchase-orders/101
                    created_at: '2026-07-16T18:40:11+00:00'
                  current_page: 1
                  last_page: 1
                  per_page: 15
                  total: 2
                  from: 1
                  to: 2
                  first_page_url: '{{protocol}}://{{domain}}/api/v2/suppliers/55/communications?page=1'
                  last_page_url: '{{protocol}}://{{domain}}/api/v2/suppliers/55/communications?page=1'
                  next_page_url: null
                  prev_page_url: null
                  path: '{{protocol}}://{{domain}}/api/v2/suppliers/55/communications'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-v2-suppliers-supplier-communications
  /api/purchase-orders/{purchase_order}/activity-log:
    get:
      tags:
      - Purchase Orders
      summary: Activity Log
      description: 'Get paginated activity log for a purchase order. Covers events
        on the PO, its lines, and invoices.


        :::info[Required scope: `purchase-orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: per_page
        in: query
        schema:
          type: integer
        description: Items per page (default 15)
        example: '15'
      - name: filter[search]
        in: query
        schema:
          type: string
        description: Search by causer name, event, subject type, or properties
      - name: purchase_order
        in: path
        schema:
          type: integer
        required: true
        example: '101'
        description: The purchase order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        description:
                          type: string
                        event:
                          type: string
                        subject_type:
                          type: string
                        subject_id:
                          type: integer
                        properties:
                          type: object
                          properties:
                            old:
                              type: object
                              properties:
                                order_status:
                                  type: string
                            attributes:
                              type: object
                              properties:
                                order_status:
                                  type: string
                        causer_name:
                          type: string
                        created_at:
                          type: string
                  current_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 1000
                    description: updated
                    event: updated
                    subject_type: PurchaseOrder
                    subject_id: 101
                    properties:
                      old:
                        order_status: draft
                      attributes:
                        order_status: open
                    causer_name: John Doe
                    created_at: '2024-01-15T10:05:00Z'
                  current_page: 1
                  total: 8
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:read
      operationId: get-api-purchase-orders-purchase-order-activity-log
  /api/purchase-orders/{purchase_order}/inventory-movements:
    get:
      tags:
      - Purchase Orders
      summary: Inventory Movements
      description: 'Get paginated inventory movements for a purchase order (via receipt
        lines).


        :::info[Required scope: `purchase-orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        For an outsourced-manufacturing PO, this also surfaces the backing manufacturing
        order''s movements: the finished-good receipt (Manufacturing Output) and the
        component consumption at the contractor (Manufacturing Consumption), so both
        are visible on the PO.'
      parameters:
      - name: per_page
        in: query
        schema:
          type: integer
        description: Items per page (default 15)
        example: '15'
      - name: purchase_order
        in: path
        schema:
          type: integer
        required: true
        example: '101'
        description: The purchase order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        type:
                          type: string
                        inventory_status:
                          type: string
                        quantity:
                          type: integer
                        reference:
                          type: string
                        product_id:
                          type: integer
                        product_sku:
                          type: string
                        product_name:
                          type: string
                        warehouse_id:
                          type: integer
                        warehouse_name:
                          type: string
                        unit_cost:
                          type: number
                        unit_cost_provisional:
                          type: boolean
                        layer:
                          type: object
                          properties:
                            name:
                              type: string
                            fifo_layer_id:
                              type: integer
                        inventory_movement_date:
                          type: string
                        created_at:
                          type: string
                  current_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 2000
                    type: receipt
                    inventory_status: in_stock
                    quantity: 100
                    reference: PO-00101
                    product_id: 10
                    product_sku: SKU-001
                    product_name: Widget A
                    warehouse_id: 2
                    warehouse_name: Main Warehouse
                    unit_cost: 15.0
                    unit_cost_provisional: false
                    layer:
                      name: L-2024-001
                      fifo_layer_id: 50
                    inventory_movement_date: '2024-02-05'
                    created_at: '2024-02-05T14:00:00Z'
                  current_page: 1
                  total: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:read
      operationId: get-api-purchase-orders-purchase-order-inventory-movements
  /api/purchase-orders/{purchase_order}/fifo-layers:
    get:
      tags:
      - Purchase Orders
      summary: FIFO Layers
      description: 'Get paginated FIFO inventory layers created from receiving this
        purchase order.


        :::info[Required scope: `purchase-orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        For an outsourced-manufacturing PO, this also includes the finished-good FIFO
        layers produced by the backing manufacturing order (the goods physically arrived
        via this PO receipt).'
      parameters:
      - name: per_page
        in: query
        schema:
          type: integer
        description: Items per page (default 15)
        example: '15'
      - name: filter[search]
        in: query
        schema:
          type: string
        description: Search by product SKU or name
      - name: purchase_order
        in: path
        schema:
          type: integer
        required: true
        example: '101'
        description: The purchase order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        product_id:
                          type: integer
                        warehouse_id:
                          type: integer
                        quantity:
                          type: integer
                        remaining_quantity:
                          type: integer
                        avg_cost:
                          type: number
                        link_type:
                          type: string
                        link_id:
                          type: integer
                        created_at:
                          type: string
                  current_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 50
                    product_id: 10
                    warehouse_id: 2
                    quantity: 100
                    remaining_quantity: 95
                    avg_cost: 15.0
                    link_type: App\Models\PurchaseOrderShipmentReceiptLine
                    link_id: 501
                    created_at: '2024-02-05T14:00:00Z'
                  current_page: 1
                  total: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:read
      operationId: get-api-purchase-orders-purchase-order-fifo-layers
  /api/purchase-orders/{purchaseOrder}/invoices:
    get:
      tags:
      - Purchase Orders
      summary: List PO Invoices
      description: 'Get paginated purchase invoices for a specific purchase order.


        :::info[Required scope: `purchase-orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: purchaseOrder
        in: path
        schema:
          type: integer
        required: true
        example: '101'
        description: The purchase order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        supplier_invoice_number:
                          type: string
                        purchase_invoice_date:
                          type: string
                        total:
                          type: number
                  current_page:
                    type: integer
                example:
                  data:
                  - id: 800
                    supplier_invoice_number: INV-2024-001
                    purchase_invoice_date: '2024-01-20T00:00:00Z'
                    total: 1500.0
                  current_page: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:read
      operationId: get-api-purchase-orders-purchaseorder-invoices
  /api/purchase-orders/{purchase_order}/invoice/preview:
    get:
      tags:
      - Purchase Orders
      summary: Preview Invoice
      description: 'Generate an invoice PDF preview and return the URL path.


        :::info[Required scope: `purchase-orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: purchase_order
        in: path
        schema:
          type: integer
        required: true
        example: '101'
        description: The purchase order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      path:
                        type: string
                example:
                  data:
                    path: https://sku2.test/storage/reports/purchase-order-invoice-101.pdf
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:read
      operationId: get-api-purchase-orders-purchase-order-invoice-preview
  /api/purchase-orders/{purchase_order}/bills:
    post:
      tags:
      - Purchase Orders
      summary: Create Bill
      description: 'Create a landed cost bill linked to this purchase order.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                vendor_id:
                  type: integer
                invoice_number:
                  type: string
                invoice_date:
                  type: string
                currency_id:
                  type: integer
                currency_rate:
                  type: integer
                lines:
                  type: array
                  items:
                    type: object
                    properties:
                      description:
                        type: string
                      quantity:
                        type: integer
                      unit_price:
                        type: integer
                      tax_rate_id:
                        type: string
                        nullable: true
                allocations:
                  type: array
                proration_strategy:
                  type: string
              example:
                vendor_id: 5
                invoice_number: BILL-2024-001
                invoice_date: '2024-01-20'
                currency_id: 1
                currency_rate: 1
                lines:
                - description: Freight charge
                  quantity: 1
                  unit_price: 150
                  tax_rate_id: null
                allocations: []
                proration_strategy: quantity
      parameters:
      - name: purchase_order
        in: path
        schema:
          type: integer
        required: true
        example: '101'
        description: The purchase order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      invoice_number:
                        type: string
                      grand_total:
                        type: number
                example:
                  data:
                    id: 900
                    invoice_number: BILL-2024-001
                    grand_total: 150.0
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: purchase-orders:write
      operationId: post-api-purchase-orders-purchase-order-bills
  /api/purchase-orders/{purchase_order}/bills/{bill}:
    get:
      tags:
      - Purchase Orders
      summary: Get Bill
      description: 'Get a single bill linked to this purchase order. Returns 404 if
        the bill does not belong to this PO.


        :::info[Required scope: `purchase-orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: purchase_order
        in: path
        schema:
          type: integer
        required: true
        example: '101'
        description: The purchase order ID.
      - name: bill
        in: path
        schema:
          type: integer
        required: true
        example: '900'
        description: The bill ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      invoice_number:
                        type: string
                      grand_total:
                        type: number
                example:
                  data:
                    id: 900
                    invoice_number: BILL-2024-001
                    grand_total: 150.0
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:read
      operationId: get-api-purchase-orders-purchase-order-bills-bill
    patch:
      tags:
      - Purchase Orders
      summary: Update Bill
      description: 'Update a bill linked to this purchase order. Returns 404 if the
        bill does not belong to this PO.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                invoice_number:
                  type: string
                lines:
                  type: array
                  items:
                    type: object
                    properties:
                      description:
                        type: string
                      quantity:
                        type: integer
                      unit_price:
                        type: integer
              example:
                invoice_number: BILL-2024-001-REVISED
                lines:
                - description: Freight charge revised
                  quantity: 1
                  unit_price: 175
      parameters:
      - name: purchase_order
        in: path
        schema:
          type: integer
        required: true
        example: '101'
        description: The purchase order ID.
      - name: bill
        in: path
        schema:
          type: integer
        required: true
        example: '900'
        description: The bill ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      invoice_number:
                        type: string
                      grand_total:
                        type: number
                example:
                  data:
                    id: 900
                    invoice_number: BILL-2024-001-REVISED
                    grand_total: 175.0
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: purchase-orders:write
      operationId: patch-api-purchase-orders-purchase-order-bills-bill
  /api/purchase-orders/import/template:
    get:
      tags:
      - Purchase Orders
      summary: Download Import Template
      description: 'Download an XLSX import template with headers, sample data, field
        guide, and reference data.


        :::info[Required scope: `purchase-orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Response: Binary XLSX file download.


        **Requires permission:** `purchase_orders.import`'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
          content:
            text/plain:
              schema:
                type: string
                example: (Binary XLSX file)
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: purchase-orders:read
      operationId: get-api-purchase-orders-import-template
  /api/purchase-orders/import/preview:
    post:
      tags:
      - Purchase Orders
      summary: Preview Purchase Order Import
      description: 'Preview a purchase order import file before executing. Returns
        a grouped preview of what would be imported.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `purchase_orders.import`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                file:
                  type: string
              example:
                file: temp/uploaded-po-import.xlsx
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      preview:
                        type: array
                        items:
                          type: object
                          properties:
                            purchase_order_number:
                              type: string
                            supplier_name:
                              type: string
                            lines:
                              type: array
                              items:
                                type: object
                                properties:
                                  sku:
                                    type: string
                                  quantity:
                                    type: integer
                example:
                  data:
                    preview:
                    - purchase_order_number: PO-IMPORT-001
                      supplier_name: Acme Supplies
                      lines:
                      - sku: SKU-001
                        quantity: 50
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: purchase-orders:write
      operationId: post-api-purchase-orders-import-preview
  /api/purchase-orders/import/validate:
    post:
      tags:
      - Purchase Orders
      summary: Validate Import
      description: 'Validate mapped import rows and return a grouped preview with
        errors. No side effects — safe to call repeatedly.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Row fields (all optional/nullable):

        - supplier_name, purchase_order_number, purchase_order_date, destination_warehouse,
        currency_code

        - estimated_delivery_date, supplier_notes, tracking_number, tags, payment_term,
        shipping_method, incoterm

        - sku, quantity, unit_price, description, discount, tax_rate, line_estimated_delivery_date,
        nominal_code


        **Requires permission:** `purchase_orders.import`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                rows:
                  type: array
                  items:
                    type: object
                    properties:
                      supplier_name:
                        type: string
                      purchase_order_number:
                        type: string
                      purchase_order_date:
                        type: string
                      destination_warehouse:
                        type: string
                      currency_code:
                        type: string
                      estimated_delivery_date:
                        type: string
                      supplier_notes:
                        type: string
                        nullable: true
                      tracking_number:
                        type: string
                        nullable: true
                      tags:
                        type: string
                        nullable: true
                      payment_term:
                        type: string
                      shipping_method:
                        type: string
                        nullable: true
                      incoterm:
                        type: string
                        nullable: true
                      sku:
                        type: string
                      quantity:
                        type: integer
                      unit_price:
                        type: integer
                      description:
                        type: string
                      discount:
                        type: string
                        nullable: true
                      tax_rate:
                        type: string
                        nullable: true
                      line_estimated_delivery_date:
                        type: string
                        nullable: true
                      nominal_code:
                        type: string
                        nullable: true
              example:
                rows:
                - supplier_name: Acme Supplies
                  purchase_order_number: PO-IMPORT-001
                  purchase_order_date: '2024-01-15'
                  destination_warehouse: Main Warehouse
                  currency_code: USD
                  estimated_delivery_date: '2024-02-01'
                  supplier_notes: null
                  tracking_number: null
                  tags: null
                  payment_term: Net 30
                  shipping_method: null
                  incoterm: null
                  sku: SKU-001
                  quantity: 50
                  unit_price: 15
                  description: Widget A
                  discount: null
                  tax_rate: null
                  line_estimated_delivery_date: null
                  nominal_code: null
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  valid:
                    type: array
                    items:
                      type: object
                      properties:
                        purchase_order_number:
                          type: string
                        supplier_id:
                          type: integer
                        destination_warehouse_id:
                          type: integer
                        lines:
                          type: array
                          items:
                            type: object
                            properties:
                              product_id:
                                type: integer
                              quantity:
                                type: integer
                              amount:
                                type: number
                  invalid:
                    type: array
                  warnings:
                    type: array
                example:
                  valid:
                  - purchase_order_number: PO-IMPORT-001
                    supplier_id: 5
                    destination_warehouse_id: 2
                    lines:
                    - product_id: 10
                      quantity: 50
                      amount: 15.0
                  invalid: []
                  warnings: []
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: purchase-orders:write
      operationId: post-api-purchase-orders-import-validate
  /api/purchase-orders/import:
    post:
      tags:
      - Purchase Orders
      summary: Import Purchase Orders
      description: 'Execute the purchase order import — create purchase orders from
        validated data.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Returns 201 Created on success, 422 on failure.


        Purchase order fields:

        - purchase_order_date (required, date)

        - supplier_id (required, exists:suppliers)

        - destination_warehouse_id (required, exists:warehouses)

        - purchase_order_number (optional)

        - currency_id (optional), currency_code (optional)

        - order_status (optional, in:draft,open)

        - estimated_delivery_date, supplier_notes, tracking_number, tags (all optional)

        - payment_term_id, shipping_method_id, incoterm_id, store_id (all optional)


        Line fields:

        - quantity (required, numeric, min:1)

        - amount (required, numeric, min:0)

        - product_id, description, discount, tax_rate, nominal_code_id, estimated_delivery_date
        (all optional)


        **Requires permission:** `purchase_orders.import`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                purchase_orders:
                  type: array
                  items:
                    type: object
                    properties:
                      purchase_order_number:
                        type: string
                      purchase_order_date:
                        type: string
                      supplier_id:
                        type: integer
                      destination_warehouse_id:
                        type: integer
                      currency_id:
                        type: integer
                      order_status:
                        type: string
                      estimated_delivery_date:
                        type: string
                      supplier_notes:
                        type: string
                        nullable: true
                      tracking_number:
                        type: string
                        nullable: true
                      tags:
                        type: string
                        nullable: true
                      payment_term_id:
                        type: integer
                      shipping_method_id:
                        type: string
                        nullable: true
                      incoterm_id:
                        type: string
                        nullable: true
                      lines:
                        type: array
                        items:
                          type: object
                          properties:
                            product_id:
                              type: integer
                            quantity:
                              type: integer
                            amount:
                              type: integer
                            description:
                              type: string
                            discount:
                              type: string
                              nullable: true
                            tax_rate:
                              type: string
                              nullable: true
                            nominal_code_id:
                              type: string
                              nullable: true
                            estimated_delivery_date:
                              type: string
                              nullable: true
              example:
                purchase_orders:
                - purchase_order_number: PO-IMPORT-001
                  purchase_order_date: '2024-01-15'
                  supplier_id: 5
                  destination_warehouse_id: 2
                  currency_id: 1
                  order_status: draft
                  estimated_delivery_date: '2024-02-01'
                  supplier_notes: null
                  tracking_number: null
                  tags: null
                  payment_term_id: 1
                  shipping_method_id: null
                  incoterm_id: null
                  lines:
                  - product_id: 10
                    quantity: 50
                    amount: 15
                    description: Widget A
                    discount: null
                    tax_rate: null
                    nominal_code_id: null
                    estimated_delivery_date: null
      parameters: []
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  created:
                    type: integer
                  purchase_orders:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        purchase_order_number:
                          type: string
                example:
                  created: 1
                  purchase_orders:
                  - id: 105
                    purchase_order_number: PO-IMPORT-001
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 'Import failed: Supplier not found'
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: purchase-orders:write
      operationId: post-api-purchase-orders-import
  /api/purchase-orders/{purchase_order}/asn:
    post:
      tags:
      - Purchase Orders
      summary: Send ASN
      description: 'Send an Advanced Shipment Notice (ASN) for this purchase order
        to the 3PL warehouse.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Requires destination warehouse to be of type 3PL with a valid email address
        configured.


        **Requires permission:** `purchase_orders.update`'
      requestBody:
        content: {}
      parameters:
      - name: purchase_order
        in: path
        schema:
          type: integer
        required: true
        example: '101'
        description: The purchase order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Advanced Shipment Notice sent successfully
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Warehouse should be 3PL
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:write
      operationId: post-api-purchase-orders-purchase-order-asn
  /api/purchase-orders/{purchase_order}/dropship:
    post:
      tags:
      - Purchase Orders
      summary: Dropship (Ship Fulfillment)
      description: 'Create a dropship fulfillment for a dropship purchase order (ship
        directly to customer).


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `purchase_orders.update`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                tracking_number:
                  type: string
                carrier:
                  type: string
                shipped_at:
                  type: string
                lines:
                  type: array
                  items:
                    type: object
                    properties:
                      sales_order_line_id:
                        type: integer
                      quantity:
                        type: integer
              example:
                tracking_number: DROPSHIP-TRACK-001
                carrier: UPS
                shipped_at: '2024-01-20'
                lines:
                - sales_order_line_id: 300
                  quantity: 10
      parameters:
      - name: purchase_order
        in: path
        schema:
          type: integer
        required: true
        example: '101'
        description: The purchase order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      tracking_number:
                        type: string
                      status:
                        type: string
                example:
                  data:
                    id: 700
                    tracking_number: DROPSHIP-TRACK-001
                    status: shipped
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: purchase-orders:write
      operationId: post-api-purchase-orders-purchase-order-dropship
  /api/purchase-orders/awaiting-invoices:
    get:
      tags:
      - Purchase Orders
      summary: List Awaiting-Invoice POs
      description: "Paginated worklist of purchase orders still awaiting the supplier's\
        \ invoice — invoice_status in (uninvoiced, partially_invoiced) AND submission_status\
        \ in (submitted, finalized), not archived. Prepaid POs (a paid vendor deposit)\
        \ are the priority to chase. Each row projects amount_paid (sum of paid vendor\
        \ deposits) and age_days.\n\n:::info[Required scope: `purchase-orders:read`]\n\
        Grant this scope to your token under [Settings → Developer → Personal Access\
        \ Tokens](https://app.sku.io/settings/api).\n:::\n\nAuthentication: Requires\
        \ Bearer token.\n\n**Quick filters** (flat Spatie QueryBuilder params):\n\
        - filter[search] — search PO number, exact ID, or supplier name\n- filter[supplier_id]\
        \ — exact supplier id\n- filter[invoice_status] — exact: uninvoiced | partially_invoiced\n\
        - filter[prepaid_only] — true to only include POs with a paid vendor deposit\n\
        - filter[requested] — true = already requested (invoice_requested_at not null);\
        \ false = never requested\n\n**Advanced filters** (operator-aware, via GroupedFilterSupport).\
        \ Send either as a base64-encoded `filter_groups` tree (AND/OR conjunctions)\
        \ or as flat `filter[column.operator]=value` params. Filterable columns:\n\
        - purchase_order_number (text)\n- invoice_status (text)\n- supplier_name (text,\
        \ matches the related supplier's name)\n- total (numeric — maps to total_cost)\n\
        - purchase_order_date (date)\n- invoice_requested_at (datetime; use is_empty\
        \ / is_not_empty for never / already requested)\n- invoice_request_count (numeric)\n\
        \nText operators: contains, does_not_contain, is, is_not, is_one_of, is_not_one_of,\
        \ starts_with, does_not_start_with, ends_with, does_not_end_with, is_empty,\
        \ is_not_empty. Numeric operators: is, is_not, is_one_of, is_not_one_of, greater_than,\
        \ less_than, greater_than_or_equal, less_than_or_equal, between, is_empty,\
        \ is_not_empty. Datetime operators additionally include before/after and relative\
        \ shortcuts (today, yesterday, past_week, days_ago, between, etc.).\n\nfilter_groups\
        \ example (before base64-encoding):\n{\n  \"conjunction\": \"and\",\n  \"\
        children\": [\n    {\"type\": \"condition\", \"condition\": {\"column\": \"\
        invoice_status\", \"operator\": \"is\", \"value\": \"partially_invoiced\"\
        }},\n    {\"type\": \"condition\", \"condition\": {\"column\": \"total\",\
        \ \"operator\": \"greater_than\", \"value\": \"1000\"}}\n  ]\n}\n\n**Sorts:**\
        \ id, purchase_order_number, purchase_order_date, total_cost, amount_paid_total,\
        \ age_days, invoice_requested_at, invoice_request_count (prefix with - for\
        \ DESC). Default sort: purchase_order_date.\n\n**Pagination:** page, per_page\
        \ (default 15).\n\n**Filter update (tab rebuild):** supplier_id is now operator-aware\
        \ (supplier_id.is / .is_not / .is_one_of …) in addition to the flat filter[supplier_id];\
        \ prepaid_only and requested also accept the tree form prepaid_only.is / requested.is\
        \ (value true|false) so they work as FilterInput pills + saved views. Flat\
        \ forms still work."
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        purchase_order_number:
                          type: string
                        purchase_order_date:
                          type: string
                        age_days:
                          type: integer
                        supplier:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            email:
                              type: string
                        supplier_route:
                          type: string
                        po_route:
                          type: string
                        invoice_status:
                          type: string
                        currency_code:
                          type: string
                        total:
                          type: number
                        amount_paid:
                          type: number
                        is_prepaid:
                          type: boolean
                        invoice_requested_at:
                          type: string
                          nullable: true
                        invoice_request_count:
                          type: integer
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                  path:
                    type: string
                example:
                  data:
                  - id: 4521
                    purchase_order_number: PO-004521
                    purchase_order_date: '2025-10-21T00:00:00+00:00'
                    age_days: 255
                    supplier:
                      id: 12
                      name: Acme Supplier
                      email: ap@acme.example
                    supplier_route: /crm/suppliers/12
                    po_route: /orders/purchase-orders/4521
                    invoice_status: uninvoiced
                    currency_code: USD
                    total: 14202.88
                    amount_paid: 7101.44
                    is_prepaid: true
                    invoice_requested_at: null
                    invoice_request_count: 0
                  current_page: 1
                  last_page: 2
                  per_page: 15
                  total: 19
                  from: 1
                  to: 15
                  path: '{{protocol}}{{domain}}/api/purchase-orders/awaiting-invoices'
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: purchase-orders:read
      operationId: get-api-purchase-orders-awaiting-invoices
  /api/purchase-orders/{purchase_order}/request-invoice:
    post:
      tags:
      - Purchase Orders
      summary: Request Invoice (Single PO)
      description: 'Email the supplier requesting the outstanding invoice for a single
        purchase order, optionally attaching vendor-deposit documents (e.g. proof
        of the prepayment). The reply-to is set to the sending user. On success the
        PO is stamped: invoice_requested_at = now, invoice_request_count incremented,
        invoice_last_requested_by = current user.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Only allowed when the PO is still awaiting its invoice (invoice_status in
        uninvoiced/partially_invoiced AND submission_status in submitted/finalized)
        — otherwise returns 422.


        Authentication: Requires Bearer token.

        **Requires permission:** `purchase_orders.update`. Throttled: 60 requests/min.


        **Body fields:**

        - to (string, required) — recipient email

        - subject (string, required, max 255)

        - note (string, optional, max 2000) — appended to the email body

        - cc (array of emails, optional, max 10)

        - attachment_ids (array of ints, optional) — VendorDepositAttachment ids;
        each MUST belong to one of this PO''s deposits or the request is rejected
        (422)'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                to:
                  type: string
                subject:
                  type: string
                note:
                  type: string
                cc:
                  type: array
                  items:
                    type: string
                attachment_ids:
                  type: array
                  items:
                    type: integer
              example:
                to: ap@acme.example
                subject: Invoice request for PO-004521
                note: We show this order as prepaid but have not yet received your
                  invoice. Please send it at your earliest convenience.
                cc:
                - buyer@ourcompany.example
                attachment_ids:
                - 88
                - 91
      parameters:
      - name: purchase_order
        in: path
        schema:
          type: integer
        required: true
        description: Purchase Order ID
        example: '4521'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      purchase_order_number:
                        type: string
                      invoice_status:
                        type: string
                      submission_status:
                        type: string
                      invoice_requested_at:
                        type: string
                      invoice_request_count:
                        type: integer
                      supplier_id:
                        type: integer
                      currency_code:
                        type: string
                      total_cost:
                        type: number
                      total:
                        type: number
                example:
                  data:
                    id: 4521
                    purchase_order_number: PO-004521
                    invoice_status: uninvoiced
                    submission_status: submitted
                    invoice_requested_at: '2026-07-03T14:22:05+00:00'
                    invoice_request_count: 1
                    supplier_id: 12
                    currency_code: USD
                    total_cost: 14202.88
                    total: 14202.88
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: An invoice can only be requested for a submitted purchase
                    order that is still awaiting its invoice.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:write
      operationId: post-api-purchase-orders-purchase-order-request-invoice
  /api/purchase-orders/cash-flow-schedule:
    get:
      tags:
      - Purchase Orders
      summary: Get Purchase Order Cash Flow Schedule
      description: 'Get the purchasing cash-flow schedule — expected vendor payments
        derived from all open, non-archived purchase orders.


        :::info[Required scope: `purchase-orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Each expected payment row is built from the best available source, reported
        as `forecast_source`:

        - `scheduled` — the PO''s own payment-term deposit schedule (high confidence)

        - `inferred` — the supplier''s default payment-term schedule or default deposit
        percentage (medium confidence)

        - `heuristic` — a due date estimated from PO/shipment ETD or ETA

        - `unscheduled` — no schedule and no usable date; rows with a null `due_date`
        are always included regardless of the date window


        If a milestone already has a linked vendor deposit, the row amount reflects
        that deposit''s remaining open exposure and the deposit''s own due date takes
        precedence. Fully settled milestones are omitted.


        The response contains time buckets (by the chosen granularity), per-source
        sections with full rows, a per-source summary, and overall exposure totals
        including overdue and due-in-7/30-day figures.


        Read-only. Requires the `purchase-orders:read` token scope.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      date_from:
                        type: string
                      date_to:
                        type: string
                      granularity:
                        type: string
                      available_granularities:
                        type: array
                        items:
                          type: object
                          properties:
                            value:
                              type: string
                            label:
                              type: string
                      applied_forecast_sources:
                        type: array
                        items:
                          type: string
                      forecast_source_summary:
                        type: array
                        items:
                          type: object
                          properties:
                            key:
                              type: string
                            label:
                              type: string
                            color:
                              type: string
                            row_count:
                              type: integer
                            amount_in_tenant_currency:
                              type: integer
                      buckets:
                        type: array
                        items:
                          type: object
                          properties:
                            period_start:
                              type: string
                            period_label:
                              type: string
                            row_count:
                              type: integer
                            purchase_order_count:
                              type: integer
                            total_amount_in_tenant_currency:
                              type: integer
                            scheduled_amount_in_tenant_currency:
                              type: integer
                            inferred_amount_in_tenant_currency:
                              type: integer
                            heuristic_amount_in_tenant_currency:
                              type: integer
                            unscheduled_amount_in_tenant_currency:
                              type: integer
                      sections:
                        type: object
                        properties:
                          scheduled:
                            type: object
                            properties:
                              rows:
                                type: array
                                items:
                                  type: object
                                  properties:
                                    purchase_order_id:
                                      type: integer
                                    purchase_order_number:
                                      type: string
                                    supplier_id:
                                      type: integer
                                    supplier_name:
                                      type: string
                                    forecast_source:
                                      type: string
                                    forecast_source_label:
                                      type: string
                                    confidence:
                                      type: string
                                    confidence_label:
                                      type: string
                                    forecast_note:
                                      type: string
                                    payment_term_id:
                                      type: integer
                                    payment_term_name:
                                      type: string
                                    milestone_sequence:
                                      type: integer
                                    milestone_label:
                                      type: string
                                    settlement_type:
                                      type: string
                                    settlement_type_label:
                                      type: string
                                    trigger_event:
                                      type: string
                                    trigger_event_label:
                                      type: string
                                    basis_source_label:
                                      type: string
                                    shipment_id:
                                      type: string
                                      nullable: true
                                    shipment_reference:
                                      type: string
                                      nullable: true
                                    basis_date:
                                      type: string
                                    due_date:
                                      type: string
                                    amount_in_tenant_currency:
                                      type: integer
                                    linked_vendor_deposit_id:
                                      type: integer
                                    linked_vendor_deposit_number:
                                      type: string
                                    linked_vendor_deposit_status:
                                      type: string
                                    is_trigger_reached:
                                      type: boolean
                              row_count:
                                type: integer
                              purchase_order_count:
                                type: integer
                              amount_in_tenant_currency:
                                type: integer
                              dated_amount_in_tenant_currency:
                                type: integer
                              undated_amount_in_tenant_currency:
                                type: integer
                              overdue_amount_in_tenant_currency:
                                type: integer
                          inferred:
                            type: object
                            properties:
                              rows:
                                type: array
                              row_count:
                                type: integer
                              purchase_order_count:
                                type: integer
                              amount_in_tenant_currency:
                                type: integer
                              dated_amount_in_tenant_currency:
                                type: integer
                              undated_amount_in_tenant_currency:
                                type: integer
                              overdue_amount_in_tenant_currency:
                                type: integer
                          heuristic:
                            type: object
                            properties:
                              rows:
                                type: array
                              row_count:
                                type: integer
                              purchase_order_count:
                                type: integer
                              amount_in_tenant_currency:
                                type: integer
                              dated_amount_in_tenant_currency:
                                type: integer
                              undated_amount_in_tenant_currency:
                                type: integer
                              overdue_amount_in_tenant_currency:
                                type: integer
                          unscheduled:
                            type: object
                            properties:
                              rows:
                                type: array
                              row_count:
                                type: integer
                              purchase_order_count:
                                type: integer
                              amount_in_tenant_currency:
                                type: integer
                              dated_amount_in_tenant_currency:
                                type: integer
                              undated_amount_in_tenant_currency:
                                type: integer
                              overdue_amount_in_tenant_currency:
                                type: integer
                      summary:
                        type: object
                        properties:
                          total_rows:
                            type: integer
                          total_purchase_orders:
                            type: integer
                          total_exposure_in_tenant_currency:
                            type: integer
                          dated_exposure_in_tenant_currency:
                            type: integer
                          undated_exposure_in_tenant_currency:
                            type: integer
                          overdue_exposure_in_tenant_currency:
                            type: integer
                          due_next_7_days_in_tenant_currency:
                            type: integer
                          due_next_30_days_in_tenant_currency:
                            type: integer
                          bucket_count:
                            type: integer
                example:
                  data:
                    date_from: '2026-07-06'
                    date_to: '2027-01-06'
                    granularity: week
                    available_granularities:
                    - value: day
                      label: Day
                    - value: week
                      label: Week
                    - value: month
                      label: Month
                    applied_forecast_sources:
                    - scheduled
                    - inferred
                    - heuristic
                    - unscheduled
                    forecast_source_summary:
                    - key: scheduled
                      label: Scheduled
                      color: '#0f766e'
                      row_count: 4
                      amount_in_tenant_currency: 42500
                    - key: inferred
                      label: Supplier Default
                      color: '#1d4ed8'
                      row_count: 2
                      amount_in_tenant_currency: 9800
                    - key: heuristic
                      label: Heuristic
                      color: '#d97706'
                      row_count: 1
                      amount_in_tenant_currency: 15200
                    - key: unscheduled
                      label: Unscheduled
                      color: '#b91c1c'
                      row_count: 1
                      amount_in_tenant_currency: 3100
                    buckets:
                    - period_start: '2026-07-06'
                      period_label: Week of Jul 6, 2026
                      row_count: 2
                      purchase_order_count: 2
                      total_amount_in_tenant_currency: 21500
                      scheduled_amount_in_tenant_currency: 18400
                      inferred_amount_in_tenant_currency: 3100
                      heuristic_amount_in_tenant_currency: 0
                      unscheduled_amount_in_tenant_currency: 0
                    sections:
                      scheduled:
                        rows:
                        - purchase_order_id: 812
                          purchase_order_number: PO-00812
                          supplier_id: 44
                          supplier_name: Shenzhen Widgets Co
                          forecast_source: scheduled
                          forecast_source_label: Scheduled
                          confidence: high
                          confidence_label: High
                          forecast_note: Explicit PO payment schedule
                          payment_term_id: 6
                          payment_term_name: 30% Deposit / 70% on Shipment
                          milestone_sequence: 1
                          milestone_label: Production Deposit
                          settlement_type: vendor_deposit
                          settlement_type_label: Vendor Deposit
                          trigger_event: po_approved
                          trigger_event_label: PO Approved
                          basis_source_label: PO Approved
                          shipment_id: null
                          shipment_reference: null
                          basis_date: '2026-07-01'
                          due_date: '2026-07-08'
                          amount_in_tenant_currency: 12500
                          linked_vendor_deposit_id: 91
                          linked_vendor_deposit_number: VD-00091
                          linked_vendor_deposit_status: approved
                          is_trigger_reached: true
                        row_count: 4
                        purchase_order_count: 3
                        amount_in_tenant_currency: 42500
                        dated_amount_in_tenant_currency: 40000
                        undated_amount_in_tenant_currency: 2500
                        overdue_amount_in_tenant_currency: 5000
                      inferred:
                        rows: []
                        row_count: 0
                        purchase_order_count: 0
                        amount_in_tenant_currency: 0
                        dated_amount_in_tenant_currency: 0
                        undated_amount_in_tenant_currency: 0
                        overdue_amount_in_tenant_currency: 0
                      heuristic:
                        rows: []
                        row_count: 0
                        purchase_order_count: 0
                        amount_in_tenant_currency: 0
                        dated_amount_in_tenant_currency: 0
                        undated_amount_in_tenant_currency: 0
                        overdue_amount_in_tenant_currency: 0
                      unscheduled:
                        rows: []
                        row_count: 0
                        purchase_order_count: 0
                        amount_in_tenant_currency: 0
                        dated_amount_in_tenant_currency: 0
                        undated_amount_in_tenant_currency: 0
                        overdue_amount_in_tenant_currency: 0
                    summary:
                      total_rows: 8
                      total_purchase_orders: 5
                      total_exposure_in_tenant_currency: 70600
                      dated_exposure_in_tenant_currency: 67500
                      undated_exposure_in_tenant_currency: 3100
                      overdue_exposure_in_tenant_currency: 5000
                      due_next_7_days_in_tenant_currency: 21500
                      due_next_30_days_in_tenant_currency: 38900
                      bucket_count: 6
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      date_to:
                        type: array
                        items:
                          type: string
                example:
                  message: The date to field must be a date after or equal to date
                    from.
                  errors:
                    date_to:
                    - The date to field must be a date after or equal to date from.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: purchase-orders:read
      operationId: get-api-purchase-orders-cash-flow-schedule
  /api/purchase-orders/{purchase_order}/expected-vendor-deposit-milestones:
    get:
      tags:
      - Purchase Orders
      summary: List Expected Vendor Deposit Milestones
      description: 'List the expected payment milestones for a purchase order, derived
        from its payment-term deposit schedule.


        :::info[Required scope: `purchase-orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Returns one row per schedule line. Per-shipment lines fan out into one row
        per inbound shipment (key `line-{n}-shipment-{id}`), plus a `line-{n}-remainder`
        row for PO value not yet assigned to a shipment. If the payment term has no
        schedule, a single synthesized `Final Invoice Balance` milestone (key `synthesized-final-balance`)
        covers the un-deposited remainder.


        Each milestone''s `status` is one of:

        - `expected` — planned but the trigger event has not happened yet

        - `ready_to_create` — the trigger has been reached; the milestone can be turned
        into a vendor deposit

        - `created` — a vendor deposit is already linked (`linked_vendor_deposit_id`)

        - `out_of_sync` — the linked deposit no longer matches the schedule (amount,
        due date, trigger, or shipment changed); see `status_reasons`


        Use the `key` value with **Create Vendor Deposit from Milestone** to materialize
        a `ready_to_create` milestone.


        Read-only. Requires the `purchase-orders:read` token scope.'
      parameters:
      - name: purchase_order
        in: path
        schema:
          type: integer
        required: true
        description: Purchase order ID
        example: '812'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        key:
                          type: string
                        status:
                          type: string
                        status_label:
                          type: string
                        status_reason:
                          type: string
                        status_reasons:
                          type: array
                          items:
                            type: string
                        purchase_order_id:
                          type: integer
                        purchase_order_number:
                          type: string
                        supplier_id:
                          type: integer
                        supplier_name:
                          type: string
                        currency_id:
                          type: integer
                        currency_code:
                          type: string
                        line_index:
                          type: integer
                        shipment_id:
                          type: string
                          nullable: true
                        shipment_reference:
                          type: string
                          nullable: true
                        label:
                          type: string
                        amount_mode:
                          type: string
                        fixed_amount:
                          type: string
                          nullable: true
                        percentage:
                          type: integer
                        is_ownership_transfer:
                          type: boolean
                        settlement_type:
                          type: string
                        settlement_type_label:
                          type: string
                        creates_vendor_deposit:
                          type: boolean
                        trigger_event:
                          type: string
                        trigger_event_label:
                          type: string
                        offset_days:
                          type: integer
                        per_shipment:
                          type: boolean
                        shipment_date_basis:
                          type: string
                          nullable: true
                        forecast_source:
                          type: string
                        forecast_source_label:
                          type: string
                        is_synthesized:
                          type: boolean
                        expected_amount:
                          type: number
                        expected_amount_in_tenant_currency:
                          type: number
                        basis_date:
                          type: string
                        due_date:
                          type: string
                        is_trigger_reached:
                          type: boolean
                        is_ready_to_create:
                          type: boolean
                        linked_vendor_deposit_id:
                          type: integer
                        linked_vendor_deposit_number:
                          type: string
                        linked_vendor_deposit_status:
                          type: string
                        linked_vendor_deposit_status_label:
                          type: string
                        schedule_snapshot:
                          type: object
                          properties:
                            line_index:
                              type: integer
                            label:
                              type: string
                            amount_mode:
                              type: string
                            fixed_amount:
                              type: string
                              nullable: true
                            percentage:
                              type: integer
                            is_ownership_transfer:
                              type: boolean
                            settlement_type:
                              type: string
                            trigger_event:
                              type: string
                            offset_days:
                              type: integer
                            per_shipment:
                              type: boolean
                            shipment_date_basis:
                              type: string
                              nullable: true
                            shipment_id:
                              type: string
                              nullable: true
                            expected_amount:
                              type: number
                            due_date:
                              type: string
                        placeholder_reason:
                          type: string
                          nullable: true
                example:
                  data:
                  - key: line-1
                    status: created
                    status_label: Created
                    status_reason: A vendor deposit already exists for this schedule
                      milestone.
                    status_reasons:
                    - A vendor deposit already exists for this schedule milestone.
                    purchase_order_id: 812
                    purchase_order_number: PO-00812
                    supplier_id: 44
                    supplier_name: Shenzhen Widgets Co
                    currency_id: 2
                    currency_code: USD
                    line_index: 1
                    shipment_id: null
                    shipment_reference: null
                    label: Production Deposit
                    amount_mode: percent
                    fixed_amount: null
                    percentage: 30
                    is_ownership_transfer: false
                    settlement_type: vendor_deposit
                    settlement_type_label: Vendor Deposit
                    creates_vendor_deposit: true
                    trigger_event: po_approved
                    trigger_event_label: PO Approved
                    offset_days: 0
                    per_shipment: false
                    shipment_date_basis: null
                    forecast_source: actual_trigger_date
                    forecast_source_label: Actual trigger date — PO Approved
                    is_synthesized: false
                    expected_amount: 12499.95
                    expected_amount_in_tenant_currency: 12499.95
                    basis_date: '2026-07-01'
                    due_date: '2026-07-01'
                    is_trigger_reached: true
                    is_ready_to_create: false
                    linked_vendor_deposit_id: 91
                    linked_vendor_deposit_number: VD-00091
                    linked_vendor_deposit_status: approved
                    linked_vendor_deposit_status_label: Approved
                    schedule_snapshot:
                      line_index: 1
                      label: Production Deposit
                      amount_mode: percent
                      fixed_amount: null
                      percentage: 30
                      is_ownership_transfer: false
                      settlement_type: vendor_deposit
                      trigger_event: po_approved
                      offset_days: 0
                      per_shipment: false
                      shipment_date_basis: null
                      shipment_id: null
                      expected_amount: 12499.95
                      due_date: '2026-07-01'
                    placeholder_reason: null
                  - key: line-2-shipment-345
                    status: ready_to_create
                    status_label: Ready to Create
                    status_reason: The schedule trigger has been reached and this
                      milestone can now be turned into a vendor deposit document.
                    status_reasons:
                    - The schedule trigger has been reached and this milestone can
                      now be turned into a vendor deposit document.
                    purchase_order_id: 812
                    purchase_order_number: PO-00812
                    supplier_id: 44
                    supplier_name: Shenzhen Widgets Co
                    currency_id: 2
                    currency_code: USD
                    line_index: 2
                    shipment_id: 345
                    shipment_reference: 'Shipment #345'
                    label: Balance on Dispatch
                    amount_mode: percent
                    fixed_amount: null
                    percentage: 70
                    is_ownership_transfer: false
                    settlement_type: vendor_deposit
                    settlement_type_label: Vendor Deposit
                    creates_vendor_deposit: true
                    trigger_event: po_shipped
                    trigger_event_label: PO First Shipment
                    offset_days: 0
                    per_shipment: true
                    shipment_date_basis: dispatched
                    forecast_source: actual_trigger_date
                    forecast_source_label: Actual trigger date — PO First Shipment
                    is_synthesized: false
                    expected_amount: 29166.55
                    expected_amount_in_tenant_currency: 29166.55
                    basis_date: '2026-07-04'
                    due_date: '2026-07-04'
                    is_trigger_reached: true
                    is_ready_to_create: true
                    linked_vendor_deposit_id: null
                    linked_vendor_deposit_number: null
                    linked_vendor_deposit_status: null
                    linked_vendor_deposit_status_label: null
                    schedule_snapshot:
                      line_index: 2
                      label: Balance on Dispatch
                      amount_mode: percent
                      fixed_amount: null
                      percentage: 70
                      is_ownership_transfer: false
                      settlement_type: vendor_deposit
                      trigger_event: po_shipped
                      offset_days: 0
                      per_shipment: true
                      shipment_date_basis: dispatched
                      shipment_id: 345
                      expected_amount: 29166.55
                      due_date: '2026-07-04'
                    placeholder_reason: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:read
      operationId: get-api-purchase-orders-purchase-order-expected-vendor-deposit-milestones
  /api/purchase-orders/{purchase_order}/expected-vendor-deposit-milestones/{milestoneKey}/create-deposit:
    post:
      tags:
      - Purchase Orders
      summary: Create Vendor Deposit from Milestone
      description: 'Create a draft vendor deposit from a payment-term schedule milestone.
        No request body — the milestone key (from **List Expected Vendor Deposit Milestones**)
        fully identifies the action.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Only milestones with `is_ready_to_create: true` and `settlement_type: vendor_deposit`
        can be materialized. The created deposit:

        - starts in `draft` status with an auto-assigned number (e.g. `VD-00092`)

        - copies supplier, currency, and rate from the purchase order

        - takes its amount and due date from the milestone, and records the schedule
        line and shipment it came from

        - does not post any accounting entries while in draft


        The call is idempotent against races — if a deposit already exists for the
        same schedule line and shipment, that deposit is returned instead of creating
        a duplicate.


        Errors:

        - 404 — unknown milestone key for this purchase order

        - 422 — the milestone already has a linked vendor deposit

        - 422 — the milestone''s trigger event has not happened yet


        Synchronous — no background processing. Requires the `purchase-orders:write`
        token scope and permission to update purchase orders.'
      requestBody:
        content: {}
      parameters:
      - name: purchase_order
        in: path
        schema:
          type: integer
        required: true
        description: Purchase order ID
        example: '812'
      - name: milestoneKey
        in: path
        schema:
          type: string
        required: true
        description: Milestone key from List Expected Vendor Deposit Milestones, e.g.
          line-1 or line-2-shipment-345
        example: line-2-shipment-345
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: integer
                  deposit_number:
                    type: string
                  status:
                    type: string
                  status_label:
                    type: string
                  supplier_id:
                    type: integer
                  supplier:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      email:
                        type: string
                      wire_instructions:
                        type: string
                      link_route:
                        type: string
                  purchase_order_id:
                    type: integer
                  payment_term_schedule_line_index:
                    type: integer
                  inbound_shipment_id:
                    type: integer
                  payment_term_schedule_snapshot:
                    type: object
                    properties:
                      line_index:
                        type: integer
                      label:
                        type: string
                      amount_mode:
                        type: string
                      fixed_amount:
                        type: string
                        nullable: true
                      percentage:
                        type: integer
                      is_ownership_transfer:
                        type: boolean
                      settlement_type:
                        type: string
                      trigger_event:
                        type: string
                      offset_days:
                        type: integer
                      per_shipment:
                        type: boolean
                      shipment_date_basis:
                        type: string
                      shipment_id:
                        type: integer
                      expected_amount:
                        type: number
                      due_date:
                        type: string
                  is_ownership_transfer:
                    type: boolean
                  ownership_transferred_at:
                    type: string
                    nullable: true
                  purchase_order:
                    type: object
                    properties:
                      id:
                        type: integer
                      purchase_order_number:
                        type: string
                      link_route:
                        type: string
                      link_reference:
                        type: string
                  currency_id:
                    type: integer
                  currency:
                    type: object
                    properties:
                      id:
                        type: integer
                      code:
                        type: string
                      symbol:
                        type: string
                  currency_rate:
                    type: integer
                  tenant_currency:
                    type: object
                    properties:
                      id:
                        type: integer
                      code:
                        type: string
                      symbol:
                        type: string
                  amount:
                    type: number
                  amount_in_tenant_currency:
                    type: number
                  amount_paid:
                    type: integer
                  amount_applied:
                    type: integer
                  amount_refunded:
                    type: integer
                  amount_written_off:
                    type: integer
                  available_balance:
                    type: integer
                  tax_amount:
                    type: integer
                  tax_lines:
                    type: string
                    nullable: true
                  deposit_date:
                    type: string
                  due_date:
                    type: string
                  paid_at:
                    type: string
                    nullable: true
                  external_reference:
                    type: string
                    nullable: true
                  payee_bank_details:
                    type: string
                    nullable: true
                  payment_requested_at:
                    type: string
                    nullable: true
                  remittance_sent_at:
                    type: string
                    nullable: true
                  notes:
                    type: string
                  proportional_apply_enabled:
                    type: boolean
                  auto_apply_enabled:
                    type: string
                    nullable: true
                  auto_apply_effective:
                    type: boolean
                  approved_by:
                    type: string
                    nullable: true
                  approved_at:
                    type: string
                    nullable: true
                  approval_notes:
                    type: string
                    nullable: true
                  submit_action:
                    type: string
                  submit_action_label:
                    type: string
                  applications:
                    type: array
                  payments:
                    type: array
                  refunds:
                    type: array
                  created_at:
                    type: string
                  updated_at:
                    type: string
                  archived_at:
                    type: string
                    nullable: true
                example:
                  id: 92
                  deposit_number: VD-00092
                  status: draft
                  status_label: Draft
                  supplier_id: 44
                  supplier:
                    id: 44
                    name: Shenzhen Widgets Co
                    email: orders@szwidgets.example
                    wire_instructions: Bank of China — SWIFT BKCHCNBJ — Acct 1234567890
                    link_route: /v2/crm/suppliers/44
                  purchase_order_id: 812
                  payment_term_schedule_line_index: 2
                  inbound_shipment_id: 345
                  payment_term_schedule_snapshot:
                    line_index: 2
                    label: Balance on Dispatch
                    amount_mode: percent
                    fixed_amount: null
                    percentage: 70
                    is_ownership_transfer: false
                    settlement_type: vendor_deposit
                    trigger_event: po_shipped
                    offset_days: 0
                    per_shipment: true
                    shipment_date_basis: dispatched
                    shipment_id: 345
                    expected_amount: 29166.55
                    due_date: '2026-07-04'
                  is_ownership_transfer: false
                  ownership_transferred_at: null
                  purchase_order:
                    id: 812
                    purchase_order_number: PO-00812
                    link_route: /v2/orders/purchase-orders/812
                    link_reference: PO-00812
                  currency_id: 2
                  currency:
                    id: 2
                    code: USD
                    symbol: $
                  currency_rate: 1
                  tenant_currency:
                    id: 2
                    code: USD
                    symbol: $
                  amount: 29166.55
                  amount_in_tenant_currency: 29166.55
                  amount_paid: 0
                  amount_applied: 0
                  amount_refunded: 0
                  amount_written_off: 0
                  available_balance: 0
                  tax_amount: 0
                  tax_lines: null
                  deposit_date: '2026-07-06'
                  due_date: '2026-07-04'
                  paid_at: null
                  external_reference: null
                  payee_bank_details: null
                  payment_requested_at: null
                  remittance_sent_at: null
                  notes: 'Created from payment term schedule milestone: Balance on
                    Dispatch'
                  proportional_apply_enabled: false
                  auto_apply_enabled: null
                  auto_apply_effective: true
                  approved_by: null
                  approved_at: null
                  approval_notes: null
                  submit_action: approve
                  submit_action_label: Approve Deposit
                  applications: []
                  payments: []
                  refunds: []
                  created_at: '2026-07-06T09:14:22+00:00'
                  updated_at: '2026-07-06T09:14:22+00:00'
                  archived_at: null
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: Expected vendor deposit milestone not found.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: This milestone is planned by the payment term but its trigger
                    event has not happened yet.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: purchase-orders:write
      operationId: post-api-purchase-orders-purchase-order-expected-vendor-deposit-milestones-milestonekey-create-deposit
  /api/purchase-orders/{purchaseOrder}/return-metrics:
    get:
      tags:
      - Purchase Orders
      summary: Get Purchase Order Return Metrics
      description: 'Get the annualized return (Annualized ROI / IRR) for a purchase
        order.


        Models the purchase as a dated cash-flow series — vendor deposit and balance
        payments out, then net sales proceeds in as the received units sell through,
        plus any remaining stock valued at cost as of today — and solves the money-weighted
        annualized rate (XIRR).


        Two variants are returned: `product` (purchase payments and sales proceeds
        only) and `fully_loaded` (also charges allocated time-based cost entries).
        Each variant includes the rate, cash multiple (moic), days held, realized
        fraction, profit, an NPV at the tenant hurdle rate, a maturity `status` (provisional,
        interim, final, or nm), presentation caveats, and the full signed cash-flow
        series.


        Requires a Bearer token.


        Each variant includes a `disposition` breakdown accounting for every received
        unit — bucketed into sold (direct / after transfer or kitting), still-owned
        (on hand / held elsewhere), and lost (written off / stock-taken) — so the
        sell-through figure is fully reconciled to units received.'
      parameters:
      - name: purchaseOrder
        in: path
        schema:
          type: integer
        required: true
        description: Purchase order ID
        example: '1042'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      purchase_order_id:
                        type: integer
                      default_variant:
                        type: string
                      variants:
                        type: object
                        properties:
                          product:
                            type: object
                            properties:
                              variant:
                                type: string
                              variant_label:
                                type: string
                              status:
                                type: string
                              status_label:
                                type: string
                              is_rankable:
                                type: boolean
                              is_interim:
                                type: boolean
                              is_provisional:
                                type: boolean
                              is_nm:
                                type: boolean
                              is_short_hold:
                                type: boolean
                              xirr:
                                type: number
                              period_return:
                                type: number
                              headline_metric:
                                type: string
                              annualized_display_capped:
                                type: boolean
                              annualized_display_cap:
                                type: integer
                              moic:
                                type: number
                              days_held:
                                type: integer
                              pct_realized:
                                type: number
                              realized_xirr:
                                type: number
                              total_cash_out:
                                type: integer
                              total_cash_in:
                                type: integer
                              profit:
                                type: integer
                              npv_at_hurdle:
                                type: number
                              has_estimated_outflows:
                                type: boolean
                              caveats:
                                type: array
                                items:
                                  type: string
                              cash_flows:
                                type: array
                                items:
                                  type: object
                                  properties:
                                    date:
                                      type: string
                                    amount:
                                      type: integer
                                    type:
                                      type: string
                                    label:
                                      type: string
                                    source_type:
                                      type: string
                                    source_type_label:
                                      type: string
                                    source_id:
                                      type: integer
                                    source_route:
                                      type: string
                                      nullable: true
                              disposition:
                                type: object
                                properties:
                                  units_bought:
                                    type: integer
                                  buckets:
                                    type: array
                                    items:
                                      type: object
                                      properties:
                                        key:
                                          type: string
                                        label:
                                          type: string
                                        group:
                                          type: string
                                        units:
                                          type: integer
                              as_of_date:
                                type: string
                              computed_at:
                                type: string
                          fully_loaded:
                            type: object
                            properties:
                              variant:
                                type: string
                              variant_label:
                                type: string
                              status:
                                type: string
                              status_label:
                                type: string
                              is_rankable:
                                type: boolean
                              is_interim:
                                type: boolean
                              is_provisional:
                                type: boolean
                              is_nm:
                                type: boolean
                              is_short_hold:
                                type: boolean
                              xirr:
                                type: number
                              period_return:
                                type: number
                              headline_metric:
                                type: string
                              annualized_display_capped:
                                type: boolean
                              annualized_display_cap:
                                type: integer
                              moic:
                                type: number
                              days_held:
                                type: integer
                              pct_realized:
                                type: number
                              realized_xirr:
                                type: number
                              total_cash_out:
                                type: integer
                              total_cash_in:
                                type: integer
                              profit:
                                type: integer
                              npv_at_hurdle:
                                type: number
                              has_estimated_outflows:
                                type: boolean
                              caveats:
                                type: array
                                items:
                                  type: string
                              cash_flows:
                                type: array
                                items:
                                  type: object
                                  properties:
                                    date:
                                      type: string
                                    amount:
                                      type: integer
                                    type:
                                      type: string
                                    label:
                                      type: string
                                    source_type:
                                      type: string
                                    source_type_label:
                                      type: string
                                    source_id:
                                      type: integer
                                    source_route:
                                      type: string
                                      nullable: true
                              disposition:
                                type: object
                                properties:
                                  units_bought:
                                    type: integer
                                  buckets:
                                    type: array
                                    items:
                                      type: object
                                      properties:
                                        key:
                                          type: string
                                        label:
                                          type: string
                                        group:
                                          type: string
                                        units:
                                          type: integer
                              as_of_date:
                                type: string
                              computed_at:
                                type: string
                example:
                  data:
                    purchase_order_id: 1042
                    default_variant: product
                    variants:
                      product:
                        variant: product
                        variant_label: Product
                        status: interim
                        status_label: Interim
                        is_rankable: true
                        is_interim: true
                        is_provisional: false
                        is_nm: false
                        is_short_hold: false
                        xirr: 1.3421
                        period_return: 0.7834
                        headline_metric: xirr
                        annualized_display_capped: false
                        annualized_display_cap: 2
                        moic: 1.85
                        days_held: 212
                        pct_realized: 0.78
                        realized_xirr: 1.1032
                        total_cash_out: 8000
                        total_cash_in: 14800
                        profit: 6800
                        npv_at_hurdle: 4120.55
                        has_estimated_outflows: false
                        caveats:
                        - Interim — includes remaining stock valued at cost as of
                          today.
                        cash_flows:
                        - date: '2026-03-01'
                          amount: -2400
                          type: deposit
                          label: Vendor deposit
                          source_type: App\Models\VendorDeposit
                          source_type_label: Vendor Deposit
                          source_id: 331
                          source_route: null
                        - date: '2026-04-15'
                          amount: -5600
                          type: balance_payment
                          label: Bill payment
                          source_type: App\Models\Bill
                          source_type_label: Bill
                          source_id: 883
                          source_route: /accounting/bills/883
                        - date: '2026-06-02'
                          amount: 1180
                          type: sale
                          label: Sale of 14 unit(s)
                          source_type: App\Models\SalesOrderLine
                          source_type_label: Sales Order Line
                          source_id: 5521
                          source_route: null
                        - date: '2026-07-17'
                          amount: 1760
                          type: terminal_value
                          label: Remaining stock at cost
                          source_type: App\Models\PurchaseOrder
                          source_type_label: Purchase Order
                          source_id: 1042
                          source_route: /orders/purchase-orders/1042
                        disposition:
                          units_bought: 500
                          buckets:
                          - key: sold_direct
                            label: Sold directly
                            group: sold
                            units: 360
                          - key: sold_downstream
                            label: Sold after transfer / kitting
                            group: sold
                            units: 55
                          - key: on_hand
                            label: On hand (unsold)
                            group: held
                            units: 40
                          - key: written_off
                            label: Written off / adjusted
                            group: lost
                            units: 30
                          - key: lost_downstream
                            label: Lost downstream (write-off / stock-take)
                            group: lost
                            units: 15
                        as_of_date: '2026-07-17'
                        computed_at: '2026-07-17T03:15:00+00:00'
                      fully_loaded:
                        variant: fully_loaded
                        variant_label: Fully-loaded
                        status: interim
                        status_label: Interim
                        is_rankable: true
                        is_interim: true
                        is_provisional: false
                        is_nm: false
                        is_short_hold: false
                        xirr: 1.1105
                        period_return: 0.6521
                        headline_metric: xirr
                        annualized_display_capped: false
                        annualized_display_cap: 2
                        moic: 1.71
                        days_held: 212
                        pct_realized: 0.78
                        realized_xirr: 1.1032
                        total_cash_out: 8000
                        total_cash_in: 13680
                        profit: 5680
                        npv_at_hurdle: 3210.4
                        has_estimated_outflows: false
                        caveats:
                        - Interim — includes remaining stock valued at cost as of
                          today.
                        cash_flows:
                        - date: '2026-03-01'
                          amount: -2400
                          type: deposit
                          label: Vendor deposit
                          source_type: App\Models\VendorDeposit
                          source_type_label: Vendor Deposit
                          source_id: 331
                          source_route: null
                        - date: '2026-04-15'
                          amount: -5600
                          type: balance_payment
                          label: Bill payment
                          source_type: App\Models\Bill
                          source_type_label: Bill
                          source_id: 883
                          source_route: /accounting/bills/883
                        - date: '2026-06-02'
                          amount: 1180
                          type: sale
                          label: Sale of 14 unit(s)
                          source_type: App\Models\SalesOrderLine
                          source_type_label: Sales Order Line
                          source_id: 5521
                          source_route: null
                        - date: '2026-07-17'
                          amount: 1760
                          type: terminal_value
                          label: Remaining stock at cost
                          source_type: App\Models\PurchaseOrder
                          source_type_label: Purchase Order
                          source_id: 1042
                          source_route: /orders/purchase-orders/1042
                        disposition:
                          units_bought: 500
                          buckets:
                          - key: sold_direct
                            label: Sold directly
                            group: sold
                            units: 360
                          - key: sold_downstream
                            label: Sold after transfer / kitting
                            group: sold
                            units: 55
                          - key: on_hand
                            label: On hand (unsold)
                            group: held
                            units: 40
                          - key: written_off
                            label: Written off / adjusted
                            group: lost
                            units: 30
                          - key: lost_downstream
                            label: Lost downstream (write-off / stock-take)
                            group: lost
                            units: 15
                        as_of_date: '2026-07-17'
                        computed_at: '2026-07-17T03:15:00+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-purchase-orders-purchaseorder-return-metrics
  /api/purchase-orders/{purchaseOrder}/consignment/settlement-preview:
    get:
      tags:
      - Purchase Orders
      summary: Get Consignment Settlement Preview
      description: 'For a consignment purchase order, list each line''s consigned
        stock that has sold but has not yet been settled with the supplier, priced
        at the consignment cost. Lines with nothing left to settle are omitted.


        Authentication: Requires a Bearer token.'
      parameters:
      - name: purchaseOrder
        in: path
        schema:
          type: integer
        required: true
        description: Purchase order ID
        example: '123'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        purchase_order_line_id:
                          type: integer
                        sku:
                          type: string
                        sold_quantity:
                          type: integer
                        settled_quantity:
                          type: integer
                        sold_unsettled_quantity:
                          type: integer
                        unit_cost:
                          type: integer
                        amount:
                          type: integer
                example:
                  data:
                  - purchase_order_line_id: 5501
                    sku: WIDGET-1
                    sold_quantity: 12
                    settled_quantity: 0
                    sold_unsettled_quantity: 12
                    unit_cost: 4
                    amount: 48
                  - purchase_order_line_id: 5502
                    sku: WIDGET-2
                    sold_quantity: 5
                    settled_quantity: 0
                    sold_unsettled_quantity: 5
                    unit_cost: 6.5
                    amount: 32.5
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-purchase-orders-purchaseorder-consignment-settlement-preview
  /api/purchase-orders/{purchaseOrder}/consignment/settlements:
    post:
      tags:
      - Purchase Orders
      summary: Create Consignment Settlement
      description: 'Generate a settlement bill for a consignment purchase order, covering
        the consigned stock that has sold but not yet been settled. The bill is created
        for the supplier and the purchase order stays open so further sales can be
        settled later.


        Request body (all optional):

        - settlement_date (date): the report/settlement date. Defaults to today.

        - line_quantities (object): map of purchase order line ID to the quantity
        to settle for that line. Each value is clamped to what is still unsettled.
        Omit to settle every sold-but-unsettled unit.


        Returns 422 when the purchase order is not a consignment order, or when there
        is nothing left to settle.


        Authentication: Requires a Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                settlement_date:
                  type: string
                line_quantities:
                  type: object
                  properties:
                    '5501':
                      type: integer
                    '5502':
                      type: integer
              example:
                settlement_date: '2026-07-08'
                line_quantities:
                  '5501': 12
                  '5502': 5
      parameters:
      - name: purchaseOrder
        in: path
        schema:
          type: integer
        required: true
        description: Purchase order ID
        example: '123'
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: integer
                  purchase_order_id:
                    type: integer
                  purchase_order_number:
                    type: string
                  supplier_invoice_number:
                    type: string
                  supplier_id:
                    type: integer
                  supplier_name:
                    type: string
                  purchase_invoice_date:
                    type: string
                  due_date:
                    type: string
                  status:
                    type: string
                  is_consignment_settlement:
                    type: boolean
                  purchase_invoice_lines:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        purchase_order_line_id:
                          type: integer
                        quantity_invoiced:
                          type: integer
                        unit_price:
                          type: integer
                example:
                  id: 9001
                  purchase_order_id: 123
                  purchase_order_number: PO-10432
                  supplier_invoice_number: CONSIGN-PO-10432-20260708-1
                  supplier_id: 44
                  supplier_name: Acme Wholesale
                  purchase_invoice_date: '2026-07-08'
                  due_date: '2026-08-07'
                  status: unpaid
                  is_consignment_settlement: true
                  purchase_invoice_lines:
                  - id: 71001
                    purchase_order_line_id: 5501
                    quantity_invoiced: 12
                    unit_price: 4
                  - id: 71002
                    purchase_order_line_id: 5502
                    quantity_invoiced: 5
                    unit_price: 6.5
        '422':
          description: Unprocessable Content
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Nothing to settle — no sold consigned units are outstanding.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-purchase-orders-purchaseorder-consignment-settlements
  /api/purchase-orders/{purchaseOrder}/consignment/returns:
    post:
      tags:
      - Purchase Orders
      summary: Return Unsold Consigned Stock
      description: 'Return unsold consigned stock to the supplier for a consignment
        purchase order. This removes the returned units from sellable stock; it creates
        no bill and no credit, because unsold consigned stock was never owed for.
        Returning stock also updates the purchase order''s consignment settlement
        status, and a purchase order whose stock is now entirely sold-and-settled
        or returned is automatically closed.


        Request body (all optional):

        - line_quantities (object): map of purchase order line ID to the quantity
        to return for that line. Each value is clamped to the units still unsold on
        hand. Omit to return every unsold unit across all lines.


        Returns 422 when the purchase order is not a consignment order.


        Authentication: Requires a Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                line_quantities:
                  type: object
                  properties:
                    '5501':
                      type: integer
              example:
                line_quantities:
                  '5501': 3
      parameters:
      - name: purchaseOrder
        in: path
        schema:
          type: integer
        required: true
        description: Purchase order ID
        example: '123'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        purchase_order_line_id:
                          type: integer
                        returned:
                          type: integer
                  consignment_status:
                    type: string
                example:
                  data:
                  - purchase_order_line_id: 5501
                    returned: 3
                  consignment_status: fully_settled
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-purchase-orders-purchaseorder-consignment-returns
  /api/consignment/settlements/{settlement}/share:
    post:
      tags:
      - Purchase Orders
      summary: Share Consignment Settlement Report
      description: 'Share a consignment settlement''s Account Sales Report with the
        supplier. The report is term-aware — it states how much is owed and when it
        is due, derived from the consignment payment term on the purchase order.


        Request body:

        - channel (required): how to share — email, portal, or both.

        - recipient_email (optional): the address to email the report to. When omitted,
        the supplier''s own contact email is used. Ignored when channel is portal.


        A public, unauthenticated portal link is always returned so it can be copied
        and shared directly. The portal page shows the supplier the amount owed, the
        due date, the line items that sold, and the payment terms.


        Authentication: Requires a Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                channel:
                  type: string
                recipient_email:
                  type: string
              example:
                channel: both
                recipient_email: ap@supplier.com
      parameters:
      - name: settlement
        in: path
        schema:
          type: integer
        required: true
        description: Consignment settlement bill (purchase invoice) ID
        example: '9001'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  portal_url:
                    type: string
                  emailed:
                    type: boolean
                  recipient:
                    type: string
                  report:
                    type: object
                    properties:
                      supplier_name:
                        type: string
                      purchase_order_number:
                        type: string
                      settlement_reference:
                        type: string
                      report_date:
                        type: string
                      due_date:
                        type: string
                      currency_code:
                        type: string
                      lines:
                        type: array
                        items:
                          type: object
                          properties:
                            sku:
                              type: string
                            product_name:
                              type: string
                            quantity:
                              type: integer
                            unit_price:
                              type: integer
                            amount:
                              type: integer
                      total_units:
                        type: integer
                      amount_owed:
                        type: integer
                      payment_term:
                        type: object
                        properties:
                          name:
                            type: string
                          settlement_frequency:
                            type: string
                          net_days:
                            type: integer
                          summary:
                            type: string
                example:
                  portal_url: https://acme.example.com/consignment-report/hULzoBcZJh1nlGzqx3Rgp732pEfWwXfZKZ9huJ12S9W
                  emailed: true
                  recipient: ap@supplier.com
                  report:
                    supplier_name: Acme Wholesale Co.
                    purchase_order_number: PO-CONSIGN-1001
                    settlement_reference: CONSIGN-PO-CONSIGN-1001-20260709-1
                    report_date: '2026-07-09'
                    due_date: '2026-08-08'
                    currency_code: USD
                    lines:
                    - sku: WIDGET-BLUE
                      product_name: Blue Widget
                      quantity: 15
                      unit_price: 4
                      amount: 60
                    total_units: 15
                    amount_owed: 60
                    payment_term:
                      name: Consignment — Monthly, Net 30
                      settlement_frequency: Monthly
                      net_days: 30
                      summary: Consignment — Monthly, Net 30, payment due 30 days
                        after this report
        '422':
          description: Unprocessable Content
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: This bill is not a consignment settlement.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-consignment-settlements-settlement-share
  /api/consignment/suppliers/{supplier}/statement:
    get:
      tags:
      - Purchase Orders
      summary: Get Consignment Statement of Account
      description: 'A rolling balance-forward statement of account for a supplier''s
        consignment settlements: opening balance, each settlement with amount / paid
        / outstanding and a running balance, and the closing balance. The summary
        also reports the consignment liability that has accrued from sales but has
        not yet been settled.


        Optionally window the statement with date_from / date_to (m/d/Y or Y-m-d):
        settlements before date_from roll into the opening balance; settlements after
        date_to are excluded.


        Authentication: Requires a Bearer token.'
      parameters:
      - name: supplier
        in: path
        schema:
          type: integer
        required: true
        description: Supplier ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  supplier_id:
                    type: integer
                  supplier_name:
                    type: string
                  currency_code:
                    type: string
                  date_from:
                    type: string
                    nullable: true
                  date_to:
                    type: string
                    nullable: true
                  opening_balance:
                    type: integer
                  closing_balance:
                    type: integer
                  lines:
                    type: array
                    items:
                      type: object
                      properties:
                        settlement_id:
                          type: integer
                        date:
                          type: string
                        due_date:
                          type: string
                        reference:
                          type: string
                        purchase_order_id:
                          type: integer
                        purchase_order_number:
                          type: string
                        amount:
                          type: integer
                        paid:
                          type: integer
                        outstanding:
                          type: integer
                        running_balance:
                          type: integer
                        status:
                          type: string
                  summary:
                    type: object
                    properties:
                      settlement_count:
                        type: integer
                      total_settled:
                        type: integer
                      total_paid:
                        type: integer
                      total_outstanding:
                        type: integer
                      accrued_unsettled:
                        type: integer
                example:
                  supplier_id: 42
                  supplier_name: Acme Wholesale Co.
                  currency_code: USD
                  date_from: null
                  date_to: null
                  opening_balance: 0
                  closing_balance: 60
                  lines:
                  - settlement_id: 9001
                    date: '2026-01-15'
                    due_date: '2026-02-14'
                    reference: CONSIGN-PO-CONSIGN-1001-20260115-1
                    purchase_order_id: 1001
                    purchase_order_number: PO-CONSIGN-1001
                    amount: 40
                    paid: 10
                    outstanding: 30
                    running_balance: 30
                    status: partially_paid
                  - settlement_id: 9014
                    date: '2026-02-15'
                    due_date: '2026-03-17'
                    reference: CONSIGN-PO-CONSIGN-1001-20260215-1
                    purchase_order_id: 1001
                    purchase_order_number: PO-CONSIGN-1001
                    amount: 30
                    paid: 0
                    outstanding: 30
                    running_balance: 60
                    status: unpaid
                  summary:
                    settlement_count: 2
                    total_settled: 70
                    total_paid: 10
                    total_outstanding: 60
                    accrued_unsettled: 45
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-consignment-suppliers-supplier-statement
  /api/consignment/settings:
    get:
      tags:
      - Purchase Orders
      summary: Get Consignment Aging Settings
      description: 'The consignment aging-alert configuration: whether aging alerts
        are sent, the age (in days on consignment) at which unsold consigned stock
        is flagged, and whether flagged stock is automatically returned to the supplier.


        Authentication: Requires a Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  aging_alerts_enabled:
                    type: boolean
                  aging_threshold_days:
                    type: integer
                  aging_auto_return_enabled:
                    type: boolean
                example:
                  aging_alerts_enabled: true
                  aging_threshold_days: 90
                  aging_auto_return_enabled: false
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-consignment-settings
    put:
      tags:
      - Purchase Orders
      summary: Update Consignment Aging Settings
      description: 'Update the consignment aging-alert configuration. All fields are
        optional; only the provided fields are changed.


        Fields:

        - aging_alerts_enabled (boolean): send aging alerts when consigned stock ages
        past the threshold.

        - aging_threshold_days (integer, 1-3650): age in days on consignment at which
        unsold stock is flagged.

        - aging_auto_return_enabled (boolean): automatically return flagged stock
        to the supplier. Off by default — returning consigned stock is irreversible.


        Authentication: Requires a Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                aging_alerts_enabled:
                  type: boolean
                aging_threshold_days:
                  type: integer
                aging_auto_return_enabled:
                  type: boolean
              example:
                aging_alerts_enabled: true
                aging_threshold_days: 120
                aging_auto_return_enabled: false
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  aging_alerts_enabled:
                    type: boolean
                  aging_threshold_days:
                    type: integer
                  aging_auto_return_enabled:
                    type: boolean
                example:
                  aging_alerts_enabled: true
                  aging_threshold_days: 120
                  aging_auto_return_enabled: false
        '422':
          description: Unprocessable Content
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      aging_threshold_days:
                        type: array
                        items:
                          type: string
                example:
                  message: The aging threshold must be at least 1 day.
                  errors:
                    aging_threshold_days:
                    - The aging threshold must be at least 1 day.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: put-api-consignment-settings
  /api/purchase-orders/{purchase_order}/snapshots:
    get:
      tags:
      - Purchase Orders
      summary: List Purchase Order Revisions
      description: 'List the immutable revision snapshots captured for a purchase
        order, newest first. A snapshot is recorded every time the order is sent to
        the supplier, so this is the complete send history of the order.


        Each snapshot preserves exactly what the supplier received at that revision
        — the line quantities and costs, the order totals, a content hash of the sent
        document, who sent it and when — together with the current acknowledgement
        status of that revision.


        Path params:

        - `purchase_order` (required): id of the purchase order.


        Response: a collection under `data`. Each item includes `revision_number`,
        `reason`, `submission_format`, `sent_to_email`, `sent_by_name`, `sent_at`,
        `acknowledgement_status` (one of `pending`, `acknowledged`, `changes_requested`,
        `rejected`, `superseded`), `acknowledged_at`, `document_hash`, `total_quantity`
        and `total_cost`.


        Authentication: Requires Bearer token.


        **Requires permission:** `purchase_orders.view`'
      parameters:
      - name: purchase_order
        in: path
        schema:
          type: integer
        required: true
        example: '739'
        description: The purchase order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        purchase_order_id:
                          type: integer
                        revision_number:
                          type: integer
                        reason:
                          type: string
                        submission_format:
                          type: string
                        sent_to_email:
                          type: string
                        sent_by_name:
                          type: string
                        sent_at:
                          type: string
                        acknowledgement_status:
                          type: string
                        acknowledged_at:
                          type: string
                        document_hash:
                          type: string
                        total_quantity:
                          type: integer
                        total_cost:
                          type: number
                example:
                  data:
                  - id: 12
                    purchase_order_id: 739
                    revision_number: 2
                    reason: Corrected qty per supplier
                    submission_format: email_pdf_attachment
                    sent_to_email: supplier@acme.com
                    sent_by_name: K. Mizzi
                    sent_at: '2026-07-12T09:03:00+00:00'
                    acknowledgement_status: acknowledged
                    acknowledged_at: '2026-07-12T14:00:00+00:00'
                    document_hash: b659cce4f6fe9e5f...
                    total_quantity: 124
                    total_cost: 289.4
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-purchase-orders-purchase-order-snapshots
  /api/purchase-orders/{purchase_order}/snapshots/{snapshot}:
    get:
      tags:
      - Purchase Orders
      summary: Get Purchase Order Revision
      description: 'Retrieve a single purchase order revision snapshot with its full
        header and line detail. The snapshot is a frozen copy of the order as it was
        sent to the supplier for that revision.


        Path params:

        - `purchase_order` (required): id of the purchase order.

        - `snapshot` (required): id of the revision snapshot to retrieve.


        Response: a single snapshot object (not wrapped in `data`) with the header
        summary, the captured `lines[]`, and the same top-level revision metadata
        returned by the list endpoint (`revision_number`, `reason`, `submission_format`,
        `sent_to_email`, `sent_by_name`, `sent_at`, `acknowledgement_status`, `acknowledged_at`,
        `document_hash`, `total_quantity`, `total_cost`).


        Authentication: Requires Bearer token.


        **Requires permission:** `purchase_orders.view`'
      parameters:
      - name: purchase_order
        in: path
        schema:
          type: integer
        required: true
        example: '739'
        description: The purchase order ID.
      - name: snapshot
        in: path
        schema:
          type: integer
        required: true
        example: '12'
        description: The snapshot ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: integer
                  purchase_order_id:
                    type: integer
                  revision_number:
                    type: integer
                  reason:
                    type: string
                  submission_format:
                    type: string
                  sent_to_email:
                    type: string
                  sent_by_name:
                    type: string
                  sent_at:
                    type: string
                  acknowledgement_status:
                    type: string
                  acknowledged_at:
                    type: string
                  document_hash:
                    type: string
                  total_quantity:
                    type: integer
                  total_cost:
                    type: number
                  lines:
                    type: array
                    items:
                      type: object
                      properties:
                        purchase_order_line_id:
                          type: integer
                        product_id:
                          type: integer
                        sku:
                          type: string
                        description:
                          type: string
                        quantity:
                          type: integer
                        amount:
                          type: number
                        discount_rate:
                          type: integer
                        tax_rate:
                          type: string
                          nullable: true
                        line_total:
                          type: number
                  header:
                    type: object
                    properties:
                      purchase_order_number:
                        type: string
                      supplier_id:
                        type: integer
                      supplier_name:
                        type: string
                      currency_code:
                        type: string
                      currency_rate:
                        type: integer
                      estimated_delivery_date:
                        type: string
                        nullable: true
                      etd:
                        type: string
                        nullable: true
                      incoterm_code:
                        type: string
                        nullable: true
                      payment_term_name:
                        type: string
                        nullable: true
                      supplier_notes:
                        type: string
                        nullable: true
                      total_quantity:
                        type: integer
                      total_cost:
                        type: number
                example:
                  id: 12
                  purchase_order_id: 739
                  revision_number: 2
                  reason: Corrected qty per supplier
                  submission_format: email_pdf_attachment
                  sent_to_email: supplier@acme.com
                  sent_by_name: K. Mizzi
                  sent_at: '2026-07-12T09:03:00+00:00'
                  acknowledgement_status: acknowledged
                  acknowledged_at: '2026-07-12T14:00:00+00:00'
                  document_hash: b659cce4...
                  total_quantity: 124
                  total_cost: 289.4
                  lines:
                  - purchase_order_line_id: 7
                    product_id: 7
                    sku: SKU-1042
                    description: Widget A
                    quantity: 74
                    amount: 3.1
                    discount_rate: 0
                    tax_rate: null
                    line_total: 229.4
                  header:
                    purchase_order_number: PO-000739
                    supplier_id: 14
                    supplier_name: Acme Supply
                    currency_code: USD
                    currency_rate: 1
                    estimated_delivery_date: null
                    etd: null
                    incoterm_code: null
                    payment_term_name: null
                    supplier_notes: null
                    total_quantity: 124
                    total_cost: 289.4
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-purchase-orders-purchase-order-snapshots-snapshot
  /api/purchase-orders/{purchase_order}/changes-since-sent:
    get:
      tags:
      - Purchase Orders
      summary: Get Changes Since Last Sent
      description: 'Compare the live purchase order against the most recent revision
        snapshot and return a line-level and header-level diff. Use it to detect when
        an order has been edited after it was last sent to the supplier, so those
        pending changes can be reviewed and re-sent.


        Path params:

        - `purchase_order` (required): id of the purchase order.


        Response under `data`:

        - `latest_revision_number` / `latest_sent_at` — the revision the live order
        is compared against.

        - `has_pending_changes` — `true` when the live order differs from that revision.

        - `changes_pending_since` — when the order first diverged from the sent revision.

        - `line_changes[]` — each entry has a `change_type` of `added`, `removed`
        or `modified`, and (for `modified`) a `fields[]` array of `{ field, from,
        to }`.

        - `header_changes[]` — same shape for header-level fields.


        If the order has never been sent there is no revision to compare against.


        Authentication: Requires Bearer token.


        **Requires permission:** `purchase_orders.view`'
      parameters:
      - name: purchase_order
        in: path
        schema:
          type: integer
        required: true
        example: '739'
        description: The purchase order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      latest_revision_number:
                        type: integer
                      latest_sent_at:
                        type: string
                      has_pending_changes:
                        type: boolean
                      changes_pending_since:
                        type: string
                      line_changes:
                        type: array
                        items:
                          type: object
                          properties:
                            purchase_order_line_id:
                              type: integer
                            sku:
                              type: string
                            description:
                              type: string
                            change_type:
                              type: string
                            fields:
                              type: array
                              items:
                                type: object
                                properties:
                                  field:
                                    type: string
                                  from:
                                    type: integer
                                  to:
                                    type: integer
                      header_changes:
                        type: array
                example:
                  data:
                    latest_revision_number: 1
                    latest_sent_at: '2026-07-10T14:14:00+00:00'
                    has_pending_changes: true
                    changes_pending_since: '2026-07-11T10:00:00+00:00'
                    line_changes:
                    - purchase_order_line_id: 7
                      sku: SKU-1042
                      description: Widget A
                      change_type: modified
                      fields:
                      - field: quantity
                        from: 76
                        to: 74
                    header_changes: []
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-purchase-orders-purchase-order-changes-since-sent
  /api/purchase-orders/{purchase_order}/changes-since-sent/dismiss:
    post:
      tags:
      - Purchase Orders
      summary: Dismiss Pending Changes
      description: 'Dismiss the pending post-send changes on a purchase order without
        re-sending it. Use this when an order was edited after it was sent but the
        change does not need to go to the supplier — the supplier keeps the last sent
        revision.


        Clears the pending-changes marker (the order returns to `submitted`) and remembers
        the dismissed state, so routine saves that leave the order unchanged will
        not raise it again. Any further material change to the order (lines, quantities,
        pricing, terms) re-raises the pending-changes state.


        No new revision is created — `revision_number` is unchanged and the last sent
        revision remains what the supplier has. Dismissing an order with nothing pending
        is a no-op.


        Path params:

        - `purchase_order` (required): id of the purchase order.


        Returns the updated purchase order under `data`.


        Authentication: Requires Bearer token.


        **Requires permission:** `purchase_orders.update`'
      requestBody:
        content: {}
      parameters:
      - name: purchase_order
        in: path
        schema:
          type: integer
        required: true
        example: '739'
        description: The purchase order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      purchase_order_number:
                        type: string
                      submission_status:
                        type: string
                      revision_number:
                        type: integer
                      changes_pending_since:
                        type: string
                        nullable: true
                example:
                  data:
                    id: 739
                    purchase_order_number: PO-0664
                    submission_status: submitted
                    revision_number: 1
                    changes_pending_since: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-purchase-orders-purchase-order-changes-since-sent-dismiss
  /api/purchase-orders/{purchase_order}/supplier-responses:
    get:
      tags:
      - Purchase Orders
      summary: List Supplier Responses
      description: 'List the supplier responses recorded against a purchase order''s
        sent revisions, newest first. A response captures how the supplier replied
        to a revision they received — accepting it, requesting changes, or rejecting
        it — optionally with per-line confirmed quantities, costs and dates.


        Path params:

        - `purchase_order` (required): id of the purchase order.


        Response: a collection under `data`. Each item includes `response_type` (`accepted`,
        `changes_requested` or `rejected`), `source`, `responder`, `note`, `recorded_by_name`,
        `responded_at`, the `purchase_order_snapshot_id` the response applies to,
        and a `lines[]` array of the supplier-confirmed line detail.


        Authentication: Requires Bearer token.


        **Requires permission:** `purchase_orders.view`'
      parameters:
      - name: purchase_order
        in: path
        schema:
          type: integer
        required: true
        example: '739'
        description: The purchase order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        purchase_order_id:
                          type: integer
                        purchase_order_snapshot_id:
                          type: integer
                        response_type:
                          type: string
                        source:
                          type: string
                        responder:
                          type: string
                        note:
                          type: string
                        recorded_by_name:
                          type: string
                        responded_at:
                          type: string
                        lines:
                          type: array
                          items:
                            type: object
                            properties:
                              id:
                                type: integer
                              purchase_order_line_id:
                                type: integer
                              sku:
                                type: string
                              ordered_quantity:
                                type: integer
                              confirmed_quantity:
                                type: integer
                              confirmed_unit_cost:
                                type: string
                                nullable: true
                              confirmed_date:
                                type: string
                                nullable: true
                              exception_code:
                                type: string
                              status:
                                type: string
                              note:
                                type: string
                example:
                  data:
                  - id: 5
                    purchase_order_id: 739
                    purchase_order_snapshot_id: 11
                    response_type: changes_requested
                    source: internal
                    responder: Jane @ Acme
                    note: MOQ is 74
                    recorded_by_name: K. Mizzi
                    responded_at: '2026-07-11T12:00:00+00:00'
                    lines:
                    - id: 9
                      purchase_order_line_id: 7
                      sku: SKU-1042
                      ordered_quantity: 76
                      confirmed_quantity: 74
                      confirmed_unit_cost: null
                      confirmed_date: null
                      exception_code: MIN
                      status: changed
                      note: MOQ is 74
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-purchase-orders-purchase-order-supplier-responses
    post:
      tags:
      - Purchase Orders
      summary: Record Supplier Response
      description: "Record a supplier's response to a sent purchase order revision.\
        \ Use it to log that the supplier accepted the order, requested changes, or\
        \ rejected it, optionally capturing the quantities, costs and dates the supplier\
        \ confirmed for individual lines.\n\nRecording an `accepted` response stamps\
        \ the order's last supplier confirmation time. Recording a `changes_requested`\
        \ response moves the order into a supplier-change state so the confirmed quantities\
        \ can be reviewed and applied.\n\nPath params:\n- `purchase_order` (required):\
        \ id of the purchase order.\n\nBody:\n- `response_type` (required): one of\
        \ `accepted`, `changes_requested`, `rejected`.\n- `source` (optional): one\
        \ of `internal`, `supplier_portal`, `email`.\n- `responder` (nullable string):\
        \ name of the person on the supplier side.\n- `note` (nullable string, max\
        \ 5000).\n- `snapshot_id` (nullable integer): id of the revision snapshot\
        \ the response applies to.\n- `lines` (optional array). For each line:\n \
        \   - `purchase_order_line_id` (required with `lines`, integer).\n    - `ordered_quantity`\
        \ (nullable numeric).\n    - `confirmed_quantity` (nullable numeric).\n  \
        \  - `confirmed_unit_cost` (nullable numeric).\n    - `confirmed_date` (nullable\
        \ date).\n    - `exception_code` (nullable): one of `CAP`, `MAT`, `LOG`, `PRI`,\
        \ `UOM`, `SUB`, `MIN`, `DOC`.\n    - `status` (required with `lines`): one\
        \ of `accepted`, `changed`, `rejected`.\n    - `note` (nullable string).\n\
        \nReturns the recorded response and the refreshed purchase order under `data`.\n\
        \nAuthentication: Requires Bearer token.\n\n**Requires permission:** `purchase_orders.update`"
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                response_type:
                  type: string
                source:
                  type: string
                responder:
                  type: string
                note:
                  type: string
                snapshot_id:
                  type: integer
                lines:
                  type: array
                  items:
                    type: object
                    properties:
                      purchase_order_line_id:
                        type: integer
                      ordered_quantity:
                        type: integer
                      confirmed_quantity:
                        type: integer
                      confirmed_unit_cost:
                        type: string
                        nullable: true
                      confirmed_date:
                        type: string
                        nullable: true
                      exception_code:
                        type: string
                      status:
                        type: string
                      note:
                        type: string
              example:
                response_type: changes_requested
                source: internal
                responder: Jane @ Acme
                note: MOQ is 74
                snapshot_id: 11
                lines:
                - purchase_order_line_id: 7
                  ordered_quantity: 76
                  confirmed_quantity: 74
                  confirmed_unit_cost: null
                  confirmed_date: null
                  exception_code: MIN
                  status: changed
                  note: MOQ is 74
      parameters:
      - name: purchase_order
        in: path
        schema:
          type: integer
        required: true
        example: '739'
        description: The purchase order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      response:
                        type: object
                        properties:
                          id:
                            type: integer
                          purchase_order_id:
                            type: integer
                          purchase_order_snapshot_id:
                            type: integer
                          response_type:
                            type: string
                          source:
                            type: string
                          responder:
                            type: string
                          note:
                            type: string
                          recorded_by_name:
                            type: string
                          responded_at:
                            type: string
                          lines:
                            type: array
                            items:
                              type: object
                              properties:
                                id:
                                  type: integer
                                purchase_order_line_id:
                                  type: integer
                                sku:
                                  type: string
                                ordered_quantity:
                                  type: integer
                                confirmed_quantity:
                                  type: integer
                                confirmed_unit_cost:
                                  type: string
                                  nullable: true
                                confirmed_date:
                                  type: string
                                  nullable: true
                                exception_code:
                                  type: string
                                status:
                                  type: string
                                note:
                                  type: string
                      purchase_order:
                        type: object
                        properties:
                          id:
                            type: integer
                          purchase_order_number:
                            type: string
                          submission_status:
                            type: string
                          last_supplier_confirmed_at:
                            type: string
                            nullable: true
                example:
                  message: Supplier response recorded.
                  data:
                    response:
                      id: 5
                      purchase_order_id: 739
                      purchase_order_snapshot_id: 11
                      response_type: changes_requested
                      source: internal
                      responder: Jane @ Acme
                      note: MOQ is 74
                      recorded_by_name: K. Mizzi
                      responded_at: '2026-07-11T12:00:00+00:00'
                      lines:
                      - id: 9
                        purchase_order_line_id: 7
                        sku: SKU-1042
                        ordered_quantity: 76
                        confirmed_quantity: 74
                        confirmed_unit_cost: null
                        confirmed_date: null
                        exception_code: MIN
                        status: changed
                        note: MOQ is 74
                    purchase_order:
                      id: 739
                      purchase_order_number: PO-000739
                      submission_status: change_supplier
                      last_supplier_confirmed_at: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-purchase-orders-purchase-order-supplier-responses
  /api/purchase-orders/{purchase_order}/supplier-responses/{response}/apply:
    post:
      tags:
      - Purchase Orders
      summary: Apply Supplier Confirmed Changes
      description: 'Apply a `changes_requested` supplier response''s confirmed line
        quantities back onto the live purchase order. Each confirmed quantity is written
        to its line, respecting the floors already received or invoiced on that line
        so committed quantities are never reduced below what has already happened.


        Applying the confirmed changes creates a divergence between the live order
        and the last revision the supplier received, which the buyer then re-sends
        as a new revision.


        Path params:

        - `purchase_order` (required): id of the purchase order.

        - `response` (required): id of the supplier response to apply.


        No request body.


        Response under `data`: the refreshed `purchase_order`, an `applied` count
        of lines updated, and a `skipped[]` array describing any lines that could
        not be changed.


        Authentication: Requires Bearer token.


        **Requires permission:** `purchase_orders.update`'
      requestBody:
        content: {}
      parameters:
      - name: purchase_order
        in: path
        schema:
          type: integer
        required: true
        example: '739'
        description: The purchase order ID.
      - name: response
        in: path
        schema:
          type: integer
        required: true
        example: '5'
        description: The response ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      purchase_order:
                        type: object
                        properties:
                          id:
                            type: integer
                          submission_status:
                            type: string
                          changes_pending_since:
                            type: string
                      applied:
                        type: integer
                      skipped:
                        type: array
                example:
                  message: Applied 1 supplier-confirmed line change(s).
                  data:
                    purchase_order:
                      id: 739
                      submission_status: change_buyer
                      changes_pending_since: '2026-07-11T12:05:00+00:00'
                    applied: 1
                    skipped: []
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-purchase-orders-purchase-order-supplier-responses-response-apply
  /api/purchase-invoices:
    get:
      tags:
      - Purchase Invoices
      summary: List Purchase Invoices
      description: 'Get a paginated list of purchase invoices with filtering and sorting.


        :::info[Required scope: `purchase-orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Filters use the filter[field] syntax. Text filters support operators like
        is, is_not, contains, starts_with, ends_with, is_empty, is_not_empty.

        Numeric filters support is, is_not, greater_than, less_than, between.

        Datetime filters support date range comparisons.


        Allowed sorts: id, purchase_invoice_date, due_date, other_date, supplier_invoice_number,
        status, purchase_order_id, supplier_id, created_at, updated_at, purchase_order_number,
        supplier_name, line_item_count, attachments_count.


        Each row includes attachments_count (number of attached documents) and attachment_filenames
        (their file names). Filter with filter[attachments_count] (e.g. =0 for invoices
        with no documents) or filter[attachment_filename] (match a document''s file
        name).

        Default sort: -id (newest first).

        Default: excludes archived invoices unless filter[archived] is provided.


        The response also includes `unfiltered_total`, the count of rows in the base
        scope before any user filters are applied — used by the frontend to show export
        totals.'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        description: 'Page number (default: 1)'
        example: '1'
      - name: per_page
        in: query
        schema:
          type: integer
        description: 'Items per page (default: 10)'
        example: '10'
      - name: sort
        in: query
        schema:
          type: string
        description: 'Sort field. Prefix with - for descending. Allowed: id, purchase_invoice_date,
          due_date, other_date, supplier_invoice_number, status, purchase_order_id,
          supplier_id, created_at, updated_at, purchase_order_number, supplier_name,
          line_item_count, attachments_count'
        example: -id
      - name: filter[status]
        in: query
        schema:
          type: string
        description: Filter by invoice status (open, partial, paid, etc.)
        example: open
      - name: filter[supplier_invoice_number]
        in: query
        schema:
          type: string
        description: Filter by supplier invoice number (text match)
        example: INV-001
      - name: filter[supplier_name]
        in: query
        schema:
          type: string
        description: Filter by supplier name (text match)
      - name: filter[currency]
        in: query
        schema:
          type: string
        description: Filter by currency code (text match)
      - name: filter[purchase_invoice_date]
        in: query
        schema:
          type: string
        description: Filter by invoice date (date/datetime)
      - name: filter[due_date]
        in: query
        schema:
          type: string
        description: Filter by due date
      - name: filter[other_date]
        in: query
        schema:
          type: string
        description: Filter by other date
      - name: filter[attachments_count]
        in: query
        schema:
          type: string
        description: Filter by number of attached documents (numeric). Supports is,
          is_not, greater_than, less_than, between, is_empty, is_not_empty. Use filter[attachments_count.is]=0
          (or is_empty) to find invoices with no documents yet.
      - name: filter[attachment_filename]
        in: query
        schema:
          type: string
        description: Filter to invoices that have an attached document whose file
          name matches (text). Supports contains, is, starts_with, ends_with, is_empty,
          is_not_empty. e.g. filter[attachment_filename.contains]=packing-slip
      - name: filter[created_at]
        in: query
        schema:
          type: string
        description: Filter by created_at datetime
      - name: filter[updated_at]
        in: query
        schema:
          type: string
        description: Filter by updated_at datetime
      - name: filter[supplier_id]
        in: query
        schema:
          type: string
        description: Filter by supplier ID (numeric)
      - name: filter[id]
        in: query
        schema:
          type: string
        description: Filter by invoice ID (numeric)
      - name: filter[purchase_order_id]
        in: query
        schema:
          type: string
        description: Filter by purchase order ID (exact match)
      - name: filter[purchase_order_number]
        in: query
        schema:
          type: string
        description: Filter by purchase order number (text match)
      - name: filter[archived]
        in: query
        schema:
          type: string
        description: 'archived filter: omit for non-archived only, ''only'' for archived
          only, ''all'' for all records'
      - name: filter[search]
        in: query
        schema:
          type: string
        description: Search across supplier_invoice_number, id, supplier name, purchase_order_number
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        purchase_order_id:
                          type: integer
                        purchase_order_number:
                          type: string
                        purchase_order:
                          type: object
                          properties:
                            id:
                              type: integer
                            purchase_order_number:
                              type: string
                            purchase_order_date:
                              type: string
                            total:
                              type: integer
                            receipts:
                              type: array
                        supplier_invoice_number:
                          type: string
                        supplier_id:
                          type: integer
                        supplier_name:
                          type: string
                        status:
                          type: string
                        purchase_invoice_lines:
                          type: string
                          nullable: true
                        financial_lines:
                          type: string
                          nullable: true
                        purchase_invoice_date:
                          type: string
                        due_date:
                          type: string
                        other_date:
                          type: string
                          nullable: true
                        currency_id:
                          type: integer
                        currency_rate:
                          type: integer
                        currency:
                          type: object
                          properties:
                            id:
                              type: integer
                            code:
                              type: string
                            name:
                              type: string
                            symbol:
                              type: string
                        line_item_count:
                          type: integer
                        first_line_sku:
                          type: string
                        calculated_total:
                          type: integer
                        tax_total:
                          type: integer
                        total_paid:
                          type: integer
                        payments:
                          type: string
                          nullable: true
                        approval_status:
                          type: string
                        approved_by:
                          type: string
                          nullable: true
                        approved_by_name:
                          type: string
                          nullable: true
                        approved_at:
                          type: string
                          nullable: true
                        approval_notes:
                          type: string
                          nullable: true
                        tags:
                          type: array
                        created_at:
                          type: string
                        updated_at:
                          type: string
                        archived_at:
                          type: string
                          nullable: true
                        attachments_count:
                          type: integer
                        attachment_filenames:
                          type: array
                          items:
                            type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  unfiltered_total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - id: 42
                    purchase_order_id: 15
                    purchase_order_number: PO-2024-0015
                    purchase_order:
                      id: 15
                      purchase_order_number: PO-2024-0015
                      purchase_order_date: '2024-01-15T00:00:00+00:00'
                      total: 1250
                      receipts: []
                    supplier_invoice_number: INV-2024-001
                    supplier_id: 7
                    supplier_name: Acme Supplies Ltd
                    status: open
                    purchase_invoice_lines: null
                    financial_lines: null
                    purchase_invoice_date: '2024-01-20'
                    due_date: '2024-02-20'
                    other_date: null
                    currency_id: 1
                    currency_rate: 1
                    currency:
                      id: 1
                      code: USD
                      name: US Dollar
                      symbol: $
                    line_item_count: 3
                    first_line_sku: SKU-001
                    calculated_total: 1250
                    tax_total: 125
                    total_paid: 0
                    payments: null
                    approval_status: approved
                    approved_by: null
                    approved_by_name: null
                    approved_at: null
                    approval_notes: null
                    tags: []
                    created_at: '2024-01-20T10:30:00.000000Z'
                    updated_at: '2024-01-20T10:30:00.000000Z'
                    archived_at: null
                    attachments_count: 2
                    attachment_filenames:
                    - packing-slip.pdf
                    - invoice-scan.pdf
                  current_page: 1
                  last_page: 5
                  per_page: 10
                  total: 47
                  unfiltered_total: 612
                  from: 1
                  to: 10
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: purchase-orders:read
      operationId: get-api-purchase-invoices
    post:
      tags:
      - Purchase Invoices
      summary: Create Purchase Invoice
      description: 'Create a new purchase invoice linked to a purchase order.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Either purchase_invoice_lines or financial_lines must be provided on creation.

        Invoice lines must belong to the specified purchase order and must not be
        fully invoiced.


        When financial_lines are provided, each entry requires: id (an existing financial_lines.id),
        quantity (numeric), and amount (numeric). A 422 is returned if any are missing.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                purchase_order_id:
                  type: integer
                purchase_invoice_date:
                  type: string
                due_date:
                  type: string
                other_date:
                  type: string
                  nullable: true
                supplier_invoice_number:
                  type: string
                status:
                  type: string
                currency_id:
                  type: integer
                currency_rate:
                  type: integer
                tags:
                  type: array
                  items:
                    type: string
                purchase_invoice_lines:
                  type: array
                  items:
                    type: object
                    properties:
                      purchase_order_line_id:
                        type: integer
                      quantity_invoiced:
                        type: integer
                      unit_price:
                        type: integer
                financial_lines:
                  type: array
                  items:
                    type: object
                    properties:
                      id:
                        type: integer
                      quantity:
                        type: integer
                      amount:
                        type: integer
                      link_type:
                        type: string
              example:
                purchase_order_id: 15
                purchase_invoice_date: '2024-01-20'
                due_date: '2024-02-20'
                other_date: null
                supplier_invoice_number: INV-2024-001
                status: open
                currency_id: 1
                currency_rate: 1
                tags:
                - urgent
                - priority
                purchase_invoice_lines:
                - purchase_order_line_id: 101
                  quantity_invoiced: 10
                  unit_price: 25
                financial_lines:
                - id: 55
                  quantity: 1
                  amount: 120
                  link_type: App\Models\PurchaseOrder
      parameters: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      purchase_order_id:
                        type: integer
                      supplier_invoice_number:
                        type: string
                      supplier_id:
                        type: integer
                      supplier_name:
                        type: string
                      status:
                        type: string
                      purchase_invoice_date:
                        type: string
                      due_date:
                        type: string
                      calculated_total:
                        type: integer
                      tax_total:
                        type: integer
                      total_paid:
                        type: integer
                      approval_status:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                  message:
                    type: string
                example:
                  data:
                    id: 43
                    purchase_order_id: 15
                    supplier_invoice_number: INV-2024-001
                    supplier_id: 7
                    supplier_name: Acme Supplies Ltd
                    status: open
                    purchase_invoice_date: '2024-01-20'
                    due_date: '2024-02-20'
                    calculated_total: 250
                    tax_total: 0
                    total_paid: 0
                    approval_status: approved
                    created_at: '2024-01-20T10:30:00.000000Z'
                    updated_at: '2024-01-20T10:30:00.000000Z'
                    archived_at: null
                  message: Purchase invoice created successfully
        '422':
          description: Unprocessable Entity
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      purchase_order_id:
                        type: array
                        items:
                          type: string
                      supplier_invoice_number:
                        type: array
                        items:
                          type: string
                      purchase_invoice_lines:
                        type: array
                        items:
                          type: string
                example:
                  message: The given data was invalid.
                  errors:
                    purchase_order_id:
                    - The purchase order id field is required.
                    supplier_invoice_number:
                    - The supplier invoice number field is required.
                    purchase_invoice_lines:
                    - Either purchase_invoice_lines or financial_lines must be provided.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: purchase-orders:write
      operationId: post-api-purchase-invoices
    delete:
      tags:
      - Purchase Invoices
      summary: Bulk Delete Purchase Invoices
      description: 'Bulk delete purchase invoices by IDs or by applying filters.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Either ids or apply_to_all must be provided. If apply_to_all is true, filters
        will be used to resolve which IDs to delete.'
      parameters: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Purchase Invoices deleted successfully
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: purchase-orders:write
      operationId: delete-api-purchase-invoices
  /api/purchase-invoices/{purchase_invoice}:
    get:
      tags:
      - Purchase Invoices
      summary: Get Purchase Invoice
      description: 'Get a single purchase invoice with full detail including lines,
        financial lines, payments, and accounting transaction.


        :::info[Required scope: `purchase-orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        The `purchase_order` object includes `total_invoiced` — the discount-netted
        amount billed across every invoice on the purchase order (not just this one).
        Subtract it from `purchase_order.total` for the amount still to be invoiced
        on the order.'
      parameters:
      - name: purchase_invoice
        in: path
        schema:
          type: integer
        required: true
        description: Purchase invoice ID
        example: '42'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      purchase_order_id:
                        type: integer
                      purchase_order_number:
                        type: string
                      purchase_order:
                        type: object
                        properties:
                          id:
                            type: integer
                          purchase_order_number:
                            type: string
                          total:
                            type: integer
                          total_invoiced:
                            type: integer
                      supplier_invoice_number:
                        type: string
                      supplier_id:
                        type: integer
                      supplier_name:
                        type: string
                      status:
                        type: string
                      purchase_invoice_lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            purchase_order_line_id:
                              type: integer
                            quantity_invoiced:
                              type: integer
                            unit_price:
                              type: integer
                            subtotal:
                              type: integer
                      financial_lines:
                        type: array
                      purchase_invoice_date:
                        type: string
                      due_date:
                        type: string
                      other_date:
                        type: string
                        nullable: true
                      currency_id:
                        type: integer
                      currency_rate:
                        type: integer
                      currency:
                        type: object
                        properties:
                          id:
                            type: integer
                          code:
                            type: string
                          name:
                            type: string
                          symbol:
                            type: string
                      line_item_count:
                        type: integer
                      first_line_sku:
                        type: string
                      calculated_total:
                        type: integer
                      tax_total:
                        type: integer
                      total_paid:
                        type: integer
                      payments:
                        type: array
                      approval_status:
                        type: string
                      approved_by:
                        type: string
                        nullable: true
                      approved_by_name:
                        type: string
                        nullable: true
                      approved_at:
                        type: string
                        nullable: true
                      approval_notes:
                        type: string
                        nullable: true
                      tags:
                        type: array
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                example:
                  data:
                    id: 42
                    purchase_order_id: 15
                    purchase_order_number: PO-2024-0015
                    purchase_order:
                      id: 15
                      purchase_order_number: PO-2024-0015
                      total: 500
                      total_invoiced: 250
                    supplier_invoice_number: INV-2024-001
                    supplier_id: 7
                    supplier_name: Acme Supplies Ltd
                    status: open
                    purchase_invoice_lines:
                    - id: 201
                      purchase_order_line_id: 101
                      quantity_invoiced: 10
                      unit_price: 25
                      subtotal: 250
                    financial_lines: []
                    purchase_invoice_date: '2024-01-20'
                    due_date: '2024-02-20'
                    other_date: null
                    currency_id: 1
                    currency_rate: 1
                    currency:
                      id: 1
                      code: USD
                      name: US Dollar
                      symbol: $
                    line_item_count: 1
                    first_line_sku: SKU-001
                    calculated_total: 250
                    tax_total: 0
                    total_paid: 0
                    payments: []
                    approval_status: approved
                    approved_by: null
                    approved_by_name: null
                    approved_at: null
                    approval_notes: null
                    tags: []
                    created_at: '2024-01-20T10:30:00.000000Z'
                    updated_at: '2024-01-20T10:30:00.000000Z'
                    archived_at: null
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No query results for model [App\Models\PurchaseInvoice]
                    9999
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: purchase-orders:read
      operationId: get-api-purchase-invoices-purchase-invoice
    put:
      tags:
      - Purchase Invoices
      summary: Update Purchase Invoice
      description: 'Update an existing purchase invoice. All fields are optional on
        update (uses sometimes validation).


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Note: purchase_order_id cannot be changed on update.


        When financial_lines are provided, each entry requires: id (an existing financial_lines.id),
        quantity (numeric), and amount (numeric). A 422 is returned if any are missing.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                purchase_invoice_date:
                  type: string
                due_date:
                  type: string
                supplier_invoice_number:
                  type: string
                status:
                  type: string
                currency_id:
                  type: integer
                currency_rate:
                  type: integer
                tags:
                  type: array
                  items:
                    type: string
                purchase_invoice_lines:
                  type: array
                  items:
                    type: object
                    properties:
                      purchase_order_line_id:
                        type: integer
                      quantity_invoiced:
                        type: integer
                      unit_price:
                        type: integer
                financial_lines:
                  type: array
              example:
                purchase_invoice_date: '2024-01-22'
                due_date: '2024-02-22'
                supplier_invoice_number: INV-2024-001-REV
                status: open
                currency_id: 1
                currency_rate: 1
                tags:
                - revised
                purchase_invoice_lines:
                - purchase_order_line_id: 101
                  quantity_invoiced: 12
                  unit_price: 25
                financial_lines: []
      parameters:
      - name: purchase_invoice
        in: path
        schema:
          type: integer
        required: true
        description: Purchase invoice ID
        example: '42'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      supplier_invoice_number:
                        type: string
                      status:
                        type: string
                      calculated_total:
                        type: integer
                      updated_at:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 42
                    supplier_invoice_number: INV-2024-001-REV
                    status: open
                    calculated_total: 300
                    updated_at: '2024-01-22T14:00:00.000000Z'
                  message: Purchase invoice updated successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: purchase-orders:write
      operationId: put-api-purchase-invoices-purchase-invoice
    delete:
      tags:
      - Purchase Invoices
      summary: Delete Purchase Invoice
      description: 'Delete a single purchase invoice. Also unlinks any associated
        financial lines.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: purchase_invoice
        in: path
        schema:
          type: integer
        required: true
        description: Purchase invoice ID
        example: '42'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Purchase Invoice deleted successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:write
      operationId: delete-api-purchase-invoices-purchase-invoice
  /api/purchase-invoices/{purchaseInvoice}/line-items:
    get:
      tags:
      - Purchase Invoices
      summary: Get Line Items
      description: 'Get the line items for a purchase invoice (used for expand row
        in the list view).


        :::info[Required scope: `purchase-orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: purchaseInvoice
        in: path
        schema:
          type: integer
        required: true
        description: Purchase invoice ID
        example: '42'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        sku:
                          type: string
                        product_name:
                          type: string
                        product_id:
                          type: integer
                        quantity_invoiced:
                          type: integer
                        unit_price:
                          type: integer
                        amount:
                          type: integer
                        po_unit_price:
                          type: integer
                        line_total:
                          type: integer
                example:
                  data:
                  - id: 201
                    sku: SKU-001
                    product_name: Widget A
                    product_id: 55
                    quantity_invoiced: 10
                    unit_price: 25
                    amount: 25
                    po_unit_price: 24
                    line_total: 250
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:read
      operationId: get-api-purchase-invoices-purchaseinvoice-line-items
  /api/purchase-invoices/{purchaseInvoice}/shipment-prefill:
    get:
      tags:
      - Purchase Invoices
      summary: Get Shipment Prefill (From Invoice)
      description: 'Build the prefill payload used by the Create Inbound Shipment
        from Invoice form.


        :::info[Required scope: `purchase-orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Returns header info (supplier, PO, invoice number, default destination warehouse
        from PO), one row per non-fully-shipped invoice line with quantity_remaining_to_ship
        pre-filled, and soft warnings (e.g. fully-shipped lines).


        Authentication: Requires Bearer token.'
      parameters:
      - name: purchaseInvoice
        in: path
        schema:
          type: integer
        required: true
        description: Purchase invoice ID
        example: '42'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      purchase_invoice_id:
                        type: integer
                      supplier_invoice_number:
                        type: string
                      supplier_id:
                        type: integer
                      supplier_name:
                        type: string
                      purchase_order_id:
                        type: integer
                      purchase_order_number:
                        type: string
                      default_destination_warehouse_id:
                        type: integer
                      lines:
                        type: array
                        items:
                          type: object
                          properties:
                            purchase_invoice_line_id:
                              type: integer
                            purchase_order_id:
                              type: integer
                            purchase_order_line_id:
                              type: integer
                            product_id:
                              type: integer
                            product_sku:
                              type: string
                            product_name:
                              type: string
                            quantity_invoiced:
                              type: integer
                            quantity_already_shipped:
                              type: integer
                            quantity_remaining_to_ship:
                              type: integer
                            unit_price:
                              type: integer
                      warnings:
                        type: array
                example:
                  data:
                    purchase_invoice_id: 42
                    supplier_invoice_number: INV-2024-001
                    supplier_id: 7
                    supplier_name: Acme Supplies Ltd
                    purchase_order_id: 15
                    purchase_order_number: PO-2024-0015
                    default_destination_warehouse_id: 1
                    lines:
                    - purchase_invoice_line_id: 201
                      purchase_order_id: 15
                      purchase_order_line_id: 101
                      product_id: 10
                      product_sku: SKU-001
                      product_name: Widget A
                      quantity_invoiced: 10
                      quantity_already_shipped: 0
                      quantity_remaining_to_ship: 10
                      unit_price: 25
                    warnings: []
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No query results for model [App\Models\PurchaseInvoice]
                    9999
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: purchase-orders:read
      operationId: get-api-purchase-invoices-purchaseinvoice-shipment-prefill
  /api/purchase-invoices/{purchaseInvoice}/inbound-shipments:
    get:
      tags:
      - Purchase Invoices
      summary: List Inbound Shipments for Invoice
      description: 'List all inbound shipments that were created from this purchase
        invoice. Used by the Inbound Shipments traceability panel on the invoice detail
        page.


        :::info[Required scope: `purchase-orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: purchaseInvoice
        in: path
        schema:
          type: integer
        required: true
        description: Purchase invoice ID
        example: '42'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        shipment_number:
                          type: string
                        status:
                          type: string
                        status_label:
                          type: string
                        supplier_id:
                          type: integer
                        purchase_invoice_id:
                          type: integer
                        destination_warehouse_id:
                          type: integer
                        carrier:
                          type: string
                        tracking_number:
                          type: string
                          nullable: true
                        shipping_method_id:
                          type: integer
                        expected_arrival_date:
                          type: string
                        actual_arrival_date:
                          type: string
                          nullable: true
                        shipped_at:
                          type: string
                          nullable: true
                        created_from_receipt:
                          type: boolean
                        notes:
                          type: string
                          nullable: true
                        created_by:
                          type: integer
                        asn_last_sent_at:
                          type: string
                          nullable: true
                        total_expected_quantity:
                          type: integer
                        total_received_quantity:
                          type: integer
                        inbound_shipment_lines_count:
                          type: integer
                        supplier:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        destination_warehouse:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        shipping_method:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        creator:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                example:
                  data:
                  - id: 87
                    shipment_number: IS-00087
                    status: draft
                    status_label: Draft
                    supplier_id: 7
                    purchase_invoice_id: 42
                    destination_warehouse_id: 1
                    carrier: FedEx
                    tracking_number: null
                    shipping_method_id: 3
                    expected_arrival_date: '2025-06-01'
                    actual_arrival_date: null
                    shipped_at: null
                    created_from_receipt: false
                    notes: null
                    created_by: 1
                    asn_last_sent_at: null
                    total_expected_quantity: 10
                    total_received_quantity: 0
                    inbound_shipment_lines_count: 1
                    supplier:
                      id: 7
                      name: Acme Supplies Ltd
                    destination_warehouse:
                      id: 1
                      name: Main Warehouse
                    shipping_method:
                      id: 3
                      name: Ground
                    creator:
                      id: 1
                      name: Admin User
                    created_at: '2025-05-07T10:00:00.000000Z'
                    updated_at: '2025-05-07T10:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:read
      operationId: get-api-purchase-invoices-purchaseinvoice-inbound-shipments
  /api/purchase-invoices/{purchaseOrderId}/print:
    get:
      tags:
      - Purchase Invoices
      summary: Print Purchase Invoice PDF
      description: 'Generate and stream a PDF of the purchase order invoice.


        :::info[Required scope: `purchase-orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        **Important:** the `:purchaseOrderId` path parameter is a **purchase ORDER
        id**, not a purchase invoice id. Despite living under `/api/purchase-invoices/`,
        this endpoint looks up the purchase order and renders its invoice PDF.


        Authentication: Requires Bearer token.


        Response: Inline PDF file (application/pdf). Not a JSON response.'
      parameters:
      - name: purchaseOrderId
        in: path
        schema:
          type: integer
        required: true
        description: Purchase ORDER id (not a purchase invoice id).
        example: '15'
      responses:
        '200':
          description: OK
          content:
            text/plain:
              schema:
                type: string
                example: (binary PDF content — open in browser or save as .pdf)
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:read
      operationId: get-api-purchase-invoices-purchaseorderid-print
  /api/purchase-invoices/{purchaseInvoice}/reset-due-date:
    post:
      tags:
      - Purchase Invoices
      summary: Reset Invoice Due Date to Term
      description: 'Discards a manually-overridden due date on a supplier invoice
        and re-derives it from the effective payment term (the invoice''s own term,
        else the linked purchase order''s term, else the supplier default). The response''s
        `due_date_source` returns to `derived` (or `none` when no term is resolvable).


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: purchaseInvoice
        in: path
        schema:
          type: string
        required: true
        description: The purchase invoice ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      supplier_invoice_number:
                        type: string
                      supplier_id:
                        type: integer
                      purchase_order_id:
                        type: integer
                      purchase_order_number:
                        type: string
                      purchase_invoice_date:
                        type: string
                      due_date:
                        type: string
                      due_date_source:
                        type: string
                      payment_term_name:
                        type: string
                      payment_term_snapshot:
                        type: object
                        properties:
                          payment_term_id:
                            type: integer
                          name:
                            type: string
                          net_days:
                            type: integer
                          due_date_type:
                            type: string
                          discount_percentage:
                            type: integer
                          discount_days:
                            type: integer
                          captured_at:
                            type: string
                      term_diverges_from_po:
                        type: boolean
                      discount_due_date:
                        type: string
                      discount_amount:
                        type: integer
                      discount_available:
                        type: boolean
                      payment_due_status:
                        type: string
                      days_until_due:
                        type: integer
                example:
                  data:
                    id: 12
                    supplier_invoice_number: INV-88231
                    supplier_id: 40
                    purchase_order_id: 707
                    purchase_order_number: PO-0636
                    purchase_invoice_date: '2026-01-01'
                    due_date: '2026-01-31'
                    due_date_source: derived
                    payment_term_name: Net 30
                    payment_term_snapshot:
                      payment_term_id: 2
                      name: Net 30
                      net_days: 30
                      due_date_type: from_invoice_date
                      discount_percentage: 2
                      discount_days: 10
                      captured_at: '2026-01-01T12:00:00+00:00'
                    term_diverges_from_po: false
                    discount_due_date: '2026-01-11'
                    discount_amount: 20
                    discount_available: true
                    payment_due_status: not_due
                    days_until_due: 30
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-purchase-invoices-purchaseinvoice-reset-due-date
  /api/purchase-invoices/archive:
    put:
      tags:
      - Purchase Invoices
      summary: Bulk Archive Purchase Invoices
      description: 'Bulk archive purchase invoices.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
                apply_to_all:
                  type: boolean
                filters:
                  type: object
                  properties: {}
              example:
                ids:
                - 42
                - 43
                apply_to_all: false
                filters: {}
      parameters: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: purchase invoice archived successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: purchase-orders:write
      operationId: put-api-purchase-invoices-archive
  /api/purchase-invoices/unarchive:
    put:
      tags:
      - Purchase Invoices
      summary: Bulk Unarchive Purchase Invoices
      description: 'Bulk unarchive purchase invoices.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
                apply_to_all:
                  type: boolean
                filters:
                  type: object
                  properties: {}
              example:
                ids:
                - 42
                - 43
                apply_to_all: false
                filters: {}
      parameters: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: purchase invoice unarchived successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: purchase-orders:write
      operationId: put-api-purchase-invoices-unarchive
  /api/purchase-invoices/{purchaseInvoice}/archive:
    put:
      tags:
      - Purchase Invoices
      summary: Archive Purchase Invoice
      description: 'Archive a single purchase invoice.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: purchaseInvoice
        in: path
        schema:
          type: integer
        required: true
        description: Purchase invoice ID
        example: '42'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: purchase invoice INV-2024-001 archived successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: purchase-orders:write
      operationId: put-api-purchase-invoices-purchaseinvoice-archive
  /api/purchase-invoices/{purchaseInvoice}/unarchived:
    put:
      tags:
      - Purchase Invoices
      summary: Unarchive Purchase Invoice
      description: 'Unarchive a single purchase invoice.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: purchaseInvoice
        in: path
        schema:
          type: integer
        required: true
        description: Purchase invoice ID
        example: '42'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: purchase invoice INV-2024-001 unarchived successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: purchase-orders:write
      operationId: put-api-purchase-invoices-purchaseinvoice-unarchived
  /api/purchase-invoices/deletable:
    post:
      tags:
      - Purchase Invoices
      summary: Check Deletability
      description: 'Check whether purchase invoices can be deleted. Invoices are always
        deletable.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 42
                - 43
      parameters: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        deletable:
                          type: boolean
                        reason:
                          type: string
                          nullable: true
                example:
                  data:
                  - id: 42
                    deletable: true
                    reason: null
                  - id: 43
                    deletable: true
                    reason: null
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: purchase-orders:write
      operationId: post-api-purchase-invoices-deletable
  /api/purchase-invoices/fees-received:
    post:
      tags:
      - Purchase Invoices
      summary: Create Custom (Fees Received) Invoice
      description: 'Create a custom purchase invoice for fees (e.g., freight, handling).
        Fires events to recalculate FIFO layers and product averages.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                purchase_order_id:
                  type: integer
                purchase_invoice_date:
                  type: string
                supplier_invoice_number:
                  type: string
                supplier_id:
                  type: integer
                status:
                  type: string
                total:
                  type: integer
                description:
                  type: string
              example:
                purchase_order_id: 15
                purchase_invoice_date: '2024-01-20'
                supplier_invoice_number: FEE-2024-001
                supplier_id: 7
                status: open
                total: 150
                description: Handling and freight fee
      parameters: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: custom Purchase Invoice created successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: purchase-orders:write
      operationId: post-api-purchase-invoices-fees-received
  /api/purchase-invoices/{purchaseInvoice}/approve:
    post:
      tags:
      - Purchase Invoices
      summary: Approve Purchase Invoice
      description: 'Approve a purchase invoice that requires approval.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Returns 422 if invoice is already approved.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                notes:
                  type: string
              example:
                notes: Approved after review of line items
      parameters:
      - name: purchaseInvoice
        in: path
        schema:
          type: integer
        required: true
        description: Purchase invoice ID
        example: '42'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      approval_status:
                        type: string
                      approved_by:
                        type: integer
                      approved_by_name:
                        type: string
                      approved_at:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 42
                    approval_status: approved
                    approved_by: 3
                    approved_by_name: Jane Smith
                    approved_at: '2024-01-22T09:15:00.000000Z'
                  message: Invoice approved successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: purchase-orders:write
      operationId: post-api-purchase-invoices-purchaseinvoice-approve
  /api/purchase-invoices/{purchaseInvoice}/reject:
    post:
      tags:
      - Purchase Invoices
      summary: Reject Purchase Invoice
      description: 'Reject a purchase invoice that requires approval.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Required: notes (string, max 1000 chars).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                notes:
                  type: string
              example:
                notes: Price variance exceeds acceptable threshold
      parameters:
      - name: purchaseInvoice
        in: path
        schema:
          type: integer
        required: true
        description: Purchase invoice ID
        example: '42'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      approval_status:
                        type: string
                      approval_notes:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 42
                    approval_status: rejected
                    approval_notes: Price variance exceeds acceptable threshold
                  message: Invoice rejected.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: purchase-orders:write
      operationId: post-api-purchase-invoices-purchaseinvoice-reject
  /api/purchase-invoices/{purchaseInvoice}/resubmit:
    post:
      tags:
      - Purchase Invoices
      summary: Resubmit Purchase Invoice for Approval
      description: 'Re-submit a rejected invoice back to pending approval status.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Only rejected invoices can be resubmitted. Returns 422 otherwise.'
      requestBody:
        content: {}
      parameters:
      - name: purchaseInvoice
        in: path
        schema:
          type: integer
        required: true
        description: Purchase invoice ID
        example: '42'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      approval_status:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 42
                    approval_status: pending
                  message: Invoice resubmitted for approval.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: purchase-orders:write
      operationId: post-api-purchase-invoices-purchaseinvoice-resubmit
  /api/purchase-invoices/{purchaseInvoice}/generate-accounting-transaction:
    post:
      tags:
      - Purchase Invoices
      summary: Generate Accounting Transaction
      description: 'Generate or regenerate the accounting transaction for a purchase
        invoice.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: purchaseInvoice
        in: path
        schema:
          type: integer
        required: true
        description: Purchase invoice ID
        example: '42'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      status:
                        type: string
                      total:
                        type: integer
                      reference:
                        type: string
                      transaction_date:
                        type: string
                      type:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 88
                    status: pending
                    total: 250
                    reference: INV-2024-001
                    transaction_date: '2024-01-20T00:00:00+00:00'
                    type: purchase_invoice
                  message: Accounting transaction generated successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: purchase-orders:write
      operationId: post-api-purchase-invoices-purchaseinvoice-generate-accounting-transaction
  /api/purchase-invoices/{purchaseInvoice}/lines/{purchaseInvoiceLine}/sync-po-price:
    post:
      tags:
      - Purchase Invoices
      summary: Sync PO Price From Invoice Line
      description: 'Push the unit_price from a single invoice line up to the linked
        PO line''s amount, then re-evaluate the invoice''s approval status.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Use this from the 3-Way Match view when a price variance is confirmed legitimate
        (e.g. supplier raised the price). The PO line is updated, an activity log
        entry is recorded on the PO line, and the invoice is re-evaluated — typically
        returning it to auto_approved once the price matches. Works on both open and
        closed POs.


        Authentication: Requires Bearer token.


        Request body fields:

        - notes (string, optional, max 1000): free-text justification stored on the
        activity log entry.


        Result statuses:

        - updated: PO line amount changed; old_amount and new_amount are returned.

        - unchanged: PO line amount already matched invoice line unit price; no write
        occurred.

        - skipped: nothing was done. The reason field explains why. Possible reasons:
        ''invoice line not linked to a PO line'', ''invoice line has no unit price''.


        Returns 404 if the invoice line does not belong to the purchase invoice.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                notes:
                  type: string
              example:
                notes: Confirmed price increase with supplier
      parameters:
      - name: purchaseInvoice
        in: path
        schema:
          type: integer
        required: true
        description: Purchase invoice ID
        example: '42'
      - name: purchaseInvoiceLine
        in: path
        schema:
          type: integer
        required: true
        description: Purchase invoice line ID (must belong to the invoice)
        example: '501'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 OK - Updated
                  value:
                    data:
                      result:
                        status: updated
                        old_amount: 12.65
                        new_amount: 13.48
                      invoice:
                        id: 42
                        reference: INV-2024-001
                        approval_status: auto_approved
                        purchase_order_id: 17
                        invoice_date: '2024-01-15'
                        total: 269.6
                    message: PO price updated from invoice.
                example-1:
                  summary: 200 OK - Unchanged
                  value:
                    data:
                      result:
                        status: unchanged
                        old_amount: 13.48
                        new_amount: 13.48
                      invoice:
                        id: 42
                        approval_status: auto_approved
                    message: PO price already matches invoice.
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Invoice line does not belong to this invoice.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: purchase-orders:write
      operationId: post-api-purchase-invoices-purchaseinvoice-lines-purchaseinvoiceline-sync-po-price
  /api/purchase-invoices/{purchaseInvoice}/sync-po-prices:
    post:
      tags:
      - Purchase Invoices
      summary: Sync PO Prices Bulk
      description: 'Sync PO line prices from many invoice lines on a single invoice
        in one request, then re-evaluate the invoice''s approval status once at the
        end.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Use this from the 3-Way Match view when several lines have confirmed price
        variances. Each invoice line is processed individually using the same logic
        as POST /api/purchase-invoices/:purchaseInvoice/lines/:purchaseInvoiceLine/sync-po-price,
        and the final results are returned keyed by purchase_invoice_line_id. Works
        on both open and closed POs.


        Authentication: Requires Bearer token.


        Request body fields:

        - purchase_invoice_line_ids (integer[], required, min 1): IDs of invoice lines
        to sync. Each must belong to this purchase invoice (validated via Rule::exists
        with where purchase_invoice_id).

        - notes (string, optional, max 1000): free-text justification stored on each
        activity log entry.


        Per-line result statuses (same as single endpoint):

        - updated: PO line amount changed; old_amount and new_amount are returned.

        - unchanged: PO line amount already matched invoice line unit price.

        - skipped: nothing was done; reason is one of ''invoice line not found on
        this invoice'', ''invoice line not linked to a PO line'', ''invoice line has
        no unit price''.


        The top-level message summarises counts (e.g. ''Synced 2 line(s); 1 unchanged;
        0 skipped.'').'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                purchase_invoice_line_ids:
                  type: array
                  items:
                    type: integer
                notes:
                  type: string
              example:
                purchase_invoice_line_ids:
                - 501
                - 502
                - 503
                notes: Bulk reconcile after supplier price update
      parameters:
      - name: purchaseInvoice
        in: path
        schema:
          type: integer
        required: true
        description: Purchase invoice ID
        example: '42'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      results:
                        type: object
                        properties:
                          '501':
                            type: object
                            properties:
                              status:
                                type: string
                              old_amount:
                                type: number
                              new_amount:
                                type: number
                          '502':
                            type: object
                            properties:
                              status:
                                type: string
                              old_amount:
                                type: number
                              new_amount:
                                type: number
                          '503':
                            type: object
                            properties:
                              status:
                                type: string
                              reason:
                                type: string
                      invoice:
                        type: object
                        properties:
                          id:
                            type: integer
                          reference:
                            type: string
                          approval_status:
                            type: string
                          purchase_order_id:
                            type: integer
                          total:
                            type: number
                  message:
                    type: string
                example:
                  data:
                    results:
                      '501':
                        status: updated
                        old_amount: 12.65
                        new_amount: 13.48
                      '502':
                        status: unchanged
                        old_amount: 8.5
                        new_amount: 8.5
                      '503':
                        status: skipped
                        reason: invoice line not linked to a PO line
                    invoice:
                      id: 42
                      reference: INV-2024-001
                      approval_status: auto_approved
                      purchase_order_id: 17
                      total: 540.3
                  message: Synced 1 line(s); 1 unchanged; 1 skipped.
        '422':
          description: Unprocessable Entity
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      purchase_invoice_line_ids:
                        type: array
                        items:
                          type: string
                example:
                  message: The purchase invoice line ids field is required.
                  errors:
                    purchase_invoice_line_ids:
                    - The purchase invoice line ids field is required.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:write
      operationId: post-api-purchase-invoices-purchaseinvoice-sync-po-prices
  /api/purchase-invoices/variance-report:
    get:
      tags:
      - Purchase Invoices
      summary: Get Variance Report
      description: 'Get paginated price variance data comparing invoice prices vs.
        PO prices.


        :::info[Required scope: `purchase-orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Returns purchase invoice lines where unit_price is set, with computed variance
        metrics.'
      parameters:
      - name: per_page
        in: query
        schema:
          type: integer
        description: 'Items per page (default: 15)'
        example: '15'
      - name: filter[min_variance_percent]
        in: query
        schema:
          type: integer
        description: Minimum price variance % to include (e.g. 5 = only show lines
          with >=5% variance)
        example: '5'
      - name: filter[search]
        in: query
        schema:
          type: string
        description: Search across supplier invoice number, supplier name, PO number,
          SKU, and product name
        example: Acme
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        purchase_invoice_id:
                          type: integer
                        supplier_invoice_number:
                          type: string
                        purchase_order_number:
                          type: string
                        purchase_order_id:
                          type: integer
                        supplier_name:
                          type: string
                        invoice_date:
                          type: string
                        invoice_status:
                          type: string
                        sku:
                          type: string
                        product_name:
                          type: string
                        quantity_invoiced:
                          type: integer
                        po_unit_price:
                          type: integer
                        invoice_unit_price:
                          type: integer
                        price_variance:
                          type: integer
                        price_variance_percent:
                          type: number
                        extended_variance:
                          type: integer
                  current_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 201
                    purchase_invoice_id: 42
                    supplier_invoice_number: INV-2024-001
                    purchase_order_number: PO-2024-0015
                    purchase_order_id: 15
                    supplier_name: Acme Supplies Ltd
                    invoice_date: '2024-01-20'
                    invoice_status: open
                    sku: SKU-001
                    product_name: Widget A
                    quantity_invoiced: 10
                    po_unit_price: 24
                    invoice_unit_price: 25
                    price_variance: 1
                    price_variance_percent: 4.17
                    extended_variance: 10
                  current_page: 1
                  per_page: 15
                  total: 12
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: purchase-orders:read
      operationId: get-api-purchase-invoices-variance-report
  /api/purchase-invoices/{purchaseInvoice}/three-way-match:
    get:
      tags:
      - Purchase Invoices
      summary: Get Three-Way Match Data
      description: 'Get three-way match data for an invoice: compares PO quantities/prices,
        received quantities, and invoice quantities/prices.


        :::info[Required scope: `purchase-orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Receipt sources (matches PurchaseOrderLine::getEffectiveReceivedQuantity):

        - Amazon AWD destination POs: receipts come from amazon_awd_ledgers (matched
        receipts).

        - Amazon FBA destination POs: receipts come from amazon_ledgers (matched receipts).

        - Standard warehouse destinations: receipts come from inbound_shipment_receipt_lines.


        Qty match statuses: match, over_invoiced, under_invoiced.


        Response fields:

        - lines[]: per-PO-line comparison (po_quantity, received_quantity, invoice_quantity,
        price_variance, qty_match_status, receipts[]).

        - financial_lines[]: non-product invoice lines (freight, fees, etc.).

        - has_receipts: true if any line has a non-zero received_quantity.


        Quantity reconciliation is evaluated at the purchase-order-line level across
        every invoice and matched vendor credit on the order, adjusted for short-closes
        and explicit billing settlement — not for this invoice in isolation. A line
        split across multiple invoices, or offset by a credit, reports `qty_match_status`
        = `match`.


        Per-line fields: `invoiced_all_quantity` (billed across all invoices on the
        PO), `credited_quantity` (matched credits on the line), `effective_ordered_quantity`
        (ordered, after short-close), `net_invoiced_quantity` (invoiced − credited),
        and `qty_status_reason` (human-readable explanation of the status).'
      parameters:
      - name: purchaseInvoice
        in: path
        schema:
          type: integer
        required: true
        description: Purchase invoice ID
        example: '42'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      lines:
                        type: array
                        items:
                          type: object
                          properties:
                            purchase_order_line_id:
                              type: integer
                            product_id:
                              type: integer
                            sku:
                              type: string
                            product_name:
                              type: string
                            po_quantity:
                              type: integer
                            po_unit_price:
                              type: number
                            received_quantity:
                              type: integer
                            receipts:
                              type: array
                              items:
                                type: object
                                properties:
                                  id:
                                    type: integer
                                  received_at:
                                    type: string
                                  quantity:
                                    type: integer
                            invoice_quantity:
                              type: integer
                            invoice_unit_price:
                              type: number
                            price_variance:
                              type: number
                            price_variance_percent:
                              type: number
                            qty_match_status:
                              type: string
                            invoiced_all_quantity:
                              type: integer
                            credited_quantity:
                              type: integer
                            effective_ordered_quantity:
                              type: integer
                            net_invoiced_quantity:
                              type: integer
                            qty_status_reason:
                              type: string
                            po_extended:
                              type: integer
                            invoice_extended:
                              type: number
                      financial_lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            description:
                              type: string
                            quantity:
                              type: integer
                            invoice_amount:
                              type: integer
                      has_receipts:
                        type: boolean
                example:
                  data:
                    lines:
                    - purchase_order_line_id: 101
                      product_id: 55
                      sku: SKU-001
                      product_name: Widget A
                      po_quantity: 20
                      po_unit_price: 12.65
                      received_quantity: 20
                      receipts:
                      - id: 9001
                        received_at: '2024-05-27'
                        quantity: 20
                      invoice_quantity: 20
                      invoice_unit_price: 13.48
                      price_variance: 0.83
                      price_variance_percent: 6.56
                      qty_match_status: match
                      invoiced_all_quantity: 20
                      credited_quantity: 0
                      effective_ordered_quantity: 20
                      net_invoiced_quantity: 20
                      qty_status_reason: 'Reconciled: 20 net invoiced matches 20 ordered
                        across all invoices on this PO.'
                      po_extended: 253
                      invoice_extended: 269.6
                    financial_lines:
                    - id: 33
                      description: Freight
                      quantity: 1
                      invoice_amount: 25
                    has_receipts: true
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:read
      operationId: get-api-purchase-invoices-purchaseinvoice-three-way-match
  /api/purchase-invoices/{purchaseInvoice}/variance-resolution-preview:
    get:
      tags:
      - Purchase Invoices
      summary: Variance Resolution Preview
      description: 'Preview over-billed quantities per PO line so the UI can prefill
        a ''Resolve with vendor credit'' dialog.


        :::info[Required scope: `purchase-orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        A line is considered over-billed when its effective invoiced quantity (quantity_invoiced
        minus quantity already credited on this bill via existing vendor credit allocations)
        exceeds the PO line''s effective received quantity. Receipt sources match
        `PurchaseOrderLine::getEffectiveReceivedQuantity` (standard warehouse receipts,
        FBA/AWD ledgers, accounting for any active short-close event).


        The suggested credit quantity is exactly the over-bill delta. The suggested
        credit amount is `over_billed * unit_price` (invoice unit price, falling back
        to PO amount).


        Response fields:

        - `invoice_id`, `purchase_order_id`, `supplier_id`, `currency_id`, `currency_code`

        - `has_over_bills`: true if any line has over-billed quantity

        - `total_suggested_credit`: sum of `suggested_credit_amount` across over-billed
        lines

        - `lines[]`: only includes lines with over-billed quantity. Each line has
        `purchase_invoice_line_id`, `purchase_order_line_id`, `product_id`, `sku`,
        `product_name`, `quantity_invoiced`, `received_quantity`, `already_credited`,
        `over_billed_quantity`, `suggested_credit_quantity`, `unit_price`, `suggested_credit_amount`.'
      parameters:
      - name: purchaseInvoice
        in: path
        schema:
          type: integer
        required: true
        description: Purchase invoice ID
        example: '42'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      invoice_id:
                        type: integer
                      purchase_order_id:
                        type: integer
                      supplier_id:
                        type: integer
                      currency_id:
                        type: integer
                      currency_code:
                        type: string
                      has_over_bills:
                        type: boolean
                      total_suggested_credit:
                        type: number
                      lines:
                        type: array
                        items:
                          type: object
                          properties:
                            purchase_invoice_line_id:
                              type: integer
                            purchase_order_line_id:
                              type: integer
                            product_id:
                              type: integer
                            sku:
                              type: string
                            product_name:
                              type: string
                            quantity_invoiced:
                              type: integer
                            received_quantity:
                              type: integer
                            already_credited:
                              type: integer
                            over_billed_quantity:
                              type: integer
                            suggested_credit_quantity:
                              type: integer
                            unit_price:
                              type: number
                            suggested_credit_amount:
                              type: number
                example:
                  data:
                    invoice_id: 42
                    purchase_order_id: 18
                    supplier_id: 7
                    currency_id: 1
                    currency_code: USD
                    has_over_bills: true
                    total_suggested_credit: 39.5
                    lines:
                    - purchase_invoice_line_id: 301
                      purchase_order_line_id: 101
                      product_id: 55
                      sku: T-NS02-OAK-CV
                      product_name: Oak Canvas
                      quantity_invoiced: 91
                      received_quantity: 89
                      already_credited: 0
                      over_billed_quantity: 2
                      suggested_credit_quantity: 2
                      unit_price: 19.75
                      suggested_credit_amount: 39.5
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:read
      operationId: get-api-purchase-invoices-purchaseinvoice-variance-resolution-preview
  /api/purchase-invoices/{purchaseInvoice}/resolve-with-credit:
    post:
      tags:
      - Purchase Invoices
      summary: Resolve with Vendor Credit
      description: 'Resolve an over-billed purchase invoice by issuing a vendor credit
        for the over-billed quantities and auto-allocating it against the bill.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        The credit is created in `open` status with `restock_inventory=false` (it''s
        a billing correction, not a physical return). After the credit is allocated,
        the invoice''s approval status is re-evaluated so the variance flag clears
        automatically when the credit fully offsets the over-bill.


        Request body fields:

        - `lines` (required, min 1): array of `{ purchase_order_line_id, quantity
        }`. Each `quantity` must be > 0 and ≤ the over-billed quantity for that PO
        line.

        - `credit_date` (optional, nullable, date): defaults to today.

        - `supplier_reference` (optional, nullable, max 255): defaults to the invoice''s
        `supplier_invoice_number`.

        - `reason` (optional, nullable, max 2000): copied into the vendor credit''s
        note.


        Validation errors return 422 with a `message` for: invoice not linked to a
        PO, PO line not on this invoice, PO line not on this invoice''s PO, requested
        quantity exceeds over-billed delta, or no over-billed quantities provided.


        Returns the newly created VendorCredit (eager-loaded with supplier, currency,
        lines, and allocations).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                lines:
                  type: array
                  items:
                    type: object
                    properties:
                      purchase_order_line_id:
                        type: integer
                      quantity:
                        type: integer
                credit_date:
                  type: string
                supplier_reference:
                  type: string
                reason:
                  type: string
              example:
                lines:
                - purchase_order_line_id: 101
                  quantity: 2
                credit_date: '2026-05-14'
                supplier_reference: N26A038
                reason: Short-shipped 2 units against billed quantity.
      parameters:
      - name: purchaseInvoice
        in: path
        schema:
          type: integer
        required: true
        description: Purchase invoice ID
        example: '42'
      responses:
        '201':
          description: Created
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      supplier_id:
                        type: integer
                      purchase_order_id:
                        type: integer
                      currency_id:
                        type: integer
                      credit_date:
                        type: string
                      credit_status:
                        type: string
                      supplier_reference:
                        type: string
                      vendor_credit_note:
                        type: string
                      total_credit:
                        type: number
                      allocated_amount:
                        type: number
                      remaining_amount:
                        type: integer
                      vendor_credit_lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            purchase_order_line_id:
                              type: integer
                            product_id:
                              type: integer
                            quantity:
                              type: integer
                            amount:
                              type: number
                            restock_inventory:
                              type: boolean
                      vendor_credit_allocations:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            purchase_invoice_id:
                              type: integer
                            amount:
                              type: number
                example:
                  data:
                    id: 88
                    supplier_id: 7
                    purchase_order_id: 18
                    currency_id: 1
                    credit_date: '2026-05-14'
                    credit_status: open
                    supplier_reference: N26A038
                    vendor_credit_note: Short-shipped 2 units against billed quantity.
                    total_credit: 39.5
                    allocated_amount: 39.5
                    remaining_amount: 0
                    vendor_credit_lines:
                    - id: 220
                      purchase_order_line_id: 101
                      product_id: 55
                      quantity: 2
                      amount: 19.75
                      restock_inventory: false
                    vendor_credit_allocations:
                    - id: 130
                      purchase_invoice_id: 42
                      amount: 39.5
        '422':
          description: Unprocessable Entity
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Requested credit quantity (5) exceeds over-billed quantity
                    (2) for purchase order line 101.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:write
      operationId: post-api-purchase-invoices-purchaseinvoice-resolve-with-credit
  /api/purchase-invoices/{purchaseInvoice}/activity-log:
    get:
      tags:
      - Purchase Invoices
      summary: List Activity Log Entries
      description: 'Get paginated activity log entries for a purchase invoice.


        :::info[Required scope: `purchase-orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: per_page
        in: query
        schema:
          type: integer
        description: 'Items per page (default: 15)'
        example: '15'
      - name: filter[search]
        in: query
        schema:
          type: string
        description: Search across causer name, properties, and event
        example: updated
      - name: purchaseInvoice
        in: path
        schema:
          type: integer
        required: true
        description: Purchase invoice ID
        example: '42'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        description:
                          type: string
                        event:
                          type: string
                        subject_type:
                          type: string
                        subject_id:
                          type: integer
                        properties:
                          type: object
                          properties:
                            old:
                              type: object
                              properties:
                                status:
                                  type: string
                            attributes:
                              type: object
                              properties:
                                status:
                                  type: string
                        causer_name:
                          type: string
                        created_at:
                          type: string
                  current_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 1001
                    description: updated
                    event: updated
                    subject_type: PurchaseInvoice
                    subject_id: 42
                    properties:
                      old:
                        status: open
                      attributes:
                        status: partial
                    causer_name: Jane Smith
                    created_at: '2024-01-22T09:15:00.000000Z'
                  current_page: 1
                  per_page: 15
                  total: 5
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:read
      operationId: get-api-purchase-invoices-purchaseinvoice-activity-log
  /api/purchase-invoices/list/export:
    get:
      tags:
      - Purchase Invoices
      summary: Export Purchase Invoices
      description: 'Export purchase invoices as XLSX or CSV.


        :::info[Required scope: `purchase-orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Response: Binary file download (xlsx or csv). Not a JSON response.


        Column keys: id, supplier_invoice_number, purchase_order_number, supplier_name,
        status, purchase_invoice_date, due_date, other_date, currency_code, calculated_total,
        tax_total, total_paid, created_at, updated_at, archived_at.


        In line_items mode, additional columns are added for each line: item_sku,
        item_name, item_quantity_invoiced, item_amount, item_line_total.'
      parameters:
      - name: format
        in: query
        schema:
          type: string
        description: 'Export format: xlsx or csv (default: xlsx)'
        example: xlsx
      - name: content_mode
        in: query
        schema:
          type: string
        description: 'Export mode: summary (one row per invoice) or line_items (one
          row per line item)'
        example: summary
      - name: scope
        in: query
        schema:
          type: string
        description: 'Scope: all, filtered, current_page, or selected'
        example: filtered
      - name: ids
        in: query
        schema:
          type: string
        description: Comma-separated IDs when scope=selected
      - name: columns
        in: query
        schema:
          type: string
        description: 'Comma-separated column keys to include. Available: id, supplier_invoice_number,
          purchase_order_number, supplier_name, status, purchase_invoice_date, due_date,
          other_date, currency_code, calculated_total, tax_total, total_paid, created_at,
          updated_at, archived_at'
        example: id,supplier_invoice_number,status
      responses:
        '200':
          description: OK
          content:
            text/plain:
              schema:
                type: string
                example: (binary xlsx/csv file)
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: purchase-orders:read
      operationId: get-api-purchase-invoices-list-export
  /api/purchase-invoices/aging-report:
    get:
      tags:
      - Purchase Invoices
      summary: Get Payables Aging Report
      description: 'Supplier payables aging report over outstanding (unpaid and partially
        paid) purchase invoices and, optionally, bills.


        Authentication: Requires Bearer token.


        Records are bucketed by days past the selected age-by date: current (not yet
        past, or no date), 1-30, 31-60, 61-90, and 90+ days. Amounts are converted
        to the tenant currency using each record''s exchange-rate snapshot. The summary
        block reports total outstanding, total overdue (past due date), and the amount
        due within the next 7 days. Rows are grouped by supplier, sorted by total
        outstanding descending, and each row includes the individual invoice/bill
        records that make up its buckets.'
      parameters: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      summary:
                        type: object
                        properties:
                          total_outstanding:
                            type: integer
                          total_overdue:
                            type: integer
                          due_this_week:
                            type: integer
                          currency:
                            type: string
                          age_by:
                            type: string
                      buckets:
                        type: object
                        properties:
                          current:
                            type: integer
                          d1_30:
                            type: integer
                          d31_60:
                            type: integer
                          d61_90:
                            type: integer
                          d90_plus:
                            type: integer
                      rows:
                        type: array
                        items:
                          type: object
                          properties:
                            supplier_id:
                              type: integer
                            supplier_name:
                              type: string
                            current:
                              type: integer
                            d1_30:
                              type: integer
                            d31_60:
                              type: integer
                            d61_90:
                              type: integer
                            d90_plus:
                              type: integer
                            total:
                              type: integer
                            items:
                              type: array
                              items:
                                type: object
                                properties:
                                  id:
                                    type: integer
                                  type:
                                    type: string
                                  number:
                                    type: string
                                  supplier_id:
                                    type: integer
                                  supplier_name:
                                    type: string
                                  invoice_date:
                                    type: string
                                  due_date:
                                    type: string
                                  days_overdue:
                                    type: integer
                                  bucket:
                                    type: string
                                  outstanding:
                                    type: integer
                                  currency_code:
                                    type: string
                                  outstanding_in_tenant_currency:
                                    type: integer
                example:
                  data:
                    summary:
                      total_outstanding: 42300
                      total_overdue: 9120
                      due_this_week: 6540
                      currency: USD
                      age_by: due_date
                    buckets:
                      current: 33180
                      d1_30: 5100
                      d31_60: 2820
                      d61_90: 700
                      d90_plus: 500
                    rows:
                    - supplier_id: 12
                      supplier_name: Acme Supplies Ltd
                      current: 4120
                      d1_30: 980
                      d31_60: 0
                      d61_90: 0
                      d90_plus: 0
                      total: 5100
                      items:
                      - id: 42
                        type: invoice
                        number: INV-2024-001
                        supplier_id: 12
                        supplier_name: Acme Supplies Ltd
                        invoice_date: '2024-01-20'
                        due_date: '2024-02-19'
                        days_overdue: 12
                        bucket: d1_30
                        outstanding: 980
                        currency_code: USD
                        outstanding_in_tenant_currency: 980
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-purchase-invoices-aging-report
  /api/purchase-invoices/{purchaseInvoice}/calendar.ics:
    get:
      tags:
      - Purchase Invoices
      summary: Download Due-Date Calendar Event
      description: 'Download a single-event iCalendar (.ics) file for the invoice''s
        payment due date, suitable for importing into Outlook, Apple Calendar, or
        any calendar app.


        Authentication: Requires Bearer token.


        The response is a text/calendar file download (not JSON) containing one all-day
        VEVENT on the due date with a stable UID, so re-importing an updated file
        replaces the earlier event. The event carries popup reminders 7 days and 1
        day before the deadline.


        Returns 422 when the invoice has no payment due date.'
      parameters:
      - name: purchaseInvoice
        in: path
        schema:
          type: integer
        required: true
        description: Purchase invoice ID
        example: '42'
      responses:
        '422':
          description: Unprocessable Entity
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: This invoice has no payment due date to add to a calendar.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-purchase-invoices-purchaseinvoice-calendar-ics
  /api/purchase-invoices/{purchaseInvoice}/notes:
    get:
      tags:
      - Purchase Invoices
      summary: List Notes
      description: 'Get paginated notes for a purchase invoice, ordered by newest
        first.


        :::info[Required scope: `purchase-orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: purchaseInvoice
        in: path
        schema:
          type: integer
        required: true
        description: Purchase invoice ID
        example: '42'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        note:
                          type: string
                        is_pinned:
                          type: boolean
                        created_at:
                          type: string
                        user:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                  current_page:
                    type: integer
                example:
                  data:
                  - id: 5
                    note: Confirmed with supplier.
                    is_pinned: false
                    created_at: '2024-01-21T08:00:00.000000Z'
                    user:
                      id: 3
                      name: Jane Smith
                  current_page: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:read
      operationId: get-api-purchase-invoices-purchaseinvoice-notes
    post:
      tags:
      - Purchase Invoices
      summary: Add Note
      description: 'Add a note to a purchase invoice.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Required: note (string).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                note:
                  type: string
              example:
                note: Checked with supplier — price correct.
      parameters:
      - name: purchaseInvoice
        in: path
        schema:
          type: integer
        required: true
        description: Purchase invoice ID
        example: '42'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      note:
                        type: string
                      is_pinned:
                        type: boolean
                      created_at:
                        type: string
                      user:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                  message:
                    type: string
                example:
                  data:
                    id: 6
                    note: Checked with supplier — price correct.
                    is_pinned: false
                    created_at: '2024-01-22T11:30:00.000000Z'
                    user:
                      id: 3
                      name: Jane Smith
                  message: note created successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: purchase-orders:write
      operationId: post-api-purchase-invoices-purchaseinvoice-notes
  /api/purchase-invoices/{purchaseInvoice}/notes/{noteId}/toggle-pin:
    put:
      tags:
      - Purchase Invoices
      summary: Toggle Note Pin
      description: 'Toggle the pinned state of a note on a purchase invoice.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: purchaseInvoice
        in: path
        schema:
          type: integer
        required: true
        description: Purchase invoice ID
        example: '42'
      - name: noteId
        in: path
        schema:
          type: integer
        required: true
        description: Note ID
        example: '5'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      note:
                        type: string
                      is_pinned:
                        type: boolean
                      user:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                  message:
                    type: string
                example:
                  data:
                    id: 5
                    note: Confirmed with supplier.
                    is_pinned: true
                    user:
                      id: 3
                      name: Jane Smith
                  message: Note pinned
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: purchase-orders:write
      operationId: put-api-purchase-invoices-purchaseinvoice-notes-noteid-toggle-pin
  /api/purchase-invoices/{purchaseInvoice}/notes/{noteId}:
    delete:
      tags:
      - Purchase Invoices
      summary: Delete Note
      description: 'Delete a note from a purchase invoice.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: purchaseInvoice
        in: path
        schema:
          type: integer
        required: true
        description: Purchase invoice ID
        example: '42'
      - name: noteId
        in: path
        schema:
          type: integer
        required: true
        description: Note ID
        example: '5'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: note 5 deleted successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:write
      operationId: delete-api-purchase-invoices-purchaseinvoice-notes-noteid
  /api/purchase-invoices/{purchaseInvoiceId}/payments:
    get:
      tags:
      - Purchase Invoices
      summary: List Payments
      description: 'List all payments for a purchase invoice.


        :::info[Required scope: `purchase-orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: purchaseInvoiceId
        in: path
        schema:
          type: integer
        required: true
        description: Purchase invoice ID
        example: '42'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        amount:
                          type: integer
                        cost:
                          type: string
                          nullable: true
                        payment_date:
                          type: string
                        payment_type:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        external_reference:
                          type: string
                        type:
                          type: string
                          nullable: true
                        currency_code:
                          type: string
                example:
                  data:
                  - id: 10
                    amount: 250
                    cost: null
                    payment_date: '2024-02-01'
                    payment_type:
                      id: 1
                      name: Bank Transfer
                    external_reference: TXN-12345
                    type: null
                    currency_code: USD
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:read
      operationId: get-api-purchase-invoices-purchaseinvoiceid-payments
    post:
      tags:
      - Purchase Invoices
      summary: Create Payment
      description: 'Record a payment against a purchase invoice.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Required: payment_type_id, amount. Payment date defaults to today if omitted.

        Amount must not exceed the remaining balance. Negative amounts are allowed
        for refunds (cannot exceed total paid).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                payment_date:
                  type: string
                payment_type_id:
                  type: integer
                external_reference:
                  type: string
                amount:
                  type: integer
                currency_id:
                  type: integer
              example:
                payment_date: '2024-02-01'
                payment_type_id: 1
                external_reference: TXN-12345
                amount: 250
                currency_id: 1
      parameters:
      - name: purchaseInvoiceId
        in: path
        schema:
          type: integer
        required: true
        description: Purchase invoice ID
        example: '42'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      amount:
                        type: integer
                      payment_date:
                        type: string
                      payment_type:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      external_reference:
                        type: string
                      currency_code:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 10
                    amount: 250
                    payment_date: '2024-02-01'
                    payment_type:
                      id: 1
                      name: Bank Transfer
                    external_reference: TXN-12345
                    currency_code: USD
                  message: purchase invoice payment created successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: purchase-orders:write
      operationId: post-api-purchase-invoices-purchaseinvoiceid-payments
  /api/purchase-invoices/{purchaseInvoiceId}/payments/{payment}:
    get:
      tags:
      - Purchase Invoices
      summary: Get Payment
      description: 'Get a single payment for a purchase invoice.


        :::info[Required scope: `purchase-orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: purchaseInvoiceId
        in: path
        schema:
          type: integer
        required: true
        description: Purchase invoice ID
        example: '42'
      - name: payment
        in: path
        schema:
          type: integer
        required: true
        description: Payment ID
        example: '10'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      amount:
                        type: integer
                      payment_date:
                        type: string
                      payment_type:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      external_reference:
                        type: string
                      currency_code:
                        type: string
                example:
                  data:
                    id: 10
                    amount: 250
                    payment_date: '2024-02-01'
                    payment_type:
                      id: 1
                      name: Bank Transfer
                    external_reference: TXN-12345
                    currency_code: USD
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:read
      operationId: get-api-purchase-invoices-purchaseinvoiceid-payments-payment
    put:
      tags:
      - Purchase Invoices
      summary: Update Payment
      description: 'Update a payment on a purchase invoice. All fields are optional
        on update.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Note: payment_type_id cannot be changed for credit payment types (system-created).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                payment_date:
                  type: string
                payment_type_id:
                  type: integer
                external_reference:
                  type: string
                amount:
                  type: integer
                currency_id:
                  type: integer
              example:
                payment_date: '2024-02-05'
                payment_type_id: 1
                external_reference: TXN-12345-REVISED
                amount: 250
                currency_id: 1
      parameters:
      - name: purchaseInvoiceId
        in: path
        schema:
          type: integer
        required: true
        description: Purchase invoice ID
        example: '42'
      - name: payment
        in: path
        schema:
          type: integer
        required: true
        description: Payment ID
        example: '10'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      amount:
                        type: integer
                      payment_date:
                        type: string
                      external_reference:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 10
                    amount: 250
                    payment_date: '2024-02-05'
                    external_reference: TXN-12345-REVISED
                  message: purchase invoice payment 10 updated successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: purchase-orders:write
      operationId: put-api-purchase-invoices-purchaseinvoiceid-payments-payment
    delete:
      tags:
      - Purchase Invoices
      summary: Delete Payment
      description: 'Delete a payment from a purchase invoice.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: purchaseInvoiceId
        in: path
        schema:
          type: integer
        required: true
        description: Purchase invoice ID
        example: '42'
      - name: payment
        in: path
        schema:
          type: integer
        required: true
        description: Payment ID
        example: '10'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: purchase invoice payment 10 deleted successfully
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:write
      operationId: delete-api-purchase-invoices-purchaseinvoiceid-payments-payment
  /api/purchase-invoices/import/template:
    get:
      tags:
      - Purchase Invoices
      summary: Download Import Template
      description: 'Download an XLSX import template with headers, sample data, field
        guide, and reference data from the tenant''s account.


        :::info[Required scope: `purchase-orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Response: Binary XLSX file download.'
      parameters: []
      responses:
        '200':
          description: OK
          content:
            text/plain:
              schema:
                type: string
                example: (binary XLSX file — save as purchase-invoices-import-template.xlsx)
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: purchase-orders:read
      operationId: get-api-purchase-invoices-import-template
  /api/purchase-invoices/import/validate:
    post:
      tags:
      - Purchase Invoices
      summary: Validate Import Data
      description: 'Validate mapped import data and return a grouped preview. No side
        effects — safe to call repeatedly.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Required: rows array with at least one item.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                rows:
                  type: array
                  items:
                    type: object
                    properties:
                      purchase_order_number:
                        type: string
                      supplier_invoice_number:
                        type: string
                      purchase_invoice_date:
                        type: string
                      due_date:
                        type: string
                      other_date:
                        type: string
                        nullable: true
                      currency_code:
                        type: string
                      sku:
                        type: string
                      quantity_invoiced:
                        type: integer
              example:
                rows:
                - purchase_order_number: PO-2024-0015
                  supplier_invoice_number: INV-2024-001
                  purchase_invoice_date: '2024-01-20'
                  due_date: '2024-02-20'
                  other_date: null
                  currency_code: USD
                  sku: SKU-001
                  quantity_invoiced: 10
      parameters: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  valid:
                    type: array
                    items:
                      type: object
                      properties:
                        purchase_order_id:
                          type: integer
                        purchase_order_number:
                          type: string
                        supplier_invoice_number:
                          type: string
                        lines:
                          type: array
                          items:
                            type: object
                            properties:
                              sku:
                                type: string
                              purchase_order_line_id:
                                type: integer
                              quantity_invoiced:
                                type: integer
                  errors:
                    type: array
                example:
                  valid:
                  - purchase_order_id: 15
                    purchase_order_number: PO-2024-0015
                    supplier_invoice_number: INV-2024-001
                    lines:
                    - sku: SKU-001
                      purchase_order_line_id: 101
                      quantity_invoiced: 10
                  errors: []
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: purchase-orders:write
      operationId: post-api-purchase-invoices-import-validate
  /api/purchase-invoices/import:
    post:
      tags:
      - Purchase Invoices
      summary: Execute Import
      description: 'Execute the import — create purchase invoices from validated data.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Required: purchase_invoices array where each item has purchase_order_id, supplier_invoice_number,
        purchase_invoice_date, and lines with purchase_order_line_id and quantity_invoiced.


        Returns 201 on success, 422 on validation or import failure.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                purchase_invoices:
                  type: array
                  items:
                    type: object
                    properties:
                      purchase_order_id:
                        type: integer
                      supplier_invoice_number:
                        type: string
                      purchase_invoice_date:
                        type: string
                      due_date:
                        type: string
                      other_date:
                        type: string
                        nullable: true
                      currency_id:
                        type: integer
                      lines:
                        type: array
                        items:
                          type: object
                          properties:
                            purchase_order_line_id:
                              type: integer
                            quantity_invoiced:
                              type: integer
              example:
                purchase_invoices:
                - purchase_order_id: 15
                  supplier_invoice_number: INV-2024-001
                  purchase_invoice_date: '2024-01-20'
                  due_date: '2024-02-20'
                  other_date: null
                  currency_id: 1
                  lines:
                  - purchase_order_line_id: 101
                    quantity_invoiced: 10
      parameters: []
      responses:
        '201':
          description: Created
          content:
            application/json:
              schema:
                type: object
                properties:
                  created:
                    type: integer
                  errors:
                    type: array
                example:
                  created: 1
                  errors: []
        '422':
          description: Unprocessable Entity
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 'Import failed: Purchase order line 999 not found'
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: purchase-orders:write
      operationId: post-api-purchase-invoices-import
  /api/purchase-invoices/{purchaseInvoice}/attachments:
    get:
      tags:
      - Purchase Invoices
      summary: List Purchase Invoice Attachments
      description: 'List all file attachments on a purchase invoice, ordered oldest
        first.


        :::info[Required scope: `purchase-orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Each attachment includes its OCR scan state: `ocr_status` is `null` (never
        scanned), `pending`, `processing`, `completed`, or `failed`. `download_url`
        is an absolute URL to the download endpoint.


        Requires the `purchase-orders:read` token scope. Returns the full list — this
        endpoint is not paginated.'
      parameters:
      - name: purchaseInvoice
        in: path
        schema:
          type: integer
        required: true
        description: Purchase invoice ID
        example: '123'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        file_name:
                          type: string
                        file_size:
                          type: integer
                        mime_type:
                          type: string
                        created_at:
                          type: string
                        uploaded_by:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        download_url:
                          type: string
                        ocr_status:
                          type: string
                        ocr_error_message:
                          type: string
                          nullable: true
                        ocr_processed_at:
                          type: string
                example:
                  data:
                  - id: 45
                    file_name: supplier-invoice-march.pdf
                    file_size: 482113
                    mime_type: application/pdf
                    created_at: '2026-07-01T14:23:45.000000Z'
                    uploaded_by:
                      id: 3
                      name: Jane Doe
                    download_url: https://acme.sku.io/api/purchase-invoices/123/attachments/45/download
                    ocr_status: completed
                    ocr_error_message: null
                    ocr_processed_at: '2026-07-01T14:25:02.000000Z'
                  - id: 46
                    file_name: packing-list.png
                    file_size: 120441
                    mime_type: image/png
                    created_at: '2026-07-02T09:10:11.000000Z'
                    uploaded_by:
                      id: 3
                      name: Jane Doe
                    download_url: https://acme.sku.io/api/purchase-invoices/123/attachments/46/download
                    ocr_status: null
                    ocr_error_message: null
                    ocr_processed_at: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:read
      operationId: get-api-purchase-invoices-purchaseinvoice-attachments
    post:
      tags:
      - Purchase Invoices
      summary: Upload Purchase Invoice Attachment
      description: 'Upload a file attachment to a purchase invoice. Send as `multipart/form-data`
        with a `file` field and an optional `category` field.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Accepted types: PDF, DOC, DOCX, PNG, JPG/JPEG. Maximum size 20 MB. Uploading
        to an archived invoice returns 422.


        Fields:

        - file (required): The file to attach.

        - category (optional): Document category — one of `invoice`, `payment_proof`,
        or `other`. Defaults to `other`.


        Side effects:

        - If the invoice is already synced to a connected accounting provider (QuickBooks
        Online / Xero), the file is forwarded to the remote document asynchronously.

        - If Invoice OCR is enabled with auto-scan on upload and the file is a PDF,
        an OCR scan is queued automatically in the background — the returned attachment
        will show `ocr_status: "processing"`.


        Requires the `purchase-orders:write` token scope.'
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                file:
                  type: string
                  description: 'Required. The file to attach. Allowed types: pdf,
                    doc, docx, png, jpg, jpeg. Max size 20 MB. Empty files are rejected.'
                  format: binary
                category:
                  type: string
                  description: 'Optional. Document category: invoice, payment_proof,
                    or other. Defaults to other.'
                  example: invoice
      parameters:
      - name: purchaseInvoice
        in: path
        schema:
          type: integer
        required: true
        description: Purchase invoice ID
        example: '123'
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      file_name:
                        type: string
                      file_size:
                        type: integer
                      mime_type:
                        type: string
                      category:
                        type: string
                      category_label:
                        type: string
                      created_at:
                        type: string
                      uploaded_by:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      download_url:
                        type: string
                      ocr_status:
                        type: string
                        nullable: true
                      ocr_error_message:
                        type: string
                        nullable: true
                      ocr_processed_at:
                        type: string
                        nullable: true
                example:
                  data:
                    id: 47
                    file_name: supplier-invoice-april.pdf
                    file_size: 391208
                    mime_type: application/pdf
                    category: invoice
                    category_label: Invoice
                    created_at: '2026-07-06T10:15:30.000000Z'
                    uploaded_by:
                      id: 3
                      name: Jane Doe
                    download_url: https://acme.sku.io/api/purchase-invoices/123/attachments/47/download
                    ocr_status: null
                    ocr_error_message: null
                    ocr_processed_at: null
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      file:
                        type: array
                        items:
                          type: string
                example:
                  message: Only PDF, DOC, DOCX, PNG, and JPG files are allowed.
                  errors:
                    file:
                    - Only PDF, DOC, DOCX, PNG, and JPG files are allowed.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:write
      operationId: post-api-purchase-invoices-purchaseinvoice-attachments
  /api/purchase-invoices/{purchaseInvoice}/attachments/{attachment}:
    delete:
      tags:
      - Purchase Invoices
      summary: Delete Purchase Invoice Attachment
      description: 'Delete an attachment from a purchase invoice. Removes both the
        stored file and its record, including any OCR extraction history for the attachment.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Returns 404 if the attachment does not belong to the given invoice.


        Requires the `purchase-orders:write` token scope.'
      parameters:
      - name: purchaseInvoice
        in: path
        schema:
          type: integer
        required: true
        description: Purchase invoice ID
        example: '123'
      - name: attachment
        in: path
        schema:
          type: integer
        required: true
        description: Attachment ID
        example: '45'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Attachment deleted.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:write
      operationId: delete-api-purchase-invoices-purchaseinvoice-attachments-attachment
  /api/purchase-invoices/{purchaseInvoice}/attachments/{attachment}/download:
    get:
      tags:
      - Purchase Invoices
      summary: Download Purchase Invoice Attachment
      description: 'Download the attachment file. The response is a file stream (not
        JSON) with `Content-Disposition: attachment` and the original file name, so
        clients save it as a download. The `Content-Type` matches the stored file
        type (e.g. `application/pdf`).


        :::info[Required scope: `purchase-orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Returns 404 if the attachment does not belong to the given invoice.


        Requires the `purchase-orders:read` token scope.'
      parameters:
      - name: purchaseInvoice
        in: path
        schema:
          type: integer
        required: true
        description: Purchase invoice ID
        example: '123'
      - name: attachment
        in: path
        schema:
          type: integer
        required: true
        description: Attachment ID
        example: '45'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/pdf
            Content-Disposition:
              schema:
                type: string
                example: attachment; filename="supplier-invoice-march.pdf"
          content:
            text/plain:
              schema:
                type: string
                example: (binary file stream)
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:read
      operationId: get-api-purchase-invoices-purchaseinvoice-attachments-attachment-download
  /api/purchase-invoices/{purchaseInvoice}/attachments/{attachment}/view:
    get:
      tags:
      - Purchase Invoices
      summary: View Purchase Invoice Attachment
      description: 'Stream the attachment file for inline display. Identical to the
        download endpoint except the response uses `Content-Disposition: inline`,
        so browsers render PDFs and images in the tab instead of saving them.


        :::info[Required scope: `purchase-orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Returns 404 if the attachment does not belong to the given invoice.


        Requires the `purchase-orders:read` token scope.'
      parameters:
      - name: purchaseInvoice
        in: path
        schema:
          type: integer
        required: true
        description: Purchase invoice ID
        example: '123'
      - name: attachment
        in: path
        schema:
          type: integer
        required: true
        description: Attachment ID
        example: '45'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/pdf
            Content-Disposition:
              schema:
                type: string
                example: inline; filename="supplier-invoice-march.pdf"
          content:
            text/plain:
              schema:
                type: string
                example: (binary file stream)
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:read
      operationId: get-api-purchase-invoices-purchaseinvoice-attachments-attachment-view
  /api/purchase-invoices/payment-request-routing:
    get:
      tags:
      - Purchase Invoices
      summary: Preview Payment Approval Routing
      description: 'Preview where a bill payment request of a given amount would be
        routed, before submitting it. Returns the routing mode and the resolved payer
        (if the amount routes directly to a single payer).


        Authentication: Requires Bearer token.


        Query parameters:

        - amount (optional, numeric, >= 0): Amount to evaluate. Defaults to 0.


        Routing modes: approval_levels (multi-step approval chain), payer (single
        designated payer to send the request to), self_payer (the acting user is the
        designated payer, so they approve and record the payment directly instead
        of sending a request to themselves), threshold_approval (single approval against
        a threshold), auto_approve (no approval required).'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 Success
                  value:
                    mode: approval_levels
                    payer:
                      id: 5
                      name: Sam Manager
                      email: sam@company.com
                    payer_configured: true
                    levels_count: 2
                example-1:
                  summary: 200 Auto Approve
                  value:
                    mode: auto_approve
                    payer: null
                    payer_configured: false
                    levels_count: 0
                example-2:
                  summary: 200 Self Payer
                  value:
                    mode: self_payer
                    payer:
                      id: 12
                      name: Jordan Buyer
                      email: jordan@company.com
                    payer_configured: true
                    levels_count: 0
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-purchase-invoices-payment-request-routing
  /api/purchase-invoices/{purchaseInvoice}/payment-request/submit:
    post:
      tags:
      - Purchase Invoices
      summary: Submit Bill Payment for Approval
      description: 'Submit a bill''s outstanding balance for payment authorization.
        Routes the request to the appropriate approval chain, designated payer, or
        auto-approves it depending on configuration and amount.


        Authentication: Requires Bearer token.


        This endpoint has no request body — the outstanding balance is used automatically.
        Returns the updated bill including its payment approval status and generated
        approval steps.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties: {}
              example: {}
      parameters:
      - name: purchaseInvoice
        in: path
        schema:
          type: integer
        required: true
        description: Purchase invoice ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: integer
                  purchase_order_id:
                    type: integer
                  purchase_order_number:
                    type: string
                  supplier_invoice_number:
                    type: string
                  supplier_id:
                    type: integer
                  supplier_name:
                    type: string
                  status:
                    type: string
                  outstanding_balance:
                    type: number
                  payment_approval_status:
                    type: string
                  payment_requested_by:
                    type: integer
                  payment_requested_by_name:
                    type: string
                  payment_requested_at:
                    type: string
                  payment_approved_by:
                    type: string
                    nullable: true
                  payment_approved_by_name:
                    type: string
                    nullable: true
                  payment_approved_at:
                    type: string
                    nullable: true
                  payment_approval_notes:
                    type: string
                    nullable: true
                  payment_approval_steps:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        purchase_invoice_id:
                          type: integer
                        approval_level_id:
                          type: integer
                        level_order:
                          type: integer
                        level_name:
                          type: string
                        status:
                          type: string
                        approver_user_id:
                          type: integer
                        actioned_by:
                          type: string
                          nullable: true
                        actioned_at:
                          type: string
                          nullable: true
                        notes:
                          type: string
                          nullable: true
                  supplier_bank_details_verified:
                    type: boolean
                example:
                  id: 42
                  purchase_order_id: 15
                  purchase_order_number: PO-000015
                  supplier_invoice_number: INV-2025-0042
                  supplier_id: 7
                  supplier_name: Acme Components Ltd
                  status: open
                  outstanding_balance: 1250.0
                  payment_approval_status: pending_approval
                  payment_requested_by: 3
                  payment_requested_by_name: Jane Buyer
                  payment_requested_at: '2026-07-10T14:32:00+00:00'
                  payment_approved_by: null
                  payment_approved_by_name: null
                  payment_approved_at: null
                  payment_approval_notes: null
                  payment_approval_steps:
                  - id: 15
                    purchase_invoice_id: 42
                    approval_level_id: 2
                    level_order: 1
                    level_name: Manager Approval
                    status: pending
                    approver_user_id: 5
                    actioned_by: null
                    actioned_at: null
                    notes: null
                  supplier_bank_details_verified: true
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: This bill has no outstanding balance to submit for payment.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-purchase-invoices-purchaseinvoice-payment-request-submit
  /api/purchase-invoices/{purchaseInvoice}/payment-request/approve:
    post:
      tags:
      - Purchase Invoices
      summary: Approve and Pay Bill
      description: 'Approve a pending bill payment request and record the payment
        in a single step. The payment amount defaults to the bill''s outstanding balance
        when omitted.


        Authentication: Requires Bearer token.


        Fields:

        - amount (optional, numeric, > 0): Payment amount. Defaults to the outstanding
        balance.

        - payment_date (required, date): Date the payment was made.

        - currency_rate (optional, numeric, > 0): Exchange rate. Defaults to the bill''s
        rate.

        - payment_type_id (optional, integer): Payment method ID.

        - external_reference (optional, max 255): External reference; alias ''reference''
        is also accepted.

        - notes (optional, max 1000): Approval notes.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                amount:
                  type: integer
                payment_date:
                  type: string
                payment_type_id:
                  type: integer
                external_reference:
                  type: string
                notes:
                  type: string
              example:
                amount: 1250
                payment_date: '2026-07-10'
                payment_type_id: 2
                external_reference: WIRE-99812
                notes: Verified against receipt.
      parameters:
      - name: purchaseInvoice
        in: path
        schema:
          type: integer
        required: true
        description: Purchase invoice ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: integer
                  purchase_order_id:
                    type: integer
                  purchase_order_number:
                    type: string
                  supplier_invoice_number:
                    type: string
                  supplier_id:
                    type: integer
                  supplier_name:
                    type: string
                  status:
                    type: string
                  outstanding_balance:
                    type: number
                  payment_approval_status:
                    type: string
                  payment_requested_by:
                    type: integer
                  payment_requested_by_name:
                    type: string
                  payment_requested_at:
                    type: string
                  payment_approved_by:
                    type: integer
                  payment_approved_by_name:
                    type: string
                  payment_approved_at:
                    type: string
                  payment_approval_notes:
                    type: string
                  payment_approval_steps:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        purchase_invoice_id:
                          type: integer
                        approval_level_id:
                          type: integer
                        level_order:
                          type: integer
                        level_name:
                          type: string
                        status:
                          type: string
                        approver_user_id:
                          type: integer
                        actioned_by:
                          type: integer
                        actioned_at:
                          type: string
                        notes:
                          type: string
                  supplier_bank_details_verified:
                    type: boolean
                example:
                  id: 42
                  purchase_order_id: 15
                  purchase_order_number: PO-000015
                  supplier_invoice_number: INV-2025-0042
                  supplier_id: 7
                  supplier_name: Acme Components Ltd
                  status: paid
                  outstanding_balance: 0.0
                  payment_approval_status: approved
                  payment_requested_by: 3
                  payment_requested_by_name: Jane Buyer
                  payment_requested_at: '2026-07-10T14:32:00+00:00'
                  payment_approved_by: 5
                  payment_approved_by_name: Sam Manager
                  payment_approved_at: '2026-07-10T15:10:00+00:00'
                  payment_approval_notes: Verified against receipt.
                  payment_approval_steps:
                  - id: 15
                    purchase_invoice_id: 42
                    approval_level_id: 2
                    level_order: 1
                    level_name: Manager Approval
                    status: approved
                    approver_user_id: 5
                    actioned_by: 5
                    actioned_at: '2026-07-10T15:10:00+00:00'
                    notes: Verified against receipt.
                  supplier_bank_details_verified: true
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 422 Validation Error
                  value:
                    message: The payment date field is required.
                    errors:
                      payment_date:
                      - The payment date field is required.
                example-1:
                  summary: 422 Not Pending
                  value:
                    error: This bill's payment is not pending approval.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-purchase-invoices-purchaseinvoice-payment-request-approve
  /api/purchase-invoices/{purchaseInvoice}/payment-request/approve-only:
    post:
      tags:
      - Purchase Invoices
      summary: Approve Bill Payment
      description: 'Approve a pending bill payment request without recording a payment.
        Use this when authorization and payment are handled separately.


        Authentication: Requires Bearer token.


        Fields:

        - notes (optional, max 1000): Approval notes.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                notes:
                  type: string
              example:
                notes: Approved — finance will pay on Friday.
      parameters:
      - name: purchaseInvoice
        in: path
        schema:
          type: integer
        required: true
        description: Purchase invoice ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: integer
                  purchase_order_id:
                    type: integer
                  purchase_order_number:
                    type: string
                  supplier_invoice_number:
                    type: string
                  supplier_id:
                    type: integer
                  supplier_name:
                    type: string
                  status:
                    type: string
                  outstanding_balance:
                    type: number
                  payment_approval_status:
                    type: string
                  payment_requested_by:
                    type: integer
                  payment_requested_by_name:
                    type: string
                  payment_requested_at:
                    type: string
                  payment_approved_by:
                    type: integer
                  payment_approved_by_name:
                    type: string
                  payment_approved_at:
                    type: string
                  payment_approval_notes:
                    type: string
                  payment_approval_steps:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        purchase_invoice_id:
                          type: integer
                        approval_level_id:
                          type: integer
                        level_order:
                          type: integer
                        level_name:
                          type: string
                        status:
                          type: string
                        approver_user_id:
                          type: integer
                        actioned_by:
                          type: integer
                        actioned_at:
                          type: string
                        notes:
                          type: string
                  supplier_bank_details_verified:
                    type: boolean
                example:
                  id: 42
                  purchase_order_id: 15
                  purchase_order_number: PO-000015
                  supplier_invoice_number: INV-2025-0042
                  supplier_id: 7
                  supplier_name: Acme Components Ltd
                  status: open
                  outstanding_balance: 1250.0
                  payment_approval_status: approved
                  payment_requested_by: 3
                  payment_requested_by_name: Jane Buyer
                  payment_requested_at: '2026-07-10T14:32:00+00:00'
                  payment_approved_by: 5
                  payment_approved_by_name: Sam Manager
                  payment_approved_at: '2026-07-10T15:10:00+00:00'
                  payment_approval_notes: Verified against receipt.
                  payment_approval_steps:
                  - id: 15
                    purchase_invoice_id: 42
                    approval_level_id: 2
                    level_order: 1
                    level_name: Manager Approval
                    status: approved
                    approver_user_id: 5
                    actioned_by: 5
                    actioned_at: '2026-07-10T15:10:00+00:00'
                    notes: Verified against receipt.
                  supplier_bank_details_verified: true
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: This bill's payment is not pending approval.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-purchase-invoices-purchaseinvoice-payment-request-approve-only
  /api/purchase-invoices/{purchaseInvoice}/payment-request/record-payment:
    post:
      tags:
      - Purchase Invoices
      summary: Record Bill Payment
      description: 'Record a payment against a bill whose payment has already been
        approved.


        Authentication: Requires Bearer token.


        Fields:

        - amount (required, numeric, > 0): Payment amount.

        - payment_date (required, date): Date the payment was made.

        - currency_rate (optional, numeric, > 0): Exchange rate. Defaults to the bill''s
        rate.

        - payment_type_id (optional, integer): Payment method ID.

        - external_reference (optional, max 255): External reference; alias ''reference''
        is also accepted.

        - notes (optional, max 1000): Payment notes.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                amount:
                  type: integer
                payment_date:
                  type: string
                payment_type_id:
                  type: integer
                external_reference:
                  type: string
              example:
                amount: 1250
                payment_date: '2026-07-11'
                payment_type_id: 2
                external_reference: WIRE-99813
      parameters:
      - name: purchaseInvoice
        in: path
        schema:
          type: integer
        required: true
        description: Purchase invoice ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: integer
                  purchase_order_id:
                    type: integer
                  purchase_order_number:
                    type: string
                  supplier_invoice_number:
                    type: string
                  supplier_id:
                    type: integer
                  supplier_name:
                    type: string
                  status:
                    type: string
                  outstanding_balance:
                    type: number
                  payment_approval_status:
                    type: string
                  payment_requested_by:
                    type: integer
                  payment_requested_by_name:
                    type: string
                  payment_requested_at:
                    type: string
                  payment_approved_by:
                    type: integer
                  payment_approved_by_name:
                    type: string
                  payment_approved_at:
                    type: string
                  payment_approval_notes:
                    type: string
                  payment_approval_steps:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        purchase_invoice_id:
                          type: integer
                        approval_level_id:
                          type: integer
                        level_order:
                          type: integer
                        level_name:
                          type: string
                        status:
                          type: string
                        approver_user_id:
                          type: integer
                        actioned_by:
                          type: integer
                        actioned_at:
                          type: string
                        notes:
                          type: string
                  supplier_bank_details_verified:
                    type: boolean
                example:
                  id: 42
                  purchase_order_id: 15
                  purchase_order_number: PO-000015
                  supplier_invoice_number: INV-2025-0042
                  supplier_id: 7
                  supplier_name: Acme Components Ltd
                  status: paid
                  outstanding_balance: 0.0
                  payment_approval_status: approved
                  payment_requested_by: 3
                  payment_requested_by_name: Jane Buyer
                  payment_requested_at: '2026-07-10T14:32:00+00:00'
                  payment_approved_by: 5
                  payment_approved_by_name: Sam Manager
                  payment_approved_at: '2026-07-10T15:10:00+00:00'
                  payment_approval_notes: Verified against receipt.
                  payment_approval_steps:
                  - id: 15
                    purchase_invoice_id: 42
                    approval_level_id: 2
                    level_order: 1
                    level_name: Manager Approval
                    status: approved
                    approver_user_id: 5
                    actioned_by: 5
                    actioned_at: '2026-07-10T15:10:00+00:00'
                    notes: Verified against receipt.
                  supplier_bank_details_verified: true
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 422 Validation Error
                  value:
                    message: The payment date field is required.
                    errors:
                      payment_date:
                      - The payment date field is required.
                example-1:
                  summary: 422 Not Approved
                  value:
                    error: This bill's payment has not been approved.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-purchase-invoices-purchaseinvoice-payment-request-record-payment
  /api/purchase-invoices/{purchaseInvoice}/payment-request/send-remittance:
    post:
      tags:
      - Purchase Invoices
      summary: Send Invoice Payment Remittance
      description: 'Email a remittance advice to the supplier for a bill that has
        already been paid. The message confirms the payment and can include selected
        invoice documents as attachments; supplier banking details are never included.
        A recorded payment is required first — sending before any payment is recorded
        returns 422. On success the bill''s `remittance_sent_at` timestamp is stamped.


        Authentication: Requires Bearer token.


        Fields:

        - to (required, email): Recipient email address.

        - cc (optional, array of email, max 10): Additional recipients.

        - subject (required, string, max 255): Email subject.

        - note (optional, string, max 2000): Message added to the remittance advice
        body.

        - attachment_ids (optional, array of integer): IDs of invoice attachments
        to include with the email.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                to:
                  type: string
                cc:
                  type: array
                  items:
                    type: string
                subject:
                  type: string
                note:
                  type: string
                attachment_ids:
                  type: array
                  items:
                    type: integer
              example:
                to: accounts@acme-components.example
                cc:
                - ap@acme.com
                subject: Remittance advice for INV-2025-0042
                note: Payment of USD 1,250.00 sent by wire on 2026-07-11.
                attachment_ids:
                - 45
                - 47
      parameters:
      - name: purchaseInvoice
        in: path
        schema:
          type: integer
        required: true
        description: Purchase invoice ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: integer
                  purchase_order_id:
                    type: integer
                  purchase_order_number:
                    type: string
                  supplier_invoice_number:
                    type: string
                  supplier_id:
                    type: integer
                  supplier_name:
                    type: string
                  status:
                    type: string
                  outstanding_balance:
                    type: number
                  payment_approval_status:
                    type: string
                  payment_requested_by:
                    type: integer
                  payment_requested_by_name:
                    type: string
                  payment_requested_at:
                    type: string
                  payment_approved_by:
                    type: integer
                  payment_approved_by_name:
                    type: string
                  payment_approved_at:
                    type: string
                  payment_approval_notes:
                    type: string
                  remittance_sent_at:
                    type: string
                  payment_approval_steps:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        purchase_invoice_id:
                          type: integer
                        approval_level_id:
                          type: integer
                        level_order:
                          type: integer
                        level_name:
                          type: string
                        status:
                          type: string
                        approver_user_id:
                          type: integer
                        actioned_by:
                          type: integer
                        actioned_at:
                          type: string
                        notes:
                          type: string
                  supplier_bank_details_verified:
                    type: boolean
                example:
                  id: 42
                  purchase_order_id: 15
                  purchase_order_number: PO-000015
                  supplier_invoice_number: INV-2025-0042
                  supplier_id: 7
                  supplier_name: Acme Components Ltd
                  status: paid
                  outstanding_balance: 0.0
                  payment_approval_status: approved
                  payment_requested_by: 3
                  payment_requested_by_name: Jane Buyer
                  payment_requested_at: '2026-07-10T14:32:00+00:00'
                  payment_approved_by: 5
                  payment_approved_by_name: Sam Manager
                  payment_approved_at: '2026-07-10T15:10:00+00:00'
                  payment_approval_notes: Verified against receipt.
                  remittance_sent_at: '2026-07-11T09:20:00+00:00'
                  payment_approval_steps:
                  - id: 15
                    purchase_invoice_id: 42
                    approval_level_id: 2
                    level_order: 1
                    level_name: Manager Approval
                    status: approved
                    approver_user_id: 5
                    actioned_by: 5
                    actioned_at: '2026-07-10T15:10:00+00:00'
                    notes: Verified against receipt.
                  supplier_bank_details_verified: true
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 422 No Recorded Payment
                  value:
                    error: Remittance advice can only be sent after a payment has
                      been recorded on the bill.
                example-1:
                  summary: 422 Validation Error
                  value:
                    message: The subject field is required.
                    errors:
                      subject:
                      - The subject field is required.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-purchase-invoices-purchaseinvoice-payment-request-send-remittance
  /api/purchase-invoices/{purchaseInvoice}/payment-request/scan-proof:
    post:
      tags:
      - Purchase Invoices
      summary: Scan Invoice Payment Proof
      description: 'Scan a payment proof — a bank transfer confirmation image or PDF
        — and return the payment details read from it, used to pre-fill the record-payment
        form. Nothing is stored: the file is only persisted later (as a payment-proof
        attachment) when the payment is actually recorded.


        Send as `multipart/form-data` with a single `file` field. Accepted types:
        PDF, JPG/JPEG, PNG, GIF, WEBP, TIFF, BMP. Maximum size 10 MB. If the extraction
        service is unavailable the endpoint returns 422.


        Authentication: Requires Bearer token.


        Response fields (each nullable when a value cannot be read):

        - reference: Payment reference or transaction ID.

        - amount: Payment amount.

        - currency_code: ISO currency code.

        - value_date: Date the payment settled (YYYY-MM-DD).

        - payee_name: Beneficiary name shown on the proof.'
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                file:
                  type: string
                  description: 'Required. Payment proof to scan. Allowed types: pdf,
                    jpg, jpeg, png, gif, webp, tiff, bmp. Max size 10 MB.'
                  format: binary
      parameters:
      - name: purchaseInvoice
        in: path
        schema:
          type: integer
        required: true
        description: Purchase invoice ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      reference:
                        type: string
                      amount:
                        type: integer
                      currency_code:
                        type: string
                      value_date:
                        type: string
                      payee_name:
                        type: string
                example:
                  data:
                    reference: WIRE-99813
                    amount: 1250
                    currency_code: USD
                    value_date: '2026-07-11'
                    payee_name: Acme Components Ltd
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 422 Extraction Unavailable
                  value:
                    error: The payment proof could not be scanned. Please enter the
                      details manually.
                example-1:
                  summary: 422 Validation Error
                  value:
                    message: A payment proof image or PDF is required to scan.
                    errors:
                      file:
                      - A payment proof image or PDF is required to scan.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-purchase-invoices-purchaseinvoice-payment-request-scan-proof
  /api/purchase-invoices/{purchaseInvoice}/payment-request/reject:
    post:
      tags:
      - Purchase Invoices
      summary: Reject Bill Payment Request
      description: 'Reject a pending bill payment request.


        Authentication: Requires Bearer token.


        Fields:

        - reason (optional, max 500): Reason for rejection.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                reason:
                  type: string
              example:
                reason: Duplicate of INV-2025-0039.
      parameters:
      - name: purchaseInvoice
        in: path
        schema:
          type: integer
        required: true
        description: Purchase invoice ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: integer
                  purchase_order_id:
                    type: integer
                  purchase_order_number:
                    type: string
                  supplier_invoice_number:
                    type: string
                  supplier_id:
                    type: integer
                  supplier_name:
                    type: string
                  status:
                    type: string
                  outstanding_balance:
                    type: number
                  payment_approval_status:
                    type: string
                  payment_requested_by:
                    type: integer
                  payment_requested_by_name:
                    type: string
                  payment_requested_at:
                    type: string
                  payment_approved_by:
                    type: string
                    nullable: true
                  payment_approved_by_name:
                    type: string
                    nullable: true
                  payment_approved_at:
                    type: string
                    nullable: true
                  payment_approval_notes:
                    type: string
                  payment_approval_steps:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        purchase_invoice_id:
                          type: integer
                        approval_level_id:
                          type: integer
                        level_order:
                          type: integer
                        level_name:
                          type: string
                        status:
                          type: string
                        approver_user_id:
                          type: integer
                        actioned_by:
                          type: integer
                        actioned_at:
                          type: string
                        notes:
                          type: string
                          nullable: true
                  supplier_bank_details_verified:
                    type: boolean
                example:
                  id: 42
                  purchase_order_id: 15
                  purchase_order_number: PO-000015
                  supplier_invoice_number: INV-2025-0042
                  supplier_id: 7
                  supplier_name: Acme Components Ltd
                  status: open
                  outstanding_balance: 1250.0
                  payment_approval_status: rejected
                  payment_requested_by: 3
                  payment_requested_by_name: Jane Buyer
                  payment_requested_at: '2026-07-10T14:32:00+00:00'
                  payment_approved_by: null
                  payment_approved_by_name: null
                  payment_approved_at: null
                  payment_approval_notes: Duplicate of INV-2025-0039.
                  payment_approval_steps:
                  - id: 15
                    purchase_invoice_id: 42
                    approval_level_id: 2
                    level_order: 1
                    level_name: Manager Approval
                    status: rejected
                    approver_user_id: 5
                    actioned_by: 5
                    actioned_at: '2026-07-10T15:12:00+00:00'
                    notes: null
                  supplier_bank_details_verified: true
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: This bill's payment is not pending approval.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-purchase-invoices-purchaseinvoice-payment-request-reject
  /api/purchase-invoices/{purchaseInvoice}/payment-request/revert-to-draft:
    post:
      tags:
      - Purchase Invoices
      summary: Withdraw Bill Payment Request
      description: 'Withdraw an untouched pending payment request, returning the bill
        to the not-requested state. Only allowed while no approval step has been actioned.


        Authentication: Requires Bearer token.


        Fields:

        - reason (optional, max 500): Reason for withdrawing the request.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                reason:
                  type: string
              example:
                reason: Submitted in error.
      parameters:
      - name: purchaseInvoice
        in: path
        schema:
          type: integer
        required: true
        description: Purchase invoice ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: integer
                  purchase_order_id:
                    type: integer
                  purchase_order_number:
                    type: string
                  supplier_invoice_number:
                    type: string
                  supplier_id:
                    type: integer
                  supplier_name:
                    type: string
                  status:
                    type: string
                  outstanding_balance:
                    type: number
                  payment_approval_status:
                    type: string
                  payment_requested_by:
                    type: string
                    nullable: true
                  payment_requested_by_name:
                    type: string
                    nullable: true
                  payment_requested_at:
                    type: string
                    nullable: true
                  payment_approved_by:
                    type: string
                    nullable: true
                  payment_approved_by_name:
                    type: string
                    nullable: true
                  payment_approved_at:
                    type: string
                    nullable: true
                  payment_approval_notes:
                    type: string
                    nullable: true
                  payment_approval_steps:
                    type: array
                  supplier_bank_details_verified:
                    type: boolean
                example:
                  id: 42
                  purchase_order_id: 15
                  purchase_order_number: PO-000015
                  supplier_invoice_number: INV-2025-0042
                  supplier_id: 7
                  supplier_name: Acme Components Ltd
                  status: open
                  outstanding_balance: 1250.0
                  payment_approval_status: not_requested
                  payment_requested_by: null
                  payment_requested_by_name: null
                  payment_requested_at: null
                  payment_approved_by: null
                  payment_approved_by_name: null
                  payment_approved_at: null
                  payment_approval_notes: null
                  payment_approval_steps: []
                  supplier_bank_details_verified: true
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: This payment request has already been actioned and cannot
                    be withdrawn.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-purchase-invoices-purchaseinvoice-payment-request-revert-to-draft
  /api/purchase-invoices/{purchaseInvoice}/payment-approval-steps:
    get:
      tags:
      - Purchase Invoices
      summary: List Bill Payment Approval Steps
      description: 'List the payment approval steps for a bill, in level order. Each
        step represents one level of the multi-step approval chain.


        Authentication: Requires Bearer token.'
      parameters:
      - name: purchaseInvoice
        in: path
        schema:
          type: integer
        required: true
        description: Purchase invoice ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        purchase_invoice_id:
                          type: integer
                        approval_level_id:
                          type: integer
                        level_order:
                          type: integer
                        level_name:
                          type: string
                        status:
                          type: string
                        approver_user_id:
                          type: integer
                        approver_user:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            email:
                              type: string
                        actioned_by:
                          type: integer
                        actioned_by_user:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        actioned_at:
                          type: string
                        notes:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                example:
                  data:
                  - id: 15
                    purchase_invoice_id: 42
                    approval_level_id: 2
                    level_order: 1
                    level_name: Manager Approval
                    status: approved
                    approver_user_id: 5
                    approver_user:
                      id: 5
                      name: Sam Manager
                      email: sam@company.com
                    actioned_by: 5
                    actioned_by_user:
                      id: 5
                      name: Sam Manager
                    actioned_at: '2026-07-10T15:10:00+00:00'
                    notes: Looks good.
                    created_at: '2026-07-10T14:32:00+00:00'
                    updated_at: '2026-07-10T15:10:00+00:00'
                  - id: 16
                    purchase_invoice_id: 42
                    approval_level_id: 3
                    level_order: 2
                    level_name: Director Approval
                    status: pending
                    approver_user_id: 9
                    approver_user:
                      id: 9
                      name: Dana Director
                      email: dana@company.com
                    actioned_by: null
                    actioned_by_user: null
                    actioned_at: null
                    notes: null
                    created_at: '2026-07-10T14:32:00+00:00'
                    updated_at: '2026-07-10T14:32:00+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-purchase-invoices-purchaseinvoice-payment-approval-steps
  /api/purchase-invoices/{purchaseInvoice}/payment-approval-steps/approve:
    post:
      tags:
      - Purchase Invoices
      summary: Approve Bill Payment Approval Step
      description: 'Approve the current pending step in a bill''s payment approval
        chain. When the final step is approved the bill''s payment becomes approved.


        Authentication: Requires Bearer token.


        Fields:

        - notes (optional, max 1000): Notes for this approval step.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                notes:
                  type: string
              example:
                notes: Looks good.
      parameters:
      - name: purchaseInvoice
        in: path
        schema:
          type: integer
        required: true
        description: Purchase invoice ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      purchase_invoice_id:
                        type: integer
                      approval_level_id:
                        type: integer
                      level_order:
                        type: integer
                      level_name:
                        type: string
                      status:
                        type: string
                      approver_user_id:
                        type: integer
                      approver_user:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          email:
                            type: string
                      actioned_by:
                        type: integer
                      actioned_by_user:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      actioned_at:
                        type: string
                      notes:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 15
                    purchase_invoice_id: 42
                    approval_level_id: 2
                    level_order: 1
                    level_name: Manager Approval
                    status: approved
                    approver_user_id: 5
                    approver_user:
                      id: 5
                      name: Sam Manager
                      email: sam@company.com
                    actioned_by: 5
                    actioned_by_user:
                      id: 5
                      name: Sam Manager
                    actioned_at: '2026-07-10T15:10:00+00:00'
                    notes: Looks good.
                    created_at: '2026-07-10T14:32:00+00:00'
                    updated_at: '2026-07-10T15:10:00+00:00'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: There is no pending approval step to approve.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-purchase-invoices-purchaseinvoice-payment-approval-steps-approve
  /api/purchase-invoices/{purchaseInvoice}/payment-approval-steps/reject:
    post:
      tags:
      - Purchase Invoices
      summary: Reject Bill Payment Approval Step
      description: 'Reject the current pending step in a bill''s payment approval
        chain, rejecting the overall payment request.


        Authentication: Requires Bearer token.


        Fields:

        - notes (optional, max 1000): Notes explaining the rejection.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                notes:
                  type: string
              example:
                notes: Amount exceeds agreed PO value.
      parameters:
      - name: purchaseInvoice
        in: path
        schema:
          type: integer
        required: true
        description: Purchase invoice ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      purchase_invoice_id:
                        type: integer
                      approval_level_id:
                        type: integer
                      level_order:
                        type: integer
                      level_name:
                        type: string
                      status:
                        type: string
                      approver_user_id:
                        type: integer
                      approver_user:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          email:
                            type: string
                      actioned_by:
                        type: integer
                      actioned_by_user:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      actioned_at:
                        type: string
                      notes:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 15
                    purchase_invoice_id: 42
                    approval_level_id: 2
                    level_order: 1
                    level_name: Manager Approval
                    status: rejected
                    approver_user_id: 5
                    approver_user:
                      id: 5
                      name: Sam Manager
                      email: sam@company.com
                    actioned_by: 5
                    actioned_by_user:
                      id: 5
                      name: Sam Manager
                    actioned_at: '2026-07-10T15:10:00+00:00'
                    notes: Amount exceeds agreed PO value.
                    created_at: '2026-07-10T14:32:00+00:00'
                    updated_at: '2026-07-10T15:10:00+00:00'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: There is no pending approval step to reject.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-purchase-invoices-purchaseinvoice-payment-approval-steps-reject
  /api/purchase-invoice-approval-levels:
    get:
      tags:
      - Purchase Invoices
      summary: List Purchase Invoice Approval Levels
      description: 'List the configured bill payment approval levels, in level order.
        Levels define the multi-step approval chain and the amount threshold at which
        each level applies.


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        level_order:
                          type: integer
                        name:
                          type: string
                        threshold_amount:
                          type: number
                        approver_user_id:
                          type: integer
                        approver_role_id:
                          type: string
                          nullable: true
                        approver_user:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            email:
                              type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                example:
                  data:
                  - id: 2
                    level_order: 1
                    name: Manager Approval
                    threshold_amount: 5000.0
                    approver_user_id: 5
                    approver_role_id: null
                    approver_user:
                      id: 5
                      name: Sam Manager
                      email: sam@company.com
                    created_at: '2026-07-01T09:00:00+00:00'
                    updated_at: '2026-07-01T09:00:00+00:00'
                  - id: 3
                    level_order: 2
                    name: Director Approval
                    threshold_amount: 25000.0
                    approver_user_id: 9
                    approver_role_id: null
                    approver_user:
                      id: 9
                      name: Dana Director
                      email: dana@company.com
                    created_at: '2026-07-01T09:05:00+00:00'
                    updated_at: '2026-07-01T09:05:00+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-purchase-invoice-approval-levels
    post:
      tags:
      - Purchase Invoices
      summary: Create Purchase Invoice Approval Level
      description: 'Create a bill payment approval level.


        Authentication: Requires Bearer token.


        Fields:

        - level_order (required, integer, >= 1, unique): Position of this level in
        the approval chain. Must be unique across levels — reusing an existing order
        returns a 422 validation error.

        - name (required, max 100): Display name for the level.

        - threshold_amount (required, numeric, >= 0): Amount at or above which this
        level''s approval is required.

        - approver_user_id (optional, integer): Designated approver user ID.

        - approver_role_id (optional, integer): Designated approver role ID.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                level_order:
                  type: integer
                name:
                  type: string
                threshold_amount:
                  type: integer
                approver_user_id:
                  type: integer
                approver_role_id:
                  type: string
                  nullable: true
              example:
                level_order: 1
                name: Manager Approval
                threshold_amount: 5000
                approver_user_id: 5
                approver_role_id: null
      parameters: []
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      level_order:
                        type: integer
                      name:
                        type: string
                      threshold_amount:
                        type: number
                      approver_user_id:
                        type: integer
                      approver_role_id:
                        type: string
                        nullable: true
                      approver_user:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          email:
                            type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 2
                    level_order: 1
                    name: Manager Approval
                    threshold_amount: 5000.0
                    approver_user_id: 5
                    approver_role_id: null
                    approver_user:
                      id: 5
                      name: Sam Manager
                      email: sam@company.com
                    created_at: '2026-07-01T09:00:00+00:00'
                    updated_at: '2026-07-01T09:00:00+00:00'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      name:
                        type: array
                        items:
                          type: string
                example:
                  message: The name field is required.
                  errors:
                    name:
                    - The name field is required.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-purchase-invoice-approval-levels
  /api/purchase-invoice-approval-levels/{purchaseInvoiceApprovalLevel}:
    put:
      tags:
      - Purchase Invoices
      summary: Update Purchase Invoice Approval Level
      description: 'Update a bill payment approval level. All fields are optional;
        only supplied fields are changed.


        Authentication: Requires Bearer token.


        Fields:

        - level_order (optional, integer, >= 1, unique): Position of this level in
        the approval chain. Must be unique across levels (the level being updated
        is excluded from the check); reusing another level''s order returns a 422
        validation error.

        - name (optional, max 100): Display name for the level.

        - threshold_amount (optional, numeric, >= 0): Amount at or above which this
        level''s approval is required.

        - approver_user_id (optional, integer): Designated approver user ID.

        - approver_role_id (optional, integer): Designated approver role ID.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                threshold_amount:
                  type: integer
                approver_user_id:
                  type: integer
              example:
                threshold_amount: 7500
                approver_user_id: 8
      parameters:
      - name: purchaseInvoiceApprovalLevel
        in: path
        schema:
          type: integer
        required: true
        description: Approval level ID
        example: '2'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      level_order:
                        type: integer
                      name:
                        type: string
                      threshold_amount:
                        type: number
                      approver_user_id:
                        type: integer
                      approver_role_id:
                        type: string
                        nullable: true
                      approver_user:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          email:
                            type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 2
                    level_order: 1
                    name: Manager Approval
                    threshold_amount: 7500.0
                    approver_user_id: 8
                    approver_role_id: null
                    approver_user:
                      id: 5
                      name: Sam Manager
                      email: sam@company.com
                    created_at: '2026-07-01T09:00:00+00:00'
                    updated_at: '2026-07-01T09:00:00+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-purchase-invoice-approval-levels-purchaseinvoiceapprovallevel
    delete:
      tags:
      - Purchase Invoices
      summary: Delete Purchase Invoice Approval Level
      description: 'Delete a bill payment approval level.


        Authentication: Requires Bearer token.'
      parameters:
      - name: purchaseInvoiceApprovalLevel
        in: path
        schema:
          type: integer
        required: true
        description: Approval level ID
        example: '2'
      responses:
        '204':
          description: No Content
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            text/plain:
              schema:
                type: string
                example: ''
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-purchase-invoice-approval-levels-purchaseinvoiceapprovallevel
  /api/purchase-invoices/supplier-payments:
    get:
      tags:
      - Purchase Invoices
      summary: List Supplier Payments
      description: 'Paginated list of supplier payments, newest first.


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        supplier_id:
                          type: integer
                        supplier_name:
                          type: string
                        payment_date:
                          type: string
                        payment_type_id:
                          type: integer
                        payment_type_name:
                          type: string
                        external_reference:
                          type: string
                        total_amount:
                          type: integer
                        currency_code:
                          type: string
                        created_at:
                          type: string
                        allocations:
                          type: array
                          items:
                            type: object
                            properties:
                              id:
                                type: integer
                              purchase_invoice_id:
                                type: integer
                              reference:
                                type: string
                              amount:
                                type: integer
                              payment_id:
                                type: integer
                  current_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 1
                    supplier_id: 12
                    supplier_name: Acme Supplies Ltd
                    payment_date: '2026-07-11'
                    payment_type_id: 1
                    payment_type_name: Cash
                    external_reference: WIRE-42
                    total_amount: 5000
                    currency_code: USD
                    created_at: '2026-07-11T12:00:00Z'
                    allocations:
                    - id: 1
                      purchase_invoice_id: 42
                      reference: INV-2026-101
                      amount: 4120
                      payment_id: 90
                  current_page: 1
                  per_page: 10
                  total: 1
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-purchase-invoices-supplier-payments
    post:
      tags:
      - Purchase Invoices
      summary: Record Supplier Payment
      description: 'Record one supplier-level payment allocated across multiple open
        invoices. All-or-nothing: the run is rejected (422) if any allocation exceeds
        its invoice''s outstanding balance, targets another supplier''s invoice, or
        repeats an invoice.


        Fields:

        - supplier_id (required)

        - payment_date (required, Y-m-d)

        - payment_type_id (optional; defaults to Cash)

        - external_reference (optional; stored on the payment run and suffixed per
        invoice on the individual payment records)

        - allocations (required, min 1): purchase_invoice_id + amount (> 0, at most
        the invoice''s outstanding balance)


        Each allocation creates a regular invoice payment, so invoice payment statuses
        (paid / partially paid) update immediately.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                supplier_id:
                  type: integer
                payment_date:
                  type: string
                payment_type_id:
                  type: integer
                external_reference:
                  type: string
                allocations:
                  type: array
                  items:
                    type: object
                    properties:
                      purchase_invoice_id:
                        type: integer
                      amount:
                        type: integer
              example:
                supplier_id: 12
                payment_date: '2026-07-11'
                payment_type_id: 1
                external_reference: WIRE-42
                allocations:
                - purchase_invoice_id: 42
                  amount: 4120
                - purchase_invoice_id: 43
                  amount: 880
      parameters: []
      responses:
        '201':
          description: Created
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      supplier_id:
                        type: integer
                      supplier_name:
                        type: string
                      payment_date:
                        type: string
                      payment_type_id:
                        type: integer
                      payment_type_name:
                        type: string
                      external_reference:
                        type: string
                      total_amount:
                        type: integer
                      currency_code:
                        type: string
                      created_at:
                        type: string
                      allocations:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            purchase_invoice_id:
                              type: integer
                            reference:
                              type: string
                            amount:
                              type: integer
                            payment_id:
                              type: integer
                example:
                  data:
                    id: 1
                    supplier_id: 12
                    supplier_name: Acme Supplies Ltd
                    payment_date: '2026-07-11'
                    payment_type_id: 1
                    payment_type_name: Cash
                    external_reference: WIRE-42
                    total_amount: 5000
                    currency_code: USD
                    created_at: '2026-07-11T12:00:00Z'
                    allocations:
                    - id: 1
                      purchase_invoice_id: 42
                      reference: INV-2026-101
                      amount: 4120
                      payment_id: 90
                    - id: 2
                      purchase_invoice_id: 43
                      reference: INV-2026-102
                      amount: 880
                      payment_id: 91
        '422':
          description: Unprocessable Entity
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Allocation for invoice INV-2026-101 exceeds its outstanding
                    balance of 4120.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-purchase-invoices-supplier-payments
  /api/purchase-invoices/supplier-payments/allocation-suggestion:
    get:
      tags:
      - Purchase Invoices
      summary: Get Allocation Suggestion
      description: 'The supplier''s open (unpaid or partially paid) invoices with
        a suggested allocation of the given total, distributed oldest due date first
        — the prefill for a payment run.


        Authentication: Requires Bearer token.'
      parameters:
      - name: supplier_id
        in: query
        schema:
          type: integer
        description: The supplier whose open invoices to allocate against
        example: '12'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      invoices:
                        type: array
                        items:
                          type: object
                          properties:
                            purchase_invoice_id:
                              type: integer
                            supplier_invoice_number:
                              type: string
                            purchase_order_number:
                              type: string
                            invoice_date:
                              type: string
                            due_date:
                              type: string
                            payment_due_status:
                              type: string
                            currency_code:
                              type: string
                            outstanding:
                              type: integer
                            suggested_amount:
                              type: integer
                      suggested_total:
                        type: integer
                example:
                  data:
                    invoices:
                    - purchase_invoice_id: 42
                      supplier_invoice_number: INV-2026-101
                      purchase_order_number: PO-2026-0015
                      invoice_date: '2026-04-27'
                      due_date: '2026-05-27'
                      payment_due_status: overdue
                      currency_code: USD
                      outstanding: 4120
                      suggested_amount: 4120
                    suggested_total: 4120
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-purchase-invoices-supplier-payments-allocation-suggestion
  /api/vendor-returns:
    get:
      tags:
      - Vendor Returns
      summary: List Vendor Returns
      description: 'Paginated list of vendor returns, sorted by return date (newest
        first) by default. Archived returns are excluded unless filter[archived] is
        provided.


        Authentication: Requires Bearer token.


        Filters:

        - filter[search]: matches return ID (exact), return number, vendor RMA number,
        supplier name, item SKU, and purchase order number

        - filter[return_status]: draft, authorized, shipped, completed, void

        - filter[supplier_id], filter[warehouse_id]: exact ID match

        - filter[purchase_order_id]: returns containing lines from that purchase order

        - filter[return_date.from] / filter[return_date.to]: date range (YYYY-MM-DD,
        inclusive)

        - filter[archived]: ''only'' = archived only, ''all'' = both; omitted = active
        only


        Allowed sorts: id, vendor_return_number, supplier_rma_number, return_date,
        return_status, created_at, updated_at, supplier_name. Prefix with - for descending;
        default is -return_date.


        Pagination: page and per_page (default 10).'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        vendor_return_number:
                          type: string
                        return_status:
                          type: string
                        return_date:
                          type: string
                        supplier_rma_number:
                          type: string
                        reason:
                          type: string
                        notes:
                          type: string
                        supplier_id:
                          type: integer
                        supplier:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            email:
                              type: string
                        warehouse_id:
                          type: integer
                        warehouse:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        currency_id:
                          type: integer
                        currency:
                          type: object
                          properties:
                            id:
                              type: integer
                            code:
                              type: string
                        purchase_order:
                          type: object
                          properties:
                            id:
                              type: integer
                            purchase_order_number:
                              type: string
                        is_fully_credited:
                          type: boolean
                        total_cost:
                          type: integer
                        lines:
                          type: array
                          items:
                            type: object
                            properties:
                              id:
                                type: integer
                              purchase_order_line_id:
                                type: integer
                              product_id:
                                type: integer
                              product:
                                type: object
                                properties:
                                  id:
                                    type: integer
                                  sku:
                                    type: string
                                  name:
                                    type: string
                              quantity:
                                type: integer
                              unit_cost:
                                type: integer
                              reason:
                                type: string
                              is_write_off:
                                type: boolean
                              clearing_quantity:
                                type: integer
                              ap_quantity:
                                type: integer
                              credited_quantity:
                                type: integer
                              purchase_order_number:
                                type: string
                        credits:
                          type: array
                        created_at:
                          type: string
                        updated_at:
                          type: string
                        archived_at:
                          type: string
                          nullable: true
                        accounting_exempt:
                          type: boolean
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                    items:
                      type: object
                      properties:
                        url:
                          type: string
                          nullable: true
                        label:
                          type: string
                        active:
                          type: boolean
                  next_page_url:
                    type: string
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 12
                    vendor_return_number: VR-00012
                    return_status: shipped
                    return_date: '2026-03-14'
                    supplier_rma_number: RMA-4821
                    reason: Damaged in transit
                    notes: Carton crushed on arrival; supplier approved the return.
                    supplier_id: 5
                    supplier:
                      id: 5
                      name: Acme Supplies
                      email: orders@acmesupplies.com
                    warehouse_id: 2
                    warehouse:
                      id: 2
                      name: Main Warehouse
                    currency_id: 1
                    currency:
                      id: 1
                      code: USD
                    purchase_order:
                      id: 101
                      purchase_order_number: PO-00101
                    is_fully_credited: false
                    total_cost: 250
                    lines:
                    - id: 34
                      purchase_order_line_id: 210
                      product_id: 88
                      product:
                        id: 88
                        sku: WIDGET-BLUE
                        name: Blue Widget
                      quantity: 10
                      unit_cost: 25
                      reason: Damaged in transit
                      is_write_off: false
                      clearing_quantity: 6
                      ap_quantity: 4
                      credited_quantity: 0
                      purchase_order_number: PO-00101
                    credits: []
                    created_at: '2026-03-14T15:22:08.000000Z'
                    updated_at: '2026-03-15T09:10:44.000000Z'
                    archived_at: null
                    accounting_exempt: false
                  first_page_url: https://yourdomain.example/api/vendor-returns?page=1
                  from: 1
                  last_page: 3
                  last_page_url: https://yourdomain.example/api/vendor-returns?page=3
                  links:
                  - url: null
                    label: '&laquo; Previous'
                    active: false
                  - url: https://yourdomain.example/api/vendor-returns?page=1
                    label: '1'
                    active: true
                  - url: https://yourdomain.example/api/vendor-returns?page=2
                    label: '2'
                    active: false
                  - url: https://yourdomain.example/api/vendor-returns?page=2
                    label: Next &raquo;
                    active: false
                  next_page_url: https://yourdomain.example/api/vendor-returns?page=2
                  path: https://yourdomain.example/api/vendor-returns
                  per_page: 10
                  prev_page_url: null
                  to: 10
                  total: 24
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-vendor-returns
    post:
      tags:
      - Vendor Returns
      summary: Create Vendor Return
      description: "Create a draft vendor return for goods that will be physically\
        \ sent back to a supplier.\n\nAuthentication: Requires Bearer token.\n\nBody\
        \ fields:\n- supplier_id (integer, required): supplier the goods return to\n\
        - warehouse_id (integer, required): warehouse the goods ship out of\n- return_date\
        \ (date, required, YYYY-MM-DD)\n- supplier_rma_number (string, optional, max\
        \ 255): the supplier's RMA reference\n- reason (string, optional, max 255)\n\
        - notes (string, optional)\n- currency_id (integer, optional): defaults to\
        \ the account's base currency\n- lines (array, optional) - each line:\n  -\
        \ purchase_order_line_id (integer, required unless product_id is given): the\
        \ received purchase order line being returned\n  - product_id (integer, required\
        \ unless purchase_order_line_id is given; derived from the purchase order\
        \ line when omitted)\n  - quantity (number, required, greater than 0)\n  -\
        \ unit_cost (number, optional; when omitted it is filled from the cost basis\
        \ of the purchase order line)\n  - reason (string, optional, max 255)\n  -\
        \ is_write_off (boolean, optional, default false): write-off lines are expensed\
        \ to cost of goods sold at ship instead of the clearing/accounts-payable split\n\
        \nValidation invariants:\n- Single purchase order: every line that references\
        \ a purchase order line must belong to the SAME purchase order. Mixing lines\
        \ from different purchase orders is rejected.\n- Returnable quantity: per\
        \ purchase order line, the return quantity cannot exceed received quantity\
        \ minus what was already returned (across other non-void returns and historical\
        \ credits). Check availability first with List Returnable Lines For Purchase\
        \ Order."
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                supplier_id:
                  type: integer
                warehouse_id:
                  type: integer
                return_date:
                  type: string
                supplier_rma_number:
                  type: string
                reason:
                  type: string
                notes:
                  type: string
                currency_id:
                  type: integer
                lines:
                  type: array
                  items:
                    type: object
                    properties:
                      purchase_order_line_id:
                        type: integer
                      product_id:
                        type: integer
                      quantity:
                        type: integer
                      unit_cost:
                        type: integer
                      reason:
                        type: string
                      is_write_off:
                        type: boolean
              example:
                supplier_id: 5
                warehouse_id: 2
                return_date: '2026-03-14'
                supplier_rma_number: RMA-4821
                reason: Damaged in transit
                notes: Carton crushed on arrival; supplier approved the return.
                currency_id: 1
                lines:
                - purchase_order_line_id: 210
                  product_id: 88
                  quantity: 10
                  unit_cost: 25
                  reason: Damaged in transit
                  is_write_off: false
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      vendor_return_number:
                        type: string
                      return_status:
                        type: string
                      return_date:
                        type: string
                      supplier_rma_number:
                        type: string
                      reason:
                        type: string
                      notes:
                        type: string
                      supplier_id:
                        type: integer
                      supplier:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          email:
                            type: string
                      warehouse_id:
                        type: integer
                      warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      currency_id:
                        type: integer
                      purchase_order:
                        type: object
                        properties:
                          id:
                            type: integer
                          purchase_order_number:
                            type: string
                      is_fully_credited:
                        type: boolean
                      total_cost:
                        type: integer
                      lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            purchase_order_line_id:
                              type: integer
                            product_id:
                              type: integer
                            product:
                              type: object
                              properties:
                                id:
                                  type: integer
                                sku:
                                  type: string
                                name:
                                  type: string
                            quantity:
                              type: integer
                            unit_cost:
                              type: integer
                            reason:
                              type: string
                            is_write_off:
                              type: boolean
                            clearing_quantity:
                              type: string
                              nullable: true
                            ap_quantity:
                              type: string
                              nullable: true
                            credited_quantity:
                              type: integer
                            purchase_order_number:
                              type: string
                      credits:
                        type: array
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                      accounting_exempt:
                        type: boolean
                  message:
                    type: string
                example:
                  data:
                    id: 12
                    vendor_return_number: VR-00012
                    return_status: draft
                    return_date: '2026-03-14'
                    supplier_rma_number: RMA-4821
                    reason: Damaged in transit
                    notes: Carton crushed on arrival; supplier approved the return.
                    supplier_id: 5
                    supplier:
                      id: 5
                      name: Acme Supplies
                      email: orders@acmesupplies.com
                    warehouse_id: 2
                    warehouse:
                      id: 2
                      name: Main Warehouse
                    currency_id: 1
                    purchase_order:
                      id: 101
                      purchase_order_number: PO-00101
                    is_fully_credited: false
                    total_cost: 250
                    lines:
                    - id: 34
                      purchase_order_line_id: 210
                      product_id: 88
                      product:
                        id: 88
                        sku: WIDGET-BLUE
                        name: Blue Widget
                      quantity: 10
                      unit_cost: 25
                      reason: Damaged in transit
                      is_write_off: false
                      clearing_quantity: null
                      ap_quantity: null
                      credited_quantity: 0
                      purchase_order_number: PO-00101
                    credits: []
                    created_at: '2026-03-14T15:22:08.000000Z'
                    updated_at: '2026-03-15T09:10:44.000000Z'
                    archived_at: null
                    accounting_exempt: false
                  message: The vendor return created successfully
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      supplier_id:
                        type: array
                        items:
                          type: string
                      lines.1.purchase_order_line_id:
                        type: array
                        items:
                          type: string
                      lines.0.quantity:
                        type: array
                        items:
                          type: string
                example:
                  message: The given data was invalid.
                  errors:
                    supplier_id:
                    - Supplier is required.
                    lines.1.purchase_order_line_id:
                    - All return lines must belong to the same purchase order.
                    lines.0.quantity:
                    - Return quantity (10) exceeds the available (received minus already
                      returned) quantity (6) for this purchase order line.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-vendor-returns
  /api/vendor-returns/{vendorReturn}:
    get:
      tags:
      - Vendor Returns
      summary: Get Vendor Return
      description: 'Get a single vendor return with its lines, outbound shipments,
        and any vendor credits created from it.


        Authentication: Requires Bearer token.


        Response notes:

        - purchase_order is derived from the return''s lines (a return references
        purchase orders through its lines)

        - lines[].clearing_quantity / lines[].ap_quantity are set at ship time: the
        un-invoiced portion posts to the vendor-returns clearing account, the invoiced
        portion posts to accounts payable

        - lines[].credited_quantity is the quantity already covered by vendor credit
        lines referencing the return line

        - is_fully_credited is true once every line is fully covered by vendor credits

        - total_cost is the sum of line quantity x unit cost'
      parameters:
      - name: vendorReturn
        in: path
        schema:
          type: integer
        required: true
        description: Vendor return ID
        example: '12'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      vendor_return_number:
                        type: string
                      return_status:
                        type: string
                      return_date:
                        type: string
                      supplier_rma_number:
                        type: string
                      reason:
                        type: string
                      notes:
                        type: string
                      supplier_id:
                        type: integer
                      supplier:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          email:
                            type: string
                      warehouse_id:
                        type: integer
                      warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      currency_id:
                        type: integer
                      currency:
                        type: object
                        properties:
                          id:
                            type: integer
                          code:
                            type: string
                      purchase_order:
                        type: object
                        properties:
                          id:
                            type: integer
                          purchase_order_number:
                            type: string
                      is_fully_credited:
                        type: boolean
                      total_cost:
                        type: integer
                      lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            purchase_order_line_id:
                              type: integer
                            product_id:
                              type: integer
                            product:
                              type: object
                              properties:
                                id:
                                  type: integer
                                sku:
                                  type: string
                                name:
                                  type: string
                            quantity:
                              type: integer
                            unit_cost:
                              type: integer
                            reason:
                              type: string
                            is_write_off:
                              type: boolean
                            clearing_quantity:
                              type: integer
                            ap_quantity:
                              type: integer
                            credited_quantity:
                              type: integer
                            purchase_order_number:
                              type: string
                      shipments:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            shipment_date:
                              type: string
                            status:
                              type: string
                            tracking_number:
                              type: string
                            custom_carrier:
                              type: string
                              nullable: true
                            shipping_method:
                              type: object
                              properties:
                                id:
                                  type: integer
                                name:
                                  type: string
                            notes:
                              type: string
                              nullable: true
                      credits:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            vendor_credit_number:
                              type: string
                            credit_status:
                              type: string
                            total_credit:
                              type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                      accounting_exempt:
                        type: boolean
                example:
                  data:
                    id: 12
                    vendor_return_number: VR-00012
                    return_status: shipped
                    return_date: '2026-03-14'
                    supplier_rma_number: RMA-4821
                    reason: Damaged in transit
                    notes: Carton crushed on arrival; supplier approved the return.
                    supplier_id: 5
                    supplier:
                      id: 5
                      name: Acme Supplies
                      email: orders@acmesupplies.com
                    warehouse_id: 2
                    warehouse:
                      id: 2
                      name: Main Warehouse
                    currency_id: 1
                    currency:
                      id: 1
                      code: USD
                    purchase_order:
                      id: 101
                      purchase_order_number: PO-00101
                    is_fully_credited: false
                    total_cost: 250
                    lines:
                    - id: 34
                      purchase_order_line_id: 210
                      product_id: 88
                      product:
                        id: 88
                        sku: WIDGET-BLUE
                        name: Blue Widget
                      quantity: 10
                      unit_cost: 25
                      reason: Damaged in transit
                      is_write_off: false
                      clearing_quantity: 6
                      ap_quantity: 4
                      credited_quantity: 0
                      purchase_order_number: PO-00101
                    shipments:
                    - id: 7
                      shipment_date: '2026-03-15'
                      status: shipped
                      tracking_number: 1Z999AA10123456784
                      custom_carrier: null
                      shipping_method:
                        id: 3
                        name: UPS Ground
                      notes: null
                    credits:
                    - id: 55
                      vendor_credit_number: VC-00055
                      credit_status: draft
                      total_credit: 250
                    created_at: '2026-03-14T15:22:08.000000Z'
                    updated_at: '2026-03-15T09:10:44.000000Z'
                    archived_at: null
                    accounting_exempt: false
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Resource not found
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-vendor-returns-vendorreturn
    put:
      tags:
      - Vendor Returns
      summary: Update Vendor Return
      description: 'Update a DRAFT vendor return. Returns that have been authorized,
        shipped, completed, or voided cannot be edited.


        Authentication: Requires Bearer token.


        Accepts the same fields as Create Vendor Return. On update, supplier_id, warehouse_id,
        and return_date are optional - omitted values keep their current value. When
        a lines array is provided it REPLACES the full existing line set; omit lines
        entirely to leave them unchanged.


        The same validation invariants apply as on create: all lines must belong to
        a single purchase order, and per-line quantities cannot exceed the returnable
        (received minus already returned) quantity.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                supplier_rma_number:
                  type: string
                reason:
                  type: string
                notes:
                  type: string
                lines:
                  type: array
                  items:
                    type: object
                    properties:
                      purchase_order_line_id:
                        type: integer
                      quantity:
                        type: integer
                      unit_cost:
                        type: integer
                      reason:
                        type: string
                      is_write_off:
                        type: boolean
              example:
                supplier_rma_number: RMA-4821-B
                reason: Wrong items shipped
                notes: Supplier issued an updated RMA reference.
                lines:
                - purchase_order_line_id: 210
                  quantity: 8
                  unit_cost: 25
                  reason: Wrong items shipped
                  is_write_off: false
      parameters:
      - name: vendorReturn
        in: path
        schema:
          type: integer
        required: true
        description: Vendor return ID
        example: '12'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      vendor_return_number:
                        type: string
                      return_status:
                        type: string
                      return_date:
                        type: string
                      supplier_rma_number:
                        type: string
                      reason:
                        type: string
                      notes:
                        type: string
                      supplier_id:
                        type: integer
                      supplier:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          email:
                            type: string
                      warehouse_id:
                        type: integer
                      warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      currency_id:
                        type: integer
                      purchase_order:
                        type: object
                        properties:
                          id:
                            type: integer
                          purchase_order_number:
                            type: string
                      is_fully_credited:
                        type: boolean
                      total_cost:
                        type: integer
                      lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            purchase_order_line_id:
                              type: integer
                            product_id:
                              type: integer
                            product:
                              type: object
                              properties:
                                id:
                                  type: integer
                                sku:
                                  type: string
                                name:
                                  type: string
                            quantity:
                              type: integer
                            unit_cost:
                              type: integer
                            reason:
                              type: string
                            is_write_off:
                              type: boolean
                            clearing_quantity:
                              type: string
                              nullable: true
                            ap_quantity:
                              type: string
                              nullable: true
                            credited_quantity:
                              type: integer
                            purchase_order_number:
                              type: string
                      credits:
                        type: array
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                      accounting_exempt:
                        type: boolean
                  message:
                    type: string
                example:
                  data:
                    id: 12
                    vendor_return_number: VR-00012
                    return_status: draft
                    return_date: '2026-03-14'
                    supplier_rma_number: RMA-4821
                    reason: Damaged in transit
                    notes: Carton crushed on arrival; supplier approved the return.
                    supplier_id: 5
                    supplier:
                      id: 5
                      name: Acme Supplies
                      email: orders@acmesupplies.com
                    warehouse_id: 2
                    warehouse:
                      id: 2
                      name: Main Warehouse
                    currency_id: 1
                    purchase_order:
                      id: 101
                      purchase_order_number: PO-00101
                    is_fully_credited: false
                    total_cost: 250
                    lines:
                    - id: 34
                      purchase_order_line_id: 210
                      product_id: 88
                      product:
                        id: 88
                        sku: WIDGET-BLUE
                        name: Blue Widget
                      quantity: 10
                      unit_cost: 25
                      reason: Damaged in transit
                      is_write_off: false
                      clearing_quantity: null
                      ap_quantity: null
                      credited_quantity: 0
                      purchase_order_number: PO-00101
                    credits: []
                    created_at: '2026-03-14T15:22:08.000000Z'
                    updated_at: '2026-03-15T09:10:44.000000Z'
                    archived_at: null
                    accounting_exempt: false
                  message: The vendor return '12' updated successfully
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: object
                    properties:
                      vendor_return_id:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: object
                              properties:
                                id:
                                  type: integer
                example:
                  errors:
                    vendor_return_id:
                    - message: Only draft vendor returns can be edited.
                      code: VendorReturn422
                      data:
                        id: 12
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: put-api-vendor-returns-vendorreturn
    delete:
      tags:
      - Vendor Returns
      summary: Delete Vendor Return
      description: 'Delete a DRAFT vendor return and its lines. Returns that have
        progressed past draft cannot be deleted - void them instead (Void Vendor Return),
        which reverses their postings while keeping an auditable record.


        Authentication: Requires Bearer token.'
      parameters:
      - name: vendorReturn
        in: path
        schema:
          type: integer
        required: true
        description: Vendor return ID
        example: '12'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: The vendor return 12 deleted successfully
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: object
                    properties:
                      vendor_return_id:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: object
                              properties:
                                id:
                                  type: integer
                example:
                  errors:
                    vendor_return_id:
                    - message: Only draft vendor returns can be deleted. Void it instead.
                      code: VendorReturn422
                      data:
                        id: 12
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-vendor-returns-vendorreturn
  /api/vendor-returns/{vendorReturn}/authorize:
    post:
      tags:
      - Vendor Returns
      summary: Authorize Vendor Return
      description: 'Authorize a DRAFT vendor return: locks it for editing and reserves
        the stock. A stock allocation is created for each product line so the goods
        awaiting return shipment cannot be sold or allocated elsewhere. Status moves
        from draft to authorized.


        Authentication: Requires Bearer token.


        Fails with 422 when:

        - the return is not in draft status

        - the return has no lines

        - any line''s quantity exceeds the remaining returnable quantity for its purchase
        order line'
      requestBody:
        content: {}
      parameters:
      - name: vendorReturn
        in: path
        schema:
          type: integer
        required: true
        description: Vendor return ID
        example: '12'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      vendor_return_number:
                        type: string
                      return_status:
                        type: string
                      return_date:
                        type: string
                      supplier_rma_number:
                        type: string
                      reason:
                        type: string
                      notes:
                        type: string
                      supplier_id:
                        type: integer
                      warehouse_id:
                        type: integer
                      currency_id:
                        type: integer
                      purchase_order:
                        type: object
                        properties:
                          id:
                            type: integer
                          purchase_order_number:
                            type: string
                      is_fully_credited:
                        type: boolean
                      total_cost:
                        type: integer
                      lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            purchase_order_line_id:
                              type: integer
                            product_id:
                              type: integer
                            product:
                              type: object
                              properties:
                                id:
                                  type: integer
                                sku:
                                  type: string
                                name:
                                  type: string
                            quantity:
                              type: integer
                            unit_cost:
                              type: integer
                            reason:
                              type: string
                            is_write_off:
                              type: boolean
                            clearing_quantity:
                              type: string
                              nullable: true
                            ap_quantity:
                              type: string
                              nullable: true
                            credited_quantity:
                              type: integer
                            purchase_order_number:
                              type: string
                      credits:
                        type: array
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                      accounting_exempt:
                        type: boolean
                  message:
                    type: string
                example:
                  data:
                    id: 12
                    vendor_return_number: VR-00012
                    return_status: authorized
                    return_date: '2026-03-14'
                    supplier_rma_number: RMA-4821
                    reason: Damaged in transit
                    notes: Carton crushed on arrival; supplier approved the return.
                    supplier_id: 5
                    warehouse_id: 2
                    currency_id: 1
                    purchase_order:
                      id: 101
                      purchase_order_number: PO-00101
                    is_fully_credited: false
                    total_cost: 250
                    lines:
                    - id: 34
                      purchase_order_line_id: 210
                      product_id: 88
                      product:
                        id: 88
                        sku: WIDGET-BLUE
                        name: Blue Widget
                      quantity: 10
                      unit_cost: 25
                      reason: Damaged in transit
                      is_write_off: false
                      clearing_quantity: null
                      ap_quantity: null
                      credited_quantity: 0
                      purchase_order_number: PO-00101
                    credits: []
                    created_at: '2026-03-14T15:22:08.000000Z'
                    updated_at: '2026-03-14T16:02:31.000000Z'
                    archived_at: null
                    accounting_exempt: false
                  message: Vendor return authorized.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 422 Not Draft
                  value:
                    errors:
                      vendor_return_id:
                      - message: Only draft vendor returns can be authorized.
                        code: VendorReturn422
                        data:
                          id: 12
                example-1:
                  summary: 422 No Lines
                  value:
                    errors:
                      vendor_return_id:
                      - message: Cannot authorize a vendor return with no lines.
                        code: VendorReturn422
                        data:
                          id: 12
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-vendor-returns-vendorreturn-authorize
  /api/vendor-returns/{vendorReturn}/ship:
    post:
      tags:
      - Vendor Returns
      summary: Ship Vendor Return
      description: 'Ship the vendor return: the goods physically leave the warehouse.
        Creates the outbound shipment record, posts the inventory-out movements, and
        posts the accounting for the return. Status moves from authorized to shipped.
        A DRAFT return is authorized automatically before shipping, so shipping is
        allowed from draft or authorized status.


        Accounting split, captured per line at ship time:

        - un-invoiced units debit the vendor-returns clearing account (reversing the
        receipt accrual)

        - units already invoiced by the supplier debit accounts payable

        - write-off lines (is_write_off = true) debit cost of goods sold instead

        Un-invoiced units are consumed first when splitting. The split is recorded
        on each line as clearing_quantity and ap_quantity.


        Authentication: Requires Bearer token.


        Body fields (all optional):

        - shipment_date (date, YYYY-MM-DD; defaults to today)

        - tracking_number (string, max 255)

        - shipping_method_id (integer): ID of a shipping method

        - custom_carrier (string, max 255): free-text carrier name when no shipping
        method applies

        - notes (string)


        Fails with 422 when the return is already shipped, completed, or void, or
        when a line''s quantity exceeds the remaining returnable quantity for its
        purchase order line.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                shipment_date:
                  type: string
                tracking_number:
                  type: string
                shipping_method_id:
                  type: integer
                custom_carrier:
                  type: string
                  nullable: true
                notes:
                  type: string
              example:
                shipment_date: '2026-03-15'
                tracking_number: 1Z999AA10123456784
                shipping_method_id: 3
                custom_carrier: null
                notes: Two cartons, prepaid label from supplier.
      parameters:
      - name: vendorReturn
        in: path
        schema:
          type: integer
        required: true
        description: Vendor return ID
        example: '12'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      vendor_return_number:
                        type: string
                      return_status:
                        type: string
                      return_date:
                        type: string
                      supplier_rma_number:
                        type: string
                      reason:
                        type: string
                      notes:
                        type: string
                      supplier_id:
                        type: integer
                      warehouse_id:
                        type: integer
                      currency_id:
                        type: integer
                      purchase_order:
                        type: object
                        properties:
                          id:
                            type: integer
                          purchase_order_number:
                            type: string
                      is_fully_credited:
                        type: boolean
                      total_cost:
                        type: integer
                      lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            purchase_order_line_id:
                              type: integer
                            product_id:
                              type: integer
                            product:
                              type: object
                              properties:
                                id:
                                  type: integer
                                sku:
                                  type: string
                                name:
                                  type: string
                            quantity:
                              type: integer
                            unit_cost:
                              type: integer
                            reason:
                              type: string
                            is_write_off:
                              type: boolean
                            clearing_quantity:
                              type: integer
                            ap_quantity:
                              type: integer
                            credited_quantity:
                              type: integer
                            purchase_order_number:
                              type: string
                      shipments:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            shipment_date:
                              type: string
                            status:
                              type: string
                            tracking_number:
                              type: string
                            custom_carrier:
                              type: string
                              nullable: true
                            shipping_method:
                              type: string
                              nullable: true
                            notes:
                              type: string
                      credits:
                        type: array
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                      accounting_exempt:
                        type: boolean
                  message:
                    type: string
                example:
                  data:
                    id: 12
                    vendor_return_number: VR-00012
                    return_status: shipped
                    return_date: '2026-03-14'
                    supplier_rma_number: RMA-4821
                    reason: Damaged in transit
                    notes: Carton crushed on arrival; supplier approved the return.
                    supplier_id: 5
                    warehouse_id: 2
                    currency_id: 1
                    purchase_order:
                      id: 101
                      purchase_order_number: PO-00101
                    is_fully_credited: false
                    total_cost: 250
                    lines:
                    - id: 34
                      purchase_order_line_id: 210
                      product_id: 88
                      product:
                        id: 88
                        sku: WIDGET-BLUE
                        name: Blue Widget
                      quantity: 10
                      unit_cost: 25
                      reason: Damaged in transit
                      is_write_off: false
                      clearing_quantity: 6
                      ap_quantity: 4
                      credited_quantity: 0
                      purchase_order_number: PO-00101
                    shipments:
                    - id: 7
                      shipment_date: '2026-03-15'
                      status: shipped
                      tracking_number: 1Z999AA10123456784
                      custom_carrier: null
                      shipping_method: null
                      notes: Two cartons, prepaid label from supplier.
                    credits: []
                    created_at: '2026-03-14T15:22:08.000000Z'
                    updated_at: '2026-03-15T09:10:44.000000Z'
                    archived_at: null
                    accounting_exempt: false
                  message: Vendor return shipped.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: object
                    properties:
                      vendor_return_id:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: object
                              properties:
                                id:
                                  type: integer
                example:
                  errors:
                    vendor_return_id:
                    - message: Only authorized vendor returns can be shipped.
                      code: VendorReturn422
                      data:
                        id: 12
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-vendor-returns-vendorreturn-ship
  /api/vendor-returns/{vendorReturn}/complete:
    post:
      tags:
      - Vendor Returns
      summary: Complete Vendor Return
      description: 'Mark a SHIPPED vendor return as completed - the supplier has acknowledged
        the return (typically once it is fully credited). Status moves from shipped
        to completed. No inventory or accounting changes are made.


        Authentication: Requires Bearer token.


        Fails with 422 when the return is not in shipped status.'
      requestBody:
        content: {}
      parameters:
      - name: vendorReturn
        in: path
        schema:
          type: integer
        required: true
        description: Vendor return ID
        example: '12'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      vendor_return_number:
                        type: string
                      return_status:
                        type: string
                      return_date:
                        type: string
                      supplier_rma_number:
                        type: string
                      reason:
                        type: string
                      notes:
                        type: string
                      supplier_id:
                        type: integer
                      warehouse_id:
                        type: integer
                      currency_id:
                        type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                      accounting_exempt:
                        type: boolean
                  message:
                    type: string
                example:
                  data:
                    id: 12
                    vendor_return_number: VR-00012
                    return_status: completed
                    return_date: '2026-03-14'
                    supplier_rma_number: RMA-4821
                    reason: Damaged in transit
                    notes: Carton crushed on arrival; supplier approved the return.
                    supplier_id: 5
                    warehouse_id: 2
                    currency_id: 1
                    created_at: '2026-03-14T15:22:08.000000Z'
                    updated_at: '2026-03-20T11:41:03.000000Z'
                    archived_at: null
                    accounting_exempt: false
                  message: Vendor return completed.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: object
                    properties:
                      vendor_return_id:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: object
                              properties:
                                id:
                                  type: integer
                example:
                  errors:
                    vendor_return_id:
                    - message: Only shipped vendor returns can be completed.
                      code: VendorReturn422
                      data:
                        id: 12
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-vendor-returns-vendorreturn-complete
  /api/vendor-returns/{vendorReturn}/void:
    post:
      tags:
      - Vendor Returns
      summary: Void Vendor Return
      description: 'Void a vendor return, reversing everything it posted:

        - shipped inventory movements are reversed (stock is put back)

        - reserved stock from authorization is released

        - the return''s accounting entries are removed

        - per-line clearing/accounts-payable quantities are cleared


        Status moves to void. Voiding an already-void return succeeds and returns
        it unchanged.


        Authentication: Requires Bearer token.


        Blocked with 422 when any vendor credit line references the return - remove
        those credit lines first.'
      requestBody:
        content: {}
      parameters:
      - name: vendorReturn
        in: path
        schema:
          type: integer
        required: true
        description: Vendor return ID
        example: '12'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      vendor_return_number:
                        type: string
                      return_status:
                        type: string
                      return_date:
                        type: string
                      supplier_rma_number:
                        type: string
                      reason:
                        type: string
                      notes:
                        type: string
                      supplier_id:
                        type: integer
                      warehouse_id:
                        type: integer
                      currency_id:
                        type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                      accounting_exempt:
                        type: boolean
                  message:
                    type: string
                example:
                  data:
                    id: 12
                    vendor_return_number: VR-00012
                    return_status: void
                    return_date: '2026-03-14'
                    supplier_rma_number: RMA-4821
                    reason: Damaged in transit
                    notes: Carton crushed on arrival; supplier approved the return.
                    supplier_id: 5
                    warehouse_id: 2
                    currency_id: 1
                    created_at: '2026-03-14T15:22:08.000000Z'
                    updated_at: '2026-03-21T08:19:47.000000Z'
                    archived_at: null
                    accounting_exempt: false
                  message: Vendor return voided.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: object
                    properties:
                      vendor_return_id:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: object
                              properties:
                                id:
                                  type: integer
                example:
                  errors:
                    vendor_return_id:
                    - message: Cannot void a vendor return that has vendor credits
                        referencing it. Remove the credit lines first.
                      code: VendorReturn422
                      data:
                        id: 12
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-vendor-returns-vendorreturn-void
  /api/vendor-returns/{vendorReturn}/allocations:
    get:
      tags:
      - Vendor Returns
      summary: List Vendor Return Allocations
      description: 'List the inventory allocations linked to this vendor return''s
        lines - its Planned stock reservations plus any successor allocations they
        were promoted or demoted into. Paginated (10 per page by default). Each allocation
        carries its product, warehouse, quantity, status, hard-allocated flag, priority,
        and a `link_route` back to the source document.


        Authentication: Requires Bearer token.


        Query parameters:

        - `page` (integer, optional) - page number.

        - `per_page` (integer, optional) - items per page (default 10).'
      parameters:
      - name: vendorReturn
        in: path
        schema:
          type: integer
        required: true
        description: Vendor return ID
        example: '12'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        product_id:
                          type: integer
                        product:
                          type: object
                          properties:
                            id:
                              type: integer
                            sku:
                              type: string
                            name:
                              type: string
                        warehouse_id:
                          type: integer
                        warehouse:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            locations_enabled:
                              type: boolean
                        warehouse_location_id:
                          type: string
                          nullable: true
                        warehouse_location:
                          type: string
                          nullable: true
                        link_id:
                          type: integer
                        link_type:
                          type: string
                        link_type_label:
                          type: string
                        link_route:
                          type: string
                        link_reference:
                          type: string
                          nullable: true
                        date:
                          type: string
                          nullable: true
                        quantity:
                          type: integer
                        status:
                          type: string
                        status_label:
                          type: string
                        hard_allocated:
                          type: boolean
                        priority:
                          type: integer
                        supplier_id:
                          type: integer
                        supplier:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        purchase_order_line_id:
                          type: integer
                        is_tight_coverage:
                          type: boolean
                        release_source_id:
                          type: string
                          nullable: true
                        release_source_type:
                          type: string
                          nullable: true
                        fulfilled_at:
                          type: string
                          nullable: true
                        cancelled_at:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                    items:
                      type: object
                      properties:
                        url:
                          type: string
                          nullable: true
                        label:
                          type: string
                        active:
                          type: boolean
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 88213
                    product_id: 88
                    product:
                      id: 88
                      sku: WIDGET-BLUE
                      name: Blue Widget
                    warehouse_id: 2
                    warehouse:
                      id: 2
                      name: Main Warehouse
                      locations_enabled: false
                    warehouse_location_id: null
                    warehouse_location: null
                    link_id: 34
                    link_type: App\Models\VendorReturnLine
                    link_type_label: Vendor Return
                    link_route: /purchases/vendor-returns/12
                    link_reference: null
                    date: null
                    quantity: 10
                    status: planned
                    status_label: Planned
                    hard_allocated: false
                    priority: 100
                    supplier_id: 5
                    supplier:
                      id: 5
                      name: Acme Supplies Co.
                    purchase_order_line_id: 210
                    is_tight_coverage: false
                    release_source_id: null
                    release_source_type: null
                    fulfilled_at: null
                    cancelled_at: null
                    created_at: '2026-03-14T15:22:08.000000Z'
                    updated_at: '2026-03-14T16:02:31.000000Z'
                  current_page: 1
                  first_page_url: '{{protocol}}{{domain}}/api/vendor-returns/12/allocations?page=1'
                  from: 1
                  last_page: 1
                  last_page_url: '{{protocol}}{{domain}}/api/vendor-returns/12/allocations?page=1'
                  links:
                  - url: null
                    label: '&laquo; Previous'
                    active: false
                  - url: '{{protocol}}{{domain}}/api/vendor-returns/12/allocations?page=1'
                    label: '1'
                    active: true
                  - url: null
                    label: Next &raquo;
                    active: false
                  next_page_url: null
                  path: '{{protocol}}{{domain}}/api/vendor-returns/12/allocations'
                  per_page: 10
                  prev_page_url: null
                  to: 1
                  total: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-vendor-returns-vendorreturn-allocations
  /api/vendor-returns/{vendorReturn}/activity-log:
    get:
      tags:
      - Vendor Returns
      summary: Get Vendor Return Activity Log
      description: 'Paginated activity feed for this vendor return - its own status
        transitions plus events logged on its lines, shipments, and shipment lines,
        all rolled up onto the return. Newest first, 15 per page by default.


        Authentication: Requires Bearer token.


        Query parameters:

        - `page` (integer, optional) - page number.

        - `per_page` (integer, optional) - items per page (default 15).

        - `filter[search]` (string, optional) - filter entries by causer name, event,
        subject type, or change payload.'
      parameters:
      - name: vendorReturn
        in: path
        schema:
          type: integer
        required: true
        description: Vendor return ID
        example: '12'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        description:
                          type: string
                        event:
                          type: string
                        subject_type:
                          type: string
                        subject_id:
                          type: integer
                        properties:
                          type: object
                          properties:
                            attributes:
                              type: object
                              properties:
                                return_status:
                                  type: string
                            old:
                              type: object
                              properties:
                                return_status:
                                  type: string
                        causer_name:
                          type: string
                        created_at:
                          type: string
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 4821
                    description: updated
                    event: updated
                    subject_type: VendorReturn
                    subject_id: 12
                    properties:
                      attributes:
                        return_status: shipped
                      old:
                        return_status: authorized
                    causer_name: Jane Buyer
                    created_at: '2026-04-19T14:32:10.000000Z'
                  - id: 4815
                    description: created
                    event: created
                    subject_type: VendorReturnShipment
                    subject_id: 30
                    properties:
                      attributes:
                        vendor_return_id: 12
                        status: shipped
                        tracking_number: TRK-RETURN-1
                    causer_name: Jane Buyer
                    created_at: '2026-04-19T14:32:09.000000Z'
                  first_page_url: '{{protocol}}{{domain}}/api/vendor-returns/12/activity-log?page=1'
                  from: 1
                  last_page: 1
                  last_page_url: '{{protocol}}{{domain}}/api/vendor-returns/12/activity-log?page=1'
                  next_page_url: null
                  path: '{{protocol}}{{domain}}/api/vendor-returns/12/activity-log'
                  per_page: 15
                  prev_page_url: null
                  to: 2
                  total: 2
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-vendor-returns-vendorreturn-activity-log
  /api/vendor-returns/{vendorReturn}/ship-impact:
    get:
      tags:
      - Vendor Returns
      summary: Preview Vendor Return Ship Impact
      description: 'Read-only preview of the allocation-demotion impact of shipping
        this vendor return. Shipping consumes the source stock reserved for the return,
        which can demote soft sales-order reservations to backorder and requires voiding
        printed shipping labels for any hard-allocated units. This returns the per-product
        rows describing exactly which order allocations would be affected, so the
        caller can collect the necessary `void_confirmations` before calling Ship
        Vendor Return.


        Each row is one product whose stock the action would consume. `shortfall_quantity`
        is how much more than available the action removes (stock goes negative when
        above zero). `unallocated_quantity` / `soft_allocated_quantity` / `hard_allocated_quantity`
        split the consumed quantity into free / soft-reserved / hard-allocated (label-printed)
        units. `affected_allocations[]` lists the order allocations consumed, highest
        priority first: `allocation_type` is `soft` or `hard`, and for hard rows `fulfillment_id`/`carrier`
        identify the label while `carrier_void_supported` and `voidable_status` say
        whether it can be voided through the API.


        Authentication: Requires Bearer token.'
      parameters:
      - name: vendorReturn
        in: path
        schema:
          type: integer
        required: true
        description: Vendor return ID
        example: '12'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        product_id:
                          type: integer
                        product_sku:
                          type: string
                        product_name:
                          type: string
                        shortfall_quantity:
                          type: integer
                        unallocated_quantity:
                          type: integer
                        soft_allocated_quantity:
                          type: integer
                        hard_allocated_quantity:
                          type: integer
                        affected_allocations:
                          type: array
                          items:
                            type: object
                            properties:
                              allocation_id:
                                type: integer
                              allocation_type:
                                type: string
                              sales_order_id:
                                type: integer
                              order_number:
                                type: string
                              customer_name:
                                type: string
                              fulfillment_id:
                                type: string
                                nullable: true
                              carrier:
                                type: string
                                nullable: true
                              carrier_void_supported:
                                type: string
                                nullable: true
                              voidable_status:
                                type: string
                                nullable: true
                              voidable_detail:
                                type: string
                                nullable: true
                              quantity:
                                type: integer
                example:
                  data:
                  - product_id: 123
                    product_sku: WIDGET-001
                    product_name: Blue Widget 500ml
                    shortfall_quantity: 0
                    unallocated_quantity: 4
                    soft_allocated_quantity: 3
                    hard_allocated_quantity: 2
                    affected_allocations:
                    - allocation_id: 88213
                      allocation_type: soft
                      sales_order_id: 4521
                      order_number: SO-10442
                      customer_name: Acme Retail
                      fulfillment_id: null
                      carrier: null
                      carrier_void_supported: null
                      voidable_status: null
                      voidable_detail: null
                      quantity: 3
                    - allocation_id: 88240
                      allocation_type: hard
                      sales_order_id: 4530
                      order_number: SO-10450
                      customer_name: Beta Wholesale
                      fulfillment_id: 77120
                      carrier: ups
                      carrier_void_supported: true
                      voidable_status: voidable
                      voidable_detail: null
                      quantity: 2
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-vendor-returns-vendorreturn-ship-impact
  /api/vendor-returns/{vendorReturn}/create-credit:
    post:
      tags:
      - Vendor Returns
      summary: Create Vendor Credit From Return
      description: 'Create the financial vendor credit from a SHIPPED (or completed)
        vendor return - use this once the supplier''s credit memo arrives. Returns
        the newly created draft vendor credit.


        The credit''s lines link to the return''s lines at the line level, so each
        return line tracks how much of it has been credited (credited_quantity). Crediting
        the un-invoiced portion settles the vendor-returns clearing account. Only
        the remaining un-credited quantity of each return line is included; lines
        already fully credited are skipped.


        Authentication: Requires Bearer token.


        Body fields (all optional):

        - vendor_credit_number (string, max 255, must be unique; auto-generated when
        omitted)

        - supplier_reference (string, max 255; defaults to the return''s vendor RMA
        number)

        - credit_date (date, YYYY-MM-DD; defaults to today)


        Fails with 422 when the return is not shipped/completed, or when it is already
        fully credited.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                vendor_credit_number:
                  type: string
                supplier_reference:
                  type: string
                credit_date:
                  type: string
              example:
                vendor_credit_number: VC-00055
                supplier_reference: CM-99120
                credit_date: '2026-03-20'
      parameters:
      - name: vendorReturn
        in: path
        schema:
          type: integer
        required: true
        description: Vendor return ID
        example: '12'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      vendor_credit_number:
                        type: string
                      supplier_reference:
                        type: string
                      supplier_po_number:
                        type: string
                        nullable: true
                      credit_date:
                        type: string
                      vendor_credit_note:
                        type: string
                        nullable: true
                      credit_status:
                        type: string
                      credit_status_label:
                        type: string
                      payment_status:
                        type: string
                      payment_status_label:
                        type: string
                      is_for_overpayment:
                        type: boolean
                      supplier_id:
                        type: integer
                      purchase_order_id:
                        type: integer
                      purchase_order:
                        type: object
                        properties:
                          id:
                            type: integer
                          purchase_order_number:
                            type: string
                      warehouse_id:
                        type: integer
                      store_id:
                        type: string
                        nullable: true
                      currency_id:
                        type: integer
                      currency_rate:
                        type: integer
                      is_tax_included:
                        type: boolean
                      tax_total:
                        type: integer
                      product_total:
                        type: integer
                      total_credit:
                        type: integer
                      total:
                        type: integer
                      allocated_amount:
                        type: integer
                      available_to_allocate:
                        type: integer
                      refunded_amount:
                        type: integer
                      remaining_amount:
                        type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                  message:
                    type: string
                example:
                  data:
                    id: 55
                    vendor_credit_number: VC-00055
                    supplier_reference: CM-99120
                    supplier_po_number: null
                    credit_date: '2026-03-20'
                    vendor_credit_note: null
                    credit_status: draft
                    credit_status_label: Draft
                    payment_status: unpaid
                    payment_status_label: Unpaid
                    is_for_overpayment: false
                    supplier_id: 5
                    purchase_order_id: 101
                    purchase_order:
                      id: 101
                      purchase_order_number: PO-00101
                    warehouse_id: 2
                    store_id: null
                    currency_id: 1
                    currency_rate: 1
                    is_tax_included: false
                    tax_total: 0
                    product_total: 250
                    total_credit: 250
                    total: 250
                    allocated_amount: 0
                    available_to_allocate: 250
                    refunded_amount: 0
                    remaining_amount: 250
                    created_at: '2026-03-20T14:05:12.000000Z'
                    updated_at: '2026-03-20T14:05:12.000000Z'
                    archived_at: null
                  message: The vendor credit created successfully
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 422 Not Shipped
                  value:
                    errors:
                      vendor_return_id:
                      - message: A vendor credit can only be created from a shipped
                          vendor return.
                        code: VendorReturn422
                        data:
                          id: 12
                example-1:
                  summary: 422 Fully Credited
                  value:
                    errors:
                      vendor_return_id:
                      - message: This vendor return is already fully credited.
                        code: VendorReturn422
                        data:
                          id: 12
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-vendor-returns-vendorreturn-create-credit
  /api/vendor-returns/returnable-lines/{purchaseOrder}:
    get:
      tags:
      - Vendor Returns
      summary: List Returnable Lines For Purchase Order
      description: 'For each line of a purchase order, report how much was received,
        how much has already been returned (across all non-void vendor returns, plus
        historical restock credits), and how much remains returnable. Use this before
        creating a vendor return to know which lines and quantities are still available
        to return.


        Authentication: Requires Bearer token.


        Response fields per line:

        - purchase_order_line_id (integer)

        - product_id (integer, nullable)

        - sku (string, nullable)

        - name (string): product name, or the line description when there is no product

        - received_quantity (number)

        - already_returned_quantity (number)

        - returnable_quantity (number): received minus already returned, never below
        0'
      parameters:
      - name: purchaseOrder
        in: path
        schema:
          type: integer
        required: true
        description: Purchase order ID
        example: '101'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        purchase_order_line_id:
                          type: integer
                        product_id:
                          type: integer
                        sku:
                          type: string
                        name:
                          type: string
                        received_quantity:
                          type: integer
                        already_returned_quantity:
                          type: integer
                        returnable_quantity:
                          type: integer
                example:
                  data:
                  - purchase_order_line_id: 210
                    product_id: 88
                    sku: WIDGET-BLUE
                    name: Blue Widget
                    received_quantity: 24
                    already_returned_quantity: 10
                    returnable_quantity: 14
                  - purchase_order_line_id: 211
                    product_id: 89
                    sku: WIDGET-RED
                    name: Red Widget
                    received_quantity: 12
                    already_returned_quantity: 0
                    returnable_quantity: 12
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-vendor-returns-returnable-lines-purchaseorder
  /api/purchase-receipts/{receipt}:
    get:
      tags:
      - Purchase Receipts
      summary: Get Purchase Receipt
      description: 'Returns full details for a purchase receipt including shipment,
        purchase order, supplier, warehouse, and line items.

        Authentication: Requires Bearer token.'
      parameters:
      - name: receipt
        in: path
        schema:
          type: integer
        required: true
        description: Purchase receipt ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      received_at:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      fulfilled_by:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      purchase_order:
                        type: object
                        properties:
                          id:
                            type: integer
                          po_number:
                            type: string
                          purchase_order_date:
                            type: string
                          currency_code:
                            type: string
                          currency_rate:
                            type: number
                          is_tax_included:
                            type: boolean
                      supplier:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      destination_warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            quantity:
                              type: integer
                            total_cost:
                              type: number
                            purchase_order_line:
                              type: object
                              properties:
                                id:
                                  type: integer
                                quantity:
                                  type: integer
                                amount:
                                  type: number
                                discount_rate:
                                  type: integer
                                received_quantity:
                                  type: integer
                                description:
                                  type: string
                            product:
                              type: object
                              properties:
                                id:
                                  type: integer
                                sku:
                                  type: string
                                name:
                                  type: string
                                image_url:
                                  type: string
                      summary:
                        type: object
                        properties:
                          total_lines:
                            type: integer
                          total_units:
                            type: integer
                  status:
                    type: string
                example:
                  data:
                    id: 1
                    received_at: '2024-01-15T14:00:00Z'
                    created_at: '2024-01-15T14:00:00Z'
                    updated_at: '2024-01-15T14:05:00Z'
                    fulfilled_by:
                      id: 5
                      name: John Smith
                    purchase_order:
                      id: 20
                      po_number: PO-2024-0020
                      purchase_order_date: '2024-01-01'
                      currency_code: USD
                      currency_rate: 1.0
                      is_tax_included: false
                    supplier:
                      id: 3
                      name: Acme Supplies Co.
                    destination_warehouse:
                      id: 1
                      name: Main Warehouse
                    lines:
                    - id: 10
                      quantity: 100
                      total_cost: 1250.0
                      purchase_order_line:
                        id: 50
                        quantity: 100
                        amount: 1250.0
                        discount_rate: 0
                        received_quantity: 100
                        description: Blue Widget
                      product:
                        id: 42
                        sku: WIDGET-001
                        name: Blue Widget
                        image_url: https://cdn.example.com/widget.jpg
                    summary:
                      total_lines: 1
                      total_units: 100
                  status: success
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No query results for model [App\Models\PurchaseOrderShipmentReceipt]
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-purchase-receipts-receipt
  /api/purchase-receipts/{receipt}/activity-log:
    get:
      tags:
      - Purchase Receipts
      summary: Get Activity Log
      description: 'Returns paginated activity log for a purchase receipt.

        Authentication: Requires Bearer token.'
      parameters:
      - name: per_page
        in: query
        schema:
          type: integer
        description: 'Items per page (default: 15)'
        example: '15'
      - name: filter[search]
        in: query
        schema:
          type: string
        description: Search across causer name, properties, event
      - name: receipt
        in: path
        schema:
          type: integer
        required: true
        description: Purchase receipt ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        description:
                          type: string
                        event:
                          type: string
                        subject_type:
                          type: string
                        subject_id:
                          type: integer
                        properties:
                          type: object
                          properties: {}
                        causer_name:
                          type: string
                        created_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 200
                    description: created
                    event: created
                    subject_type: PurchaseOrderShipmentReceipt
                    subject_id: 1
                    properties: {}
                    causer_name: John Smith
                    created_at: '2024-01-15T14:00:00Z'
                  current_page: 1
                  last_page: 1
                  per_page: 15
                  total: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-purchase-receipts-receipt-activity-log
  /api/purchase-receipts/{receipt}/fifo-layers:
    get:
      tags:
      - Purchase Receipts
      summary: Get FIFO Layers
      description: 'Returns paginated FIFO inventory layers that were created when
        this purchase receipt was processed.

        Authentication: Requires Bearer token.'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        description: Page number
        example: '1'
      - name: per_page
        in: query
        schema:
          type: integer
        description: Items per page
        example: '25'
      - name: receipt
        in: path
        schema:
          type: integer
        required: true
        description: Purchase receipt ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        fifo_layer_date:
                          type: string
                        quantity:
                          type: integer
                        fulfilled_quantity:
                          type: integer
                        available_quantity:
                          type: integer
                        unit_cost:
                          type: number
                        total_cost:
                          type: number
                        product_id:
                          type: integer
                        product_sku:
                          type: string
                        product_name:
                          type: string
                        warehouse_id:
                          type: integer
                        warehouse_name:
                          type: string
                        source_type:
                          type: string
                        source_reference:
                          type: string
                        link_type:
                          type: string
                        link_id:
                          type: integer
                        parent_link_id:
                          type: string
                          nullable: true
                        detail_link_id:
                          type: string
                          nullable: true
                        condition:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 300
                    fifo_layer_date: '2024-01-15'
                    quantity: 100
                    fulfilled_quantity: 30
                    available_quantity: 70
                    unit_cost: 12.5
                    total_cost: 1250.0
                    product_id: 42
                    product_sku: WIDGET-001
                    product_name: Blue Widget
                    warehouse_id: 1
                    warehouse_name: Main Warehouse
                    source_type: Purchase Receipt
                    source_reference: PO-2024-0020
                    link_type: App\Models\PurchaseOrderShipmentReceipt
                    link_id: 1
                    parent_link_id: null
                    detail_link_id: null
                    condition: null
                    created_at: '2024-01-15T14:05:00Z'
                  current_page: 1
                  last_page: 1
                  per_page: 25
                  total: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-purchase-receipts-receipt-fifo-layers
  /api/purchase-receipts/{receipt}/inventory-movements:
    get:
      tags:
      - Purchase Receipts
      summary: Get Inventory Movements
      description: 'Returns paginated inventory movements generated when this receipt
        was processed.

        Authentication: Requires Bearer token.'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        description: Page number
        example: '1'
      - name: per_page
        in: query
        schema:
          type: integer
        description: Items per page
        example: '25'
      - name: receipt
        in: path
        schema:
          type: integer
        required: true
        description: Purchase receipt ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        type:
                          type: string
                        inventory_status:
                          type: string
                        quantity:
                          type: integer
                        reference:
                          type: string
                        link_type:
                          type: string
                        link_id:
                          type: integer
                        parent_link_id:
                          type: string
                          nullable: true
                        detail_link_id:
                          type: string
                          nullable: true
                        product_id:
                          type: integer
                        product_sku:
                          type: string
                        product_name:
                          type: string
                        warehouse_id:
                          type: integer
                        warehouse_name:
                          type: string
                        unit_cost:
                          type: number
                        unit_cost_provisional:
                          type: boolean
                        total_cost:
                          type: number
                        layer:
                          type: object
                          properties:
                            name:
                              type: string
                            layer_type:
                              type: string
                            layer_id:
                              type: integer
                        inventory_movement_date:
                          type: string
                        created_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 400
                    type: purchase_receipt
                    inventory_status: available
                    quantity: 100
                    reference: PO-2024-0020
                    link_type: App\Models\PurchaseOrderShipmentReceipt
                    link_id: 1
                    parent_link_id: null
                    detail_link_id: null
                    product_id: 42
                    product_sku: WIDGET-001
                    product_name: Blue Widget
                    warehouse_id: 1
                    warehouse_name: Main Warehouse
                    unit_cost: 12.5
                    unit_cost_provisional: false
                    total_cost: 1250.0
                    layer:
                      name: 'FIFO Layer #300'
                      layer_type: App\Models\FifoLayer
                      layer_id: 300
                    inventory_movement_date: '2024-01-15'
                    created_at: '2024-01-15T14:05:00Z'
                  current_page: 1
                  last_page: 1
                  per_page: 25
                  total: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-purchase-receipts-receipt-inventory-movements
  /api/purchase-receipts/{receipt}/notes:
    get:
      tags:
      - Purchase Receipts
      summary: Get Purchase Receipt Notes
      description: 'Returns paginated notes for a purchase receipt, ordered by most
        recent first.

        Authentication: Requires Bearer token.'
      parameters:
      - name: receipt
        in: path
        schema:
          type: integer
        required: true
        description: Purchase receipt ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      data:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            note:
                              type: string
                            is_pinned:
                              type: boolean
                            user:
                              type: object
                              properties:
                                id:
                                  type: integer
                                name:
                                  type: string
                            created_at:
                              type: string
                            updated_at:
                              type: string
                      current_page:
                        type: integer
                      total:
                        type: integer
                  status:
                    type: string
                example:
                  data:
                    data:
                    - id: 7
                      note: Receipt verified by warehouse manager.
                      is_pinned: true
                      user:
                        id: 5
                        name: John Smith
                      created_at: '2024-01-15T15:00:00Z'
                      updated_at: '2024-01-15T15:00:00Z'
                    current_page: 1
                    total: 1
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-purchase-receipts-receipt-notes
    post:
      tags:
      - Purchase Receipts
      summary: Add Purchase Receipt Note
      description: 'Adds a note to a purchase receipt.

        Authentication: Requires Bearer token.


        Fields:

        - note (required): Note text content

        - is_pinned (optional, boolean): Whether to pin the note'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                note:
                  type: string
                is_pinned:
                  type: boolean
              example:
                note: Receipt verified by warehouse manager.
                is_pinned: false
      parameters:
      - name: receipt
        in: path
        schema:
          type: integer
        required: true
        description: Purchase receipt ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      note:
                        type: string
                      is_pinned:
                        type: boolean
                      user:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                  message:
                    type: string
                  status:
                    type: string
                example:
                  data:
                    id: 8
                    note: Receipt verified by warehouse manager.
                    is_pinned: false
                    user:
                      id: 5
                      name: John Smith
                    created_at: '2024-01-15T15:30:00Z'
                    updated_at: '2024-01-15T15:30:00Z'
                  message: note created successfully.
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-purchase-receipts-receipt-notes
  /api/purchase-receipts/{receipt}/notes/{noteId}:
    delete:
      tags:
      - Purchase Receipts
      summary: Delete Purchase Receipt Note
      description: 'Deletes a note from a purchase receipt.

        Authentication: Requires Bearer token.'
      parameters:
      - name: receipt
        in: path
        schema:
          type: integer
        required: true
        description: Purchase receipt ID
        example: '1'
      - name: noteId
        in: path
        schema:
          type: integer
        required: true
        description: Note ID to delete
        example: '8'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  status:
                    type: string
                example:
                  message: note 8 deleted successfully.
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-purchase-receipts-receipt-notes-noteid
  /api/purchase-receipts/{receipt}/notes/{noteId}/toggle-pin:
    put:
      tags:
      - Purchase Receipts
      summary: Toggle Note Pin
      description: 'Toggles the pinned state of a note on a purchase receipt.

        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: receipt
        in: path
        schema:
          type: integer
        required: true
        description: Purchase receipt ID
        example: '1'
      - name: noteId
        in: path
        schema:
          type: integer
        required: true
        description: Note ID to pin/unpin
        example: '8'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      note:
                        type: string
                      is_pinned:
                        type: boolean
                      user:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                  message:
                    type: string
                  status:
                    type: string
                example:
                  data:
                    id: 8
                    note: Receipt verified by warehouse manager.
                    is_pinned: true
                    user:
                      id: 5
                      name: John Smith
                    created_at: '2024-01-15T15:30:00Z'
                    updated_at: '2024-01-15T16:00:00Z'
                  message: Note pinned
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-purchase-receipts-receipt-notes-noteid-toggle-pin
  /api/purchase-receipts/{receipt}/generate-accounting-transaction:
    post:
      tags:
      - Purchase Receipts
      summary: Generate Accounting Transaction
      description: 'Generates (or regenerates) the accounting transaction for a purchase
        receipt.

        Authentication: Requires Bearer token.

        Returns 422 if the purchase order is a dropship order (has a sales_order_id)
        or has no destination warehouse.'
      requestBody:
        content: {}
      parameters:
      - name: receipt
        in: path
        schema:
          type: integer
        required: true
        description: Purchase receipt ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      transaction_date:
                        type: string
                      reference:
                        type: string
                      amount:
                        type: number
                  message:
                    type: string
                  status:
                    type: string
                example:
                  data:
                    id: 88
                    transaction_date: '2024-01-15'
                    reference: PO-2024-0020
                    amount: 1250.0
                  message: Accounting transaction generated successfully.
                  status: success
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Cannot generate accounting transaction for a dropship purchase
                    order receipt.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-purchase-receipts-receipt-generate-accounting-transaction
  /api/purchase-order-shipments/{shipment}:
    get:
      tags:
      - Purchase Order Shipments
      summary: Get Shipment
      description: 'Retrieve detailed information for a single purchase order shipment.
        Includes purchase order, supplier, destination warehouse, all shipment lines
        (with products), receipts, and summary totals.


        Authentication: Requires Bearer token.'
      parameters:
      - name: shipment
        in: path
        schema:
          type: integer
        required: true
        description: Purchase order shipment ID
        example: '50'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      shipment_date:
                        type: string
                      tracking:
                        type: string
                      fulfilled_shipping_method:
                        type: string
                      fulfilled_shipping_method_id:
                        type: integer
                      fully_received_at:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      purchase_order:
                        type: object
                        properties:
                          id:
                            type: integer
                          po_number:
                            type: string
                          purchase_order_date:
                            type: string
                          currency_code:
                            type: string
                      supplier:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      destination_warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            quantity:
                              type: integer
                            received_quantity:
                              type: integer
                            purchase_order_line:
                              type: object
                              properties:
                                id:
                                  type: integer
                                quantity:
                                  type: integer
                                amount:
                                  type: number
                                received_quantity:
                                  type: integer
                                description:
                                  type: string
                            product:
                              type: object
                              properties:
                                id:
                                  type: integer
                                sku:
                                  type: string
                                name:
                                  type: string
                                image_url:
                                  type: string
                      receipts:
                        type: array
                      summary:
                        type: object
                        properties:
                          total_lines:
                            type: integer
                          total_shipped:
                            type: integer
                          total_received:
                            type: integer
                          total_receipts:
                            type: integer
                example:
                  data:
                    id: 50
                    shipment_date: '2024-03-10'
                    tracking: 1Z999AA10123456784
                    fulfilled_shipping_method: UPS Ground
                    fulfilled_shipping_method_id: 5
                    fully_received_at: null
                    created_at: '2024-03-10T08:00:00Z'
                    updated_at: '2024-03-10T08:00:00Z'
                    purchase_order:
                      id: 200
                      po_number: PO-2024-001
                      purchase_order_date: '2024-03-01'
                      currency_code: USD
                    supplier:
                      id: 10
                      name: Acme Supplies Ltd.
                    destination_warehouse:
                      id: 1
                      name: Main Warehouse
                    lines:
                    - id: 301
                      quantity: 100
                      received_quantity: 0
                      purchase_order_line:
                        id: 401
                        quantity: 100
                        amount: 12.5
                        received_quantity: 0
                        description: Blue Widget 500ml
                      product:
                        id: 42
                        sku: SKU-ABC-123
                        name: Blue Widget 500ml
                        image_url: https://cdn.example.com/products/42.jpg
                    receipts: []
                    summary:
                      total_lines: 1
                      total_shipped: 100
                      total_received: 0
                      total_receipts: 0
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No query results for model [App\Models\PurchaseOrderShipment]
                    9999
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-purchase-order-shipments-shipment
    put:
      tags:
      - Purchase Order Shipments
      summary: Update Shipment
      description: 'Update an existing purchase order shipment''s shipping method
        or tracking number.


        Authentication: Requires Bearer token.


        Fields:

        - shipping_method_id (optional): Updated system shipping method ID (or null
        to unset)

        - tracking (optional): Updated tracking number, max 255 characters'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                shipping_method_id:
                  type: integer
                tracking:
                  type: string
              example:
                shipping_method_id: 6
                tracking: 1Z999AA10987654321
      parameters:
      - name: shipment
        in: path
        required: true
        schema:
          type: string
        description: The shipment identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      tracking:
                        type: string
                      shipping_method_id:
                        type: integer
                      updated_at:
                        type: string
                example:
                  message: purchase order shipment 50 has been successfully updated
                  data:
                    id: 50
                    tracking: 1Z999AA10987654321
                    shipping_method_id: 6
                    updated_at: '2024-03-11T09:00:00Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-purchase-order-shipments-shipment
  /api/purchase-order-shipments:
    post:
      tags:
      - Purchase Order Shipments
      summary: Create Shipment
      description: 'Create a new shipment for an open purchase order. If shipment_lines
        is omitted, creates a shipment for all remaining unshipped quantity.


        Authentication: Requires Bearer token.


        Fields:

        - purchase_order_id (required): ID of the purchase order (must not be draft,
        not fully shipped)

        - shipment_date (required): Date of shipment in Y-m-d format

        - shipping_method_id (optional): System shipping method ID

        - tracking (optional): Tracking number, max 255 characters

        - shipment_lines (optional): Array of line quantities to ship. If omitted,
        ships everything remaining

        - shipment_lines[].purchase_order_line_id (conditional): PO line ID. Required
        without purchase_order_line_reference

        - shipment_lines[].purchase_order_line_reference (conditional): PO line reference
        code. Required without purchase_order_line_id

        - shipment_lines[].quantity (required): Quantity to ship (must not exceed
        unfulfilled quantity)


        Errors:

        - 422: AWD purchase orders use ''Mark as Shipped'' instead

        - 400: Purchase order is not open (draft)'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                purchase_order_id:
                  type: integer
                shipment_date:
                  type: string
                shipping_method_id:
                  type: integer
                tracking:
                  type: string
                shipment_lines:
                  type: array
                  items:
                    type: object
                    properties:
                      purchase_order_line_id:
                        type: integer
                      quantity:
                        type: integer
              example:
                purchase_order_id: 200
                shipment_date: '2024-03-10'
                shipping_method_id: 5
                tracking: 1Z999AA10123456784
                shipment_lines:
                - purchase_order_line_id: 401
                  quantity: 100
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      shipment_date:
                        type: string
                      shipping_method_id:
                        type: integer
                      fulfilled_shipping_method_id:
                        type: integer
                      tracking:
                        type: string
                      fully_received_at:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      purchase_order_shipment_lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            purchase_order_line_id:
                              type: integer
                            quantity:
                              type: integer
                      purchase_order_shipment_receipts:
                        type: array
                example:
                  message: purchase order shipment has been successfully created
                  data:
                    id: 50
                    shipment_date: '2024-03-10'
                    shipping_method_id: 5
                    fulfilled_shipping_method_id: 5
                    tracking: 1Z999AA10123456784
                    fully_received_at: null
                    created_at: '2024-03-10T08:00:00Z'
                    updated_at: '2024-03-10T08:00:00Z'
                    purchase_order_shipment_lines:
                    - id: 301
                      purchase_order_line_id: 401
                      quantity: 100
                    purchase_order_shipment_receipts: []
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: AWD purchase orders do not use shipments. Use 'Mark as
                    Shipped' to create a pending inbound instead.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-purchase-order-shipments
  /api/inbound-shipments/receive:
    post:
      tags:
      - Purchase Order Shipments
      summary: Receive Shipment
      description: 'Receive goods against a purchase order shipment. Creates a receipt
        record and triggers inventory movements.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Async behavior:

        - By default, this endpoint dispatches the receive to a background job chain
        and returns 202 Accepted with `data.tracked_job_log_id`. The frontend should
        open the tracked job log endpoints (notifyJobStarted) and watch lastCompletedJob
        to refresh.

        - Pass `?async=0` to force the legacy synchronous response (200 with the receipt
        resource).

        - The async path is only taken when the payload is ad-hoc eligible: requires
        `purchase_order_id`, and rejects any payload that includes `unexpected_items`,
        `inbound_shipment_id`, or negative `receipt_lines[].quantity`. Ineligible
        payloads silently fall back to the sync path.

        - 409 Conflict is returned when a background job is already in flight (PENDING
        or PROCESSING) for the same `purchase_order_id` — the caller should tell the
        user to track progress via the tracked job log endpoints instead of retrying.


        Fields:

        - purchase_order_id (conditional): Required if purchase_order_shipment_id
        is not provided. Required for the async path.

        - purchase_order_shipment_id (optional): Specific shipment ID to receive.
        If omitted, receives for the entire PO

        - received_at (required): Date/time of receipt

        - warehouse_id (optional): Override destination warehouse

        - shipment_date (optional): Used if a new shipment needs to be created automatically

        - shipping_method_id (optional): Shipping method for auto-created shipment

        - tracking (optional): Tracking number for auto-created shipment, max 255
        characters

        - inbound_shipment_id (optional, exists:inbound_shipments,id): Route the whole
        receive against this specific inbound shipment. Restricts delegation to that
        shipment and over-receives it past its planned capacity if the received quantity
        exceeds what was expected. Used by the PO-detail receive drawer when the receiver
        explicitly picks a target shipment. Presence forces sync fallback.

        - force_new_shipment (optional, boolean): If true, skip auto-routing/delegation
        to existing planned shipments and create a brand-new ad-hoc inbound shipment
        for this receipt. Mutually exclusive in intent with inbound_shipment_id

        - receipt_lines (optional): Array of specific line quantities to receive.
        If omitted, receives all unreceived lines

        - receipt_lines[].purchase_order_shipment_line_id (conditional): Shipment
        line ID. Required without purchase_order_line_reference or purchase_order_line_id

        - receipt_lines[].purchase_order_line_id (conditional): PO line ID. Alternative
        to shipment_line_id

        - receipt_lines[].purchase_order_line_reference (conditional): PO line reference
        code. Alternative to IDs

        - receipt_lines[].quantity (required): Quantity received. Negative quantities
        force sync fallback.

        - unexpected_items (optional): Items received that were not on the original
        PO. Presence forces sync fallback.

        - unexpected_items[].product_id (conditional): Product ID. Required without
        product_sku

        - unexpected_items[].product_sku (conditional): Product SKU. Required without
        product_id

        - unexpected_items[].quantity (required): Quantity of unexpected item

        - unexpected_items[].action (optional): Action for unexpected item (e.g.,
        add_to_inventory)

        - unexpected_items[].amount (optional): Unit cost for unexpected item

        - unexpected_items[].description (optional): Description for unexpected item'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                purchase_order_id:
                  type: integer
                purchase_order_shipment_id:
                  type: integer
                received_at:
                  type: string
                warehouse_id:
                  type: integer
                inbound_shipment_id:
                  type: integer
                force_new_shipment:
                  type: boolean
                receipt_lines:
                  type: array
                  items:
                    type: object
                    properties:
                      purchase_order_shipment_line_id:
                        type: integer
                      quantity:
                        type: integer
                unexpected_items:
                  type: array
                  items:
                    type: object
                    properties:
                      product_id:
                        type: integer
                      quantity:
                        type: integer
                      action:
                        type: string
                      amount:
                        type: integer
                      description:
                        type: string
              example:
                purchase_order_id: 200
                purchase_order_shipment_id: 50
                received_at: '2024-03-15'
                warehouse_id: 1
                inbound_shipment_id: 42
                force_new_shipment: false
                receipt_lines:
                - purchase_order_shipment_line_id: 301
                  quantity: 100
                unexpected_items:
                - product_id: 43
                  quantity: 5
                  action: add_to_inventory
                  amount: 15
                  description: Extra items received
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      received_at:
                        type: string
                      fulfilled_by:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      inbound_shipment_receipt_lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            purchase_order_shipment_line_id:
                              type: integer
                            quantity:
                              type: integer
                example:
                  message: purchase order shipment receipt has been successfully created
                  data:
                    id: 601
                    received_at: '2024-03-15'
                    fulfilled_by:
                      id: 1
                      name: Jane Smith
                    inbound_shipment_receipt_lines:
                    - id: 701
                      purchase_order_shipment_line_id: 301
                      quantity: 100
        '202':
          description: Accepted
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                example:
                  message: Receiving started — track progress in the job tray
                  data:
                    tracked_job_log_id: 98765
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: array
                    items:
                      type: object
                      properties:
                        message:
                          type: string
                        code:
                          type: string
                        field:
                          type: string
                example:
                  errors:
                  - message: Purchase order 200 is not open
                    code: PurchaseOrder
                    field: id
        '409':
          description: Conflict
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: A receive is already in progress for this purchase order.
                    Track progress in the job tray.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: purchase-orders:write
      operationId: post-api-inbound-shipments-receive
  /api/inbound-shipments/receipts/{receipt}:
    put:
      tags:
      - Purchase Order Shipments
      summary: Update Receipt
      description: 'Update an existing shipment receipt. Adjusts inventory movements
        accordingly.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Path params:

        - receipt: InboundShipmentReceipt (ISR) ID — canonical wire id since Phase
        4.4g.6a (use the `id` returned by /api/purchase-orders/{po}/receipts).


        Fields:

        - received_at (required): Updated receipt date

        - warehouse_id (optional): Override destination warehouse

        - shipment_date (optional): Shipment date if auto-creating a shipment

        - shipping_method_id (optional): Shipping method

        - tracking (optional): Tracking number

        - receipt_lines (required): Updated receipt line quantities

        - receipt_lines[].purchase_order_shipment_line_id (conditional): Shipment
        line ID

        - receipt_lines[].purchase_order_line_id (conditional): PO line ID

        - receipt_lines[].purchase_order_line_reference (conditional): PO line reference

        - receipt_lines[].quantity (required): Updated quantity received

        - unexpected_items (optional): Unexpected items


        Response: returns the canonical InboundShipmentReceipt rendered with `inbound_shipment_receipt_lines`;
        both `data.id` and `data.inbound_shipment_receipt_lines[].id` are ISR / ISRL
        ids.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                received_at:
                  type: string
                warehouse_id:
                  type: integer
                receipt_lines:
                  type: array
                  items:
                    type: object
                    properties:
                      purchase_order_shipment_line_id:
                        type: integer
                      quantity:
                        type: integer
              example:
                received_at: '2024-03-16'
                warehouse_id: 2
                receipt_lines:
                - purchase_order_shipment_line_id: 301
                  quantity: 95
      parameters:
      - name: receipt
        in: path
        schema:
          type: integer
        required: true
        description: InboundShipmentReceipt (ISR) ID — canonical wire id (Phase 4.4g.6a)
        example: '9001'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      received_at:
                        type: string
                      fulfilled_by:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      inbound_shipment_receipt_lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            quantity:
                              type: integer
                            purchase_order_line:
                              type: object
                              properties:
                                id:
                                  type: integer
                                product:
                                  type: object
                                  properties:
                                    id:
                                      type: integer
                                    sku:
                                      type: string
                                    supplier_sku:
                                      type: string
                                description:
                                  type: string
                                received_quantity:
                                  type: integer
                                quantity:
                                  type: integer
                example:
                  message: purchase order shipment receipt has been successfully updated
                  data:
                    id: 9001
                    received_at: '2024-03-16'
                    fulfilled_by:
                      id: 1
                      name: Jane Smith
                    inbound_shipment_receipt_lines:
                    - id: 8101
                      quantity: 95
                      purchase_order_line:
                        id: 501
                        product:
                          id: 42
                          sku: WIDGET-001
                          supplier_sku: SUP-WIDG-001
                        description: Widget
                        received_quantity: 95
                        quantity: 100
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: purchase-orders:write
      operationId: put-api-inbound-shipments-receipts-receipt
    delete:
      tags:
      - Purchase Order Shipments
      summary: Delete Receipt
      description: 'Delete an entire shipment receipt and reverse its inventory movements.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Path params:

        - receipt: InboundShipmentReceipt (ISR) ID — canonical wire id since Phase
        4.4g.6a.'
      parameters:
      - name: receipt
        in: path
        schema:
          type: integer
        required: true
        description: InboundShipmentReceipt (ISR) ID — canonical wire id (Phase 4.4g.6a)
        example: '9001'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: purchase order shipment receipt has been successfully deleted
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: array
                    items:
                      type: object
                      properties:
                        message:
                          type: string
                        code:
                          type: string
                        field:
                          type: string
                example:
                  errors:
                  - message: The FIFO layer for SKU-ABC-123 has already been used
                      in fulfillment
                    code: Product
                    field: sku
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:write
      operationId: delete-api-inbound-shipments-receipts-receipt
  /api/purchase-order-shipments/receipts/{receipt}/delete-lines:
    put:
      tags:
      - Purchase Order Shipments
      summary: Delete Receipt Lines
      description: 'Delete specific lines from a shipment receipt.


        Authentication: Requires Bearer token.


        Path params:

        - receipt: InboundShipmentReceipt (ISR) ID — canonical wire id since Phase
        4.4g.6a.


        Body:

        - ids (required): Array of InboundShipmentReceiptLine (ISRL) IDs to delete.
        The controller resolves them to the paired POSRL ids before reversing inventory.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 8101
                - 8102
      parameters:
      - name: receipt
        in: path
        schema:
          type: integer
        required: true
        description: InboundShipmentReceipt (ISR) ID — canonical wire id (Phase 4.4g.6a)
        example: '9001'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: purchase order shipment receipt has been successfully deleted
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-purchase-order-shipments-receipts-receipt-delete-lines
  /api/inbound-shipments/receipts/{receipt}/delete-impact:
    get:
      tags:
      - Purchase Order Shipments
      summary: Preview Receipt Delete Impact
      description: 'Read-only preview of the allocation-demotion impact of deleting
        this inbound shipment receipt. Because deleting it removes the stock it added,
        this behaves like a manual negative adjustment and returns one row per affected
        product: how much of the removed quantity is unallocated vs soft-allocated
        vs hard-allocated, plus every sales-order allocation and fulfillment (printed
        shipping label) the removal would disturb. Use it to decide which fulfillments
        to authorize voiding via `void_confirmations` on the deleting call. Nothing
        is mutated. A removal that only re-adds stock returns an empty `data` array.


        Authentication: Requires Bearer token.'
      parameters:
      - name: receipt
        in: path
        schema:
          type: integer
        required: true
        description: InboundShipmentReceipt (ISR) ID — canonical wire id (Phase 4.4g.6a)
        example: '9001'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        product_id:
                          type: integer
                        product_sku:
                          type: string
                        product_name:
                          type: string
                        shortfall_quantity:
                          type: integer
                        unallocated_quantity:
                          type: integer
                        soft_allocated_quantity:
                          type: integer
                        hard_allocated_quantity:
                          type: integer
                        affected_allocations:
                          type: array
                          items:
                            type: object
                            properties:
                              allocation_id:
                                type: integer
                              allocation_type:
                                type: string
                              sales_order_id:
                                type: integer
                              order_number:
                                type: string
                              customer_name:
                                type: string
                              fulfillment_id:
                                type: string
                                nullable: true
                              carrier:
                                type: string
                                nullable: true
                              carrier_void_supported:
                                type: string
                                nullable: true
                              voidable_status:
                                type: string
                                nullable: true
                              voidable_detail:
                                type: string
                                nullable: true
                              quantity:
                                type: integer
                example:
                  data:
                  - product_id: 5567
                    product_sku: WIDGET-BLUE
                    product_name: Blue Widget
                    shortfall_quantity: 0
                    unallocated_quantity: 10
                    soft_allocated_quantity: 6
                    hard_allocated_quantity: 4
                    affected_allocations:
                    - allocation_id: 88201
                      allocation_type: soft
                      sales_order_id: 3120
                      order_number: SO-3120
                      customer_name: Acme Co.
                      fulfillment_id: null
                      carrier: null
                      carrier_void_supported: null
                      voidable_status: null
                      voidable_detail: null
                      quantity: 6
                    - allocation_id: 88205
                      allocation_type: hard
                      sales_order_id: 3125
                      order_number: SO-3125
                      customer_name: Beta LLC
                      fulfillment_id: 90142
                      carrier: ups
                      carrier_void_supported: true
                      voidable_status: voidable
                      voidable_detail: null
                      quantity: 4
                      allocation_ids:
                      - 88205
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-inbound-shipments-receipts-receipt-delete-impact
  /api/inbound-shipments/receive/preview-release-impact:
    post:
      tags:
      - Inbound Shipments
      summary: Preview Inbound Shipment Release Impact
      description: 'Read-only preview of which back-ordered sales orders an inbound-shipment
        receive would fill, per receipt line. Send the same payload you would POST
        to receive the shipment; each line is resolved to its purchase order line,
        product and receive warehouse and evaluated against waiting back-ordered demand.
        Nothing is written.


        Each row describes one product the receive would restock. `releasable_quantity`
        is the number of incoming units that can be released to back-ordered demand;
        `orders[]` are the back-ordered sales orders that would be filled; `held_back[]`
        is demand that stays back-ordered, with `reason_kept` explaining why (e.g.
        "Insufficient supply").


        Body: the same shape as the receive call. Minimum: `received_at` plus either
        a `purchase_order_id` or `receipt_lines` (each with `purchase_order_line_id`
        or `purchase_order_line_reference` and a `quantity`). `warehouse_id` defaults
        to the purchase order''s destination warehouse. `release_backorders` (true/false/null)
        mirrors the receive call''s release control.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                purchase_order_id:
                  type: integer
                received_at:
                  type: string
                warehouse_id:
                  type: integer
                release_backorders:
                  type: boolean
                receipt_lines:
                  type: array
                  items:
                    type: object
                    properties:
                      purchase_order_line_id:
                        type: integer
                      quantity:
                        type: integer
              example:
                purchase_order_id: 20
                received_at: '2026-03-15'
                warehouse_id: 2
                release_backorders: true
                receipt_lines:
                - purchase_order_line_id: 50
                  quantity: 8
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        product_id:
                          type: integer
                        product_sku:
                          type: string
                        product_name:
                          type: string
                        releasable_quantity:
                          type: integer
                        orders:
                          type: array
                          items:
                            type: object
                            properties:
                              sales_order_id:
                                type: integer
                              order_number:
                                type: string
                              customer_name:
                                type: string
                              quantity:
                                type: integer
                        held_back:
                          type: array
                          items:
                            type: object
                            properties:
                              allocation_id:
                                type: integer
                              product_id:
                                type: integer
                              sales_order_id:
                                type: integer
                              sales_order_line_id:
                                type: integer
                              sales_order_number:
                                type: string
                              customer_name:
                                type: string
                              quantity:
                                type: integer
                              from_status:
                                type: string
                              to_status:
                                type: string
                              reason_kept:
                                type: string
                example:
                  data:
                  - product_id: 123
                    product_sku: WIDGET-001
                    product_name: Blue Widget 500ml
                    releasable_quantity: 8
                    orders:
                    - sales_order_id: 4602
                      order_number: SO-10501
                      customer_name: Acme Retail
                      quantity: 5
                    - sales_order_id: 4610
                      order_number: SO-10509
                      customer_name: Gamma Foods
                      quantity: 3
                    held_back:
                    - allocation_id: 90311
                      product_id: 123
                      sales_order_id: 4620
                      sales_order_line_id: 55123
                      sales_order_number: SO-10518
                      customer_name: Delta Mart
                      quantity: 4
                      from_status: planned
                      to_status: allocated
                      reason_kept: Insufficient supply
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-inbound-shipments-receive-preview-release-impact
  /api/purchase-order-shipments/{shipment}/activity-log:
    get:
      tags:
      - Purchase Order Shipments
      summary: Get Activity Log
      description: 'Get paginated activity log for a purchase order shipment.


        Authentication: Requires Bearer token.'
      parameters:
      - name: per_page
        in: query
        schema:
          type: integer
        description: 'Records per page. Default: 15'
        example: '15'
      - name: shipment
        in: path
        schema:
          type: integer
        required: true
        description: Purchase order shipment ID
        example: '50'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        description:
                          type: string
                        event:
                          type: string
                        subject_type:
                          type: string
                        subject_id:
                          type: integer
                        properties:
                          type: object
                          properties: {}
                        causer_name:
                          type: string
                        created_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 8001
                    description: created
                    event: created
                    subject_type: PurchaseOrderShipment
                    subject_id: 50
                    properties: {}
                    causer_name: John Doe
                    created_at: '2024-03-10T08:00:00Z'
                  current_page: 1
                  last_page: 1
                  per_page: 15
                  total: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-purchase-order-shipments-shipment-activity-log
  /api/purchase-order-shipments/{shipment}/notes:
    get:
      tags:
      - Purchase Order Shipments
      summary: Get Notes
      description: 'Get paginated notes for a purchase order shipment, ordered by
        newest first.


        Authentication: Requires Bearer token.'
      parameters:
      - name: shipment
        in: path
        schema:
          type: integer
        required: true
        description: Purchase order shipment ID
        example: '50'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        note:
                          type: string
                        is_pinned:
                          type: boolean
                        user:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        created_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 901
                    note: Checked with supplier — shipment on track
                    is_pinned: false
                    user:
                      id: 1
                      name: Jane Smith
                    created_at: '2024-03-12T10:00:00Z'
                  current_page: 1
                  last_page: 1
                  per_page: 15
                  total: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-purchase-order-shipments-shipment-notes
    post:
      tags:
      - Purchase Order Shipments
      summary: Add Note
      description: 'Add a note to a purchase order shipment.


        Authentication: Requires Bearer token.


        Body:

        - note (required): Note text content

        - is_pinned (optional): Whether the note should be pinned. Default: false'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                note:
                  type: string
                is_pinned:
                  type: boolean
              example:
                note: Supplier confirmed goods departed warehouse
                is_pinned: true
      parameters:
      - name: shipment
        in: path
        schema:
          type: integer
        required: true
        description: Purchase order shipment ID
        example: '50'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      note:
                        type: string
                      is_pinned:
                        type: boolean
                      user:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      created_at:
                        type: string
                example:
                  message: note has been successfully created
                  data:
                    id: 902
                    note: Supplier confirmed goods departed warehouse
                    is_pinned: true
                    user:
                      id: 1
                      name: Jane Smith
                    created_at: '2024-03-12T11:00:00Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-purchase-order-shipments-shipment-notes
  /api/purchase-order-shipments/{shipment}/notes/{noteId}:
    delete:
      tags:
      - Purchase Order Shipments
      summary: Delete Note
      description: 'Delete a note from a purchase order shipment.


        Authentication: Requires Bearer token.'
      parameters:
      - name: shipment
        in: path
        schema:
          type: integer
        required: true
        description: Purchase order shipment ID
        example: '50'
      - name: noteId
        in: path
        schema:
          type: integer
        required: true
        description: Note ID to delete
        example: '902'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: note 902 has been successfully deleted
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-purchase-order-shipments-shipment-notes-noteid
  /api/inbound-shipments:
    get:
      tags:
      - Inbound Shipments
      summary: List Inbound Shipments
      description: 'Returns a paginated list of inbound shipments. Supports Spatie
        QueryBuilder filters and sorts.


        :::info[Required scope: `purchase-orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Available sorts: id, shipment_number, status, carrier, tracking_number, expected_arrival_date,
        actual_arrival_date, shipped_at, num_lines, created_at, updated_at


        Default sort: -id (newest first)


        Pagination defaults: 10 per page


        Logistics tracking date filter columns: `logistics_<slug>`_estimate, `logistics_<slug>`_actual
        — where &lt;slug> is the slug of any active LogisticsTrackingField. Each shipment
        row also includes a logistics_tracking_field_values array with { field_slug,
        field_name, estimate_date, actual_date } entries for every active logistics
        tracking field.


        Each shipment row also includes a purchase_orders array — the distinct set
        of purchase orders linked via the shipment’s lines, each as { id, purchase_order_number
        }. A single linked PO yields a one-element array; multiple yields N entries.'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        description: 'Page number (default: 1)'
        example: '1'
      - name: per_page
        in: query
        schema:
          type: integer
        description: 'Items per page (default: 10)'
        example: '10'
      - name: sort
        in: query
        schema:
          type: string
        description: 'Sort field. Prefix with - for descending. Allowed: id, shipment_number,
          status, carrier, tracking_number, expected_arrival_date, actual_arrival_date,
          shipped_at, num_lines, created_at, updated_at'
        example: -id
      - name: filter[search]
        in: query
        schema:
          type: string
        description: Search across shipment number, carrier, tracking number, supplier
          name
      - name: filter[status]
        in: query
        schema:
          type: string
        description: Filter by status (draft, in_transit, received, closed, cancelled)
      - name: filter[date_from]
        in: query
        schema:
          type: string
        description: Filter shipments created on or after this date (YYYY-MM-DD)
      - name: filter[date_to]
        in: query
        schema:
          type: string
        description: Filter shipments created on or before this date (YYYY-MM-DD)
      - name: filter[supplier_id]
        in: query
        schema:
          type: string
        description: Filter by supplier ID (exact match)
      - name: filter[destination_warehouse_id]
        in: query
        schema:
          type: string
        description: Filter by destination warehouse ID
      - name: filter[purchase_order_id]
        in: query
        schema:
          type: string
        description: Filter shipments that include lines from the given purchase order
          ID
      - name: filter[shipment_number.contains]
        in: query
        schema:
          type: string
        description: 'Advanced text filter: shipment number contains value'
      - name: filter[carrier.contains]
        in: query
        schema:
          type: string
        description: 'Advanced text filter: carrier contains value'
      - name: filter[tracking_number.contains]
        in: query
        schema:
          type: string
        description: 'Advanced text filter: tracking number contains value'
      - name: filter[logistics_<slug>_estimate][on_or_after]
        in: query
        schema:
          type: string
        description: 'Date filter on a logistics tracking field estimate date for
          the shipment. Replace &lt;slug> with any active LogisticsTrackingField slug
          (e.g. logistics_port-arrived_estimate). Operators: on, before, after, on_or_before,
          on_or_after, between, is_empty, is_not_empty, is.'
      - name: filter[logistics_<slug>_actual][is_empty]
        in: query
        schema:
          type: string
        description: Date filter on a logistics tracking field actual date for the
          shipment (e.g. logistics_customs-cleared_actual). Same operators as the
          estimate filter.
      - name: filter_groups[conjunction]
        in: query
        schema:
          type: string
        description: 'GroupedFilterSupport tree root conjunction: and/or. Use filter_groups[children][i][...]
          to express nested AND/OR conditions over the logistics tracking columns
          (column = `logistics_<slug>`_estimate or `logistics_<slug>`_actual).'
        example: and
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        shipment_number:
                          type: string
                        status:
                          type: string
                        status_label:
                          type: string
                        supplier_id:
                          type: integer
                        destination_warehouse_id:
                          type: integer
                        carrier:
                          type: string
                        tracking_number:
                          type: string
                        shipping_method_id:
                          type: integer
                        expected_arrival_date:
                          type: string
                        port_eta:
                          type: string
                        warehouse_eta:
                          type: string
                        actual_arrival_date:
                          type: string
                          nullable: true
                        shipped_at:
                          type: string
                        late_shipment:
                          type: boolean
                        created_from_receipt:
                          type: boolean
                        notes:
                          type: string
                        created_by:
                          type: integer
                        asn_last_sent_at:
                          type: string
                          nullable: true
                        total_expected_quantity:
                          type: number
                        total_received_quantity:
                          type: number
                        inbound_shipment_lines_count:
                          type: integer
                        purchase_orders:
                          type: array
                          items:
                            type: object
                            properties:
                              id:
                                type: integer
                              purchase_order_number:
                                type: string
                        supplier:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        destination_warehouse:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        shipping_method:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        creator:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        inbound_shipment_lines:
                          type: array
                        logistics_tracking_field_values:
                          type: array
                          items:
                            type: object
                            properties:
                              field_slug:
                                type: string
                              field_name:
                                type: string
                              estimate_date:
                                type: string
                              actual_date:
                                type: string
                                nullable: true
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  next_page_url:
                    type: string
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 42
                    shipment_number: IS-00042
                    status: in_transit
                    status_label: In Transit
                    supplier_id: 7
                    destination_warehouse_id: 1
                    carrier: FedEx
                    tracking_number: '793644540'
                    shipping_method_id: 3
                    expected_arrival_date: '2025-05-15'
                    port_eta: '2025-05-08'
                    warehouse_eta: '2025-05-15'
                    actual_arrival_date: null
                    shipped_at: '2025-04-20T14:00:00+00:00'
                    late_shipment: false
                    created_from_receipt: false
                    notes: Priority shipment
                    created_by: 1
                    asn_last_sent_at: null
                    total_expected_quantity: 250.0
                    total_received_quantity: 0.0
                    inbound_shipment_lines_count: 5
                    purchase_orders:
                    - id: 30
                      purchase_order_number: PO-001029
                    - id: 31
                      purchase_order_number: PO-001030
                    supplier:
                      id: 7
                      name: Acme Supplies
                    destination_warehouse:
                      id: 1
                      name: Main Warehouse
                    shipping_method:
                      id: 3
                      name: Ground
                    creator:
                      id: 1
                      name: Admin User
                    inbound_shipment_lines: []
                    logistics_tracking_field_values:
                    - field_slug: port-arrived
                      field_name: Port Arrived
                      estimate_date: '2025-05-08'
                      actual_date: null
                    - field_slug: customs-cleared
                      field_name: Customs Cleared
                      estimate_date: '2025-05-12'
                      actual_date: null
                    created_at: '2025-04-18T10:00:00.000000Z'
                    updated_at: '2025-04-20T14:00:00.000000Z'
                  first_page_url: https://sku2.test/api/inbound-shipments?page=1
                  from: 1
                  last_page: 5
                  last_page_url: https://sku2.test/api/inbound-shipments?page=5
                  next_page_url: https://sku2.test/api/inbound-shipments?page=2
                  path: https://sku2.test/api/inbound-shipments
                  per_page: 10
                  prev_page_url: null
                  to: 10
                  total: 48
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: purchase-orders:read
      operationId: get-api-inbound-shipments
    post:
      tags:
      - Inbound Shipments
      summary: Create Inbound Shipment
      description: 'Creates a new inbound shipment in Draft status. Lines are optional
        and can be added later.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Fields:

        - destination_warehouse_id (required): ID of the warehouse where the goods
        will actually land. This is the authoritative destination and is independent
        of the linked purchase order''s header destination warehouse — a shipment
        may deliver a PO''s goods to any warehouse, and one PO may have shipments
        to multiple warehouses.

        - supplier_id (optional): Supplier ID (auto-detected from PO lines if not
        provided)

        - carrier (optional): Carrier name

        - tracking_number (optional): Tracking number

        - shipping_method_id (optional): Shipping method ID

        - expected_arrival_date (optional): Expected arrival date (date)

        - notes (optional): Freeform notes

        - lines (optional): Array of shipment lines — each line requires purchase_order_line_id
        and expected_quantity


        **Logistics dates** (optional): `port_eta` and `warehouse_eta` are persisted
        as `LogisticsTrackingFieldValue` rows (slugs `port-arrived` / `warehouse-arrival`)
        and surfaced as flat fields on the response for backward compatibility.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                destination_warehouse_id:
                  type: integer
                supplier_id:
                  type: integer
                carrier:
                  type: string
                tracking_number:
                  type: string
                  nullable: true
                shipping_method_id:
                  type: integer
                expected_arrival_date:
                  type: string
                port_eta:
                  type: string
                warehouse_eta:
                  type: string
                notes:
                  type: string
                lines:
                  type: array
                  items:
                    type: object
                    properties:
                      purchase_order_line_id:
                        type: integer
                      product_id:
                        type: integer
                      expected_quantity:
                        type: integer
              example:
                destination_warehouse_id: 1
                supplier_id: 7
                carrier: FedEx
                tracking_number: null
                shipping_method_id: 3
                expected_arrival_date: '2025-05-15'
                port_eta: '2025-05-08'
                warehouse_eta: '2025-05-15'
                notes: Priority shipment
                lines:
                - purchase_order_line_id: 55
                  product_id: 12
                  expected_quantity: 50
                - purchase_order_line_id: 56
                  product_id: 13
                  expected_quantity: 25
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      shipment_number:
                        type: string
                      status:
                        type: string
                      status_label:
                        type: string
                      supplier_id:
                        type: integer
                      destination_warehouse_id:
                        type: integer
                      carrier:
                        type: string
                      tracking_number:
                        type: string
                        nullable: true
                      shipping_method_id:
                        type: integer
                      expected_arrival_date:
                        type: string
                      port_eta:
                        type: string
                      warehouse_eta:
                        type: string
                      actual_arrival_date:
                        type: string
                        nullable: true
                      shipped_at:
                        type: string
                        nullable: true
                      late_shipment:
                        type: boolean
                      created_from_receipt:
                        type: boolean
                      notes:
                        type: string
                      created_by:
                        type: integer
                      asn_last_sent_at:
                        type: string
                        nullable: true
                      total_expected_quantity:
                        type: integer
                      total_received_quantity:
                        type: integer
                      inbound_shipment_lines_count:
                        type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 43
                    shipment_number: IS-00043
                    status: draft
                    status_label: Draft
                    supplier_id: 7
                    destination_warehouse_id: 1
                    carrier: FedEx
                    tracking_number: null
                    shipping_method_id: 3
                    expected_arrival_date: '2025-05-15'
                    port_eta: '2025-05-08'
                    warehouse_eta: '2025-05-15'
                    actual_arrival_date: null
                    shipped_at: null
                    late_shipment: false
                    created_from_receipt: false
                    notes: Priority shipment
                    created_by: 1
                    asn_last_sent_at: null
                    total_expected_quantity: 75
                    total_received_quantity: 0
                    inbound_shipment_lines_count: 2
                    created_at: '2025-04-23T10:00:00.000000Z'
                    updated_at: '2025-04-23T10:00:00.000000Z'
                  message: inbound shipment created successfully
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      destination_warehouse_id:
                        type: array
                        items:
                          type: string
                      lines.0.expected_quantity:
                        type: array
                        items:
                          type: string
                example:
                  message: The destination warehouse id field is required.
                  errors:
                    destination_warehouse_id:
                    - A destination warehouse is required.
                    lines.0.expected_quantity:
                    - Expected quantity must be greater than zero.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: purchase-orders:write
      operationId: post-api-inbound-shipments
  /api/inbound-shipments/{inbound_shipment}:
    get:
      tags:
      - Inbound Shipments
      summary: Get Inbound Shipment
      description: 'Returns a single inbound shipment with its lines, supplier, destination
        warehouse, shipping method, purchase order references, and creator.


        :::info[Required scope: `purchase-orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: inbound_shipment
        in: path
        schema:
          type: integer
        required: true
        description: Inbound shipment ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      shipment_number:
                        type: string
                      status:
                        type: string
                      status_label:
                        type: string
                      supplier_id:
                        type: integer
                      destination_warehouse_id:
                        type: integer
                      carrier:
                        type: string
                      tracking_number:
                        type: string
                        nullable: true
                      shipping_method_id:
                        type: integer
                      expected_arrival_date:
                        type: string
                      port_eta:
                        type: string
                      warehouse_eta:
                        type: string
                      actual_arrival_date:
                        type: string
                        nullable: true
                      shipped_at:
                        type: string
                        nullable: true
                      late_shipment:
                        type: boolean
                      created_from_receipt:
                        type: boolean
                      notes:
                        type: string
                      created_by:
                        type: integer
                      asn_last_sent_at:
                        type: string
                        nullable: true
                      total_expected_quantity:
                        type: number
                      total_received_quantity:
                        type: number
                      inbound_shipment_lines_count:
                        type: integer
                      purchase_orders:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            purchase_order_number:
                              type: string
                      supplier:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      destination_warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      shipping_method:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      creator:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      inbound_shipment_lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            inbound_shipment_id:
                              type: integer
                            purchase_order_line_id:
                              type: integer
                            product_id:
                              type: integer
                            expected_quantity:
                              type: number
                            received_quantity:
                              type: number
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 42
                    shipment_number: IS-00042
                    status: draft
                    status_label: Draft
                    supplier_id: 7
                    destination_warehouse_id: 1
                    carrier: FedEx
                    tracking_number: null
                    shipping_method_id: 3
                    expected_arrival_date: '2025-05-15'
                    port_eta: '2025-05-08'
                    warehouse_eta: '2025-05-15'
                    actual_arrival_date: null
                    shipped_at: null
                    late_shipment: false
                    created_from_receipt: false
                    notes: Fragile items
                    created_by: 1
                    asn_last_sent_at: null
                    total_expected_quantity: 100.0
                    total_received_quantity: 0.0
                    inbound_shipment_lines_count: 2
                    purchase_orders:
                    - id: 30
                      purchase_order_number: PO-001029
                    supplier:
                      id: 7
                      name: Acme Supplies
                    destination_warehouse:
                      id: 1
                      name: Main Warehouse
                    shipping_method:
                      id: 3
                      name: Ground
                    creator:
                      id: 1
                      name: Admin User
                    inbound_shipment_lines:
                    - id: 101
                      inbound_shipment_id: 42
                      purchase_order_line_id: 55
                      product_id: 12
                      expected_quantity: 50.0
                      received_quantity: 0.0
                    - id: 102
                      inbound_shipment_id: 42
                      purchase_order_line_id: 56
                      product_id: 13
                      expected_quantity: 50.0
                      received_quantity: 0.0
                    created_at: '2025-04-18T10:00:00.000000Z'
                    updated_at: '2025-04-18T10:00:00.000000Z'
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No query results for model [App\Models\InboundShipment]
                    42
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: purchase-orders:read
      operationId: get-api-inbound-shipments-inbound-shipment
    put:
      tags:
      - Inbound Shipments
      summary: Update Inbound Shipment
      description: 'Updates an inbound shipment. Only editable for shipments in Draft
        status. Lines array syncs the shipment lines (pass line id to update existing,
        omit id to add new, omit line entirely to delete).


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        **destination_warehouse_id** (optional): The shipment''s destination warehouse
        may be changed only while the shipment has no receipts. Once goods have been
        received against the shipment it is locked — attempting to change it returns
        a 422 validation error on `destination_warehouse_id` (the receipts and their
        FIFO layers / inventory movements already point at it).


        **Logistics dates** (optional): `port_eta` and `warehouse_eta` are routed
        through `LogisticsTrackingFieldValue` rows. Pass them as part of the standard
        PATCH/PUT payload — the controller persists them only when the keys are present
        (use `null` to clear an existing value).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                destination_warehouse_id:
                  type: integer
                carrier:
                  type: string
                tracking_number:
                  type: string
                shipping_method_id:
                  type: integer
                expected_arrival_date:
                  type: string
                port_eta:
                  type: string
                warehouse_eta:
                  type: string
                notes:
                  type: string
                lines:
                  type: array
                  items:
                    type: object
                    properties:
                      id:
                        type: integer
                      purchase_order_line_id:
                        type: integer
                      product_id:
                        type: integer
                      expected_quantity:
                        type: integer
              example:
                destination_warehouse_id: 2
                carrier: UPS
                tracking_number: 1Z999AA10123456784
                shipping_method_id: 2
                expected_arrival_date: '2025-05-20'
                port_eta: '2025-05-08'
                warehouse_eta: '2025-05-20'
                notes: Updated tracking info
                lines:
                - id: 101
                  purchase_order_line_id: 55
                  product_id: 12
                  expected_quantity: 60
      parameters:
      - name: inbound_shipment
        in: path
        schema:
          type: integer
        required: true
        example: '42'
        description: The inbound shipment ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      shipment_number:
                        type: string
                      status:
                        type: string
                      status_label:
                        type: string
                      carrier:
                        type: string
                      tracking_number:
                        type: string
                      port_eta:
                        type: string
                      warehouse_eta:
                        type: string
                      updated_at:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 42
                    shipment_number: IS-00042
                    status: draft
                    status_label: Draft
                    carrier: UPS
                    tracking_number: 1Z999AA10123456784
                    port_eta: '2025-05-08'
                    warehouse_eta: '2025-05-20'
                    updated_at: '2025-04-23T12:00:00.000000Z'
                  message: inbound shipment updated successfully
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 422 Not Editable
                  value:
                    message: Cannot update a shipment that is not in draft status.
                example-1:
                  summary: 422 Destination Warehouse Locked
                  value:
                    message: The destination warehouse cannot be changed once goods
                      have been received against this shipment.
                    errors:
                      destination_warehouse_id:
                      - The destination warehouse cannot be changed once goods have
                        been received against this shipment.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:write
      operationId: put-api-inbound-shipments-inbound-shipment
    delete:
      tags:
      - Inbound Shipments
      summary: Delete Inbound Shipment
      description: 'Deletes an inbound shipment. Only shipments in Draft or Cancelled
        status that have not been received can be deleted.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: inbound_shipment
        in: path
        schema:
          type: integer
        required: true
        example: '42'
        description: The inbound shipment ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: inbound shipment deleted successfully
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Cannot delete a shipment that has been received or is closed.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:write
      operationId: delete-api-inbound-shipments-inbound-shipment
  /api/inbound-shipments/from-invoice/{purchaseInvoice}:
    post:
      tags:
      - Inbound Shipments
      summary: Create Inbound Shipment From Purchase Invoice
      description: 'Create a new inbound shipment pre-filled from a supplier invoice.
        Each invoice line is converted into a shipment line that retains the purchase_invoice_line_id
        and resolves to its underlying purchase_order_line_id.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Validation:

        - destination_warehouse_id: required, must exist on warehouses

        - lines: required, min 1, each must reference an existing purchase_invoice_line_id

        - expected_quantity: required, numeric > 0


        If an invoice line has already been fully shipped on a prior shipment, the
        response includes a soft warning under warnings[] (key: `lines.<purchase_invoice_line_id>`)
        rather than failing the request. Set mark_as_shipped=true to immediately transition
        the new shipment to in_transit.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                destination_warehouse_id:
                  type: integer
                carrier:
                  type: string
                tracking_number:
                  type: string
                shipping_method_id:
                  type: integer
                expected_arrival_date:
                  type: string
                etd:
                  type: string
                  nullable: true
                port_eta:
                  type: string
                  nullable: true
                warehouse_eta:
                  type: string
                  nullable: true
                notes:
                  type: string
                mark_as_shipped:
                  type: boolean
                lines:
                  type: array
                  items:
                    type: object
                    properties:
                      purchase_invoice_line_id:
                        type: integer
                      expected_quantity:
                        type: integer
              example:
                destination_warehouse_id: 1
                carrier: FedEx
                tracking_number: '793644540'
                shipping_method_id: 3
                expected_arrival_date: '2025-06-15'
                etd: null
                port_eta: null
                warehouse_eta: null
                notes: Shipment created from invoice INV-2024-001
                mark_as_shipped: false
                lines:
                - purchase_invoice_line_id: 201
                  expected_quantity: 10
      parameters:
      - name: purchaseInvoice
        in: path
        schema:
          type: integer
        required: true
        description: Purchase invoice ID to create the shipment from
        example: '42'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 Success
                  value:
                    data:
                      id: 87
                      shipment_number: IS-00087
                      status: draft
                      status_label: Draft
                      supplier_id: 7
                      purchase_invoice_id: 42
                      destination_warehouse_id: 1
                      carrier: FedEx
                      tracking_number: '793644540'
                      shipping_method_id: 3
                      expected_arrival_date: '2025-06-15'
                      actual_arrival_date: null
                      shipped_at: null
                      notes: Shipment created from invoice INV-2024-001
                      created_by: 1
                      asn_last_sent_at: null
                      total_expected_quantity: 10
                      total_received_quantity: 0
                      inbound_shipment_lines_count: 1
                      supplier:
                        id: 7
                        name: Acme Supplies Ltd
                      destination_warehouse:
                        id: 1
                        name: Main Warehouse
                      shipping_method:
                        id: 3
                        name: Ground
                      creator:
                        id: 1
                        name: Admin User
                      purchase_invoice:
                        id: 42
                        supplier_invoice_number: INV-2024-001
                        reference: INV-2024-001
                      inbound_shipment_lines:
                      - id: 301
                        inbound_shipment_id: 87
                        purchase_order_id: 15
                        purchase_order_line_id: 101
                        purchase_invoice_line_id: 201
                        product_id: 10
                        expected_quantity: 10
                        received_quantity: 0
                      created_at: '2025-05-07T10:00:00.000000Z'
                      updated_at: '2025-05-07T10:00:00.000000Z'
                    message: inbound shipment created successfully
                    warnings: []
                example-1:
                  summary: 200 Success With Overshipment Warning
                  value:
                    data:
                      id: 88
                      shipment_number: IS-00088
                      status: draft
                    message: inbound shipment created successfully
                    warnings:
                    - message: Line 201 has already been shipped on prior shipments.
                        Overshipment will be allowed but flagged.
                      code: overshipment
                      key: lines.201
                      data:
                        purchase_invoice_line_id: 201
        '422':
          description: Unprocessable Entity
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      destination_warehouse_id:
                        type: array
                        items:
                          type: string
                      lines:
                        type: array
                        items:
                          type: string
                      lines.0.purchase_invoice_line_id:
                        type: array
                        items:
                          type: string
                      lines.0.expected_quantity:
                        type: array
                        items:
                          type: string
                example:
                  message: The given data was invalid.
                  errors:
                    destination_warehouse_id:
                    - A destination warehouse is required.
                    lines:
                    - At least one invoice line must be selected.
                    lines.0.purchase_invoice_line_id:
                    - One or more invoice lines could not be found.
                    lines.0.expected_quantity:
                    - Expected quantity must be greater than zero.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:write
      operationId: post-api-inbound-shipments-from-invoice-purchaseinvoice
  /api/inbound-shipments/{inbound_shipment}/mark-as-planned:
    post:
      tags:
      - Inbound Shipments
      summary: Mark As Planned
      description: 'Transitions the shipment from Draft to Planned status. Planned
        is an optional intermediate state indicating the shipment is scheduled but
        has not yet shipped. Planned shipments do not reserve quantity against purchase
        order fulfillment.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        The shipment must be in Draft status and must have at least one line.


        Takes no request body.


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: inbound_shipment
        in: path
        schema:
          type: integer
        required: true
        example: '42'
        description: The inbound shipment ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      status:
                        type: string
                      status_label:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 42
                    status: planned
                    status_label: Planned
                  message: Inbound shipment marked as planned.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 422 Not Draft
                  value:
                    message: Only draft shipments can be marked as planned.
                example-1:
                  summary: 422 No Items
                  value:
                    message: Cannot mark a shipment as planned without any items.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:write
      operationId: post-api-inbound-shipments-inbound-shipment-mark-as-planned
  /api/inbound-shipments/{inbound_shipment}/unmark-as-planned:
    post:
      tags:
      - Inbound Shipments
      summary: Unmark As Planned
      description: 'Reverts a Planned shipment back to Draft status, allowing edits.
        Only shipments currently in Planned status can be unmarked.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Takes no request body.


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: inbound_shipment
        in: path
        schema:
          type: integer
        required: true
        example: '42'
        description: The inbound shipment ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      status:
                        type: string
                      status_label:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 42
                    status: draft
                    status_label: Draft
                  message: Inbound shipment unmarked as planned.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Only planned shipments can be unmarked as planned.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:write
      operationId: post-api-inbound-shipments-inbound-shipment-unmark-as-planned
  /api/inbound-shipments/{inbound_shipment}/mark-as-shipped:
    post:
      tags:
      - Inbound Shipments
      summary: Mark As Shipped
      description: 'Transitions the shipment from Draft to In Transit status and records
        carrier/tracking information.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Fields:

        - carrier (optional): Carrier name

        - tracking_number (optional): Tracking number

        - shipped_at (optional): Date/time shipped (defaults to now)'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                carrier:
                  type: string
                tracking_number:
                  type: string
                shipped_at:
                  type: string
              example:
                carrier: FedEx
                tracking_number: '793644540123'
                shipped_at: '2025-04-23T10:00:00'
      parameters:
      - name: inbound_shipment
        in: path
        schema:
          type: integer
        required: true
        example: '42'
        description: The inbound shipment ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      status:
                        type: string
                      status_label:
                        type: string
                      carrier:
                        type: string
                      tracking_number:
                        type: string
                      shipped_at:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 42
                    status: in_transit
                    status_label: In Transit
                    carrier: FedEx
                    tracking_number: '793644540123'
                    shipped_at: '2025-04-23T10:00:00+00:00'
                  message: Inbound shipment marked as shipped.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Cannot mark a shipment as shipped unless it is in draft
                    status.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:write
      operationId: post-api-inbound-shipments-inbound-shipment-mark-as-shipped
  /api/inbound-shipments/{inbound_shipment}/receive:
    post:
      tags:
      - Inbound Shipments
      summary: Receive Shipment
      description: 'Records receipt of items for the specified shipment lines and
        updates inventory. Can be called multiple times for partial receiving.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Fields:

        - received_at (required): Date/time of receipt

        - warehouse_id (optional): Override destination warehouse for this receipt

        - receipt_lines (required): Array of lines to receive — each requires inbound_shipment_line_id
        and quantity (min 0.0001)'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                received_at:
                  type: string
                warehouse_id:
                  type: integer
                receipt_lines:
                  type: array
                  items:
                    type: object
                    properties:
                      inbound_shipment_line_id:
                        type: integer
                      quantity:
                        type: integer
              example:
                received_at: '2025-05-15T09:00:00'
                warehouse_id: 1
                receipt_lines:
                - inbound_shipment_line_id: 101
                  quantity: 50
                - inbound_shipment_line_id: 102
                  quantity: 25
      parameters:
      - name: inbound_shipment
        in: path
        schema:
          type: integer
        required: true
        example: '42'
        description: The inbound shipment ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      status:
                        type: string
                      status_label:
                        type: string
                      total_received_quantity:
                        type: number
                      actual_arrival_date:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 42
                    status: received
                    status_label: Received
                    total_received_quantity: 75.0
                    actual_arrival_date: '2025-05-15'
                  message: Items received successfully.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      received_at:
                        type: array
                        items:
                          type: string
                      receipt_lines:
                        type: array
                        items:
                          type: string
                example:
                  message: The received at field is required.
                  errors:
                    received_at:
                    - The received at field is required.
                    receipt_lines:
                    - The receipt lines field is required.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:write
      operationId: post-api-inbound-shipments-inbound-shipment-receive
  /api/inbound-shipments/{inbound_shipment}/receipts:
    post:
      tags:
      - Inbound Shipments
      summary: Create Receipt
      description: "Creates a native InboundShipmentReceipt with lines and posts FIFO/inventory\
        \ directly via the new IS-first path (Phase 1 of the InboundShipment / PurchaseOrderShipment\
        \ unification). Coexists with the legacy `/receive` endpoint, which delegates\
        \ through the PO shipment receipt path.\n\n:::info[Required scope: `purchase-orders:write`]\n\
        Grant this scope to your token under [Settings → Developer → Personal Access\
        \ Tokens](https://app.sku.io/settings/api).\n:::\n\nAuthentication: Requires\
        \ Bearer token.\n\nFields:\n- received_at (required, datetime): Date/time\
        \ of receipt\n- warehouse_id (required, exists:warehouses): Receiving warehouse\
        \ for this receipt\n- notes (optional, string): Free-text notes attached to\
        \ the receipt\n- receipt_lines (required, min 1):\n  - inbound_shipment_line_id\
        \ (required, exists:inbound_shipment_lines): Must belong to this inbound shipment\n\
        \  - quantity (required, numeric, min 0.0001)\n\nSide effects:\n- Creates\
        \ an `inbound_shipment_receipts` row + per-line `inbound_shipment_receipt_lines`\
        \ rows\n- Creates a FIFO layer + InventoryMovement per line (TYPE_PURCHASE_RECEIPT)\
        \ at the receipt's warehouse\n- Increments `received_quantity` on each InboundShipmentLine\
        \ and the matching PurchaseOrderLine\n- Transitions the InboundShipment to\
        \ `partially_received` or `received` (sets `fully_received_at` when all lines\
        \ are fully received)"
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                received_at:
                  type: string
                warehouse_id:
                  type: integer
                notes:
                  type: string
                receipt_lines:
                  type: array
                  items:
                    type: object
                    properties:
                      inbound_shipment_line_id:
                        type: integer
                      quantity:
                        type: integer
              example:
                received_at: '2026-04-26T09:00:00'
                warehouse_id: 1
                notes: Partial receipt — pallet 1 of 3
                receipt_lines:
                - inbound_shipment_line_id: 101
                  quantity: 50
                - inbound_shipment_line_id: 102
                  quantity: 25
      parameters:
      - name: inbound_shipment
        in: path
        schema:
          type: integer
        required: true
        example: '42'
        description: The inbound shipment ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      inbound_shipment_id:
                        type: integer
                      warehouse_id:
                        type: integer
                      received_at:
                        type: string
                      notes:
                        type: string
                      received_by:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      inbound_shipment_receipt_lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            inbound_shipment_receipt_id:
                              type: integer
                            inbound_shipment_line_id:
                              type: integer
                            purchase_order_line_id:
                              type: integer
                            quantity:
                              type: string
                            total_cost:
                              type: string
                  message:
                    type: string
                example:
                  data:
                    id: 18
                    inbound_shipment_id: 42
                    warehouse_id: 1
                    received_at: '2026-04-26T09:00:00.000000Z'
                    notes: Partial receipt — pallet 1 of 3
                    received_by:
                      id: 7
                      name: Casey Receiver
                    inbound_shipment_receipt_lines:
                    - id: 31
                      inbound_shipment_receipt_id: 18
                      inbound_shipment_line_id: 101
                      purchase_order_line_id: 5012
                      quantity: '50.0000'
                      total_cost: '1250.0000'
                    - id: 32
                      inbound_shipment_receipt_id: 18
                      inbound_shipment_line_id: 102
                      purchase_order_line_id: 5013
                      quantity: '25.0000'
                      total_cost: '500.0000'
                  message: Inbound shipment receipt created successfully.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 422 Validation Error
                  value:
                    message: The received at field is required.
                    errors:
                      received_at:
                      - A received_at datetime is required.
                      warehouse_id:
                      - A receiving warehouse is required.
                      receipt_lines:
                      - At least one receipt line is required.
                example-1:
                  summary: 422 Line Not On Shipment
                  value:
                    message: Inbound shipment line 999 does not belong to this shipment.
                    data: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:write
      operationId: post-api-inbound-shipments-inbound-shipment-receipts
  /api/inbound-shipments/{inbound_shipment}/cancel:
    post:
      tags:
      - Inbound Shipments
      summary: Cancel Shipment
      description: 'Cancels an inbound shipment. Only shipments in Draft or In Transit
        status can be cancelled.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: inbound_shipment
        in: path
        schema:
          type: integer
        required: true
        example: '42'
        description: The inbound shipment ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      status:
                        type: string
                      status_label:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 42
                    status: cancelled
                    status_label: Cancelled
                  message: Inbound shipment cancelled.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Cannot cancel a shipment in its current status.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:write
      operationId: post-api-inbound-shipments-inbound-shipment-cancel
  /api/inbound-shipments/{inbound_shipment}/close:
    post:
      tags:
      - Inbound Shipments
      summary: Close Shipment
      description: 'Closes an inbound shipment, marking it as fully processed. Only
        Received shipments can be closed.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: inbound_shipment
        in: path
        schema:
          type: integer
        required: true
        example: '42'
        description: The inbound shipment ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      status:
                        type: string
                      status_label:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 42
                    status: closed
                    status_label: Closed
                  message: Inbound shipment closed.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: purchase-orders:write
      operationId: post-api-inbound-shipments-inbound-shipment-close
  /api/inbound-shipments/{inbound_shipment}/revert-to-draft:
    post:
      tags:
      - Inbound Shipments
      summary: Revert to Draft
      description: 'Reverts an In Transit shipment back to Draft status, allowing
        edits. Only In Transit shipments that have not been received can be reverted.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: inbound_shipment
        in: path
        schema:
          type: integer
        required: true
        example: '42'
        description: The inbound shipment ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      status:
                        type: string
                      status_label:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 42
                    status: draft
                    status_label: Draft
                  message: Inbound shipment reverted to draft.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: purchase-orders:write
      operationId: post-api-inbound-shipments-inbound-shipment-revert-to-draft
  /api/inbound-shipments/{inbound_shipment}/resolve-import:
    post:
      tags:
      - Inbound Shipments
      summary: Preview Import Resolution
      description: 'Resolves SKUs and PO numbers from a bulk import file, returning
        matched products and purchase order lines before committing. Use this as a
        preview/validation step before calling import-items.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Fields:

        - skus (required): Array of SKUs or barcodes to resolve (1-5000 items)

        - po_numbers (optional): Array of PO numbers to filter matching lines'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                skus:
                  type: array
                  items:
                    type: string
                po_numbers:
                  type: array
                  items:
                    type: string
              example:
                skus:
                - SKU-001
                - SKU-002
                - SKU-003
                po_numbers:
                - PO-0042
                - PO-0043
      parameters:
      - name: inbound_shipment
        in: path
        schema:
          type: integer
        required: true
        example: '42'
        description: The inbound shipment ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  resolved:
                    type: array
                    items:
                      type: object
                      properties:
                        sku:
                          type: string
                        product_id:
                          type: integer
                        product_name:
                          type: string
                        matched_po_lines:
                          type: array
                          items:
                            type: object
                            properties:
                              purchase_order_line_id:
                                type: integer
                              po_number:
                                type: string
                              unreceived_quantity:
                                type: integer
                  unresolved:
                    type: array
                    items:
                      type: string
                example:
                  resolved:
                  - sku: SKU-001
                    product_id: 12
                    product_name: Widget A
                    matched_po_lines:
                    - purchase_order_line_id: 55
                      po_number: PO-0042
                      unreceived_quantity: 100
                  unresolved:
                  - SKU-003
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: purchase-orders:write
      operationId: post-api-inbound-shipments-inbound-shipment-resolve-import
  /api/inbound-shipments/{inbound_shipment}/import-items:
    post:
      tags:
      - Inbound Shipments
      summary: Import Items
      description: 'Bulk imports items into an inbound shipment. Adds shipment lines
        for each item. Set replace_existing=true to clear existing lines first.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Fields:

        - items (required): Array of items (1-5000) — each requires product_id and
        expected_quantity; purchase_order_line_id is optional

        - replace_existing (optional): If true, removes all existing unlinked lines
        before adding. Default: false'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                items:
                  type: array
                  items:
                    type: object
                    properties:
                      product_id:
                        type: integer
                      purchase_order_line_id:
                        type: integer
                      expected_quantity:
                        type: integer
                replace_existing:
                  type: boolean
              example:
                items:
                - product_id: 12
                  purchase_order_line_id: 55
                  expected_quantity: 50
                - product_id: 13
                  purchase_order_line_id: null
                  expected_quantity: 25
                replace_existing: false
      parameters:
      - name: inbound_shipment
        in: path
        schema:
          type: integer
        required: true
        example: '42'
        description: The inbound shipment ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      shipment_number:
                        type: string
                      status:
                        type: string
                      inbound_shipment_lines_count:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    id: 42
                    shipment_number: IS-00042
                    status: draft
                    inbound_shipment_lines_count: 2
                  message: Items imported successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: purchase-orders:write
      operationId: post-api-inbound-shipments-inbound-shipment-import-items
  /api/inbound-shipments/{inbound_shipment}/available-purchase-orders:
    get:
      tags:
      - Inbound Shipments
      summary: List Available Purchase Orders
      description: 'Returns open purchase orders that have unreceived lines available
        to be added to this inbound shipment. Excludes POs where all lines are already
        fully assigned.


        :::info[Required scope: `purchase-orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        **Warehouse scope:** results are NOT restricted to the shipment''s destination
        warehouse. The PO header `destination_warehouse_id` is only a pre-fill default
        — an inbound shipment carries its own authoritative destination, so any open,
        unreceived PO may be assigned regardless of its header warehouse. POs whose
        header warehouse matches this shipment''s destination are surfaced first as
        the likeliest match, then ordered by id descending.'
      parameters:
      - name: inbound_shipment
        in: path
        schema:
          type: integer
        required: true
        example: '42'
        description: The inbound shipment ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        purchase_order_number:
                          type: string
                        date:
                          type: string
                        supplier_name:
                          type: string
                        unreceived_lines_count:
                          type: integer
                        total_unreceived_quantity:
                          type: number
                        lines_on_active_shipments:
                          type: integer
                        all_lines_assigned:
                          type: boolean
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 10
                    purchase_order_number: PO-0042
                    date: '2025-04-01'
                    supplier_name: Acme Supplies
                    unreceived_lines_count: 3
                    total_unreceived_quantity: 150.0
                    lines_on_active_shipments: 1
                    all_lines_assigned: false
                  per_page: 10
                  total: 5
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:read
      operationId: get-api-inbound-shipments-inbound-shipment-available-purchase-orders
  /api/inbound-shipments/{inbound_shipment}/available-po-lines:
    get:
      tags:
      - Inbound Shipments
      summary: List Available Purchase Order Lines
      description: 'Returns unreceived PO lines grouped by purchase order for the
        given PO IDs. Each line shows how much quantity is available to assign to
        this shipment.


        :::info[Required scope: `purchase-orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Query parameters:

        - purchase_order_ids (required): Comma-separated PO IDs

        - search (optional): Filter by product SKU or name'
      parameters:
      - name: purchase_order_ids
        in: query
        schema:
          type: string
        description: Comma-separated list of purchase order IDs to fetch lines for
          (required)
        example: 10,11
      - name: search
        in: query
        schema:
          type: string
        description: Optional search to filter lines by SKU or product name
      - name: inbound_shipment
        in: path
        schema:
          type: integer
        required: true
        example: '42'
        description: The inbound shipment ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        purchase_order_id:
                          type: integer
                        purchase_order_number:
                          type: string
                        supplier_name:
                          type: string
                        lines:
                          type: array
                          items:
                            type: object
                            properties:
                              purchase_order_line_id:
                                type: integer
                              product_id:
                                type: integer
                              sku:
                                type: string
                              product_name:
                                type: string
                              ordered_quantity:
                                type: number
                              received_quantity:
                                type: number
                              unreceived_quantity:
                                type: number
                              already_on_shipment:
                                type: boolean
                              on_current_shipment:
                                type: boolean
                              assigned_quantity:
                                type: number
                              available_quantity:
                                type: number
                example:
                  data:
                  - purchase_order_id: 10
                    purchase_order_number: PO-0042
                    supplier_name: Acme Supplies
                    lines:
                    - purchase_order_line_id: 55
                      product_id: 12
                      sku: SKU-001
                      product_name: Widget A
                      ordered_quantity: 100.0
                      received_quantity: 0.0
                      unreceived_quantity: 100.0
                      already_on_shipment: false
                      on_current_shipment: false
                      assigned_quantity: 0.0
                      available_quantity: 100.0
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:read
      operationId: get-api-inbound-shipments-inbound-shipment-available-po-lines
  /api/inbound-shipments/{inbound_shipment}/bills:
    get:
      tags:
      - Inbound Shipments
      summary: List Bills
      description: 'Returns all landed cost bills attached to this inbound shipment,
        ordered by invoice date descending. Includes bill lines and allocations to
        purchase order lines.


        :::info[Required scope: `purchase-orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: inbound_shipment
        in: path
        schema:
          type: integer
        required: true
        example: '42'
        description: The inbound shipment ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        vendor_id:
                          type: integer
                        vendor_name:
                          type: string
                        invoice_number:
                          type: string
                        invoice_date:
                          type: string
                        currency_id:
                          type: integer
                        currency_code:
                          type: string
                        currency_rate:
                          type: number
                        proration_strategy:
                          type: string
                        total_amount:
                          type: number
                        totals:
                          type: object
                          properties:
                            line_count:
                              type: integer
                            amount:
                              type: number
                            tax:
                              type: number
                            grand_total:
                              type: number
                        lines:
                          type: array
                          items:
                            type: object
                            properties:
                              id:
                                type: integer
                              description:
                                type: string
                              quantity:
                                type: integer
                              amount:
                                type: number
                              extended_amount:
                                type: number
                              nominal_code_id:
                                type: integer
                        allocations:
                          type: array
                          items:
                            type: object
                            properties:
                              id:
                                type: integer
                              allocation_amount:
                                type: number
                              allocation_percentage:
                                type: number
                              proration_strategy:
                                type: string
                              purchase_order_line_id:
                                type: integer
                              purchase_order_line:
                                type: object
                                properties:
                                  id:
                                    type: integer
                                  description:
                                    type: string
                                  quantity:
                                    type: integer
                                  product:
                                    type: object
                                    properties:
                                      id:
                                        type: integer
                                      name:
                                        type: string
                                      sku:
                                        type: string
                example:
                  data:
                  - id: 7
                    vendor_id: 3
                    vendor_name: Freight Co.
                    invoice_number: INV-20250420
                    invoice_date: '2025-04-20'
                    currency_id: 1
                    currency_code: USD
                    currency_rate: 1.0
                    proration_strategy: cost_based
                    total_amount: 500.0
                    totals:
                      line_count: 1
                      amount: 500.0
                      tax: 0.0
                      grand_total: 500.0
                    lines:
                    - id: 20
                      description: Ocean freight
                      quantity: 1
                      amount: 500.0
                      extended_amount: 500.0
                      nominal_code_id: 5
                    allocations:
                    - id: 11
                      allocation_amount: 250.0
                      allocation_percentage: 50.0
                      proration_strategy: cost_based
                      purchase_order_line_id: 55
                      purchase_order_line:
                        id: 55
                        description: Widget A
                        quantity: 100
                        product:
                          id: 12
                          name: Widget A
                          sku: SKU-001
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:read
      operationId: get-api-inbound-shipments-inbound-shipment-bills
    post:
      tags:
      - Inbound Shipments
      summary: Create Bill
      description: 'Creates a landed cost bill attached to this inbound shipment.
        Cannot be added to cancelled shipments.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Fields:

        - vendor_id (required): Vendor/supplier ID

        - invoice_number (required, unique): Invoice number

        - invoice_date (required): Invoice date

        - currency_id (optional): Currency ID

        - currency_rate (optional): Exchange rate

        - proration_strategy (required): One of: cost_based, quantity_based, weight_based,
        manual

        - lines (required): Array of bill line items — each requires description,
        quantity, amount; nominal_code_id optional

        - allocations (optional): Array of allocations to PO lines or warehouse transfer
        lines — allocation amounts must not exceed bill total'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                vendor_id:
                  type: integer
                invoice_number:
                  type: string
                invoice_date:
                  type: string
                currency_id:
                  type: integer
                currency_rate:
                  type: integer
                proration_strategy:
                  type: string
                lines:
                  type: array
                  items:
                    type: object
                    properties:
                      description:
                        type: string
                      quantity:
                        type: integer
                      amount:
                        type: integer
                      nominal_code_id:
                        type: integer
                      tax_rate_id:
                        type: string
                        nullable: true
                allocations:
                  type: array
                  items:
                    type: object
                    properties:
                      purchase_order_line_id:
                        type: integer
                      warehouse_transfer_line_id:
                        type: string
                        nullable: true
                      allocation_amount:
                        type: integer
                      proration_strategy:
                        type: string
              example:
                vendor_id: 3
                invoice_number: INV-20250420
                invoice_date: '2025-04-20'
                currency_id: 1
                currency_rate: 1
                proration_strategy: cost_based
                lines:
                - description: Ocean freight
                  quantity: 1
                  amount: 500
                  nominal_code_id: 5
                  tax_rate_id: null
                allocations:
                - purchase_order_line_id: 55
                  warehouse_transfer_line_id: null
                  allocation_amount: 250
                  proration_strategy: cost_based
                - purchase_order_line_id: 56
                  warehouse_transfer_line_id: null
                  allocation_amount: 250
                  proration_strategy: cost_based
      parameters:
      - name: inbound_shipment
        in: path
        schema:
          type: integer
        required: true
        example: '42'
        description: The inbound shipment ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      vendor_id:
                        type: integer
                      vendor_name:
                        type: string
                      invoice_number:
                        type: string
                      invoice_date:
                        type: string
                      total_amount:
                        type: number
                  message:
                    type: string
                example:
                  data:
                    id: 7
                    vendor_id: 3
                    vendor_name: Freight Co.
                    invoice_number: INV-20250420
                    invoice_date: '2025-04-20'
                    total_amount: 500.0
                  message: Bill created successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: purchase-orders:write
      operationId: post-api-inbound-shipments-inbound-shipment-bills
  /api/inbound-shipments/{inbound_shipment}/bills/{bill}:
    get:
      tags:
      - Inbound Shipments
      summary: Get Bill
      description: 'Returns a single bill attached to this inbound shipment with all
        lines and allocations.


        :::info[Required scope: `purchase-orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: inbound_shipment
        in: path
        schema:
          type: integer
        required: true
        example: '42'
        description: The inbound shipment ID.
      - name: bill
        in: path
        schema:
          type: integer
        required: true
        example: '7'
        description: The bill ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      vendor_id:
                        type: integer
                      vendor_name:
                        type: string
                      invoice_number:
                        type: string
                      invoice_date:
                        type: string
                      currency_code:
                        type: string
                      currency_rate:
                        type: number
                      proration_strategy:
                        type: string
                      total_amount:
                        type: number
                      lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            description:
                              type: string
                            quantity:
                              type: integer
                            amount:
                              type: number
                            extended_amount:
                              type: number
                      allocations:
                        type: array
                example:
                  data:
                    id: 7
                    vendor_id: 3
                    vendor_name: Freight Co.
                    invoice_number: INV-20250420
                    invoice_date: '2025-04-20'
                    currency_code: USD
                    currency_rate: 1.0
                    proration_strategy: cost_based
                    total_amount: 500.0
                    lines:
                    - id: 20
                      description: Ocean freight
                      quantity: 1
                      amount: 500.0
                      extended_amount: 500.0
                    allocations: []
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Bill not found for this inbound shipment.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: purchase-orders:read
      operationId: get-api-inbound-shipments-inbound-shipment-bills-bill
    patch:
      tags:
      - Inbound Shipments
      summary: Update Bill
      description: 'Updates a bill attached to this inbound shipment. Cannot modify
        bills on a cancelled shipment.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Fields:

        - vendor_id (required): Vendor ID

        - invoice_number (required): Invoice number

        - invoice_date (required): Invoice date

        - currency_id (optional): Currency ID

        - currency_rate (optional): Exchange rate

        - proration_strategy (optional): One of: cost_based, quantity_based, weight_based,
        manual

        - allocations (optional): Updated allocations — replaces existing allocations'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                vendor_id:
                  type: integer
                invoice_number:
                  type: string
                invoice_date:
                  type: string
                currency_id:
                  type: integer
                currency_rate:
                  type: integer
                proration_strategy:
                  type: string
                allocations:
                  type: array
                  items:
                    type: object
                    properties:
                      purchase_order_line_id:
                        type: integer
                      warehouse_transfer_line_id:
                        type: string
                        nullable: true
                      allocation_amount:
                        type: integer
              example:
                vendor_id: 3
                invoice_number: INV-20250420-REV
                invoice_date: '2025-04-20'
                currency_id: 1
                currency_rate: 1
                proration_strategy: quantity_based
                allocations:
                - purchase_order_line_id: 55
                  warehouse_transfer_line_id: null
                  allocation_amount: 300
      parameters:
      - name: inbound_shipment
        in: path
        schema:
          type: integer
        required: true
        example: '42'
        description: The inbound shipment ID.
      - name: bill
        in: path
        schema:
          type: integer
        required: true
        example: '7'
        description: The bill ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      invoice_number:
                        type: string
                      proration_strategy:
                        type: string
                      total_amount:
                        type: number
                  message:
                    type: string
                example:
                  data:
                    id: 7
                    invoice_number: INV-20250420-REV
                    proration_strategy: quantity_based
                    total_amount: 500.0
                  message: Bill updated successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: purchase-orders:write
      operationId: patch-api-inbound-shipments-inbound-shipment-bills-bill
    delete:
      tags:
      - Inbound Shipments
      summary: Delete Bill
      description: 'Deletes a bill attached to this inbound shipment. Cannot delete
        bills on a cancelled shipment.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: inbound_shipment
        in: path
        schema:
          type: integer
        required: true
        example: '42'
        description: The inbound shipment ID.
      - name: bill
        in: path
        schema:
          type: integer
        required: true
        example: '7'
        description: The bill ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Bill deleted successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:write
      operationId: delete-api-inbound-shipments-inbound-shipment-bills-bill
  /api/inbound-shipments/{inbound_shipment}/landed-cost-preview:
    get:
      tags:
      - Inbound Shipments
      summary: Landed Cost Preview
      description: 'Returns a per-PO-line aggregation of all landed cost allocations
        across every bill attached to this shipment. Useful for previewing total landed
        costs before closing.


        :::info[Required scope: `purchase-orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: inbound_shipment
        in: path
        schema:
          type: integer
        required: true
        example: '42'
        description: The inbound shipment ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        purchase_order_line_id:
                          type: integer
                        sku:
                          type: string
                        product_name:
                          type: string
                        total_landed_cost:
                          type: number
                example:
                  data:
                  - purchase_order_line_id: 55
                    sku: SKU-001
                    product_name: Widget A
                    total_landed_cost: 250.0
                  - purchase_order_line_id: 56
                    sku: SKU-002
                    product_name: Widget B
                    total_landed_cost: 250.0
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:read
      operationId: get-api-inbound-shipments-inbound-shipment-landed-cost-preview
  /api/inbound-shipment-receipts/{receipt}:
    get:
      tags:
      - Inbound Shipments
      summary: Get Inbound Shipment Receipt
      description: 'Returns full details for an inbound shipment receipt including
        the parent inbound shipment, supplier, destination warehouse, all distinct
        purchase orders represented across receipt lines, line items (with product
        + PO line context), and the linked accounting transaction.


        :::info[Required scope: `purchase-orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        A single receipt may span multiple purchase orders — the `purchase_orders`
        array lists every distinct PO referenced by its lines. Each line also carries
        its own `purchase_order` reference for per-line attribution.


        Authentication: Requires Bearer token.'
      parameters:
      - name: receipt
        in: path
        schema:
          type: integer
        required: true
        description: Inbound shipment receipt ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      received_at:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      notes:
                        type: string
                      fulfilled_by:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      inbound_shipment:
                        type: object
                        properties:
                          id:
                            type: integer
                          shipment_number:
                            type: string
                          reference:
                            type: string
                      purchase_orders:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            po_number:
                              type: string
                            purchase_order_date:
                              type: string
                            currency_code:
                              type: string
                            currency_rate:
                              type: number
                            is_tax_included:
                              type: boolean
                      supplier:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      destination_warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          display_name:
                            type: string
                      lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            quantity:
                              type: integer
                            total_cost:
                              type: number
                            purchase_order:
                              type: object
                              properties:
                                id:
                                  type: integer
                                po_number:
                                  type: string
                            purchase_order_line:
                              type: object
                              properties:
                                id:
                                  type: integer
                                quantity:
                                  type: integer
                                amount:
                                  type: number
                                discount_rate:
                                  type: integer
                                received_quantity:
                                  type: integer
                                description:
                                  type: string
                            product:
                              type: object
                              properties:
                                id:
                                  type: integer
                                sku:
                                  type: string
                                name:
                                  type: string
                                image_url:
                                  type: string
                      summary:
                        type: object
                        properties:
                          total_lines:
                            type: integer
                          total_units:
                            type: integer
                          total_purchase_orders:
                            type: integer
                  status:
                    type: string
                example:
                  data:
                    id: 1
                    received_at: '2024-04-15T14:00:00Z'
                    created_at: '2024-04-15T14:00:00Z'
                    updated_at: '2024-04-15T14:05:00Z'
                    notes: Received in good condition
                    fulfilled_by:
                      id: 5
                      name: John Smith
                    inbound_shipment:
                      id: 12
                      shipment_number: ISH-2024-0012
                      reference: ISH-2024-0012
                    purchase_orders:
                    - id: 20
                      po_number: PO-2024-0020
                      purchase_order_date: '2024-04-01'
                      currency_code: USD
                      currency_rate: 1.0
                      is_tax_included: false
                    - id: 21
                      po_number: PO-2024-0021
                      purchase_order_date: '2024-04-02'
                      currency_code: USD
                      currency_rate: 1.0
                      is_tax_included: false
                    supplier:
                      id: 3
                      name: Acme Supplies Co.
                    destination_warehouse:
                      id: 1
                      name: Main Warehouse
                      display_name: Main Warehouse
                    lines:
                    - id: 10
                      quantity: 100
                      total_cost: 1250.0
                      purchase_order:
                        id: 20
                        po_number: PO-2024-0020
                      purchase_order_line:
                        id: 50
                        quantity: 100
                        amount: 1250.0
                        discount_rate: 0
                        received_quantity: 100
                        description: Blue Widget
                      product:
                        id: 42
                        sku: WIDGET-001
                        name: Blue Widget
                        image_url: https://cdn.example.com/widget.jpg
                    summary:
                      total_lines: 1
                      total_units: 100
                      total_purchase_orders: 2
                  status: success
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No query results for model [App\Models\InboundShipmentReceipt]
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: purchase-orders:read
      operationId: get-api-inbound-shipment-receipts-receipt
    delete:
      tags:
      - Inbound Shipments
      summary: Delete Inbound Shipment Receipt
      description: 'Deletes an inbound shipment receipt and reverses the inventory
        movements it created. Because it removes the stock the receipt added, it behaves
        like a manual negative adjustment and rebalances any now-unbacked reservations
        to backorder.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        **Voiding hard-allocated labels (`void_confirmations`):** When this removal
        would consume stock that is hard-allocated to a fulfillment (a printed shipping
        label), include a `void_confirmations` array in the request body — one entry
        per fulfillment you authorize voiding: `{ "fulfillment_id": <int>, "attempt_void":
        true, "reason": <string|null> }`. Each confirmed label is voided first so
        the removal can proceed. Omit `void_confirmations` (or leave out a fulfillment
        that is in the way) and the request is rejected with 422 when hard-allocated
        stock blocks the operation. Call the matching delete-impact / reverse-impact
        preview endpoint first to see exactly which fulfillments block it.


        Authentication: Requires Bearer token.'
      parameters:
      - name: receipt
        in: path
        schema:
          type: integer
        required: true
        description: Inbound shipment receipt ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  status:
                    type: string
                example:
                  message: Inbound shipment receipt deleted successfully.
                  status: success
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 422 Protected Inventory Conflict
                  value:
                    message: Cannot take 100 units. Only 20 available after protecting
                      80 units allocated to submitted or acknowledged fulfillments.
                    conflict:
                      requested_quantity: 100
                      available_quantity: 20
                      protected_quantity: 80
                      conflicting_allocations:
                      - type: sales_order_fulfillment
                        id: 123
                        reference: SO-12345
                        quantity_allocated: 5
                        line_details:
                          sales_order_number: SO-12345
                          sales_order_line_id: 456
                          product_sku: ABC-123
                example-1:
                  summary: 422 Label Not Voidable
                  value:
                    message: 'Fulfillment #90142 can''t be voided (its label cannot
                      be voided), so this reduction isn''t allowed.'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:write
      operationId: delete-api-inbound-shipment-receipts-receipt
  /api/inbound-shipment-receipts/{receipt}/activity-log:
    get:
      tags:
      - Inbound Shipments
      summary: Get Purchase Receipt Activity Log
      description: 'Paginated activity log entries for an inbound shipment receipt.
        Supports search across causer name, properties JSON, and event; filterable
        by event, causer, and date range.


        :::info[Required scope: `purchase-orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: per_page
        in: query
        schema:
          type: integer
        description: 'Items per page (default: 15)'
        example: '15'
      - name: receipt
        in: path
        schema:
          type: integer
        required: true
        description: Inbound shipment receipt ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        description:
                          type: string
                        event:
                          type: string
                        subject_type:
                          type: string
                        subject_id:
                          type: integer
                        properties:
                          type: object
                          properties:
                            attributes:
                              type: object
                              properties:
                                received_at:
                                  type: string
                        causer_name:
                          type: string
                        created_at:
                          type: string
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 901
                    description: created
                    event: created
                    subject_type: InboundShipmentReceipt
                    subject_id: 1
                    properties:
                      attributes:
                        received_at: '2024-04-15T14:00:00Z'
                    causer_name: John Smith
                    created_at: '2024-04-15T14:00:00Z'
                  first_page_url: '...'
                  from: 1
                  last_page: 1
                  last_page_url: '...'
                  links: []
                  next_page_url: null
                  path: '...'
                  per_page: 15
                  prev_page_url: null
                  to: 1
                  total: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:read
      operationId: get-api-inbound-shipment-receipts-receipt-activity-log
  /api/inbound-shipment-receipts/{receipt}/fifo-layers:
    get:
      tags:
      - Inbound Shipments
      summary: Get FIFO Layers
      description: 'Paginated list of FIFO layers created by this inbound shipment
        receipt''s lines. Each layer is scoped to `link_type = InboundShipmentReceiptLine`
        and the receipt''s line IDs.


        :::info[Required scope: `purchase-orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: per_page
        in: query
        schema:
          type: integer
        description: Items per page
        example: '15'
      - name: receipt
        in: path
        schema:
          type: integer
        required: true
        description: Inbound shipment receipt ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        fifo_layer_date:
                          type: string
                        quantity:
                          type: integer
                        fulfilled_quantity:
                          type: integer
                        available_quantity:
                          type: integer
                        unit_cost:
                          type: number
                        total_cost:
                          type: number
                        product_id:
                          type: integer
                        product_sku:
                          type: string
                        product_name:
                          type: string
                        warehouse_id:
                          type: integer
                        warehouse_name:
                          type: string
                        source_type:
                          type: string
                        source_reference:
                          type: string
                        link_type:
                          type: string
                        link_id:
                          type: integer
                        parent_link_id:
                          type: integer
                        detail_link_id:
                          type: integer
                        condition:
                          type: string
                        created_at:
                          type: string
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 1001
                    fifo_layer_date: '2024-04-15'
                    quantity: 100
                    fulfilled_quantity: 0
                    available_quantity: 100
                    unit_cost: 12.5
                    total_cost: 1250.0
                    product_id: 42
                    product_sku: WIDGET-001
                    product_name: Blue Widget
                    warehouse_id: 1
                    warehouse_name: Main Warehouse
                    source_type: inbound_shipment_receipt
                    source_reference: ISR-1
                    link_type: App\Models\InboundShipmentReceiptLine
                    link_id: 10
                    parent_link_id: 20
                    detail_link_id: 1
                    condition: active
                    created_at: '2024-04-15T14:00:00Z'
                  first_page_url: '...'
                  from: 1
                  last_page: 1
                  last_page_url: '...'
                  links: []
                  next_page_url: null
                  path: '...'
                  per_page: 15
                  prev_page_url: null
                  to: 1
                  total: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:read
      operationId: get-api-inbound-shipment-receipts-receipt-fifo-layers
  /api/inbound-shipment-receipts/{receipt}/inventory-movements:
    get:
      tags:
      - Inbound Shipments
      summary: Get Inventory Movements
      description: 'Paginated inventory movements generated by this inbound shipment
        receipt''s lines. Includes per-movement FIFO layer reference and unit/total
        cost.


        :::info[Required scope: `purchase-orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: per_page
        in: query
        schema:
          type: integer
        description: Items per page
        example: '15'
      - name: receipt
        in: path
        schema:
          type: integer
        required: true
        description: Inbound shipment receipt ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        type:
                          type: string
                        inventory_status:
                          type: string
                        quantity:
                          type: integer
                        reference:
                          type: string
                        link_type:
                          type: string
                        link_id:
                          type: integer
                        parent_link_id:
                          type: integer
                        detail_link_id:
                          type: integer
                        product_id:
                          type: integer
                        product_sku:
                          type: string
                        product_name:
                          type: string
                        warehouse_id:
                          type: integer
                        warehouse_name:
                          type: string
                        unit_cost:
                          type: number
                        unit_cost_provisional:
                          type: boolean
                        total_cost:
                          type: number
                        layer:
                          type: object
                          properties:
                            name:
                              type: string
                            layer_type:
                              type: string
                            layer_id:
                              type: integer
                        inventory_movement_date:
                          type: string
                        created_at:
                          type: string
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 5500
                    type: purchase_receipt
                    inventory_status: active
                    quantity: 100
                    reference: ISR-1
                    link_type: App\Models\InboundShipmentReceiptLine
                    link_id: 10
                    parent_link_id: 20
                    detail_link_id: 1
                    product_id: 42
                    product_sku: WIDGET-001
                    product_name: Blue Widget
                    warehouse_id: 1
                    warehouse_name: Main Warehouse
                    unit_cost: 12.5
                    unit_cost_provisional: false
                    total_cost: 1250.0
                    layer:
                      name: 'FIFO Layer #1001'
                      layer_type: App\Models\FifoLayer
                      layer_id: 1001
                    inventory_movement_date: '2024-04-15'
                    created_at: '2024-04-15T14:00:00Z'
                  first_page_url: '...'
                  from: 1
                  last_page: 1
                  last_page_url: '...'
                  links: []
                  next_page_url: null
                  path: '...'
                  per_page: 15
                  prev_page_url: null
                  to: 1
                  total: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:read
      operationId: get-api-inbound-shipment-receipts-receipt-inventory-movements
  /api/inbound-shipment-receipts/{receipt}/generate-accounting-transaction:
    post:
      tags:
      - Inbound Shipments
      summary: Generate Accounting Transaction
      description: 'Generates (or regenerates) the accounting transaction entry for
        an inbound shipment receipt. Returns the created transaction with its nominal-code-tagged
        lines.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties: {}
              example: {}
      parameters:
      - name: receipt
        in: path
        schema:
          type: integer
        required: true
        description: Inbound shipment receipt ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      transaction_date:
                        type: string
                      reference:
                        type: string
                  message:
                    type: string
                  status:
                    type: string
                example:
                  data:
                    id: 88
                    transaction_date: '2024-04-15'
                    reference: ISR-1
                  message: Accounting transaction generated successfully.
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: purchase-orders:write
      operationId: post-api-inbound-shipment-receipts-receipt-generate-accounting-transaction
  /api/inbound-shipment-receipts/{receipt}/delete-impact:
    get:
      tags:
      - Inbound Shipments
      summary: Preview Inbound Shipment Receipt Delete Impact
      description: 'Read-only preview of the allocation-demotion impact of deleting
        this inbound shipment receipt. Because deleting it removes the stock it added,
        this behaves like a manual negative adjustment and returns one row per affected
        product: how much of the removed quantity is unallocated vs soft-allocated
        vs hard-allocated, plus every sales-order allocation and fulfillment (printed
        shipping label) the removal would disturb. Use it to decide which fulfillments
        to authorize voiding via `void_confirmations` on the deleting call. Nothing
        is mutated. A removal that only re-adds stock returns an empty `data` array.


        Authentication: Requires Bearer token.'
      parameters:
      - name: receipt
        in: path
        schema:
          type: integer
        required: true
        description: Inbound shipment receipt ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        product_id:
                          type: integer
                        product_sku:
                          type: string
                        product_name:
                          type: string
                        shortfall_quantity:
                          type: integer
                        unallocated_quantity:
                          type: integer
                        soft_allocated_quantity:
                          type: integer
                        hard_allocated_quantity:
                          type: integer
                        affected_allocations:
                          type: array
                          items:
                            type: object
                            properties:
                              allocation_id:
                                type: integer
                              allocation_type:
                                type: string
                              sales_order_id:
                                type: integer
                              order_number:
                                type: string
                              customer_name:
                                type: string
                              fulfillment_id:
                                type: string
                                nullable: true
                              carrier:
                                type: string
                                nullable: true
                              carrier_void_supported:
                                type: string
                                nullable: true
                              voidable_status:
                                type: string
                                nullable: true
                              voidable_detail:
                                type: string
                                nullable: true
                              quantity:
                                type: integer
                example:
                  data:
                  - product_id: 5567
                    product_sku: WIDGET-BLUE
                    product_name: Blue Widget
                    shortfall_quantity: 0
                    unallocated_quantity: 10
                    soft_allocated_quantity: 6
                    hard_allocated_quantity: 4
                    affected_allocations:
                    - allocation_id: 88201
                      allocation_type: soft
                      sales_order_id: 3120
                      order_number: SO-3120
                      customer_name: Acme Co.
                      fulfillment_id: null
                      carrier: null
                      carrier_void_supported: null
                      voidable_status: null
                      voidable_detail: null
                      quantity: 6
                    - allocation_id: 88205
                      allocation_type: hard
                      sales_order_id: 3125
                      order_number: SO-3125
                      customer_name: Beta LLC
                      fulfillment_id: 90142
                      carrier: ups
                      carrier_void_supported: true
                      voidable_status: voidable
                      voidable_detail: null
                      quantity: 4
                      allocation_ids:
                      - 88205
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-inbound-shipment-receipts-receipt-delete-impact
  /api/inbound-shipment-receipts/{receipt}/lines/{line}/quantity-preview:
    get:
      tags:
      - Inbound Shipments
      summary: Preview Receipt Line Quantity
      description: 'Read-only preview of the effect of changing a receipt line''s
        received quantity before saving. Returns how the change flows onto the inbound
        shipment line quantity and the purchase order line quantity (`implications`),
        the FIFO teardown/redistribution needed for a reduction (`inventory`), and
        - when the new quantity is LOWER than the current one - a `demotion_impact`
        list describing which order allocations the reduction would consume.


        :::info[Required scope: `purchase-orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Each row is one product whose stock the action would consume. `shortfall_quantity`
        is how much more than available the action removes (stock goes negative when
        above zero). `unallocated_quantity` / `soft_allocated_quantity` / `hard_allocated_quantity`
        split the consumed quantity into free / soft-reserved / hard-allocated (label-printed)
        units. `affected_allocations[]` lists the order allocations consumed, highest
        priority first: `allocation_type` is `soft` or `hard`, and for hard rows `fulfillment_id`/`carrier`
        identify the label while `carrier_void_supported` and `voidable_status` say
        whether it can be voided through the API.


        `demotion_impact` is empty for an increase or a no-op; only a reduction can
        strand an allocation. Use it to decide whether Update Receipt Line Quantity
        needs `void_confirmations`.


        Query parameters:

        - `quantity` (integer, required) - the proposed new received quantity.


        Authentication: Requires Bearer token.'
      parameters:
      - name: quantity
        in: query
        schema:
          type: integer
        description: Proposed new received quantity
        example: '8'
      - name: receipt
        in: path
        schema:
          type: integer
        required: true
        description: Inbound shipment receipt ID
        example: '1'
      - name: line
        in: path
        schema:
          type: integer
        required: true
        description: Receipt line ID
        example: '5012'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      receipt_type:
                        type: string
                      line_id:
                        type: integer
                      current_quantity:
                        type: integer
                      new_quantity:
                        type: integer
                      delta:
                        type: integer
                      requires_confirmation:
                        type: boolean
                      can_update:
                        type: boolean
                      implications:
                        type: object
                        properties:
                          shipment_quantity:
                            type: object
                            properties:
                              label:
                                type: string
                              current:
                                type: integer
                              after_if_updated:
                                type: integer
                              differs_after_edit:
                                type: boolean
                          order_quantity:
                            type: object
                            properties:
                              label:
                                type: string
                              current:
                                type: integer
                              after_if_updated:
                                type: integer
                              received_after_edit:
                                type: integer
                              differs_after_edit:
                                type: boolean
                      inventory:
                        type: object
                        properties:
                          fifo_layer:
                            type: object
                            properties:
                              id:
                                type: integer
                              product_id:
                                type: integer
                              warehouse_id:
                                type: integer
                              original_quantity:
                                type: integer
                              fulfilled_quantity:
                                type: integer
                              available_quantity:
                                type: integer
                          decrease_quantity:
                            type: integer
                          available_without_reassignment:
                            type: integer
                          usage_quantity_to_redistribute:
                            type: integer
                          requires_redistribution:
                            type: boolean
                          can_redistribute:
                            type: boolean
                          blocks_update:
                            type: boolean
                          alternative_available_quantity:
                            type: integer
                          alternative_shortage_quantity:
                            type: integer
                          movable_usage_quantity:
                            type: integer
                          movable_usage_shortage_quantity:
                            type: integer
                          usages:
                            type: array
                          alternative_layers:
                            type: array
                      demotion_impact:
                        type: array
                        items:
                          type: object
                          properties:
                            product_id:
                              type: integer
                            product_sku:
                              type: string
                            product_name:
                              type: string
                            shortfall_quantity:
                              type: integer
                            unallocated_quantity:
                              type: integer
                            soft_allocated_quantity:
                              type: integer
                            hard_allocated_quantity:
                              type: integer
                            affected_allocations:
                              type: array
                              items:
                                type: object
                                properties:
                                  allocation_id:
                                    type: integer
                                  allocation_type:
                                    type: string
                                  sales_order_id:
                                    type: integer
                                  order_number:
                                    type: string
                                  customer_name:
                                    type: string
                                  fulfillment_id:
                                    type: string
                                    nullable: true
                                  carrier:
                                    type: string
                                    nullable: true
                                  carrier_void_supported:
                                    type: string
                                    nullable: true
                                  voidable_status:
                                    type: string
                                    nullable: true
                                  voidable_detail:
                                    type: string
                                    nullable: true
                                  quantity:
                                    type: integer
                example:
                  data:
                    receipt_type: inbound_shipment
                    line_id: 5012
                    current_quantity: 12
                    new_quantity: 8
                    delta: -4
                    requires_confirmation: true
                    can_update: true
                    implications:
                      shipment_quantity:
                        label: Inbound shipment line quantity
                        current: 12
                        after_if_updated: 8
                        differs_after_edit: true
                      order_quantity:
                        label: Purchase order line quantity
                        current: 12
                        after_if_updated: 8
                        received_after_edit: 8
                        differs_after_edit: true
                    inventory:
                      fifo_layer:
                        id: 44120
                        product_id: 123
                        warehouse_id: 2
                        original_quantity: 12
                        fulfilled_quantity: 5
                        available_quantity: 7
                      decrease_quantity: 4
                      available_without_reassignment: 7
                      usage_quantity_to_redistribute: 0
                      requires_redistribution: false
                      can_redistribute: true
                      blocks_update: false
                      alternative_available_quantity: 0
                      alternative_shortage_quantity: 0
                      movable_usage_quantity: 0
                      movable_usage_shortage_quantity: 0
                      usages: []
                      alternative_layers: []
                    demotion_impact:
                    - product_id: 123
                      product_sku: WIDGET-001
                      product_name: Blue Widget 500ml
                      shortfall_quantity: 0
                      unallocated_quantity: 4
                      soft_allocated_quantity: 3
                      hard_allocated_quantity: 2
                      affected_allocations:
                      - allocation_id: 88213
                        allocation_type: soft
                        sales_order_id: 4521
                        order_number: SO-10442
                        customer_name: Acme Retail
                        fulfillment_id: null
                        carrier: null
                        carrier_void_supported: null
                        voidable_status: null
                        voidable_detail: null
                        quantity: 3
                      - allocation_id: 88240
                        allocation_type: hard
                        sales_order_id: 4530
                        order_number: SO-10450
                        customer_name: Beta Wholesale
                        fulfillment_id: 77120
                        carrier: ups
                        carrier_void_supported: true
                        voidable_status: voidable
                        voidable_detail: null
                        quantity: 2
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:read
      operationId: get-api-inbound-shipment-receipts-receipt-lines-line-quantity-preview
  /api/inbound-shipment-receipts/{receipt}/lines/{line}:
    patch:
      tags:
      - Inbound Shipments
      summary: Update Receipt Line Quantity
      description: 'Change a receipt line''s received quantity. An increase adds stock
        to the line''s FIFO layer; a reduction removes it. Reducing below the currently
        allocated quantity consumes order allocations - soft reservations are demoted
        to backorder, and hard-allocated (label-printed) units require voiding their
        labels first.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Confirmation flow: preview the change first (see Preview Receipt Line Quantity).
        If the change alters the shipment or order line quantity, or needs FIFO redistribution,
        the request returns 409 with the preview payload until you resubmit with `confirmed_implications`
        (and, when redistribution is needed, `redistribute_usages`) set to true.


        Body fields:

        - `quantity` (integer, required) - the new received quantity (>= 0).

        - `confirmed_implications` (boolean, optional) - acknowledge the shipment/order
        quantity changes.

        - `redistribute_usages` (boolean, optional) - authorize moving existing FIFO
        usages to other layers.

        - `update_shipment_quantity` (boolean, optional) - also adjust the inbound
        shipment line quantity.

        - `update_order_quantity` (boolean, optional) - also adjust the purchase order
        line quantity.


        Optional void confirmations (`void_confirmations`):

        This action consumes the stock reserved for it. When that stock is hard-allocated
        to a sales-order fulfillment whose shipping label is already printed, include
        one `void_confirmations` entry per fulfillment to authorize voiding that label
        and reclaiming its stock; omit it and the request fails with a 422 conflict
        listing the blocking fulfillments.

        - `void_confirmations` (array, optional)

        - `void_confirmations[].fulfillment_id` (integer, required) - the fulfillment
        whose label may be voided.

        - `void_confirmations[].attempt_void` (boolean, required) - true to void the
        label and consume its stock.

        - `void_confirmations[].reason` (string, optional) - free-text audit note
        for the void.


        422 (hard-allocation conflict): returned when the action would consume stock
        hard-allocated to a printed shipping label and no matching `void_confirmations`
        entry authorized voiding it. `conflict.requested_quantity` is what the action
        needs, `available_quantity` is what is free, `protected_quantity` is the hard-allocated
        + held amount, and `conflicting_allocations` lists the blocking fulfillments
        (`line_details.fulfillment_id`).


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                quantity:
                  type: integer
                confirmed_implications:
                  type: boolean
                redistribute_usages:
                  type: boolean
                update_shipment_quantity:
                  type: boolean
                update_order_quantity:
                  type: boolean
                void_confirmations:
                  type: array
                  items:
                    type: object
                    properties:
                      fulfillment_id:
                        type: integer
                      attempt_void:
                        type: boolean
                      reason:
                        type: string
              example:
                quantity: 8
                confirmed_implications: true
                redistribute_usages: false
                update_shipment_quantity: false
                update_order_quantity: false
                void_confirmations:
                - fulfillment_id: 77120
                  attempt_void: true
                  reason: Customer cancelled after the label was printed
      parameters:
      - name: receipt
        in: path
        schema:
          type: integer
        required: true
        description: Inbound shipment receipt ID
        example: '1'
      - name: line
        in: path
        schema:
          type: integer
        required: true
        description: Receipt line ID
        example: '5012'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      received_at:
                        type: string
                      notes:
                        type: string
                        nullable: true
                      inbound_shipment:
                        type: object
                        properties:
                          id:
                            type: integer
                          shipment_number:
                            type: string
                          reference:
                            type: string
                      supplier:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      destination_warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          display_name:
                            type: string
                      lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            quantity:
                              type: integer
                            total_cost:
                              type: integer
                            purchase_order_line:
                              type: object
                              properties:
                                id:
                                  type: integer
                                quantity:
                                  type: integer
                                received_quantity:
                                  type: integer
                            product:
                              type: object
                              properties:
                                id:
                                  type: integer
                                sku:
                                  type: string
                                name:
                                  type: string
                  message:
                    type: string
                example:
                  data:
                    id: 1
                    received_at: '2026-03-15T14:00:00Z'
                    notes: null
                    inbound_shipment:
                      id: 12
                      shipment_number: ISH-2026-0012
                      reference: ISH-2026-0012
                    supplier:
                      id: 3
                      name: Acme Supplies Co.
                    destination_warehouse:
                      id: 2
                      name: Main Warehouse
                      display_name: Main Warehouse
                    lines:
                    - id: 5012
                      quantity: 8
                      total_cost: 200
                      purchase_order_line:
                        id: 50
                        quantity: 12
                        received_quantity: 8
                      product:
                        id: 123
                        sku: WIDGET-001
                        name: Blue Widget 500ml
                  message: Receipt line quantity updated successfully.
        '409':
          description: Conflict
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      receipt_type:
                        type: string
                      line_id:
                        type: integer
                      current_quantity:
                        type: integer
                      new_quantity:
                        type: integer
                      delta:
                        type: integer
                      requires_confirmation:
                        type: boolean
                      can_update:
                        type: boolean
                      implications:
                        type: object
                        properties:
                          shipment_quantity:
                            type: object
                            properties:
                              label:
                                type: string
                              current:
                                type: integer
                              after_if_updated:
                                type: integer
                              differs_after_edit:
                                type: boolean
                          order_quantity:
                            type: object
                            properties:
                              label:
                                type: string
                              current:
                                type: integer
                              after_if_updated:
                                type: integer
                              received_after_edit:
                                type: integer
                              differs_after_edit:
                                type: boolean
                      inventory:
                        type: object
                        properties:
                          fifo_layer:
                            type: object
                            properties:
                              id:
                                type: integer
                              product_id:
                                type: integer
                              warehouse_id:
                                type: integer
                              original_quantity:
                                type: integer
                              fulfilled_quantity:
                                type: integer
                              available_quantity:
                                type: integer
                          decrease_quantity:
                            type: integer
                          available_without_reassignment:
                            type: integer
                          usage_quantity_to_redistribute:
                            type: integer
                          requires_redistribution:
                            type: boolean
                          can_redistribute:
                            type: boolean
                          blocks_update:
                            type: boolean
                          alternative_available_quantity:
                            type: integer
                          alternative_shortage_quantity:
                            type: integer
                          movable_usage_quantity:
                            type: integer
                          movable_usage_shortage_quantity:
                            type: integer
                          usages:
                            type: array
                          alternative_layers:
                            type: array
                      demotion_impact:
                        type: array
                        items:
                          type: object
                          properties:
                            product_id:
                              type: integer
                            product_sku:
                              type: string
                            product_name:
                              type: string
                            shortfall_quantity:
                              type: integer
                            unallocated_quantity:
                              type: integer
                            soft_allocated_quantity:
                              type: integer
                            hard_allocated_quantity:
                              type: integer
                            affected_allocations:
                              type: array
                              items:
                                type: object
                                properties:
                                  allocation_id:
                                    type: integer
                                  allocation_type:
                                    type: string
                                  sales_order_id:
                                    type: integer
                                  order_number:
                                    type: string
                                  customer_name:
                                    type: string
                                  fulfillment_id:
                                    type: string
                                    nullable: true
                                  carrier:
                                    type: string
                                    nullable: true
                                  carrier_void_supported:
                                    type: string
                                    nullable: true
                                  voidable_status:
                                    type: string
                                    nullable: true
                                  voidable_detail:
                                    type: string
                                    nullable: true
                                  quantity:
                                    type: integer
                example:
                  message: Confirm the receipt quantity implications before saving.
                  data:
                    receipt_type: inbound_shipment
                    line_id: 5012
                    current_quantity: 12
                    new_quantity: 8
                    delta: -4
                    requires_confirmation: true
                    can_update: true
                    implications:
                      shipment_quantity:
                        label: Inbound shipment line quantity
                        current: 12
                        after_if_updated: 8
                        differs_after_edit: true
                      order_quantity:
                        label: Purchase order line quantity
                        current: 12
                        after_if_updated: 8
                        received_after_edit: 8
                        differs_after_edit: true
                    inventory:
                      fifo_layer:
                        id: 44120
                        product_id: 123
                        warehouse_id: 2
                        original_quantity: 12
                        fulfilled_quantity: 5
                        available_quantity: 7
                      decrease_quantity: 4
                      available_without_reassignment: 7
                      usage_quantity_to_redistribute: 0
                      requires_redistribution: false
                      can_redistribute: true
                      blocks_update: false
                      alternative_available_quantity: 0
                      alternative_shortage_quantity: 0
                      movable_usage_quantity: 0
                      movable_usage_shortage_quantity: 0
                      usages: []
                      alternative_layers: []
                    demotion_impact:
                    - product_id: 123
                      product_sku: WIDGET-001
                      product_name: Blue Widget 500ml
                      shortfall_quantity: 0
                      unallocated_quantity: 4
                      soft_allocated_quantity: 3
                      hard_allocated_quantity: 2
                      affected_allocations:
                      - allocation_id: 88213
                        allocation_type: soft
                        sales_order_id: 4521
                        order_number: SO-10442
                        customer_name: Acme Retail
                        fulfillment_id: null
                        carrier: null
                        carrier_void_supported: null
                        voidable_status: null
                        voidable_detail: null
                        quantity: 3
                      - allocation_id: 88240
                        allocation_type: hard
                        sales_order_id: 4530
                        order_number: SO-10450
                        customer_name: Beta Wholesale
                        fulfillment_id: 77120
                        carrier: ups
                        carrier_void_supported: true
                        voidable_status: voidable
                        voidable_detail: null
                        quantity: 2
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  conflict:
                    type: object
                    properties:
                      requested_quantity:
                        type: integer
                      available_quantity:
                        type: integer
                      protected_quantity:
                        type: integer
                      conflicting_allocations:
                        type: array
                        items:
                          type: object
                          properties:
                            type:
                              type: string
                            id:
                              type: integer
                            reference:
                              type: string
                            quantity_allocated:
                              type: integer
                            line_details:
                              type: object
                              properties:
                                fulfillment_id:
                                  type: integer
                                fulfillment_status:
                                  type: string
                                tracking_number:
                                  type: string
                example:
                  message: Cannot decrease 5 units. Only 3 available after protecting
                    2 hard-allocated units and 0 active hold units.
                  conflict:
                    requested_quantity: 5
                    available_quantity: 3
                    protected_quantity: 2
                    conflicting_allocations:
                    - type: shipping_label
                      id: 88240
                      reference: SO-10450
                      quantity_allocated: 2
                      line_details:
                        fulfillment_id: 77120
                        fulfillment_status: label_purchased
                        tracking_number: 1Z999AA10123456784
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:write
      operationId: patch-api-inbound-shipment-receipts-receipt-lines-line
  /api/sales-orders/ocr/upload:
    post:
      tags:
      - Sales Order OCR
      summary: Upload Customer PO Document
      description: 'Upload a customer PO PDF to start the OCR extraction process.
        Returns the extraction ID and a tracked-job ID; the actual OCR work runs asynchronously
        via Azure Document Intelligence. Poll GET /sales-orders/ocr/{id} until status
        is ''pending_review'' (or ''failed'' / ''duplicate_detected'').


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Response 201 includes:

        - extraction_id

        - tracked_job_log_id (for the JobProgressTray)

        - status: ''processing'''
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                file:
                  type: string
                  description: 'Customer purchase order file (required, max 20 MB).
                    Accepts PDF and image scans: pdf, jpg, jpeg, png, tif, tiff, bmp,
                    webp.'
                  format: binary
                customer_id:
                  type: integer
                  description: Customer ID to pre-associate with the extraction (optional).
                    When provided, customer SKU mappings are used to resolve line
                    items automatically.
                  example: '1'
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: orders:write
      operationId: post-api-sales-orders-ocr-upload
  /api/sales-orders/ocr/{extraction_id}:
    get:
      tags:
      - Sales Order OCR
      summary: Get OCR Extraction
      description: 'Retrieve a single OCR extraction record by ID. Returns the extracted
        header (customer PO number, dates, customer match, totals), per-line items
        with quantities/prices/match status, and the current review status.


        :::info[Required scope: `orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Statuses: processing, pending_review, confirmed, failed, rejected, duplicate_detected


        Source-related fields:

        - `source` — `manual`, `email`, or `email_body` (new). `email_body` indicates
        the extraction came from email body text rather than a PDF attachment, processed
        via Azure OpenAI gpt-4o-mini.

        - `source_email_from`, `source_email_subject` — set when `source` is `email`
        or `email_body`.

        - `source_body_text`, `source_body_html` — set when `source` is `email_body`.
        The frontend renders these in a body preview pane instead of the PDF viewer.

        - `sales_order_id` — the linked sales order created from this extraction (set
        when `status` is `confirmed`). When the linked sales order is later deleted,
        the FK `nullOnDelete` clears this field, leaving the extraction in an "orphaned
        confirmed" state which the rescan/delete/clone-from/reclassify guards treat
        as unlocked (see those endpoints'' descriptions).

        - `sales_order` — eager-loaded summary `{ id, number, order_date, customer_po_number
        }` of the linked sales order, present when `sales_order_id` is set. The OCR
        review page uses it to render a click-through link to the created sales order''s
        detail page. Omitted from list responses where the relation is not loaded.

        - `clone_of_sales_order_id` — set when this extraction was cloned from a prior
        sales order (via the LLM `clone_last_order` flag, or manually via the Clone
        Lines from Sales Order endpoint).

        - `clone_of_sales_order` — eager-loaded summary `{ id, number, order_date,
        customer_po_number }` of the source order when `clone_of_sales_order_id` is
        set.


        **Header field normalization (added 2026-05-06):**

        The extractors store header keys with names that vary by source:

        - Azure Document Intelligence (PDF) returns `po_number` and `invoice_date`.

        - OpenAI (email body) returns `po_number` and `order_date`.


        The API response layers canonical UI keys on top of these so the frontend
        has stable field names to bind to:

        - `customer_po_number` — derived from `po_number` (or already-set canonical
        value).

        - `po_date` — derived from `order_date` → `invoice_date` (or already-set canonical
        value).

        - `deliver_by_date` — the customer-requested delivery date. The PDF flow stores
        it under `due_date` (Azure `DueDate` / the LLM header extractor maps `deliver_by_date`
        → `due_date`); the email-body flow emits `deliver_by_date` directly. The response
        bridges `due_date` → `deliver_by_date` so the UI always has the key.


        The original extractor keys are preserved alongside the canonical ones, so
        consumers that read `po_number` / `invoice_date` / `order_date` / `due_date`
        directly continue to work.


        **Per-PO ship-to address (added 2026-05-18):**

        The header includes `ship_to_address` — a nullable object `{ name, company,
        address1, address2, city, province, zip, country_code }` extracted from the
        customer PO''s "Ship To" / "Deliver To" block. A customer can specify a different
        shipping destination on each PO, so this is captured per-extraction. It is
        `null` when the PO states no separate shipping destination.'
      parameters:
      - name: extraction_id
        in: path
        schema:
          type: string
        required: true
        description: The extraction ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 OK — Customer PO PDF (Azure Document Intelligence)
                  value:
                    data:
                      id: 3
                      status: pending_review
                      sales_order_id: null
                      sales_order: null
                      source: manual
                      source_email_from: null
                      source_email_subject: null
                      source_body_text: null
                      source_body_html: null
                      clone_of_sales_order_id: null
                      file_url: https://sku2.test/api/sales-orders/ocr/3/pdf
                      page_count: 1
                      header:
                        invoice_number: null
                        invoice_date: '2026-04-27'
                        due_date: '2026-05-18'
                        customer_name: Las Cosas Kitchen Shoppe
                        vendor_name: A Bar Above
                        vendor_address: null
                        customer_address: null
                        ship_to_address:
                          name: APPLEBEES CORTLANDT MOHEGAN 251
                          company: DOHERTY APPLE NY STATEWIDE LLC
                          address1: 3127 EAST MAIN STREET
                          address2: null
                          city: MOHEGAN LAKE
                          province: NY
                          zip: '10547'
                          country_code: US
                        total_amount: 595.2
                        subtotal: 595.2
                        tax_amount: null
                        currency_code: USD
                        po_number: BAR42326
                        customer_po_number: BAR42326
                        po_date: '2026-04-27'
                        deliver_by_date: '2026-05-18'
                        matched_customer_id: 142
                        matched_customer_name: Stephen Young Group - LA
                      lines:
                      - id: 3f1b1c4e-3a76-4a2a-9f9b-2c1d8e6c0e21
                        raw_sku: JGR-BELL-GO
                        raw_description: Bell Jigger Gold
                        quantity: 6
                        unit_price: 10.5
                        unit_price_source: extracted
                        line_total: 63
                        confidence: 0.97
                        match_status: exact
                        matched_product_id: 4321
                        matched_product_name: Bell Jigger Gold
                        matched_product_sku: JGR-BELL-GO
                        catalog_price: 10.5
                        price_variance_pct: 0
                        customer_sku_mapping_id: null
                        saved_financial_line_type_id: null
                        resolved_from_history: false
                      unmatched_line_count: 0
                      azure_cost_usd: 0.001
                      error_message: null
                      created_at: '2026-05-06T14:22:11.000000Z'
                example-1:
                  summary: 200 OK — Email body extraction (OpenAI)
                  value:
                    data:
                      id: 9
                      status: pending_review
                      sales_order_id: null
                      sales_order: null
                      source: email_body
                      source_email_from: buyer@acme.com
                      source_email_subject: Repeat order — 5 widgets
                      source_body_text: Hi, please ship 5 of WIDGET-A. Thanks!
                      source_body_html: null
                      clone_of_sales_order_id: null
                      file_url: null
                      page_count: null
                      header:
                        po_number: EMAIL-PO-9
                        vendor_name: Acme Corp
                        order_date: '2026-05-01'
                        deliver_by_date: null
                        memo: null
                        customer_po_number: EMAIL-PO-9
                        po_date: '2026-05-01'
                        matched_customer_id: 88
                        matched_customer_name: Acme Corp
                      lines:
                      - id: 7c2f4b1a-8d1c-49aa-b4f3-1e2a9d6f0ac8
                        raw_sku: WIDGET-A
                        raw_description: Widget A
                        quantity: 5
                        unit_price: 12
                        unit_price_source: customer_tier
                        line_total: null
                        confidence: 0.95
                        match_status: exact
                        matched_product_id: 1011
                        matched_product_name: Widget A
                        matched_product_sku: WIDGET-A
                        catalog_price: 12
                        price_variance_pct: 0
                        customer_sku_mapping_id: null
                        saved_financial_line_type_id: null
                        resolved_from_history: false
                      unmatched_line_count: 0
                      azure_cost_usd: 0.000175
                      error_message: null
                      created_at: '2026-05-06T15:01:42.000000Z'
                example-2:
                  summary: 200 OK — Confirmed extraction (linked sales order)
                  value:
                    data:
                      id: 11
                      status: confirmed
                      sales_order_id: 412
                      sales_order:
                        id: 412
                        number: SO-2026-0412
                        order_date: '2026-05-18'
                        customer_po_number: 7005832658-30
                      source: manual
                      source_email_from: null
                      source_email_subject: null
                      source_body_text: null
                      source_body_html: null
                      clone_of_sales_order_id: null
                      file_url: https://sku2.test/api/sales-orders/ocr/11/pdf
                      page_count: 1
                      header:
                        po_number: 7005832658-30
                        customer_po_number: 7005832658-30
                        invoice_date: '2026-05-18'
                        po_date: '2026-05-18'
                        due_date: '2026-05-18'
                        deliver_by_date: '2026-05-18'
                        vendor_name: Edward Don & Company
                        ship_to_address:
                          name: APPLEBEES CORTLANDT MOHEGAN 251
                          company: DOHERTY APPLE NY STATEWIDE LLC
                          address1: 3127 EAST MAIN STREET
                          address2: null
                          city: MOHEGAN LAKE
                          province: NY
                          zip: '10547'
                          country_code: US
                        total_amount: 6.6
                        matched_customer_id: 142
                        matched_customer_name: A Bar Above
                      lines:
                      - id: a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d
                        raw_sku: OB-SHAKER-ACP-18-U
                        raw_description: CUP SHAKER 18 OZ BOSTON SS ANTIQUE CPR
                        quantity: 1
                        unit_price: 6.6
                        unit_price_source: extracted
                        line_total: 6.6
                        confidence: 0.98
                        match_status: exact
                        matched_product_id: 4321
                        matched_product_name: Unweighted 18oz shaker cup - Antique
                          Copper - Open Box
                        matched_product_sku: OB-SHAKER-ACP-18-U
                        catalog_price: 8.31
                        price_variance_pct: -20.6
                        customer_sku_mapping_id: null
                        saved_financial_line_type_id: null
                        resolved_from_history: false
                      unmatched_line_count: 0
                      azure_cost_usd: 0.001
                      error_message: null
                      created_at: '2026-05-18T13:40:02.000000Z'
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No query results for model [App\Models\SalesOrderOcrExtraction]
                    99999
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: orders:read
      operationId: get-api-sales-orders-ocr-extraction-id
    delete:
      tags:
      - Sales Order OCR
      summary: Delete OCR Extraction
      description: 'Delete an OCR extraction record and its associated uploaded PDF.
        Use this to discard an extraction that will not be converted to a sales order.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Returns 422 if the extraction is *locked confirmed* — i.e. `status=''confirmed''`
        AND `sales_order_id` is non-null. Orphaned confirmed extractions (linked sales
        order was deleted, `sales_order_id` is null via FK `nullOnDelete`) are treated
        as unlocked and *can* be deleted.'
      parameters:
      - name: extraction_id
        in: path
        schema:
          type: string
        required: true
        description: The extraction ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:write
      operationId: delete-api-sales-orders-ocr-extraction-id
  /api/sales-orders/ocr/{extraction_id}/pdf:
    get:
      tags:
      - Sales Order OCR
      summary: Stream Extraction PDF
      description: 'Stream the original uploaded PDF back to the client through the
        backend (avoids CORS issues when fetching from S3 directly). Returns Content-Type:
        application/pdf with inline disposition. 404 if the underlying S3 object is
        missing.


        :::info[Required scope: `orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: extraction_id
        in: path
        schema:
          type: string
        required: true
        description: The extraction ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:read
      operationId: get-api-sales-orders-ocr-extraction-id-pdf
  /api/sales-orders/ocr/{extraction_id}/create-order:
    post:
      tags:
      - Sales Order OCR
      summary: Create Sales Order from Extraction
      description: 'Create a sales order from a reviewed OCR extraction. The request
        body contains the confirmed/edited field values from the review UI.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        When save_sku_mappings is true, any resolved customer SKU-to-product mappings
        from the extraction lines are persisted to the customer''s SKU mapping table
        for future use.


        **ship_to_address (optional, nullable object):** the per-PO shipping destination
        extracted from the customer PO''s "Ship To" block. A customer can have a different
        ship-to address on each PO, so this is captured per-extraction rather than
        read from the customer''s default address. When present and non-empty, it
        is passed through to the API as the order''s `shipping_address`. Fields: `name`,
        `company`, `address1`, `address2`, `city`, `province` (all nullable, max 255),
        `zip` (nullable, max 50), `country_code` (nullable, max 10). Omit or send
        null when the PO states no separate shipping destination.


        Returns the newly created sales order id and number, and marks the extraction
        status as ''confirmed''.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                customer_id:
                  type: integer
                customer_po_number:
                  type: string
                order_date:
                  type: string
                deliver_by_date:
                  type: string
                sales_channel_id:
                  type: integer
                currency_id:
                  type: integer
                memo_for_customer:
                  type: string
                  nullable: true
                ship_to_address:
                  type: object
                  properties:
                    name:
                      type: string
                    company:
                      type: string
                    address1:
                      type: string
                    address2:
                      type: string
                      nullable: true
                    city:
                      type: string
                    province:
                      type: string
                    zip:
                      type: string
                    country_code:
                      type: string
                save_sku_mappings:
                  type: boolean
                lines:
                  type: array
                  items:
                    type: object
                    properties:
                      product_id:
                        type: integer
                      quantity:
                        type: integer
                      amount:
                        type: integer
                      description:
                        type: string
                      warehouse_id:
                        type: string
                        nullable: true
              example:
                customer_id: 1
                customer_po_number: PO-12345
                order_date: '2024-01-15'
                deliver_by_date: '2024-02-15'
                sales_channel_id: 1
                currency_id: 1
                memo_for_customer: null
                ship_to_address:
                  name: APPLEBEES CORTLANDT MOHEGAN 251
                  company: DOHERTY APPLE NY STATEWIDE LLC
                  address1: 3127 EAST MAIN STREET
                  address2: null
                  city: MOHEGAN LAKE
                  province: NY
                  zip: '10547'
                  country_code: US
                save_sku_mappings: true
                lines:
                - product_id: 1
                  quantity: 10
                  amount: 25
                  description: Widget
                  warehouse_id: null
      parameters:
      - name: extraction_id
        in: path
        schema:
          type: string
        required: true
        description: The extraction ID.
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      sales_order_number:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 4821
                    sales_order_number: SO-004821
                  message: Sales order created successfully.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Only extractions with status "pending_review" can be used
                    to create an order.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:write
      operationId: post-api-sales-orders-ocr-extraction-id-create-order
  /api/sales-orders/ocr/{extraction_id}/clone-from:
    post:
      tags:
      - Sales Order OCR
      summary: Clone Lines from Sales Order
      description: 'Clone confirmed lines from a prior sales order into this extraction''s
        lines_data.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Used when the extraction''s customer history (or LLM analysis on email-body
        extractions) suggests this PO is a repeat order — the reviewer can pull lines
        from a previous confirmed sales order in one click instead of editing line
        by line.


        Request body:

        - `sales_order_id` (required, integer) — the source sales order to clone from.
        Must belong to the same customer as the extraction (when extraction has a
        customer_id set).


        Behavior:

        - Replaces (or merges with) `lines_data` on the extraction with one entry
        per source order line.

        - Each cloned line records the matched product (sku, name, average cost) and
        a unit price computed as `amount / quantity`.

        - Lines whose product is archived or missing are still copied but flagged
        `match_status: unmatched` so the reviewer must reassign.

        - Sets `clone_of_sales_order_id` on the extraction so the UI can show the
        "cloned from" banner.


        Returns the updated SalesOrderOcrExtraction resource (with `cloneOfSalesOrder`
        eager-loaded).


        Errors:

        - 422 — Confirmed extractions cannot be modified (only when the extraction
        is *locked*: `status=''confirmed''` AND `sales_order_id` is non-null. Orphaned
        confirmed extractions — where the linked sales order was deleted and the FK
        `nullOnDelete` cleared `sales_order_id` — are treated as unlocked and *can*
        be re-cloned).

        - 422 — Source order belongs to a different customer than the extraction.

        - 404 — Source sales order not found.

        - 422 — Validation: `sales_order_id` is required and must exist in `sales_orders`.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                sales_order_id:
                  type: integer
              example:
                sales_order_id: 12345
      parameters:
      - name: extraction_id
        in: path
        schema:
          type: string
        required: true
        description: The extraction ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: orders:write
      operationId: post-api-sales-orders-ocr-extraction-id-clone-from
  /api/sales-orders/ocr/{extraction_id}/reclassify-as-supplier-invoice:
    post:
      tags:
      - Sales Order OCR
      summary: Reclassify as Supplier Invoice
      description: 'Reclassify a Customer PO OCR extraction as a Supplier Invoice.
        Used when an inbound email was routed to orders@ but the attached PDF is actually
        a supplier invoice.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Copies the file_path, header_data, lines_data, and source email metadata into
        a new PurchaseInvoiceOcrExtraction (status: pending_review). Marks the original
        SalesOrderOcrExtraction as ''rejected'' with an error_message that references
        the new extraction ID, preserving an audit trail.


        Returns 422 if the extraction is *locked confirmed* — i.e. `status=''confirmed''`
        AND `sales_order_id` is non-null. Orphaned confirmed extractions (linked sales
        order was deleted, `sales_order_id` is null) are treated as unlocked and *can*
        be reclassified.


        Response:

        ```json

        { "data": { "purchase_invoice_extraction_id": 42 } }

        ```


        The frontend should redirect to /purchases/invoices/ocr/{id} for the user
        to continue review.'
      requestBody:
        content: {}
      parameters:
      - name: extraction_id
        in: path
        schema:
          type: string
        required: true
        description: The extraction ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: orders:write
      operationId: post-api-sales-orders-ocr-extraction-id-reclassify-as-supplier-invoice
  /api/sales-orders/ocr/{extraction_id}/rescan:
    post:
      tags:
      - Sales Order OCR
      summary: Rescan Customer PO OCR
      description: "Re-run OCR extraction on an existing Customer PO record. Resets\
        \ status to 'processing', clears any prior error_message, and re-dispatches\
        \ the OCR job. Useful when the extraction failed initially (status='failed')\
        \ or when the matching/parsing logic has improved and the user wants to re-derive\
        \ the extracted data from the original PDF or email body.\n\n:::info[Required\
        \ scope: `orders:write`]\nGrant this scope to your token under [Settings →\
        \ Developer → Personal Access Tokens](https://app.sku.io/settings/api).\n\
        :::\n\nReturns 422 if:\n- Extraction is *locked confirmed* — i.e. `status='confirmed'`\
        \ AND `sales_order_id` is non-null (already used to create a sales order that\
        \ still exists — cannot be re-scanned). Orphaned confirmed extractions (linked\
        \ sales order deleted, `sales_order_id` null via FK `nullOnDelete`) are treated\
        \ as unlocked and *can* be re-scanned.\n- Both file_path and source_body_text\
        \ are null (no source content to re-scan)\n\nResponse 200:\n```json\n{\n \
        \ \"data\": {\n    \"extraction_id\": 7,\n    \"tracked_job_log_id\": 1234,\n\
        \    \"status\": \"processing\"\n  },\n  \"message\": \"Re-scan started\"\n\
        }\n```\n\nThe frontend subscribes to the returned tracked_job_log_id via the\
        \ global JobProgressTray (job name starts with 'Customer PO OCR:') and re-fetches\
        \ the extraction once the job completes."
      requestBody:
        content: {}
      parameters:
      - name: extraction_id
        in: path
        schema:
          type: string
        required: true
        description: The extraction ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: orders:write
      operationId: post-api-sales-orders-ocr-extraction-id-rescan
  /api/purchase-invoices/ocr/upload:
    post:
      tags:
      - Purchase Invoice OCR
      summary: Upload Supplier Invoice PDF
      description: "Upload a supplier invoice PDF to start the OCR extraction. Requires\
        \ Invoice OCR to be enabled in Settings → Invoice OCR (returns 422 if not\
        \ enabled).\n\n:::info[Required scope: `orders:write`]\nGrant this scope to\
        \ your token under [Settings → Developer → Personal Access Tokens](https://app.sku.io/settings/api).\n\
        :::\n\nResponse 201:\n```json\n{\n  \"data\": {\n    \"extraction_id\": 7,\n\
        \    \"tracked_job_log_id\": 1234,\n    \"status\": \"processing\"\n  },\n\
        \  \"message\": \"OCR processing started\"\n}\n```\n\nPoll GET /purchase-invoices/ocr/{id}\
        \ until status is 'pending_review' (or 'failed' / 'duplicate_detected')."
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                file:
                  type: string
                  description: 'Supplier invoice file (required, max 20 MB). Accepts
                    PDF and image scans: pdf, jpg, jpeg, png, tif, tiff, bmp, webp.'
                  format: binary
                supplier_id:
                  type: integer
                  description: Supplier ID to pre-associate with the extraction (optional).
                    Must exist in the suppliers table.
                  example: '1'
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: orders:write
      operationId: post-api-purchase-invoices-ocr-upload
  /api/purchase-invoices/ocr/{purchase_extraction_id}:
    get:
      tags:
      - Purchase Invoice OCR
      summary: Get Invoice Extraction
      description: "Retrieve a purchase invoice OCR extraction record. Returns extracted\
        \ header data merged with matched supplier and PO info, line items with per-line\
        \ product matches (5-tier match: supplier_sku → SKU → barcode → MPN → fuzzy\
        \ name), candidate purchase orders for the supplier (with attach-to-existing-invoice\
        \ metadata), error_message (if failed/duplicate), and inbound-email source\
        \ metadata.\n\n:::info[Required scope: `orders:read`]\nGrant this scope to\
        \ your token under [Settings → Developer → Personal Access Tokens](https://app.sku.io/settings/api).\n\
        :::\n\nExample 200 response:\n```json\n{\n  \"data\": {\n    \"id\": 7,\n\
        \    \"status\": \"pending_review\",\n    \"file_url\": \"https://sku2.test/api/purchase-invoices/ocr/7/pdf\"\
        ,\n    \"page_count\": 2,\n    \"header\": {\n      \"supplier_invoice_number\"\
        : \"INV-9988\",\n      \"invoice_date\": \"2026-04-20\",\n      \"due_date\"\
        : \"2026-05-20\",\n      \"subtotal\": 1250.00,\n      \"tax_amount\": 125.00,\n\
        \      \"total_amount\": 1375.00,\n      \"po_number\": \"PO-12345\",\n  \
        \    \"matched_supplier_id\": 12,\n      \"matched_supplier_name\": \"Acme\
        \ Supplies\",\n      \"matched_purchase_order_id\": 88,\n      \"matched_purchase_order_number\"\
        : \"PO-12345\"\n    },\n    \"is_matched_supplier\": true,\n    \"extracted_supplier_name\"\
        : \"Acme Supplies, Inc.\",\n    \"lines\": [\n      {\n        \"raw_sku\"\
        : \"WID-001\",\n        \"description\": \"Widget Type 1\",\n        \"quantity\"\
        : 50,\n        \"unit_price\": 25.00,\n        \"line_total\": 1250.00,\n\
        \        \"matched_product_id\": 4321,\n        \"matched_product_sku\": \"\
        WID-001\",\n        \"matched_product_name\": \"Widget Type 1 — Blue\"\n \
        \     }\n    ],\n    \"unmatched_line_count\": 0,\n    \"azure_cost_usd\"\
        : 0.0125,\n    \"error_message\": null,\n    \"source\": \"email\",\n    \"\
        source_email_from\": \"billing@acme.com\",\n    \"source_email_subject\":\
        \ \"Invoice INV-9988\",\n    \"supplier\": { \"id\": 12, \"name\": \"Acme\
        \ Supplies\" },\n    \"purchase_order\": {\n      \"id\": 88,\n      \"purchase_order_number\"\
        : \"PO-12345\",\n      \"purchase_order_date\": \"2026-04-15\"\n    },\n \
        \   \"candidate_purchase_orders\": [\n      {\n        \"id\": 88,\n     \
        \   \"purchase_order_number\": \"PO-12345\",\n        \"purchase_order_date\"\
        : \"2026-04-15\",\n        \"order_status\": \"closed\",\n        \"existing_invoice_id\"\
        : 211,\n        \"existing_invoice_number\": \"INV-9988\",\n        \"existing_invoice_has_document\"\
        : false,\n        \"can_attach_document\": true\n      }\n    ],\n    \"created_at\"\
        : \"2026-04-25T10:30:00.000000Z\"\n  }\n}\n```\n\n**Candidate purchase orders\
        \ behavior:** The backend includes both open POs for the matched supplier\
        \ AND a fallback lookup by PO number across all statuses (open/closed). When\
        \ a candidate PO has `can_attach_document: true`, the frontend should offer\
        \ the user the option to attach the OCR'd PDF to the existing invoice via\
        \ POST `/api/purchase-invoices/ocr/{extraction}/attach-to-invoice` instead\
        \ of creating a new invoice.\n\n**Existing-invoice fields (`existing_invoice_id`,\
        \ `existing_invoice_number`, `existing_invoice_has_document`, `can_attach_document`):**\
        \ These are populated ONLY when the OCR'd `supplier_invoice_number` matches\
        \ an existing invoice on that PO (case-insensitive, trimmed comparison). For\
        \ partial-invoice scenarios where a single PO has multiple invoices with different\
        \ supplier_invoice_numbers, the candidate PO returns `null` for these fields\
        \ when no invoice matches the OCR'd number — allowing a new invoice to be\
        \ created instead of triggering a false \"already invoiced\" warning."
      parameters:
      - name: purchase_extraction_id
        in: path
        schema:
          type: string
        required: true
        description: The purchase extraction ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:read
      operationId: get-api-purchase-invoices-ocr-purchase-extraction-id
    delete:
      tags:
      - Purchase Invoice OCR
      summary: Delete Extraction
      description: 'Delete a purchase invoice OCR extraction record and its associated
        PDF. Confirmed extractions cannot be deleted (returns 422).


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: purchase_extraction_id
        in: path
        schema:
          type: string
        required: true
        description: The purchase extraction ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:write
      operationId: delete-api-purchase-invoices-ocr-purchase-extraction-id
  /api/purchase-invoices/ocr/{purchase_extraction_id}/pdf:
    get:
      tags:
      - Purchase Invoice OCR
      summary: Stream Extraction PDF
      description: 'Stream the original supplier invoice PDF through the backend (avoids
        CORS when fetching from S3). Returns Content-Type: application/pdf, inline
        disposition. 404 if the underlying S3 object is missing.


        :::info[Required scope: `orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: purchase_extraction_id
        in: path
        schema:
          type: string
        required: true
        description: The purchase extraction ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:read
      operationId: get-api-purchase-invoices-ocr-purchase-extraction-id-pdf
  /api/purchase-invoices/ocr/{purchase_extraction_id}/create-invoice:
    post:
      tags:
      - Purchase Invoice OCR
      summary: Create Purchase Invoice from Extraction
      description: "Accept the reviewed/edited extraction data (header + lines + cost\
        \ lines) and create a PurchaseInvoice record, marking the extraction as 'confirmed'.\
        \ The extraction must be in `pending_review` or `duplicate_detected` status\
        \ (a duplicate-detected extraction is allowed because the user may confirm\
        \ it is not actually a duplicate and proceed to create a new invoice).\n\n\
        :::info[Required scope: `orders:write`]\nGrant this scope to your token under\
        \ [Settings → Developer → Personal Access Tokens](https://app.sku.io/settings/api).\n\
        :::\n\nThe payload supports two kinds of line items:\n- **`lines`** — product\
        \ line items, attached to PurchaseOrderLines on the target PO. Each may set\
        \ `purchase_order_line_id` to bind to a specific PO line, or `ignored: true`\
        \ to skip persisting (kept for audit but not invoiced).\n- **`cost_lines`**\
        \ — non-product COST-classified financial lines (freight, duty, handling).\
        \ These create FinancialLine records on the PurchaseInvoice keyed by a COST-classification\
        \ `financial_line_type_id`. `allocate_to_products` is always `true` for OCR-created\
        \ cost lines.\n\nAt least one of `lines` or `cost_lines` is required (`lines`\
        \ is `required_without:cost_lines`).\n\n**Request body fields:**\n| Field\
        \ | Type | Required | Notes |\n|-------|------|----------|-------|\n| purchase_order_id\
        \ | integer | yes | Must exist in `purchase_orders`. |\n| invoice_number |\
        \ string | yes | Max 255 chars. |\n| invoice_date | date | yes | |\n| due_date\
        \ | date | no | |\n| lines | array | required_without:cost_lines | Product\
        \ lines. |\n| lines[].description | string | no | |\n| lines[].qty | numeric\
        \ | yes | Negative values are accepted (e.g. PO-level discount rows surfaced\
        \ as standalone negative lines). The manager filters out `ignored: true` and\
        \ `match_status: discount_confirmation` lines before persisting. |\n| lines[].unit_price\
        \ | numeric | yes | Negative values are accepted (e.g. PO-level discount rows\
        \ surfaced as standalone negative lines). The manager filters out `ignored:\
        \ true` and `match_status: discount_confirmation` lines before persisting.\
        \ |\n| lines[].purchase_order_line_id | integer | no | Must exist in `purchase_order_lines`.\
        \ |\n| lines[].ignored | boolean | no | Skip persisting this line. |\n| cost_lines\
        \ | array | no | Non-product COST FinancialLines. |\n| cost_lines[].financial_line_type_id\
        \ | integer | yes (per cost line) | Must exist in `financial_line_types` and\
        \ be COST classification. |\n| cost_lines[].description | string | no | Max\
        \ 500 chars. |\n| cost_lines[].quantity | numeric | yes (per cost line) |\
        \ Min 0. |\n| cost_lines[].amount | numeric | yes (per cost line) | Min 0.\
        \ Per-line amount (not total). |\n| remember_mappings | boolean | no | When\
        \ `true`, upserts `(supplier_id, description) → financial_line_type_id` mappings\
        \ into `supplier_description_mappings` so future OCR imports auto-tag matching\
        \ descriptions as cost lines (Tier 0 match). |\n\n**Response 201:**\n```json\n\
        {\n  \"data\": {\n    \"purchase_invoice_id\": 312,\n    \"extraction_id\"\
        : 7\n  },\n  \"message\": \"Purchase invoice created from OCR extraction.\"\
        \n}\n```\n\n**Response 422 — wrong status (e.g. `confirmed` or `failed`):**\n\
        ```json\n{ \"message\": \"Only extractions pending review can be used to create\
        \ an invoice.\" }\n```\n\n**Response 422 — validation failure (no lines or\
        \ cost lines):**\n```json\n{\n  \"message\": \"The lines field is required\
        \ when cost lines is not present.\",\n  \"errors\": { \"lines\": [\"The lines\
        \ field is required when cost lines is not present.\"] }\n}\n```"
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                purchase_order_id:
                  type: integer
                invoice_number:
                  type: string
                invoice_date:
                  type: string
                due_date:
                  type: string
                lines:
                  type: array
                  items:
                    type: object
                    properties:
                      description:
                        type: string
                      qty:
                        type: integer
                      unit_price:
                        type: integer
                      purchase_order_line_id:
                        type: integer
                      ignored:
                        type: boolean
                cost_lines:
                  type: array
                  items:
                    type: object
                    properties:
                      financial_line_type_id:
                        type: integer
                      description:
                        type: string
                      quantity:
                        type: integer
                      amount:
                        type: integer
                remember_mappings:
                  type: boolean
              example:
                purchase_order_id: 88
                invoice_number: INV-9988
                invoice_date: '2026-04-20'
                due_date: '2026-05-20'
                lines:
                - description: Widget Type 1
                  qty: 50
                  unit_price: 25
                  purchase_order_line_id: 421
                  ignored: false
                cost_lines:
                - financial_line_type_id: 12
                  description: Freight Shipping
                  quantity: 1
                  amount: 25
                remember_mappings: true
      parameters:
      - name: purchase_extraction_id
        in: path
        schema:
          type: string
        required: true
        description: The purchase extraction ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: orders:write
      operationId: post-api-purchase-invoices-ocr-purchase-extraction-id-create-invoice
  /api/purchase-invoices/ocr/{purchase_extraction_id}/attach-to-invoice:
    post:
      tags:
      - Purchase Invoice OCR
      summary: Attach OCR Document to Existing Invoice
      description: "Attach the OCR'd PDF to an existing PurchaseInvoice that does\
        \ not yet have a document. Used when the OCR extraction's PO number matches\
        \ a PO that has already been invoiced — instead of creating a new invoice,\
        \ the user can retroactively attach the extracted PDF to the prior invoice\
        \ as the supporting document.\n\n:::info[Required scope: `orders:write`]\n\
        Grant this scope to your token under [Settings → Developer → Personal Access\
        \ Tokens](https://app.sku.io/settings/api).\n:::\n\nThis is the primary resolution\
        \ path for `duplicate_detected` extractions: the OCR detected the same supplier\
        \ + invoice number combination already exists, and the user wants to attach\
        \ the new PDF to that prior invoice.\n\nUploads the original PDF (still in\
        \ S3 from the upload step) as a PurchaseInvoiceAttachment, marks the extraction\
        \ as 'confirmed', and links the extraction to the target invoice.\n\n**Request\
        \ body fields:**\n| Field | Type | Required | Notes |\n|-------|------|----------|-------|\n\
        | purchase_invoice_id | integer | yes | Must exist in `purchase_invoices`.\
        \ The invoice's supplier_id must match the extraction's matched supplier and\
        \ the invoice must not already have an attachment. |\n\n**Allowed only when:**\n\
        - Extraction status is `pending_review` or `duplicate_detected`\n- Target\
        \ invoice's supplier matches the extraction's matched supplier\n- Target invoice\
        \ has no existing attachments (i.e. `can_attach_document: true` from the candidate_purchase_orders\
        \ block)\n\nResponse 201:\n```json\n{\n  \"data\": {\n    \"purchase_invoice_id\"\
        : 211,\n    \"extraction_id\": 7,\n    \"attachment_id\": 559\n  },\n  \"\
        message\": \"OCR document attached to existing invoice.\"\n}\n```\n\nResponse\
        \ 422 — wrong extraction status (e.g. `confirmed` or `failed`):\n```json\n\
        { \"message\": \"Only extractions pending review can be attached.\" }\n```\n\
        \nResponse 422 — supplier mismatch:\n```json\n{ \"message\": \"The selected\
        \ invoice's supplier does not match the extraction's matched supplier.\" }\n\
        ```\n\nResponse 422 — invoice already has a document:\n```json\n{ \"message\"\
        : \"The selected invoice already has an attached document.\" }\n```\n\nResponse\
        \ 404 — invoice not found (route model + findOrFail failure)."
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                purchase_invoice_id:
                  type: integer
              example:
                purchase_invoice_id: 211
      parameters:
      - name: purchase_extraction_id
        in: path
        schema:
          type: string
        required: true
        description: The purchase extraction ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: orders:write
      operationId: post-api-purchase-invoices-ocr-purchase-extraction-id-attach-to-invoice
  /api/purchase-invoices/ocr/{purchase_extraction_id}/rescan:
    post:
      tags:
      - Purchase Invoice OCR
      summary: Re-scan Extraction
      description: "Re-dispatch the OCR extraction job for an existing PurchaseInvoiceOcrExtraction.\
        \ Resets status to 'processing', clears any previous error_message, and re-queues\
        \ a background job against the original PDF in S3. Useful when Azure misread\
        \ the document (wrong supplier match, missing lines) and the user wants to\
        \ re-run extraction without re-uploading.\n\n:::info[Required scope: `orders:write`]\n\
        Grant this scope to your token under [Settings → Developer → Personal Access\
        \ Tokens](https://app.sku.io/settings/api).\n:::\n\nAllowed from any status\
        \ except 'confirmed' (a confirmed extraction has already produced a PurchaseInvoice\
        \ and is locked).\n\nResponse 200:\n```json\n{\n  \"data\": {\n    \"extraction_id\"\
        : 7,\n    \"tracked_job_log_id\": 1234,\n    \"status\": \"processing\"\n\
        \  },\n  \"message\": \"Re-scan started.\"\n}\n```\n\nResponse 422 — confirmed\
        \ extraction:\n```json\n{ \"message\": \"Confirmed extractions cannot be re-scanned.\"\
        \ }\n```\n\nResponse 422 — file no longer available:\n```json\n{ \"message\"\
        : \"Cannot re-scan — original file is no longer available.\" }\n```\n\nPoll\
        \ GET /purchase-invoices/ocr/{id} until status flips back to 'pending_review'\
        \ (or 'failed')."
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties: {}
              example: {}
      parameters:
      - name: purchase_extraction_id
        in: path
        schema:
          type: string
        required: true
        description: The purchase extraction ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: orders:write
      operationId: post-api-purchase-invoices-ocr-purchase-extraction-id-rescan
  /api/purchase-invoices/ocr/{purchase_extraction_id}/reclassify-as-customer-po:
    post:
      tags:
      - Purchase Invoice OCR
      summary: Reclassify as Customer PO
      description: "Reclassify a Supplier Invoice OCR extraction as a Customer PO.\
        \ Used when an inbound email was routed to invoices@ but the attached PDF\
        \ is actually a customer purchase order — the inverse of POST /api/sales-orders/ocr/{id}/reclassify-as-supplier-invoice.\n\
        \n:::info[Required scope: `orders:write`]\nGrant this scope to your token\
        \ under [Settings → Developer → Personal Access Tokens](https://app.sku.io/settings/api).\n\
        :::\n\nCopies the file_path, header_data, lines_data, and source email metadata\
        \ (source, source_email_from, source_email_subject, source_email_recipient)\
        \ into a new SalesOrderOcrExtraction (status: pending_review). Marks the original\
        \ PurchaseInvoiceOcrExtraction as 'rejected' with an error_message that references\
        \ the new extraction ID, preserving an audit trail.\n\nReturns 422 if the\
        \ extraction is in 'confirmed' status (confirmed extractions cannot be reclassified).\n\
        \nResponse 200:\n```json\n{\n  \"message\": \"Reclassified as customer PO.\"\
        ,\n  \"data\": { \"sales_order_extraction_id\": 42 }\n}\n```\n\nThe frontend\
        \ should redirect to /orders/sales-orders/ocr/{id} for the user to continue\
        \ review."
      requestBody:
        content: {}
      parameters:
      - name: purchase_extraction_id
        in: path
        schema:
          type: string
        required: true
        description: The purchase extraction ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: orders:write
      operationId: post-api-purchase-invoices-ocr-purchase-extraction-id-reclassify-as-customer-po
  /api/purchase-invoices/ocr/{purchase_extraction_id}/reclassify-as-credit:
    post:
      tags:
      - Purchase Invoice OCR
      summary: Reclassify as Vendor Credit
      description: 'Reclassify a Supplier Invoice OCR extraction as a Vendor Credit.
        Used when a document landed in the supplier-invoice queue but is actually
        a credit memo — the inverse of POST /api/vendor-credits/ocr/{id}/reclassify-as-invoice.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Behavior:

        - Copies the PDF to a new S3 key under ocr/vendor-credits/ (the original file
        is left in place for the rejected record''s audit trail)

        - Creates a new VendorCreditOcrExtraction carrying over supplier_id, source,
        source email metadata (source_email_from, source_email_forwarded_from, source_email_subject,
        source_email_recipient, source_message_id), and the stored Azure raw_response

        - Marks the original PurchaseInvoiceOcrExtraction as ''rejected'' with an
        error_message referencing the new extraction ID

        - If a stored Azure raw_response exists, the vendor credit pipeline re-processes
        it synchronously (no new Azure call, no extra cost). Otherwise a Scan Credit
        Memo job is dispatched to re-analyze the PDF.


        Only extractions in pending_review, duplicate_detected, or failed status can
        be reclassified.


        Errors:

        - 422 if the extraction is in ''confirmed'' status

        - 422 if the extraction status is not reclassifiable, or the original file
        is no longer available


        The frontend should direct the user to the vendor credit OCR review page for
        the returned vendor_credit_extraction_id.'
      requestBody:
        content: {}
      parameters:
      - name: purchase_extraction_id
        in: path
        schema:
          type: string
        required: true
        description: The purchase extraction ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      vendor_credit_extraction_id:
                        type: integer
                example:
                  message: Reclassified as vendor credit. Review it in the vendor
                    credit OCR queue.
                  data:
                    vendor_credit_extraction_id: 57
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Only extractions pending review can be reclassified.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:write
      operationId: post-api-purchase-invoices-ocr-purchase-extraction-id-reclassify-as-credit
  /api/purchase-invoices/{purchaseInvoice}/attachments/{attachment}/ocr:
    post:
      tags:
      - Purchase Invoice OCR
      summary: Scan Invoice Attachment
      description: 'Start an OCR scan of a purchase invoice attachment. No request
        body.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        **Asynchronous** — this queues a background scan and returns immediately.
        The attachment''s `ocr_status` moves through `processing` and finishes as
        `completed` (with `ocr_processed_at` set) or `failed` (with `ocr_error_message`).
        Poll **Get Attachment OCR Extraction** or **List Purchase Invoice Attachments**
        to track progress. Scanning does not modify the invoice itself — use **Apply
        OCR Extraction to Invoice** to accept the results.


        The scan extracts invoice header fields and line items from the document and
        matches them against the linked purchase order''s product and cost lines.


        Requirements and errors:

        - Invoice OCR must be enabled in Settings, otherwise 422.

        - Only PDF and image (JPEG/PNG) attachments can be scanned — 422 for other
        types.

        - Archived invoices return 422.

        - A scan already in progress for the attachment returns 409.


        Requires the `purchase-orders:write` token scope.'
      requestBody:
        content: {}
      parameters:
      - name: purchaseInvoice
        in: path
        schema:
          type: integer
        required: true
        description: Purchase invoice ID
        example: '123'
      - name: attachment
        in: path
        schema:
          type: integer
        required: true
        description: Attachment ID
        example: '45'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                      attachment_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 812
                    attachment_id: 45
                  message: OCR processing started
        '409':
          description: Conflict
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: OCR is already in progress for this attachment.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Invoice OCR is not enabled. Please configure it in Settings
                    → Invoice OCR.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:write
      operationId: post-api-purchase-invoices-purchaseinvoice-attachments-attachment-ocr
    get:
      tags:
      - Purchase Invoice OCR
      summary: Get Attachment OCR Extraction
      description: 'Get the latest OCR extraction result for an invoice attachment.
        Read-only — never triggers a scan.


        :::info[Required scope: `purchase-orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Returns `"data": null` when the attachment has not been scanned yet (or the
        first scan is still running). Re-scanning keeps history; only the newest extraction
        is returned.


        The extraction contains:

        - `header` — extracted invoice fields, each as `{value, confidence}` (invoice_number,
        invoice_date, due_date, vendor_name, total_amount, subtotal, tax_amount, currency_code,
        po_number, addresses).

        - `extracted_lines` — document lines matched to purchase order product lines
        (`matched_po_line_id`) or cost lines (`matched_financial_line_id`), with `match_confidence`
        of `high`, `medium`, `low`, or `none`, plus unit price variance versus the
        PO.

        - `unmatched_lines` — lines that could not be matched; `ignored` reflects
        choices saved via Apply OCR Extraction to Invoice.


        Returns 404 if the attachment does not belong to the given invoice. Requires
        the `purchase-orders:read` token scope.'
      parameters:
      - name: purchaseInvoice
        in: path
        schema:
          type: integer
        required: true
        description: Purchase invoice ID
        example: '123'
      - name: attachment
        in: path
        schema:
          type: integer
        required: true
        description: Attachment ID
        example: '45'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 OK
                  value:
                    data:
                      id: 17
                      attachment_id: 45
                      provider: azure_document_intelligence
                      confidence_score: 0.94
                      header:
                        invoice_number:
                          value: INV-20441
                          confidence: 0.98
                        invoice_date:
                          value: '2026-06-28'
                          confidence: 0.97
                        due_date:
                          value: '2026-07-28'
                          confidence: 0.95
                        vendor_name:
                          value: Shenzhen Widget Co.
                          confidence: 0.96
                        customer_name:
                          value: Acme Retail LLC
                          confidence: 0.91
                        total_amount:
                          value: 12450
                          confidence: 0.99
                        subtotal:
                          value: 11840
                          confidence: 0.98
                        tax_amount:
                          value: 0
                          confidence: 0.97
                        currency_code:
                          value: USD
                          confidence: 0.99
                        po_number:
                          value: PO-1088
                          confidence: 0.93
                      extracted_lines:
                      - product_code: WDG-100
                        description: Widget 100-pack WDG-100
                        quantity: 500
                        unit_price: 22.5
                        line_total: 11250
                        confidence: 0.97
                        matched_po_line_id: 3311
                        matched_financial_line_id: null
                        matched_product_id: 902
                        matched_po_line_description: Widget 100-pack
                        matched_po_line_unit_price: 22
                        matched_po_line_quantity: 500
                        match_confidence: high
                        price_variance: 0.5
                        price_variance_pct: 2.27
                      - product_code: null
                        description: Shipping Cost
                        quantity: null
                        unit_price: null
                        line_total: 610
                        confidence: null
                        matched_po_line_id: null
                        matched_financial_line_id: 74
                        matched_product_id: null
                        matched_po_line_description: Shipping
                        matched_po_line_unit_price: 610
                        matched_po_line_quantity: 1
                        match_confidence: high
                        price_variance: null
                        price_variance_pct: null
                      unmatched_lines:
                      - product_code: null
                        description: Fuel surcharge
                        quantity: null
                        unit_price: null
                        line_total: 45
                        confidence: 0.88
                        matched_po_line_id: null
                        matched_financial_line_id: null
                        matched_product_id: null
                        match_confidence: none
                        ignored: true
                      created_at: '2026-07-01T14:25:01.000000Z'
                example-1:
                  summary: 200 OK (not scanned yet)
                  value:
                    data: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:read
      operationId: get-api-purchase-invoices-purchaseinvoice-attachments-attachment-ocr
  /api/purchase-invoices/{purchaseInvoice}/ocr-apply:
    post:
      tags:
      - Purchase Invoice OCR
      summary: Apply OCR Extraction to Invoice
      description: 'Apply reviewed OCR extraction results to a purchase invoice. Synchronous
        — the invoice is updated immediately.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Body fields:

        - `extraction_id` (integer, optional) — the extraction whose unmatched-line
        decisions should be saved.

        - `header.supplier_invoice_number` (string, optional, max 255) and `header.purchase_invoice_date`
        (date, optional) — update the invoice header. Null values are ignored (fields
        cannot be blanked here).

        - `lines` (array, required, min 1) — the resulting invoice lines. Each line
        needs `quantity_invoiced` (numeric, required, min 0), optional `unit_price`
        (numeric, min 0), and either `purchase_order_line_id` (existing PO line) or
        `financial_line_id` (existing cost line).

        - `unmatched_lines` (array, optional) — snapshot of unmatched document lines;
        set `ignored: true` on lines to exclude. Saved onto the extraction for future
        reads.


        **Line replacement semantics:** entries with `purchase_order_line_id` fully
        sync the invoice''s product lines — invoice lines whose PO line is not in
        the payload are **deleted**, new ones are created, and existing ones are updated.
        Entries with `financial_line_id` update the invoice''s cost lines, or copy
        the PO''s planned cost line onto the invoice if not present (the PO''s own
        line is never modified).


        After applying, the invoice''s approval status is re-evaluated: price or quantity
        variances against the PO (or invoicing more than was received) set `pending_approval`;
        otherwise `auto_approved`.


        Archived invoices return 422. Requires the `purchase-orders:write` token scope.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                extraction_id:
                  type: integer
                header:
                  type: object
                  properties:
                    supplier_invoice_number:
                      type: string
                    purchase_invoice_date:
                      type: string
                lines:
                  type: array
                  items:
                    type: object
                    properties:
                      purchase_order_line_id:
                        type: integer
                      quantity_invoiced:
                        type: integer
                      unit_price:
                        type: number
                unmatched_lines:
                  type: array
                  items:
                    type: object
                    properties:
                      description:
                        type: string
                      line_total:
                        type: integer
                      ignored:
                        type: boolean
              example:
                extraction_id: 17
                header:
                  supplier_invoice_number: INV-20441
                  purchase_invoice_date: '2026-06-28'
                lines:
                - purchase_order_line_id: 3311
                  quantity_invoiced: 500
                  unit_price: 22.5
                - financial_line_id: 74
                  quantity_invoiced: 1
                  unit_price: 610
                unmatched_lines:
                - description: Fuel surcharge
                  line_total: 45
                  ignored: true
      parameters:
      - name: purchaseInvoice
        in: path
        schema:
          type: integer
        required: true
        description: Purchase invoice ID
        example: '123'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      approval_status:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    approval_status: pending_approval
                  message: Invoice lines updated from OCR extraction.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      lines:
                        type: array
                        items:
                          type: string
                example:
                  message: At least one invoice line is required.
                  errors:
                    lines:
                    - At least one invoice line is required.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:write
      operationId: post-api-purchase-invoices-purchaseinvoice-ocr-apply
  /api/landed-cost-invoices/ocr:
    get:
      tags:
      - Landed Cost Invoice OCR
      summary: List Extractions (Inbox)
      description: 'List landed cost invoice OCR extractions for the inbox queue.
        Requires Bearer token. Returns a paginated `LengthAwarePaginator` of landed
        cost invoice OCR extraction object items. All filters are optional. Useful
        for the OCR Inbox page that surfaces freight/customs/brokerage/insurance invoices
        awaiting review.


        :::info[Required scope: `purchase-orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        status:
                          type: string
                        file_url:
                          type: string
                        file_name:
                          type: string
                        page_count:
                          type: integer
                        header:
                          type: object
                          properties:
                            vendor_name:
                              type: object
                              properties:
                                value:
                                  type: string
                                confidence:
                                  type: number
                            invoice_number:
                              type: object
                              properties:
                                value:
                                  type: string
                                confidence:
                                  type: number
                            invoice_date:
                              type: object
                              properties:
                                value:
                                  type: string
                                confidence:
                                  type: number
                            currency_code:
                              type: object
                              properties:
                                value:
                                  type: string
                                confidence:
                                  type: number
                            currency_rate:
                              type: integer
                            total_amount:
                              type: object
                              properties:
                                value:
                                  type: number
                                confidence:
                                  type: number
                            matched_supplier_id:
                              type: integer
                            matched_supplier_name:
                              type: string
                        is_matched_supplier:
                          type: boolean
                        extracted_supplier_name:
                          type: string
                        lines:
                          type: array
                          items:
                            type: object
                            properties:
                              description:
                                type: string
                              quantity:
                                type: integer
                              unit_price:
                                type: integer
                              line_total:
                                type: integer
                              matched_cost_category_id:
                                type: integer
                              matched_cost_category_name:
                                type: string
                              match_tier:
                                type: string
                              ignored:
                                type: boolean
                        unmatched_line_count:
                          type: integer
                        candidate_targets:
                          type: array
                          items:
                            type: object
                            properties:
                              target_type:
                                type: string
                              target_id:
                                type: integer
                              reference:
                                type: string
                              reason:
                                type: string
                        working_state:
                          type: string
                          nullable: true
                        prebind_target_type:
                          type: string
                          nullable: true
                        prebind_target_id:
                          type: string
                          nullable: true
                        azure_cost_usd:
                          type: number
                        error_message:
                          type: string
                          nullable: true
                        source:
                          type: string
                        source_email_from:
                          type: string
                        source_email_subject:
                          type: string
                        tracked_job_log_id:
                          type: integer
                        confirmed_at:
                          type: string
                          nullable: true
                        confirmed_by_user_id:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - id: 18
                    status: pending_review
                    file_url: https://sku2.test/api/landed-cost-invoices/ocr/18/pdf
                    file_name: DHL-Invoice-INV-44219.pdf
                    page_count: 2
                    header:
                      vendor_name:
                        value: DHL Express
                        confidence: 0.94
                      invoice_number:
                        value: INV-44219
                        confidence: 0.91
                      invoice_date:
                        value: '2026-04-12'
                        confidence: 0.88
                      currency_code:
                        value: USD
                        confidence: 0.97
                      currency_rate: 1
                      total_amount:
                        value: 1850.75
                        confidence: 0.93
                      matched_supplier_id: 12
                      matched_supplier_name: DHL Express
                    is_matched_supplier: true
                    extracted_supplier_name: DHL Express
                    lines:
                    - description: Freight Charges
                      quantity: 1
                      unit_price: 1500
                      line_total: 1500
                      matched_cost_category_id: 4
                      matched_cost_category_name: Freight
                      match_tier: exact_name
                      ignored: false
                    - description: Fuel Surcharge
                      quantity: 1
                      unit_price: 350.75
                      line_total: 350.75
                      matched_cost_category_id: 4
                      matched_cost_category_name: Freight
                      match_tier: keyword
                      ignored: false
                    unmatched_line_count: 0
                    candidate_targets:
                    - target_type: inbound_shipment
                      target_id: 142
                      reference: IS-00142
                      reason: prebind
                    working_state: null
                    prebind_target_type: null
                    prebind_target_id: null
                    azure_cost_usd: 0.0125
                    error_message: null
                    source: email
                    source_email_from: billing@dhl.com
                    source_email_subject: DHL Invoice INV-44219
                    tracked_job_log_id: 9221
                    confirmed_at: null
                    confirmed_by_user_id: null
                    created_at: '2026-05-01T08:14:00.000000Z'
                    updated_at: '2026-05-01T08:14:00.000000Z'
                  current_page: 1
                  last_page: 3
                  per_page: 20
                  total: 47
                  from: 1
                  to: 20
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: purchase-orders:read
      operationId: get-api-landed-cost-invoices-ocr
  /api/landed-cost-invoices/ocr/upload:
    post:
      tags:
      - Landed Cost Invoice OCR
      summary: Upload Landed Cost Invoice PDF
      description: "Upload a landed cost invoice PDF to start OCR extraction. Requires\
        \ Invoice OCR to be enabled in Settings → Invoice OCR (returns 422 if not\
        \ enabled).\n\n:::info[Required scope: `purchase-orders:write`]\nGrant this\
        \ scope to your token under [Settings → Developer → Personal Access Tokens](https://app.sku.io/settings/api).\n\
        :::\n\nAsync — returns immediately with a `tracked_job_log_id` for progress\
        \ tracking via the tracked job log endpoints. Poll `GET /landed-cost-invoices/ocr/{id}`\
        \ until status is `pending_review` (or `failed` / `duplicate_detected`).\n\
        \nResponse 201:\n```json\n{\n  \"data\": {\n    \"extraction_id\": 18,\n \
        \   \"tracked_job_log_id\": 9221,\n    \"status\": \"processing\"\n  },\n\
        \  \"message\": \"OCR processing started.\"\n}\n```\n\nResponse 422 (OCR disabled):\n\
        ```json\n{ \"message\": \"Landed Cost Invoice OCR is not enabled. Please configure\
        \ it in Settings → Invoice OCR.\" }\n```"
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                file:
                  type: string
                  description: 'Landed cost invoice file (required, max 20 MB). Accepts
                    PDF and image scans: pdf, jpg, jpeg, png, tif, tiff, bmp, webp.
                    Examples: freight, customs, brokerage, insurance, duty.'
                  format: binary
                supplier_id:
                  type: integer
                  description: Optional. Pre-associate the extraction with a known
                    supplier (must exist in suppliers). If omitted, the OCR pipeline
                    attempts to fuzzy-match the extracted vendor_name against existing
                    suppliers.
                  example: '12'
                prebind_target_type:
                  type: string
                  description: 'Optional. One of: inbound_shipment, purchase_order,
                    warehouse_transfer. When set, the resulting extraction is pre-bound
                    to a specific target so it appears as a candidate during apply.'
                  example: inbound_shipment
                prebind_target_id:
                  type: integer
                  description: Optional. ID of the prebind target. Required when prebind_target_type
                    is set.
                  example: '142'
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: purchase-orders:write
      operationId: post-api-landed-cost-invoices-ocr-upload
  /api/landed-cost-invoices/ocr/{landed_cost_extraction_id}:
    get:
      tags:
      - Landed Cost Invoice OCR
      summary: Get Extraction
      description: "Retrieve a landed cost invoice OCR extraction record. Eager-loads\
        \ the matched supplier and any extraction→bill pivots created during apply.\
        \ Returns extracted header data merged with matched supplier info, line items\
        \ with per-line cost-category matches (6-tier match: mapped → exact_name →\
        \ name_substring → keyword → fuzzy_name → fuzzy_mapped → unmatched), candidate\
        \ targets (inbound shipments / POs / warehouse transfers that fit the supplier\
        \ + ETA window), and inbound-email source metadata.\n\n:::info[Required scope:\
        \ `purchase-orders:read`]\nGrant this scope to your token under [Settings\
        \ → Developer → Personal Access Tokens](https://app.sku.io/settings/api).\n\
        :::\n\nExample 200 response:\n```json\n{\n  \"data\": {\n    \"id\": 18,\n\
        \    \"status\": \"pending_review\",\n    \"file_url\": \"https://sku2.test/api/landed-cost-invoices/ocr/18/pdf\"\
        ,\n    \"file_name\": \"DHL-Invoice-INV-44219.pdf\",\n    \"page_count\":\
        \ 2,\n    \"header\": {\n      \"vendor_name\": {\"value\": \"DHL Express\"\
        , \"confidence\": 0.94},\n      \"invoice_number\": {\"value\": \"INV-44219\"\
        , \"confidence\": 0.91},\n      \"invoice_date\": {\"value\": \"2026-04-12\"\
        , \"confidence\": 0.88},\n      \"currency_code\": {\"value\": \"USD\", \"\
        confidence\": 0.97},\n      \"currency_rate\": 1.0,\n      \"total_amount\"\
        : {\"value\": 1850.75, \"confidence\": 0.93},\n      \"matched_supplier_id\"\
        : 12,\n      \"matched_supplier_name\": \"DHL Express\"\n    },\n    \"is_matched_supplier\"\
        : true,\n    \"extracted_supplier_name\": \"DHL Express\",\n    \"lines\"\
        : [\n      {\n        \"description\": \"Freight Charges\",\n        \"quantity\"\
        : 1,\n        \"unit_price\": 1500.00,\n        \"line_total\": 1500.00,\n\
        \        \"matched_cost_category_id\": 4,\n        \"matched_cost_category_name\"\
        : \"Freight\",\n        \"match_tier\": \"exact_name\",\n        \"ignored\"\
        : false\n      }\n    ],\n    \"unmatched_line_count\": 0,\n    \"candidate_targets\"\
        : [\n      {\n        \"target_type\": \"inbound_shipment\",\n        \"target_id\"\
        : 142,\n        \"reference\": \"IS-00142\",\n        \"eta\": \"2026-04-15\"\
        ,\n        \"reason\": \"supplier_eta_close\"\n      },\n      {\n       \
        \ \"target_type\": \"purchase_order\",\n        \"target_id\": 88,\n     \
        \   \"reference\": \"PO-12345\",\n        \"reason\": \"supplier_match\"\n\
        \      }\n    ],\n    \"working_state\": null,\n    \"prebind_target_type\"\
        : null,\n    \"prebind_target_id\": null,\n    \"azure_cost_usd\": 0.0125,\n\
        \    \"error_message\": null,\n    \"source\": \"email\",\n    \"source_email_from\"\
        : \"billing@dhl.com\",\n    \"source_email_subject\": \"DHL Invoice INV-44219\"\
        ,\n    \"tracked_job_log_id\": 9221,\n    \"supplier\": { \"id\": 12, \"name\"\
        : \"DHL Express\" },\n    \"extraction_bills\": [],\n    \"confirmed_at\"\
        : null,\n    \"confirmed_by_user_id\": null,\n    \"created_at\": \"2026-05-01T08:14:00.000000Z\"\
        ,\n    \"updated_at\": \"2026-05-01T08:14:00.000000Z\"\n  }\n}\n```\n\n**Match\
        \ tiers** (in order of confidence): `mapped` (Tier 0 — saved supplier mapping),\
        \ `exact_name`, `name_substring`, `keyword`, `fuzzy_name`, `fuzzy_mapped`,\
        \ `unmatched`.\n\n**Candidate target reasons**: `prebind` (from upload param),\
        \ `supplier_eta_close` (open inbound shipment for matched supplier with ETA\
        \ within window), `supplier_match` (any open PO / WT for matched supplier)."
      parameters:
      - name: landed_cost_extraction_id
        in: path
        schema:
          type: integer
        required: true
        description: ID of the LandedCostInvoiceOcrExtraction record.
        example: '18'
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:read
      operationId: get-api-landed-cost-invoices-ocr-landed-cost-extraction-id
    delete:
      tags:
      - Landed Cost Invoice OCR
      summary: Delete Extraction
      description: 'Soft-delete a landed cost invoice OCR extraction record (and its
        associated S3 PDF). Confirmed extractions cannot be deleted (returns 422).


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        **Response:** 204 No Content on success.


        **Response 422 (already confirmed):**

        ```json

        { "message": "Confirmed extractions cannot be deleted." }

        ```'
      parameters:
      - name: landed_cost_extraction_id
        in: path
        schema:
          type: string
        required: true
        description: The landed cost extraction ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:write
      operationId: delete-api-landed-cost-invoices-ocr-landed-cost-extraction-id
  /api/landed-cost-invoices/ocr/{landed_cost_extraction_id}/pdf:
    get:
      tags:
      - Landed Cost Invoice OCR
      summary: Stream Extraction PDF
      description: 'Stream the original landed cost invoice PDF through the backend
        (avoids CORS when fetching from S3). Returns Content-Type: application/pdf,
        `Content-Disposition: inline; filename="landed-cost-invoice.pdf"`. Returns
        404 if the underlying S3 object is missing. Cache-Control: private, max-age=300.


        :::info[Required scope: `purchase-orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: landed_cost_extraction_id
        in: path
        schema:
          type: string
        required: true
        description: The landed cost extraction ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: purchase-orders:read
      operationId: get-api-landed-cost-invoices-ocr-landed-cost-extraction-id-pdf
  /api/landed-cost-invoices/ocr/{landed_cost_extraction_id}/apply:
    post:
      tags:
      - Landed Cost Invoice OCR
      summary: Apply Extraction (Create Bills)
      description: "Accept the reviewed/edited extraction and create one or more `Bill`\
        \ records — one per target entity (inbound shipment, purchase order, or warehouse\
        \ transfer) — each with its own apportionment of the cost lines. Marks the\
        \ extraction as `confirmed` and persists `Bill` rows linked via the polymorphic\
        \ `bills.link_type` / `link_id` columns. Bridges supplier → vendor since Bills\
        \ require `vendor_id`.\n\n:::info[Required scope: `purchase-orders:write`]\n\
        Grant this scope to your token under [Settings → Developer → Personal Access\
        \ Tokens](https://app.sku.io/settings/api).\n:::\n\nThe extraction must be\
        \ in `pending_review` or `duplicate_detected` status (a duplicate-detected\
        \ extraction is allowed because the user may confirm it is not actually a\
        \ duplicate and proceed). Returns 422 otherwise.\n\nWhen multiple targets\
        \ are supplied, the invoice number is suffixed per target (`{invoice_number}-{type3}-{target_id}`)\
        \ to avoid `bills.invoice_number` unique constraint violations.\n\n**Request\
        \ body fields:**\n| Field | Type | Required | Notes |\n|-------|------|----------|-------|\n\
        | supplier_id | integer | yes | Must exist in suppliers. |\n| invoice_number\
        \ | string | yes | Max 255 chars. |\n| invoice_date | date | yes | |\n| currency_code\
        \ | string | yes | ISO 4217 (size:3). |\n| currency_rate | numeric | yes |\
        \ Min 0. Conversion rate to base currency. |\n| total_amount | numeric | yes\
        \ | Total invoice amount. |\n| cost_lines | array | yes | At least 1 line.\
        \ |\n| cost_lines[].description | string | yes | Max 500 chars. |\n| cost_lines[].quantity\
        \ | numeric | yes | |\n| cost_lines[].unit_price | numeric | yes | |\n| cost_lines[].line_total\
        \ | numeric | yes | |\n| cost_lines[].cost_category_id | integer | no (nullable)\
        \ | Must exist in cost_categories. Null = unclassified line. |\n| cost_lines[].ignored\
        \ | boolean | no | Skip persisting this line (audit-only). |\n| targets |\
        \ array | yes | At least 1 target. Allocation shares MUST sum to 1.0 ±0.001.\
        \ |\n| targets[].target_type | string | yes | One of: inbound_shipment, purchase_order,\
        \ warehouse_transfer. |\n| targets[].target_id | integer | yes | ID of target\
        \ entity. |\n| targets[].proration_strategy | string | yes | FinancialLineProrationStrategyEnum:\
        \ revenue_based, cost_based, weight_based, volume_based, quantity_based, specific_line,\
        \ manual. |\n| targets[].allocation_share | numeric | yes | 0–1. Share of\
        \ the total this target receives. |\n| remember_mappings | boolean | no |\
        \ When `true`, upserts `(supplier_id, normalized_description) → cost_category_id`\
        \ mappings into `supplier_landed_cost_mappings` so future OCR imports auto-tag\
        \ matching descriptions as cost lines (Tier 0 match). |\n\n**Response 201:**\n\
        ```json\n{\n  \"data\": {\n    \"id\": 18,\n    \"status\": \"confirmed\"\
        ,\n    \"extraction_bills\": [\n      {\"id\": 33, \"bill_id\": 491, \"target_type\"\
        : \"inbound_shipment\", \"target_id\": 142, \"allocation_share\": 0.6},\n\
        \      {\"id\": 34, \"bill_id\": 492, \"target_type\": \"purchase_order\"\
        , \"target_id\": 88, \"allocation_share\": 0.4}\n    ],\n    \"confirmed_at\"\
        : \"2026-05-01T08:30:00.000000Z\",\n    \"confirmed_by_user_id\": 7\n  },\n\
        \  \"message\": \"Landed cost invoice applied.\"\n}\n```\n\n**Response 422\
        \ — wrong status:**\n```json\n{ \"message\": \"Only extractions pending review\
        \ can be applied.\" }\n```\n\n**Response 422 — allocation shares do not sum\
        \ to 1.0:**\n```json\n{ \"message\": \"Target allocation shares must sum to\
        \ 1.0.\" }\n```"
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                supplier_id:
                  type: integer
                invoice_number:
                  type: string
                invoice_date:
                  type: string
                currency_code:
                  type: string
                currency_rate:
                  type: integer
                total_amount:
                  type: number
                cost_lines:
                  type: array
                  items:
                    type: object
                    properties:
                      description:
                        type: string
                      quantity:
                        type: integer
                      unit_price:
                        type: integer
                      line_total:
                        type: integer
                      cost_category_id:
                        type: integer
                      ignored:
                        type: boolean
                targets:
                  type: array
                  items:
                    type: object
                    properties:
                      target_type:
                        type: string
                      target_id:
                        type: integer
                      proration_strategy:
                        type: string
                      allocation_share:
                        type: number
                remember_mappings:
                  type: boolean
              example:
                supplier_id: 12
                invoice_number: INV-44219
                invoice_date: '2026-04-12'
                currency_code: USD
                currency_rate: 1
                total_amount: 1850.75
                cost_lines:
                - description: Freight Charges
                  quantity: 1
                  unit_price: 1500
                  line_total: 1500
                  cost_category_id: 4
                  ignored: false
                - description: Fuel Surcharge
                  quantity: 1
                  unit_price: 350.75
                  line_total: 350.75
                  cost_category_id: 4
                  ignored: false
                targets:
                - target_type: inbound_shipment
                  target_id: 142
                  proration_strategy: cost_based
                  allocation_share: 0.6
                - target_type: purchase_order
                  target_id: 88
                  proration_strategy: quantity_based
                  allocation_share: 0.4
                remember_mappings: true
      parameters:
      - name: landed_cost_extraction_id
        in: path
        schema:
          type: string
        required: true
        description: The landed cost extraction ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: purchase-orders:write
      operationId: post-api-landed-cost-invoices-ocr-landed-cost-extraction-id-apply
  /api/landed-cost-invoices/ocr/{landed_cost_extraction_id}/rescan:
    post:
      tags:
      - Landed Cost Invoice OCR
      summary: Re-scan Extraction
      description: "Re-run Azure Document Intelligence OCR on the original PDF (e.g.,\
        \ after Azure model improvements, or to retry a failed extraction). Async\
        \ — returns a `tracked_job_log_id` for progress tracking via the tracked job\
        \ log endpoints.\n\n:::info[Required scope: `purchase-orders:write`]\nGrant\
        \ this scope to your token under [Settings → Developer → Personal Access Tokens](https://app.sku.io/settings/api).\n\
        :::\n\nRefuses (422) if the extraction is in `confirmed` status, or if the\
        \ original `file_path` is missing.\n\n**Response 200:**\n```json\n{\n  \"\
        data\": {\n    \"extraction_id\": 18,\n    \"tracked_job_log_id\": 9311,\n\
        \    \"status\": \"processing\"\n  },\n  \"message\": \"Re-scan started.\"\
        \n}\n```\n\n**Response 422 (already confirmed):**\n```json\n{ \"message\"\
        : \"Confirmed extractions cannot be re-scanned.\" }\n```\n\n**Response 422\
        \ (file missing):**\n```json\n{ \"message\": \"Cannot re-scan — original file\
        \ is no longer available.\" }\n```"
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties: {}
              example: {}
      parameters:
      - name: landed_cost_extraction_id
        in: path
        schema:
          type: string
        required: true
        description: The landed cost extraction ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: purchase-orders:write
      operationId: post-api-landed-cost-invoices-ocr-landed-cost-extraction-id-rescan
  /api/landed-cost-invoices/ocr/{landed_cost_extraction_id}/draft:
    patch:
      tags:
      - Landed Cost Invoice OCR
      summary: Save Draft (Working State)
      description: 'Persist in-progress edits to the review form so users can resume
        later (across browser refresh / device switch). The `working_state` body is
        an opaque object stored on the extraction — the frontend defines its shape
        (typically header_overrides, line_overrides, selected_targets, etc.). Returns
        the updated extraction.


        :::info[Required scope: `purchase-orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        **Request body:**

        | Field | Type | Required | Notes |

        |-------|------|----------|-------|

        | working_state | object | yes | Opaque JSON; shape defined by the frontend
        review UI. |


        Refuses (422) if the extraction is in `confirmed` status.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                working_state:
                  type: object
                  properties:
                    header_overrides:
                      type: object
                      properties:
                        invoice_number:
                          type: string
                        invoice_date:
                          type: string
                    line_overrides:
                      type: array
                      items:
                        type: object
                        properties:
                          index:
                            type: integer
                          cost_category_id:
                            type: integer
                    selected_targets:
                      type: array
                      items:
                        type: object
                        properties:
                          target_type:
                            type: string
                          target_id:
                            type: integer
                          allocation_share:
                            type: number
              example:
                working_state:
                  header_overrides:
                    invoice_number: INV-44219
                    invoice_date: '2026-04-12'
                  line_overrides:
                  - index: 0
                    cost_category_id: 4
                  - index: 1
                    cost_category_id: 4
                  selected_targets:
                  - target_type: inbound_shipment
                    target_id: 142
                    allocation_share: 0.6
                  - target_type: purchase_order
                    target_id: 88
                    allocation_share: 0.4
      parameters:
      - name: landed_cost_extraction_id
        in: path
        schema:
          type: string
        required: true
        description: The landed cost extraction ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: purchase-orders:write
      operationId: patch-api-landed-cost-invoices-ocr-landed-cost-extraction-id-draft
  /api/cost-category-keyword-aliases:
    get:
      tags:
      - Landed Cost Invoice OCR
      summary: List Cost Category Keyword Aliases
      description: "List active cost-category keyword aliases used by the OCR cost-line\
        \ matcher. Returns an object keyed by `cost_category_id` with arrays of keyword\
        \ strings. Used by the Settings page that lets users curate which keywords\
        \ (e.g., \"freight\", \"fuel surcharge\", \"customs\", \"duty\", \"clearance\"\
        ) map to which CostCategory.\n\n:::info[Required scope: `purchase-orders:read`]\n\
        Grant this scope to your token under [Settings → Developer → Personal Access\
        \ Tokens](https://app.sku.io/settings/api).\n:::\n\nKeywords feed Tier 4 (`keyword`)\
        \ of the 6-tier match cascade in the OCR manager.\n\n**Response 200:**\n```json\n\
        {\n  \"data\": {\n    \"4\": [\"freight\", \"shipping\", \"fuel surcharge\"\
        , \"airfreight\"],\n    \"5\": [\"customs\", \"duty\", \"clearance\", \"import\
        \ duty\"],\n    \"6\": [\"insurance\", \"cargo insurance\"]\n  }\n}\n```"
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      '4':
                        type: array
                        items:
                          type: string
                      '5':
                        type: array
                        items:
                          type: string
                      '6':
                        type: array
                        items:
                          type: string
                example:
                  data:
                    '4':
                    - freight
                    - shipping
                    - fuel surcharge
                    '5':
                    - customs
                    - duty
                    - clearance
                    '6':
                    - insurance
                    - cargo insurance
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: purchase-orders:read
      operationId: get-api-cost-category-keyword-aliases
    put:
      tags:
      - Landed Cost Invoice OCR
      summary: Replace Cost Category Keyword Aliases
      description: "Replace the full set of keyword aliases for a single cost category.\
        \ Idempotent — the repository diffs the supplied list against the existing\
        \ rows: removes keywords not in the new list, inserts new ones. Default-flagged\
        \ keywords (seeded by migration) are preserved if they remain in the new list,\
        \ or removed if dropped. Keywords are normalized to lowercase + trimmed; duplicates\
        \ are deduped server-side.\n\n:::info[Required scope: `purchase-orders:write`]\n\
        Grant this scope to your token under [Settings → Developer → Personal Access\
        \ Tokens](https://app.sku.io/settings/api).\n:::\n\n**Request body:**\n| Field\
        \ | Type | Required | Notes |\n|-------|------|----------|-------|\n| cost_category_id\
        \ | integer | yes | Must exist in cost_categories. |\n| keywords | array |\
        \ yes (present) | Each keyword: string, min 2 / max 100 chars. May be empty\
        \ array to clear all keywords. |\n\n**Response 200:**\n```json\n{\n  \"data\"\
        : {\n    \"cost_category_id\": 4,\n    \"keywords\": [\"freight\", \"shipping\"\
        , \"fuel surcharge\", \"airfreight\"]\n  },\n  \"message\": \"Keyword aliases\
        \ updated.\"\n}\n```\n\n**Response 422 (validation):**\n```json\n{\n  \"message\"\
        : \"The cost category id field is required.\",\n  \"errors\": {\n    \"cost_category_id\"\
        : [\"The cost category id field is required.\"],\n    \"keywords.0\": [\"\
        Each keyword must be at least 2 characters.\"]\n  }\n}\n```"
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                cost_category_id:
                  type: integer
                keywords:
                  type: array
                  items:
                    type: string
              example:
                cost_category_id: 4
                keywords:
                - freight
                - shipping
                - fuel surcharge
                - airfreight
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: purchase-orders:write
      operationId: put-api-cost-category-keyword-aliases
  /api/document-inbox:
    get:
      tags:
      - Document Inbox
      summary: List Inbox Documents
      description: "Return a unified, paginated, descending-by-created_at list combining\
        \ customer PO, supplier invoice, vendor credit, and landed cost invoice OCR\
        \ extractions. Each item is normalized to the same shape so a single mixed-type\
        \ list can be rendered. Vendor credit extractions that are attached to an\
        \ existing vendor credit (vendor_credit_attachment_id set) are excluded —\
        \ they belong to that credit's documents, not the inbox.\n\n:::warning[Not\
        \ yet available to API tokens]\nThis endpoint currently requires session authentication;\
        \ Personal Access Token scope support is in progress.\n:::\n\nExample item:\n\
        ```json\n{\n  \"id\": 42,\n  \"type\": \"supplier_invoice\",\n  \"status\"\
        : \"pending_review\",\n  \"source\": \"email\",\n  \"source_email_from\":\
        \ \"Jane Doe <jane@tenant.com>\",\n  \"source_email_forwarded_from\": \"orders-usa@tecmate.com\"\
        ,\n  \"source_email_subject\": \"Fwd: Invoice Number-0002020\",\n  \"customer_name\"\
        : null,\n  \"supplier_name\": \"TecMATE\",\n  \"document_type\": \"invoice\"\
        ,\n  \"detection_signals\": [],\n  \"auto_routed\": false,\n  \"ocr_header\"\
        : {\n    \"doc_number\": {\"value\": \"0002020\", \"confidence\": 0.97},\n\
        \    \"total\": {\"value\": 37.06, \"confidence\": 0.97},\n    \"tax_amount\"\
        : {\"value\": 2.10, \"confidence\": 0.9},\n    \"currency_code\": {\"value\"\
        : \"USD\", \"confidence\": 0.99},\n    \"doc_date\": {\"value\": \"2026-07-17\"\
        , \"confidence\": 0.97},\n    \"po_number\": {\"value\": \"PO-0671\", \"confidence\"\
        : 0.95}\n  },\n  \"confirmed_record\": null,\n  \"error_message\": null,\n\
        \  \"created_at\": \"2026-07-17T22:28:48.000000Z\"\n}\n```\n\nSender fields:\n\
        - `source_email_from` — the sender of the email that reached the intake address.\
        \ For forwarded emails this is the forwarder, not the original contact.\n\
        - `source_email_forwarded_from` — the original sender parsed out of a forwarded\
        \ email's body/headers (null for direct sends and uploads). Prefer this as\
        \ the document's real contact when present.\n\nOCR header summary (`ocr_header`):\n\
        - A compact summary of what OCR extracted from the document, or null while\
        \ the document is still processing (or when extraction failed before analysis).\n\
        - Each field is `{value, confidence}`; `confidence` is 0–1 or null when the\
        \ extraction pipeline did not score the field.\n- `doc_number` — the document's\
        \ own number: invoice number (supplier_invoice, landed_cost_invoice), credit\
        \ memo number (vendor_credit), or customer PO number (customer_po).\n- `total`,\
        \ `tax_amount`, `currency_code` — extracted money fields.\n- `doc_date` —\
        \ the document's own date (invoice date, credit date, or order date), distinct\
        \ from `created_at` (when the document arrived).\n- `po_number` — for supplier\
        \ invoices, the purchase order number referenced on the invoice (null for\
        \ customer POs, where the PO number IS `doc_number`).\n\nClassification fields:\n\
        - `document_type` — what the classifier decided the document is: `invoice`\
        \ or `credit_memo`. Populated on supplier_invoice and vendor_credit items;\
        \ always null for customer_po and landed_cost_invoice.\n- `detection_signals`\
        \ — array of signal keys that drove the classification (e.g. `keyword:credit\
        \ memo`, `doc_number:CM prefix`, `total:negative`). Null when no detection\
        \ ran.\n- `auto_routed` — true when the document arrived in the supplier invoice\
        \ pipeline but was automatically routed to the vendor credit queue by the\
        \ classifier. Always false for customer_po, supplier_invoice, and landed_cost_invoice\
        \ items.\n\nWhen status is 'confirmed', `confirmed_record` is populated with\
        \ `{ id, type, number }` of the created sales order, purchase invoice, vendor\
        \ credit (type: `vendor_credit`, number: the vendor_credit_number), or landed\
        \ cost bill (type: `landed_cost_invoice`).\n\nLanded cost invoice items (`type:\
        \ \"landed_cost_invoice\"`) expose `supplier_id`/`supplier_name` (the matched\
        \ supplier, when detected) and always have `customer_id`, `customer_name`,\
        \ `document_type`, and `detection_signals` as null with `auto_routed` false."
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: get-api-document-inbox
  /api/document-inbox/pending-count:
    get:
      tags:
      - Document Inbox
      summary: Get Pending Count
      description: 'Lightweight count of all extractions currently in ''pending_review''
        status (sales + purchase + vendor credit + landed cost invoice). Vendor credit
        extractions that belong to an existing credit (vendor_credit_attachment_id
        set) are excluded from the count. Polled by the navigation drawer every 60
        seconds to render the inbox badge.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Response:

        ```json

        { "data": { "pending_review": 7 } }

        ```'
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: get-api-document-inbox-pending-count
  /api/document-inbox/customer_po/{extraction_id}/retry:
    post:
      tags:
      - Document Inbox
      summary: Retry Failed Extraction
      description: 'Re-dispatch OCR processing for a failed extraction. Path param
        `type` must be one of `customer_po`, `supplier_invoice`, `vendor_credit`,
        or `landed_cost_invoice` (regex-constrained); `id` is the matching extraction
        ID.


        Validations (return 422):

        - Extraction status must be ''failed''

        - Original file must still be present (file_path != null)

        - type must be customer_po, supplier_invoice, vendor_credit, or landed_cost_invoice


        On success for customer_po / supplier_invoice: resets the extraction status
        to ''processing'', clears error_message, dispatches the appropriate OCR job.


        For vendor_credit: routes, which claims the extraction for processing, then
        re-runs the parse from the stored Azure `raw_response` synchronously when
        available (no second Azure charge), or dispatches the Scan Credit Memo job
        otherwise. Returns 422 with the manager''s error message if the credit''s
        documents are locked or a scan is already in progress.


        For landed_cost_invoice: routes, which marks the extraction as processing
        and re-dispatches a background job. Returns 422 with the manager''s error
        message on failure.


        Response 200:

        ```json

        { "message": "Retry queued." }

        ```'
      requestBody:
        content: {}
      parameters:
      - name: extraction_id
        in: path
        schema:
          type: string
        required: true
        description: The extraction ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-document-inbox-customer-po-extraction-id-retry
  /api/document-inbox/bulk-destroy:
    post:
      tags:
      - Document Inbox
      summary: Bulk Delete Inbox Documents
      description: "Bulk-delete a polymorphic mix of OCR extractions from the unified\
        \ Document Inbox. Powers the bulk-actions toolbar shown when rows are selected\
        \ in the inbox UI.\n\n:::warning[Not yet available to API tokens]\nThis endpoint\
        \ currently requires session authentication; Personal Access Token scope support\
        \ is in progress.\n:::\n\nRequest body:\n- `items` (required, array, min:1)\
        \ — list of extractions to delete\n- `items.*.type` (required, string, in:customer_po,supplier_invoice,vendor_credit,landed_cost_invoice)\
        \ — which OCR extraction model the id belongs to\n- `items.*.id` (required,\
        \ integer) — extraction ID\n\nBehavior:\n- Validates the entire payload with\
        \ Laravel validation (returns 422 on shape errors)\n- Iterates each item;\
        \ routes `customer_po` to the API::deleteExtraction`, `supplier_invoice` to\
        \ the API::deleteExtraction`, `vendor_credit` to the API::deleteExtraction`,\
        \ and `landed_cost_invoice` to the API::deleteExtraction` (deletes the S3\
        \ file and soft-deletes the extraction row)\n- All managers delete the S3\
        \ file (if any) and the DB record (vendor credit deletes skip the S3 delete\
        \ when the file belongs to an attachment on an existing credit)\n- **Confirmed\
        \ extractions are SKIPPED** (cannot be deleted — same constraint as the single-record\
        \ DELETE endpoints)\n- Missing IDs are reported in `not_found` rather than\
        \ failing the whole request — partial success is allowed\n\nResponse 200:\n\
        ```json\n{\n  \"deleted\": 2,\n  \"skipped\": [\n    { \"type\": \"customer_po\"\
        , \"id\": 91, \"reason\": \"confirmed\" }\n  ],\n  \"not_found\": [],\n  \"\
        message\": \"2 document(s) deleted successfully. 1 skipped (confirmed).\"\n\
        }\n```"
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                items:
                  type: array
                  items:
                    type: object
                    properties:
                      type:
                        type: string
                      id:
                        type: integer
              example:
                items:
                - type: customer_po
                  id: 42
                - type: supplier_invoice
                  id: 17
                - type: vendor_credit
                  id: 9
                - type: landed_cost_invoice
                  id: 5
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-session-only: true
      operationId: post-api-document-inbox-bulk-destroy
  /api/document-inbox/customer_po/{extraction_id}/siblings:
    get:
      tags:
      - Document Inbox
      summary: Get Adjacent Documents
      description: "Returns the previous and next document in the unified inbox relative\
        \ to the given extraction. Powers the prev/next pager on the OCR review pages\
        \ so the user can walk through the queue without bouncing back to the inbox\
        \ list.\n\nPath params:\n- `type` (required) — one of `customer_po`, `supplier_invoice`,\
        \ `vendor_credit`, or `landed_cost_invoice` (regex-constrained at the route\
        \ level; unknown values return 404)\n- `id` (required, integer) — extraction\
        \ ID of the currently-viewed document\n\nBehavior:\n- Walks `sales_order_ocr_extractions`,\
        \ `purchase_invoice_ocr_extractions`, `vendor_credit_ocr_extractions`, and\
        \ `landed_cost_invoice_ocr_extractions` together (vendor credit rows tied\
        \ to an existing credit's attachment are excluded, matching the inbox listing)\n\
        - Only `pending_review` extractions participate in the walk — confirmed/failed/processing\
        \ rows have no Review button in the inbox, so the OCR review page wouldn't\
        \ show anything actionable for them\n- The current item itself is ALWAYS included\
        \ even if it's no longer `pending_review` (e.g. the user just confirmed it\
        \ but hasn't navigated yet) — keeps `position`/`total` correct on the open\
        \ page\n- Sort order matches the inbox listing: `created_at DESC, id DESC`\n\
        - `prev`/`next` cross table boundaries — the next document may be a customer\
        \ PO, vendor credit, or landed cost invoice even if the current one is a supplier\
        \ invoice\n- `prev`/`next` are `null` at the boundaries of the list\n- Each\
        \ sibling reference includes both `type` and `id` so the frontend can route\
        \ to the correct OCR review page\n- `position` is 1-indexed (1 = newest);\
        \ `null` if the current item is not found at all (e.g. just deleted)\n\nResponse\
        \ 200:\n```json\n{\n  \"data\": {\n    \"prev\": { \"type\": \"supplier_invoice\"\
        , \"id\": 17 },\n    \"next\": { \"type\": \"vendor_credit\", \"id\": 9 },\n\
        \    \"position\": 2,\n    \"total\": 47\n  }\n}\n```\n\nResponse 404: route\
        \ constraint blocks `type` values other than `customer_po`, `supplier_invoice`,\
        \ `vendor_credit`, or `landed_cost_invoice`."
      parameters:
      - name: extraction_id
        in: path
        schema:
          type: string
        required: true
        description: The extraction ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-document-inbox-customer-po-extraction-id-siblings
  /api/document-inbox/customer_po/{extraction_id}/reclassify:
    post:
      tags:
      - Document Inbox
      summary: Reclassify Document Type
      description: "Reclassify an inbox extraction as a different document type —\
        \ the user-facing escape hatch when automatic type detection got it wrong.\
        \ Copies the original file into the target pipeline, creates a new extraction\
        \ there, and rejects the source extraction with a back-reference.\n\nPath\
        \ params:\n- `type` (required) — current document type: one of `customer_po`,\
        \ `supplier_invoice`, `vendor_credit`, or `landed_cost_invoice` (regex-constrained\
        \ at the route level; unknown values return 404)\n- `id` (required, integer)\
        \ — extraction ID\n\nRequest body:\n- `target_type` (required, string, in:customer_po,supplier_invoice,vendor_credit,landed_cost_invoice)\
        \ — the type to reclassify the document as (returns 422 validation error otherwise)\n\
        \nBehavior:\n- Source extraction must be in a reclassifiable status: `pending_review`,\
        \ `duplicate_detected`, or `failed`\n- Three pairwise conversions are delegated\
        \ to their existing dedicated flows (which can reuse the stored Azure `raw_response`\
        \ to avoid a second OCR charge): customer_po → supplier_invoice, supplier_invoice\
        \ → vendor_credit, and vendor_credit → supplier_invoice\n- All other source/target\
        \ pairs use the generic flow: the original file is copied from the source\
        \ pipeline's storage into the target pipeline's staging directory, a new extraction\
        \ row is created in the target table, and the target's OCR job is dispatched.\
        \ When the source already has a stored `raw_response` and the target is supplier_invoice\
        \ or vendor_credit, the result is parsed synchronously instead of dispatching\
        \ a job\n- The source extraction is marked `rejected` with error_message \"\
        Reclassified as {label} (extraction #{id}).\" inside the same transaction\n\
        \nResponse 200:\n```json\n{\n  \"message\": \"Document reclassified.\",\n\
        \  \"data\": { \"type\": \"supplier_invoice\", \"id\": 88 }\n}\n```\n`data.type`/`data.id`\
        \ identify the NEW extraction so the frontend can route straight to the correct\
        \ OCR review page.\n\nErrors (422, `{ \"error\": \"...\" }`):\n- \"The document\
        \ is already classified as a {label}.\" — target_type equals the current type\n\
        - \"Only extractions pending review can be reclassified.\" — source status\
        \ not in pending_review/duplicate_detected/failed\n- \"Original OCR file is\
        \ no longer available.\" — source file_path is empty\n- Standard Laravel validation\
        \ error when `target_type` is missing or not one of the four allowed values\n\
        \nResponse 404: route constraint blocks unknown `type` path values; unknown\
        \ `id` returns 404 via findOrFail."
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                target_type:
                  type: string
              example:
                target_type: supplier_invoice
      parameters:
      - name: extraction_id
        in: path
        schema:
          type: string
        required: true
        description: The extraction ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-document-inbox-customer-po-extraction-id-reclassify
  /api/documents:
    get:
      tags:
      - Documents
      summary: List Documents for a Record
      description: 'Lists the documents linked to a given business record (purchase
        order, purchase invoice, or bill). Because one document can be linked to several
        records, the same file appears here for every record it relates to.


        Authentication: Requires Bearer token.'
      parameters:
      - name: type
        in: query
        schema:
          type: string
        description: 'Required. The record type to list documents for. One of: purchase_order,
          purchase_invoice, bill.'
        example: purchase_order
      - name: id
        in: query
        schema:
          type: integer
        description: Required. The record's ID.
        example: '900'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        file_name:
                          type: string
                        mime_type:
                          type: string
                        is_image:
                          type: boolean
                        file_size:
                          type: integer
                        source:
                          type: string
                        file_url:
                          type: string
                        linked_records:
                          type: array
                          items:
                            type: object
                            properties:
                              type:
                                type: string
                              id:
                                type: integer
                        created_at:
                          type: string
                example:
                  data:
                  - id: 42
                    file_name: invoice-INV-5501.pdf
                    mime_type: application/pdf
                    is_image: false
                    file_size: 81234
                    source: ocr_supplier_invoice
                    file_url: '{{protocol}}{{domain}}/api/documents/42/file'
                    linked_records:
                    - type: App\Models\PurchaseOrder
                      id: 900
                    - type: App\Models\PurchaseInvoice
                      id: 1201
                    created_at: '2026-07-18T01:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-documents
  /api/documents/{documentId}/file:
    get:
      tags:
      - Documents
      summary: Stream Document File
      description: 'Streams a document''s file inline (PDF or image) through the backend.
        Content-Type reflects the stored file''s type.


        Authentication: Requires Bearer token.'
      parameters:
      - name: documentId
        in: path
        schema:
          type: integer
        required: true
        description: Document ID
        example: '42'
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-documents-documentid-file
  /api/sales-orders/{salesOrder}/fulfillment-orders:
    get:
      tags:
      - Fulfillment Orders
      summary: List Fulfillment Orders for a Sales Order
      description: 'Lists every FulfillmentOrder attached to a SalesOrder with eager-loaded
        lines + warehouse. Powers the Pending sub-tab in the application UI SO detail
        page.


        :::info[Required scope: `orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        **Channel double-fulfillment coverage (F6):** each FO carries a transient
        boolean `has_channel_covered_units` — true when an still-open sales-channel
        (Shopify) fulfillment order may yet ship some of this FO''s units. When present,
        every line carries `channel_covered`: `true` for a line the channel may still
        ship ("awaiting channel"), `false` for a line safe to dispatch natively ("dispatchable").
        Both fields are stamped only by this list endpoint (not the single-FO detail
        endpoint) and omitted on FOs whose lines are not loaded. They drive the per-line
        awaiting-channel vs dispatchable badges and the submit-time guardrail.


        Returns 404 if the feature flag is off.


        Response is a JSON:API-style resource collection (no pagination — typically
        a handful of FOs per SO).


        **Fulfillability:** each line carries `fulfillable_quantity` and `unfulfillable_quantity`,
        computed against the FulfillmentOrder''s own (intent) warehouse — not the
        SalesOrderLine''s warehouse_id. The warehouse block''s `tracks_inventory`
        flag is false for externally-managed warehouses (Amazon FBA/AWD).


        **Line field `executed_quantity`** (per FO line): the physically-executed
        quantity — the sum of non-voided child SalesOrderFulfillmentLine quantities.
        Distinct from the accounting figure `quantity - remaining_quantity`; when
        the two disagree the line carries a masked shortfall (e.g. a bundle line grown
        to its component quantity with `remaining_quantity = 0` though fewer component
        units actually shipped).


        **`provider_order_link`** (object|null): INTERNAL cross-link to this FO''s
        registered shipping-provider order detail page inside SKU — `{ link_reference,
        link_type_label, link_id, link_route }`. Distinct from the EXTERNAL `provider_order_url`.
        Populated for providers with an in-app per-order page (ShipStation, ShipHero,
        Starshipit, Trackstar, VeraCore, Shipfusion); `null` for providers with no
        detail page (ShipMyOrders), for pre-submit FOs, and for FBA/Manual FOs with
        no provider order. `link_route` is a application UI path, e.g. `/integrations/shipstation/4/orders/92532`.


        **Line field `sales_order_fulfillment_lines`** (per FO line): the child SalesOrderFulfillmentLine
        (execution) records for this FOL — a debug aid so support can trace SOL →
        FOL → SOFL on any line. Each entry is `{ id, sales_order_fulfillment_id, voided
        }`; `voided` reflects the parent SalesOrderFulfillment''s `voided_at` (a voided
        SOFL can pin its FOL at quantity 0). Empty array until the FO is submitted
        into a carrier shipment. Example populated value: `[{ "id": 1194390, "sales_order_fulfillment_id":
        685484, "voided": false }]`.'
      parameters:
      - name: salesOrder
        in: path
        schema:
          type: integer
        required: true
        description: Sales order ID
        example: '123'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        sales_order_id:
                          type: integer
                        warehouse_id:
                          type: integer
                        status:
                          type: string
                        request_status:
                          type: string
                        external_id:
                          type: string
                          nullable: true
                        external_type:
                          type: string
                          nullable: true
                        integration_instance_id:
                          type: string
                          nullable: true
                        effective_fulfillment_provider:
                          type: string
                        effective_integration_instance_name:
                          type: string
                          nullable: true
                        provider_order_link:
                          type: string
                          nullable: true
                        submitted_at:
                          type: string
                          nullable: true
                        accepted_at:
                          type: string
                          nullable: true
                        closed_at:
                          type: string
                          nullable: true
                        cancelled_at:
                          type: string
                          nullable: true
                        rejection_reason:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                        updated_at:
                          type: string
                        has_channel_covered_units:
                          type: boolean
                        sales_channel_fulfillment_link:
                          type: object
                          properties:
                            channel:
                              type: string
                            fulfillment:
                              type: string
                              nullable: true
                            fulfillment_orders:
                              type: array
                              items:
                                type: object
                                properties:
                                  link_id:
                                    type: integer
                                  link_reference:
                                    type: string
                                  link_type_label:
                                    type: string
                                  link_route:
                                    type: string
                                  status:
                                    type: string
                                  status_label:
                                    type: string
                                  tracking_company:
                                    type: string
                                    nullable: true
                                  tracking_number:
                                    type: string
                                    nullable: true
                                  tracking_url:
                                    type: string
                                    nullable: true
                                  items:
                                    type: array
                                    items:
                                      type: object
                                      properties:
                                        sku:
                                          type: string
                                        name:
                                          type: string
                                        quantity:
                                          type: integer
                                  item_match:
                                    type: object
                                    properties:
                                      matches:
                                        type: boolean
                                      lines:
                                        type: array
                                        items:
                                          type: object
                                          properties:
                                            sku:
                                              type: string
                                            name:
                                              type: string
                                            our_qty:
                                              type: integer
                                            channel_qty:
                                              type: integer
                                            state:
                                              type: string
                        lines:
                          type: array
                          items:
                            type: object
                            properties:
                              id:
                                type: integer
                              fulfillment_order_id:
                                type: integer
                              sales_order_line_id:
                                type: integer
                              quantity:
                                type: integer
                              remaining_quantity:
                                type: integer
                              fulfillable_quantity:
                                type: integer
                              unfulfillable_quantity:
                                type: integer
                              executed_quantity:
                                type: integer
                              sales_order_fulfillment_lines:
                                type: array
                              lot_allocation:
                                type: string
                                nullable: true
                              channel_covered:
                                type: boolean
                              sku:
                                type: string
                              name:
                                type: string
                              product_id:
                                type: integer
                              warehouse_id:
                                type: integer
                              created_at:
                                type: string
                              updated_at:
                                type: string
                        warehouse:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            type:
                              type: string
                            tracks_inventory:
                              type: boolean
                example:
                  data:
                  - id: 451
                    sales_order_id: 123
                    warehouse_id: 7
                    status: open
                    request_status: unsubmitted
                    external_id: null
                    external_type: null
                    integration_instance_id: null
                    effective_fulfillment_provider: manual
                    effective_integration_instance_name: null
                    provider_order_link: null
                    submitted_at: null
                    accepted_at: null
                    closed_at: null
                    cancelled_at: null
                    rejection_reason: null
                    created_at: '2026-05-26T10:15:00+00:00'
                    updated_at: '2026-05-26T10:15:00+00:00'
                    has_channel_covered_units: true
                    sales_channel_fulfillment_link:
                      channel: shopify
                      fulfillment: null
                      fulfillment_orders:
                      - link_id: 8001
                        link_reference: '#8593402003694'
                        link_type_label: Shopify Fulfillment Order
                        link_route: /integrations/shopify/fulfillment-orders/8001?filter[integration_instance_ids]=2
                        status: open
                        status_label: Open
                        tracking_company: null
                        tracking_number: null
                        tracking_url: null
                        items:
                        - sku: RCF5OZ
                          name: Bellwether Farms Creme Fraiche 5 oz
                          quantity: 1
                        item_match:
                          matches: true
                          lines:
                          - sku: RCF5OZ
                            name: Bellwether Farms Creme Fraiche 5 oz
                            our_qty: 1
                            channel_qty: 1
                            state: ok
                    lines:
                    - id: 901
                      fulfillment_order_id: 451
                      sales_order_line_id: 55347
                      quantity: 3
                      remaining_quantity: 3
                      fulfillable_quantity: 3
                      unfulfillable_quantity: 0
                      executed_quantity: 0
                      sales_order_fulfillment_lines: []
                      lot_allocation: null
                      channel_covered: true
                      sku: WIDGET-01
                      name: Blue Widget
                      product_id: 88
                      warehouse_id: 7
                      created_at: '2026-05-26T10:15:00+00:00'
                      updated_at: '2026-05-26T10:15:00+00:00'
                    warehouse:
                      id: 7
                      name: Main Warehouse
                      type: standard
                      tracks_inventory: true
                  - id: 452
                    sales_order_id: 123
                    warehouse_id: 9
                    status: open
                    request_status: submitted
                    external_id: shipfusion-93214
                    external_type: shipfusion
                    integration_instance_id: 4
                    effective_fulfillment_provider: shipfusion
                    effective_integration_instance_name: Shipfusion — Atlanta
                    provider_order_link:
                      link_reference: ORD-100245
                      link_type_label: Shipfusion Order
                      link_id: 101
                      link_route: /integrations/shipfusion/4/orders/101
                    submitted_at: '2026-05-26T09:45:00+00:00'
                    accepted_at: '2026-05-26T09:46:00+00:00'
                    closed_at: null
                    cancelled_at: null
                    rejection_reason: null
                    created_at: '2026-05-26T09:40:00+00:00'
                    updated_at: '2026-05-26T09:46:00+00:00'
                    has_channel_covered_units: false
                    lines:
                    - id: 905
                      fulfillment_order_id: 452
                      sales_order_line_id: 55349
                      quantity: 4
                      remaining_quantity: 4
                      fulfillable_quantity: 4
                      unfulfillable_quantity: 0
                      executed_quantity: 0
                      sales_order_fulfillment_lines: []
                      lot_allocation: null
                      channel_covered: false
                      sku: FBA-SKU
                      name: FBA Item
                      product_id: 90
                      warehouse_id: 9
                      created_at: '2026-05-26T09:40:00+00:00'
                      updated_at: '2026-05-26T09:46:00+00:00'
                    warehouse:
                      id: 9
                      name: 3PL Atlanta
                      type: 3pl
                      tracks_inventory: true
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Not Found
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: orders:read
      operationId: get-api-sales-orders-salesorder-fulfillment-orders
  /api/fulfillment-orders/{fulfillmentOrder}:
    get:
      tags:
      - Fulfillment Orders
      summary: Get Fulfillment Order Detail
      description: 'Returns a single FulfillmentOrder with its lines and warehouse
        eager-loaded. Each line exposes its `quantity` (the original budget) and `remaining_quantity`
        (the over-fulfilment backstop — units still available to consume via a SalesOrderFulfillmentLine).


        :::info[Required scope: `orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Returns 404 if the feature flag is off or the FO does not exist.


        **Fulfillability:** each line carries `fulfillable_quantity` and `unfulfillable_quantity`,
        computed against the FulfillmentOrder''s own (intent) warehouse — not the
        SalesOrderLine''s warehouse_id. The warehouse block''s `tracks_inventory`
        flag is false for externally-managed warehouses (Amazon FBA/AWD).


        **Line field `executed_quantity`** (per FO line): the physically-executed
        quantity — the sum of non-voided child SalesOrderFulfillmentLine quantities.
        Distinct from the accounting figure `quantity - remaining_quantity`; when
        the two disagree the line carries a masked shortfall (e.g. a bundle line grown
        to its component quantity with `remaining_quantity = 0` though fewer component
        units actually shipped).


        **`provider_order_link`** (object|null): INTERNAL cross-link to this FO''s
        registered shipping-provider order detail page inside SKU — `{ link_reference,
        link_type_label, link_id, link_route }`. Distinct from the EXTERNAL `provider_order_url`.
        Populated for providers with an in-app per-order page (ShipStation, ShipHero,
        Starshipit, Trackstar, VeraCore, Shipfusion); `null` for providers with no
        detail page (ShipMyOrders), for pre-submit FOs, and for FBA/Manual FOs with
        no provider order. `link_route` is a application UI path, e.g. `/integrations/shipstation/4/orders/92532`.


        **Line field `sales_order_fulfillment_lines`** (per FO line): the child SalesOrderFulfillmentLine
        (execution) records for this FOL — a debug aid so support can trace SOL →
        FOL → SOFL on any line. Each entry is `{ id, sales_order_fulfillment_id, voided
        }`; `voided` reflects the parent SalesOrderFulfillment''s `voided_at` (a voided
        SOFL can pin its FOL at quantity 0). Empty array until the FO is submitted
        into a carrier shipment. Example populated value: `[{ "id": 1194390, "sales_order_fulfillment_id":
        685484, "voided": false }]`.'
      parameters:
      - name: fulfillmentOrder
        in: path
        schema:
          type: integer
        required: true
        description: FulfillmentOrder ID
        example: '451'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      sales_order_id:
                        type: integer
                      warehouse_id:
                        type: integer
                      status:
                        type: string
                      request_status:
                        type: string
                      external_id:
                        type: string
                      external_type:
                        type: string
                      integration_instance_id:
                        type: integer
                      effective_fulfillment_provider:
                        type: string
                      effective_integration_instance_name:
                        type: string
                      provider_order_link:
                        type: object
                        properties:
                          link_reference:
                            type: string
                          link_type_label:
                            type: string
                          link_id:
                            type: integer
                          link_route:
                            type: string
                      submitted_at:
                        type: string
                      accepted_at:
                        type: string
                      closed_at:
                        type: string
                        nullable: true
                      cancelled_at:
                        type: string
                        nullable: true
                      rejection_reason:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            fulfillment_order_id:
                              type: integer
                            sales_order_line_id:
                              type: integer
                            quantity:
                              type: integer
                            remaining_quantity:
                              type: integer
                            fulfillable_quantity:
                              type: integer
                            unfulfillable_quantity:
                              type: integer
                            executed_quantity:
                              type: integer
                            sales_order_fulfillment_lines:
                              type: array
                            lot_allocation:
                              type: string
                              nullable: true
                            sku:
                              type: string
                            name:
                              type: string
                            product_id:
                              type: integer
                            warehouse_id:
                              type: integer
                            created_at:
                              type: string
                            updated_at:
                              type: string
                      warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          type:
                            type: string
                          tracks_inventory:
                            type: boolean
                example:
                  data:
                    id: 451
                    sales_order_id: 123
                    warehouse_id: 7
                    status: open
                    request_status: accepted
                    external_id: '92532'
                    external_type: shipstation_order
                    integration_instance_id: 4
                    effective_fulfillment_provider: shipstation
                    effective_integration_instance_name: ShipStation
                    provider_order_link:
                      link_reference: O260613JZ3ECM.1
                      link_type_label: ShipStation Order
                      link_id: 92532
                      link_route: /integrations/shipstation/4/orders/92532
                    submitted_at: '2026-06-13T14:22:05.000000Z'
                    accepted_at: '2026-06-13T14:22:09.000000Z'
                    closed_at: null
                    cancelled_at: null
                    rejection_reason: null
                    created_at: '2026-05-26T10:15:00+00:00'
                    updated_at: '2026-05-26T10:15:00+00:00'
                    lines:
                    - id: 901
                      fulfillment_order_id: 451
                      sales_order_line_id: 55347
                      quantity: 3
                      remaining_quantity: 3
                      fulfillable_quantity: 3
                      unfulfillable_quantity: 0
                      executed_quantity: 0
                      sales_order_fulfillment_lines: []
                      lot_allocation: null
                      sku: WIDGET-01
                      name: Blue Widget
                      product_id: 88
                      warehouse_id: 7
                      created_at: '2026-05-26T10:15:00+00:00'
                      updated_at: '2026-05-26T10:15:00+00:00'
                    - id: 902
                      fulfillment_order_id: 451
                      sales_order_line_id: 55348
                      quantity: 2
                      remaining_quantity: 1
                      fulfillable_quantity: 1
                      unfulfillable_quantity: 0
                      executed_quantity: 0
                      sales_order_fulfillment_lines: []
                      lot_allocation: null
                      sku: WIDGET-02
                      name: Red Widget
                      product_id: 89
                      warehouse_id: 7
                      created_at: '2026-05-26T10:15:00+00:00'
                      updated_at: '2026-05-26T10:32:00+00:00'
                    warehouse:
                      id: 7
                      name: Main Warehouse
                      type: standard
                      tracks_inventory: true
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:read
      operationId: get-api-fulfillment-orders-fulfillmentorder
  /api/fulfillment-orders:
    post:
      tags:
      - Fulfillment Orders
      summary: Create Fulfillment Order
      description: 'Creates a new FulfillmentOrder + its line budgets in a single
        transaction. Each line''s `remaining_quantity` is initialized to `quantity`.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        **Overfulfilment guard.** For every line, the manager row-locks the parent
        SalesOrderLine and validates that `SUM(quantity)` across all non-cancelled
        FOs for that SOL + the new requested quantity does not exceed `SalesOrderLine.quantity`.
        Violations return 422.


        **Request body fields:**

        - `sales_order_id` (required, integer, must exist) — parent SO.

        - `warehouse_id` (required, integer, must exist) — the warehouse this FO will
        be routed to. Cannot be changed once the FO leaves Open/Unsubmitted (see Move
        endpoint).

        - `lines` (required, array, min 1) — one entry per SOL being budgeted from
        this warehouse.

        - `lines.*.sales_order_line_id` (required, integer, must exist) — SOL ID.

        - `lines.*.quantity` (required, integer, min 1) — units to budget for this
        SOL from this warehouse.

        - `external_id` (nullable, string, max 128) — external provider''s FO/shipment
        ID once submitted.

        - `external_type` (nullable, string, max 64) — provider type discriminator
        (e.g. "shipfusion", "3pl").

        - `integration_instance_id` (nullable, integer, must exist) — integration
        instance for the provider.


        Returns 201 with the eager-loaded FO + lines + warehouse on success, 422 on
        overfulfilment, 404 if the feature flag is off.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                sales_order_id:
                  type: integer
                warehouse_id:
                  type: integer
                lines:
                  type: array
                  items:
                    type: object
                    properties:
                      sales_order_line_id:
                        type: integer
                      quantity:
                        type: integer
                external_id:
                  type: string
                  nullable: true
                external_type:
                  type: string
                  nullable: true
                integration_instance_id:
                  type: string
                  nullable: true
              example:
                sales_order_id: 123
                warehouse_id: 7
                lines:
                - sales_order_line_id: 55347
                  quantity: 3
                - sales_order_line_id: 55348
                  quantity: 2
                external_id: null
                external_type: null
                integration_instance_id: null
      parameters: []
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      sales_order_id:
                        type: integer
                      warehouse_id:
                        type: integer
                      status:
                        type: string
                      request_status:
                        type: string
                      external_id:
                        type: string
                        nullable: true
                      external_type:
                        type: string
                        nullable: true
                      integration_instance_id:
                        type: string
                        nullable: true
                      submitted_at:
                        type: string
                        nullable: true
                      accepted_at:
                        type: string
                        nullable: true
                      closed_at:
                        type: string
                        nullable: true
                      cancelled_at:
                        type: string
                        nullable: true
                      rejection_reason:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            fulfillment_order_id:
                              type: integer
                            sales_order_line_id:
                              type: integer
                            quantity:
                              type: integer
                            remaining_quantity:
                              type: integer
                            created_at:
                              type: string
                            updated_at:
                              type: string
                      warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          type:
                            type: string
                example:
                  data:
                    id: 451
                    sales_order_id: 123
                    warehouse_id: 7
                    status: open
                    request_status: unsubmitted
                    external_id: null
                    external_type: null
                    integration_instance_id: null
                    submitted_at: null
                    accepted_at: null
                    closed_at: null
                    cancelled_at: null
                    rejection_reason: null
                    created_at: '2026-05-26T10:15:00+00:00'
                    updated_at: '2026-05-26T10:15:00+00:00'
                    lines:
                    - id: 901
                      fulfillment_order_id: 451
                      sales_order_line_id: 55347
                      quantity: 3
                      remaining_quantity: 3
                      created_at: '2026-05-26T10:15:00+00:00'
                      updated_at: '2026-05-26T10:15:00+00:00'
                    warehouse:
                      id: 7
                      name: Main Warehouse
                      type: standard
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 422 Overfulfilment
                  value:
                    error: 'Cannot fulfill 99 of sales_order_line 55347: only 3 units
                      remain unbudgeted across all FulfillmentOrders.'
                example-1:
                  summary: 422 Validation Error
                  value:
                    message: The lines field must have at least 1 items.
                    errors:
                      lines:
                      - The lines field must have at least 1 items.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: orders:write
      operationId: post-api-fulfillment-orders
    get:
      tags:
      - Fulfillment Orders
      summary: List Active Fulfillment Orders (Dispatch Feed, capped)
      description: 'Cross-order **dispatch board** feed: every ACTIVE fulfillment
        order across all sales orders (excludes `closed` and `cancelled`), with `salesOrder`
        (for `sales_order_number`), `warehouse`, and `lines` eager-loaded. The frontend
        groups these into Kanban columns by `request_status` / `status` (Awaiting
        dispatch → Submitting → Submitted/Accepted → In progress → Needs attention).


        :::info[Required scope: `orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        **Lazy-load per lifecycle:** pass `lifecycle` (manual|pickup|push|pull|channel)
        to load just that tab''s lifecycle; the cap (most recent 500) then applies
        per lifecycle. Omit for all lifecycles. Pickup is request-status-driven (awaiting_pickup
        / picked_up) — an FO with a pickup fulfillment but no pickup method still
        lands under pickup, not its warehouse carrier. Use **Dispatch Board — Lifecycle
        Counts** for the tab badges.


        Authenticate with a Personal Access Token.


        **Card detail fields:** each FO also returns sales_order_date, customer_name,
        sales_channel_name, and total_quantity (sum of line quantities). packing_slip_printed_at
        is included too (null until printed).'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        sales_order_id:
                          type: integer
                        sales_order_number:
                          type: string
                        sales_order_date:
                          type: string
                        customer_name:
                          type: string
                        customer_id:
                          type: integer
                        sales_channel_name:
                          type: string
                        integration_name:
                          type: string
                        total_quantity:
                          type: integer
                        packing_slip_printed_at:
                          type: string
                        warehouse_id:
                          type: integer
                        status:
                          type: string
                        request_status:
                          type: string
                        is_stuck_submitting:
                          type: boolean
                        is_pickup:
                          type: boolean
                        external_id:
                          type: string
                          nullable: true
                        external_type:
                          type: string
                          nullable: true
                        integration_instance_id:
                          type: string
                          nullable: true
                        requested_shipping_method_id:
                          type: string
                          nullable: true
                        requested_shipping_method:
                          type: string
                          nullable: true
                        requested_ship_date:
                          type: string
                          nullable: true
                        requested_metadata:
                          type: string
                          nullable: true
                        submitted_at:
                          type: string
                          nullable: true
                        accepted_at:
                          type: string
                          nullable: true
                        closed_at:
                          type: string
                          nullable: true
                        cancelled_at:
                          type: string
                          nullable: true
                        rejection_reason:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                        updated_at:
                          type: string
                        lines:
                          type: array
                          items:
                            type: object
                            properties:
                              id:
                                type: integer
                              fulfillment_order_id:
                                type: integer
                              sales_order_line_id:
                                type: integer
                              quantity:
                                type: integer
                              remaining_quantity:
                                type: integer
                        warehouse:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            type:
                              type: string
                            order_fulfillment:
                              type: string
                            supplier_id:
                              type: string
                              nullable: true
                            supplier_name:
                              type: string
                              nullable: true
                example:
                  data:
                  - id: 451
                    sales_order_id: 123
                    sales_order_number: SO-0042
                    sales_order_date: '2026-06-15T00:00:00+00:00'
                    customer_name: Acme Retail Co.
                    customer_id: 281384
                    sales_channel_name: Shopify
                    integration_name: Curvy AU
                    total_quantity: 5
                    packing_slip_printed_at: '2026-06-16T14:32:10+00:00'
                    warehouse_id: 7
                    status: open
                    request_status: unsubmitted
                    is_stuck_submitting: false
                    is_pickup: false
                    external_id: null
                    external_type: null
                    integration_instance_id: null
                    requested_shipping_method_id: null
                    requested_shipping_method: null
                    requested_ship_date: null
                    requested_metadata: null
                    submitted_at: null
                    accepted_at: null
                    closed_at: null
                    cancelled_at: null
                    rejection_reason: null
                    created_at: '2026-05-31T10:15:00+00:00'
                    updated_at: '2026-05-31T10:15:00+00:00'
                    lines:
                    - id: 901
                      fulfillment_order_id: 451
                      sales_order_line_id: 55347
                      quantity: 5
                      remaining_quantity: 5
                    warehouse:
                      id: 7
                      name: Default Warehouse
                      type: direct
                      order_fulfillment: starshipit
                      supplier_id: null
                      supplier_name: null
                  - id: 452
                    sales_order_id: 124
                    sales_order_number: SO-0043
                    sales_order_date: '2026-06-15T00:00:00+00:00'
                    customer_name: Acme Retail Co.
                    customer_id: 281384
                    sales_channel_name: Shopify
                    integration_name: Curvy AU
                    total_quantity: 5
                    packing_slip_printed_at: '2026-06-16T14:32:10+00:00'
                    warehouse_id: 9
                    status: open
                    request_status: rejected
                    is_stuck_submitting: false
                    is_pickup: false
                    rejection_reason: Invalid postal code for service
                    created_at: '2026-05-31T10:20:00+00:00'
                    updated_at: '2026-05-31T10:21:00+00:00'
                    lines:
                    - id: 902
                      fulfillment_order_id: 452
                      sales_order_line_id: 55400
                      quantity: 4
                      remaining_quantity: 4
                    warehouse:
                      id: 9
                      name: West Coast WH
                      type: direct
                      order_fulfillment: starshipit
                      supplier_id: null
                      supplier_name: null
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: orders:read
      operationId: get-api-fulfillment-orders
  /api/fulfillment-orders/{fulfillmentOrder}/move-preview:
    get:
      tags:
      - Fulfillment Orders
      summary: Preview Fulfillment Order Move (Coverage)
      description: 'Read-only coverage check for a prospective whole-FO move. Reports,
        per line that would move, whether the target warehouse can ship it from on-hand
        stock or would backorder it — so the UI can warn before committing. Mutates
        nothing.


        :::info[Required scope: `orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Use this to drive the move dialog''s warning, then call `PATCH .../move` with
        `acknowledge_backorder: true` to commit.


        **Query params:**

        - `warehouse_id` (required, integer, must exist) — the prospective destination.


        **Per-line `outcome` values:** `covered` (ships in full), `partial` (some
        ships, the rest backorders), `backorder` (whole line backorders), `blemished_shortfall`
        (blemished line short on stock — can''t backorder).'
      parameters:
      - name: warehouse_id
        in: query
        schema:
          type: integer
        description: Prospective destination warehouse (required, must exist).
        example: '9'
      - name: fulfillmentOrder
        in: path
        schema:
          type: integer
        required: true
        description: FulfillmentOrder ID
        example: '451'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      warehouse_id:
                        type: integer
                      warehouse_name:
                        type: string
                      tracks_inventory:
                        type: boolean
                      lines:
                        type: array
                        items:
                          type: object
                          properties:
                            sales_order_line_id:
                              type: integer
                            fulfillment_order_line_id:
                              type: integer
                            product_id:
                              type: integer
                            sku:
                              type: string
                            product_name:
                              type: string
                            requested_quantity:
                              type: integer
                            coverable_quantity:
                              type: integer
                            backorder_quantity:
                              type: integer
                            is_blemished:
                              type: boolean
                            outcome:
                              type: string
                      moving_line_count:
                        type: integer
                      shortfall_line_count:
                        type: integer
                      has_shortfall:
                        type: boolean
                      has_blemished_shortfall:
                        type: boolean
                      will_empty_fo:
                        type: boolean
                example:
                  data:
                    warehouse_id: 9
                    warehouse_name: 3PL Atlanta
                    tracks_inventory: true
                    lines:
                    - sales_order_line_id: 55347
                      fulfillment_order_line_id: 901
                      product_id: 1088
                      sku: SHAVE-FIG
                      product_name: Shave Soap Bar - Mediterranean Fig
                      requested_quantity: 3
                      coverable_quantity: 1
                      backorder_quantity: 2
                      is_blemished: false
                      outcome: partial
                    moving_line_count: 1
                    shortfall_line_count: 1
                    has_shortfall: true
                    has_blemished_shortfall: false
                    will_empty_fo: false
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:read
      operationId: get-api-fulfillment-orders-fulfillmentorder-move-preview
  /api/fulfillment-orders/{fulfillmentOrder}/move:
    patch:
      tags:
      - Fulfillment Orders
      summary: Move Fulfillment Order to Different Warehouse
      description: 'Pre-submit warehouse re-route. Relocates the WHOLE fulfillment
        order to a new warehouse: every line on the FO has its sales-order-line warehouse
        moved and its committed stock re-allocated at the target, and the FO itself
        is re-pointed there (the shipping provider follows the warehouse). It is the
        FO-level equivalent of moving each line individually. To move a single line
        instead, use the per-line move on the sales order.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        **Mutability gate.** Allowed ONLY when the FO is `status=open` AND `request_status=unsubmitted`.
        Once the FO is handed to a provider (anything beyond unsubmitted) the warehouse
        decision is frozen — returns 409.


        **Backorder, warn-first.** A target short on stock does NOT block the move:
        the shortfall backorders (Planned) and is evicted off the FO so it holds only
        shippable lines (a wholly-uncovered FO is deleted). Because that quietly backorders,
        an un-acknowledged move that would backorder returns **409 with `requires_acknowledgement:
        true` and a `coverage` object** instead of committing — call `GET .../move-preview`
        (or read that coverage) to warn the user, then resend with `acknowledge_backorder:
        true`. Blemished products can''t backorder; their shortfall is flagged as
        `blemished_shortfall` in the coverage.


        **Body fields:**

        - `warehouse_id` (required, integer, must exist) — new destination warehouse.

        - `acknowledge_backorder` (optional, boolean, default false) — set true to
        proceed when the move would backorder one or more lines.

        - `reason` (optional, string, max 1000) — free-text note for the audit trail.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                warehouse_id:
                  type: integer
                acknowledge_backorder:
                  type: boolean
                reason:
                  type: string
              example:
                warehouse_id: 9
                acknowledge_backorder: false
                reason: Out of stock at original location
      parameters:
      - name: fulfillmentOrder
        in: path
        schema:
          type: integer
        required: true
        description: FulfillmentOrder ID
        example: '451'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      sales_order_id:
                        type: integer
                      warehouse_id:
                        type: integer
                      status:
                        type: string
                      request_status:
                        type: string
                      external_id:
                        type: string
                        nullable: true
                      external_type:
                        type: string
                        nullable: true
                      integration_instance_id:
                        type: string
                        nullable: true
                      submitted_at:
                        type: string
                        nullable: true
                      accepted_at:
                        type: string
                        nullable: true
                      closed_at:
                        type: string
                        nullable: true
                      cancelled_at:
                        type: string
                        nullable: true
                      rejection_reason:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            fulfillment_order_id:
                              type: integer
                            sales_order_line_id:
                              type: integer
                            quantity:
                              type: integer
                            remaining_quantity:
                              type: integer
                            created_at:
                              type: string
                            updated_at:
                              type: string
                      warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          type:
                            type: string
                example:
                  data:
                    id: 451
                    sales_order_id: 123
                    warehouse_id: 9
                    status: open
                    request_status: unsubmitted
                    external_id: null
                    external_type: null
                    integration_instance_id: null
                    submitted_at: null
                    accepted_at: null
                    closed_at: null
                    cancelled_at: null
                    rejection_reason: null
                    created_at: '2026-05-26T10:15:00+00:00'
                    updated_at: '2026-05-26T10:18:00+00:00'
                    lines:
                    - id: 901
                      fulfillment_order_id: 451
                      sales_order_line_id: 55347
                      quantity: 3
                      remaining_quantity: 3
                      created_at: '2026-05-26T10:15:00+00:00'
                      updated_at: '2026-05-26T10:15:00+00:00'
                    warehouse:
                      id: 9
                      name: 3PL Atlanta
                      type: 3pl
        '409':
          description: Conflict
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 409 Not Mutable
                  value:
                    error: 'FulfillmentOrder #451 cannot be moved: status=open, request_status=submitted.
                      Only open + unsubmitted FOs are movable.'
                example-1:
                  summary: 409 Backorder Acknowledgement Required
                  value:
                    error: Moving this fulfillment order to 3PL Atlanta would backorder
                      1 of 1 line(s). Confirm to move what is in stock and backorder
                      the rest.
                    requires_acknowledgement: true
                    coverage:
                      warehouse_id: 9
                      warehouse_name: 3PL Atlanta
                      tracks_inventory: true
                      lines:
                      - sales_order_line_id: 55347
                        fulfillment_order_line_id: 901
                        product_id: 1088
                        sku: SHAVE-FIG
                        product_name: Shave Soap Bar - Mediterranean Fig
                        requested_quantity: 3
                        coverable_quantity: 1
                        backorder_quantity: 2
                        is_blemished: false
                        outcome: partial
                      moving_line_count: 1
                      shortfall_line_count: 1
                      has_shortfall: true
                      has_blemished_shortfall: false
                      will_empty_fo: false
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: orders:write
      operationId: patch-api-fulfillment-orders-fulfillmentorder-move
  /api/fulfillment-orders/{fulfillmentOrder}/submit:
    post:
      tags:
      - Fulfillment Orders
      summary: Submit Fulfillment Order to Provider
      description: 'Transitions `request_status` from `unsubmitted` → `submitting`
        and stamps `submitted_at` to the moment of hand-off (NOT when the carrier
        confirms — see Stage 2 for the carrier-callback flow that flips `submitting`
        → `submitted`/`accepted`).


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        **Mutability gate.** Allowed ONLY when `status=open` AND `request_status=unsubmitted`.
        Violations return 409.


        **Request body (all fields optional).** Submission acts on the WHOLE FO —
        there are no per-line quantities (split the FO first to dispatch part of it).


        - `acknowledge_open_channel_fulfillment` (boolean, default false) — double-fulfillment
        guardrail (F4a). When an still-open sales-channel (Shopify) fulfillment order
        may yet ship some of this FO''s units, an omitted/false submit is refused
        with **409** carrying `requires_acknowledgement: true` and a `coverage` preview.
        Resubmit with this `true` to dispatch natively anyway.

        - `requested_integration_instance_id` (integer|null) — per-FO shipping-provider
        override; must be a SHIPPING_PROVIDER instance.

        - `requested_fulfillment_type` (string|null, only `manual`) — force Manual
        dispatch (no integration instance).

        - `requested_shipping_method_id` (integer|null) / `requested_shipping_method`
        (string|null) — requested carrier service.

        - `requested_ship_date` (date|null), `requested_metadata` (object|null) —
        optional ship intent bridged onto the SalesOrderFulfillment (`notes`, `fulfillment_sequence`,
        `signature_required`, `veracore_*`, `isInsured`, `instructionsForWarehouse`).

        - `lot_allocations` (array|null) — per-line FEFO override for lot-tracked
        lines: `[{ sales_order_line_id, lots: [{ fifo_layer_id, quantity }] }]`. Re-validated
        at dispatch; stale picks fall back to FEFO. Omit for automatic FEFO/FIFO.


        Set `override_partial_dispatch` to true to dispatch a sales order that is
        only partially fulfillable even when partial dispatch is disabled in fulfillment
        settings. When it is disabled and the order is not fully fulfillable, the
        request is refused with 409 and a body `code` of `partial_dispatch_disabled`.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                acknowledge_open_channel_fulfillment:
                  type: boolean
                override_partial_dispatch:
                  type: boolean
              example:
                acknowledge_open_channel_fulfillment: false
                override_partial_dispatch: false
      parameters:
      - name: fulfillmentOrder
        in: path
        schema:
          type: integer
        required: true
        description: FulfillmentOrder ID
        example: '451'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      sales_order_id:
                        type: integer
                      warehouse_id:
                        type: integer
                      status:
                        type: string
                      request_status:
                        type: string
                      external_id:
                        type: string
                        nullable: true
                      external_type:
                        type: string
                        nullable: true
                      integration_instance_id:
                        type: string
                        nullable: true
                      effective_fulfillment_provider:
                        type: string
                      effective_integration_instance_name:
                        type: string
                        nullable: true
                      submitted_at:
                        type: string
                      accepted_at:
                        type: string
                        nullable: true
                      closed_at:
                        type: string
                        nullable: true
                      cancelled_at:
                        type: string
                        nullable: true
                      rejection_reason:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            fulfillment_order_id:
                              type: integer
                            sales_order_line_id:
                              type: integer
                            quantity:
                              type: integer
                            remaining_quantity:
                              type: integer
                            created_at:
                              type: string
                            updated_at:
                              type: string
                      warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          type:
                            type: string
                example:
                  data:
                    id: 451
                    sales_order_id: 123
                    warehouse_id: 7
                    status: open
                    request_status: submitting
                    external_id: null
                    external_type: null
                    integration_instance_id: null
                    effective_fulfillment_provider: manual
                    effective_integration_instance_name: null
                    submitted_at: '2026-05-26T10:20:00+00:00'
                    accepted_at: null
                    closed_at: null
                    cancelled_at: null
                    rejection_reason: null
                    created_at: '2026-05-26T10:15:00+00:00'
                    updated_at: '2026-05-26T10:20:00+00:00'
                    lines:
                    - id: 901
                      fulfillment_order_id: 451
                      sales_order_line_id: 55347
                      quantity: 3
                      remaining_quantity: 3
                      created_at: '2026-05-26T10:15:00+00:00'
                      updated_at: '2026-05-26T10:15:00+00:00'
                    warehouse:
                      id: 7
                      name: Main Warehouse
                      type: standard
        '409':
          description: Conflict
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 409 Not Mutable
                  value:
                    error: 'Cannot submit fulfillment_order 451: only open + unsubmitted
                      FOs can be submitted (currently status=open, request_status=submitting).'
                example-1:
                  summary: 409 Requires Channel Acknowledgement
                  value:
                    error: An open sales-channel fulfillment may still ship some of
                      these units. Resubmit with acknowledge_open_channel_fulfillment=true
                      to dispatch natively anyway.
                    requires_acknowledgement: true
                    coverage:
                      fulfillment_order_id: 451
                      sales_order_id: 123
                      sales_order_number: C632930
                      covered_line_count: 1
                      has_open_channel_coverage: true
                      lines:
                      - sales_order_line_id: 55347
                        fulfillment_order_line_id: 901
                        product_id: 88
                        sku: WIDGET-01
                        product_name: Blue Widget
                        requested_quantity: 3
                        channel_open_quantity: 1
                        channel_covered: true
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: orders:write
      operationId: post-api-fulfillment-orders-fulfillmentorder-submit
  /api/fulfillment-orders/{fulfillmentOrder}/cancel:
    post:
      tags:
      - Fulfillment Orders
      summary: Cancel Fulfillment Order
      description: 'Cancels the fulfillment order, releases its line budgets back
        to the parent sales-order lines (so a different fulfillment order can pick
        them up), and optionally records a reason. Sets `status=cancelled` + `cancelled_at`.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        **Provider recall.** If the fulfillment order has already been submitted to
        a shipping provider, cancelling first attempts to recall (cancel) it at the
        provider, then cancels it in SKU. Set `local_only=true` to skip the provider
        recall and cancel only in SKU — leaving any live provider order in place (use
        this when the provider can''t or won''t recall the order).


        **Mutability gate.** Rejected if the fulfillment order is already terminal
        (`status=closed`/`cancelled`) or is currently in-flight with the provider
        (`request_status=submitting`/`cancellation_requested`).


        **Body fields:**

        - `reason` (optional, string, max 1000) — stored for audit.

        - `local_only` (optional, boolean, default false) — cancel only in SKU without
        recalling the provider order.


        **Recall failure (409).** When a provider recall fails, the response carries
        `needs_local_only: true` so you can retry with `local_only=true`. `provider_unsupported`
        is `true` when the provider has no cancel capability at all (the order can
        never be recalled automatically), and `false` when the order may already have
        shipped.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                reason:
                  type: string
                local_only:
                  type: boolean
              example:
                reason: Customer requested change of address
                local_only: false
      parameters:
      - name: fulfillmentOrder
        in: path
        schema:
          type: integer
        required: true
        description: FulfillmentOrder ID
        example: '451'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      sales_order_id:
                        type: integer
                      warehouse_id:
                        type: integer
                      status:
                        type: string
                      request_status:
                        type: string
                      external_id:
                        type: string
                        nullable: true
                      external_type:
                        type: string
                        nullable: true
                      integration_instance_id:
                        type: string
                        nullable: true
                      submitted_at:
                        type: string
                        nullable: true
                      accepted_at:
                        type: string
                        nullable: true
                      closed_at:
                        type: string
                        nullable: true
                      cancelled_at:
                        type: string
                      rejection_reason:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            fulfillment_order_id:
                              type: integer
                            sales_order_line_id:
                              type: integer
                            quantity:
                              type: integer
                            remaining_quantity:
                              type: integer
                            created_at:
                              type: string
                            updated_at:
                              type: string
                      warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          type:
                            type: string
                example:
                  data:
                    id: 451
                    sales_order_id: 123
                    warehouse_id: 7
                    status: cancelled
                    request_status: unsubmitted
                    external_id: null
                    external_type: null
                    integration_instance_id: null
                    submitted_at: null
                    accepted_at: null
                    closed_at: null
                    cancelled_at: '2026-05-26T10:25:00+00:00'
                    rejection_reason: Customer requested change of address
                    created_at: '2026-05-26T10:15:00+00:00'
                    updated_at: '2026-05-26T10:25:00+00:00'
                    lines:
                    - id: 901
                      fulfillment_order_id: 451
                      sales_order_line_id: 55347
                      quantity: 3
                      remaining_quantity: 3
                      created_at: '2026-05-26T10:15:00+00:00'
                      updated_at: '2026-05-26T10:15:00+00:00'
                    warehouse:
                      id: 7
                      name: Main Warehouse
                      type: standard
        '409':
          description: Conflict
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 409 Not Cancellable
                  value:
                    error: 'Cannot cancel fulfillment_order 451: FO is in flight with
                      the provider (request_status=submitting). Use the cancel-request
                      flow to cancel an in-flight FO.'
                example-1:
                  summary: 409 Provider Recall Failed
                  value:
                    error: Mintsoft UK doesn't support cancelling orders through its
                      API, so this fulfillment order can't be recalled automatically.
                      Void it in SKU only — the order stays live at the provider,
                      so cancel it there directly if it still needs stopping.
                    needs_local_only: true
                    provider_unsupported: true
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: orders:write
      operationId: post-api-fulfillment-orders-fulfillmentorder-cancel
  /api/fulfillment-orders/{fulfillmentOrder}/mark-picked-up:
    put:
      tags:
      - Fulfillment Orders
      summary: Mark Fulfillment Order Picked Up
      description: 'Records an in-person Click & Collect collection. Creates the execution
        `SalesOrderFulfillment` (status=`fulfilled`) directly from the awaiting-pickup
        FulfillmentOrder — driving the inventory deduction at create-time — and advances
        the FO `request_status` to `picked_up`. No SalesOrderFulfillment exists before
        this point; the awaiting-pickup state lives entirely on the FO.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        **Gate.** 422 unless the FO is a Click & Collect order (`is_pickup`) currently
        at `request_status=awaiting_pickup`. 422 with `shortfalls` if `inventory_allocations`
        don''t cover the FO''s line quantities.


        **Body fields:**

        - `picked_up_at` (nullable, date) — collection timestamp; defaults to now.

        - `note` (nullable, string, max 1000) — recorded as a sales-order pickup note.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                picked_up_at:
                  type: string
                note:
                  type: string
              example:
                picked_up_at: '2026-06-24T03:14:00Z'
                note: Collected at front desk
      parameters:
      - name: fulfillmentOrder
        in: path
        schema:
          type: integer
        required: true
        description: FulfillmentOrder ID
        example: '451'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      sales_order_id:
                        type: integer
                      warehouse_id:
                        type: integer
                      status:
                        type: string
                      request_status:
                        type: string
                      is_pickup:
                        type: boolean
                      expected_pickup_at:
                        type: string
                      marked_for_pickup_at:
                        type: string
                      marked_for_pickup_by:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                example:
                  data:
                    id: 451
                    sales_order_id: 1234
                    warehouse_id: 2
                    status: closed
                    request_status: picked_up
                    is_pickup: true
                    expected_pickup_at: '2026-06-25T00:00:00+00:00'
                    marked_for_pickup_at: '2026-06-24T03:14:00+00:00'
                    marked_for_pickup_by:
                      id: 7
                      name: Jane Operator
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: orders:write
      operationId: put-api-fulfillment-orders-fulfillmentorder-mark-picked-up
  /api/fulfillment-orders/{fulfillmentOrder}/unmark-picked-up:
    put:
      tags:
      - Fulfillment Orders
      summary: Unmark Fulfillment Order Picked Up
      description: 'Reverses a Click & Collect collection. Voids the collected pickup
        `SalesOrderFulfillment` (reversing its inventory movements + allocations and
        restoring the FulfillmentOrderLine budget) and returns the FO `request_status`
        to `awaiting_pickup`.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        **Gate.** 422 unless the FO `request_status` is currently `picked_up`.'
      requestBody:
        content: {}
      parameters:
      - name: fulfillmentOrder
        in: path
        schema:
          type: integer
        required: true
        description: FulfillmentOrder ID
        example: '451'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      sales_order_id:
                        type: integer
                      warehouse_id:
                        type: integer
                      status:
                        type: string
                      request_status:
                        type: string
                      is_pickup:
                        type: boolean
                      expected_pickup_at:
                        type: string
                      marked_for_pickup_at:
                        type: string
                      marked_for_pickup_by:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                example:
                  data:
                    id: 451
                    sales_order_id: 1234
                    warehouse_id: 2
                    status: open
                    request_status: awaiting_pickup
                    is_pickup: true
                    expected_pickup_at: '2026-06-25T00:00:00+00:00'
                    marked_for_pickup_at: '2026-06-24T03:14:00+00:00'
                    marked_for_pickup_by:
                      id: 7
                      name: Jane Operator
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: orders:write
      operationId: put-api-fulfillment-orders-fulfillmentorder-unmark-picked-up
  /api/fulfillment-orders/{fulfillmentOrder}/split:
    post:
      tags:
      - Fulfillment Orders
      summary: Split Fulfillment Order
      description: "Manually carve an **unsubmitted (proforma)** FulfillmentOrder\
        \ into a NEW open/unsubmitted FO sized to the supplied per-line quantities.\
        \ The original FO keeps the remainder. This is pure FulfillmentOrderLine budget\
        \ redistribution — **neither FO is submitted** as a result (split and submit\
        \ are separate concerns). To dispatch part of an order, split it then submit/hold\
        \ each piece.\n\n:::info[Required scope: `orders:write`]\nGrant this scope\
        \ to your token under [Settings → Developer → Personal Access Tokens](https://app.sku.io/settings/api).\n\
        :::\n\n**Only valid while the FO is `open` + `unsubmitted`.** Allocations\
        \ are SOL-linked, so no allocation moves on a split.\n\n**Request body**\n\
        - `lines` (required, array, min 1): the quantities to carve into the new FO.\n\
        \  - `lines[].sales_order_line_id` (required, integer, exists) — a SOL present\
        \ on this FO.\n  - `lines[].quantity` (required, integer, min 1) — must not\
        \ exceed the FOL's `remaining_quantity`, and must not carve the FO's entire\
        \ remaining budget (that would leave nothing behind — submit/fulfill the whole\
        \ FO instead).\n\n**Responses**\n- `201` — the NEW carved FO (open/unsubmitted).\n\
        - `422` — a quantity exceeds the FOL remaining budget, or validation failed.\n\
        - `409` — the FO is not open+unsubmitted, or the request would carve the entire\
        \ FO (nothing left to split)."
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                lines:
                  type: array
                  items:
                    type: object
                    properties:
                      sales_order_line_id:
                        type: integer
                      quantity:
                        type: integer
              example:
                lines:
                - sales_order_line_id: 55347
                  quantity: 2
      parameters:
      - name: fulfillmentOrder
        in: path
        schema:
          type: integer
        required: true
        description: FulfillmentOrder ID (the proforma to split — must be open + unsubmitted)
        example: '451'
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      sales_order_id:
                        type: integer
                      warehouse_id:
                        type: integer
                      status:
                        type: string
                      request_status:
                        type: string
                      is_stuck_submitting:
                        type: boolean
                      is_pickup:
                        type: boolean
                      external_id:
                        type: string
                        nullable: true
                      external_type:
                        type: string
                        nullable: true
                      integration_instance_id:
                        type: string
                        nullable: true
                      requested_shipping_method_id:
                        type: string
                        nullable: true
                      requested_shipping_method:
                        type: string
                        nullable: true
                      requested_ship_date:
                        type: string
                        nullable: true
                      requested_metadata:
                        type: string
                        nullable: true
                      submitted_at:
                        type: string
                        nullable: true
                      accepted_at:
                        type: string
                        nullable: true
                      closed_at:
                        type: string
                        nullable: true
                      cancelled_at:
                        type: string
                        nullable: true
                      rejection_reason:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            fulfillment_order_id:
                              type: integer
                            sales_order_line_id:
                              type: integer
                            quantity:
                              type: integer
                            remaining_quantity:
                              type: integer
                            created_at:
                              type: string
                            updated_at:
                              type: string
                      warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          type:
                            type: string
                example:
                  data:
                    id: 452
                    sales_order_id: 123
                    warehouse_id: 7
                    status: open
                    request_status: unsubmitted
                    is_stuck_submitting: false
                    is_pickup: false
                    external_id: null
                    external_type: null
                    integration_instance_id: null
                    requested_shipping_method_id: null
                    requested_shipping_method: null
                    requested_ship_date: null
                    requested_metadata: null
                    submitted_at: null
                    accepted_at: null
                    closed_at: null
                    cancelled_at: null
                    rejection_reason: null
                    created_at: '2026-05-30T10:20:00+00:00'
                    updated_at: '2026-05-30T10:20:00+00:00'
                    lines:
                    - id: 902
                      fulfillment_order_id: 452
                      sales_order_line_id: 55347
                      quantity: 2
                      remaining_quantity: 2
                      created_at: '2026-05-30T10:20:00+00:00'
                      updated_at: '2026-05-30T10:20:00+00:00'
                    warehouse:
                      id: 7
                      name: Main Warehouse
                      type: standard
        '409':
          description: Conflict
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: 'FulfillmentOrder #451 cannot be split for execution: status=open,
                    request_status=unsubmitted. Only open + unsubmitted FOs can be
                    split, and only for a PARTIAL execution (a full execution must
                    transition in place).'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: 'FulfillmentOrderLine #901 cannot be over-fulfilled: requested
                    99 but only 5 remaining (quantity=5).'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:write
      operationId: post-api-fulfillment-orders-fulfillmentorder-split
  /api/fulfillment-orders/{fulfillmentOrder}/retry-submission:
    post:
      tags:
      - Fulfillment Orders
      summary: Retry Fulfillment Order Submission
      description: 'Operator recovery action for a FO that is **stuck submitting**
        — i.e. `request_status=submitting` for longer than the stuck threshold (`config(''fulfillment.stuck_submitting_threshold_minutes'')`,
        default 15) without the provider confirming. Resets `request_status` back
        to `unsubmitted` and clears `submitted_at`, so the operator (or the dispatcher)
        can re-attempt the hand-off.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        The FO detail/list payloads expose `is_stuck_submitting` (boolean) so the
        UI can surface the amber ''stuck dispatch'' banner that drives this action.


        **Mutability gate.** Allowed ONLY when `request_status=submitting` AND the
        FO is not terminal (`status` not closed/cancelled). Any other state returns
        409.


        No request body.'
      requestBody:
        content: {}
      parameters:
      - name: fulfillmentOrder
        in: path
        schema:
          type: integer
        required: true
        description: FulfillmentOrder ID
        example: '451'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      sales_order_id:
                        type: integer
                      warehouse_id:
                        type: integer
                      status:
                        type: string
                      request_status:
                        type: string
                      is_stuck_submitting:
                        type: boolean
                      is_pickup:
                        type: boolean
                      external_id:
                        type: string
                        nullable: true
                      external_type:
                        type: string
                        nullable: true
                      integration_instance_id:
                        type: string
                        nullable: true
                      submitted_at:
                        type: string
                        nullable: true
                      accepted_at:
                        type: string
                        nullable: true
                      closed_at:
                        type: string
                        nullable: true
                      cancelled_at:
                        type: string
                        nullable: true
                      rejection_reason:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            fulfillment_order_id:
                              type: integer
                            sales_order_line_id:
                              type: integer
                            quantity:
                              type: integer
                            remaining_quantity:
                              type: integer
                            created_at:
                              type: string
                            updated_at:
                              type: string
                      warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          type:
                            type: string
                example:
                  data:
                    id: 451
                    sales_order_id: 123
                    warehouse_id: 7
                    status: open
                    request_status: unsubmitted
                    is_stuck_submitting: false
                    is_pickup: false
                    external_id: null
                    external_type: null
                    integration_instance_id: null
                    submitted_at: null
                    accepted_at: null
                    closed_at: null
                    cancelled_at: null
                    rejection_reason: null
                    created_at: '2026-05-26T10:15:00+00:00'
                    updated_at: '2026-05-26T10:42:00+00:00'
                    lines:
                    - id: 901
                      fulfillment_order_id: 451
                      sales_order_line_id: 55347
                      quantity: 3
                      remaining_quantity: 3
                      created_at: '2026-05-26T10:15:00+00:00'
                      updated_at: '2026-05-26T10:15:00+00:00'
                    warehouse:
                      id: 7
                      name: Main Warehouse
                      type: standard
        '409':
          description: Conflict
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: 'Cannot retry submission for fulfillment_order 451: only
                    a FO that is currently submitting can be retried (currently status=open,
                    request_status=unsubmitted).'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: orders:write
      operationId: post-api-fulfillment-orders-fulfillmentorder-retry-submission
  /api/fulfillment-orders/{fulfillmentOrder}/force-fail-submission:
    post:
      tags:
      - Fulfillment Orders
      summary: Force-Fail Fulfillment Order Submission
      description: 'Operator recovery action for a FO that is **stuck submitting**
        when retrying is not appropriate (e.g. confirmed provider/carrier outage).
        Transitions `request_status` to `rejected` and records the supplied reason
        on `rejection_reason`. The FO drops out of the in-flight set so it can be
        cancelled or re-routed.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        The FO detail/list payloads expose `is_stuck_submitting` (boolean) so the
        UI can surface the amber ''stuck dispatch'' banner that drives this action.


        **Mutability gate.** Allowed ONLY when `request_status=submitting` AND the
        FO is not terminal (`status` not closed/cancelled). Any other state returns
        409.


        **Body fields:**

        - `reason` (nullable, string, max 1000) — stored on `rejection_reason` for
        audit. Defaults to ''Force-failed by operator (stuck dispatch).'' when omitted.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                reason:
                  type: string
              example:
                reason: Carrier outage — manual force-fail
      parameters:
      - name: fulfillmentOrder
        in: path
        schema:
          type: integer
        required: true
        description: FulfillmentOrder ID
        example: '451'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      sales_order_id:
                        type: integer
                      warehouse_id:
                        type: integer
                      status:
                        type: string
                      request_status:
                        type: string
                      is_stuck_submitting:
                        type: boolean
                      is_pickup:
                        type: boolean
                      external_id:
                        type: string
                        nullable: true
                      external_type:
                        type: string
                        nullable: true
                      integration_instance_id:
                        type: string
                        nullable: true
                      submitted_at:
                        type: string
                      accepted_at:
                        type: string
                        nullable: true
                      closed_at:
                        type: string
                        nullable: true
                      cancelled_at:
                        type: string
                        nullable: true
                      rejection_reason:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            fulfillment_order_id:
                              type: integer
                            sales_order_line_id:
                              type: integer
                            quantity:
                              type: integer
                            remaining_quantity:
                              type: integer
                            created_at:
                              type: string
                            updated_at:
                              type: string
                      warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          type:
                            type: string
                example:
                  data:
                    id: 451
                    sales_order_id: 123
                    warehouse_id: 7
                    status: open
                    request_status: rejected
                    is_stuck_submitting: false
                    is_pickup: false
                    external_id: null
                    external_type: null
                    integration_instance_id: null
                    submitted_at: '2026-05-26T10:20:00+00:00'
                    accepted_at: null
                    closed_at: null
                    cancelled_at: null
                    rejection_reason: Carrier outage — manual force-fail
                    created_at: '2026-05-26T10:15:00+00:00'
                    updated_at: '2026-05-26T10:45:00+00:00'
                    lines:
                    - id: 901
                      fulfillment_order_id: 451
                      sales_order_line_id: 55347
                      quantity: 3
                      remaining_quantity: 3
                      created_at: '2026-05-26T10:15:00+00:00'
                      updated_at: '2026-05-26T10:15:00+00:00'
                    warehouse:
                      id: 7
                      name: Main Warehouse
                      type: standard
        '409':
          description: Conflict
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: 'Cannot force-fail submission for fulfillment_order 451:
                    only a FO that is currently submitting can be force-failed (currently
                    status=open, request_status=unsubmitted).'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: orders:write
      operationId: post-api-fulfillment-orders-fulfillmentorder-force-fail-submission
  /api/fulfillment-orders/board-counts:
    get:
      tags:
      - Fulfillment Orders
      summary: Get Dispatch Board Counts
      description: 'Active-FO counts per dispatch-board lifecycle (+ `all`) for the
        board tab badges. Computed from the FULL active set (not the per-tab capped
        feed), so a badge reflects the true total even when its tab''s column list
        is capped. Uses the same lifecycle classification as the board feed''s `lifecycle`
        filter + the FO-table lifecycle filter, so the badge count and the loaded
        tab agree.


        :::info[Required scope: `orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authenticate with a Personal Access Token.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      all:
                        type: integer
                      manual:
                        type: integer
                      pickup:
                        type: integer
                      push:
                        type: integer
                      pull:
                        type: integer
                      channel:
                        type: integer
                example:
                  data:
                    all: 116
                    manual: 4
                    pickup: 7
                    push: 98
                    pull: 5
                    channel: 2
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: orders:read
      operationId: get-api-fulfillment-orders-board-counts
  /api/fulfillment-orders/{fulfillmentOrder}/merge-candidates:
    get:
      tags:
      - Fulfillment Orders
      summary: List Merge Candidates
      description: 'Returns sibling pre-dispatch fulfillment orders on OTHER sales
        orders that could dispatch together with the anchor as ONE provider order
        (cross-order merge). Powers the "Mergeable orders found" nudge on the sales
        order fulfillment tab.


        :::info[Required scope: `orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        **Eligibility** — a candidate is included only if it (and the anchor):

        - Is `status=open` and `request_status` in {`unsubmitted`, `rejected`} (pre-dispatch).

        - Belongs to a sales order that is NOT cancelled (a cancelled order''s FOs
        are recalled; a stale Open FO is never offered).

        - Is at the SAME warehouse, resolves to the SAME provider type + requested
        integration instance, and is NOT FBA-routed.

        - Ships to the SAME shipping-address signature (name + company + address1
        + address2 + city + province + zip + country_code) as the anchor.

        - Is on a DIFFERENT sales order, and is either ungrouped or already in the
        anchor''s merge group.


        If the anchor is itself ineligible (not pre-dispatch, FBA, cancelled order,
        or no shipping address) an empty list is returned.


        **Response shape** — `data[]` is an array of `FulfillmentOrderMergeCandidateData`:

        - `fulfillment_order_id` (int)

        - `sales_order_id` (int)

        - `sales_order_number` (string)

        - `customer_name` (string | null)

        - `integration_instance_name` (string | null)

        - `integration_instance_id` (int | null)

        - `line_count` (int)

        - `total_quantity` (int)

        - `requested_shipping_method` (string | null)

        - `integration_matches_anchor` (bool) — `false` when the candidate is from
        a different sales channel; the UI warns before merging.

        - `already_in_group` (bool) — `true` when the candidate is already a member
        of the anchor''s merge group.

        - `ship_by_date` (string | null) — UTC ISO 8601; the candidate order''s ship-by
        deadline, when set.

        - `hold_until_date` (string | null) — UTC ISO 8601; the candidate order''s
        hold-until ("do not ship before") date, when set.

        - `deliver_by_date` (string | null) — UTC ISO 8601; the candidate order''s
        deliver-by deadline, when set.


        **Auth:** Bearer token.'
      parameters:
      - name: fulfillmentOrder
        in: path
        schema:
          type: integer
        required: true
        description: Anchor FulfillmentOrder ID — the FO to find cross-order merge
          candidates for.
        example: '451'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        fulfillment_order_id:
                          type: integer
                        sales_order_id:
                          type: integer
                        sales_order_number:
                          type: string
                        customer_name:
                          type: string
                        integration_instance_name:
                          type: string
                        integration_instance_id:
                          type: integer
                        line_count:
                          type: integer
                        total_quantity:
                          type: integer
                        requested_shipping_method:
                          type: string
                        integration_matches_anchor:
                          type: boolean
                        already_in_group:
                          type: boolean
                        ship_by_date:
                          type: string
                        hold_until_date:
                          type: string
                        deliver_by_date:
                          type: string
                example:
                  data:
                  - fulfillment_order_id: 452
                    sales_order_id: 124
                    sales_order_number: GML430901
                    customer_name: Jane Doe
                    integration_instance_name: Acme Shopify
                    integration_instance_id: 3
                    line_count: 2
                    total_quantity: 5
                    requested_shipping_method: UPS Ground
                    integration_matches_anchor: true
                    already_in_group: false
                    ship_by_date: '2026-07-01T00:00:00.000000Z'
                    hold_until_date: '2026-06-28T00:00:00.000000Z'
                    deliver_by_date: '2026-07-05T00:00:00.000000Z'
                  - fulfillment_order_id: 453
                    sales_order_id: 125
                    sales_order_number: GML430902
                    customer_name: Jane Doe
                    integration_instance_name: Acme Amazon US
                    integration_instance_id: 7
                    line_count: 1
                    total_quantity: 1
                    requested_shipping_method: null
                    integration_matches_anchor: false
                    already_in_group: false
                    ship_by_date: null
                    hold_until_date: null
                    deliver_by_date: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:read
      operationId: get-api-fulfillment-orders-fulfillmentorder-merge-candidates
  /api/fulfillment-orders/{fulfillmentOrder}/post-submission-merge-candidates:
    get:
      tags:
      - Fulfillment Orders
      summary: List Post-Submission Merge Candidates
      description: "Returns sibling fulfillment orders on OTHER sales orders that\
        \ this ALREADY-DISPATCHED fulfillment order could still be merged with at\
        \ the shipping provider (post-submission cross-order merge). Same customer/address/warehouse/provider\
        \ consensus as the pre-dispatch merge candidates, but for the window after\
        \ auto-dispatch has already sent the orders to the provider.\n\n:::info[Required\
        \ scope: `orders:read`]\nGrant this scope to your token under [Settings →\
        \ Developer → Personal Access Tokens](https://app.sku.io/settings/api).\n\
        :::\n\n**Eligibility** — a candidate is included only if it (and the anchor):\n\
        - Is `status=open` and `request_status` in {`submitted`, `accepted`, `acknowledged`}\
        \ (handed to the provider, awaiting tracking).\n- Belongs to a sales order\
        \ that is NOT cancelled.\n- Is at the SAME warehouse, resolves to the SAME\
        \ provider type + requested integration instance, and is NOT FBA-routed.\n\
        - Ships to the SAME shipping-address signature as the anchor, and is on a\
        \ DIFFERENT sales order (ungrouped or already in the anchor's merge group).\n\
        \nIf the anchor is itself ineligible (not in the post-submission window, FBA,\
        \ cancelled order, or no shipping address) an empty list is returned.\n\n\
        **Response shape** — `data[]` is an array of merge candidates. Same fields\
        \ as the pre-dispatch merge candidates, plus a provider-side verdict:\n- `provider_eligibility`\
        \ (object) — whether the candidate can still be cancelled/merged at its provider:\n\
        \  - `eligible` (bool) — `false` when the provider order has already shipped\
        \ or been cancelled.\n  - `reason` (string | null) — human-facing explanation\
        \ shown when ineligible.\n  - `requires_label_void` (bool) — `true` when a\
        \ shipping label must be voided before the order becomes mutable again.\n\n\
        This is a conservative list-level read of each candidate's locally-synced\
        \ provider order; the precise, live per-provider \"too far gone\" check runs\
        \ immediately before the merge is executed."
      parameters:
      - name: fulfillmentOrder
        in: path
        schema:
          type: integer
        required: true
        description: Anchor FulfillmentOrder ID — the already-dispatched FO to find
          post-submission merge candidates for.
        example: '451'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        fulfillment_order_id:
                          type: integer
                        sales_order_id:
                          type: integer
                        sales_order_number:
                          type: string
                        customer_name:
                          type: string
                        integration_instance_name:
                          type: string
                        integration_instance_id:
                          type: integer
                        line_count:
                          type: integer
                        total_quantity:
                          type: integer
                        requested_shipping_method:
                          type: string
                        integration_matches_anchor:
                          type: boolean
                        already_in_group:
                          type: boolean
                        ship_by_date:
                          type: string
                        hold_until_date:
                          type: string
                          nullable: true
                        deliver_by_date:
                          type: string
                          nullable: true
                        provider_eligibility:
                          type: object
                          properties:
                            eligible:
                              type: boolean
                            reason:
                              type: string
                              nullable: true
                            requires_label_void:
                              type: boolean
                example:
                  data:
                  - fulfillment_order_id: 462
                    sales_order_id: 1055
                    sales_order_number: SO-1055
                    customer_name: Acme Retail
                    integration_instance_name: Shopify — Main Store
                    integration_instance_id: 12
                    line_count: 2
                    total_quantity: 5
                    requested_shipping_method: Standard
                    integration_matches_anchor: true
                    already_in_group: false
                    ship_by_date: '2026-07-09T00:00:00.000000Z'
                    hold_until_date: null
                    deliver_by_date: null
                    provider_eligibility:
                      eligible: true
                      reason: null
                      requires_label_void: false
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:read
      operationId: get-api-fulfillment-orders-fulfillmentorder-post-submission-merge-candidates
  /api/fulfillment-orders/merge-provider/preflight:
    post:
      tags:
      - Fulfillment Orders
      summary: Preflight Post-Submission Merge
      description: 'Returns the read-only PLAN for merging two or more already-dispatched
        fulfillment orders into one provider order (post-submission cross-order merge).
        No provider call and no data is changed — this is the plan the operator confirms
        before the merge runs.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        **Body**

        - `fulfillment_order_ids` (int[], required, min 2) — the already-dispatched
        fulfillment orders to merge.

        - `primary_fulfillment_order_id` (int, optional) — the order to keep as the
        master (it receives the others'' lines). Defaults to the order with the most
        lines.


        **Response** — a plan object:

        - `primary_fulfillment_order_id` (int) — the master.

        - `provider` (string | null) — the resolved shipping provider.

        - `warehouse_id` (int | null).

        - `can_execute` (bool) — true only when there are no blockers and at least
        two eligible members (including the master).

        - `blockers` (string[]) — whole-plan problems (different warehouses, providers,
        or addresses) that no per-order exclusion can fix.

        - `members[]` — one per order: `fulfillment_order_id`, `sales_order_id`, `sales_order_number`,
        `role` (`master` | `absorbed`), `action` (`receive_lines` | `cancel`), `line_count`,
        `eligible` (bool), `reason` (string | null), `requires_label_void` (bool),
        `provider_order_reference` (string | null), `provider_status` (string | null).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                fulfillment_order_ids:
                  type: array
                  items:
                    type: integer
                primary_fulfillment_order_id:
                  type: integer
              example:
                fulfillment_order_ids:
                - 451
                - 462
                primary_fulfillment_order_id: 451
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      primary_fulfillment_order_id:
                        type: integer
                      provider:
                        type: string
                      warehouse_id:
                        type: integer
                      can_execute:
                        type: boolean
                      blockers:
                        type: array
                      members:
                        type: array
                        items:
                          type: object
                          properties:
                            fulfillment_order_id:
                              type: integer
                            sales_order_id:
                              type: integer
                            sales_order_number:
                              type: string
                            role:
                              type: string
                            action:
                              type: string
                            line_count:
                              type: integer
                            eligible:
                              type: boolean
                            reason:
                              type: string
                              nullable: true
                            requires_label_void:
                              type: boolean
                            provider_order_reference:
                              type: string
                            provider_status:
                              type: string
                example:
                  data:
                    primary_fulfillment_order_id: 451
                    provider: shipstation
                    warehouse_id: 7
                    can_execute: true
                    blockers: []
                    members:
                    - fulfillment_order_id: 451
                      sales_order_id: 1042
                      sales_order_number: SO-1042
                      role: master
                      action: receive_lines
                      line_count: 3
                      eligible: true
                      reason: null
                      requires_label_void: false
                      provider_order_reference: SO-1042
                      provider_status: Awaiting Shipment
                    - fulfillment_order_id: 462
                      sales_order_id: 1055
                      sales_order_number: SO-1055
                      role: absorbed
                      action: cancel
                      line_count: 2
                      eligible: true
                      reason: null
                      requires_label_void: false
                      provider_order_reference: SO-1055
                      provider_status: Awaiting Shipment
        '422':
          description: Unprocessable Content
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      fulfillment_order_ids:
                        type: array
                        items:
                          type: string
                example:
                  message: Select at least two fulfillment orders to merge.
                  errors:
                    fulfillment_order_ids:
                    - Select at least two fulfillment orders to merge.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: orders:write
      operationId: post-api-fulfillment-orders-merge-provider-preflight
  /api/fulfillment-orders/merge-provider/execute:
    post:
      tags:
      - Fulfillment Orders
      summary: Execute Post-Submission Merge
      description: 'Runs a post-submission cross-order merge for already-dispatched
        fulfillment orders. The plan is re-validated first; if it can still run, a
        background job cancels the absorbed orders at the shipping provider, adds
        their items to the master order, and then records the merge in SKU (each sales
        order keeps its own tracking). Returns a job handle to track progress.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        **Body**

        - `fulfillment_order_ids` (int[], required, min 2) — the orders to merge.

        - `primary_fulfillment_order_id` (int, required) — the order that survives
        as the master (it receives the others'' items).

        - `acknowledge_label_voids` (bool, optional) — set true to confirm any labels
        that must be voided first.


        **Responses**

        - `202 Accepted` — `data.tracked_job_log_id` to poll/subscribe on.

        - `422` — the merge can''t run; `blockers` lists why.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                fulfillment_order_ids:
                  type: array
                  items:
                    type: integer
                primary_fulfillment_order_id:
                  type: integer
                acknowledge_label_voids:
                  type: boolean
              example:
                fulfillment_order_ids:
                - 451
                - 462
                primary_fulfillment_order_id: 451
                acknowledge_label_voids: false
      parameters: []
      responses:
        '202':
          description: Accepted
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 90321
                  message: Merge started
        '422':
          description: Unprocessable Content
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                  blockers:
                    type: array
                    items:
                      type: string
                example:
                  error: This merge can’t run yet — resolve the highlighted issues
                    and try again.
                  blockers:
                  - Fulfillment orders must ship to the same address to be merged
                    into one shipment.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: orders:write
      operationId: post-api-fulfillment-orders-merge-provider-execute
  /api/fulfillment-orders/{fulfillmentOrder}/merge:
    post:
      tags:
      - Fulfillment Orders
      summary: Merge Fulfillment Orders
      description: 'Fold a sibling fulfillment order (`source_fulfillment_order_id`)
        INTO the route FO (the target). The source''s lines are merged into the target
        per sales order line, the emptied source FO is deleted, and the target is
        returned. One fulfillment order → one submission → one shipment.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        **Mutability gate.** Both FOs must be `status=open` AND `request_status` in
        {`unsubmitted`, `rejected`}, at the SAME warehouse, on the SAME sales order.
        Violations return 409 (not mutable) or 422 (different warehouse / different
        sales order / self-merge).


        **Body fields:**

        - `source_fulfillment_order_id` (required, integer, must exist) — the FO to
        merge in and remove.

        - `requested_shipping_method_id` (optional, integer, nullable) — resolved
        shipping method id (overwrites the target''s).

        - `requested_shipping_method` (optional, string, nullable) — resolved shipping
        method label.

        - `requested_ship_date` (optional, date, nullable) — resolved requested ship
        date.

        - `requested_metadata` (optional, object, nullable) — resolved provider metadata;
        REPLACES the target''s metadata wholesale, so send the complete merged object.
        Allowed keys: `notes`, `fulfillment_sequence`, `signature_required`, `veracore_packing_slip_comments`,
        `veracore_shipping_comments`, `veracore_third_party_type` (1–3), `veracore_third_party_account_number`,
        `isInsured`, `instructionsForWarehouse`.


        The resolved-shipping fields are the CONFLICT RESOLUTION chosen in the merge
        dialog — omit them entirely to keep the target''s existing shipping details.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                source_fulfillment_order_id:
                  type: integer
                requested_shipping_method:
                  type: string
                requested_metadata:
                  type: object
                  properties:
                    signature_required:
                      type: boolean
                    notes:
                      type: string
              example:
                source_fulfillment_order_id: 452
                requested_shipping_method: UPS Ground
                requested_metadata:
                  signature_required: true
                  notes: Combined into a single shipment
      parameters:
      - name: fulfillmentOrder
        in: path
        schema:
          type: integer
        required: true
        description: Target FulfillmentOrder ID — the FO the source is folded INTO
          (kept).
        example: '451'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      sales_order_id:
                        type: integer
                      warehouse_id:
                        type: integer
                      status:
                        type: string
                      request_status:
                        type: string
                      is_stuck_submitting:
                        type: boolean
                      is_pickup:
                        type: boolean
                      external_id:
                        type: string
                        nullable: true
                      external_type:
                        type: string
                        nullable: true
                      integration_instance_id:
                        type: string
                        nullable: true
                      requested_shipping_method_id:
                        type: string
                        nullable: true
                      requested_shipping_method:
                        type: string
                      requested_ship_date:
                        type: string
                        nullable: true
                      requested_metadata:
                        type: object
                        properties:
                          signature_required:
                            type: boolean
                          notes:
                            type: string
                      submitted_at:
                        type: string
                        nullable: true
                      accepted_at:
                        type: string
                        nullable: true
                      closed_at:
                        type: string
                        nullable: true
                      cancelled_at:
                        type: string
                        nullable: true
                      rejection_reason:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            fulfillment_order_id:
                              type: integer
                            sales_order_line_id:
                              type: integer
                            quantity:
                              type: integer
                            remaining_quantity:
                              type: integer
                            created_at:
                              type: string
                            updated_at:
                              type: string
                      warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          type:
                            type: string
                          order_fulfillment:
                            type: string
                          supplier_id:
                            type: string
                            nullable: true
                          supplier_name:
                            type: string
                            nullable: true
                example:
                  data:
                    id: 451
                    sales_order_id: 123
                    warehouse_id: 9
                    status: open
                    request_status: unsubmitted
                    is_stuck_submitting: false
                    is_pickup: false
                    external_id: null
                    external_type: null
                    integration_instance_id: null
                    requested_shipping_method_id: null
                    requested_shipping_method: UPS Ground
                    requested_ship_date: null
                    requested_metadata:
                      signature_required: true
                      notes: Combined into a single shipment
                    submitted_at: null
                    accepted_at: null
                    closed_at: null
                    cancelled_at: null
                    rejection_reason: null
                    created_at: '2026-05-26T10:15:00+00:00'
                    updated_at: '2026-05-26T10:22:00+00:00'
                    lines:
                    - id: 901
                      fulfillment_order_id: 451
                      sales_order_line_id: 55347
                      quantity: 5
                      remaining_quantity: 5
                      created_at: '2026-05-26T10:15:00+00:00'
                      updated_at: '2026-05-26T10:22:00+00:00'
                    warehouse:
                      id: 9
                      name: 3PL Atlanta
                      type: 3pl
                      order_fulfillment: starshipit
                      supplier_id: null
                      supplier_name: null
        '409':
          description: Conflict
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: 'FulfillmentOrder #452 cannot be merged: status=open, request_status=submitted.
                    Only open + unsubmitted/rejected FOs at the same warehouse are
                    mergeable.'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: Fulfillment orders at different warehouses cannot be merged
                    — move one first.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:write
      operationId: post-api-fulfillment-orders-fulfillmentorder-merge
  /api/fulfillment-orders/{fulfillmentOrder}/activity-log:
    get:
      tags:
      - Fulfillment Orders
      summary: Get Fulfillment Order Activity Log
      description: 'Paginated audit trail for a single fulfillment order — created,
        warehouse move, shipping-method change, submit, merge, cancel — newest first.
        The same events also roll up onto the parent sales order''s Activity tab (`GET
        /api/v2/sales-orders/{salesOrder}/activity-log`).


        :::info[Required scope: `orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        **Query params (all optional):**

        - `per_page` (integer, default 15)

        - `filter[search]` (string) — searches causer name / event / property changes

        - `filter[event]` (string) — exact event match (created, updated, deleted)

        - `filter[source]` (string) — matches `properties.source`'
      parameters:
      - name: fulfillmentOrder
        in: path
        schema:
          type: integer
        required: true
        description: FulfillmentOrder ID
        example: '451'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        description:
                          type: string
                        event:
                          type: string
                        subject_type:
                          type: string
                        subject_id:
                          type: integer
                        properties:
                          type: object
                          properties:
                            attributes:
                              type: object
                              properties:
                                requested_shipping_method_id:
                                  type: integer
                                requested_shipping_method:
                                  type: string
                            old:
                              type: object
                              properties:
                                requested_shipping_method_id:
                                  type: integer
                                requested_shipping_method:
                                  type: string
                        causer_name:
                          type: string
                        created_at:
                          type: string
                  current_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  last_page:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - id: 88231
                    description: updated
                    event: updated
                    subject_type: FulfillmentOrder
                    subject_id: 451
                    properties:
                      attributes:
                        requested_shipping_method_id: 9
                        requested_shipping_method: UPS Ground
                      old:
                        requested_shipping_method_id: 4
                        requested_shipping_method: USPS Priority
                    causer_name: Kalvin Mizzi
                    created_at: '2026-06-02T10:22:00+00:00'
                  - id: 88210
                    description: created
                    event: created
                    subject_type: FulfillmentOrder
                    subject_id: 451
                    properties:
                      attributes:
                        sales_order_id: 123
                        warehouse_id: 9
                        status: open
                        request_status: unsubmitted
                    causer_name: null
                    created_at: '2026-06-02T10:15:00+00:00'
                  current_page: 1
                  per_page: 15
                  total: 2
                  last_page: 1
                  from: 1
                  to: 2
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:read
      operationId: get-api-fulfillment-orders-fulfillmentorder-activity-log
  /api/fulfillment-orders/{fulfillmentOrder}/shipping:
    patch:
      tags:
      - Fulfillment Orders
      summary: Edit Fulfillment Order Shipping Details
      description: 'Edit the **requested** shipping params on a proforma fulfillment
        order before it is submitted — the shipping method, requested ship date, and
        provider-specific metadata (e.g. notes). These travel with the FO into the
        submission payload.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        **Mutability gate.** Allowed ONLY while the FO is `status=open` AND `request_status`
        is `unsubmitted` or `rejected` (i.e. not yet successfully sent). Once submitting/accepted
        the carrier owns the values, so edits return **409**.


        **Body fields (all optional — `sometimes`; only the keys present are written):**

        - `requested_shipping_method_id` (nullable, integer, must exist in `shipping_methods`)
        — the chosen shipping method.

        - `requested_shipping_method` (nullable, string, max 255) — free-text method
        label (used when no method id applies / provider-specific).

        - `requested_ship_date` (nullable, date) — requested dispatch date.

        - `requested_metadata` (nullable, object) — free-form, provider-varying values.
        Only the keys the active provider owns are written; on submission they are
        bridged onto the SalesOrderFulfillment metadata the carrier dispatchers read.

        - `requested_metadata.notes` (nullable, string, max 2000) — fulfillment notes
        for the provider.

        - `requested_metadata.signature_required` (nullable, boolean) — signature
        on delivery (Starshipit / ShipHero / ShipMyOrders / ShipFusion). Aliased to
        `isSignatureRequired` for ShipHero & ShipMyOrders when bridged onto the fulfillment.

        - `requested_metadata.veracore_packing_slip_comments` (nullable, string, max
        500) — Veracore packing-slip comments.

        - `requested_metadata.veracore_shipping_comments` (nullable, string, max 500)
        — Veracore shipping comments.

        - `requested_metadata.veracore_third_party_type` (nullable, integer, in 1,2,3)
        — Veracore third-party billing type.

        - `requested_metadata.veracore_third_party_account_number` (nullable, string,
        max 100) — Veracore third-party account number.

        - `requested_metadata.isInsured` (nullable, boolean) — ShipMyOrders insured
        flag.

        - `requested_metadata.instructionsForWarehouse` (nullable, string, max 500)
        — ShipMyOrders warehouse instructions.

        - `requested_metadata.fulfillment_sequence` (nullable, integer, min 1) — backup
        override for the postfix pushed to the provider as the order number (`{sales_order_number}.{sequence}`).
        Omit/null to auto-assign the next sequence at submit. The current default
        is exposed on the fulfillment order object as `next_fulfillment_sequence`.

        - `requested_integration_instance_id` (nullable, integer, must exist in `integration_instances`
        AND be a SHIPPING_PROVIDER instance) — per-FO shipping-provider override;
        null = use the warehouse default.

        - `requested_fulfillment_type` (nullable, string, in: `manual`) — per-FO "force
        Manual" override.


        **Click & Collect (pickup) lock.** When the order''s effective shipping method
        is a pickup method (`is_pickup`), it is collected in person and is never dispatched
        — so a `requested_integration_instance_id` (carrier) or `requested_fulfillment_type=manual`
        override is **rejected with 422**. The lock is keyed on the RESULTING method:
        passing a non-pickup `requested_shipping_method_id` in the SAME request releases
        the lock (the resource then reports `is_pickup=false`).


        Returns the updated fulfillment order object (which includes `next_fulfillment_sequence`
        and `is_pickup`).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                requested_shipping_method_id:
                  type: integer
                requested_shipping_method:
                  type: string
                requested_ship_date:
                  type: string
                requested_metadata:
                  type: object
                  properties:
                    notes:
                      type: string
                    signature_required:
                      type: boolean
                    veracore_packing_slip_comments:
                      type: string
                    veracore_shipping_comments:
                      type: string
                    veracore_third_party_type:
                      type: integer
                    veracore_third_party_account_number:
                      type: string
                    isInsured:
                      type: boolean
                    instructionsForWarehouse:
                      type: string
                    fulfillment_sequence:
                      type: integer
              example:
                requested_shipping_method_id: 12
                requested_shipping_method: Starshipit Express
                requested_ship_date: '2026-06-02'
                requested_metadata:
                  notes: Leave at the side door.
                  signature_required: true
                  veracore_packing_slip_comments: Fragile
                  veracore_shipping_comments: ''
                  veracore_third_party_type: 2
                  veracore_third_party_account_number: ACME-123
                  isInsured: true
                  instructionsForWarehouse: Gift wrap
                  fulfillment_sequence: 2
      parameters:
      - name: fulfillmentOrder
        in: path
        schema:
          type: integer
        required: true
        description: FulfillmentOrder ID
        example: '451'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      sales_order_id:
                        type: integer
                      sales_order_number:
                        type: string
                      warehouse_id:
                        type: integer
                      status:
                        type: string
                      request_status:
                        type: string
                      is_stuck_submitting:
                        type: boolean
                      is_pickup:
                        type: boolean
                      external_id:
                        type: string
                        nullable: true
                      external_type:
                        type: string
                        nullable: true
                      integration_instance_id:
                        type: string
                        nullable: true
                      requested_shipping_method_id:
                        type: integer
                      requested_shipping_method:
                        type: string
                      requested_ship_date:
                        type: string
                      requested_metadata:
                        type: object
                        properties:
                          notes:
                            type: string
                      next_fulfillment_sequence:
                        type: integer
                      submitted_at:
                        type: string
                        nullable: true
                      accepted_at:
                        type: string
                        nullable: true
                      closed_at:
                        type: string
                        nullable: true
                      cancelled_at:
                        type: string
                        nullable: true
                      rejection_reason:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            fulfillment_order_id:
                              type: integer
                            sales_order_line_id:
                              type: integer
                            quantity:
                              type: integer
                            remaining_quantity:
                              type: integer
                      warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          type:
                            type: string
                          order_fulfillment:
                            type: string
                          supplier_id:
                            type: string
                            nullable: true
                          supplier_name:
                            type: string
                            nullable: true
                example:
                  data:
                    id: 451
                    sales_order_id: 123
                    sales_order_number: SO-0123
                    warehouse_id: 9
                    status: open
                    request_status: unsubmitted
                    is_stuck_submitting: false
                    is_pickup: false
                    external_id: null
                    external_type: null
                    integration_instance_id: null
                    requested_shipping_method_id: 12
                    requested_shipping_method: Starshipit Express
                    requested_ship_date: '2026-06-02T00:00:00+00:00'
                    requested_metadata:
                      notes: Leave at the side door.
                    next_fulfillment_sequence: 1
                    submitted_at: null
                    accepted_at: null
                    closed_at: null
                    cancelled_at: null
                    rejection_reason: null
                    created_at: '2026-05-26T10:15:00+00:00'
                    updated_at: '2026-05-31T18:40:00+00:00'
                    lines:
                    - id: 901
                      fulfillment_order_id: 451
                      sales_order_line_id: 55347
                      quantity: 3
                      remaining_quantity: 3
                    warehouse:
                      id: 9
                      name: Default Warehouse
                      type: standard
                      order_fulfillment: starshipit
                      supplier_id: null
                      supplier_name: null
        '409':
          description: Conflict
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: 'FulfillmentOrder #451 shipping details cannot be edited:
                    status=open, request_status=submitting. Requested shipping is
                    editable only before the order is successfully submitted (open
                    + unsubmitted/rejected).'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 422 Validation Error
                  value:
                    message: The selected requested shipping method id is invalid.
                    errors:
                      requested_shipping_method_id:
                      - The selected requested shipping method id is invalid.
                example-1:
                  summary: 422 Click & Collect Lock
                  value:
                    message: This is a Click & Collect (pickup) order and cannot be
                      fulfilled manually. Change the shipping method to a delivery
                      method first.
                    errors:
                      requested_fulfillment_type:
                      - This is a Click & Collect (pickup) order and cannot be fulfilled
                        manually. Change the shipping method to a delivery method
                        first.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:write
      operationId: patch-api-fulfillment-orders-fulfillmentorder-shipping
  /api/fulfillment-orders/{fulfillmentOrder}/record-shipment:
    post:
      tags:
      - Fulfillment Orders
      summary: Record Shipment
      description: 'Record a REAL shipment (one SalesOrderFulfillment) against this
        fulfillment order — the operator fallback for the intent/execution split.
        A fulfillment order is the provider''s order; shipments come back as 1..N
        SalesOrderFulfillments over time.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Body:

        - `lines` (optional array): per-line shipped quantities `{sales_order_line_id,
        quantity}`. OMIT to ship the full remaining_quantity of every line. Each quantity
        is clamped to the line''s remaining_quantity.

        - `tracking_number` (optional), `carrier` (optional), `shipping_method` (optional).

        - `shipped_at` (optional date, Y-m-d): the provider''s actual shipped date
        — becomes the SOF fulfilled_at / COGS accounting date (defaults to today if
        omitted).

        - `provider_shipment_id` (optional): the provider''s shipment identifier —
        idempotent dedup (a re-recorded id never duplicates the SOF).


        Side effects: creates the SalesOrderFulfillment (+ inventory movements, COGS,
        fulfilled_quantity), decrements each line''s remaining_quantity, and advances
        the FO lifecycle: Open → Closed (fully shipped). A partially-shipped FO stays
        `open` with `remaining_quantity` > 0 on its lines — the separate in_progress
        / incomplete partial-shipped statuses were retired in rung 3.


        Returns the FO with its updated lines + shipments. 422 if there is nothing
        left to ship or the report exceeds remaining quantity.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                lines:
                  type: array
                  items:
                    type: object
                    properties:
                      sales_order_line_id:
                        type: integer
                      quantity:
                        type: integer
                tracking_number:
                  type: string
                carrier:
                  type: string
                shipping_method:
                  type: string
                shipped_at:
                  type: string
                provider_shipment_id:
                  type: string
              example:
                lines:
                - sales_order_line_id: 14
                  quantity: 1
                tracking_number: 1Z999AA10123456784
                carrier: UPS
                shipping_method: UPS Ground
                shipped_at: '2026-06-03'
                provider_shipment_id: SHP-7781
      parameters:
      - name: fulfillmentOrder
        in: path
        schema:
          type: integer
        required: true
        description: Fulfillment order id
        example: '6'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      sales_order_id:
                        type: integer
                      sales_order_number:
                        type: string
                      warehouse_id:
                        type: integer
                      status:
                        type: string
                      status_label:
                        type: string
                      request_status:
                        type: string
                      provider_order_link:
                        type: string
                        nullable: true
                      is_stuck_submitting:
                        type: boolean
                      is_pickup:
                        type: boolean
                      requested_shipping_method:
                        type: string
                      requested_shipping_method_id:
                        type: integer
                      requested_ship_date:
                        type: string
                        nullable: true
                      rejection_reason:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            fulfillment_order_id:
                              type: integer
                            sales_order_line_id:
                              type: integer
                            quantity:
                              type: integer
                            remaining_quantity:
                              type: integer
                            sku:
                              type: string
                            name:
                              type: string
                            product_id:
                              type: integer
                      fulfillments:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            number:
                              type: string
                            status:
                              type: string
                            fulfillment_sequence:
                              type: integer
                      warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          type:
                            type: string
                          order_fulfillment:
                            type: string
                          supplier_id:
                            type: string
                            nullable: true
                          supplier_name:
                            type: string
                            nullable: true
                example:
                  data:
                    id: 6
                    sales_order_id: 1
                    sales_order_number: SO-0001
                    warehouse_id: 1
                    status: open
                    status_label: Open
                    request_status: submitted
                    provider_order_link: null
                    is_stuck_submitting: false
                    is_pickup: false
                    requested_shipping_method: UPS Ground
                    requested_shipping_method_id: 12
                    requested_ship_date: null
                    rejection_reason: null
                    created_at: '2026-06-02T20:43:00+00:00'
                    updated_at: '2026-06-03T14:10:00+00:00'
                    lines:
                    - id: 9
                      fulfillment_order_id: 6
                      sales_order_line_id: 14
                      quantity: 2
                      remaining_quantity: 1
                      sku: abc
                      name: abc desc
                      product_id: 3
                    fulfillments:
                    - id: 21
                      number: SO-0001.1
                      status: fulfilled
                      fulfillment_sequence: 1
                    warehouse:
                      id: 1
                      name: Default Warehouse
                      type: direct
                      order_fulfillment: starshipit
                      supplier_id: null
                      supplier_name: null
        '422':
          description: Unprocessable Content
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: 'FulfillmentOrder #6: no remaining quantity to record a shipment
                    for.'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:write
      operationId: post-api-fulfillment-orders-fulfillmentorder-record-shipment
  /api/fulfillment-orders/{fulfillmentOrder}/accept-discrepancy:
    post:
      tags:
      - Fulfillment Orders
      summary: Accept Fulfillment Order Discrepancy
      description: 'Self-heal a shipping-provider ↔ fulfillment-order line discrepancy.
        Use this when the shipping provider marked the order shipped but one line''s
        product cannot be fulfilled (no on-hand to deduct) — a permanent mismatch
        between what the provider shipped and what can actually leave the warehouse.


        Accepting records a real shipment (with the provider''s tracking) for the
        lines that DID ship and parks the discrepant line so it is never deducted
        from inventory. The provider''s order record is left untouched (it stays the
        source of truth for what the provider believes shipped), and the open discrepancy
        alert is resolved.


        Body:

        - `acknowledged` (required, must be true): explicit confirmation that the
        discrepant line will NOT be deducted from inventory. Any other value returns
        422.


        Side effects: records the SalesOrderFulfillment (+ tracking, inventory movements,
        COGS) for the fulfillable lines, marks the discrepant line out-of-sync (parked),
        stamps who/when accepted, advances the fulfillment order lifecycle, and resolves
        the discrepancy alert.


        Returns the fulfillment order with `discrepancy_accepted_at` / `discrepancy_accepted_by`
        set. 422 if there is no shipped provider order, nothing discrepant to accept,
        or the shipment cannot be recorded.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                acknowledged:
                  type: boolean
              example:
                acknowledged: true
      parameters:
      - name: fulfillmentOrder
        in: path
        schema:
          type: integer
        required: true
        description: Fulfillment order id
        example: '6'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      sales_order_id:
                        type: integer
                      sales_order_number:
                        type: string
                      warehouse_id:
                        type: integer
                      status:
                        type: string
                      status_label:
                        type: string
                      request_status:
                        type: string
                      provider_order_link:
                        type: object
                        properties:
                          link_reference:
                            type: string
                          link_type_label:
                            type: string
                          link_id:
                            type: integer
                          link_route:
                            type: string
                      discrepancy_accepted_at:
                        type: string
                      discrepancy_accepted_by:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      is_pickup:
                        type: boolean
                      requested_shipping_method:
                        type: string
                      requested_ship_date:
                        type: string
                        nullable: true
                      rejection_reason:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            fulfillment_order_id:
                              type: integer
                            sales_order_line_id:
                              type: integer
                            quantity:
                              type: integer
                            remaining_quantity:
                              type: integer
                            sku:
                              type: string
                            name:
                              type: string
                            product_id:
                              type: integer
                      fulfillments:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            number:
                              type: string
                            status:
                              type: string
                            fulfillment_sequence:
                              type: integer
                      warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          type:
                            type: string
                          order_fulfillment:
                            type: string
                          supplier_id:
                            type: string
                            nullable: true
                          supplier_name:
                            type: string
                            nullable: true
                  message:
                    type: string
                example:
                  data:
                    id: 6
                    sales_order_id: 1
                    sales_order_number: SO-0001
                    warehouse_id: 1
                    status: closed
                    status_label: Closed
                    request_status: submitted
                    provider_order_link:
                      link_reference: C636160.1
                      link_type_label: Starshipit Order
                      link_id: 4821
                      link_route: /v2/integrations/starshipit/orders/4821
                    discrepancy_accepted_at: '2026-07-21T13:40:00+00:00'
                    discrepancy_accepted_by:
                      id: 3
                      name: Warehouse Manager
                    is_pickup: false
                    requested_shipping_method: Standard
                    requested_ship_date: null
                    rejection_reason: null
                    created_at: '2026-07-20T09:12:00+00:00'
                    updated_at: '2026-07-21T13:40:00+00:00'
                    lines:
                    - id: 9
                      fulfillment_order_id: 6
                      sales_order_line_id: 14
                      quantity: 1
                      remaining_quantity: 0
                      sku: abc
                      name: In-stock item
                      product_id: 3
                    - id: 10
                      fulfillment_order_id: 6
                      sales_order_line_id: 15
                      quantity: 1
                      remaining_quantity: 1
                      sku: '195093200861'
                      name: Mis-tagged item (parked)
                      product_id: 7
                    fulfillments:
                    - id: 21
                      number: SO-0001.1
                      status: fulfilled
                      fulfillment_sequence: 1
                    warehouse:
                      id: 1
                      name: Default Warehouse
                      type: direct
                      order_fulfillment: starshipit
                      supplier_id: null
                      supplier_name: null
                  message: Discrepancy accepted; tracking processed for the shipped
                    lines.
        '422':
          description: Unprocessable Content
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      acknowledged:
                        type: array
                        items:
                          type: string
                example:
                  message: You must acknowledge that the discrepant line will not
                    be deducted from inventory.
                  errors:
                    acknowledged:
                    - You must acknowledge that the discrepant line will not be deducted
                      from inventory.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-fulfillment-orders-fulfillmentorder-accept-discrepancy
  /api/fulfillment-orders/{fulfillmentOrder}/reopen-discrepancy:
    post:
      tags:
      - Fulfillment Orders
      summary: Reopen Fulfillment Order Discrepancy
      description: 'Reverse a prior discrepancy acceptance and re-open the discrepancy
        alert for a fulfillment order. This clears the accepted stamp (`discrepancy_accepted_at`
        / `discrepancy_accepted_by`) and re-fires the discrepancy alert so the mismatch
        is surfaced again.


        This does NOT reverse an already-recorded shipment — the lines that shipped
        genuinely shipped; it only re-opens the discrepancy state so it can be reviewed
        or accepted again.


        Returns the fulfillment order with the acceptance cleared.


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: fulfillmentOrder
        in: path
        schema:
          type: integer
        required: true
        description: Fulfillment order id
        example: '6'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      sales_order_id:
                        type: integer
                      sales_order_number:
                        type: string
                      warehouse_id:
                        type: integer
                      status:
                        type: string
                      status_label:
                        type: string
                      request_status:
                        type: string
                      discrepancy_accepted_at:
                        type: string
                        nullable: true
                      discrepancy_accepted_by:
                        type: string
                        nullable: true
                      lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            fulfillment_order_id:
                              type: integer
                            sales_order_line_id:
                              type: integer
                            quantity:
                              type: integer
                            remaining_quantity:
                              type: integer
                            sku:
                              type: string
                            name:
                              type: string
                            product_id:
                              type: integer
                  message:
                    type: string
                example:
                  data:
                    id: 6
                    sales_order_id: 1
                    sales_order_number: SO-0001
                    warehouse_id: 1
                    status: open
                    status_label: Open
                    request_status: submitted
                    discrepancy_accepted_at: null
                    discrepancy_accepted_by: null
                    lines:
                    - id: 9
                      fulfillment_order_id: 6
                      sales_order_line_id: 14
                      quantity: 1
                      remaining_quantity: 0
                      sku: abc
                      name: In-stock item
                      product_id: 3
                    - id: 10
                      fulfillment_order_id: 6
                      sales_order_line_id: 15
                      quantity: 1
                      remaining_quantity: 1
                      sku: '195093200861'
                      name: Mis-tagged item (parked)
                      product_id: 7
                  message: Discrepancy re-opened.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-fulfillment-orders-fulfillmentorder-reopen-discrepancy
  /api/fulfillment-orders/list:
    get:
      tags:
      - Fulfillment Orders
      summary: List Fulfillment Orders
      description: 'Paginated, filtered, sorted list of FulfillmentOrders across ALL
        sales orders — the data source for the top-level **Fulfillment Orders** list
        view (a sibling of the Fulfillments table). Distinct from `GET /api/fulfillment-orders`
        (the active dispatch board): this `list` endpoint includes closed/cancelled
        FOs and supports the full filter/sort/paginate surface.


        :::info[Required scope: `orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Each row eager-loads `warehouse`, `salesOrder` (for sales_order_number), `lines.salesOrderLine.product`
        (for the expandable line rows), and the requested shipping method.


        Filters also accept the Advanced-Filters base64 `filter_groups` tree (the
        chips/modal send operator-suffixed keys such as `status.is`, `created_at.between`);
        both flat `filter[col]` and `filter_groups` flow through the same Spatie QueryBuilder
        + GroupedFilterSupport pipeline.


        Returns standard Laravel pagination — items directly under `data[]` (NOT `data.data`).
        Authenticate with a Personal Access Token.


        **New columns (also returned by the dispatch board):** sales_order_date, customer_name,
        sales_channel_name, total_quantity (sum of line quantities), and packing_slip_printed_at
        (when the FO''s packing slip was last printed; null until printed). The customer/sales-channel/sales-order-date
        columns are filterable via the filters above (customer_name / sales_channel_type_name
        already exist), and packing_slip_printed_at is sortable.


        **Shipping method filters:** `filter[shipping_method]` (structured/mapped
        method) and `filter[shipping_method_manual]` (free-text "Manual" method).
        The response exposes `shipping_method` and `shipping_method_manual` accordingly
        - exactly one is populated per FO.


        The response is standard Laravel pagination (items under `data`, plus `current_page`,
        `last_page`, `per_page`, `total`) with one extra top-level key: `unfiltered_total`
        — the count of all fulfillment orders ignoring filters (used to label the
        "All records" option in the export modal).'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        sales_order_id:
                          type: integer
                        sales_order_number:
                          type: string
                        sales_order_date:
                          type: string
                        customer_name:
                          type: string
                        customer_id:
                          type: integer
                        sales_channel_name:
                          type: string
                        integration_name:
                          type: string
                        total_quantity:
                          type: integer
                        packing_slip_printed_at:
                          type: string
                        warehouse_id:
                          type: integer
                        status:
                          type: string
                        request_status:
                          type: string
                        status_label:
                          type: string
                        is_stuck_submitting:
                          type: boolean
                        is_pickup:
                          type: boolean
                        external_id:
                          type: string
                          nullable: true
                        external_type:
                          type: string
                          nullable: true
                        integration_instance_id:
                          type: string
                          nullable: true
                        requested_shipping_method_id:
                          type: integer
                        requested_shipping_method:
                          type: string
                        shipping_method:
                          type: string
                        shipping_method_manual:
                          type: string
                          nullable: true
                        shipping_method_origin:
                          type: string
                        requested_ship_date:
                          type: string
                          nullable: true
                        requested_metadata:
                          type: string
                          nullable: true
                        next_fulfillment_sequence:
                          type: integer
                        submitted_at:
                          type: string
                          nullable: true
                        accepted_at:
                          type: string
                          nullable: true
                        closed_at:
                          type: string
                          nullable: true
                        cancelled_at:
                          type: string
                          nullable: true
                        rejection_reason:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                        updated_at:
                          type: string
                        lines:
                          type: array
                          items:
                            type: object
                            properties:
                              id:
                                type: integer
                              fulfillment_order_id:
                                type: integer
                              sales_order_line_id:
                                type: integer
                              quantity:
                                type: integer
                              remaining_quantity:
                                type: integer
                              sku:
                                type: string
                              name:
                                type: string
                              product_id:
                                type: integer
                              created_at:
                                type: string
                              updated_at:
                                type: string
                        warehouse:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            type:
                              type: string
                            order_fulfillment:
                              type: string
                            supplier_id:
                              type: string
                              nullable: true
                            supplier_name:
                              type: string
                              nullable: true
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                  first_page_url:
                    type: string
                  last_page_url:
                    type: string
                  next_page_url:
                    type: string
                    nullable: true
                  prev_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  links:
                    type: array
                example:
                  data:
                  - id: 6
                    sales_order_id: 1
                    sales_order_number: SO-0001
                    sales_order_date: '2026-06-15T00:00:00+00:00'
                    customer_name: Acme Retail Co.
                    customer_id: 281384
                    sales_channel_name: Shopify
                    integration_name: Curvy AU
                    total_quantity: 5
                    packing_slip_printed_at: '2026-06-16T14:32:10+00:00'
                    warehouse_id: 1
                    status: open
                    request_status: unsubmitted
                    status_label: Open
                    is_stuck_submitting: false
                    is_pickup: false
                    external_id: null
                    external_type: null
                    integration_instance_id: null
                    requested_shipping_method_id: 12
                    requested_shipping_method: UPS Ground
                    shipping_method: UPS Ground
                    shipping_method_manual: null
                    shipping_method_origin: inherited
                    requested_ship_date: null
                    requested_metadata: null
                    next_fulfillment_sequence: 2
                    submitted_at: null
                    accepted_at: null
                    closed_at: null
                    cancelled_at: null
                    rejection_reason: null
                    created_at: '2026-06-02T20:43:00+00:00'
                    updated_at: '2026-06-02T20:43:00+00:00'
                    lines:
                    - id: 9
                      fulfillment_order_id: 6
                      sales_order_line_id: 14
                      quantity: 2
                      remaining_quantity: 2
                      sku: abc
                      name: abc desc
                      product_id: 3
                      created_at: '2026-06-02T20:43:00+00:00'
                      updated_at: '2026-06-02T20:43:00+00:00'
                    warehouse:
                      id: 1
                      name: Default Warehouse
                      type: direct
                      order_fulfillment: starshipit
                      supplier_id: null
                      supplier_name: null
                  current_page: 1
                  last_page: 1
                  per_page: 20
                  total: 1
                  from: 1
                  to: 1
                  first_page_url: '{{protocol}}{{domain}}/api/fulfillment-orders/list?page=1'
                  last_page_url: '{{protocol}}{{domain}}/api/fulfillment-orders/list?page=1'
                  next_page_url: null
                  prev_page_url: null
                  path: '{{protocol}}{{domain}}/api/fulfillment-orders/list'
                  links: []
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: orders:read
      operationId: get-api-fulfillment-orders-list
  /api/fulfillment-orders/{fulfillmentOrder}/line-items:
    get:
      tags:
      - Fulfillment Orders
      summary: Get Fulfillment Order Line Items
      description: 'The FO''s lines (sku / name / product_id / quantity / remaining_quantity)
        for the list view''s lazily-loaded expandable rows. Mirrors the SOF / PO line-items
        endpoints. `quantity` is the FOL budget; `remaining_quantity` is the amount
        still to be fulfilled.


        :::info[Required scope: `orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authenticate with a Personal Access Token.


        **Fulfillability:** each line carries `fulfillable_quantity` and `unfulfillable_quantity`,
        computed against the FulfillmentOrder''s own (intent) warehouse — not the
        SalesOrderLine''s warehouse_id. The warehouse block''s `tracks_inventory`
        flag is false for externally-managed warehouses (Amazon FBA/AWD).'
      parameters:
      - name: fulfillmentOrder
        in: path
        schema:
          type: integer
        required: true
        description: Fulfillment order id
        example: '6'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        fulfillment_order_id:
                          type: integer
                        sales_order_line_id:
                          type: integer
                        quantity:
                          type: integer
                        remaining_quantity:
                          type: integer
                        fulfillable_quantity:
                          type: integer
                        unfulfillable_quantity:
                          type: integer
                        lot_allocation:
                          type: string
                          nullable: true
                        sku:
                          type: string
                        name:
                          type: string
                        product_id:
                          type: integer
                        warehouse_id:
                          type: integer
                        created_at:
                          type: string
                        updated_at:
                          type: string
                example:
                  data:
                  - id: 9
                    fulfillment_order_id: 6
                    sales_order_line_id: 14
                    quantity: 2
                    remaining_quantity: 2
                    fulfillable_quantity: 2
                    unfulfillable_quantity: 0
                    lot_allocation: null
                    sku: abc
                    name: abc desc
                    product_id: 3
                    warehouse_id: 6
                    created_at: '2026-06-02T20:43:00+00:00'
                    updated_at: '2026-06-02T20:43:00+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:read
      operationId: get-api-fulfillment-orders-fulfillmentorder-line-items
  /api/fulfillment-orders/{fulfillmentOrder}/shipping-provider-options:
    get:
      tags:
      - Fulfillment Orders
      summary: Get Shipping Provider Options
      description: 'The shipping-provider options for the Edit Shipping Details picker
        (per-FO provider override). Lists the configured shipping-provider integration
        instances in the tenant PLUS a synthetic Manual option, each with whether
        it''s mapped to this FO''s warehouse (`is_mapped`) and whether it''s the warehouse''s
        preferred default (`is_warehouse_default`). The dialog pre-selects `default_integration_instance_id`.


        :::info[Required scope: `orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        The provider an FO dispatches to is normally the warehouse''s preferred; this
        lets an operator override it per FO. ANY configured shipping provider is selectable
        AND submittable — `is_mapped` merely reflects whether an explicit ShippingProviderWarehouse
        mapping exists and never gates submission (the mapping only informs the default).


        **Click & Collect (pickup) lock.** When the FO''s effective shipping method
        is a pickup method, the response collapses to a single locked option (`default_fulfillment_type
        = pickup`, one option named "Pickup (Click & Collect)") — a pickup order is
        collected in person and is never dispatched to a carrier. Pass `shipping_method_id`
        to preview the options against a not-yet-saved method so the lock engages/releases
        live.


        **Optional query param:** `shipping_method_id` — see above.


        Authenticate with a Personal Access Token.'
      parameters:
      - name: fulfillmentOrder
        in: path
        schema:
          type: integer
        required: true
        description: Fulfillment order id
        example: '6'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      options:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: string
                              nullable: true
                            name:
                              type: string
                            integration_name:
                              type: string
                              nullable: true
                            fulfillment_type:
                              type: string
                            is_mapped:
                              type: boolean
                            is_warehouse_default:
                              type: boolean
                      default_integration_instance_id:
                        type: integer
                example:
                  data:
                    options:
                    - id: null
                      name: Manual
                      integration_name: null
                      fulfillment_type: manual
                      is_mapped: true
                      is_warehouse_default: false
                    - id: 5
                      name: Starshipit — AU
                      integration_name: Starshipit
                      fulfillment_type: starshipit
                      is_mapped: true
                      is_warehouse_default: true
                    - id: 8
                      name: ShipStation — Main
                      integration_name: ShipStation
                      fulfillment_type: shipstation
                      is_mapped: false
                      is_warehouse_default: false
                    default_integration_instance_id: 5
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:read
      operationId: get-api-fulfillment-orders-fulfillmentorder-shipping-provider-options
  /api/fulfillment-orders/bulk-submit:
    post:
      tags:
      - Fulfillment Orders
      summary: Bulk Submit Fulfillment Orders
      description: 'Bulk submitted many FulfillmentOrders at once. Accepts `ids[]`
        (required without apply_to_all; each must exist in fulfillment_orders) OR
        `apply_to_all=true`.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        With `apply_to_all=true` the entire filtered set is resolved server-side from
        the table''s current `filter[...]` / `filter_groups` **query-string** params
        (there is no body `filters` param). FOs not in a submittedable state are **skipped**
        (reported in `skipped[]`, not failed). Returns the acted ids, the skipped
        ids+reasons, and a summary message.


        Authenticate with a Personal Access Token.


        Set `override_partial_dispatch` to true to submit orders that are only partially
        fulfillable even when partial dispatch is disabled. Otherwise such orders
        are returned in `skipped` with a `code` of `partial_dispatch_disabled`.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
                override_partial_dispatch:
                  type: boolean
              example:
                ids:
                - 6
                - 7
                override_partial_dispatch: false
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      submitted:
                        type: array
                        items:
                          type: integer
                      skipped:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            reason:
                              type: string
                  message:
                    type: string
                example:
                  data:
                    submitted:
                    - 6
                    skipped:
                    - id: 7
                      reason: Fulfillment order is not submitted.
                  message: 1 fulfillment order(s) submitted. 1 skipped.
        '422':
          description: Unprocessable Content
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      ids:
                        type: array
                        items:
                          type: string
                example:
                  message: The ids field is required when apply to all is not present.
                  errors:
                    ids:
                    - The ids field is required when apply to all is not present.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: orders:write
      operationId: post-api-fulfillment-orders-bulk-submit
  /api/fulfillment-orders/bulk-cancel:
    post:
      tags:
      - Fulfillment Orders
      summary: Bulk Cancel Fulfillment Orders
      description: 'Bulk cancelled many FulfillmentOrders at once. Accepts `ids[]`
        (required without apply_to_all; each must exist in fulfillment_orders) OR
        `apply_to_all=true`, optional `reason` (string, max 1000) recorded on each
        cancelled FO.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        With `apply_to_all=true` the entire filtered set is resolved server-side from
        the table''s current `filter[...]` / `filter_groups` **query-string** params
        (there is no body `filters` param). FOs not in a cancelledable state are **skipped**
        (reported in `skipped[]`, not failed). Returns the acted ids, the skipped
        ids+reasons, and a summary message.


        Authenticate with a Personal Access Token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
                reason:
                  type: string
              example:
                ids:
                - 6
                - 7
                reason: Customer cancelled
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      cancelled:
                        type: array
                        items:
                          type: integer
                      skipped:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            reason:
                              type: string
                  message:
                    type: string
                example:
                  data:
                    cancelled:
                    - 6
                    skipped:
                    - id: 7
                      reason: Fulfillment order is not cancelled.
                  message: 1 fulfillment order(s) cancelled. 1 skipped.
        '422':
          description: Unprocessable Content
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      ids:
                        type: array
                        items:
                          type: string
                example:
                  message: The ids field is required when apply to all is not present.
                  errors:
                    ids:
                    - The ids field is required when apply to all is not present.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: orders:write
      operationId: post-api-fulfillment-orders-bulk-cancel
  /api/export/fulfillment-orders/packing-slips:
    get:
      tags:
      - Fulfillment Orders
      summary: Print Packing Slips
      description: 'Render (and combine, when several) packing slips for the given
        FulfillmentOrders and return the resulting file URL. The FO is the warehouse
        work package, so its slip lists the FO''s planned line quantities.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Authentication:** Requires Bearer token.


        **Query parameters:**

        - `ids` (required) — comma-separated FulfillmentOrder ids (e.g. `1,2,3`).
        Ids that no longer exist are skipped.

        - `engine` (optional, default `snappy`) — `snappy` renders through the NEW
        PdfTemplate-driven pipeline with fingerprinted `<fo_id>_<fp>.pdf` caching;
        `jasper` keeps the legacy Jasper flow with stable `<fo_id>.pdf` caching.


        Printing stamps `packing_slip_printed_at` on each FO. When multiple slips
        render, they are combined into a single PDF and a `reports` disk URL is returned.


        **Errors:** If the selected engine''s renderer fails, the endpoint returns
        HTTP 500 with a JSON `message` describing which engine failed (details are
        written to the application logs).'
      parameters:
      - name: ids
        in: query
        schema:
          type: integer
        description: Comma-separated FulfillmentOrder ids (required). Slips are rendered
          (and combined when several) and the resulting file URL is returned.
        example: '6'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 Success
                  value:
                    data:
                      file: https://{{domain}}/storage/fulfillment_order_packing_slips/6.pdf
                    status: success
                    message: null
                example-1:
                  summary: 200 No Slips
                  value:
                    data: []
                    status: success
                    message: There are no packing slips for the selected fulfillment
                      orders.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-export-fulfillment-orders-packing-slips
  /api/export/fulfillment-orders/{fulfillmentOrder}/packing-slip/cache-status:
    get:
      tags:
      - Fulfillment Orders
      summary: Get Fulfillment Order Packing Slip Cache Status
      description: 'Report whether a rendered packing-slip PDF is cached for this
        FulfillmentOrder (and when it was generated) so the UI can surface a "cached"
        indicator and offer a one-click clear. Reports the newer of the legacy Jasper
        (`<fo_id>.pdf`) and Snappy (fingerprinted `<fo_id>_<fp>.pdf`) cache entries.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Authentication:** Requires Bearer token.'
      parameters:
      - name: fulfillmentOrder
        in: path
        schema:
          type: integer
        required: true
        description: Fulfillment order ID
        example: '123'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 Cached
                  value:
                    data:
                      cached: true
                      generated_at: '2026-06-23T22:24:20+00:00'
                example-1:
                  summary: 200 Not Cached
                  value:
                    data:
                      cached: false
                      generated_at: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-export-fulfillment-orders-fulfillmentorder-packing-slip-cache-status
  /api/export/fulfillment-orders/{fulfillmentOrder}/packing-slip/cache:
    delete:
      tags:
      - Fulfillment Orders
      summary: Clear Fulfillment Order Packing Slip Cache
      description: 'Operator self-serve: drop the cached packing-slip PDF so the next
        print regenerates from current data. Wipes BOTH engines'' caches — the legacy
        Jasper `<fo_id>.pdf` and every Snappy fingerprinted `<fo_id>_<fp>.pdf`. Idempotent
        — clearing a slip that was never cached is a no-op.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Authentication:** Requires Bearer token.'
      parameters:
      - name: fulfillmentOrder
        in: path
        schema:
          type: integer
        required: true
        description: Fulfillment order ID
        example: '123'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Cached packing slip cleared — the next print will regenerate
                    from current data.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-export-fulfillment-orders-fulfillmentorder-packing-slip-cache
  /api/fulfillment-orders/merge-group:
    post:
      tags:
      - Fulfillment Orders
      summary: Create Fulfillment Order Merge Group
      description: 'Merge two or more pre-dispatch fulfillment orders from DIFFERENT
        sales orders into one merged shipment group. The group dispatches to the shipping
        provider as a single order keyed on the primary member; at ship time each
        member''s sales order records its own fulfillment carrying the shared tracking.
        If one of the given fulfillment orders already belongs to a group, the others
        are added to that group.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Eligibility is enforced server-side: every member must be pre-dispatch (`status=open`,
        `request_status` unsubmitted/rejected), at the same warehouse, for the same
        shipping provider and shipping address. Amazon FBA fulfillment orders can
        never be merged.


        **Body fields:**

        - `fulfillment_order_ids` (required, array of integers, min 2) — the fulfillment
        orders to merge.

        - `primary_fulfillment_order_id` (optional, integer, nullable) — which member''s
        reference the provider order is keyed on; defaults to the first id.


        Returns 201 with the group and its member summaries. 409 when a member is
        no longer mutable (already dispatched); 422 for ineligible combinations.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                fulfillment_order_ids:
                  type: array
                  items:
                    type: integer
                primary_fulfillment_order_id:
                  type: integer
              example:
                fulfillment_order_ids:
                - 451
                - 468
                primary_fulfillment_order_id: 451
      parameters: []
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      primary_fulfillment_order_id:
                        type: integer
                      warehouse_id:
                        type: integer
                      members:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            sales_order_id:
                              type: integer
                            sales_order_number:
                              type: string
                            is_primary:
                              type: boolean
                            status:
                              type: string
                            request_status:
                              type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 31
                    primary_fulfillment_order_id: 451
                    warehouse_id: 7
                    members:
                    - id: 451
                      sales_order_id: 123
                      sales_order_number: SO-000123
                      is_primary: true
                      status: open
                      request_status: unsubmitted
                    - id: 468
                      sales_order_id: 130
                      sales_order_number: SO-000130
                      is_primary: false
                      status: open
                      request_status: unsubmitted
                    created_at: '2026-06-20T14:05:00+00:00'
                    updated_at: '2026-06-20T14:05:00+00:00'
        '409':
          description: Conflict
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: Fulfillment order 468 has already been dispatched and can
                    no longer be merged.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: Fulfillment orders must belong to the same warehouse to be
                    merged.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: orders:write
      operationId: post-api-fulfillment-orders-merge-group
  /api/fulfillment-orders/merge-group/{mergeGroup}:
    delete:
      tags:
      - Fulfillment Orders
      summary: Delete Fulfillment Order Merge Group
      description: 'Dissolve a merged shipment group entirely: every member fulfillment
        order reverts to an independent pre-dispatch fulfillment order. Only allowed
        while the group is still pre-dispatch — once dispatched to the provider the
        group can no longer be dissolved (409).


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Returns 204 No Content on success.


        Authentication: Requires Bearer token.'
      parameters:
      - name: mergeGroup
        in: path
        schema:
          type: integer
        required: true
        description: Merge group ID
        example: '31'
      responses:
        '204':
          description: No Content
          headers:
            Content-Type:
              schema:
                type: string
                example: text/plain
          content:
            text/plain:
              schema:
                type: string
                example: ''
        '409':
          description: Conflict
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: This merged shipment has already been dispatched and can
                    no longer be dissolved.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:write
      operationId: delete-api-fulfillment-orders-merge-group-mergegroup
  /api/fulfillment-orders/{fulfillmentOrder}/unmerge:
    post:
      tags:
      - Fulfillment Orders
      summary: Remove Fulfillment Order from Merge Group
      description: 'Remove this fulfillment order from its merged shipment group (pre-dispatch
        only). If the removal leaves fewer than two members, the whole group dissolves
        automatically.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Returns the fulfillment order with refreshed lines and warehouse. 409 when
        the group has already been dispatched; 422 when the fulfillment order is not
        in a merge group.


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: fulfillmentOrder
        in: path
        schema:
          type: integer
        required: true
        description: Fulfillment order ID to remove from its merge group
        example: '468'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: integer
                  sales_order_id:
                    type: integer
                  warehouse_id:
                    type: integer
                  status:
                    type: string
                  request_status:
                    type: string
                  external_id:
                    type: string
                    nullable: true
                  external_type:
                    type: string
                    nullable: true
                  integration_instance_id:
                    type: string
                    nullable: true
                  effective_fulfillment_provider:
                    type: string
                  effective_integration_instance_name:
                    type: string
                    nullable: true
                  provider_order_link:
                    type: string
                    nullable: true
                  submitted_at:
                    type: string
                    nullable: true
                  accepted_at:
                    type: string
                    nullable: true
                  closed_at:
                    type: string
                    nullable: true
                  cancelled_at:
                    type: string
                    nullable: true
                  rejection_reason:
                    type: string
                    nullable: true
                  created_at:
                    type: string
                  updated_at:
                    type: string
                  lines:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        fulfillment_order_id:
                          type: integer
                        sales_order_line_id:
                          type: integer
                        quantity:
                          type: integer
                        remaining_quantity:
                          type: integer
                        fulfillable_quantity:
                          type: integer
                        unfulfillable_quantity:
                          type: integer
                        executed_quantity:
                          type: integer
                        sales_order_fulfillment_lines:
                          type: array
                        lot_allocation:
                          type: string
                          nullable: true
                        sku:
                          type: string
                        name:
                          type: string
                        product_id:
                          type: integer
                        warehouse_id:
                          type: integer
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  warehouse:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      type:
                        type: string
                      tracks_inventory:
                        type: boolean
                example:
                  id: 451
                  sales_order_id: 123
                  warehouse_id: 7
                  status: open
                  request_status: unsubmitted
                  external_id: null
                  external_type: null
                  integration_instance_id: null
                  effective_fulfillment_provider: manual
                  effective_integration_instance_name: null
                  provider_order_link: null
                  submitted_at: null
                  accepted_at: null
                  closed_at: null
                  cancelled_at: null
                  rejection_reason: null
                  created_at: '2026-05-26T10:15:00+00:00'
                  updated_at: '2026-05-26T10:15:00+00:00'
                  lines:
                  - id: 901
                    fulfillment_order_id: 451
                    sales_order_line_id: 55347
                    quantity: 3
                    remaining_quantity: 3
                    fulfillable_quantity: 3
                    unfulfillable_quantity: 0
                    executed_quantity: 0
                    sales_order_fulfillment_lines: []
                    lot_allocation: null
                    sku: WIDGET-01
                    name: Blue Widget
                    product_id: 88
                    warehouse_id: 7
                    created_at: '2026-05-26T10:15:00+00:00'
                    updated_at: '2026-05-26T10:15:00+00:00'
                  - id: 902
                    fulfillment_order_id: 451
                    sales_order_line_id: 55348
                    quantity: 2
                    remaining_quantity: 1
                    fulfillable_quantity: 1
                    unfulfillable_quantity: 0
                    executed_quantity: 0
                    sales_order_fulfillment_lines: []
                    lot_allocation: null
                    sku: WIDGET-02
                    name: Red Widget
                    product_id: 89
                    warehouse_id: 7
                    created_at: '2026-05-26T10:15:00+00:00'
                    updated_at: '2026-05-26T10:32:00+00:00'
                  warehouse:
                    id: 7
                    name: Main Warehouse
                    type: standard
                    tracks_inventory: true
        '409':
          description: Conflict
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: This merged shipment has already been dispatched and can
                    no longer be changed.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: Fulfillment order 468 is not part of a merged shipment.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:write
      operationId: post-api-fulfillment-orders-fulfillmentorder-unmerge
  /api/fulfillment-orders/{fulfillmentOrder}/sync-from-provider:
    post:
      tags:
      - Fulfillment Orders
      summary: Sync Fulfillment Order from Provider
      description: 'Pull the shipping provider''s latest data for the whole fulfillment
        order and reconcile the shipments it may have produced. An awaiting fulfillment
        order that the provider now reports shipped gets its shipment created; existing
        shipments have their tracking and status refreshed.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        The fulfillment order must already have a registered provider order — 422
        otherwise, and 422 on provider/transport failures.


        **Response fields:** `data` (the refreshed fulfillment order with lines and
        shipments), `message` (summary of what the sync did), `shipment_status` (the
        provider''s reported shipment status), `tracking_pipeline_ran` (whether tracking
        updates were processed).


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: fulfillmentOrder
        in: path
        schema:
          type: integer
        required: true
        description: Fulfillment order ID
        example: '451'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      sales_order_id:
                        type: integer
                      warehouse_id:
                        type: integer
                      status:
                        type: string
                      request_status:
                        type: string
                      external_id:
                        type: string
                        nullable: true
                      external_type:
                        type: string
                        nullable: true
                      integration_instance_id:
                        type: string
                        nullable: true
                      effective_fulfillment_provider:
                        type: string
                      effective_integration_instance_name:
                        type: string
                        nullable: true
                      provider_order_link:
                        type: string
                        nullable: true
                      submitted_at:
                        type: string
                        nullable: true
                      accepted_at:
                        type: string
                        nullable: true
                      closed_at:
                        type: string
                        nullable: true
                      cancelled_at:
                        type: string
                        nullable: true
                      rejection_reason:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            fulfillment_order_id:
                              type: integer
                            sales_order_line_id:
                              type: integer
                            quantity:
                              type: integer
                            remaining_quantity:
                              type: integer
                            fulfillable_quantity:
                              type: integer
                            unfulfillable_quantity:
                              type: integer
                            executed_quantity:
                              type: integer
                            sales_order_fulfillment_lines:
                              type: array
                            lot_allocation:
                              type: string
                              nullable: true
                            sku:
                              type: string
                            name:
                              type: string
                            product_id:
                              type: integer
                            warehouse_id:
                              type: integer
                            created_at:
                              type: string
                            updated_at:
                              type: string
                      warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          type:
                            type: string
                          tracks_inventory:
                            type: boolean
                  message:
                    type: string
                  shipment_status:
                    type: string
                  tracking_pipeline_ran:
                    type: boolean
                example:
                  data:
                    id: 451
                    sales_order_id: 123
                    warehouse_id: 7
                    status: open
                    request_status: unsubmitted
                    external_id: null
                    external_type: null
                    integration_instance_id: null
                    effective_fulfillment_provider: manual
                    effective_integration_instance_name: null
                    provider_order_link: null
                    submitted_at: null
                    accepted_at: null
                    closed_at: null
                    cancelled_at: null
                    rejection_reason: null
                    created_at: '2026-05-26T10:15:00+00:00'
                    updated_at: '2026-05-26T10:15:00+00:00'
                    lines:
                    - id: 901
                      fulfillment_order_id: 451
                      sales_order_line_id: 55347
                      quantity: 3
                      remaining_quantity: 3
                      fulfillable_quantity: 3
                      unfulfillable_quantity: 0
                      executed_quantity: 0
                      sales_order_fulfillment_lines: []
                      lot_allocation: null
                      sku: WIDGET-01
                      name: Blue Widget
                      product_id: 88
                      warehouse_id: 7
                      created_at: '2026-05-26T10:15:00+00:00'
                      updated_at: '2026-05-26T10:15:00+00:00'
                    - id: 902
                      fulfillment_order_id: 451
                      sales_order_line_id: 55348
                      quantity: 2
                      remaining_quantity: 1
                      fulfillable_quantity: 1
                      unfulfillable_quantity: 0
                      executed_quantity: 0
                      sales_order_fulfillment_lines: []
                      lot_allocation: null
                      sku: WIDGET-02
                      name: Red Widget
                      product_id: 89
                      warehouse_id: 7
                      created_at: '2026-05-26T10:15:00+00:00'
                      updated_at: '2026-05-26T10:32:00+00:00'
                    warehouse:
                      id: 7
                      name: Main Warehouse
                      type: standard
                      tracks_inventory: true
                  message: Provider order refreshed; 1 shipment updated.
                  shipment_status: shipped
                  tracking_pipeline_ran: true
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: This fulfillment order has no provider order to sync from
                    yet.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:write
      operationId: post-api-fulfillment-orders-fulfillmentorder-sync-from-provider
  /api/fulfillment-orders/{fulfillmentOrder}/sync-to-provider:
    post:
      tags:
      - Fulfillment Orders
      summary: Sync Fulfillment Order to Provider
      description: 'Push the fulfillment order''s current order-level state (items,
        quantities, customer address) to the shipping provider. When shipments already
        exist each one is reconciled and re-sent; when none exist yet the registered
        provider order is updated in place — the primary use while the order is still
        awaiting fulfillment.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        The fulfillment order must already have a registered provider order — 422
        otherwise, and 422 on provider/transport failures.


        **Response fields:** `data` (the refreshed fulfillment order), `message` (summary),
        `shipments_pushed` (how many provider shipments were re-sent), `awaiting`
        (true when the provider order was updated in place because no shipments exist
        yet).


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: fulfillmentOrder
        in: path
        schema:
          type: integer
        required: true
        description: Fulfillment order ID
        example: '451'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      sales_order_id:
                        type: integer
                      warehouse_id:
                        type: integer
                      status:
                        type: string
                      request_status:
                        type: string
                      external_id:
                        type: string
                        nullable: true
                      external_type:
                        type: string
                        nullable: true
                      integration_instance_id:
                        type: string
                        nullable: true
                      effective_fulfillment_provider:
                        type: string
                      effective_integration_instance_name:
                        type: string
                        nullable: true
                      provider_order_link:
                        type: string
                        nullable: true
                      submitted_at:
                        type: string
                        nullable: true
                      accepted_at:
                        type: string
                        nullable: true
                      closed_at:
                        type: string
                        nullable: true
                      cancelled_at:
                        type: string
                        nullable: true
                      rejection_reason:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            fulfillment_order_id:
                              type: integer
                            sales_order_line_id:
                              type: integer
                            quantity:
                              type: integer
                            remaining_quantity:
                              type: integer
                            fulfillable_quantity:
                              type: integer
                            unfulfillable_quantity:
                              type: integer
                            executed_quantity:
                              type: integer
                            sales_order_fulfillment_lines:
                              type: array
                            lot_allocation:
                              type: string
                              nullable: true
                            sku:
                              type: string
                            name:
                              type: string
                            product_id:
                              type: integer
                            warehouse_id:
                              type: integer
                            created_at:
                              type: string
                            updated_at:
                              type: string
                      warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          type:
                            type: string
                          tracks_inventory:
                            type: boolean
                  message:
                    type: string
                  shipments_pushed:
                    type: integer
                  awaiting:
                    type: boolean
                example:
                  data:
                    id: 451
                    sales_order_id: 123
                    warehouse_id: 7
                    status: open
                    request_status: unsubmitted
                    external_id: null
                    external_type: null
                    integration_instance_id: null
                    effective_fulfillment_provider: manual
                    effective_integration_instance_name: null
                    provider_order_link: null
                    submitted_at: null
                    accepted_at: null
                    closed_at: null
                    cancelled_at: null
                    rejection_reason: null
                    created_at: '2026-05-26T10:15:00+00:00'
                    updated_at: '2026-05-26T10:15:00+00:00'
                    lines:
                    - id: 901
                      fulfillment_order_id: 451
                      sales_order_line_id: 55347
                      quantity: 3
                      remaining_quantity: 3
                      fulfillable_quantity: 3
                      unfulfillable_quantity: 0
                      executed_quantity: 0
                      sales_order_fulfillment_lines: []
                      lot_allocation: null
                      sku: WIDGET-01
                      name: Blue Widget
                      product_id: 88
                      warehouse_id: 7
                      created_at: '2026-05-26T10:15:00+00:00'
                      updated_at: '2026-05-26T10:15:00+00:00'
                    - id: 902
                      fulfillment_order_id: 451
                      sales_order_line_id: 55348
                      quantity: 2
                      remaining_quantity: 1
                      fulfillable_quantity: 1
                      unfulfillable_quantity: 0
                      executed_quantity: 0
                      sales_order_fulfillment_lines: []
                      lot_allocation: null
                      sku: WIDGET-02
                      name: Red Widget
                      product_id: 89
                      warehouse_id: 7
                      created_at: '2026-05-26T10:15:00+00:00'
                      updated_at: '2026-05-26T10:32:00+00:00'
                    warehouse:
                      id: 7
                      name: Main Warehouse
                      type: standard
                      tracks_inventory: true
                  message: Provider order updated in place.
                  shipments_pushed: 0
                  awaiting: true
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: This fulfillment order has no provider order to sync to yet.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:write
      operationId: post-api-fulfillment-orders-fulfillmentorder-sync-to-provider
  /api/fulfillment-orders/{fulfillmentOrder}/apply-line-update:
    post:
      tags:
      - Fulfillment Orders
      summary: Apply Fulfillment Order Line Update
      description: 'Apply a quantity change to a submitted fulfillment order in place.
        When a quantity increase created a separate fulfillment order for the extra
        units, this absorbs that fulfillment order back into this one and pushes the
        enlarged line set to the shipping provider as an update.


        The provider update is attempted first: if the provider rejects it (for example,
        the order can no longer be edited), the change is rolled back and the response
        reports `provider_ineligible` so you can keep the separate fulfillment order
        instead.


        Always returns 200 with an `outcome` of `success` (grown and confirmed by
        the provider), `provider_ineligible` (provider rejected the update; rolled
        back), or `not_update_capable` (no registered provider order, a shipment already
        exists, or the provider has no in-place update). `data` is the refreshed fulfillment
        order and `message` is a human-readable summary.


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: fulfillmentOrder
        in: path
        schema:
          type: integer
        required: true
        description: Fulfillment order ID
        example: '451'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      status:
                        type: string
                      request_status:
                        type: string
                      warehouse_id:
                        type: integer
                      lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            sales_order_line_id:
                              type: integer
                            quantity:
                              type: integer
                            remaining_quantity:
                              type: integer
                  outcome:
                    type: string
                  message:
                    type: string
                example:
                  data:
                    id: 451
                    status: open
                    request_status: submitted
                    warehouse_id: 12
                    lines:
                    - id: 8801
                      sales_order_line_id: 33021
                      quantity: 3
                      remaining_quantity: 3
                  outcome: success
                  message: Odoo 3PL order updated in place.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-fulfillment-orders-fulfillmentorder-apply-line-update
  /api/fulfillment-orders/bulk-sync-from-provider:
    post:
      tags:
      - Fulfillment Orders
      summary: Bulk Sync Fulfillment Orders from Provider
      description: 'Update tracking for many fulfillment orders at once by polling
        each one''s registered provider order. Accepts an explicit `ids` selection,
        or `apply_to_all=true` — in which case the entire filtered set is resolved
        server-side from the request query string''s current `filter[...]` / `filter_groups`
        parameters (the same filters as the fulfillment orders list endpoint). There
        is no body `filters` parameter.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        **This endpoint is asynchronous**: it dispatches a background job and returns
        immediately with a `tracked_job_log_id` that can be used to monitor progress.
        Fulfillment orders with no registered provider order yet are skipped by the
        job rather than rejected here.


        **Body fields:**

        - `ids` (array of integers, required unless `apply_to_all` is true) — fulfillment
        order IDs to sync.

        - `apply_to_all` (optional, boolean) — sync every fulfillment order matching
        the current query-string filters.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 451
                - 468
                - 502
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 9182
                  message: Updating tracking for 3 fulfillment order(s) — track progress
                    in the job tray.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      ids:
                        type: array
                        items:
                          type: string
                example:
                  message: The ids field is required when apply to all is not present.
                  errors:
                    ids:
                    - The ids field is required when apply to all is not present.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: orders:write
      operationId: post-api-fulfillment-orders-bulk-sync-from-provider
  /api/fulfillment-orders/{fulfillmentOrder}/fba-fulfillment-preview:
    get:
      tags:
      - Fulfillment Orders
      summary: Get FBA Fulfillment Preview
      description: 'For a still-unsubmitted Amazon FBA fulfillment order, fetch Amazon''s
        fulfillment preview: one estimate per available shipping speed (fulfillability,
        estimated fees, estimated shipping weight, and the ship/arrival window) WITHOUT
        creating a Multi-Channel Fulfillment order. Use it to compare speeds and costs
        before submitting.


        :::info[Required scope: `orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Returns 422 when the order cannot be previewed — not an FBA order, no shipping
        address, no Amazon marketplace configured for the destination country, or
        no items mapped to an active FBA listing — and when Amazon rejects the call.


        Authentication: Requires Bearer token.'
      parameters:
      - name: fulfillmentOrder
        in: path
        schema:
          type: integer
        required: true
        description: Fulfillment order ID (must be an Amazon FBA order)
        example: '451'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        shipping_speed:
                          type: string
                        is_fulfillable:
                          type: boolean
                        is_cod_capable:
                          type: boolean
                        estimated_fee:
                          type: number
                        currency:
                          type: string
                        fees:
                          type: array
                          items:
                            type: object
                            properties:
                              name:
                                type: string
                              amount:
                                type: number
                              currency:
                                type: string
                        estimated_weight:
                          type: object
                          properties:
                            value:
                              type: number
                            unit:
                              type: string
                        earliest_ship_date:
                          type: string
                        latest_ship_date:
                          type: string
                        earliest_arrival_date:
                          type: string
                        latest_arrival_date:
                          type: string
                        shipment_count:
                          type: integer
                        unfulfillable_reasons:
                          type: array
                example:
                  data:
                  - shipping_speed: Standard
                    is_fulfillable: true
                    is_cod_capable: false
                    estimated_fee: 12.47
                    currency: USD
                    fees:
                    - name: FBAPerUnitFulfillmentFee
                      amount: 10.99
                      currency: USD
                    - name: FBATransportationFee
                      amount: 1.48
                      currency: USD
                    estimated_weight:
                      value: 2.1
                      unit: LB
                    earliest_ship_date: '2026-06-21T07:00:00Z'
                    latest_ship_date: '2026-06-22T07:00:00Z'
                    earliest_arrival_date: '2026-06-25T07:00:00Z'
                    latest_arrival_date: '2026-06-28T07:00:00Z'
                    shipment_count: 1
                    unfulfillable_reasons: []
                  - shipping_speed: Expedited
                    is_fulfillable: true
                    is_cod_capable: false
                    estimated_fee: 15.32
                    currency: USD
                    fees:
                    - name: FBAPerUnitFulfillmentFee
                      amount: 12.99
                      currency: USD
                    - name: FBATransportationFee
                      amount: 2.33
                      currency: USD
                    estimated_weight:
                      value: 2.1
                      unit: LB
                    earliest_ship_date: '2026-06-21T07:00:00Z'
                    latest_ship_date: '2026-06-21T19:00:00Z'
                    earliest_arrival_date: '2026-06-23T07:00:00Z'
                    latest_arrival_date: '2026-06-24T07:00:00Z'
                    shipment_count: 1
                    unfulfillable_reasons: []
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: Fulfillment preview is only available for Amazon FBA fulfillment
                    orders.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:read
      operationId: get-api-fulfillment-orders-fulfillmentorder-fba-fulfillment-preview
  /api/fulfillment-orders/export:
    get:
      tags:
      - Fulfillment Orders
      summary: Export Fulfillment Orders
      description: 'Export the Fulfillment Orders list view as an XLSX or CSV file
        (sibling of the Fulfillments export). Requires a Bearer token.


        The response is a binary file download (not JSON): `Content-Type` is `application/vnd.openxmlformats-officedocument.spreadsheetml.sheet`
        for xlsx or `text/csv` for csv. The filename is `fulfillment-orders-<timestamp>.<ext>`
        (or `fulfillment-orders-detail-<timestamp>.<ext>` in line_items mode).


        **Scope** (`scope`): `all` exports every FO ignoring the table''s filters;
        `filtered` honours the table''s active filters/sort (pass the same `filter[...]`
        / `sort` / `filter[lifecycle]` / `filter[merged]` query params as the list
        endpoint); `current_page` exports just the current page; `selected` exports
        the ids passed in `ids`.


        **Content** (`content_mode`): `summary` = one row per fulfillment order; `line_items`
        = one row per FO line with the fulfillment-order columns repeated (item SKU
        / name / qty / remaining appended).


        **Columns** (`columns`): comma-separated visible list view column keys — only
        those columns are exported, in the given order. Omit to export all columns.


        :::info[Required scope: `orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: format
        in: query
        schema:
          type: string
        description: 'File format: xlsx (default) or csv.'
        example: xlsx
      - name: content_mode
        in: query
        schema:
          type: string
        description: summary (one row per FO, default) or line_items (one row per
          FO line).
        example: summary
      - name: scope
        in: query
        schema:
          type: string
        description: 'Which records to export: all | filtered (default) | current_page
          | selected.'
        example: filtered
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: orders:read
      operationId: get-api-fulfillment-orders-export
  /api/fulfillment-orders/{fulfillmentOrder}/packing-slip-print-events:
    get:
      tags:
      - Fulfillment Orders
      summary: List Fulfillment Order Packing Slip Print Events
      description: 'Newest-first paginated history of every time this fulfillment
        order''s packing slip was printed: who printed it, when, the render engine
        used, a print-time context snapshot (order reference, warehouse, line count),
        and whether an exact copy of the printed PDF is retained (`has_stored_copy`).
        Each event''s exact printed PDF is retrievable via the download endpoint.


        **Authentication:** Requires Bearer token.'
      parameters:
      - name: fulfillmentOrder
        in: path
        schema:
          type: integer
        required: true
        description: Fulfillment order ID
        example: '123'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        printed_at:
                          type: string
                        printed_by:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        printed_by_name:
                          type: string
                        engine:
                          type: string
                        engine_label:
                          type: string
                        trigger:
                          type: string
                        capture_status:
                          type: string
                        has_stored_copy:
                          type: boolean
                        fingerprint:
                          type: string
                        byte_count:
                          type: integer
                        page_count:
                          type: integer
                        order_reference:
                          type: string
                        warehouse_id:
                          type: integer
                        warehouse_name:
                          type: string
                        line_count:
                          type: integer
                        reprint_reason:
                          type: string
                          nullable: true
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                  first_page_url:
                    type: string
                  last_page_url:
                    type: string
                  next_page_url:
                    type: string
                    nullable: true
                  prev_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                example:
                  data:
                  - id: 9012
                    printed_at: '2026-07-23T14:03:11+00:00'
                    printed_by:
                      id: 42
                      name: Warehouse Operator
                    printed_by_name: Warehouse Operator
                    engine: snappy
                    engine_label: New
                    trigger: single
                    capture_status: stored
                    has_stored_copy: true
                    fingerprint: a1b2c3d4
                    byte_count: 48213
                    page_count: 1
                    order_reference: SO-10442
                    warehouse_id: 9
                    warehouse_name: Main DC
                    line_count: 3
                    reprint_reason: null
                  current_page: 1
                  last_page: 1
                  per_page: 10
                  total: 1
                  from: 1
                  to: 1
                  first_page_url: '...'
                  last_page_url: '...'
                  next_page_url: null
                  prev_page_url: null
                  path: '...'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-fulfillment-orders-fulfillmentorder-packing-slip-print-events
  /api/fulfillment-orders/{fulfillmentOrder}/packing-slip-print-events/{packingSlipPrintEvent}/download:
    get:
      tags:
      - Fulfillment Orders
      summary: Download Fulfillment Order Packing Slip Print Copy
      description: 'Return a signed URL to the byte-identical copy of the exact PDF
        that was printed for this event. The stored copy is never re-rendered, so
        it reflects the document exactly as it was printed even if the order has since
        changed. Returns 404 when the event does not belong to this fulfillment order,
        or when no copy was retained for it.


        **Authentication:** Requires Bearer token.'
      parameters:
      - name: fulfillmentOrder
        in: path
        schema:
          type: integer
        required: true
        description: Fulfillment order ID
        example: '123'
      - name: packingSlipPrintEvent
        in: path
        schema:
          type: integer
        required: true
        description: Print event ID
        example: '9012'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      file:
                        type: string
                example:
                  data:
                    file: /tenant-asset/reports/packing_slip_audit/fo/123/02389e97035b.pdf?t=acme
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No stored copy is available for this print event.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-fulfillment-orders-fulfillmentorder-packing-slip-print-events-packingslipprintevent-download
  /api/fulfillment-orders/{fulfillmentOrder}/packing-slip-print-events/{packingSlipPrintEvent}:
    patch:
      tags:
      - Fulfillment Orders
      summary: Update Packing Slip Print Event Reprint Reason
      description: 'Set or clear an optional free-text reason on a packing-slip print
        event (for example, explaining why a slip was reprinted). Pass `reprint_reason`
        as a string (max 255 characters) or null to clear it.


        **Authentication:** Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                reprint_reason:
                  type: string
              example:
                reprint_reason: Printer jam — first copy smeared
      parameters:
      - name: fulfillmentOrder
        in: path
        schema:
          type: integer
        required: true
        description: Fulfillment order ID
        example: '123'
      - name: packingSlipPrintEvent
        in: path
        schema:
          type: integer
        required: true
        description: Print event ID
        example: '9012'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: integer
                  printed_at:
                    type: string
                  printed_by:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                  printed_by_name:
                    type: string
                  engine:
                    type: string
                  engine_label:
                    type: string
                  trigger:
                    type: string
                  capture_status:
                    type: string
                  has_stored_copy:
                    type: boolean
                  fingerprint:
                    type: string
                  byte_count:
                    type: integer
                  page_count:
                    type: integer
                  order_reference:
                    type: string
                  warehouse_id:
                    type: integer
                  warehouse_name:
                    type: string
                  line_count:
                    type: integer
                  reprint_reason:
                    type: string
                example:
                  id: 9012
                  printed_at: '2026-07-23T14:03:11+00:00'
                  printed_by:
                    id: 42
                    name: Warehouse Operator
                  printed_by_name: Warehouse Operator
                  engine: snappy
                  engine_label: New
                  trigger: single
                  capture_status: stored
                  has_stored_copy: true
                  fingerprint: a1b2c3d4
                  byte_count: 48213
                  page_count: 1
                  order_reference: SO-10442
                  warehouse_id: 9
                  warehouse_name: Main DC
                  line_count: 3
                  reprint_reason: Printer jam — first copy smeared
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: patch-api-fulfillment-orders-fulfillmentorder-packing-slip-print-events-packingslipprintevent
  /api/sales-orders/{salesOrder}/lines/{salesOrderLine}/decorations:
    get:
      tags:
      - Line Decorations
      summary: List Line Decorations
      description: 'List all decoration specs for a sales order line. Each spec includes
        the linked artwork summary (`artwork`) and the selected thread/ink colors
        (`colors`).


        :::info[Required scope: `orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: salesOrder
        in: path
        schema:
          type: integer
        required: true
        description: Sales order ID
        example: '501'
      - name: salesOrderLine
        in: path
        schema:
          type: integer
        required: true
        description: Sales order line ID
        example: '3001'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        sales_order_line_id:
                          type: integer
                        method:
                          type: string
                        placement:
                          type: string
                        placement_custom:
                          type: string
                          nullable: true
                        blank_product_id:
                          type: integer
                        artwork:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            digitization_state:
                              type: string
                        colors:
                          type: array
                          items:
                            type: object
                            properties:
                              product_id:
                                type: integer
                              name:
                                type: string
                        stitch_count:
                          type: integer
                        ink_colors_count:
                          type: string
                          nullable: true
                        area_sq_in:
                          type: number
                        setup_type:
                          type: string
                        digitization_required:
                          type: boolean
                        quantity_multiplier:
                          type: integer
                        estimated_cost:
                          type: string
                        estimated_cost_lines:
                          type: array
                          items:
                            type: object
                            properties:
                              id:
                                type: integer
                              sales_order_line_decoration_id:
                                type: integer
                              decoration_cost_rule_id:
                                type: integer
                              cost_category_id:
                                type: integer
                              cost_category_name:
                                type: string
                              amount:
                                type: string
                              is_structural_loss_flag:
                                type: boolean
                        has_structural_loss_flag:
                          type: boolean
                        manufacturing_order_id:
                          type: string
                          nullable: true
                        notes:
                          type: string
                        created_at:
                          type: string
                example:
                  data:
                  - id: 1
                    sales_order_line_id: 3001
                    method: embroidery
                    placement: front_left_chest
                    placement_custom: null
                    blank_product_id: 240
                    artwork:
                      id: 5
                      name: Acme Corp Logo
                      digitization_state: digitized
                    colors:
                    - product_id: 88
                      name: Red Thread
                    stitch_count: 12000
                    ink_colors_count: null
                    area_sq_in: 12.5
                    setup_type: new_setup
                    digitization_required: true
                    quantity_multiplier: 1
                    estimated_cost: '4.50'
                    estimated_cost_lines:
                    - id: 1
                      sales_order_line_decoration_id: 1
                      decoration_cost_rule_id: 7
                      cost_category_id: 42
                      cost_category_name: Decoration Labor
                      amount: '3.60'
                      is_structural_loss_flag: false
                    - id: 2
                      sales_order_line_decoration_id: 1
                      decoration_cost_rule_id: 8
                      cost_category_id: 43
                      cost_category_name: Decoration Consumables
                      amount: '0.90'
                      is_structural_loss_flag: false
                    has_structural_loss_flag: false
                    manufacturing_order_id: null
                    notes: Match thread to PMS 186 C
                    created_at: '2026-06-13T10:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:read
      operationId: get-api-sales-orders-salesorder-lines-salesorderline-decorations
    post:
      tags:
      - Line Decorations
      summary: Add Line Decoration
      description: 'Add a decoration spec to a sales order line.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Required: `method`, `placement`, `setup_type`. `placement_custom` is required
        when `placement` is `custom`. `stitch_count` is required when `method` is
        `embroidery`; `ink_colors_count` is required when `method` is `screen_print`.
        `artwork_id` must reference an existing artwork; `color_product_ids[]` must
        reference existing products. `quantity_multiplier` defaults to 1.


        Requires permission: `sales_orders.update`.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                method:
                  type: string
                placement:
                  type: string
                placement_custom:
                  type: string
                  nullable: true
                blank_product_id:
                  type: integer
                artwork_id:
                  type: integer
                color_product_ids:
                  type: array
                  items:
                    type: integer
                stitch_count:
                  type: integer
                ink_colors_count:
                  type: string
                  nullable: true
                area_sq_in:
                  type: number
                setup_type:
                  type: string
                digitization_required:
                  type: boolean
                quantity_multiplier:
                  type: integer
                estimated_cost:
                  type: number
                notes:
                  type: string
              example:
                method: embroidery
                placement: front_left_chest
                placement_custom: null
                blank_product_id: 240
                artwork_id: 5
                color_product_ids:
                - 88
                stitch_count: 12000
                ink_colors_count: null
                area_sq_in: 12.5
                setup_type: new_setup
                digitization_required: true
                quantity_multiplier: 1
                estimated_cost: 4.5
                notes: Match thread to PMS 186 C
      parameters:
      - name: salesOrder
        in: path
        schema:
          type: integer
        required: true
        description: Sales order ID
        example: '501'
      - name: salesOrderLine
        in: path
        schema:
          type: integer
        required: true
        description: Sales order line ID
        example: '3001'
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      sales_order_line_id:
                        type: integer
                      method:
                        type: string
                      placement:
                        type: string
                      placement_custom:
                        type: string
                        nullable: true
                      blank_product_id:
                        type: integer
                      artwork:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          digitization_state:
                            type: string
                      colors:
                        type: array
                        items:
                          type: object
                          properties:
                            product_id:
                              type: integer
                            name:
                              type: string
                      stitch_count:
                        type: integer
                      ink_colors_count:
                        type: string
                        nullable: true
                      area_sq_in:
                        type: number
                      setup_type:
                        type: string
                      digitization_required:
                        type: boolean
                      quantity_multiplier:
                        type: integer
                      estimated_cost:
                        type: string
                      estimated_cost_lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            sales_order_line_decoration_id:
                              type: integer
                            decoration_cost_rule_id:
                              type: integer
                            cost_category_id:
                              type: integer
                            cost_category_name:
                              type: string
                            amount:
                              type: string
                            is_structural_loss_flag:
                              type: boolean
                      has_structural_loss_flag:
                        type: boolean
                      manufacturing_order_id:
                        type: string
                        nullable: true
                      notes:
                        type: string
                      created_at:
                        type: string
                example:
                  data:
                    id: 1
                    sales_order_line_id: 3001
                    method: embroidery
                    placement: front_left_chest
                    placement_custom: null
                    blank_product_id: 240
                    artwork:
                      id: 5
                      name: Acme Corp Logo
                      digitization_state: digitized
                    colors:
                    - product_id: 88
                      name: Red Thread
                    stitch_count: 12000
                    ink_colors_count: null
                    area_sq_in: 12.5
                    setup_type: new_setup
                    digitization_required: true
                    quantity_multiplier: 1
                    estimated_cost: '4.50'
                    estimated_cost_lines:
                    - id: 1
                      sales_order_line_decoration_id: 1
                      decoration_cost_rule_id: 7
                      cost_category_id: 42
                      cost_category_name: Decoration Labor
                      amount: '3.60'
                      is_structural_loss_flag: false
                    - id: 2
                      sales_order_line_decoration_id: 1
                      decoration_cost_rule_id: 8
                      cost_category_id: 43
                      cost_category_name: Decoration Consumables
                      amount: '0.90'
                      is_structural_loss_flag: false
                    has_structural_loss_flag: false
                    manufacturing_order_id: null
                    notes: Match thread to PMS 186 C
                    created_at: '2026-06-13T10:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: orders:write
      operationId: post-api-sales-orders-salesorder-lines-salesorderline-decorations
  /api/sales-orders/{salesOrder}/lines/{salesOrderLine}/decorations/{decoration}:
    put:
      tags:
      - Line Decorations
      summary: Update Line Decoration
      description: 'Update an existing decoration spec. All fields are optional (`sometimes`)
        — send only the fields you want to change. The same conditional rules apply
        when a field is present (e.g. `placement_custom` required if `placement` is
        `custom`).


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Requires permission: `sales_orders.update`.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                placement:
                  type: string
                setup_type:
                  type: string
                estimated_cost:
                  type: number
                blank_product_id:
                  type: integer
              example:
                placement: full_front
                setup_type: repeat
                estimated_cost: 3.25
                blank_product_id: 240
      parameters:
      - name: salesOrder
        in: path
        schema:
          type: integer
        required: true
        description: Sales order ID
        example: '501'
      - name: salesOrderLine
        in: path
        schema:
          type: integer
        required: true
        description: Sales order line ID
        example: '3001'
      - name: decoration
        in: path
        schema:
          type: integer
        required: true
        description: Decoration spec ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      sales_order_line_id:
                        type: integer
                      method:
                        type: string
                      placement:
                        type: string
                      placement_custom:
                        type: string
                        nullable: true
                      blank_product_id:
                        type: integer
                      artwork:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          digitization_state:
                            type: string
                      colors:
                        type: array
                        items:
                          type: object
                          properties:
                            product_id:
                              type: integer
                            name:
                              type: string
                      stitch_count:
                        type: integer
                      ink_colors_count:
                        type: string
                        nullable: true
                      area_sq_in:
                        type: number
                      setup_type:
                        type: string
                      digitization_required:
                        type: boolean
                      quantity_multiplier:
                        type: integer
                      estimated_cost:
                        type: string
                      estimated_cost_lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            sales_order_line_decoration_id:
                              type: integer
                            decoration_cost_rule_id:
                              type: integer
                            cost_category_id:
                              type: integer
                            cost_category_name:
                              type: string
                            amount:
                              type: string
                            is_structural_loss_flag:
                              type: boolean
                      has_structural_loss_flag:
                        type: boolean
                      manufacturing_order_id:
                        type: string
                        nullable: true
                      notes:
                        type: string
                      created_at:
                        type: string
                example:
                  data:
                    id: 1
                    sales_order_line_id: 3001
                    method: embroidery
                    placement: full_front
                    placement_custom: null
                    blank_product_id: 240
                    artwork:
                      id: 5
                      name: Acme Corp Logo
                      digitization_state: digitized
                    colors:
                    - product_id: 88
                      name: Red Thread
                    stitch_count: 12000
                    ink_colors_count: null
                    area_sq_in: 12.5
                    setup_type: repeat
                    digitization_required: true
                    quantity_multiplier: 1
                    estimated_cost: '3.25'
                    estimated_cost_lines:
                    - id: 1
                      sales_order_line_decoration_id: 1
                      decoration_cost_rule_id: 7
                      cost_category_id: 42
                      cost_category_name: Decoration Labor
                      amount: '3.60'
                      is_structural_loss_flag: false
                    - id: 2
                      sales_order_line_decoration_id: 1
                      decoration_cost_rule_id: 8
                      cost_category_id: 43
                      cost_category_name: Decoration Consumables
                      amount: '0.90'
                      is_structural_loss_flag: false
                    has_structural_loss_flag: false
                    manufacturing_order_id: null
                    notes: Match thread to PMS 186 C
                    created_at: '2026-06-13T10:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: orders:write
      operationId: put-api-sales-orders-salesorder-lines-salesorderline-decorations-decoration
    delete:
      tags:
      - Line Decorations
      summary: Remove Line Decoration
      description: 'Remove a decoration spec from a sales order line.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Requires permission: `sales_orders.update`.


        Authentication: Requires Bearer token.'
      parameters:
      - name: salesOrder
        in: path
        schema:
          type: integer
        required: true
        description: Sales order ID
        example: '501'
      - name: salesOrderLine
        in: path
        schema:
          type: integer
        required: true
        description: Sales order line ID
        example: '3001'
      - name: decoration
        in: path
        schema:
          type: integer
        required: true
        description: Decoration spec ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  status:
                    type: string
                example:
                  message: Decoration removed successfully.
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:write
      operationId: delete-api-sales-orders-salesorder-lines-salesorderline-decorations-decoration
  /api/sales-orders/{salesOrder}/lines/{salesOrderLine}/decorations/{decoration}/reprice:
    post:
      tags:
      - Line Decorations
      summary: Reprice Line Decoration
      description: 'Re-run the decoration cost-rule engine for a single decoration
        spec and refresh its pro-forma estimate. Matching `DecorationCostRule` records
        are re-evaluated by priority and the resulting `estimated_cost` and per-category
        estimated cost lines are recomputed. Takes no request body.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Use this after editing cost rules or changing decoration attributes (method,
        stitch count, ink colors, placement) to recalculate the estimate without otherwise
        modifying the spec.


        Requires permission: `sales_orders.update`.


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: salesOrder
        in: path
        schema:
          type: integer
        required: true
        description: Sales order ID
        example: '501'
      - name: salesOrderLine
        in: path
        schema:
          type: integer
        required: true
        description: Sales order line ID
        example: '3001'
      - name: decoration
        in: path
        schema:
          type: integer
        required: true
        description: Decoration spec ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      sales_order_line_id:
                        type: integer
                      method:
                        type: string
                      placement:
                        type: string
                      placement_custom:
                        type: string
                        nullable: true
                      blank_product_id:
                        type: integer
                      artwork:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          digitization_state:
                            type: string
                      colors:
                        type: array
                        items:
                          type: object
                          properties:
                            product_id:
                              type: integer
                            name:
                              type: string
                      stitch_count:
                        type: integer
                      ink_colors_count:
                        type: string
                        nullable: true
                      area_sq_in:
                        type: number
                      setup_type:
                        type: string
                      digitization_required:
                        type: boolean
                      quantity_multiplier:
                        type: integer
                      estimated_cost:
                        type: string
                      estimated_cost_lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            sales_order_line_decoration_id:
                              type: integer
                            decoration_cost_rule_id:
                              type: integer
                            cost_category_id:
                              type: integer
                            cost_category_name:
                              type: string
                            amount:
                              type: string
                            is_structural_loss_flag:
                              type: boolean
                      has_structural_loss_flag:
                        type: boolean
                      manufacturing_order_id:
                        type: string
                        nullable: true
                      notes:
                        type: string
                      created_at:
                        type: string
                example:
                  data:
                    id: 1
                    sales_order_line_id: 3001
                    method: embroidery
                    placement: front_left_chest
                    placement_custom: null
                    blank_product_id: 240
                    artwork:
                      id: 5
                      name: Acme Corp Logo
                      digitization_state: digitized
                    colors:
                    - product_id: 88
                      name: Red Thread
                    stitch_count: 12000
                    ink_colors_count: null
                    area_sq_in: 12.5
                    setup_type: new_setup
                    digitization_required: true
                    quantity_multiplier: 1
                    estimated_cost: '5.10'
                    estimated_cost_lines:
                    - id: 1
                      sales_order_line_decoration_id: 1
                      decoration_cost_rule_id: 7
                      cost_category_id: 42
                      cost_category_name: Decoration Labor
                      amount: '3.60'
                      is_structural_loss_flag: false
                    - id: 2
                      sales_order_line_decoration_id: 1
                      decoration_cost_rule_id: 8
                      cost_category_id: 43
                      cost_category_name: Decoration Consumables
                      amount: '0.90'
                      is_structural_loss_flag: false
                    has_structural_loss_flag: false
                    manufacturing_order_id: null
                    notes: Match thread to PMS 186 C
                    created_at: '2026-06-13T10:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: orders:write
      operationId: post-api-sales-orders-salesorder-lines-salesorderline-decorations-decoration-reprice
  /api/sales-orders/{salesOrder}/decoration-orders:
    get:
      tags:
      - Decoration Orders
      summary: List Decoration Orders
      description: 'List the decoration manufacturing orders linked to a sales order,
        with their status and production method.


        :::info[Required scope: `orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Requires a Bearer token.'
      parameters:
      - name: salesOrder
        in: path
        schema:
          type: integer
        required: true
        description: Sales order ID
        example: '501'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        decoration_id:
                          type: integer
                        sales_order_line_id:
                          type: integer
                        method:
                          type: string
                        placement:
                          type: string
                        artwork_name:
                          type: string
                        manufacturing_order_id:
                          type: integer
                        manufacturing_order:
                          type: object
                          properties:
                            id:
                              type: integer
                            mo_number:
                              type: string
                            status:
                              type: string
                            production_method:
                              type: string
                            planned_quantity:
                              type: integer
                            completed_quantity:
                              type: integer
                example:
                  data:
                  - decoration_id: 12
                    sales_order_line_id: 3001
                    method: embroidery
                    placement: front_left_chest
                    artwork_name: Acme Corp Logo
                    manufacturing_order_id: 880
                    manufacturing_order:
                      id: 880
                      mo_number: MO-000880
                      status: draft
                      production_method: in_house
                      planned_quantity: 24
                      completed_quantity: 0
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:read
      operationId: get-api-sales-orders-salesorder-decoration-orders
    post:
      tags:
      - Decoration Orders
      summary: Create Decoration Orders (Bulk)
      description: 'Bulk-create decoration manufacturing orders for every decorated
        line on the order via a tracked background job (global progress tray). One
        MO per decoration; already-linked decorations are skipped. Returns the tracked
        job log id to poll.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Requires a Bearer token and the sales_orders.update permission.'
      requestBody:
        content: {}
      parameters:
      - name: salesOrder
        in: path
        schema:
          type: integer
        required: true
        description: Sales order ID
        example: '501'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 4521
                  message: Decoration orders started — track progress in the job tray.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: orders:write
      operationId: post-api-sales-orders-salesorder-decoration-orders
  /api/sales-orders/{salesOrder}/lines/{salesOrderLine}/decoration-orders:
    post:
      tags:
      - Decoration Orders
      summary: Create Line Decoration Orders
      description: 'Create decoration manufacturing orders for a single line synchronously.
        Returns the created manufacturing order ids. Returns 422 with an actionable
        message when no blank product can be resolved for a decoration.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Requires a Bearer token and the sales_orders.update permission.'
      requestBody:
        content: {}
      parameters:
      - name: salesOrder
        in: path
        schema:
          type: integer
        required: true
        description: Sales order ID
        example: '501'
      - name: salesOrderLine
        in: path
        schema:
          type: integer
        required: true
        description: Sales order line ID
        example: '3001'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      manufacturing_order_ids:
                        type: array
                        items:
                          type: integer
                  message:
                    type: string
                example:
                  data:
                    manufacturing_order_ids:
                    - 880
                    - 881
                  message: Decoration orders created.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 'No blank product is configured for decoration #12. Set
                    a blank on the decoration, or define a BOM for the finished good.'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:write
      operationId: post-api-sales-orders-salesorder-lines-salesorderline-decoration-orders
  /api/artworks:
    get:
      tags:
      - Artwork
      summary: List Artworks
      description: 'List paginated artworks with optional filters and sorting.


        :::info[Required scope: `orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        customer_id:
                          type: integer
                        type:
                          type: string
                        digitization_state:
                          type: string
                        compatible_methods:
                          type: array
                          items:
                            type: string
                        stitch_count:
                          type: integer
                        ink_colors:
                          type: integer
                        version:
                          type: integer
                        preview_url:
                          type: string
                        production_file_url:
                          type: string
                        created_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - id: 5
                    name: Acme Corp Logo
                    customer_id: 42
                    type: logo
                    digitization_state: digitized
                    compatible_methods:
                    - embroidery
                    - screen_print
                    stitch_count: 12000
                    ink_colors: 3
                    version: 1
                    preview_url: https://cdn.example.com/tenant/images/artworks/acme-logo-preview.png
                    production_file_url: https://cdn.example.com/tenant/images/artworks/acme-logo.emb
                    created_at: '2026-06-13T10:00:00.000000Z'
                  current_page: 1
                  last_page: 1
                  per_page: 10
                  total: 1
                  from: 1
                  to: 1
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: orders:read
      operationId: get-api-artworks
    post:
      tags:
      - Artwork
      summary: Create Artwork
      description: 'Create a new artwork. Required: `name`, `type`. `digitization_state`
        defaults to `submitted` and `version` defaults to 1 when omitted. `customer_id`
        must reference an existing customer; `compatible_methods[]` must be valid
        decoration methods.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Requires permission: `sales_orders.update`.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                customer_id:
                  type: integer
                type:
                  type: string
                digitization_state:
                  type: string
                compatible_methods:
                  type: array
                  items:
                    type: string
                stitch_count:
                  type: integer
                ink_colors:
                  type: integer
                version:
                  type: integer
              example:
                name: Acme Corp Logo
                customer_id: 42
                type: logo
                digitization_state: submitted
                compatible_methods:
                - embroidery
                - screen_print
                stitch_count: 12000
                ink_colors: 3
                version: 1
      parameters: []
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      customer_id:
                        type: integer
                      type:
                        type: string
                      digitization_state:
                        type: string
                      compatible_methods:
                        type: array
                        items:
                          type: string
                      stitch_count:
                        type: integer
                      ink_colors:
                        type: integer
                      version:
                        type: integer
                      preview_url:
                        type: string
                      production_file_url:
                        type: string
                      created_at:
                        type: string
                example:
                  data:
                    id: 5
                    name: Acme Corp Logo
                    customer_id: 42
                    type: logo
                    digitization_state: submitted
                    compatible_methods:
                    - embroidery
                    - screen_print
                    stitch_count: 12000
                    ink_colors: 3
                    version: 1
                    preview_url: https://cdn.example.com/tenant/images/artworks/acme-logo-preview.png
                    production_file_url: https://cdn.example.com/tenant/images/artworks/acme-logo.emb
                    created_at: '2026-06-13T10:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: orders:write
      operationId: post-api-artworks
  /api/artworks/{artwork}:
    get:
      tags:
      - Artwork
      summary: Get Artwork
      description: 'Get a single artwork by ID.


        :::info[Required scope: `orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: artwork
        in: path
        schema:
          type: integer
        required: true
        description: Artwork ID
        example: '5'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      customer_id:
                        type: integer
                      type:
                        type: string
                      digitization_state:
                        type: string
                      compatible_methods:
                        type: array
                        items:
                          type: string
                      stitch_count:
                        type: integer
                      ink_colors:
                        type: integer
                      version:
                        type: integer
                      preview_url:
                        type: string
                      production_file_url:
                        type: string
                      created_at:
                        type: string
                example:
                  data:
                    id: 5
                    name: Acme Corp Logo
                    customer_id: 42
                    type: logo
                    digitization_state: digitized
                    compatible_methods:
                    - embroidery
                    - screen_print
                    stitch_count: 12000
                    ink_colors: 3
                    version: 1
                    preview_url: https://cdn.example.com/tenant/images/artworks/acme-logo-preview.png
                    production_file_url: https://cdn.example.com/tenant/images/artworks/acme-logo.emb
                    created_at: '2026-06-13T10:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:read
      operationId: get-api-artworks-artwork
    put:
      tags:
      - Artwork
      summary: Update Artwork
      description: 'Update an existing artwork. All fields are optional (`sometimes`)
        — send only what changes.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Requires permission: `sales_orders.update`.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                digitization_state:
                  type: string
                stitch_count:
                  type: integer
              example:
                digitization_state: digitized
                stitch_count: 12500
      parameters:
      - name: artwork
        in: path
        schema:
          type: integer
        required: true
        description: Artwork ID
        example: '5'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      customer_id:
                        type: integer
                      type:
                        type: string
                      digitization_state:
                        type: string
                      compatible_methods:
                        type: array
                        items:
                          type: string
                      stitch_count:
                        type: integer
                      ink_colors:
                        type: integer
                      version:
                        type: integer
                      preview_url:
                        type: string
                      production_file_url:
                        type: string
                      created_at:
                        type: string
                example:
                  data:
                    id: 5
                    name: Acme Corp Logo
                    customer_id: 42
                    type: logo
                    digitization_state: digitized
                    compatible_methods:
                    - embroidery
                    - screen_print
                    stitch_count: 12500
                    ink_colors: 3
                    version: 1
                    preview_url: https://cdn.example.com/tenant/images/artworks/acme-logo-preview.png
                    production_file_url: https://cdn.example.com/tenant/images/artworks/acme-logo.emb
                    created_at: '2026-06-13T10:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: orders:write
      operationId: put-api-artworks-artwork
    delete:
      tags:
      - Artwork
      summary: Archive Artwork
      description: 'Archive an artwork (soft removal). The artwork is retained for
        historical decoration specs but no longer appears in active listings.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Requires permission: `sales_orders.update`.


        Authentication: Requires Bearer token.'
      parameters:
      - name: artwork
        in: path
        schema:
          type: integer
        required: true
        description: Artwork ID
        example: '5'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  status:
                    type: string
                example:
                  message: Artwork archived successfully.
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:write
      operationId: delete-api-artworks-artwork
  /api/decoration-cost-rules:
    get:
      tags:
      - Decoration Cost Rules
      summary: List Decoration Cost Rules
      description: 'List paginated decoration cost rules with optional filters and
        sorting.


        :::info[Required scope: `orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Requires scope: `orders` (read).


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        priority:
                          type: integer
                        is_active:
                          type: boolean
                        conditions:
                          type: object
                          properties:
                            method:
                              type: string
                            placement:
                              type: string
                              nullable: true
                            setup_type:
                              type: string
                              nullable: true
                            stitch_count_min:
                              type: string
                              nullable: true
                            stitch_count_max:
                              type: string
                              nullable: true
                            ink_colors_count:
                              type: string
                              nullable: true
                            area_sq_in_min:
                              type: string
                              nullable: true
                            area_sq_in_max:
                              type: string
                              nullable: true
                            product_id:
                              type: string
                              nullable: true
                            customer_id:
                              type: string
                              nullable: true
                        effect:
                          type: object
                          properties:
                            type:
                              type: string
                            cost_category_id:
                              type: integer
                            amount:
                              type: string
                              nullable: true
                            rate:
                              type: number
                            metric:
                              type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - id: 12
                    name: Embroidery — per 1k stitches
                    priority: 10
                    is_active: true
                    conditions:
                      method: embroidery
                      placement: null
                      setup_type: null
                      stitch_count_min: null
                      stitch_count_max: null
                      ink_colors_count: null
                      area_sq_in_min: null
                      area_sq_in_max: null
                      product_id: null
                      customer_id: null
                    effect:
                      type: rate_x_metric
                      cost_category_id: 7
                      amount: null
                      rate: 0.35
                      metric: stitch_count
                    created_at: '2026-06-13T10:00:00.000000Z'
                    updated_at: '2026-06-13T10:00:00.000000Z'
                  current_page: 1
                  last_page: 1
                  per_page: 10
                  total: 1
                  from: 1
                  to: 1
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: orders:read
      operationId: get-api-decoration-cost-rules
    post:
      tags:
      - Decoration Cost Rules
      summary: Create Decoration Cost Rule
      description: 'Create a new decoration cost rule.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Required: `name`, `priority`, `is_active`, `conditions` (object), `effect`
        (object). `effect.type` must be one of `fixed`, `per_unit`, `rate_x_metric`,
        `minimum`, `flag_loss`. `effect.metric` (when present) must be one of `stitch_count`,
        `ink_colors_count`, `area_sq_in`. `conditions.method`, `conditions.placement`,
        `conditions.setup_type` must be valid enum values when present. `conditions.product_id`
        / `conditions.customer_id` and `effect.cost_category_id` must reference existing
        records.


        Requires permission: `sales_orders.update`.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                priority:
                  type: integer
                is_active:
                  type: boolean
                conditions:
                  type: object
                  properties:
                    method:
                      type: string
                    placement:
                      type: string
                      nullable: true
                    setup_type:
                      type: string
                      nullable: true
                    stitch_count_min:
                      type: string
                      nullable: true
                    stitch_count_max:
                      type: string
                      nullable: true
                    ink_colors_count:
                      type: string
                      nullable: true
                    area_sq_in_min:
                      type: string
                      nullable: true
                    area_sq_in_max:
                      type: string
                      nullable: true
                    product_id:
                      type: string
                      nullable: true
                    customer_id:
                      type: string
                      nullable: true
                effect:
                  type: object
                  properties:
                    type:
                      type: string
                    cost_category_id:
                      type: integer
                    amount:
                      type: string
                      nullable: true
                    rate:
                      type: number
                    metric:
                      type: string
              example:
                name: Embroidery — per 1k stitches
                priority: 10
                is_active: true
                conditions:
                  method: embroidery
                  placement: null
                  setup_type: null
                  stitch_count_min: null
                  stitch_count_max: null
                  ink_colors_count: null
                  area_sq_in_min: null
                  area_sq_in_max: null
                  product_id: null
                  customer_id: null
                effect:
                  type: rate_x_metric
                  cost_category_id: 7
                  amount: null
                  rate: 0.35
                  metric: stitch_count
      parameters: []
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      priority:
                        type: integer
                      is_active:
                        type: boolean
                      conditions:
                        type: object
                        properties:
                          method:
                            type: string
                          placement:
                            type: string
                            nullable: true
                          setup_type:
                            type: string
                            nullable: true
                          stitch_count_min:
                            type: string
                            nullable: true
                          stitch_count_max:
                            type: string
                            nullable: true
                          ink_colors_count:
                            type: string
                            nullable: true
                          area_sq_in_min:
                            type: string
                            nullable: true
                          area_sq_in_max:
                            type: string
                            nullable: true
                          product_id:
                            type: string
                            nullable: true
                          customer_id:
                            type: string
                            nullable: true
                      effect:
                        type: object
                        properties:
                          type:
                            type: string
                          cost_category_id:
                            type: integer
                          amount:
                            type: string
                            nullable: true
                          rate:
                            type: number
                          metric:
                            type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 12
                    name: Embroidery — per 1k stitches
                    priority: 10
                    is_active: true
                    conditions:
                      method: embroidery
                      placement: null
                      setup_type: null
                      stitch_count_min: null
                      stitch_count_max: null
                      ink_colors_count: null
                      area_sq_in_min: null
                      area_sq_in_max: null
                      product_id: null
                      customer_id: null
                    effect:
                      type: rate_x_metric
                      cost_category_id: 7
                      amount: null
                      rate: 0.35
                      metric: stitch_count
                    created_at: '2026-06-13T10:00:00.000000Z'
                    updated_at: '2026-06-13T10:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: orders:write
      operationId: post-api-decoration-cost-rules
  /api/decoration-cost-rules/{decoration_cost_rule}:
    get:
      tags:
      - Decoration Cost Rules
      summary: Get Decoration Cost Rule
      description: 'Show a single decoration cost rule.


        :::info[Required scope: `orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Requires scope: `orders` (read).


        Authentication: Requires Bearer token.'
      parameters:
      - name: decoration_cost_rule
        in: path
        schema:
          type: integer
        required: true
        description: Decoration cost rule ID
        example: '12'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      priority:
                        type: integer
                      is_active:
                        type: boolean
                      conditions:
                        type: object
                        properties:
                          method:
                            type: string
                          placement:
                            type: string
                            nullable: true
                          setup_type:
                            type: string
                            nullable: true
                          stitch_count_min:
                            type: string
                            nullable: true
                          stitch_count_max:
                            type: string
                            nullable: true
                          ink_colors_count:
                            type: string
                            nullable: true
                          area_sq_in_min:
                            type: string
                            nullable: true
                          area_sq_in_max:
                            type: string
                            nullable: true
                          product_id:
                            type: string
                            nullable: true
                          customer_id:
                            type: string
                            nullable: true
                      effect:
                        type: object
                        properties:
                          type:
                            type: string
                          cost_category_id:
                            type: integer
                          amount:
                            type: string
                            nullable: true
                          rate:
                            type: number
                          metric:
                            type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 12
                    name: Embroidery — per 1k stitches
                    priority: 10
                    is_active: true
                    conditions:
                      method: embroidery
                      placement: null
                      setup_type: null
                      stitch_count_min: null
                      stitch_count_max: null
                      ink_colors_count: null
                      area_sq_in_min: null
                      area_sq_in_max: null
                      product_id: null
                      customer_id: null
                    effect:
                      type: rate_x_metric
                      cost_category_id: 7
                      amount: null
                      rate: 0.35
                      metric: stitch_count
                    created_at: '2026-06-13T10:00:00.000000Z'
                    updated_at: '2026-06-13T10:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:read
      operationId: get-api-decoration-cost-rules-decoration-cost-rule
    put:
      tags:
      - Decoration Cost Rules
      summary: Update Decoration Cost Rule
      description: 'Update an existing decoration cost rule. `name`, `priority`, `is_active`,
        `conditions`, and `effect` are required (full replacement of the rule definition).
        Same enum / existence validation as create.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Requires permission: `sales_orders.update`.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                priority:
                  type: integer
                is_active:
                  type: boolean
                conditions:
                  type: object
                  properties:
                    method:
                      type: string
                    placement:
                      type: string
                      nullable: true
                    setup_type:
                      type: string
                      nullable: true
                    stitch_count_min:
                      type: integer
                    stitch_count_max:
                      type: string
                      nullable: true
                    ink_colors_count:
                      type: string
                      nullable: true
                    area_sq_in_min:
                      type: string
                      nullable: true
                    area_sq_in_max:
                      type: string
                      nullable: true
                    product_id:
                      type: string
                      nullable: true
                    customer_id:
                      type: string
                      nullable: true
                effect:
                  type: object
                  properties:
                    type:
                      type: string
                    cost_category_id:
                      type: integer
                    amount:
                      type: string
                      nullable: true
                    rate:
                      type: number
                    metric:
                      type: string
              example:
                name: Embroidery — per 1k stitches
                priority: 5
                is_active: true
                conditions:
                  method: embroidery
                  placement: null
                  setup_type: null
                  stitch_count_min: 5000
                  stitch_count_max: null
                  ink_colors_count: null
                  area_sq_in_min: null
                  area_sq_in_max: null
                  product_id: null
                  customer_id: null
                effect:
                  type: rate_x_metric
                  cost_category_id: 7
                  amount: null
                  rate: 0.4
                  metric: stitch_count
      parameters:
      - name: decoration_cost_rule
        in: path
        schema:
          type: integer
        required: true
        description: Decoration cost rule ID
        example: '12'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      priority:
                        type: integer
                      is_active:
                        type: boolean
                      conditions:
                        type: object
                        properties:
                          method:
                            type: string
                          placement:
                            type: string
                            nullable: true
                          setup_type:
                            type: string
                            nullable: true
                          stitch_count_min:
                            type: integer
                          stitch_count_max:
                            type: string
                            nullable: true
                          ink_colors_count:
                            type: string
                            nullable: true
                          area_sq_in_min:
                            type: string
                            nullable: true
                          area_sq_in_max:
                            type: string
                            nullable: true
                          product_id:
                            type: string
                            nullable: true
                          customer_id:
                            type: string
                            nullable: true
                      effect:
                        type: object
                        properties:
                          type:
                            type: string
                          cost_category_id:
                            type: integer
                          amount:
                            type: string
                            nullable: true
                          rate:
                            type: number
                          metric:
                            type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 12
                    name: Embroidery — per 1k stitches
                    priority: 5
                    is_active: true
                    conditions:
                      method: embroidery
                      placement: null
                      setup_type: null
                      stitch_count_min: 5000
                      stitch_count_max: null
                      ink_colors_count: null
                      area_sq_in_min: null
                      area_sq_in_max: null
                      product_id: null
                      customer_id: null
                    effect:
                      type: rate_x_metric
                      cost_category_id: 7
                      amount: null
                      rate: 0.4
                      metric: stitch_count
                    created_at: '2026-06-13T10:00:00.000000Z'
                    updated_at: '2026-06-13T11:30:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: orders:write
      operationId: put-api-decoration-cost-rules-decoration-cost-rule
    delete:
      tags:
      - Decoration Cost Rules
      summary: Delete Decoration Cost Rule
      description: 'Delete a decoration cost rule. Existing decoration estimates already
        computed are not recalculated until their spec is repriced.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Requires permission: `sales_orders.update`.


        Authentication: Requires Bearer token.'
      parameters:
      - name: decoration_cost_rule
        in: path
        schema:
          type: integer
        required: true
        description: Decoration cost rule ID
        example: '12'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  status:
                    type: string
                example:
                  message: Decoration cost rule deleted successfully.
                  status: success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:write
      operationId: delete-api-decoration-cost-rules-decoration-cost-rule
  /api/decoration-methods:
    get:
      tags:
      - Decoration Methods
      summary: List Decoration Methods
      description: 'Returns all decoration methods (active and inactive), ordered
        by sort_order then name.


        Authentication: Requires Bearer token.


        :::info[Required scope: `orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        slug:
                          type: string
                        icon:
                          type: string
                        is_active:
                          type: boolean
                        sort_order:
                          type: integer
                example:
                  data:
                  - id: 11
                    name: Foil Stamp
                    slug: foil_stamp
                    icon: mdi-needle
                    is_active: true
                    sort_order: 10
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: orders:read
      operationId: get-api-decoration-methods
    post:
      tags:
      - Decoration Methods
      summary: Create Decoration Method
      description: 'Create a new decoration method. `name` is required; `slug` is
        auto-derived from the name when omitted. `icon` is an mdi icon name.


        Authentication: Requires Bearer token + `sales_orders.update` permission.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: string
              example: '{\n  \"name\": \"Foil Stamp\",\n  \"icon\": \"mdi-needle\",\n  \"is_active\":
                true,\n  \"sort_order\": 10\n}'
      parameters: []
      responses:
        '201':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      slug:
                        type: string
                      icon:
                        type: string
                      is_active:
                        type: boolean
                      sort_order:
                        type: integer
                example:
                  data:
                    id: 11
                    name: Foil Stamp
                    slug: foil_stamp
                    icon: mdi-needle
                    is_active: true
                    sort_order: 10
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: orders:write
      operationId: post-api-decoration-methods
  /api/decoration-methods/{decoration_method}:
    put:
      tags:
      - Decoration Methods
      summary: Update Decoration Method
      description: 'Update a record. Same fields as create.


        Authentication: Requires Bearer token + `sales_orders.update` permission.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: string
              example: '{\n  \"name\": \"Foil Stamp\",\n  \"icon\": \"mdi-needle\",\n  \"is_active\":
                true,\n  \"sort_order\": 10\n}'
      parameters:
      - name: decoration_method
        in: path
        schema:
          type: integer
        required: true
        description: Record ID
        example: '11'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      slug:
                        type: string
                      icon:
                        type: string
                      is_active:
                        type: boolean
                      sort_order:
                        type: integer
                example:
                  data:
                    id: 11
                    name: Foil Stamp
                    slug: foil_stamp
                    icon: mdi-needle
                    is_active: true
                    sort_order: 10
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: orders:write
      operationId: put-api-decoration-methods-decoration-method
    delete:
      tags:
      - Decoration Methods
      summary: Delete Decoration Method
      description: 'Delete a record from the registry.


        Authentication: Requires Bearer token + `sales_orders.update` permission.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: decoration_method
        in: path
        schema:
          type: integer
        required: true
        description: Record ID
        example: '11'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Deleted successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:write
      operationId: delete-api-decoration-methods-decoration-method
  /api/decoration-placements:
    get:
      tags:
      - Decoration Placements
      summary: List Decoration Placements
      description: 'Returns all decoration placements (active and inactive), ordered
        by sort_order then name.


        Authentication: Requires Bearer token.


        :::info[Required scope: `orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        slug:
                          type: string
                        is_active:
                          type: boolean
                        sort_order:
                          type: integer
                example:
                  data:
                  - id: 11
                    name: Foil Stamp
                    slug: foil_stamp
                    is_active: true
                    sort_order: 10
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: orders:read
      operationId: get-api-decoration-placements
    post:
      tags:
      - Decoration Placements
      summary: Create Decoration Placement
      description: 'Create a new decoration placement. `name` is required; `slug`
        is auto-derived from the name when omitted.


        Authentication: Requires Bearer token + `sales_orders.update` permission.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: string
              example: '{\n  \"name\": \"Foil Stamp\",\n  \"is_active\": true,\n  \"sort_order\":
                10\n}'
      parameters: []
      responses:
        '201':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      slug:
                        type: string
                      is_active:
                        type: boolean
                      sort_order:
                        type: integer
                example:
                  data:
                    id: 11
                    name: Foil Stamp
                    slug: foil_stamp
                    is_active: true
                    sort_order: 10
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: orders:write
      operationId: post-api-decoration-placements
  /api/decoration-placements/{decoration_placement}:
    put:
      tags:
      - Decoration Placements
      summary: Update Decoration Placement
      description: 'Update a record. Same fields as create.


        Authentication: Requires Bearer token + `sales_orders.update` permission.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: string
              example: '{\n  \"name\": \"Foil Stamp\",\n  \"is_active\": true,\n  \"sort_order\":
                10\n}'
      parameters:
      - name: decoration_placement
        in: path
        schema:
          type: integer
        required: true
        description: Record ID
        example: '11'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      slug:
                        type: string
                      is_active:
                        type: boolean
                      sort_order:
                        type: integer
                example:
                  data:
                    id: 11
                    name: Foil Stamp
                    slug: foil_stamp
                    is_active: true
                    sort_order: 10
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: orders:write
      operationId: put-api-decoration-placements-decoration-placement
    delete:
      tags:
      - Decoration Placements
      summary: Delete Decoration Placement
      description: 'Delete a record from the registry.


        Authentication: Requires Bearer token + `sales_orders.update` permission.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: decoration_placement
        in: path
        schema:
          type: integer
        required: true
        description: Record ID
        example: '11'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Deleted successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:write
      operationId: delete-api-decoration-placements-decoration-placement
  /api/quotes:
    get:
      tags:
      - Quotes
      summary: List Quotes
      description: 'List quotes (paginated) using Spatie QueryBuilder.


        Authentication: Requires Bearer token (PAT).


        Filters (all optional):

        - filter[search] — fuzzy LIKE across quote_number, reference, customer_po_number
        (customer name is encrypted, not searched)

        - filter[status] — exact status (draft, sent, viewed, accepted, declined,
        expired, revised, converted)

        - filter[origin] — exact origin (staff, rfq)

        - filter[customer_id] — exact customer id

        - filter_groups — base64-encoded advanced-filter tree over id, quote_number,
        reference, customer_po_number, status, origin, customer_id, total, valid_until,
        created_at, updated_at


        Sort: sort=&lt;field>, prefix - for DESC. Allowed sorts: id, quote_number,
        status, total, valid_until, created_at. Default: -id.


        Pagination: page (default 1), per_page (default 10). Returns a LengthAwarePaginator
        of quote object.


        :::info[Required scope: `orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        quote_number:
                          type: string
                        reference:
                          type: string
                          nullable: true
                        status:
                          type: string
                        origin:
                          type: string
                        customer_id:
                          type: integer
                        customer:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            company:
                              type: string
                        sales_rep_id:
                          type: string
                          nullable: true
                        store_id:
                          type: string
                          nullable: true
                        sales_channel_id:
                          type: string
                          nullable: true
                        currency_code:
                          type: string
                        customer_po_number:
                          type: string
                        memo_for_customer:
                          type: string
                        cover_letter:
                          type: string
                          nullable: true
                        terms:
                          type: string
                        valid_until:
                          type: string
                        is_tax_included:
                          type: boolean
                        tax_rate_id:
                          type: integer
                        subtotal:
                          type: integer
                        line_discount_total:
                          type: integer
                        order_discount_total:
                          type: integer
                        discount_total:
                          type: integer
                        tax_total:
                          type: integer
                        total:
                          type: integer
                        deposit_type:
                          type: string
                        deposit_value:
                          type: string
                          nullable: true
                        quote_token:
                          type: string
                          nullable: true
                        accepted_version_id:
                          type: string
                          nullable: true
                        sent_at:
                          type: string
                          nullable: true
                        viewed_at:
                          type: string
                          nullable: true
                        accepted_at:
                          type: string
                          nullable: true
                        declined_at:
                          type: string
                          nullable: true
                        declined_reason:
                          type: string
                          nullable: true
                        expired_at:
                          type: string
                          nullable: true
                        converted_at:
                          type: string
                          nullable: true
                        lines:
                          type: array
                          items:
                            type: object
                            properties:
                              id:
                                type: integer
                              product_id:
                                type: integer
                              sku:
                                type: string
                              description:
                                type: string
                              quantity:
                                type: integer
                              unit_price:
                                type: integer
                              unit_cost:
                                type: integer
                              discount_type:
                                type: string
                              discount_value:
                                type: integer
                              tax_rate_id:
                                type: integer
                              line_type:
                                type: string
                              select_group:
                                type: string
                                nullable: true
                              is_selected:
                                type: boolean
                              subtotal:
                                type: integer
                              sort:
                                type: integer
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  last_page:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                  first_page_url:
                    type: string
                  last_page_url:
                    type: string
                  next_page_url:
                    type: string
                    nullable: true
                  prev_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  links:
                    type: array
                example:
                  data:
                  - id: 12
                    quote_number: Q-000012
                    reference: null
                    status: draft
                    origin: staff
                    customer_id: 88
                    customer:
                      id: 88
                      name: Acme Corp
                      company: Acme Corp
                    sales_rep_id: null
                    store_id: null
                    sales_channel_id: null
                    currency_code: USD
                    customer_po_number: PO-9000
                    memo_for_customer: Thanks for your business
                    cover_letter: null
                    terms: Net 30
                    valid_until: '2026-06-25T00:00:00.000000Z'
                    is_tax_included: false
                    tax_rate_id: 3
                    subtotal: 200
                    line_discount_total: 20
                    order_discount_total: 0
                    discount_total: 20
                    tax_total: 18
                    total: 198
                    deposit_type: none
                    deposit_value: null
                    quote_token: null
                    accepted_version_id: null
                    sent_at: null
                    viewed_at: null
                    accepted_at: null
                    declined_at: null
                    declined_reason: null
                    expired_at: null
                    converted_at: null
                    lines:
                    - id: 1
                      product_id: 501
                      sku: WIDGET-1
                      description: Widget
                      quantity: 2
                      unit_price: 100
                      unit_cost: 60
                      discount_type: percentage
                      discount_value: 10
                      tax_rate_id: 3
                      line_type: standard
                      select_group: null
                      is_selected: true
                      subtotal: 200
                      sort: 0
                    created_at: '2026-06-18T10:00:00.000000Z'
                    updated_at: '2026-06-18T10:00:00.000000Z'
                  current_page: 1
                  per_page: 10
                  total: 1
                  last_page: 1
                  from: 1
                  to: 1
                  first_page_url: '{{protocol}}{{domain}}/api/quotes?page=1'
                  last_page_url: '{{protocol}}{{domain}}/api/quotes?page=1'
                  next_page_url: null
                  prev_page_url: null
                  path: '{{protocol}}{{domain}}/api/quotes'
                  links: []
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: orders:read
      operationId: get-api-quotes
    post:
      tags:
      - Quotes
      summary: Create Quote
      description: 'Creates a quote with lines. Prices are resolved from the customer''s
        pricing tier when `unit_price` is omitted and a `product_id` is given; totals
        are computed server-side.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token. Permission: `quotes.create`.


        Body fields (all optional): `customer_id`, `reference`, `currency_code` (3-letter),
        `sales_rep_id`, `store_id`, `sales_channel_id`, `customer_po_number`, `memo_for_customer`,
        `cover_letter`, `terms`, `valid_until` (date), `is_tax_included` (bool), `tax_rate_id`,
        and `lines[]`.


        Each line: `product_id`, `sku`, `description`, `quantity`, `unit_price`, `discount_type`
        (none|percentage|fixed_amount), `discount_value`, `tax_rate_id`, `line_type`
        (standard|optional|single_select), `select_group`.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                customer_id:
                  type: integer
                currency_code:
                  type: string
                customer_po_number:
                  type: string
                memo_for_customer:
                  type: string
                terms:
                  type: string
                valid_until:
                  type: string
                is_tax_included:
                  type: boolean
                tax_rate_id:
                  type: integer
                lines:
                  type: array
                  items:
                    type: object
                    properties:
                      product_id:
                        type: integer
                      quantity:
                        type: integer
                      unit_price:
                        type: integer
                      discount_type:
                        type: string
                      discount_value:
                        type: integer
                      tax_rate_id:
                        type: integer
                      line_type:
                        type: string
              example:
                customer_id: 88
                currency_code: USD
                customer_po_number: PO-9000
                memo_for_customer: Thanks for your business
                terms: Net 30
                valid_until: '2026-06-25'
                is_tax_included: false
                tax_rate_id: 3
                lines:
                - product_id: 501
                  quantity: 2
                  unit_price: 100
                  discount_type: percentage
                  discount_value: 10
                  tax_rate_id: 3
                  line_type: standard
                - description: Optional add-on
                  quantity: 1
                  unit_price: 25
                  line_type: optional
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      quote_number:
                        type: string
                      reference:
                        type: string
                        nullable: true
                      status:
                        type: string
                      origin:
                        type: string
                      customer_id:
                        type: integer
                      customer:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          company:
                            type: string
                      sales_rep_id:
                        type: string
                        nullable: true
                      store_id:
                        type: string
                        nullable: true
                      sales_channel_id:
                        type: string
                        nullable: true
                      currency_code:
                        type: string
                      customer_po_number:
                        type: string
                      memo_for_customer:
                        type: string
                      cover_letter:
                        type: string
                        nullable: true
                      terms:
                        type: string
                      valid_until:
                        type: string
                      is_tax_included:
                        type: boolean
                      tax_rate_id:
                        type: integer
                      subtotal:
                        type: integer
                      line_discount_total:
                        type: integer
                      order_discount_total:
                        type: integer
                      discount_total:
                        type: integer
                      tax_total:
                        type: integer
                      total:
                        type: integer
                      deposit_type:
                        type: string
                      deposit_value:
                        type: string
                        nullable: true
                      quote_token:
                        type: string
                        nullable: true
                      accepted_version_id:
                        type: string
                        nullable: true
                      sent_at:
                        type: string
                        nullable: true
                      viewed_at:
                        type: string
                        nullable: true
                      accepted_at:
                        type: string
                        nullable: true
                      declined_at:
                        type: string
                        nullable: true
                      declined_reason:
                        type: string
                        nullable: true
                      expired_at:
                        type: string
                        nullable: true
                      converted_at:
                        type: string
                        nullable: true
                      lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            product_id:
                              type: integer
                            sku:
                              type: string
                            description:
                              type: string
                            quantity:
                              type: integer
                            unit_price:
                              type: integer
                            unit_cost:
                              type: integer
                            discount_type:
                              type: string
                            discount_value:
                              type: integer
                            tax_rate_id:
                              type: integer
                            line_type:
                              type: string
                            select_group:
                              type: string
                              nullable: true
                            is_selected:
                              type: boolean
                            subtotal:
                              type: integer
                            sort:
                              type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 12
                    quote_number: Q-000012
                    reference: null
                    status: draft
                    origin: staff
                    customer_id: 88
                    customer:
                      id: 88
                      name: Acme Corp
                      company: Acme Corp
                    sales_rep_id: null
                    store_id: null
                    sales_channel_id: null
                    currency_code: USD
                    customer_po_number: PO-9000
                    memo_for_customer: Thanks for your business
                    cover_letter: null
                    terms: Net 30
                    valid_until: '2026-06-25T00:00:00.000000Z'
                    is_tax_included: false
                    tax_rate_id: 3
                    subtotal: 200
                    line_discount_total: 20
                    order_discount_total: 0
                    discount_total: 20
                    tax_total: 18
                    total: 198
                    deposit_type: none
                    deposit_value: null
                    quote_token: null
                    accepted_version_id: null
                    sent_at: null
                    viewed_at: null
                    accepted_at: null
                    declined_at: null
                    declined_reason: null
                    expired_at: null
                    converted_at: null
                    lines:
                    - id: 1
                      product_id: 501
                      sku: WIDGET-1
                      description: Widget
                      quantity: 2
                      unit_price: 100
                      unit_cost: 60
                      discount_type: percentage
                      discount_value: 10
                      tax_rate_id: 3
                      line_type: standard
                      select_group: null
                      is_selected: true
                      subtotal: 200
                      sort: 0
                    created_at: '2026-06-18T10:00:00.000000Z'
                    updated_at: '2026-06-18T10:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: orders:write
      operationId: post-api-quotes
  /api/quotes/{quote}:
    get:
      tags:
      - Quotes
      summary: Get Quote
      description: 'Returns a single quote with its lines and customer summary.


        :::info[Required scope: `orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: quote
        in: path
        schema:
          type: integer
        required: true
        description: Quote ID
        example: '12'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      quote_number:
                        type: string
                      reference:
                        type: string
                        nullable: true
                      status:
                        type: string
                      origin:
                        type: string
                      customer_id:
                        type: integer
                      customer:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          company:
                            type: string
                      sales_rep_id:
                        type: string
                        nullable: true
                      store_id:
                        type: string
                        nullable: true
                      sales_channel_id:
                        type: string
                        nullable: true
                      currency_code:
                        type: string
                      customer_po_number:
                        type: string
                      memo_for_customer:
                        type: string
                      cover_letter:
                        type: string
                        nullable: true
                      terms:
                        type: string
                      valid_until:
                        type: string
                      is_tax_included:
                        type: boolean
                      tax_rate_id:
                        type: integer
                      subtotal:
                        type: integer
                      line_discount_total:
                        type: integer
                      order_discount_total:
                        type: integer
                      discount_total:
                        type: integer
                      tax_total:
                        type: integer
                      total:
                        type: integer
                      deposit_type:
                        type: string
                      deposit_value:
                        type: string
                        nullable: true
                      quote_token:
                        type: string
                        nullable: true
                      accepted_version_id:
                        type: string
                        nullable: true
                      sent_at:
                        type: string
                        nullable: true
                      viewed_at:
                        type: string
                        nullable: true
                      accepted_at:
                        type: string
                        nullable: true
                      declined_at:
                        type: string
                        nullable: true
                      declined_reason:
                        type: string
                        nullable: true
                      expired_at:
                        type: string
                        nullable: true
                      converted_at:
                        type: string
                        nullable: true
                      lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            product_id:
                              type: integer
                            sku:
                              type: string
                            description:
                              type: string
                            quantity:
                              type: integer
                            unit_price:
                              type: integer
                            unit_cost:
                              type: integer
                            discount_type:
                              type: string
                            discount_value:
                              type: integer
                            tax_rate_id:
                              type: integer
                            line_type:
                              type: string
                            select_group:
                              type: string
                              nullable: true
                            is_selected:
                              type: boolean
                            subtotal:
                              type: integer
                            sort:
                              type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 12
                    quote_number: Q-000012
                    reference: null
                    status: draft
                    origin: staff
                    customer_id: 88
                    customer:
                      id: 88
                      name: Acme Corp
                      company: Acme Corp
                    sales_rep_id: null
                    store_id: null
                    sales_channel_id: null
                    currency_code: USD
                    customer_po_number: PO-9000
                    memo_for_customer: Thanks for your business
                    cover_letter: null
                    terms: Net 30
                    valid_until: '2026-06-25T00:00:00.000000Z'
                    is_tax_included: false
                    tax_rate_id: 3
                    subtotal: 200
                    line_discount_total: 20
                    order_discount_total: 0
                    discount_total: 20
                    tax_total: 18
                    total: 198
                    deposit_type: none
                    deposit_value: null
                    quote_token: null
                    accepted_version_id: null
                    sent_at: null
                    viewed_at: null
                    accepted_at: null
                    declined_at: null
                    declined_reason: null
                    expired_at: null
                    converted_at: null
                    lines:
                    - id: 1
                      product_id: 501
                      sku: WIDGET-1
                      description: Widget
                      quantity: 2
                      unit_price: 100
                      unit_cost: 60
                      discount_type: percentage
                      discount_value: 10
                      tax_rate_id: 3
                      line_type: standard
                      select_group: null
                      is_selected: true
                      subtotal: 200
                      sort: 0
                    created_at: '2026-06-18T10:00:00.000000Z'
                    updated_at: '2026-06-18T10:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:read
      operationId: get-api-quotes-quote
    put:
      tags:
      - Quotes
      summary: Update Quote
      description: 'Updates a quote''s header fields and recomputes totals. Partial
        payload — only provided fields are applied. The quote must be editable (status
        draft or revised).


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token. Permission: `quotes.update`.


        Updatable fields: `customer_id`, `reference`, `currency_code`, `sales_rep_id`,
        `store_id`, `sales_channel_id`, `customer_po_number`, `memo_for_customer`,
        `cover_letter`, `terms`, `valid_until`, `is_tax_included`, `tax_rate_id`,
        `deposit_type` (none|percent|fixed), `deposit_value`.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                customer_po_number:
                  type: string
                terms:
                  type: string
                valid_until:
                  type: string
              example:
                customer_po_number: PO-9100
                terms: Net 45
                valid_until: '2026-07-01'
      parameters:
      - name: quote
        in: path
        schema:
          type: integer
        required: true
        description: Quote ID
        example: '12'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      quote_number:
                        type: string
                      reference:
                        type: string
                        nullable: true
                      status:
                        type: string
                      origin:
                        type: string
                      customer_id:
                        type: integer
                      customer:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          company:
                            type: string
                      sales_rep_id:
                        type: string
                        nullable: true
                      store_id:
                        type: string
                        nullable: true
                      sales_channel_id:
                        type: string
                        nullable: true
                      currency_code:
                        type: string
                      customer_po_number:
                        type: string
                      memo_for_customer:
                        type: string
                      cover_letter:
                        type: string
                        nullable: true
                      terms:
                        type: string
                      valid_until:
                        type: string
                      is_tax_included:
                        type: boolean
                      tax_rate_id:
                        type: integer
                      subtotal:
                        type: integer
                      line_discount_total:
                        type: integer
                      order_discount_total:
                        type: integer
                      discount_total:
                        type: integer
                      tax_total:
                        type: integer
                      total:
                        type: integer
                      deposit_type:
                        type: string
                      deposit_value:
                        type: string
                        nullable: true
                      quote_token:
                        type: string
                        nullable: true
                      accepted_version_id:
                        type: string
                        nullable: true
                      sent_at:
                        type: string
                        nullable: true
                      viewed_at:
                        type: string
                        nullable: true
                      accepted_at:
                        type: string
                        nullable: true
                      declined_at:
                        type: string
                        nullable: true
                      declined_reason:
                        type: string
                        nullable: true
                      expired_at:
                        type: string
                        nullable: true
                      converted_at:
                        type: string
                        nullable: true
                      lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            product_id:
                              type: integer
                            sku:
                              type: string
                            description:
                              type: string
                            quantity:
                              type: integer
                            unit_price:
                              type: integer
                            unit_cost:
                              type: integer
                            discount_type:
                              type: string
                            discount_value:
                              type: integer
                            tax_rate_id:
                              type: integer
                            line_type:
                              type: string
                            select_group:
                              type: string
                              nullable: true
                            is_selected:
                              type: boolean
                            subtotal:
                              type: integer
                            sort:
                              type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 12
                    quote_number: Q-000012
                    reference: null
                    status: draft
                    origin: staff
                    customer_id: 88
                    customer:
                      id: 88
                      name: Acme Corp
                      company: Acme Corp
                    sales_rep_id: null
                    store_id: null
                    sales_channel_id: null
                    currency_code: USD
                    customer_po_number: PO-9000
                    memo_for_customer: Thanks for your business
                    cover_letter: null
                    terms: Net 30
                    valid_until: '2026-06-25T00:00:00.000000Z'
                    is_tax_included: false
                    tax_rate_id: 3
                    subtotal: 200
                    line_discount_total: 20
                    order_discount_total: 0
                    discount_total: 20
                    tax_total: 18
                    total: 198
                    deposit_type: none
                    deposit_value: null
                    quote_token: null
                    accepted_version_id: null
                    sent_at: null
                    viewed_at: null
                    accepted_at: null
                    declined_at: null
                    declined_reason: null
                    expired_at: null
                    converted_at: null
                    lines:
                    - id: 1
                      product_id: 501
                      sku: WIDGET-1
                      description: Widget
                      quantity: 2
                      unit_price: 100
                      unit_cost: 60
                      discount_type: percentage
                      discount_value: 10
                      tax_rate_id: 3
                      line_type: standard
                      select_group: null
                      is_selected: true
                      subtotal: 200
                      sort: 0
                    created_at: '2026-06-18T10:00:00.000000Z'
                    updated_at: '2026-06-18T10:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: orders:write
      operationId: put-api-quotes-quote
    delete:
      tags:
      - Quotes
      summary: Delete Quote
      description: 'Soft-deletes a quote and cascades to its lines, versions, and
        events.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token. Permission: `quotes.delete`.'
      parameters:
      - name: quote
        in: path
        schema:
          type: integer
        required: true
        description: Quote ID
        example: '12'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Quote deleted.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:write
      operationId: delete-api-quotes-quote
  /api/quotes/{quote}/lines:
    post:
      tags:
      - Quotes
      summary: Add Quote Line
      description: 'Adds a line to an editable quote and recomputes totals.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token. Permission: `quotes.update`.


        Body: `product_id`, `sku`, `description`, `quantity`, `unit_price`, `discount_type`
        (none|percentage|fixed_amount), `discount_value`, `tax_rate_id`, `line_type`
        (standard|optional|single_select), `select_group`.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                product_id:
                  type: integer
                quantity:
                  type: integer
                unit_price:
                  type: integer
                discount_type:
                  type: string
                line_type:
                  type: string
              example:
                product_id: 501
                quantity: 3
                unit_price: 30
                discount_type: none
                line_type: standard
      parameters:
      - name: quote
        in: path
        schema:
          type: integer
        required: true
        description: Quote ID
        example: '12'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      quote_number:
                        type: string
                      reference:
                        type: string
                        nullable: true
                      status:
                        type: string
                      origin:
                        type: string
                      customer_id:
                        type: integer
                      customer:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          company:
                            type: string
                      sales_rep_id:
                        type: string
                        nullable: true
                      store_id:
                        type: string
                        nullable: true
                      sales_channel_id:
                        type: string
                        nullable: true
                      currency_code:
                        type: string
                      customer_po_number:
                        type: string
                      memo_for_customer:
                        type: string
                      cover_letter:
                        type: string
                        nullable: true
                      terms:
                        type: string
                      valid_until:
                        type: string
                      is_tax_included:
                        type: boolean
                      tax_rate_id:
                        type: integer
                      subtotal:
                        type: integer
                      line_discount_total:
                        type: integer
                      order_discount_total:
                        type: integer
                      discount_total:
                        type: integer
                      tax_total:
                        type: integer
                      total:
                        type: integer
                      deposit_type:
                        type: string
                      deposit_value:
                        type: string
                        nullable: true
                      quote_token:
                        type: string
                        nullable: true
                      accepted_version_id:
                        type: string
                        nullable: true
                      sent_at:
                        type: string
                        nullable: true
                      viewed_at:
                        type: string
                        nullable: true
                      accepted_at:
                        type: string
                        nullable: true
                      declined_at:
                        type: string
                        nullable: true
                      declined_reason:
                        type: string
                        nullable: true
                      expired_at:
                        type: string
                        nullable: true
                      converted_at:
                        type: string
                        nullable: true
                      lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            product_id:
                              type: integer
                            sku:
                              type: string
                            description:
                              type: string
                            quantity:
                              type: integer
                            unit_price:
                              type: integer
                            unit_cost:
                              type: integer
                            discount_type:
                              type: string
                            discount_value:
                              type: integer
                            tax_rate_id:
                              type: integer
                            line_type:
                              type: string
                            select_group:
                              type: string
                              nullable: true
                            is_selected:
                              type: boolean
                            subtotal:
                              type: integer
                            sort:
                              type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 12
                    quote_number: Q-000012
                    reference: null
                    status: draft
                    origin: staff
                    customer_id: 88
                    customer:
                      id: 88
                      name: Acme Corp
                      company: Acme Corp
                    sales_rep_id: null
                    store_id: null
                    sales_channel_id: null
                    currency_code: USD
                    customer_po_number: PO-9000
                    memo_for_customer: Thanks for your business
                    cover_letter: null
                    terms: Net 30
                    valid_until: '2026-06-25T00:00:00.000000Z'
                    is_tax_included: false
                    tax_rate_id: 3
                    subtotal: 200
                    line_discount_total: 20
                    order_discount_total: 0
                    discount_total: 20
                    tax_total: 18
                    total: 198
                    deposit_type: none
                    deposit_value: null
                    quote_token: null
                    accepted_version_id: null
                    sent_at: null
                    viewed_at: null
                    accepted_at: null
                    declined_at: null
                    declined_reason: null
                    expired_at: null
                    converted_at: null
                    lines:
                    - id: 1
                      product_id: 501
                      sku: WIDGET-1
                      description: Widget
                      quantity: 2
                      unit_price: 100
                      unit_cost: 60
                      discount_type: percentage
                      discount_value: 10
                      tax_rate_id: 3
                      line_type: standard
                      select_group: null
                      is_selected: true
                      subtotal: 200
                      sort: 0
                    created_at: '2026-06-18T10:00:00.000000Z'
                    updated_at: '2026-06-18T10:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: orders:write
      operationId: post-api-quotes-quote-lines
  /api/quotes/{quote}/lines/{line}:
    delete:
      tags:
      - Quotes
      summary: Remove Quote Line
      description: 'Removes a line from an editable quote and recomputes totals.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token. Permission: `quotes.update`.'
      parameters:
      - name: quote
        in: path
        schema:
          type: integer
        required: true
        description: Quote ID
        example: '12'
      - name: line
        in: path
        schema:
          type: integer
        required: true
        description: Quote line ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      quote_number:
                        type: string
                      reference:
                        type: string
                        nullable: true
                      status:
                        type: string
                      origin:
                        type: string
                      customer_id:
                        type: integer
                      customer:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          company:
                            type: string
                      sales_rep_id:
                        type: string
                        nullable: true
                      store_id:
                        type: string
                        nullable: true
                      sales_channel_id:
                        type: string
                        nullable: true
                      currency_code:
                        type: string
                      customer_po_number:
                        type: string
                      memo_for_customer:
                        type: string
                      cover_letter:
                        type: string
                        nullable: true
                      terms:
                        type: string
                      valid_until:
                        type: string
                      is_tax_included:
                        type: boolean
                      tax_rate_id:
                        type: integer
                      subtotal:
                        type: integer
                      line_discount_total:
                        type: integer
                      order_discount_total:
                        type: integer
                      discount_total:
                        type: integer
                      tax_total:
                        type: integer
                      total:
                        type: integer
                      deposit_type:
                        type: string
                      deposit_value:
                        type: string
                        nullable: true
                      quote_token:
                        type: string
                        nullable: true
                      accepted_version_id:
                        type: string
                        nullable: true
                      sent_at:
                        type: string
                        nullable: true
                      viewed_at:
                        type: string
                        nullable: true
                      accepted_at:
                        type: string
                        nullable: true
                      declined_at:
                        type: string
                        nullable: true
                      declined_reason:
                        type: string
                        nullable: true
                      expired_at:
                        type: string
                        nullable: true
                      converted_at:
                        type: string
                        nullable: true
                      lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            product_id:
                              type: integer
                            sku:
                              type: string
                            description:
                              type: string
                            quantity:
                              type: integer
                            unit_price:
                              type: integer
                            unit_cost:
                              type: integer
                            discount_type:
                              type: string
                            discount_value:
                              type: integer
                            tax_rate_id:
                              type: integer
                            line_type:
                              type: string
                            select_group:
                              type: string
                              nullable: true
                            is_selected:
                              type: boolean
                            subtotal:
                              type: integer
                            sort:
                              type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 12
                    quote_number: Q-000012
                    reference: null
                    status: draft
                    origin: staff
                    customer_id: 88
                    customer:
                      id: 88
                      name: Acme Corp
                      company: Acme Corp
                    sales_rep_id: null
                    store_id: null
                    sales_channel_id: null
                    currency_code: USD
                    customer_po_number: PO-9000
                    memo_for_customer: Thanks for your business
                    cover_letter: null
                    terms: Net 30
                    valid_until: '2026-06-25T00:00:00.000000Z'
                    is_tax_included: false
                    tax_rate_id: 3
                    subtotal: 200
                    line_discount_total: 20
                    order_discount_total: 0
                    discount_total: 20
                    tax_total: 18
                    total: 198
                    deposit_type: none
                    deposit_value: null
                    quote_token: null
                    accepted_version_id: null
                    sent_at: null
                    viewed_at: null
                    accepted_at: null
                    declined_at: null
                    declined_reason: null
                    expired_at: null
                    converted_at: null
                    lines:
                    - id: 1
                      product_id: 501
                      sku: WIDGET-1
                      description: Widget
                      quantity: 2
                      unit_price: 100
                      unit_cost: 60
                      discount_type: percentage
                      discount_value: 10
                      tax_rate_id: 3
                      line_type: standard
                      select_group: null
                      is_selected: true
                      subtotal: 200
                      sort: 0
                    created_at: '2026-06-18T10:00:00.000000Z'
                    updated_at: '2026-06-18T10:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:write
      operationId: delete-api-quotes-quote-lines-line
    put:
      tags:
      - Quotes
      summary: Update Quote Line
      description: 'Update a single quote line. All fields optional — send only what
        changed. Editing quantity/unit_price/discount recalculates the quote totals.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Fields: quantity (numeric), unit_price (numeric), description (string|null),
        warehouse_id (int|null), discount_type (none|percentage|fixed_amount), discount_value
        (numeric|null), tax_rate_id (int|null, exists:tax_rates — per-line tax override).


        Authentication: Requires Bearer token. Permission: `quotes.update`.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                quantity:
                  type: integer
                unit_price:
                  type: integer
                description:
                  type: string
                warehouse_id:
                  type: integer
                discount_type:
                  type: string
                discount_value:
                  type: integer
                tax_rate_id:
                  type: integer
                nominal_code_id:
                  type: integer
                financial_line_type_id:
                  type: integer
                proration_strategy:
                  type: string
                allocate_to_products:
                  type: boolean
              example:
                quantity: 5
                unit_price: 20
                description: Optional line description
                warehouse_id: 3
                discount_type: percentage
                discount_value: 10
                tax_rate_id: 2
                nominal_code_id: 8
                financial_line_type_id: 3
                proration_strategy: revenue_based
                allocate_to_products: false
      parameters:
      - name: quote
        in: path
        schema:
          type: integer
        required: true
        description: Quote ID
        example: '12'
      - name: line
        in: path
        schema:
          type: integer
        required: true
        description: Quote line ID
        example: '1'
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: orders:write
      operationId: put-api-quotes-quote-lines-line
  /api/quotes/{quote}/send:
    post:
      tags:
      - Quotes
      summary: Send Quote
      description: 'Snapshots an immutable version, issues a public token, sets status
        to `sent`, and stamps `sent_at` / `valid_until`. The quote must be editable.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token. Permission: `quotes.send`.'
      requestBody:
        content: {}
      parameters:
      - name: quote
        in: path
        schema:
          type: integer
        required: true
        description: Quote ID
        example: '12'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      quote_number:
                        type: string
                      reference:
                        type: string
                        nullable: true
                      status:
                        type: string
                      origin:
                        type: string
                      customer_id:
                        type: integer
                      customer:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          company:
                            type: string
                      sales_rep_id:
                        type: string
                        nullable: true
                      store_id:
                        type: string
                        nullable: true
                      sales_channel_id:
                        type: string
                        nullable: true
                      currency_code:
                        type: string
                      customer_po_number:
                        type: string
                      memo_for_customer:
                        type: string
                      cover_letter:
                        type: string
                        nullable: true
                      terms:
                        type: string
                      valid_until:
                        type: string
                      is_tax_included:
                        type: boolean
                      tax_rate_id:
                        type: integer
                      subtotal:
                        type: integer
                      line_discount_total:
                        type: integer
                      order_discount_total:
                        type: integer
                      discount_total:
                        type: integer
                      tax_total:
                        type: integer
                      total:
                        type: integer
                      deposit_type:
                        type: string
                      deposit_value:
                        type: string
                        nullable: true
                      quote_token:
                        type: string
                      accepted_version_id:
                        type: string
                        nullable: true
                      sent_at:
                        type: string
                      viewed_at:
                        type: string
                        nullable: true
                      accepted_at:
                        type: string
                        nullable: true
                      declined_at:
                        type: string
                        nullable: true
                      declined_reason:
                        type: string
                        nullable: true
                      expired_at:
                        type: string
                        nullable: true
                      converted_at:
                        type: string
                        nullable: true
                      lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            product_id:
                              type: integer
                            sku:
                              type: string
                            description:
                              type: string
                            quantity:
                              type: integer
                            unit_price:
                              type: integer
                            unit_cost:
                              type: integer
                            discount_type:
                              type: string
                            discount_value:
                              type: integer
                            tax_rate_id:
                              type: integer
                            line_type:
                              type: string
                            select_group:
                              type: string
                              nullable: true
                            is_selected:
                              type: boolean
                            subtotal:
                              type: integer
                            sort:
                              type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 12
                    quote_number: Q-000012
                    reference: null
                    status: sent
                    origin: staff
                    customer_id: 88
                    customer:
                      id: 88
                      name: Acme Corp
                      company: Acme Corp
                    sales_rep_id: null
                    store_id: null
                    sales_channel_id: null
                    currency_code: USD
                    customer_po_number: PO-9000
                    memo_for_customer: Thanks for your business
                    cover_letter: null
                    terms: Net 30
                    valid_until: '2026-06-25T00:00:00.000000Z'
                    is_tax_included: false
                    tax_rate_id: 3
                    subtotal: 200
                    line_discount_total: 20
                    order_discount_total: 0
                    discount_total: 20
                    tax_total: 18
                    total: 198
                    deposit_type: none
                    deposit_value: null
                    quote_token: 8f2c1a...64chars
                    accepted_version_id: null
                    sent_at: '2026-06-18T10:05:00.000000Z'
                    viewed_at: null
                    accepted_at: null
                    declined_at: null
                    declined_reason: null
                    expired_at: null
                    converted_at: null
                    lines:
                    - id: 1
                      product_id: 501
                      sku: WIDGET-1
                      description: Widget
                      quantity: 2
                      unit_price: 100
                      unit_cost: 60
                      discount_type: percentage
                      discount_value: 10
                      tax_rate_id: 3
                      line_type: standard
                      select_group: null
                      is_selected: true
                      subtotal: 200
                      sort: 0
                    created_at: '2026-06-18T10:00:00.000000Z'
                    updated_at: '2026-06-18T10:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: orders:write
      operationId: post-api-quotes-quote-send
  /api/quotes/{quote}/accept:
    post:
      tags:
      - Quotes
      summary: Accept Quote
      description: 'Marks an issued quote `accepted` and pins the accepted version
        (price-lock source for conversion).


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token. Permission: `quotes.accept`.'
      requestBody:
        content: {}
      parameters:
      - name: quote
        in: path
        schema:
          type: integer
        required: true
        description: Quote ID
        example: '12'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      quote_number:
                        type: string
                      reference:
                        type: string
                        nullable: true
                      status:
                        type: string
                      origin:
                        type: string
                      customer_id:
                        type: integer
                      customer:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          company:
                            type: string
                      sales_rep_id:
                        type: string
                        nullable: true
                      store_id:
                        type: string
                        nullable: true
                      sales_channel_id:
                        type: string
                        nullable: true
                      currency_code:
                        type: string
                      customer_po_number:
                        type: string
                      memo_for_customer:
                        type: string
                      cover_letter:
                        type: string
                        nullable: true
                      terms:
                        type: string
                      valid_until:
                        type: string
                      is_tax_included:
                        type: boolean
                      tax_rate_id:
                        type: integer
                      subtotal:
                        type: integer
                      line_discount_total:
                        type: integer
                      order_discount_total:
                        type: integer
                      discount_total:
                        type: integer
                      tax_total:
                        type: integer
                      total:
                        type: integer
                      deposit_type:
                        type: string
                      deposit_value:
                        type: string
                        nullable: true
                      quote_token:
                        type: string
                      accepted_version_id:
                        type: integer
                      sent_at:
                        type: string
                      viewed_at:
                        type: string
                        nullable: true
                      accepted_at:
                        type: string
                      declined_at:
                        type: string
                        nullable: true
                      declined_reason:
                        type: string
                        nullable: true
                      expired_at:
                        type: string
                        nullable: true
                      converted_at:
                        type: string
                        nullable: true
                      lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            product_id:
                              type: integer
                            sku:
                              type: string
                            description:
                              type: string
                            quantity:
                              type: integer
                            unit_price:
                              type: integer
                            unit_cost:
                              type: integer
                            discount_type:
                              type: string
                            discount_value:
                              type: integer
                            tax_rate_id:
                              type: integer
                            line_type:
                              type: string
                            select_group:
                              type: string
                              nullable: true
                            is_selected:
                              type: boolean
                            subtotal:
                              type: integer
                            sort:
                              type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 12
                    quote_number: Q-000012
                    reference: null
                    status: accepted
                    origin: staff
                    customer_id: 88
                    customer:
                      id: 88
                      name: Acme Corp
                      company: Acme Corp
                    sales_rep_id: null
                    store_id: null
                    sales_channel_id: null
                    currency_code: USD
                    customer_po_number: PO-9000
                    memo_for_customer: Thanks for your business
                    cover_letter: null
                    terms: Net 30
                    valid_until: '2026-06-25T00:00:00.000000Z'
                    is_tax_included: false
                    tax_rate_id: 3
                    subtotal: 200
                    line_discount_total: 20
                    order_discount_total: 0
                    discount_total: 20
                    tax_total: 18
                    total: 198
                    deposit_type: none
                    deposit_value: null
                    quote_token: 8f2c1a...64chars
                    accepted_version_id: 1
                    sent_at: '2026-06-18T10:05:00.000000Z'
                    viewed_at: null
                    accepted_at: '2026-06-18T10:10:00.000000Z'
                    declined_at: null
                    declined_reason: null
                    expired_at: null
                    converted_at: null
                    lines:
                    - id: 1
                      product_id: 501
                      sku: WIDGET-1
                      description: Widget
                      quantity: 2
                      unit_price: 100
                      unit_cost: 60
                      discount_type: percentage
                      discount_value: 10
                      tax_rate_id: 3
                      line_type: standard
                      select_group: null
                      is_selected: true
                      subtotal: 200
                      sort: 0
                    created_at: '2026-06-18T10:00:00.000000Z'
                    updated_at: '2026-06-18T10:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: orders:write
      operationId: post-api-quotes-quote-accept
  /api/quotes/{quote}/decline:
    post:
      tags:
      - Quotes
      summary: Decline Quote
      description: 'Marks a quote `declined` with an optional reason.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token. Permission: `quotes.decline`.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                reason:
                  type: string
              example:
                reason: Budget
      parameters:
      - name: quote
        in: path
        schema:
          type: integer
        required: true
        description: Quote ID
        example: '12'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      quote_number:
                        type: string
                      reference:
                        type: string
                        nullable: true
                      status:
                        type: string
                      origin:
                        type: string
                      customer_id:
                        type: integer
                      customer:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          company:
                            type: string
                      sales_rep_id:
                        type: string
                        nullable: true
                      store_id:
                        type: string
                        nullable: true
                      sales_channel_id:
                        type: string
                        nullable: true
                      currency_code:
                        type: string
                      customer_po_number:
                        type: string
                      memo_for_customer:
                        type: string
                      cover_letter:
                        type: string
                        nullable: true
                      terms:
                        type: string
                      valid_until:
                        type: string
                      is_tax_included:
                        type: boolean
                      tax_rate_id:
                        type: integer
                      subtotal:
                        type: integer
                      line_discount_total:
                        type: integer
                      order_discount_total:
                        type: integer
                      discount_total:
                        type: integer
                      tax_total:
                        type: integer
                      total:
                        type: integer
                      deposit_type:
                        type: string
                      deposit_value:
                        type: string
                        nullable: true
                      quote_token:
                        type: string
                      accepted_version_id:
                        type: string
                        nullable: true
                      sent_at:
                        type: string
                      viewed_at:
                        type: string
                        nullable: true
                      accepted_at:
                        type: string
                        nullable: true
                      declined_at:
                        type: string
                      declined_reason:
                        type: string
                      expired_at:
                        type: string
                        nullable: true
                      converted_at:
                        type: string
                        nullable: true
                      lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            product_id:
                              type: integer
                            sku:
                              type: string
                            description:
                              type: string
                            quantity:
                              type: integer
                            unit_price:
                              type: integer
                            unit_cost:
                              type: integer
                            discount_type:
                              type: string
                            discount_value:
                              type: integer
                            tax_rate_id:
                              type: integer
                            line_type:
                              type: string
                            select_group:
                              type: string
                              nullable: true
                            is_selected:
                              type: boolean
                            subtotal:
                              type: integer
                            sort:
                              type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 12
                    quote_number: Q-000012
                    reference: null
                    status: declined
                    origin: staff
                    customer_id: 88
                    customer:
                      id: 88
                      name: Acme Corp
                      company: Acme Corp
                    sales_rep_id: null
                    store_id: null
                    sales_channel_id: null
                    currency_code: USD
                    customer_po_number: PO-9000
                    memo_for_customer: Thanks for your business
                    cover_letter: null
                    terms: Net 30
                    valid_until: '2026-06-25T00:00:00.000000Z'
                    is_tax_included: false
                    tax_rate_id: 3
                    subtotal: 200
                    line_discount_total: 20
                    order_discount_total: 0
                    discount_total: 20
                    tax_total: 18
                    total: 198
                    deposit_type: none
                    deposit_value: null
                    quote_token: 8f2c1a...64chars
                    accepted_version_id: null
                    sent_at: '2026-06-18T10:05:00.000000Z'
                    viewed_at: null
                    accepted_at: null
                    declined_at: '2026-06-18T10:10:00.000000Z'
                    declined_reason: Budget
                    expired_at: null
                    converted_at: null
                    lines:
                    - id: 1
                      product_id: 501
                      sku: WIDGET-1
                      description: Widget
                      quantity: 2
                      unit_price: 100
                      unit_cost: 60
                      discount_type: percentage
                      discount_value: 10
                      tax_rate_id: 3
                      line_type: standard
                      select_group: null
                      is_selected: true
                      subtotal: 200
                      sort: 0
                    created_at: '2026-06-18T10:00:00.000000Z'
                    updated_at: '2026-06-18T10:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: orders:write
      operationId: post-api-quotes-quote-decline
  /api/quotes/{quote}/expire:
    post:
      tags:
      - Quotes
      summary: Expire Quote
      description: 'Marks a quote `expired`.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token. Permission: `quotes.update`.'
      requestBody:
        content: {}
      parameters:
      - name: quote
        in: path
        schema:
          type: integer
        required: true
        description: Quote ID
        example: '12'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      quote_number:
                        type: string
                      reference:
                        type: string
                        nullable: true
                      status:
                        type: string
                      origin:
                        type: string
                      customer_id:
                        type: integer
                      customer:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          company:
                            type: string
                      sales_rep_id:
                        type: string
                        nullable: true
                      store_id:
                        type: string
                        nullable: true
                      sales_channel_id:
                        type: string
                        nullable: true
                      currency_code:
                        type: string
                      customer_po_number:
                        type: string
                      memo_for_customer:
                        type: string
                      cover_letter:
                        type: string
                        nullable: true
                      terms:
                        type: string
                      valid_until:
                        type: string
                      is_tax_included:
                        type: boolean
                      tax_rate_id:
                        type: integer
                      subtotal:
                        type: integer
                      line_discount_total:
                        type: integer
                      order_discount_total:
                        type: integer
                      discount_total:
                        type: integer
                      tax_total:
                        type: integer
                      total:
                        type: integer
                      deposit_type:
                        type: string
                      deposit_value:
                        type: string
                        nullable: true
                      quote_token:
                        type: string
                        nullable: true
                      accepted_version_id:
                        type: string
                        nullable: true
                      sent_at:
                        type: string
                        nullable: true
                      viewed_at:
                        type: string
                        nullable: true
                      accepted_at:
                        type: string
                        nullable: true
                      declined_at:
                        type: string
                        nullable: true
                      declined_reason:
                        type: string
                        nullable: true
                      expired_at:
                        type: string
                        nullable: true
                      converted_at:
                        type: string
                        nullable: true
                      lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            product_id:
                              type: integer
                            sku:
                              type: string
                            description:
                              type: string
                            quantity:
                              type: integer
                            unit_price:
                              type: integer
                            unit_cost:
                              type: integer
                            discount_type:
                              type: string
                            discount_value:
                              type: integer
                            tax_rate_id:
                              type: integer
                            line_type:
                              type: string
                            select_group:
                              type: string
                              nullable: true
                            is_selected:
                              type: boolean
                            subtotal:
                              type: integer
                            sort:
                              type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 12
                    quote_number: Q-000012
                    reference: null
                    status: draft
                    origin: staff
                    customer_id: 88
                    customer:
                      id: 88
                      name: Acme Corp
                      company: Acme Corp
                    sales_rep_id: null
                    store_id: null
                    sales_channel_id: null
                    currency_code: USD
                    customer_po_number: PO-9000
                    memo_for_customer: Thanks for your business
                    cover_letter: null
                    terms: Net 30
                    valid_until: '2026-06-25T00:00:00.000000Z'
                    is_tax_included: false
                    tax_rate_id: 3
                    subtotal: 200
                    line_discount_total: 20
                    order_discount_total: 0
                    discount_total: 20
                    tax_total: 18
                    total: 198
                    deposit_type: none
                    deposit_value: null
                    quote_token: null
                    accepted_version_id: null
                    sent_at: null
                    viewed_at: null
                    accepted_at: null
                    declined_at: null
                    declined_reason: null
                    expired_at: null
                    converted_at: null
                    lines:
                    - id: 1
                      product_id: 501
                      sku: WIDGET-1
                      description: Widget
                      quantity: 2
                      unit_price: 100
                      unit_cost: 60
                      discount_type: percentage
                      discount_value: 10
                      tax_rate_id: 3
                      line_type: standard
                      select_group: null
                      is_selected: true
                      subtotal: 200
                      sort: 0
                    created_at: '2026-06-18T10:00:00.000000Z'
                    updated_at: '2026-06-18T10:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: orders:write
      operationId: post-api-quotes-quote-expire
  /api/quotes/{quote}/revise:
    post:
      tags:
      - Quotes
      summary: Revise Quote
      description: 'Reopens an issued/expired quote as a new editable working copy
        (status `revised`).


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token. Permission: `quotes.update`.'
      requestBody:
        content: {}
      parameters:
      - name: quote
        in: path
        schema:
          type: integer
        required: true
        description: Quote ID
        example: '12'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      quote_number:
                        type: string
                      reference:
                        type: string
                        nullable: true
                      status:
                        type: string
                      origin:
                        type: string
                      customer_id:
                        type: integer
                      customer:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          company:
                            type: string
                      sales_rep_id:
                        type: string
                        nullable: true
                      store_id:
                        type: string
                        nullable: true
                      sales_channel_id:
                        type: string
                        nullable: true
                      currency_code:
                        type: string
                      customer_po_number:
                        type: string
                      memo_for_customer:
                        type: string
                      cover_letter:
                        type: string
                        nullable: true
                      terms:
                        type: string
                      valid_until:
                        type: string
                      is_tax_included:
                        type: boolean
                      tax_rate_id:
                        type: integer
                      subtotal:
                        type: integer
                      line_discount_total:
                        type: integer
                      order_discount_total:
                        type: integer
                      discount_total:
                        type: integer
                      tax_total:
                        type: integer
                      total:
                        type: integer
                      deposit_type:
                        type: string
                      deposit_value:
                        type: string
                        nullable: true
                      quote_token:
                        type: string
                        nullable: true
                      accepted_version_id:
                        type: string
                        nullable: true
                      sent_at:
                        type: string
                        nullable: true
                      viewed_at:
                        type: string
                        nullable: true
                      accepted_at:
                        type: string
                        nullable: true
                      declined_at:
                        type: string
                        nullable: true
                      declined_reason:
                        type: string
                        nullable: true
                      expired_at:
                        type: string
                        nullable: true
                      converted_at:
                        type: string
                        nullable: true
                      lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            product_id:
                              type: integer
                            sku:
                              type: string
                            description:
                              type: string
                            quantity:
                              type: integer
                            unit_price:
                              type: integer
                            unit_cost:
                              type: integer
                            discount_type:
                              type: string
                            discount_value:
                              type: integer
                            tax_rate_id:
                              type: integer
                            line_type:
                              type: string
                            select_group:
                              type: string
                              nullable: true
                            is_selected:
                              type: boolean
                            subtotal:
                              type: integer
                            sort:
                              type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 12
                    quote_number: Q-000012
                    reference: null
                    status: draft
                    origin: staff
                    customer_id: 88
                    customer:
                      id: 88
                      name: Acme Corp
                      company: Acme Corp
                    sales_rep_id: null
                    store_id: null
                    sales_channel_id: null
                    currency_code: USD
                    customer_po_number: PO-9000
                    memo_for_customer: Thanks for your business
                    cover_letter: null
                    terms: Net 30
                    valid_until: '2026-06-25T00:00:00.000000Z'
                    is_tax_included: false
                    tax_rate_id: 3
                    subtotal: 200
                    line_discount_total: 20
                    order_discount_total: 0
                    discount_total: 20
                    tax_total: 18
                    total: 198
                    deposit_type: none
                    deposit_value: null
                    quote_token: null
                    accepted_version_id: null
                    sent_at: null
                    viewed_at: null
                    accepted_at: null
                    declined_at: null
                    declined_reason: null
                    expired_at: null
                    converted_at: null
                    lines:
                    - id: 1
                      product_id: 501
                      sku: WIDGET-1
                      description: Widget
                      quantity: 2
                      unit_price: 100
                      unit_cost: 60
                      discount_type: percentage
                      discount_value: 10
                      tax_rate_id: 3
                      line_type: standard
                      select_group: null
                      is_selected: true
                      subtotal: 200
                      sort: 0
                    created_at: '2026-06-18T10:00:00.000000Z'
                    updated_at: '2026-06-18T10:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: orders:write
      operationId: post-api-quotes-quote-revise
  /api/quotes/{quote}/convert:
    post:
      tags:
      - Quotes
      summary: Convert Quote
      description: 'Converts an accepted quote into a draft sales order with price-locked
        lines (line unit prices are copied verbatim from the frozen quote lines —
        never re-resolved against the catalog). The order is stamped with `quote_id`
        and the accepted `quote_version_id`.


        Pass `line_ids` to convert a subset (partial/progressive conversion — one
        quote may yield several orders); omit it to convert all selected, not-yet-converted
        lines. Returns the quote plus the created `sales_order_id`/`sales_order_number`.


        Authentication: Requires Bearer token. Permission: `quotes.convert`.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                line_ids:
                  type: array
                  items:
                    type: integer
              example:
                line_ids:
                - 1
                - 2
      parameters:
      - name: quote
        in: path
        schema:
          type: integer
        required: true
        description: Quote ID
        example: '12'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      quote_number:
                        type: string
                      status:
                        type: string
                  sales_order_id:
                    type: integer
                  sales_order_number:
                    type: string
                example:
                  data:
                    id: 12
                    quote_number: Q-000012
                    status: converted
                  sales_order_id: 7788
                  sales_order_number: SO-7788
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-quotes-quote-convert
  /api/quotes/{quote}/create-order:
    post:
      tags:
      - Quotes
      summary: Create Sales Order from Quote
      description: 'Creates a draft sales order from an accepted quote with price-locked
        lines (line unit prices are copied verbatim from the frozen quote lines —
        never re-resolved against the catalog). The quote is the independent source
        record and is never consumed; the order is stamped with quote_id + the accepted
        quote_version_id for provenance. Pass line_ids to order a subset (partial/progressive
        ordering — one quote may yield several orders). Requires Bearer token + the
        quotes.create-order permission. The quote must be in accepted status.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                line_ids:
                  type: array
                  items:
                    type: integer
              example:
                line_ids:
                - 1
                - 2
      parameters:
      - name: quote
        in: path
        schema:
          type: integer
        required: true
        description: Quote ID
        example: '12'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      quote_number:
                        type: string
                      status:
                        type: string
                  sales_order_id:
                    type: integer
                  sales_order_number:
                    type: string
                example:
                  data:
                    id: 12
                    quote_number: Q-000012
                    status: converted
                  sales_order_id: 7788
                  sales_order_number: SO-7788
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: orders:write
      operationId: post-api-quotes-quote-create-order
  /api/quotes/{quote}/lines/bulk-warehouse:
    post:
      tags:
      - Quotes
      summary: Bulk Set Line Warehouse
      description: 'Set the allocation warehouse on many product lines at once — the
        "send the whole order from one warehouse" convenience for large quotes.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Body:

        - `warehouse_id` (int|null, exists:warehouses) — the target warehouse (null
        to clear).

        - `line_ids` (int[], optional) — the lines to update. **Omit `line_ids` to
        apply to every product line on the quote.** Revenue (product-less) lines are
        never affected.


        Authentication: Requires Bearer token. Permission: `quotes.update`.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                warehouse_id:
                  type: integer
                line_ids:
                  type: array
                  items:
                    type: integer
              example:
                warehouse_id: 3
                line_ids:
                - 101
                - 102
      parameters:
      - name: quote
        in: path
        schema:
          type: integer
        required: true
        description: Quote ID
        example: '12'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      quote_number:
                        type: string
                      lines:
                        type: array
                      sales_orders:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            sales_order_number:
                              type: string
                example:
                  data:
                    id: 12
                    quote_number: Q-000012
                    lines: []
                    sales_orders:
                    - id: 20
                      sales_order_number: SO-0002
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: orders:write
      operationId: post-api-quotes-quote-lines-bulk-warehouse
  /api/quotes/{quote}/allocation:
    post:
      tags:
      - Quotes
      summary: Set Quote Inventory Allocation
      description: 'Toggle whether the quote holds inventory, applying the side effect
        immediately so this is the single control for allocation:

        - `allocate=false` always RELEASES any stock the quote is currently holding.

        - `allocate=true` re-allocates now if the quote is already issued (sent/viewed);
        for a draft it only records intent, since allocation otherwise happens on
        send.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Returns 422 (InvalidQuoteTransition) when the quote is in a terminal state
        (ordered/declined/expired).


        Body: `allocate` (boolean, required).


        Authentication: Requires Bearer token. Permission: `quotes.update`.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                allocate:
                  type: boolean
              example:
                allocate: true
      parameters:
      - name: quote
        in: path
        schema:
          type: integer
        required: true
        description: Quote ID
        example: '12'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      quote_number:
                        type: string
                      status:
                        type: string
                      allocate_inventory:
                        type: boolean
                      lines:
                        type: array
                      sales_orders:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            sales_order_number:
                              type: string
                example:
                  data:
                    id: 12
                    quote_number: Q-000012
                    status: sent
                    allocate_inventory: false
                    lines: []
                    sales_orders:
                    - id: 20
                      sales_order_number: SO-0002
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: orders:write
      operationId: post-api-quotes-quote-allocation
  /api/quotes/bulk-archive:
    post:
      tags:
      - Quotes
      summary: Bulk Archive Quotes
      description: 'Archives multiple quotes (sets `archived_at`). Archived quotes
        are hidden from the default list and reappear under `?archived=only`.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Targets either an explicit list of quote IDs or every quote matching the current
        filters.


        **Two request-body modes:**

        - `{ "ids": [12, 13, 14] }` — act on these specific quotes.

        - `{ "apply_to_all": true, "filters": { "status": "draft" } }` — act on every
        quote matching the given filters (same filter keys as `GET /api/quotes`: `search`,
        `status`, `origin`, `customer_id`, `archived`, `filter_groups`, etc.).


        Authentication: Requires Bearer token. Permission: `quotes.update`.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 12
                - 13
                - 14
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Archived 3 quote(s).
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: orders:write
      operationId: post-api-quotes-bulk-archive
  /api/quotes/bulk-unarchive:
    post:
      tags:
      - Quotes
      summary: Bulk Unarchive Quotes
      description: 'Restores multiple archived quotes (clears `archived_at`).


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Targets either an explicit list of quote IDs or every quote matching the current
        filters.


        **Two request-body modes:**

        - `{ "ids": [12, 13, 14] }` — act on these specific quotes.

        - `{ "apply_to_all": true, "filters": { "status": "draft" } }` — act on every
        quote matching the given filters (same filter keys as `GET /api/quotes`: `search`,
        `status`, `origin`, `customer_id`, `archived`, `filter_groups`, etc.).


        Authentication: Requires Bearer token. Permission: `quotes.update`.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 12
                - 13
                - 14
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Unarchived 3 quote(s).
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: orders:write
      operationId: post-api-quotes-bulk-unarchive
  /api/quotes/bulk-delete:
    post:
      tags:
      - Quotes
      summary: Bulk Delete Quotes
      description: 'Soft-deletes multiple quotes. Releases any allocated inventory
        for quotes that opted into allocation.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Targets either an explicit list of quote IDs or every quote matching the current
        filters.


        **Two request-body modes:**

        - `{ "ids": [12, 13, 14] }` — act on these specific quotes.

        - `{ "apply_to_all": true, "filters": { "status": "draft" } }` — act on every
        quote matching the given filters (same filter keys as `GET /api/quotes`: `search`,
        `status`, `origin`, `customer_id`, `archived`, `filter_groups`, etc.).


        Authentication: Requires Bearer token. Permission: `quotes.delete`.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 12
                - 13
                - 14
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Deleted 3 quote(s).
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: orders:write
      operationId: post-api-quotes-bulk-delete
  /api/quotes/bulk-send:
    post:
      tags:
      - Quotes
      summary: Bulk Send Quotes
      description: 'Sends multiple quotes to their customers. Only quotes in a sendable
        (draft/revised) state are sent; the rest are skipped. Inventory is allocated
        for quotes that opted in. The response reports how many were sent vs. skipped.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Targets either an explicit list of quote IDs or every quote matching the current
        filters.


        **Two request-body modes:**

        - `{ "ids": [12, 13, 14] }` — act on these specific quotes.

        - `{ "apply_to_all": true, "filters": { "status": "draft" } }` — act on every
        quote matching the given filters (same filter keys as `GET /api/quotes`: `search`,
        `status`, `origin`, `customer_id`, `archived`, `filter_groups`, etc.).


        Authentication: Requires Bearer token. Permission: `quotes.send`.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 12
                - 13
                - 14
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      sent:
                        type: integer
                      skipped:
                        type: integer
                example:
                  message: Sent 2 quote(s), skipped 1.
                  data:
                    sent: 2
                    skipped: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: orders:write
      operationId: post-api-quotes-bulk-send
  /api/quotes/bulk-expire:
    post:
      tags:
      - Quotes
      summary: Bulk Expire Quotes
      description: 'Expires multiple quotes. Only issued (sent/viewed) quotes are
        expired; the rest are skipped. Allocated inventory is released. The response
        reports how many were expired vs. skipped.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Targets either an explicit list of quote IDs or every quote matching the current
        filters.


        **Two request-body modes:**

        - `{ "ids": [12, 13, 14] }` — act on these specific quotes.

        - `{ "apply_to_all": true, "filters": { "status": "draft" } }` — act on every
        quote matching the given filters (same filter keys as `GET /api/quotes`: `search`,
        `status`, `origin`, `customer_id`, `archived`, `filter_groups`, etc.).


        Authentication: Requires Bearer token. Permission: `quotes.update`.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 12
                - 13
                - 14
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      expired:
                        type: integer
                      skipped:
                        type: integer
                example:
                  message: Expired 2 quote(s), skipped 1.
                  data:
                    expired: 2
                    skipped: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: orders:write
      operationId: post-api-quotes-bulk-expire
  /api/quotes/{quote}/lines/bulk-update:
    post:
      tags:
      - Quotes
      summary: Bulk Update Lines
      description: 'Apply the same field changes to many lines at once (bulk-edit).
        Body: line_ids (int[], required) and any of discount_type (none|percentage|fixed_amount),
        discount_value (numeric|null), tax_rate_id (int|null). Recalculates totals.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token. Permission: `quotes.update`.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                line_ids:
                  type: array
                  items:
                    type: integer
                discount_type:
                  type: string
                discount_value:
                  type: integer
                tax_rate_id:
                  type: integer
              example:
                line_ids:
                - 101
                - 102
                discount_type: percentage
                discount_value: 10
                tax_rate_id: 2
      parameters:
      - name: quote
        in: path
        schema:
          type: integer
        required: true
        example: '12'
        description: The quote ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      lines:
                        type: array
                example:
                  data:
                    id: 12
                    lines: []
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: orders:write
      operationId: post-api-quotes-quote-lines-bulk-update
  /api/quotes/{quote}/lines/{line}/convert-to-revenue:
    post:
      tags:
      - Quotes
      summary: Convert Line to Revenue
      description: 'Strip the product from a line so it becomes a revenue (product-less)
        line, releasing any inventory it held. Description, quantity and price are
        preserved.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token. Permission: `quotes.update`.'
      requestBody:
        content: {}
      parameters:
      - name: quote
        in: path
        schema:
          type: integer
        required: true
        example: '12'
        description: The quote ID.
      - name: line
        in: path
        schema:
          type: integer
        required: true
        example: '101'
        description: The line ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      lines:
                        type: array
                example:
                  data:
                    id: 12
                    lines: []
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: orders:write
      operationId: post-api-quotes-quote-lines-line-convert-to-revenue
  /api/quotes/{quote}/lines/reorder:
    post:
      tags:
      - Quotes
      summary: Reorder Lines
      description: 'Persist a new line ordering. Body: ordered_ids (int[], required)
        — line ids in the desired order. Lines not listed keep their relative order
        after the listed set.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token. Permission: `quotes.update`.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ordered_ids:
                  type: array
                  items:
                    type: integer
              example:
                ordered_ids:
                - 103
                - 101
                - 102
      parameters:
      - name: quote
        in: path
        schema:
          type: integer
        required: true
        example: '12'
        description: The quote ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      lines:
                        type: array
                example:
                  data:
                    id: 12
                    lines: []
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: orders:write
      operationId: post-api-quotes-quote-lines-reorder
  /api/quotes/analytics:
    get:
      tags:
      - Quotes
      summary: Get Quote Analytics
      description: 'Aggregate quote analytics for a date range: status counts, issued
        count, win rate, quote-to-order conversion rate, average quote value, average
        discount percentage, average days to acceptance, and the number of issued
        quotes expiring within the next 7 days.


        :::info[Required scope: `orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        `win_rate` is the percentage of decided quotes (accepted + declined + expired
        + ordered) that were won (accepted or ordered). `conversion_rate` is the percentage
        of issued quotes that converted to a sales order.


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      total:
                        type: integer
                      by_status:
                        type: object
                        properties:
                          draft:
                            type: integer
                          sent:
                            type: integer
                          viewed:
                            type: integer
                          accepted:
                            type: integer
                          declined:
                            type: integer
                          expired:
                            type: integer
                          revised:
                            type: integer
                          ordered:
                            type: integer
                      issued:
                        type: integer
                      win_rate:
                        type: number
                      conversion_rate:
                        type: number
                      average_quote_value:
                        type: number
                      average_discount_percent:
                        type: number
                      average_days_to_accept:
                        type: number
                      expiring_soon:
                        type: integer
                example:
                  data:
                    total: 148
                    by_status:
                      draft: 22
                      sent: 41
                      viewed: 18
                      accepted: 30
                      declined: 12
                      expired: 9
                      revised: 4
                      ordered: 12
                    issued: 122
                    win_rate: 66.67
                    conversion_rate: 9.84
                    average_quote_value: 1245.5
                    average_discount_percent: 7.25
                    average_days_to_accept: 3.4
                    expiring_soon: 6
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: orders:read
      operationId: get-api-quotes-analytics
  /api/quotes/{quote}/duplicate:
    post:
      tags:
      - Quotes
      summary: Duplicate Quote
      description: 'Clone a quote into a fresh editable draft. The duplicate gets
        a new quote number, `draft` status, and copies of the customer, addresses,
        terms, discounts, deposit settings, and every line. Lifecycle fields (sent/viewed/accepted
        timestamps, versions, acceptance records) are NOT copied.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Returns the new draft quote.


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: quote
        in: path
        schema:
          type: integer
        required: true
        description: Quote ID to duplicate
        example: '12'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      quote_number:
                        type: string
                      reference:
                        type: string
                        nullable: true
                      status:
                        type: string
                      origin:
                        type: string
                      customer_id:
                        type: integer
                      customer:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          company:
                            type: string
                      sales_rep_id:
                        type: string
                        nullable: true
                      store_id:
                        type: string
                        nullable: true
                      sales_channel_id:
                        type: string
                        nullable: true
                      currency_code:
                        type: string
                      customer_po_number:
                        type: string
                      memo_for_customer:
                        type: string
                      cover_letter:
                        type: string
                        nullable: true
                      terms:
                        type: string
                      valid_until:
                        type: string
                      is_tax_included:
                        type: boolean
                      tax_rate_id:
                        type: integer
                      subtotal:
                        type: integer
                      line_discount_total:
                        type: integer
                      order_discount_total:
                        type: integer
                      discount_total:
                        type: integer
                      tax_total:
                        type: integer
                      total:
                        type: integer
                      deposit_type:
                        type: string
                      deposit_value:
                        type: string
                        nullable: true
                      quote_token:
                        type: string
                        nullable: true
                      accepted_version_id:
                        type: string
                        nullable: true
                      sent_at:
                        type: string
                        nullable: true
                      viewed_at:
                        type: string
                        nullable: true
                      accepted_at:
                        type: string
                        nullable: true
                      declined_at:
                        type: string
                        nullable: true
                      declined_reason:
                        type: string
                        nullable: true
                      expired_at:
                        type: string
                        nullable: true
                      converted_at:
                        type: string
                        nullable: true
                      lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            product_id:
                              type: integer
                            sku:
                              type: string
                            description:
                              type: string
                            quantity:
                              type: integer
                            unit_price:
                              type: integer
                            unit_cost:
                              type: integer
                            discount_type:
                              type: string
                            discount_value:
                              type: integer
                            tax_rate_id:
                              type: integer
                            line_type:
                              type: string
                            select_group:
                              type: string
                              nullable: true
                            is_selected:
                              type: boolean
                            subtotal:
                              type: integer
                            sort:
                              type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 13
                    quote_number: Q-000013
                    reference: null
                    status: draft
                    origin: staff
                    customer_id: 88
                    customer:
                      id: 88
                      name: Acme Corp
                      company: Acme Corp
                    sales_rep_id: null
                    store_id: null
                    sales_channel_id: null
                    currency_code: USD
                    customer_po_number: PO-9000
                    memo_for_customer: Thanks for your business
                    cover_letter: null
                    terms: Net 30
                    valid_until: '2026-08-25T00:00:00.000000Z'
                    is_tax_included: false
                    tax_rate_id: 3
                    subtotal: 200
                    line_discount_total: 20
                    order_discount_total: 0
                    discount_total: 20
                    tax_total: 18
                    total: 198
                    deposit_type: none
                    deposit_value: null
                    quote_token: null
                    accepted_version_id: null
                    sent_at: null
                    viewed_at: null
                    accepted_at: null
                    declined_at: null
                    declined_reason: null
                    expired_at: null
                    converted_at: null
                    lines:
                    - id: 1
                      product_id: 501
                      sku: WIDGET-1
                      description: Widget
                      quantity: 2
                      unit_price: 100
                      unit_cost: 60
                      discount_type: percentage
                      discount_value: 10
                      tax_rate_id: 3
                      line_type: standard
                      select_group: null
                      is_selected: true
                      subtotal: 200
                      sort: 0
                    created_at: '2026-06-18T10:00:00.000000Z'
                    updated_at: '2026-06-18T10:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: orders:write
      operationId: post-api-quotes-quote-duplicate
  /api/quotes/{quote}/pdf:
    get:
      tags:
      - Quotes
      summary: Get Quote PDF
      description: 'Render the quote as a PDF document using the tenant''s quote template
        and return the file inline.


        :::info[Required scope: `orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        The response is binary PDF content (`Content-Type: application/pdf`, `Content-Disposition:
        inline; filename="quote-Q-000012.pdf"`), not JSON.


        Authentication: Requires Bearer token.'
      parameters:
      - name: quote
        in: path
        schema:
          type: integer
        required: true
        description: Quote ID
        example: '12'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/pdf
          content:
            text/plain:
              schema:
                type: string
                example: '%PDF-1.7 … binary PDF bytes …'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:read
      operationId: get-api-quotes-quote-pdf
  /api/quotes/{quote}/lines/{line}/select:
    post:
      tags:
      - Quotes
      summary: Select Quote Line
      description: 'Mark an optional or single-select quote line as selected or deselected.
        Selection controls which lines the customer is accepting and which lines convert
        to the sales order.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        **Body fields:**

        - `is_selected` (required, boolean) — true to select the line, false to deselect
        it.


        Returns the full quote with recalculated totals. 404 when the line does not
        belong to the quote.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                is_selected:
                  type: boolean
              example:
                is_selected: true
      parameters:
      - name: quote
        in: path
        schema:
          type: integer
        required: true
        description: Quote ID
        example: '12'
      - name: line
        in: path
        schema:
          type: integer
        required: true
        description: Quote line ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      quote_number:
                        type: string
                      reference:
                        type: string
                        nullable: true
                      status:
                        type: string
                      origin:
                        type: string
                      customer_id:
                        type: integer
                      customer:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          company:
                            type: string
                      sales_rep_id:
                        type: string
                        nullable: true
                      store_id:
                        type: string
                        nullable: true
                      sales_channel_id:
                        type: string
                        nullable: true
                      currency_code:
                        type: string
                      customer_po_number:
                        type: string
                      memo_for_customer:
                        type: string
                      cover_letter:
                        type: string
                        nullable: true
                      terms:
                        type: string
                      valid_until:
                        type: string
                      is_tax_included:
                        type: boolean
                      tax_rate_id:
                        type: integer
                      subtotal:
                        type: integer
                      line_discount_total:
                        type: integer
                      order_discount_total:
                        type: integer
                      discount_total:
                        type: integer
                      tax_total:
                        type: integer
                      total:
                        type: integer
                      deposit_type:
                        type: string
                      deposit_value:
                        type: string
                        nullable: true
                      quote_token:
                        type: string
                        nullable: true
                      accepted_version_id:
                        type: string
                        nullable: true
                      sent_at:
                        type: string
                        nullable: true
                      viewed_at:
                        type: string
                        nullable: true
                      accepted_at:
                        type: string
                        nullable: true
                      declined_at:
                        type: string
                        nullable: true
                      declined_reason:
                        type: string
                        nullable: true
                      expired_at:
                        type: string
                        nullable: true
                      converted_at:
                        type: string
                        nullable: true
                      lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            product_id:
                              type: integer
                            sku:
                              type: string
                            description:
                              type: string
                            quantity:
                              type: integer
                            unit_price:
                              type: integer
                            unit_cost:
                              type: integer
                            discount_type:
                              type: string
                            discount_value:
                              type: integer
                            tax_rate_id:
                              type: integer
                            line_type:
                              type: string
                            select_group:
                              type: string
                              nullable: true
                            is_selected:
                              type: boolean
                            subtotal:
                              type: integer
                            sort:
                              type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 12
                    quote_number: Q-000012
                    reference: null
                    status: draft
                    origin: staff
                    customer_id: 88
                    customer:
                      id: 88
                      name: Acme Corp
                      company: Acme Corp
                    sales_rep_id: null
                    store_id: null
                    sales_channel_id: null
                    currency_code: USD
                    customer_po_number: PO-9000
                    memo_for_customer: Thanks for your business
                    cover_letter: null
                    terms: Net 30
                    valid_until: '2026-08-25T00:00:00.000000Z'
                    is_tax_included: false
                    tax_rate_id: 3
                    subtotal: 200
                    line_discount_total: 20
                    order_discount_total: 0
                    discount_total: 20
                    tax_total: 18
                    total: 198
                    deposit_type: none
                    deposit_value: null
                    quote_token: null
                    accepted_version_id: null
                    sent_at: null
                    viewed_at: null
                    accepted_at: null
                    declined_at: null
                    declined_reason: null
                    expired_at: null
                    converted_at: null
                    lines:
                    - id: 1
                      product_id: 501
                      sku: WIDGET-1
                      description: Widget
                      quantity: 2
                      unit_price: 100
                      unit_cost: 60
                      discount_type: percentage
                      discount_value: 10
                      tax_rate_id: 3
                      line_type: standard
                      select_group: null
                      is_selected: true
                      subtotal: 200
                      sort: 0
                    created_at: '2026-06-18T10:00:00.000000Z'
                    updated_at: '2026-06-18T10:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: orders:write
      operationId: post-api-quotes-quote-lines-line-select
  /api/quotes/{quote}/comments:
    get:
      tags:
      - Quotes
      summary: List Quote Comments
      description: 'List the quote''s negotiation thread — comments left by staff
        and by the customer, oldest first. System entries (e.g. automatic status notes)
        are flagged with `is_system`.


        :::info[Required scope: `orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters:
      - name: quote
        in: path
        schema:
          type: integer
        required: true
        description: Quote ID
        example: '12'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        author_type:
                          type: string
                        author_id:
                          type: integer
                        body:
                          type: string
                        attachment_path:
                          type: string
                          nullable: true
                        is_system:
                          type: boolean
                        created_at:
                          type: string
                example:
                  data:
                  - id: 41
                    author_type: staff
                    author_id: 5
                    body: Updated the pricing on line 2 per our call.
                    attachment_path: null
                    is_system: false
                    created_at: '2026-06-19T09:12:00.000000Z'
                  - id: 42
                    author_type: customer
                    author_id: null
                    body: Looks good — can you extend the validity to end of month?
                    attachment_path: null
                    is_system: false
                    created_at: '2026-06-19T15:40:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:read
      operationId: get-api-quotes-quote-comments
    post:
      tags:
      - Quotes
      summary: Add Quote Comment
      description: 'Add a staff comment to the quote''s negotiation thread. The comment
        is attributed to the authenticated user.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        **Body fields:**

        - `body` (required, string, max 5000) — the comment text.

        - `attachment_path` (optional, string, nullable) — path of a previously uploaded
        attachment to link to the comment.


        Returns 201 with the created comment.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                body:
                  type: string
                attachment_path:
                  type: string
                  nullable: true
              example:
                body: Updated the pricing on line 2 per our call.
                attachment_path: null
      parameters:
      - name: quote
        in: path
        schema:
          type: integer
        required: true
        description: Quote ID
        example: '12'
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      author_type:
                        type: string
                      author_id:
                        type: integer
                      body:
                        type: string
                      attachment_path:
                        type: string
                        nullable: true
                      is_system:
                        type: boolean
                      created_at:
                        type: string
                example:
                  data:
                    id: 43
                    author_type: staff
                    author_id: 5
                    body: Updated the pricing on line 2 per our call.
                    attachment_path: null
                    is_system: false
                    created_at: '2026-06-20T10:02:00.000000Z'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      body:
                        type: array
                        items:
                          type: string
                example:
                  message: The body field is required.
                  errors:
                    body:
                    - The body field is required.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:write
      operationId: post-api-quotes-quote-comments
  /api/quotes/{quote}/record-acceptance:
    post:
      tags:
      - Quotes
      summary: Record Quote Acceptance
      description: 'Record the customer''s acceptance of an issued quote (sent or
        viewed status) together with the signer''s details, and transition the quote
        to `accepted`. The signer''s IP address and user agent are captured automatically
        from the request.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        When the quote has optional or single-select lines, `selected_line_ids` pins
        exactly which lines were accepted — an explicit empty array means "no optional
        add-ons" and deselects previously selected optional lines. Omit the field
        to keep the current selection.


        **Body fields:**

        - `signer_name` (required, string, max 255) — name of the person accepting.

        - `signature_data` (optional, string, nullable) — captured signature image
        data.

        - `selected_line_ids` (optional, array of integers, nullable) — the accepted
        optional/single-select line IDs.


        Returns the accepted quote. 422 when the quote is not in an accepting state.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                signer_name:
                  type: string
                signature_data:
                  type: string
                  nullable: true
                selected_line_ids:
                  type: array
                  items:
                    type: integer
              example:
                signer_name: Jane Doe
                signature_data: null
                selected_line_ids:
                - 1
      parameters:
      - name: quote
        in: path
        schema:
          type: integer
        required: true
        description: Quote ID
        example: '12'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      quote_number:
                        type: string
                      reference:
                        type: string
                        nullable: true
                      status:
                        type: string
                      origin:
                        type: string
                      customer_id:
                        type: integer
                      customer:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          company:
                            type: string
                      sales_rep_id:
                        type: string
                        nullable: true
                      store_id:
                        type: string
                        nullable: true
                      sales_channel_id:
                        type: string
                        nullable: true
                      currency_code:
                        type: string
                      customer_po_number:
                        type: string
                      memo_for_customer:
                        type: string
                      cover_letter:
                        type: string
                        nullable: true
                      terms:
                        type: string
                      valid_until:
                        type: string
                      is_tax_included:
                        type: boolean
                      tax_rate_id:
                        type: integer
                      subtotal:
                        type: integer
                      line_discount_total:
                        type: integer
                      order_discount_total:
                        type: integer
                      discount_total:
                        type: integer
                      tax_total:
                        type: integer
                      total:
                        type: integer
                      deposit_type:
                        type: string
                      deposit_value:
                        type: string
                        nullable: true
                      quote_token:
                        type: string
                        nullable: true
                      accepted_version_id:
                        type: integer
                      sent_at:
                        type: string
                      viewed_at:
                        type: string
                        nullable: true
                      accepted_at:
                        type: string
                      declined_at:
                        type: string
                        nullable: true
                      declined_reason:
                        type: string
                        nullable: true
                      expired_at:
                        type: string
                        nullable: true
                      converted_at:
                        type: string
                        nullable: true
                      lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            product_id:
                              type: integer
                            sku:
                              type: string
                            description:
                              type: string
                            quantity:
                              type: integer
                            unit_price:
                              type: integer
                            unit_cost:
                              type: integer
                            discount_type:
                              type: string
                            discount_value:
                              type: integer
                            tax_rate_id:
                              type: integer
                            line_type:
                              type: string
                            select_group:
                              type: string
                              nullable: true
                            is_selected:
                              type: boolean
                            subtotal:
                              type: integer
                            sort:
                              type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 12
                    quote_number: Q-000012
                    reference: null
                    status: accepted
                    origin: staff
                    customer_id: 88
                    customer:
                      id: 88
                      name: Acme Corp
                      company: Acme Corp
                    sales_rep_id: null
                    store_id: null
                    sales_channel_id: null
                    currency_code: USD
                    customer_po_number: PO-9000
                    memo_for_customer: Thanks for your business
                    cover_letter: null
                    terms: Net 30
                    valid_until: '2026-08-25T00:00:00.000000Z'
                    is_tax_included: false
                    tax_rate_id: 3
                    subtotal: 200
                    line_discount_total: 20
                    order_discount_total: 0
                    discount_total: 20
                    tax_total: 18
                    total: 198
                    deposit_type: none
                    deposit_value: null
                    quote_token: null
                    accepted_version_id: 3
                    sent_at: '2026-06-18T12:00:00.000000Z'
                    viewed_at: null
                    accepted_at: '2026-06-20T16:30:00.000000Z'
                    declined_at: null
                    declined_reason: null
                    expired_at: null
                    converted_at: null
                    lines:
                    - id: 1
                      product_id: 501
                      sku: WIDGET-1
                      description: Widget
                      quantity: 2
                      unit_price: 100
                      unit_cost: 60
                      discount_type: percentage
                      discount_value: 10
                      tax_rate_id: 3
                      line_type: standard
                      select_group: null
                      is_selected: true
                      subtotal: 200
                      sort: 0
                    created_at: '2026-06-18T10:00:00.000000Z'
                    updated_at: '2026-06-18T10:00:00.000000Z'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Quote Q-000012 cannot be accepted from status draft.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:write
      operationId: post-api-quotes-quote-record-acceptance
  /api/quotes/{quote}/deposit-payment:
    post:
      tags:
      - Quotes
      summary: Record Quote Deposit Payment
      description: 'Record a deposit payment against the quote — used for manual/offline
        payments taken by staff. Payment gateway webhooks record their own payments
        through the same mechanism.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        **Body fields:**

        - `amount` (optional, numeric, min 0) — payment amount; defaults to the quote''s
        calculated deposit amount.

        - `reference` (optional, string, max 255) — external payment reference.

        - `provider` (optional, string, max 64) — payment provider label; defaults
        to `manual`.


        Returns 201 with the recorded payment''s id, amount, and status.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                amount:
                  type: integer
                reference:
                  type: string
                provider:
                  type: string
              example:
                amount: 99
                reference: CHK-2201
                provider: manual
      parameters:
      - name: quote
        in: path
        schema:
          type: integer
        required: true
        description: Quote ID
        example: '12'
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      payment_id:
                        type: integer
                      amount:
                        type: integer
                      status:
                        type: string
                example:
                  data:
                    payment_id: 77
                    amount: 99
                    status: paid
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: orders:write
      operationId: post-api-quotes-quote-deposit-payment
  /api/quotes/{quote}/sync-accounting:
    post:
      tags:
      - Quotes
      summary: Sync Quote to Accounting
      description: 'Push the quote to the connected accounting integration (e.g. as
        an estimate) and return the accounting reference. When no accounting integration
        is connected or the sync is skipped, `synced` is false and `reference` is
        null.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: quote
        in: path
        schema:
          type: integer
        required: true
        description: Quote ID
        example: '12'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      synced:
                        type: boolean
                      reference:
                        type: string
                example:
                  data:
                    synced: true
                    reference: EST-1042
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: orders:write
      operationId: post-api-quotes-quote-sync-accounting
  /api/quotes/{quote}/request-approval:
    post:
      tags:
      - Quotes
      summary: Request Quote Discount Approval
      description: 'Request managerial approval for the quote''s current discount
        level. The quote''s totals are recalculated, the effective discount percentage
        is captured, and a pending approval is created attributed to the authenticated
        user.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        A quote can only have one pending approval at a time — requesting again while
        one is pending returns an error. Resolve it with Approve Quote Discount or
        Reject Quote Discount.


        **Response fields:** `approval_id`, `status` (`pending`), `discount_percent`
        (the discount level captured for review).


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: quote
        in: path
        schema:
          type: integer
        required: true
        description: Quote ID
        example: '12'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      approval_id:
                        type: integer
                      status:
                        type: string
                      discount_percent:
                        type: number
                example:
                  data:
                    approval_id: 9
                    status: pending
                    discount_percent: 12.5
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Quote Q-000012 already has a pending approval.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:write
      operationId: post-api-quotes-quote-request-approval
  /api/quotes/{quote}/approve-discount:
    post:
      tags:
      - Quotes
      summary: Approve Quote Discount
      description: 'Approve the quote''s pending discount approval. The approval is
        marked approved and attributed to the authenticated user, and the refreshed
        quote is returned.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        404 when the quote has no pending approval.


        Authentication: Requires Bearer token.'
      requestBody:
        content: {}
      parameters:
      - name: quote
        in: path
        schema:
          type: integer
        required: true
        description: Quote ID
        example: '12'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      quote_number:
                        type: string
                      reference:
                        type: string
                        nullable: true
                      status:
                        type: string
                      origin:
                        type: string
                      customer_id:
                        type: integer
                      customer:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          company:
                            type: string
                      sales_rep_id:
                        type: string
                        nullable: true
                      store_id:
                        type: string
                        nullable: true
                      sales_channel_id:
                        type: string
                        nullable: true
                      currency_code:
                        type: string
                      customer_po_number:
                        type: string
                      memo_for_customer:
                        type: string
                      cover_letter:
                        type: string
                        nullable: true
                      terms:
                        type: string
                      valid_until:
                        type: string
                      is_tax_included:
                        type: boolean
                      tax_rate_id:
                        type: integer
                      subtotal:
                        type: integer
                      line_discount_total:
                        type: integer
                      order_discount_total:
                        type: integer
                      discount_total:
                        type: integer
                      tax_total:
                        type: integer
                      total:
                        type: integer
                      deposit_type:
                        type: string
                      deposit_value:
                        type: string
                        nullable: true
                      quote_token:
                        type: string
                        nullable: true
                      accepted_version_id:
                        type: string
                        nullable: true
                      sent_at:
                        type: string
                        nullable: true
                      viewed_at:
                        type: string
                        nullable: true
                      accepted_at:
                        type: string
                        nullable: true
                      declined_at:
                        type: string
                        nullable: true
                      declined_reason:
                        type: string
                        nullable: true
                      expired_at:
                        type: string
                        nullable: true
                      converted_at:
                        type: string
                        nullable: true
                      lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            product_id:
                              type: integer
                            sku:
                              type: string
                            description:
                              type: string
                            quantity:
                              type: integer
                            unit_price:
                              type: integer
                            unit_cost:
                              type: integer
                            discount_type:
                              type: string
                            discount_value:
                              type: integer
                            tax_rate_id:
                              type: integer
                            line_type:
                              type: string
                            select_group:
                              type: string
                              nullable: true
                            is_selected:
                              type: boolean
                            subtotal:
                              type: integer
                            sort:
                              type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 12
                    quote_number: Q-000012
                    reference: null
                    status: draft
                    origin: staff
                    customer_id: 88
                    customer:
                      id: 88
                      name: Acme Corp
                      company: Acme Corp
                    sales_rep_id: null
                    store_id: null
                    sales_channel_id: null
                    currency_code: USD
                    customer_po_number: PO-9000
                    memo_for_customer: Thanks for your business
                    cover_letter: null
                    terms: Net 30
                    valid_until: '2026-08-25T00:00:00.000000Z'
                    is_tax_included: false
                    tax_rate_id: 3
                    subtotal: 200
                    line_discount_total: 20
                    order_discount_total: 0
                    discount_total: 20
                    tax_total: 18
                    total: 198
                    deposit_type: none
                    deposit_value: null
                    quote_token: null
                    accepted_version_id: null
                    sent_at: null
                    viewed_at: null
                    accepted_at: null
                    declined_at: null
                    declined_reason: null
                    expired_at: null
                    converted_at: null
                    lines:
                    - id: 1
                      product_id: 501
                      sku: WIDGET-1
                      description: Widget
                      quantity: 2
                      unit_price: 100
                      unit_cost: 60
                      discount_type: percentage
                      discount_value: 10
                      tax_rate_id: 3
                      line_type: standard
                      select_group: null
                      is_selected: true
                      subtotal: 200
                      sort: 0
                    created_at: '2026-06-18T10:00:00.000000Z'
                    updated_at: '2026-06-18T10:00:00.000000Z'
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No pending approval for this quote.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: orders:write
      operationId: post-api-quotes-quote-approve-discount
  /api/quotes/{quote}/reject-discount:
    post:
      tags:
      - Quotes
      summary: Reject Quote Discount
      description: 'Reject the quote''s pending discount approval, optionally recording
        a reason. The approval is marked rejected and the refreshed quote is returned.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        **Body fields:**

        - `reason` (optional, string, max 1000, nullable) — why the discount was rejected.


        404 when the quote has no pending approval.


        Authentication: Requires Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                reason:
                  type: string
              example:
                reason: Discount exceeds the allowed margin for this customer tier.
      parameters:
      - name: quote
        in: path
        schema:
          type: integer
        required: true
        description: Quote ID
        example: '12'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      quote_number:
                        type: string
                      reference:
                        type: string
                        nullable: true
                      status:
                        type: string
                      origin:
                        type: string
                      customer_id:
                        type: integer
                      customer:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          company:
                            type: string
                      sales_rep_id:
                        type: string
                        nullable: true
                      store_id:
                        type: string
                        nullable: true
                      sales_channel_id:
                        type: string
                        nullable: true
                      currency_code:
                        type: string
                      customer_po_number:
                        type: string
                      memo_for_customer:
                        type: string
                      cover_letter:
                        type: string
                        nullable: true
                      terms:
                        type: string
                      valid_until:
                        type: string
                      is_tax_included:
                        type: boolean
                      tax_rate_id:
                        type: integer
                      subtotal:
                        type: integer
                      line_discount_total:
                        type: integer
                      order_discount_total:
                        type: integer
                      discount_total:
                        type: integer
                      tax_total:
                        type: integer
                      total:
                        type: integer
                      deposit_type:
                        type: string
                      deposit_value:
                        type: string
                        nullable: true
                      quote_token:
                        type: string
                        nullable: true
                      accepted_version_id:
                        type: string
                        nullable: true
                      sent_at:
                        type: string
                        nullable: true
                      viewed_at:
                        type: string
                        nullable: true
                      accepted_at:
                        type: string
                        nullable: true
                      declined_at:
                        type: string
                        nullable: true
                      declined_reason:
                        type: string
                        nullable: true
                      expired_at:
                        type: string
                        nullable: true
                      converted_at:
                        type: string
                        nullable: true
                      lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            product_id:
                              type: integer
                            sku:
                              type: string
                            description:
                              type: string
                            quantity:
                              type: integer
                            unit_price:
                              type: integer
                            unit_cost:
                              type: integer
                            discount_type:
                              type: string
                            discount_value:
                              type: integer
                            tax_rate_id:
                              type: integer
                            line_type:
                              type: string
                            select_group:
                              type: string
                              nullable: true
                            is_selected:
                              type: boolean
                            subtotal:
                              type: integer
                            sort:
                              type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 12
                    quote_number: Q-000012
                    reference: null
                    status: draft
                    origin: staff
                    customer_id: 88
                    customer:
                      id: 88
                      name: Acme Corp
                      company: Acme Corp
                    sales_rep_id: null
                    store_id: null
                    sales_channel_id: null
                    currency_code: USD
                    customer_po_number: PO-9000
                    memo_for_customer: Thanks for your business
                    cover_letter: null
                    terms: Net 30
                    valid_until: '2026-08-25T00:00:00.000000Z'
                    is_tax_included: false
                    tax_rate_id: 3
                    subtotal: 200
                    line_discount_total: 20
                    order_discount_total: 0
                    discount_total: 20
                    tax_total: 18
                    total: 198
                    deposit_type: none
                    deposit_value: null
                    quote_token: null
                    accepted_version_id: null
                    sent_at: null
                    viewed_at: null
                    accepted_at: null
                    declined_at: null
                    declined_reason: null
                    expired_at: null
                    converted_at: null
                    lines:
                    - id: 1
                      product_id: 501
                      sku: WIDGET-1
                      description: Widget
                      quantity: 2
                      unit_price: 100
                      unit_cost: 60
                      discount_type: percentage
                      discount_value: 10
                      tax_rate_id: 3
                      line_type: standard
                      select_group: null
                      is_selected: true
                      subtotal: 200
                      sort: 0
                    created_at: '2026-06-18T10:00:00.000000Z'
                    updated_at: '2026-06-18T10:00:00.000000Z'
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: No pending approval for this quote.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: orders:write
      operationId: post-api-quotes-quote-reject-discount
  /api/pos/register-session/current:
    get:
      tags:
      - POS / Register
      summary: Get Current Register Session
      description: 'Returns the authenticated user''s currently OPEN register session,
        or `null` if they have none. Use this on POS load to resume an in-progress
        shift.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token (PAT).


        Requires permission: pos.operate (when granular permissions are enabled).'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: Open session
                  value:
                    data:
                      id: 12
                      warehouse_id: 3
                      warehouse_name: Downtown Flagship
                      opened_by_user_id: 1
                      opened_by_name: Jane Cashier
                      opened_at: '2026-06-19T14:02:11.000000Z'
                      opening_float: '150.0000'
                      status: open
                      status_label: Open
                      closed_by_user_id: null
                      closed_at: null
                      cash_sales_total: '0.0000'
                      expected_cash: null
                      counted_cash: null
                      cash_variance: null
                      notes: null
                      created_at: '2026-06-19T14:02:11.000000Z'
                      updated_at: '2026-06-19T14:02:11.000000Z'
                example-1:
                  summary: No open session
                  value:
                    data: null
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: get-api-pos-register-session-current
  /api/pos/register-sessions:
    post:
      tags:
      - POS / Register
      summary: Open Register Session
      description: 'Opens a register session (shift) for the authenticated user, tied
        to a warehouse (the register''s stock location). The opening float is the
        starting cash in the drawer.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        A user may only have ONE open session at a time — opening a second returns
        422.


        Body fields:

        - `warehouse_id` (integer, required) — the register''s warehouse (must exist).

        - `opening_float` (numeric, required, min 0) — starting cash in the drawer.


        Authentication: Requires Bearer token (PAT).


        Requires permission: pos.operate (when granular permissions are enabled).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                warehouse_id:
                  type: integer
                opening_float:
                  type: integer
              example:
                warehouse_id: 3
                opening_float: 150
      parameters: []
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      warehouse_id:
                        type: integer
                      warehouse_name:
                        type: string
                      opened_by_user_id:
                        type: integer
                      opened_by_name:
                        type: string
                      opened_at:
                        type: string
                      opening_float:
                        type: string
                      status:
                        type: string
                      status_label:
                        type: string
                      closed_by_user_id:
                        type: string
                        nullable: true
                      closed_at:
                        type: string
                        nullable: true
                      cash_sales_total:
                        type: string
                      expected_cash:
                        type: string
                        nullable: true
                      counted_cash:
                        type: string
                        nullable: true
                      cash_variance:
                        type: string
                        nullable: true
                      notes:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 12
                    warehouse_id: 3
                    warehouse_name: Downtown Flagship
                    opened_by_user_id: 1
                    opened_by_name: Jane Cashier
                    opened_at: '2026-06-19T14:02:11.000000Z'
                    opening_float: '150.0000'
                    status: open
                    status_label: Open
                    closed_by_user_id: null
                    closed_at: null
                    cash_sales_total: '0.0000'
                    expected_cash: null
                    counted_cash: null
                    cash_variance: null
                    notes: null
                    created_at: '2026-06-19T14:02:11.000000Z'
                    updated_at: '2026-06-19T14:02:11.000000Z'
        '422':
          description: Unprocessable Content
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      register:
                        type: array
                        items:
                          type: string
                example:
                  message: You already have an open register session. Close it before
                    opening another.
                  errors:
                    register:
                    - You already have an open register session. Close it before opening
                      another.
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: post-api-pos-register-sessions
  /api/pos/register-sessions/{registerSession}/close:
    post:
      tags:
      - POS / Register
      summary: Close Register Session
      description: 'Closes a register session and performs cash reconciliation.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Expected cash = opening float + cash takings for the shift. Variance = counted
        cash − expected cash (positive = over, negative = short). The response returns
        the computed `expected_cash`, `counted_cash` and `cash_variance` for the X/Z
        report.


        Body fields:

        - `counted_cash` (numeric, required, min 0) — cash counted in the drawer at
        close.

        - `notes` (string, optional, max 1000).


        Returns 422 if the session is already closed.


        Authentication: Requires Bearer token (PAT).


        Requires permission: pos.operate (when granular permissions are enabled).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                counted_cash:
                  type: integer
                notes:
                  type: string
              example:
                counted_cash: 575
                notes: End of day — over by 5.02
      parameters:
      - name: registerSession
        in: path
        schema:
          type: integer
        required: true
        description: Register session ID
        example: '12'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      warehouse_id:
                        type: integer
                      warehouse_name:
                        type: string
                      opened_by_user_id:
                        type: integer
                      opened_by_name:
                        type: string
                      opened_at:
                        type: string
                      opening_float:
                        type: string
                      status:
                        type: string
                      status_label:
                        type: string
                      closed_by_user_id:
                        type: integer
                      closed_at:
                        type: string
                      cash_sales_total:
                        type: string
                      expected_cash:
                        type: string
                      counted_cash:
                        type: string
                      cash_variance:
                        type: string
                      notes:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 12
                    warehouse_id: 3
                    warehouse_name: Downtown Flagship
                    opened_by_user_id: 1
                    opened_by_name: Jane Cashier
                    opened_at: '2026-06-19T14:02:11.000000Z'
                    opening_float: '150.0000'
                    status: closed
                    status_label: Closed
                    closed_by_user_id: 1
                    closed_at: '2026-06-19T22:10:00.000000Z'
                    cash_sales_total: '419.9800'
                    expected_cash: '569.9800'
                    counted_cash: '575.0000'
                    cash_variance: '5.0200'
                    notes: End of day — over by 5.02
                    created_at: '2026-06-19T14:02:11.000000Z'
                    updated_at: '2026-06-19T14:02:11.000000Z'
        '422':
          description: Unprocessable Content
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      register:
                        type: array
                        items:
                          type: string
                example:
                  message: This register session is already closed.
                  errors:
                    register:
                    - This register session is already closed.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-session-only: true
      operationId: post-api-pos-register-sessions-registersession-close
  /api/pos/checkout:
    post:
      tags:
      - POS / Register
      summary: Ring Up Sale (Checkout)
      description: "Ring up a sale: cart lines + tender(s) become a paid, fully-fulfilled\
        \ sales order plus a POS transaction.\n\n:::warning[Not yet available to API\
        \ tokens]\nThis endpoint currently requires session authentication; Personal\
        \ Access Token scope support is in progress.\n:::\n\nAuthentication: Requires\
        \ Bearer token.\nPermission: `pos.operate`.\n\nRequest body fields:\n- `pos_register_session_id`\
        \ (integer, required) — the open session to ring against (must exist in `pos_register_sessions`).\n\
        - `tender_type` (enum, required) — one of `cash`, `card`, `store_credit`,\
        \ `split`.\n- `amount_tendered` (numeric, required, min 0) — amount the customer\
        \ handed over (for a single tender; may exceed the total for cash, yielding\
        \ change).\n- `customer_id` (integer, nullable) — attached customer; REQUIRED\
        \ when `tender_type` is `store_credit` (store credit debits the customer's\
        \ wallet).\n- `payment_source_id` (string, nullable, max 255) — tokenized\
        \ card source (Web Payments SDK nonce / Terminal ref); REQUIRED when `tender_type`\
        \ is `card`.\n- `tax_rate_id` (integer, nullable) — optional tax rate applied\
        \ to every line (must exist in `tax_rates`).\n- `apply_customer_pricing_tier`\
        \ (boolean, nullable) — opt-in: re-price each line from the customer's assigned\
        \ pricing tier instead of the register-submitted `unit_price`. Defaults to\
        \ false.\n- `idempotency_key` (string, nullable, max 255) — client-supplied\
        \ stable token; a retried checkout re-uses the same processor idempotency\
        \ key so a timed-out sale never double-charges.\n- `tenders` (array, nullable)\
        \ — optional split tender; when present, overrides the single `tender_type`/`amount_tendered`\
        \ and each entry is settled independently.\n  - `tenders.*.type` (enum, required\
        \ with `tenders`) — `cash`, `card`, `store_credit`, or `split`.\n  - `tenders.*.amount`\
        \ (numeric, required with `tenders`, min 0) — amount for this tender.\n  -\
        \ `tenders.*.payment_source_id` (string, nullable, max 255) — tokenized card\
        \ source for a card tender.\n- `lines` (array, required, min 1) — the cart.\n\
        \  - `lines.*.product_id` (integer, required) — must exist in `products`.\n\
        \  - `lines.*.quantity` (numeric, required, > 0).\n  - `lines.*.unit_price`\
        \ (numeric, required, min 0).\n\nFor a simple single-tender sale, omit `tenders`,\
        \ set `tender_type` to `cash`/`card`/`store_credit`, and set `amount_tendered`.\n\
        \nReturns 201 with the created POS transaction.\n\n**Gift card tender:** set\
        \ `tender_type` to `gift_card` with a top-level `gift_card_code`, or include\
        \ a split tender `{\"type\":\"gift_card\",\"amount\":..,\"gift_card_code\"\
        :\"..\"}`. One gift card per sale; the card is validated and debited atomically\
        \ inside the sale (rolls back on a concurrent drain). Store-credit and gift-card\
        \ tenders settle exactly (no change).\n\n**On-account tender:** set `tender_type`\
        \ to `on_account` (or add a split tender `{\"type\":\"on_account\",\"amount\"\
        :..}`) to charge the sale to the attached customer's house account. Requires\
        \ a customer with a house account enabled and enough credit-limit headroom;\
        \ the sale is recorded as PAID (settled on account) and the customer's house-account\
        \ balance increases.\n\n**Selling gift cards (gift_cards_to_sell):** Each\
        \ entry SELLS a new gift card to the customer. It is added to the order as\
        \ a non-product line posted to the Gift Card Liability nominal (Dr Cash /\
        \ Cr Liability — never revenue, never taxed) and the card is activated for\
        \ the paid amount on checkout. `amount` is required; `code` auto-generates\
        \ when omitted. Requires the Gift Card Liability nominal to be configured\
        \ (422 otherwise). `lines` is OPTIONAL when the sale is purely gift-card sales."
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                pos_register_session_id:
                  type: integer
                tender_type:
                  type: string
                amount_tendered:
                  type: integer
                customer_id:
                  type: integer
                payment_source_id:
                  type: string
                  nullable: true
                saved_payment_method_id:
                  type: string
                  nullable: true
                tax_rate_id:
                  type: integer
                apply_customer_pricing_tier:
                  type: boolean
                idempotency_key:
                  type: string
                gift_card_code:
                  type: string
                  nullable: true
                loyalty_points_to_redeem:
                  type: integer
                gift_cards_to_sell:
                  type: array
                  items:
                    type: object
                    properties:
                      amount:
                        type: integer
                      code:
                        type: string
                      security_code:
                        type: string
                        nullable: true
                      is_digital:
                        type: boolean
                      recipient_name:
                        type: string
                      recipient_email:
                        type: string
                      expires_at:
                        type: string
                        nullable: true
                lines:
                  type: array
                  items:
                    type: object
                    properties:
                      product_id:
                        type: integer
                      quantity:
                        type: integer
                      unit_price:
                        type: integer
              example:
                pos_register_session_id: 42
                tender_type: cash
                amount_tendered: 75
                customer_id: 88
                payment_source_id: null
                saved_payment_method_id: null
                tax_rate_id: 5
                apply_customer_pricing_tier: false
                idempotency_key: cart-6f1e9c2a-3b7d-4a1e-9f0c-2d5b8e4a7c11
                gift_card_code: null
                loyalty_points_to_redeem: 200
                gift_cards_to_sell:
                - amount: 50
                  code: GIFT-2026-0007
                  security_code: null
                  is_digital: false
                  recipient_name: Jane Doe
                  recipient_email: jane@example.com
                  expires_at: null
                lines:
                - product_id: 1201
                  quantity: 1
                  unit_price: 25
      parameters: []
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      pos_register_session_id:
                        type: integer
                      sales_order_id:
                        type: integer
                      sales_order_number:
                        type: string
                      customer_id:
                        type: integer
                      customer_name:
                        type: string
                      cashier_user_id:
                        type: integer
                      cashier_name:
                        type: string
                      tender_type:
                        type: string
                      tender_type_label:
                        type: string
                      subtotal:
                        type: integer
                      tax_total:
                        type: number
                      discount_total:
                        type: integer
                      total:
                        type: number
                      amount_tendered:
                        type: integer
                      change_due:
                        type: number
                      is_refunded:
                        type: boolean
                      refunded_at:
                        type: string
                        nullable: true
                      refund_amount:
                        type: string
                        nullable: true
                      refund_reference:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                example:
                  data:
                    id: 1001
                    pos_register_session_id: 42
                    sales_order_id: 55231
                    sales_order_number: POS-1001
                    customer_id: 88
                    customer_name: Walk-in Customer
                    cashier_user_id: 7
                    cashier_name: Jane Cashier
                    tender_type: cash
                    tender_type_label: Cash
                    subtotal: 100
                    tax_total: 8.25
                    discount_total: 0
                    total: 108.25
                    amount_tendered: 120
                    change_due: 11.75
                    is_refunded: false
                    refunded_at: null
                    refund_amount: null
                    refund_reference: null
                    created_at: '2026-07-06T14:22:00.000000Z'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      payment_source_id:
                        type: array
                        items:
                          type: string
                      lines:
                        type: array
                        items:
                          type: string
                example:
                  message: The payment source id field is required when tender type
                    is card. (and 1 more error)
                  errors:
                    payment_source_id:
                    - The payment source id field is required when tender type is
                      card.
                    lines:
                    - The lines field must have at least 1 items.
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: post-api-pos-checkout
  /api/pos/transactions/{posTransaction}/refund:
    post:
      tags:
      - POS / Register
      summary: Refund Transaction
      description: 'Refund a completed POS sale in full — credit and restock the items,
        then either refund the original tenders (card via processor, cash at the drawer)
        or top up the customer''s store-credit wallet.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.

        Permission: `pos.refund`.


        Request body fields:

        - `refund_to` (enum, nullable) — `original` (default; back to the original
        tenders) or `store_credit` (top up the attached customer''s wallet). Store
        credit requires a customer on the sale (enforced server-side). Omitting the
        field defaults to `original`.


        Refunds are serialized under a row lock so a duplicate refund aborts. Returns
        200 with the updated transaction (`is_refunded` true) and a message.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                refund_to:
                  type: string
              example:
                refund_to: original
      parameters:
      - name: posTransaction
        in: path
        schema:
          type: integer
        required: true
        description: The POS transaction (sale) id to refund.
        example: '1000'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 Refunded to original
                  value:
                    data:
                      id: 1000
                      pos_register_session_id: 42
                      sales_order_id: 55230
                      sales_order_number: POS-1000
                      customer_id: 88
                      customer_name: Walk-in Customer
                      cashier_user_id: 7
                      cashier_name: Jane Cashier
                      tender_type: card
                      tender_type_label: Card
                      subtotal: 45
                      tax_total: 3.71
                      discount_total: 0
                      total: 48.71
                      amount_tendered: 48.71
                      change_due: 0
                      is_refunded: true
                      refunded_at: '2026-07-06T15:10:00.000000Z'
                      refund_amount: 48.71
                      refund_reference: re_3Pabc1EF
                      created_at: '2026-07-06T13:05:00.000000Z'
                    message: Sale refunded — credited and restocked.
                example-1:
                  summary: 200 Refunded to store credit
                  value:
                    data:
                      id: 1000
                      pos_register_session_id: 42
                      sales_order_id: 55230
                      sales_order_number: POS-1000
                      customer_id: 88
                      customer_name: Walk-in Customer
                      cashier_user_id: 7
                      cashier_name: Jane Cashier
                      tender_type: card
                      tender_type_label: Card
                      subtotal: 45
                      tax_total: 3.71
                      discount_total: 0
                      total: 48.71
                      amount_tendered: 48.71
                      change_due: 0
                      is_refunded: true
                      refunded_at: '2026-07-06T15:10:00.000000Z'
                      refund_amount: 48.71
                      refund_reference: store-credit
                      created_at: '2026-07-06T13:05:00.000000Z'
                    message: Sale refunded to store credit — wallet topped up and
                      items restocked.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-session-only: true
      operationId: post-api-pos-transactions-postransaction-refund
  /api/pos/transactions/{posTransaction}/receipt:
    get:
      tags:
      - POS / Register
      summary: Get Receipt
      description: 'Return the printable receipt for a POS sale — assembled from the
        transaction, its sales order lines, and the register session.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.

        Permission: `pos.operate`.


        Response `data` includes business/register/cashier info, customer contact,
        line items (sku, name, quantity, unit_price, line_total), monetary totals,
        tax-exemption flags, tender info, and refund status.'
      parameters:
      - name: posTransaction
        in: path
        schema:
          type: integer
        required: true
        description: The POS transaction (sale) id.
        example: '1001'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      transaction_id:
                        type: integer
                      business_name:
                        type: string
                      register:
                        type: string
                      cashier:
                        type: string
                      sales_order_number:
                        type: string
                      customer_id:
                        type: integer
                      customer_name:
                        type: string
                      customer_email:
                        type: string
                      customer_phone:
                        type: string
                      sold_at:
                        type: string
                      lines:
                        type: array
                        items:
                          type: object
                          properties:
                            sku:
                              type: string
                            name:
                              type: string
                            quantity:
                              type: integer
                            unit_price:
                              type: integer
                            line_total:
                              type: integer
                      subtotal:
                        type: integer
                      tax_total:
                        type: number
                      discount_total:
                        type: integer
                      tax_exempt:
                        type: boolean
                      tax_exemption_reference:
                        type: string
                        nullable: true
                      total:
                        type: number
                      tender_type:
                        type: string
                      tender_type_label:
                        type: string
                      amount_tendered:
                        type: integer
                      change_due:
                        type: number
                      is_refunded:
                        type: boolean
                      refunded_at:
                        type: string
                        nullable: true
                      refund_amount:
                        type: string
                        nullable: true
                example:
                  data:
                    transaction_id: 1001
                    business_name: Acme Retail
                    register: Downtown Store
                    cashier: Jane Cashier
                    sales_order_number: POS-1001
                    customer_id: 88
                    customer_name: Walk-in Customer
                    customer_email: customer@example.com
                    customer_phone: +1-555-0100
                    sold_at: '2026-07-06T14:22:00.000000Z'
                    lines:
                    - sku: WIDGET-001
                      name: Blue Widget
                      quantity: 2
                      unit_price: 25
                      line_total: 50
                    - sku: GADGET-050
                      name: Deluxe Gadget
                      quantity: 1
                      unit_price: 50
                      line_total: 50
                    subtotal: 100
                    tax_total: 8.25
                    discount_total: 0
                    tax_exempt: false
                    tax_exemption_reference: null
                    total: 108.25
                    tender_type: cash
                    tender_type_label: Cash
                    amount_tendered: 120
                    change_due: 11.75
                    is_refunded: false
                    refunded_at: null
                    refund_amount: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-session-only: true
      operationId: get-api-pos-transactions-postransaction-receipt
  /api/pos/transactions:
    get:
      tags:
      - POS / Register
      summary: List Transactions
      description: 'Paginated POS transaction (sales) history.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.

        Permission: `pos.operate`.


        Filters (Spatie QueryBuilder, all optional):

        - `filter[pos_register_session_id]` — exact register session id.

        - `filter[tender_type]` — exact tender type (cash, card, store_credit, split).

        - `filter[refunded]` — boolean; true = refunded only, false = non-refunded
        only.

        - `filter[date_from]` / `filter[date_to]` — created_at date range (Y-m-d).


        Sorts: `id`, `total`, `created_at` (prefix `-` for DESC). Default sort: `-created_at`.

        Pagination: `page` (default 1), `per_page` (default 15). Response includes
        standard Laravel pagination metadata.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        pos_register_session_id:
                          type: integer
                        sales_order_id:
                          type: integer
                        sales_order_number:
                          type: string
                        customer_id:
                          type: string
                          nullable: true
                        customer_name:
                          type: string
                          nullable: true
                        cashier_user_id:
                          type: integer
                        cashier_name:
                          type: string
                        tender_type:
                          type: string
                        tender_type_label:
                          type: string
                        subtotal:
                          type: integer
                        tax_total:
                          type: number
                        discount_total:
                          type: integer
                        total:
                          type: number
                        amount_tendered:
                          type: integer
                        change_due:
                          type: number
                        is_refunded:
                          type: boolean
                        refunded_at:
                          type: string
                          nullable: true
                        refund_amount:
                          type: string
                          nullable: true
                        refund_reference:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                  current_page:
                    type: integer
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  next_page_url:
                    type: string
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 1001
                    pos_register_session_id: 42
                    sales_order_id: 55231
                    sales_order_number: POS-1001
                    customer_id: null
                    customer_name: null
                    cashier_user_id: 7
                    cashier_name: Jane Cashier
                    tender_type: cash
                    tender_type_label: Cash
                    subtotal: 100
                    tax_total: 8.25
                    discount_total: 0
                    total: 108.25
                    amount_tendered: 120
                    change_due: 11.75
                    is_refunded: false
                    refunded_at: null
                    refund_amount: null
                    refund_reference: null
                    created_at: '2026-07-06T14:22:00.000000Z'
                  - id: 1000
                    pos_register_session_id: 42
                    sales_order_id: 55230
                    sales_order_number: POS-1000
                    customer_id: null
                    customer_name: null
                    cashier_user_id: 7
                    cashier_name: Jane Cashier
                    tender_type: card
                    tender_type_label: Card
                    subtotal: 45
                    tax_total: 3.71
                    discount_total: 0
                    total: 48.71
                    amount_tendered: 48.71
                    change_due: 0
                    is_refunded: true
                    refunded_at: '2026-07-06T15:10:00.000000Z'
                    refund_amount: 48.71
                    refund_reference: re_3Pabc0EF
                    created_at: '2026-07-06T13:05:00.000000Z'
                  current_page: 1
                  first_page_url: '{{protocol}}{{domain}}/api/pos/transactions?page=1'
                  from: 1
                  last_page: 4
                  last_page_url: '{{protocol}}{{domain}}/api/pos/transactions?page=4'
                  next_page_url: '{{protocol}}{{domain}}/api/pos/transactions?page=2'
                  path: '{{protocol}}{{domain}}/api/pos/transactions'
                  per_page: 15
                  prev_page_url: null
                  to: 15
                  total: 52
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: get-api-pos-transactions
  /api/pos/settings:
    get:
      tags:
      - POS / Register
      summary: Get POS Settings
      description: 'Return the register''s operational settings. Requires a Bearer
        token with `pos.operate`.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Includes the master `enabled` flag, the `require_customer` and `auto_print_receipt`
        behaviour toggles, the active card `payment_processor` (square|stripe), the
        Square `square_location_id`, and the list of `available_processors`. The admin-facing
        toggles are also editable via `PUT /api/v2/settings/pos`.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      enabled:
                        type: boolean
                      require_customer:
                        type: boolean
                      auto_print_receipt:
                        type: boolean
                      payment_processor:
                        type: string
                      square_location_id:
                        type: string
                      available_processors:
                        type: array
                        items:
                          type: object
                          properties:
                            value:
                              type: string
                            label:
                              type: string
                example:
                  data:
                    enabled: true
                    require_customer: false
                    auto_print_receipt: false
                    payment_processor: square
                    square_location_id: L7X8Y9Z0ABCDE
                    available_processors:
                    - value: square
                      label: Square
                    - value: stripe
                      label: Stripe
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: get-api-pos-settings
    put:
      tags:
      - POS / Register
      summary: Update POS Settings
      description: 'Update the register settings. Requires a Bearer token with `pos.manage`.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        - `payment_processor` (required) — `square` or `stripe`.

        - `square_location_id` (optional, nullable) — the Square location the Web
        Payments SDK initialises against.


        The admin toggles (`enabled`, `require_customer`, `auto_print_receipt`) are
        managed via `PUT /api/v2/settings/pos`; this endpoint focuses on the operational
        card-processor config.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                enabled:
                  type: boolean
                require_customer:
                  type: boolean
                auto_print_receipt:
                  type: boolean
                payment_processor:
                  type: string
                square_location_id:
                  type: string
              example:
                enabled: true
                require_customer: false
                auto_print_receipt: true
                payment_processor: square
                square_location_id: L7X8Y9Z0ABCDE
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      enabled:
                        type: boolean
                      require_customer:
                        type: boolean
                      auto_print_receipt:
                        type: boolean
                      payment_processor:
                        type: string
                      square_location_id:
                        type: string
                      available_processors:
                        type: array
                        items:
                          type: object
                          properties:
                            value:
                              type: string
                            label:
                              type: string
                  message:
                    type: string
                example:
                  data:
                    enabled: true
                    require_customer: false
                    auto_print_receipt: true
                    payment_processor: square
                    square_location_id: L7X8Y9Z0ABCDE
                    available_processors:
                    - value: square
                      label: Square
                    - value: stripe
                      label: Stripe
                  message: POS settings updated.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-session-only: true
      operationId: put-api-pos-settings
  /api/pos/payment-config:
    get:
      tags:
      - POS / Register
      summary: Get Payment Config
      description: 'Return the active processor''s public web-payments config that
        the in-browser SDK needs to render a card form. No secrets are returned.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.

        Permission: `pos.operate`.


        For Square: `processor`, `application_id`, `location_id`, `environment` (so
        the register can load the Web Payments SDK and tokenize a card client-side).

        For Stripe: `processor`, `publishable_key`, `stripe_account` (Stripe.js Elements
        uses both, since card payments are direct charges on the tenant''s connected
        account).'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 Square
                  value:
                    data:
                      processor: square
                      application_id: sandbox-sq0idb-Ab12Cd34Ef56Gh78Ij90Kl
                      location_id: L7X8Y9Z0ABCDE
                      environment: sandbox
                example-1:
                  summary: 200 Stripe
                  value:
                    data:
                      processor: stripe
                      publishable_key: pk_test_51AbCdEfGhIjKlMnOpQrStUv
                      stripe_account: acct_1AbCdEfGhIjKlMno
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: get-api-pos-payment-config
  /api/pos/square/locations:
    get:
      tags:
      - POS / Register
      summary: List Square Locations
      description: 'List the merchant''s Square locations, for the settings location
        picker. Returns an empty array if Square is unreachable or not configured.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        Authentication: Requires Bearer token.

        Permission: `pos.manage`.


        Each location: `id`, `name`, `status`.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: string
                        name:
                          type: string
                        status:
                          type: string
                example:
                  data:
                  - id: L7X8Y9Z0ABCDE
                    name: Downtown Store
                    status: ACTIVE
                  - id: LMNOP1234567Q
                    name: Warehouse Outlet
                    status: ACTIVE
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: get-api-pos-square-locations
  /api/pos/transactions/{posTransaction}/receipt/send:
    post:
      tags:
      - POS / Register
      summary: Send POS Receipt (E-Receipt)
      description: 'Delivers the POS sale''s e-receipt to an ad-hoc email and/or phone
        target and records the marketing opt-in captured at the register. Requires
        permission: pos.operate.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        The target is captured ad-hoc — it is NOT read from the customer''s CRM record
        — so a walk-in can get an e-receipt without becoming a customer, and an attached
        customer can have it sent to a different address than the one on file.


        Channels: `email` is sent synchronously (the response reflects sent/failed
        immediately); `phone` is recorded as a `pending` SMS delivery because no SMS
        provider is wired yet — the intent is stored and can be fulfilled once an
        SMS channel exists.


        Marketing opt-in (tri-state): `true` opts the attached customer into email
        marketing, `false` opts them out, and omitting the field leaves their existing
        preference unchanged. It is only applied when a customer is attached to the
        sale (guest checkouts skip it).


        Request body:

        - `email` (string, nullable) — email address to send the receipt to. Required
        when `phone` is absent.

        - `phone` (string, nullable, max 32) — phone number for an SMS receipt (captured
        as pending). Required when `email` is absent.

        - `marketing_opt_in` (boolean, nullable) — marketing consent captured at send
        time.


        Returns one delivery record per channel used (201 Created).


        Authentication: Requires Bearer token (PAT).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                email:
                  type: string
                phone:
                  type: string
                marketing_opt_in:
                  type: boolean
              example:
                email: jane@acme.test
                phone: +1 555-0142
                marketing_opt_in: true
      parameters:
      - name: posTransaction
        in: path
        schema:
          type: integer
        required: true
        description: POS transaction ID
        example: '88'
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        pos_transaction_id:
                          type: integer
                        channel:
                          type: string
                        channel_label:
                          type: string
                        target:
                          type: string
                        status:
                          type: string
                        status_label:
                          type: string
                        marketing_opt_in:
                          type: boolean
                        sent_by_user_id:
                          type: integer
                        error:
                          type: string
                          nullable: true
                        sent_at:
                          type: string
                        created_at:
                          type: string
                example:
                  data:
                  - id: 141
                    pos_transaction_id: 88
                    channel: email
                    channel_label: Email
                    target: jane@acme.test
                    status: sent
                    status_label: Sent
                    marketing_opt_in: true
                    sent_by_user_id: 12
                    error: null
                    sent_at: '2026-07-06T14:22:10.000000Z'
                    created_at: '2026-07-06T14:22:10.000000Z'
                  - id: 142
                    pos_transaction_id: 88
                    channel: sms
                    channel_label: SMS
                    target: '+15550142'
                    status: pending
                    status_label: Pending
                    marketing_opt_in: true
                    sent_by_user_id: 12
                    error: null
                    sent_at: null
                    created_at: '2026-07-06T14:22:10.000000Z'
        '422':
          description: Unprocessable Content
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      email:
                        type: array
                        items:
                          type: string
                      phone:
                        type: array
                        items:
                          type: string
                example:
                  message: Provide an email address or a phone number to send the
                    receipt to.
                  errors:
                    email:
                    - Provide an email address or a phone number to send the receipt
                      to.
                    phone:
                    - Provide a phone number or an email address to send the receipt
                      to.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-session-only: true
      operationId: post-api-pos-transactions-postransaction-receipt-send
  /api/v2/pick-lists:
    get:
      tags:
      - Pick Lists
      summary: List Pick Lists
      description: 'Paginated pick lists with per-status line counts for a progress
        bar.


        Authentication: Requires Bearer token. Scope: warehouses.

        Search (filter[search]) spans pick list number, order number, item SKU, bin
        code, and id. Filters: status, warehouse_id, assigned_to_user_id, created_at,
        started_at, completed_at (plain filter[...] or the filter_groups advanced
        tree). Sorts: id, number, status, created_at, started_at, completed_at.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        number:
                          type: string
                        warehouse_id:
                          type: integer
                        warehouse:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        status:
                          type: string
                        status_label:
                          type: string
                        assigned_to:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        notes:
                          type: string
                          nullable: true
                        lines_count:
                          type: integer
                        resolved_lines_count:
                          type: integer
                        started_at:
                          type: string
                          nullable: true
                        completed_at:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - id: 7
                    number: PL-000007
                    warehouse_id: 1
                    warehouse:
                      id: 1
                      name: Main Warehouse
                    status: pending
                    status_label: Pending
                    assigned_to:
                      id: 3
                      name: Casey Picker
                    notes: null
                    lines_count: 2
                    resolved_lines_count: 0
                    started_at: null
                    completed_at: null
                    created_at: '2026-01-15T10:00:00.000000Z'
                  current_page: 1
                  last_page: 1
                  per_page: 10
                  total: 1
                  from: 1
                  to: 1
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-v2-pick-lists
    post:
      tags:
      - Pick Lists
      summary: Create Pick List
      description: 'Create a pick list from fulfillment orders at one warehouse. Each
        order line is allocated to bins (split across bins as needed) and sequenced
        into a walk path; order lines already on an open pick list are skipped.


        Body fields:

        - warehouse_id (required) — all orders must be at this warehouse.

        - fulfillment_order_ids (required, array) — the orders to pick.


        Authentication: Requires Bearer token. Requires the sales_orders.fulfill permission.
        Returns 422 when the orders have nothing left to pick or no lines match the
        warehouse.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                warehouse_id:
                  type: integer
                fulfillment_order_ids:
                  type: array
                  items:
                    type: integer
              example:
                warehouse_id: 1
                fulfillment_order_ids:
                - 812
                - 815
      parameters: []
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      number:
                        type: string
                      warehouse_id:
                        type: integer
                      warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      status:
                        type: string
                      status_label:
                        type: string
                      assigned_to:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      notes:
                        type: string
                        nullable: true
                      lines_count:
                        type: integer
                      resolved_lines_count:
                        type: integer
                      started_at:
                        type: string
                        nullable: true
                      completed_at:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            sequence:
                              type: integer
                            fulfillment_order_line_id:
                              type: integer
                            product_id:
                              type: integer
                            warehouse_location_id:
                              type: integer
                            quantity:
                              type: integer
                            quantity_picked:
                              type: integer
                            status:
                              type: string
                            status_label:
                              type: string
                            has_bin:
                              type: boolean
                            picked_at:
                              type: string
                              nullable: true
                            location:
                              type: object
                              properties:
                                id:
                                  type: integer
                                code:
                                  type: string
                                name:
                                  type: string
                                type:
                                  type: string
                                type_label:
                                  type: string
                                barcode:
                                  type: string
                            product:
                              type: object
                              properties:
                                id:
                                  type: integer
                                sku:
                                  type: string
                                name:
                                  type: string
                                barcode:
                                  type: string
                                image_url:
                                  type: string
                                  nullable: true
                            order_number:
                              type: string
                  message:
                    type: string
                example:
                  data:
                    id: 7
                    number: PL-000007
                    warehouse_id: 1
                    warehouse:
                      id: 1
                      name: Main Warehouse
                    status: pending
                    status_label: Pending
                    assigned_to:
                      id: 3
                      name: Casey Picker
                    notes: null
                    lines_count: 2
                    resolved_lines_count: 0
                    started_at: null
                    completed_at: null
                    created_at: '2026-01-15T10:00:00.000000Z'
                    lines:
                    - id: 55
                      sequence: 1
                      fulfillment_order_line_id: 812
                      product_id: 42
                      warehouse_location_id: 12
                      quantity: 5
                      quantity_picked: 0
                      status: pending
                      status_label: Pending
                      has_bin: true
                      picked_at: null
                      location:
                        id: 12
                        code: A-01
                        name: Aisle A
                        type: primary_pick
                        type_label: Primary Pick
                        barcode: A-01
                      product:
                        id: 42
                        sku: WIDGET-001
                        name: Premium Widget
                        barcode: '4006381333931'
                        image_url: null
                      order_number: SO-00123
                    - id: 56
                      sequence: 2
                      fulfillment_order_line_id: 813
                      product_id: 42
                      warehouse_location_id: 12
                      quantity: 3
                      quantity_picked: 0
                      status: pending
                      status_label: Pending
                      has_bin: true
                      picked_at: null
                      location:
                        id: 14
                        code: B-14
                        name: null
                        type: reserve
                        type_label: Reserve
                        barcode: B-14
                      product:
                        id: 42
                        sku: WIDGET-001
                        name: Premium Widget
                        barcode: '4006381333931'
                        image_url: null
                      order_number: SO-00123
                  message: Pick list created.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: These fulfillment orders have nothing left to pick — their
                    lines are already on an open pick list.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-v2-pick-lists
  /api/v2/pick-lists/export:
    get:
      tags:
      - Pick Lists
      summary: Export Pick Lists
      description: 'Download the pick list results as an Excel/CSV file.


        Authentication: Requires Bearer token. Scope: warehouses.

        content_mode=summary yields one row per pick list (Pick List #, Warehouse,
        Status, Lines, Resolved, Orders, Assignee, Created, Started, Completed). content_mode=line_items
        yields one row per pick line (Pick List #, Warehouse, Seq, Bin, SKU, Product,
        Order #, Qty, Qty Picked, Line Status).

        scope=filtered honours the active filters; scope=all ignores them; scope=selected
        restricts to the ids param.


        Returns a binary file download (Content-Type application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
        for xlsx, text/csv for csv), not JSON.'
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-v2-pick-lists-export
  /api/v2/pick-lists/{pickList}:
    get:
      tags:
      - Pick Lists
      summary: Get Pick List
      description: 'A pick list with its ordered lines (bin, product, quantity, per-line
        status) — the payload the scan-to-pick screen drives from.


        Authentication: Requires Bearer token. Scope: warehouses.'
      parameters:
      - name: pickList
        in: path
        schema:
          type: integer
        required: true
        description: Pick list id
        example: '7'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      number:
                        type: string
                      warehouse_id:
                        type: integer
                      warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      status:
                        type: string
                      status_label:
                        type: string
                      assigned_to:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      notes:
                        type: string
                        nullable: true
                      lines_count:
                        type: integer
                      resolved_lines_count:
                        type: integer
                      started_at:
                        type: string
                        nullable: true
                      completed_at:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            sequence:
                              type: integer
                            fulfillment_order_line_id:
                              type: integer
                            product_id:
                              type: integer
                            warehouse_location_id:
                              type: integer
                            quantity:
                              type: integer
                            quantity_picked:
                              type: integer
                            status:
                              type: string
                            status_label:
                              type: string
                            has_bin:
                              type: boolean
                            picked_at:
                              type: string
                              nullable: true
                            location:
                              type: object
                              properties:
                                id:
                                  type: integer
                                code:
                                  type: string
                                name:
                                  type: string
                                type:
                                  type: string
                                type_label:
                                  type: string
                                barcode:
                                  type: string
                            product:
                              type: object
                              properties:
                                id:
                                  type: integer
                                sku:
                                  type: string
                                name:
                                  type: string
                                barcode:
                                  type: string
                                image_url:
                                  type: string
                                  nullable: true
                            order_number:
                              type: string
                example:
                  data:
                    id: 7
                    number: PL-000007
                    warehouse_id: 1
                    warehouse:
                      id: 1
                      name: Main Warehouse
                    status: pending
                    status_label: Pending
                    assigned_to:
                      id: 3
                      name: Casey Picker
                    notes: null
                    lines_count: 2
                    resolved_lines_count: 0
                    started_at: null
                    completed_at: null
                    created_at: '2026-01-15T10:00:00.000000Z'
                    lines:
                    - id: 55
                      sequence: 1
                      fulfillment_order_line_id: 812
                      product_id: 42
                      warehouse_location_id: 12
                      quantity: 5
                      quantity_picked: 0
                      status: pending
                      status_label: Pending
                      has_bin: true
                      picked_at: null
                      location:
                        id: 12
                        code: A-01
                        name: Aisle A
                        type: primary_pick
                        type_label: Primary Pick
                        barcode: A-01
                      product:
                        id: 42
                        sku: WIDGET-001
                        name: Premium Widget
                        barcode: '4006381333931'
                        image_url: null
                      order_number: SO-00123
                    - id: 56
                      sequence: 2
                      fulfillment_order_line_id: 813
                      product_id: 42
                      warehouse_location_id: 12
                      quantity: 3
                      quantity_picked: 0
                      status: pending
                      status_label: Pending
                      has_bin: true
                      picked_at: null
                      location:
                        id: 14
                        code: B-14
                        name: null
                        type: reserve
                        type_label: Reserve
                        barcode: B-14
                      product:
                        id: 42
                        sku: WIDGET-001
                        name: Premium Widget
                        barcode: '4006381333931'
                        image_url: null
                      order_number: SO-00123
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-v2-pick-lists-picklist
    delete:
      tags:
      - Pick Lists
      summary: Delete Pick List
      description: 'Permanently delete a pick list and its lines. Does not reverse
        any fulfillment already recorded.


        Authentication: Requires Bearer token. Permission: sales_orders.fulfill.'
      parameters:
      - name: pickList
        in: path
        schema:
          type: integer
        required: true
        example: '3'
        description: The pick list ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Pick list deleted.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-v2-pick-lists-picklist
  /api/v2/pick-lists/{pickList}/start:
    put:
      tags:
      - Pick Lists
      summary: Start Pick List
      description: 'Move a pending pick list to in_progress and stamp the start time.
        (The first pick also starts the list automatically.)


        Authentication: Requires Bearer token. Requires the sales_orders.fulfill permission.
        Returns 422 on an invalid status transition.'
      requestBody:
        content: {}
      parameters:
      - name: pickList
        in: path
        schema:
          type: integer
        required: true
        example: '7'
        description: The pick list ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      number:
                        type: string
                      warehouse_id:
                        type: integer
                      warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      status:
                        type: string
                      status_label:
                        type: string
                      assigned_to:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      notes:
                        type: string
                        nullable: true
                      lines_count:
                        type: integer
                      resolved_lines_count:
                        type: integer
                      started_at:
                        type: string
                      completed_at:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 7
                    number: PL-000007
                    warehouse_id: 1
                    warehouse:
                      id: 1
                      name: Main Warehouse
                    status: in_progress
                    status_label: In Progress
                    assigned_to:
                      id: 3
                      name: Casey Picker
                    notes: null
                    lines_count: 2
                    resolved_lines_count: 0
                    started_at: '2026-01-15T10:05:00.000000Z'
                    completed_at: null
                    created_at: '2026-01-15T10:00:00.000000Z'
                  message: Pick list started.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-v2-pick-lists-picklist-start
  /api/v2/pick-lists/{pickList}/complete:
    put:
      tags:
      - Pick Lists
      summary: Complete Pick List
      description: 'Complete an in-progress pick list (all lines should be resolved
        first).


        Authentication: Requires Bearer token. Requires the sales_orders.fulfill permission.
        Returns 422 on an invalid status transition.'
      requestBody:
        content: {}
      parameters:
      - name: pickList
        in: path
        schema:
          type: integer
        required: true
        example: '7'
        description: The pick list ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      number:
                        type: string
                      warehouse_id:
                        type: integer
                      warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      status:
                        type: string
                      status_label:
                        type: string
                      assigned_to:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      notes:
                        type: string
                        nullable: true
                      lines_count:
                        type: integer
                      resolved_lines_count:
                        type: integer
                      started_at:
                        type: string
                        nullable: true
                      completed_at:
                        type: string
                      created_at:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 7
                    number: PL-000007
                    warehouse_id: 1
                    warehouse:
                      id: 1
                      name: Main Warehouse
                    status: completed
                    status_label: Completed
                    assigned_to:
                      id: 3
                      name: Casey Picker
                    notes: null
                    lines_count: 2
                    resolved_lines_count: 0
                    started_at: null
                    completed_at: '2026-01-15T10:20:00.000000Z'
                    created_at: '2026-01-15T10:00:00.000000Z'
                  message: Pick list completed.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-v2-pick-lists-picklist-complete
  /api/v2/pick-lists/{pickList}/cancel:
    put:
      tags:
      - Pick Lists
      summary: Cancel Pick List
      description: 'Cancel an open pick list. The orders can be picked again via a
        new pick list.


        Authentication: Requires Bearer token. Requires the sales_orders.fulfill permission.'
      requestBody:
        content: {}
      parameters:
      - name: pickList
        in: path
        schema:
          type: integer
        required: true
        example: '7'
        description: The pick list ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      number:
                        type: string
                      warehouse_id:
                        type: integer
                      warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      status:
                        type: string
                      status_label:
                        type: string
                      assigned_to:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      notes:
                        type: string
                        nullable: true
                      lines_count:
                        type: integer
                      resolved_lines_count:
                        type: integer
                      started_at:
                        type: string
                        nullable: true
                      completed_at:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 7
                    number: PL-000007
                    warehouse_id: 1
                    warehouse:
                      id: 1
                      name: Main Warehouse
                    status: cancelled
                    status_label: Cancelled
                    assigned_to:
                      id: 3
                      name: Casey Picker
                    notes: null
                    lines_count: 2
                    resolved_lines_count: 0
                    started_at: null
                    completed_at: null
                    created_at: '2026-01-15T10:00:00.000000Z'
                  message: Pick list cancelled.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-v2-pick-lists-picklist-cancel
  /api/v2/pick-lists/{pickList}/fulfill:
    post:
      tags:
      - Pick Lists
      summary: Fulfill Pick List
      description: 'Fulfill a completed pick list — ship each picked / short-picked
        line from the exact bin it was pulled from, creating one fulfillment per sales
        order. Skipped and unpicked units stay open for a later pick.


        Authentication: Requires Bearer token. Scope: warehouses. Permission: sales_orders.fulfill.


        The pick list must be Completed and not already fulfilled (idempotent — a
        422 is returned otherwise). Returns the updated pick list plus a summary of
        fulfilled and failed orders.'
      requestBody:
        content: {}
      parameters:
      - name: pickList
        in: path
        schema:
          type: integer
        required: true
        description: Pick list id
        example: '3'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      number:
                        type: string
                      status:
                        type: string
                      status_label:
                        type: string
                      completed_at:
                        type: string
                      fulfilled_at:
                        type: string
                  summary:
                    type: object
                    properties:
                      fulfilled:
                        type: array
                        items:
                          type: object
                          properties:
                            sales_order_id:
                              type: integer
                            sales_order_number:
                              type: string
                            units:
                              type: integer
                            fulfillment_id:
                              type: integer
                      failed:
                        type: array
                      total_units:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    id: 3
                    number: PL-000003
                    status: completed
                    status_label: Completed
                    completed_at: '2026-07-10T01:05:00.000000Z'
                    fulfilled_at: '2026-07-10T01:12:00.000000Z'
                  summary:
                    fulfilled:
                    - sales_order_id: 3050
                      sales_order_number: SO-3050
                      units: 5
                      fulfillment_id: 8123
                    failed: []
                    total_units: 5
                  message: Fulfilled 1 order from the picked bins.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: This pick list has already been fulfilled.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-v2-pick-lists-picklist-fulfill
  /api/v2/pick-list-lines/{pickListLine}/pick:
    put:
      tags:
      - Pick Lists
      summary: Pick Pick List Line
      description: 'Record a pick against a line. A quantity equal to the line quantity
        marks it picked; less marks it short_picked (clamped to [0, line quantity]).
        The first pick auto-starts the pick list.


        Authentication: Requires Bearer token. Requires the sales_orders.fulfill permission.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                quantity:
                  type: integer
              example:
                quantity: 5
      parameters:
      - name: pickListLine
        in: path
        schema:
          type: integer
        required: true
        description: Pick list line id
        example: '55'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      sequence:
                        type: integer
                      fulfillment_order_line_id:
                        type: integer
                      product_id:
                        type: integer
                      warehouse_location_id:
                        type: integer
                      quantity:
                        type: integer
                      quantity_picked:
                        type: integer
                      status:
                        type: string
                      status_label:
                        type: string
                      has_bin:
                        type: boolean
                      picked_at:
                        type: string
                      location:
                        type: object
                        properties:
                          id:
                            type: integer
                          code:
                            type: string
                          name:
                            type: string
                          type:
                            type: string
                          type_label:
                            type: string
                          barcode:
                            type: string
                      product:
                        type: object
                        properties:
                          id:
                            type: integer
                          sku:
                            type: string
                          name:
                            type: string
                          barcode:
                            type: string
                          image_url:
                            type: string
                            nullable: true
                      order_number:
                        type: string
                example:
                  data:
                    id: 55
                    sequence: 1
                    fulfillment_order_line_id: 812
                    product_id: 42
                    warehouse_location_id: 12
                    quantity: 5
                    quantity_picked: 5
                    status: picked
                    status_label: Picked
                    has_bin: true
                    picked_at: '2026-01-15T10:06:00.000000Z'
                    location:
                      id: 12
                      code: A-01
                      name: Aisle A
                      type: primary_pick
                      type_label: Primary Pick
                      barcode: A-01
                    product:
                      id: 42
                      sku: WIDGET-001
                      name: Premium Widget
                      barcode: '4006381333931'
                      image_url: null
                    order_number: SO-00123
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-v2-pick-list-lines-picklistline-pick
  /api/v2/pick-list-lines/{pickListLine}/skip:
    put:
      tags:
      - Pick Lists
      summary: Skip Pick List Line
      description: 'Skip a line (e.g. the stock isn''t in the bin). The first action
        auto-starts the pick list.


        Authentication: Requires Bearer token. Requires the sales_orders.fulfill permission.'
      requestBody:
        content: {}
      parameters:
      - name: pickListLine
        in: path
        schema:
          type: integer
        required: true
        example: '55'
        description: The pick list line ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      sequence:
                        type: integer
                      fulfillment_order_line_id:
                        type: integer
                      product_id:
                        type: integer
                      warehouse_location_id:
                        type: integer
                      quantity:
                        type: integer
                      quantity_picked:
                        type: integer
                      status:
                        type: string
                      status_label:
                        type: string
                      has_bin:
                        type: boolean
                      picked_at:
                        type: string
                      location:
                        type: object
                        properties:
                          id:
                            type: integer
                          code:
                            type: string
                          name:
                            type: string
                          type:
                            type: string
                          type_label:
                            type: string
                          barcode:
                            type: string
                      product:
                        type: object
                        properties:
                          id:
                            type: integer
                          sku:
                            type: string
                          name:
                            type: string
                          barcode:
                            type: string
                          image_url:
                            type: string
                            nullable: true
                      order_number:
                        type: string
                example:
                  data:
                    id: 55
                    sequence: 1
                    fulfillment_order_line_id: 812
                    product_id: 42
                    warehouse_location_id: 12
                    quantity: 5
                    quantity_picked: 0
                    status: skipped
                    status_label: Skipped
                    has_bin: true
                    picked_at: '2026-01-15T10:07:00.000000Z'
                    location:
                      id: 12
                      code: A-01
                      name: Aisle A
                      type: primary_pick
                      type_label: Primary Pick
                      barcode: A-01
                    product:
                      id: 42
                      sku: WIDGET-001
                      name: Premium Widget
                      barcode: '4006381333931'
                      image_url: null
                    order_number: SO-00123
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-v2-pick-list-lines-picklistline-skip
  /api/export/pick-lists/{pickList}/pdf:
    get:
      tags:
      - Pick Lists
      summary: Download Pick List PDF
      description: 'Stream the pick list as a printable PDF (inline), rendered from
        its stored lines in walk-path order. Rendered from the configurable Pick List
        template.


        Authentication: Requires Bearer token. Returns 422 when the pick list has
        no lines or no pick list template is configured.'
      parameters:
      - name: pickList
        in: path
        schema:
          type: integer
        required: true
        example: '7'
        description: The pick list ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/pdf
          content:
            text/plain:
              schema:
                type: string
                example: '%PDF-1.4 … binary PDF stream (the rendered pick list)'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-export-pick-lists-picklist-pdf
  /api/v2/pick-lists/{pickList}/archive:
    put:
      tags:
      - Pick Lists
      summary: Archive Pick List
      description: 'Archive a pick list (soft — hidden from the default list, restorable).


        Authentication: Requires Bearer token. Permission: sales_orders.fulfill.'
      requestBody:
        content: {}
      parameters:
      - name: pickList
        in: path
        schema:
          type: integer
        required: true
        example: '3'
        description: The pick list ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      number:
                        type: string
                      status:
                        type: string
                      archived_at:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 3
                    number: PL-000003
                    status: completed
                    archived_at: '2026-07-10T10:00:00.000000Z'
                  message: Pick list archived.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-v2-pick-lists-picklist-archive
  /api/v2/pick-lists/{pickList}/unarchive:
    put:
      tags:
      - Pick Lists
      summary: Unarchive Pick List
      description: 'Restore an archived pick list.


        Authentication: Requires Bearer token. Permission: sales_orders.fulfill.'
      requestBody:
        content: {}
      parameters:
      - name: pickList
        in: path
        schema:
          type: integer
        required: true
        example: '3'
        description: The pick list ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      number:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                  message:
                    type: string
                example:
                  data:
                    id: 3
                    number: PL-000003
                    archived_at: null
                  message: Pick list restored.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-v2-pick-lists-picklist-unarchive
  /api/v2/pick-lists/bulk-archive:
    post:
      tags:
      - Pick Lists
      summary: Bulk Archive Pick Lists
      description: 'Archive many pick lists. Send explicit ids, or omit ids to target
        every pick list matching the current filters.


        Authentication: Requires Bearer token. Permission: sales_orders.fulfill.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 3
                - 4
                - 5
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      count:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    count: 3
                  message: 3 pick list(s) archived.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-v2-pick-lists-bulk-archive
  /api/v2/pick-lists/bulk-unarchive:
    post:
      tags:
      - Pick Lists
      summary: Bulk Unarchive Pick Lists
      description: 'Restore many archived pick lists. Send explicit ids, or omit ids
        to target the current filters.


        Authentication: Requires Bearer token. Permission: sales_orders.fulfill.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 3
                - 4
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      count:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    count: 2
                  message: 2 pick list(s) restored.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-v2-pick-lists-bulk-unarchive
  /api/v2/pick-lists/bulk-delete:
    post:
      tags:
      - Pick Lists
      summary: Bulk Delete Pick Lists
      description: 'Permanently delete many pick lists (and their lines). Send explicit
        ids, or omit ids to target the current filters.


        Authentication: Requires Bearer token. Permission: sales_orders.fulfill.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 3
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      count:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    count: 1
                  message: 1 pick list(s) deleted.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-v2-pick-lists-bulk-delete
  /api/purchase-orders/{purchase_order}/request-approval:
    post:
      tags:
      - API
      summary: Request Purchase Order Approval
      description: 'Submit a draft purchase order for approval. Notifies every user
        who holds the purchase_orders.approve permission. The purchase order must
        be a draft with at least one line, and must not already have a pending request.


        Authentication: Requires Bearer token.


        **Requires permission:** `purchase_orders.update`


        The optional notes field (max 1000 characters) is shown to approvers with
        the request. The response includes notified_approvers — the number of users
        notified.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                notes:
                  type: string
              example:
                notes: Urgent restock for July promotion.
      parameters:
      - name: purchase_order
        in: path
        schema:
          type: integer
        required: true
        example: '101'
        description: The purchase order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      purchase_order_number:
                        type: string
                      order_status:
                        type: string
                      approval_status:
                        type: string
                      approval_requested_at:
                        type: string
                      approval_requested_by:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      approval_request_notes:
                        type: string
                      approval_actioned_at:
                        type: string
                        nullable: true
                      approval_actioned_by:
                        type: string
                        nullable: true
                      approval_action_notes:
                        type: string
                        nullable: true
                  notified_approvers:
                    type: integer
                example:
                  data:
                    id: 101
                    purchase_order_number: PO-101
                    order_status: draft
                    approval_status: pending_approval
                    approval_requested_at: '2026-07-14T09:12:33+00:00'
                    approval_requested_by:
                      id: 7
                      name: Jane Clerk
                    approval_request_notes: Urgent restock for July promotion.
                    approval_actioned_at: null
                    approval_actioned_by: null
                    approval_action_notes: null
                  notified_approvers: 2
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: This purchase order already has a pending approval request.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-purchase-orders-purchase-order-request-approval
  /api/purchase-orders/{purchase_order}/approval-request:
    delete:
      tags:
      - API
      summary: Withdraw Purchase Order Approval Request
      description: 'Withdraw a pending approval request, returning the purchase order
        to the not-requested state. Only the user who requested approval (or an admin)
        can withdraw it.


        Authentication: Requires Bearer token.


        **Requires permission:** `purchase_orders.update`'
      parameters:
      - name: purchase_order
        in: path
        schema:
          type: integer
        required: true
        example: '101'
        description: The purchase order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: integer
                  purchase_order_number:
                    type: string
                  order_status:
                    type: string
                  approval_status:
                    type: string
                  approval_requested_at:
                    type: string
                    nullable: true
                  approval_requested_by:
                    type: string
                    nullable: true
                  approval_request_notes:
                    type: string
                    nullable: true
                  approval_actioned_at:
                    type: string
                    nullable: true
                  approval_actioned_by:
                    type: string
                    nullable: true
                  approval_action_notes:
                    type: string
                    nullable: true
                example:
                  id: 101
                  purchase_order_number: PO-101
                  order_status: draft
                  approval_status: not_requested
                  approval_requested_at: null
                  approval_requested_by: null
                  approval_request_notes: null
                  approval_actioned_at: null
                  approval_actioned_by: null
                  approval_action_notes: null
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: This purchase order has no pending approval request to withdraw.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-purchase-orders-purchase-order-approval-request
  /api/purchase-orders/{purchase_order}/approval-request/approve:
    post:
      tags:
      - API
      summary: Approve Purchase Order Approval Request
      description: 'Approve a pending approval request. Runs the standard purchase
        order approval: the order moves to open, inventory becomes inbound, and backorder
        coverage is applied. The requester is notified that their purchase order was
        approved.


        Authentication: Requires Bearer token.


        **Requires permission:** `purchase_orders.approve`


        Returns 422 if the request was already approved, rejected, or withdrawn (for
        example by another approver acting first).'
      requestBody:
        content: {}
      parameters:
      - name: purchase_order
        in: path
        schema:
          type: integer
        required: true
        example: '101'
        description: The purchase order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: integer
                  purchase_order_number:
                    type: string
                  order_status:
                    type: string
                  approval_status:
                    type: string
                  approval_requested_at:
                    type: string
                  approval_requested_by:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                  approval_request_notes:
                    type: string
                  approval_actioned_at:
                    type: string
                  approval_actioned_by:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                  approval_action_notes:
                    type: string
                    nullable: true
                example:
                  id: 101
                  purchase_order_number: PO-101
                  order_status: open
                  approval_status: approved
                  approval_requested_at: '2026-07-14T09:12:33+00:00'
                  approval_requested_by:
                    id: 7
                    name: Jane Clerk
                  approval_request_notes: Urgent restock for July promotion.
                  approval_actioned_at: '2026-07-14T10:05:00+00:00'
                  approval_actioned_by:
                    id: 3
                    name: John Manager
                  approval_action_notes: null
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: This approval request has already been actioned or withdrawn.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-purchase-orders-purchase-order-approval-request-approve
  /api/purchase-orders/{purchase_order}/approval-request/reject:
    post:
      tags:
      - API
      summary: Reject Purchase Order Approval Request
      description: 'Reject a pending approval request with a reason. The purchase
        order stays in draft, and the requester is notified with the reason so they
        can amend the order and request approval again.


        Authentication: Requires Bearer token.


        **Requires permission:** `purchase_orders.approve`


        The notes field (rejection reason) is required, max 1000 characters.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                notes:
                  type: string
              example:
                notes: Quantities are wrong — should be 74, not 76.
      parameters:
      - name: purchase_order
        in: path
        schema:
          type: integer
        required: true
        example: '101'
        description: The purchase order ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: integer
                  purchase_order_number:
                    type: string
                  order_status:
                    type: string
                  approval_status:
                    type: string
                  approval_requested_at:
                    type: string
                  approval_requested_by:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                  approval_request_notes:
                    type: string
                  approval_actioned_at:
                    type: string
                  approval_actioned_by:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                  approval_action_notes:
                    type: string
                example:
                  id: 101
                  purchase_order_number: PO-101
                  order_status: draft
                  approval_status: rejected
                  approval_requested_at: '2026-07-14T09:12:33+00:00'
                  approval_requested_by:
                    id: 7
                    name: Jane Clerk
                  approval_request_notes: Urgent restock for July promotion.
                  approval_actioned_at: '2026-07-14T10:05:00+00:00'
                  approval_actioned_by:
                    id: 3
                    name: John Manager
                  approval_action_notes: Quantities are wrong — should be 74, not
                    76.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      notes:
                        type: array
                        items:
                          type: string
                example:
                  message: A rejection reason is required so the requester knows what
                    to fix.
                  errors:
                    notes:
                    - A rejection reason is required so the requester knows what to
                      fix.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-purchase-orders-purchase-order-approval-request-reject
  /api/report-templates:
    get:
      tags:
      - Report Templates
      summary: List Report Templates
      description: 'Returns all report templates for the account. Report templates
        store saved configurations for various reports.


        :::info[Required scope: `reports:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.'
      parameters: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        content:
                          type: object
                          properties:
                            date_range:
                              type: string
                            group_by:
                              type: string
                            columns:
                              type: array
                              items:
                                type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                example:
                  data:
                  - id: 1
                    name: Monthly Sales Summary
                    content:
                      date_range: last_30_days
                      group_by: sales_channel
                      columns:
                      - revenue
                      - orders
                      - units
                    created_at: '2024-01-15T10:00:00.000000Z'
                    updated_at: '2024-01-15T10:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:read
      operationId: get-api-report-templates
    post:
      tags:
      - Report Templates
      summary: Create Report Template
      description: 'Creates a new report template. The content field stores arbitrary
        JSON configuration for the report.


        :::info[Required scope: `reports:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Request Body:

        - name (required, string): Display name for the template

        - content (required, array/object): Report configuration (arbitrary JSON)


        **Requires permission:** `reports.create`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                content:
                  type: object
                  properties:
                    date_range:
                      type: string
                    group_by:
                      type: string
                    columns:
                      type: array
                      items:
                        type: string
              example:
                name: Weekly Inventory Report
                content:
                  date_range: last_7_days
                  group_by: warehouse
                  columns:
                  - sku
                  - on_hand
                  - available
      parameters: []
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      content:
                        type: object
                        properties:
                          date_range:
                            type: string
                          group_by:
                            type: string
                          columns:
                            type: array
                            items:
                              type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 2
                    name: Weekly Inventory Report
                    content:
                      date_range: last_7_days
                      group_by: warehouse
                      columns:
                      - sku
                      - on_hand
                      - available
                    created_at: '2024-01-20T14:30:00.000000Z'
                    updated_at: '2024-01-20T14:30:00.000000Z'
        '422':
          description: Unprocessable Entity
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      name:
                        type: array
                        items:
                          type: string
                      content:
                        type: array
                        items:
                          type: string
                example:
                  message: The name field is required.
                  errors:
                    name:
                    - The name field is required.
                    content:
                    - The content field is required.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: reports:write
      operationId: post-api-report-templates
  /api/report-templates/{report_template}:
    put:
      tags:
      - Report Templates
      summary: Update Report Template
      description: 'Updates a report template. Both name and content are optional
        on update.


        :::info[Required scope: `reports:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Request Body:

        - name (sometimes, string): Display name for the template

        - content (sometimes, array/object): Report configuration


        **Requires permission:** `reports.update`'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                name:
                  type: string
                content:
                  type: object
                  properties:
                    date_range:
                      type: string
                    columns:
                      type: array
                      items:
                        type: string
              example:
                name: Updated Report Name
                content:
                  date_range: last_30_days
                  columns:
                  - sku
                  - revenue
      parameters:
      - name: report_template
        in: path
        schema:
          type: integer
        required: true
        description: Report template ID
        example: '1'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      content:
                        type: object
                        properties:
                          date_range:
                            type: string
                          columns:
                            type: array
                            items:
                              type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 1
                    name: Updated Report Name
                    content:
                      date_range: last_30_days
                      columns:
                      - sku
                      - revenue
                    created_at: '2024-01-15T10:00:00.000000Z'
                    updated_at: '2024-01-20T15:00:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: reports:write
      operationId: put-api-report-templates-report-template
    delete:
      tags:
      - Report Templates
      summary: Delete Report Template
      description: 'Permanently deletes a report template.


        :::info[Required scope: `reports:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        **Requires permission:** `reports.delete`'
      parameters:
      - name: report_template
        in: path
        schema:
          type: integer
        required: true
        description: Report template ID
        example: '1'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: string
                    nullable: true
                example:
                  data: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: reports:write
      operationId: delete-api-report-templates-report-template
  /register:
    post:
      tags:
      - 17TRACK
      summary: Register Tracking Numbers
      description: 'Register up to **40 tracking numbers per call** for auto-tracking.


        **Per-item fields:**

        - `number` (string, required) — the tracking number

        - `carrier` (int, optional) — 17TRACK carrier code; omit + set `auto_detection:
        true` to let 17TRACK guess

        - `auto_detection` (bool, optional) — fall back to auto-detect when carrier
        is unknown/wrong

        - `lang`, `order_no`, `order_time`, `tag`, `destination_country`, `destination_postal_code`,
        `shipper`, `consignee`, `phone_number_last_4`, `phone_number`, `email`, `remark`
        — optional enrichment fields


        **Response envelope:** `{code, data: {accepted, rejected}}`. Per-row rejections
        (already-registered, carrier not detected, …) come back in `data.rejected[]`
        with the error code — they''re NOT envelope errors.


        **Common envelope error codes:**

        - `-18010002` invalid API key

        - `-18010014` rate limit exceeded (also HTTP 429)

        - `-18019907` daily tracking limit reached

        - `-18019908` monthly quota exhausted'
      requestBody:
        content:
          application/json:
            schema:
              type: array
              items:
                type: object
                properties:
                  number:
                    type: string
                  carrier:
                    type: integer
                  auto_detection:
                    type: boolean
                  lang:
                    type: string
                  order_no:
                    type: string
                  order_time:
                    type: string
                  tag:
                    type: string
                  destination_country:
                    type: string
                  destination_postal_code:
                    type: string
                  shipper:
                    type: string
                  consignee:
                    type: string
              example:
              - number: RR123456789CN
                carrier: 3011
                auto_detection: true
                lang: en
                order_no: ORDER-1234
                order_time: '2026-06-25'
                tag: sku.io
                destination_country: US
                destination_postal_code: '94110'
                shipper: Acme Shipper
                consignee: Customer Name
      parameters:
      - name: 17token
        in: header
        schema:
          type: string
        example: '{{17track_api_key}}'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 Success
                  value:
                    code: 0
                    data:
                      accepted:
                      - origin: 1
                        number: RR123456789CN
                        carrier: 3011
                      rejected: []
                example-1:
                  summary: 200 Success — partial rejection (already registered)
                  value:
                    code: 0
                    data:
                      accepted: []
                      rejected:
                      - number: RR123456789CN
                        error:
                          code: -18019901
                          message: Tracking number is already registered.
                example-2:
                  summary: 200 — Quota exhausted
                  value:
                    code: -18019908
                    data:
                      errors:
                      - code: -18019908
                        message: Quotas have run out.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-register
  /api/integrations/17track/instances/{instance_id}/refresh:
    post:
      tags:
      - 17TRACK
      summary: Pull Tracking Updates from 17TRACK
      description: 'Dispatch an immediate a background job — pulls the latest status
        from 17TRACK for non-terminal trackings whose last event is older than `instance.last_polled_at`.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Fires the same code path as the scheduled 6-hour poll. Tracked via `TrackedJobLog`
        so the tracked job log endpoints surfaces it.


        **Activity log:** writes `manual_refresh_triggered` (with causer = acting
        user).'
      requestBody:
        content: {}
      parameters:
      - name: instance_id
        in: path
        schema:
          type: string
        required: true
        description: The instance ID.
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 446215
                  message: Sync started — track progress in the job tray.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-integrations-17track-instances-instance-id-refresh
  /api/integrations/17track/instances/{instance_id}/push-pending:
    post:
      tags:
      - 17TRACK
      summary: Push Pending Tracking Numbers to 17TRACK
      description: 'Push every pending or previously-failed tracking row to 17TRACK
        in one shot — manual recovery path for the **Sync to 17TRACK** button.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        **Pending = `registered_at IS NULL AND stopped_at IS NULL`** — covers (a)
        freshly-created rows the observer flow hasn''t dispatched for yet, (b) rows
        whose previous register call failed with `quota_exceeded`, and (c) orphans
        from a transient API error.


        **Response branches:**

        - `tracked_job_log_id` set when a fresh job is queued

        - `tracked_job_log_id: null` when a push is already in flight (existing job
        will pick up the new rows)

        - `pending_count: 0` early-exit when nothing is pending (no wasted queue slot)


        **Activity log:** writes `manual_push_triggered` (with causer = acting user).'
      requestBody:
        content: {}
      parameters:
      - name: instance_id
        in: path
        schema:
          type: string
        required: true
        description: The instance ID.
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 — job queued
                  value:
                    data:
                      tracked_job_log_id: 446299
                      pending_count: 13
                    message: Pushing 13 tracking(s) to 17TRACK — track progress in
                      the job tray.
                example-1:
                  summary: 200 — nothing to push
                  value:
                    data:
                      tracked_job_log_id: null
                      pending_count: 0
                    message: No trackings are waiting to be registered with 17TRACK.
                example-2:
                  summary: 200 — already running (coalesced)
                  value:
                    data:
                      tracked_job_log_id: null
                      pending_count: 13
                    message: A push is already running — watch the job tray for progress.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-integrations-17track-instances-instance-id-push-pending
  /api/v2/inventory/movements/preview-release-impact:
    post:
      tags:
      - Movement Composer
      summary: Preview Release Impact
      description: "Dry-run preview: given a receipt payload, compute which pending\
        \ backorder allocations would be released once the movement is committed.\n\
        \n**Named route:** `v2.inventory.movements.preview-release-impact`\n\n**When\
        \ to call:** UI should invoke this BEFORE committing a `direction=receive`\
        \ movement so the operator can confirm how incoming stock will be consumed\
        \ by existing backorders.\n\n**Request body:** Same shape as the commit endpoint\
        \ (see `Commit Movement`). Only `direction`, `warehouse_id`, `movement_date`,\
        \ and `lines[*].product_id` + `lines[*].quantity` are required for preview.\n\
        \n**Response shape:**\n```\n{\n  \"data\": {\n    \"total_units_receiving\"\
        : 50,\n    \"total_allocations_released\": 2,\n    \"releases\": [ { fulfillment_id,\
        \ product_id, quantity_released, ... } ],\n    \"held_back\": [ ... ]\n  }\n\
        }\n```"
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                direction:
                  type: string
                warehouse_id:
                  type: integer
                movement_date:
                  type: string
                against_type:
                  type: string
                against_id:
                  type: integer
                reason:
                  type: string
                lines:
                  type: array
                  items:
                    type: object
                    properties:
                      product_id:
                        type: integer
                      quantity:
                        type: integer
                      unit_cost:
                        type: number
              example:
                direction: receive
                warehouse_id: 1
                movement_date: '2026-04-19'
                against_type: purchase_order
                against_id: 4521
                reason: PO receipt
                lines:
                - product_id: 123
                  quantity: 50
                  unit_cost: 12.5
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-v2-inventory-movements-preview-release-impact
  /api/v2/inventory/movements/preview-demotion-impact:
    post:
      tags:
      - Movement Composer
      summary: Preview Demotion Impact
      description: "Dry-run preview: given an outbound/adjust-down payload, compute\
        \ which allocations (unallocated, soft-allocated, hard-allocated) would be\
        \ consumed, and whether any hard-allocated fulfillments will require an explicit\
        \ void confirmation before commit.\n\n**Named route:** `v2.inventory.movements.preview-demotion-impact`\n\
        \n**When to call:** UI should invoke this BEFORE committing `direction=ship`\
        \ or `direction=adjust_down` to surface any allocations that would be demoted,\
        \ including hard-allocated fulfillments whose shipping labels may need to\
        \ be voided.\n\n**Key response field:** `requires_void_confirmation` (bool)\
        \ — when true, the caller MUST include a matching `void_confirmations[]` entry\
        \ in the commit payload for every hard-allocated fulfillment listed in `lines[*].buckets.hard_allocated.fulfillments`.\n\
        \n**Response shape:**\n```\n{\n  \"data\": {\n    \"requires_void_confirmation\"\
        : true,\n    \"lines\": [\n      {\n        \"product_id\": 123,\n       \
        \ \"product_sku\": \"SKU-ABC\",\n        \"product_name\": \"Widget\",\n \
        \       \"quantity_requested\": 10,\n        \"buckets\": {\n          \"\
        unallocated\": { quantity, ... },\n          \"soft_allocated\": { quantity,\
        \ fulfillments: [...] },\n          \"hard_allocated\": { quantity, fulfillments:\
        \ [ { fulfillment_id, provider, ... } ] }\n        }\n      }\n    ]\n  }\n\
        }\n```"
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                direction:
                  type: string
                warehouse_id:
                  type: integer
                movement_date:
                  type: string
                against_type:
                  type: string
                reason:
                  type: string
                lines:
                  type: array
                  items:
                    type: object
                    properties:
                      product_id:
                        type: integer
                      quantity:
                        type: integer
              example:
                direction: ship
                warehouse_id: 1
                movement_date: '2026-04-19'
                against_type: none
                reason: Manual shipment
                lines:
                - product_id: 123
                  quantity: -10
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-v2-inventory-movements-preview-demotion-impact
  /api/v2/inventory/movements/composer:
    post:
      tags:
      - Movement Composer
      summary: Commit Movement
      description: "Atomic commit of a composed movement: creates inventory adjustments,\
        \ persists lot/serial detail, and triggers allocation release or demotion\
        \ — all inside one DB transaction. When an outbound demotion consumes hard-allocated\
        \ stock, each confirmed shipping label is voided in the same transaction (the\
        \ fulfillment's inventory is reversed back to on-hand, its FulfillmentOrder\
        \ budget reopened, and the shipment marked canceled).\n\n**Named route:**\
        \ `v2.inventory.movements.composer`\n\n**Request fields:**\n- `direction`\
        \ (required) — one of: `receive`, `ship`, `adjust_up`, `adjust_down`\n- `warehouse_id`\
        \ (required) — must exist in `warehouses`\n- `movement_date` (required) —\
        \ ISO date\n- `against_type` (optional) — `purchase_order`, `transfer`, or\
        \ `none`\n- `against_id` (optional) — ID of the source doc when `against_type`\
        \ is set\n- `reason` (optional, max 1000 chars)\n- `lines[]` (required, min\
        \ 1):\n    - `product_id` (required)\n    - `quantity` (required, non-zero\
        \ — positive for inbound, negative for outbound)\n    - `unit_cost` (optional,\
        \ >= 0)\n    - `serials[]` (optional, each max 100 chars)\n    - `lot` (optional):\
        \ `lot_number`, `expires_at`, `manufactured_at`\n    - `override_reason` (optional,\
        \ max 500 chars)\n- `void_confirmations[]` (required when preview-demotion\
        \ returned `requires_void_confirmation=true`):\n    - `fulfillment_id` (required)\n\
        \    - `attempt_void` (required bool)\n    - `reason` (optional, max 500 chars)\n\
        \n**Response shape (200):**\n```\n{\n  \"data\": {\n    \"adjustment_ids\"\
        : [101, 102],\n    \"voided_fulfillment_ids\": [9001],\n    \"skipped_fulfillments\"\
        : []\n  },\n  \"message\": \"Receipt committed — 1 line(s).\"\n}\n```\n\n\
        `voided_fulfillment_ids` lists the fulfillments whose labels were voided.\
        \ `skipped_fulfillments` lists any confirmed fulfillment that could not be\
        \ voided (already voided, or part of a multi-shipment merge group) as `{ fulfillment_id,\
        \ kind, reason }` — these are skipped, not fatal.\n\n**Error (422):** Returned\
        \ when hard-allocated fulfillments are missing from `void_confirmations` or\
        \ any other `\\InvalidArgumentException` is thrown by the manager.\n```\n\
        { \"error\": \"Hard-allocated fulfillment #9001 requires an explicit void\
        \ confirmation before committing.\" }\n```\n\n`release_backorders` (boolean,\
        \ inbound only, default true): when true, the received stock is applied to\
        \ any waiting back-orders (promoting them to allocated); when false, the stock\
        \ is received as free inventory and the back-orders keep waiting.\n\n`release_sales_order_ids`\
        \ (array of ints, inbound only, optional): granular release. Omit or null\
        \ to release ALL waiting back-orders; pass a list of sales order ids to release\
        \ only those orders' back-orders. Requires `release_backorders` = true."
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                direction:
                  type: string
                warehouse_id:
                  type: integer
                movement_date:
                  type: string
                against_type:
                  type: string
                against_id:
                  type: integer
                reason:
                  type: string
                release_backorders:
                  type: boolean
                release_sales_order_ids:
                  type: string
                  nullable: true
                lines:
                  type: array
                  items:
                    type: object
                    properties:
                      product_id:
                        type: integer
                      quantity:
                        type: integer
                      unit_cost:
                        type: number
                      serials:
                        type: array
                        items:
                          type: string
                      lot:
                        type: object
                        properties:
                          lot_number:
                            type: string
                          expires_at:
                            type: string
                          manufactured_at:
                            type: string
                void_confirmations:
                  type: array
                  items:
                    type: object
                    properties:
                      fulfillment_id:
                        type: integer
                      attempt_void:
                        type: boolean
                      reason:
                        type: string
              example:
                direction: receive
                warehouse_id: 1
                movement_date: '2026-04-19'
                against_type: purchase_order
                against_id: 4521
                reason: PO receipt — truck 8821
                release_backorders: true
                release_sales_order_ids: null
                lines:
                - product_id: 123
                  quantity: 50
                  unit_cost: 12.5
                  serials:
                  - SN-0001
                  - SN-0002
                  lot:
                    lot_number: LOT-2026-04
                    expires_at: '2027-04-19'
                    manufactured_at: '2026-03-15'
                void_confirmations:
                - fulfillment_id: 9001
                  attempt_void: true
                  reason: Operator override — customer cancelled
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      operationId: post-api-v2-inventory-movements-composer
  /api/vendor-credits:
    get:
      tags:
      - Vendor Credits
      summary: List Vendor Credits
      description: 'Returns a paginated list of vendor credits. Supports Spatie QueryBuilder
        filters, sorting, and search. Each row is transformed via vendor credit object.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        The response also includes `unfiltered_total`, the count of rows in the base
        scope before any user filters are applied — used by the frontend to show export
        totals.


        **Search** (`filter[search]`) matches across: ID, Credit Number (vendor_credit_number),
        Additional Reference (supplier_reference), Supplier PO # (supplier_po_number),
        Supplier Name, Supplier Email, line item SKU, and Purchase Order #.'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        description: 'Page number (default: 1)'
        example: '1'
      - name: per_page
        in: query
        schema:
          type: integer
        description: 'Items per page (default: 15)'
        example: '15'
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: get-api-vendor-credits
    post:
      tags:
      - Vendor Credits
      summary: Create Vendor Credit
      description: 'Create a new vendor credit.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        **Required fields:**

        - `supplier_id` (int) — Supplier the credit is from.


        **Optional top-level fields:**

        - `purchase_order_id`, `purchase_invoice_id` — Links to the source PO / bill.

        - `warehouse_id`, `store_id` — For restock-type credits.

        - `credit_type` — One of: restock, unstock, service, overpayment, rebate.

        - `refund_method` — One of: applied_to_bill, cash_refund, retained_credit.

        - `currency_id` OR `currency_code` — Pick the credit''s currency. If omitted,
        defaults are resolved in this order: (1) linked PO''s currency if `purchase_order_id`
        is set, (2) the supplier''s default pricing tier currency, (3) the tenant
        default currency. When a `purchase_order_id` is supplied, the currency MUST
        match the PO''s currency.

        - `tax_rate_id` — Default tax rate for lines.

        - `credit_date` — ISO date (defaults to today).

        - `supplier_reference` — External RMA / credit reference from supplier.

        - `vendor_credit_number` — Auto-generated if omitted.

        - `is_tax_included`, `is_for_overpayment` — Booleans.

        - `vendor_credit_note` — Free-text note.

        - `tax_lines`, `metadata` — Optional arrays.


        **Lines (array, required for most credit types):**

        Each line is either:

        1. A PO-line-linked line: `purchase_order_line_id` + `quantity` + optional
        `unit_cost`/`amount`/`restock_inventory`.

        2. A description-only line (service/rebate): `description` + `quantity` +
        `amount` (+ optional `nominal_code_id`).


        Validation enforces that the requested `quantity` on any PO-line-linked line
        does not exceed `(received_quantity - already_credited_quantity)` for that
        PO line.


        **Reference fields:**

        - `vendor_credit_number` (string, max 255, unique) — The supplier''s **credit
        memo number** as printed on their document (e.g. "Credit Memo 0001669"). This
        becomes the credit''s number in SKU. Leave blank/omit to auto-generate a local
        number (`VC-00001`, `VC-00002`, …). Supplying a number already used by another
        credit returns a 422 with a `vendor_credit_number` validation error.

        - `supplier_reference` (string, max 255) — Any **additional reference** on
        the supplier''s document, e.g. their internal order number ("Credit Order
        0010764"). The credit-memo OCR pipeline''s duplicate detection matches an
        extracted memo number against BOTH `supplier_reference` and `vendor_credit_number`.

        - `supplier_po_number` (string, max 255) — The **PO number printed on the
        supplier''s memo**, recorded as text for reference only. It does NOT link
        to a purchase order in SKU (use `purchase_order_id` for an actual link).

        - `purchase_order_id` (int) — Link the credit to an actual PO in SKU (return/damage
        credits). When linked, the credit''s currency must match the PO''s currency.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                supplier_id:
                  type: integer
                warehouse_id:
                  type: integer
                store_id:
                  type: integer
                credit_type:
                  type: string
                refund_method:
                  type: string
                currency_code:
                  type: string
                tax_rate_id:
                  type: integer
                credit_date:
                  type: string
                supplier_reference:
                  type: string
                supplier_po_number:
                  type: string
                vendor_credit_number:
                  type: string
                is_tax_included:
                  type: boolean
                is_for_overpayment:
                  type: boolean
                vendor_credit_note:
                  type: string
                lines:
                  type: array
                  items:
                    type: object
                    properties:
                      purchase_order_line_id:
                        type: integer
                      product_id:
                        type: integer
                      quantity:
                        type: integer
                      unit_cost:
                        type: number
                      amount:
                        type: number
                      tax_allocation:
                        type: integer
                      tax_rate_id:
                        type: integer
                      is_product:
                        type: boolean
                      restock_inventory:
                        type: boolean
              example:
                supplier_id: 1
                warehouse_id: 2
                store_id: 1
                credit_type: restock
                refund_method: applied_to_bill
                currency_code: USD
                tax_rate_id: 3
                credit_date: '2026-04-11'
                supplier_reference: Credit Order 0010764
                supplier_po_number: '001'
                vendor_credit_number: 0001669
                is_tax_included: false
                is_for_overpayment: false
                vendor_credit_note: Credit for 5 defective units returned to supplier.
                lines:
                - purchase_order_line_id: 101
                  product_id: 555
                  quantity: 5
                  unit_cost: 12.5
                  amount: 62.5
                  tax_allocation: 0
                  tax_rate_id: 3
                  is_product: true
                  restock_inventory: true
                - description: Freight rebate
                  nominal_code_id: 27
                  quantity: 1
                  amount: 15
                  tax_allocation: 0
                  is_product: false
                  restock_inventory: false
      parameters: []
      responses:
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      vendor_credit_number:
                        type: array
                        items:
                          type: string
                example:
                  message: This credit number is already used by another vendor credit.
                  errors:
                    vendor_credit_number:
                    - This credit number is already used by another vendor credit.
        '429': *id001
        '401': *id002
        '403': *id003
      x-session-only: true
      operationId: post-api-vendor-credits
    delete:
      tags:
      - Vendor Credits
      summary: Bulk Delete Vendor Credits
      description: 'Bulk delete vendor credits. Same body shape as Bulk Archive.


        :::info[Required scope: `accounting:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        **Note:** The route is `DELETE /api/vendor-credits` (the resource root). Laravel''s
        router resolves this before the `Route::resource` destroy route, which binds
        a `{vendor_credit}` parameter.'
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: accounting:write
      operationId: delete-api-vendor-credits
  /api/vendor-credits/{vendor_credit}:
    get:
      tags:
      - Vendor Credits
      summary: Get Vendor Credit
      description: 'Show a single vendor credit with all eager-loaded relations: supplier,
        purchase order, purchase invoice, warehouse, store, currency, tax rate, vendor
        credit lines (with product, PO line, nominal code, tax rate), allocations
        (with purchase invoice and allocator), payments, tags, and the linked accounting
        transaction.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::'
      parameters:
      - name: vendor_credit
        in: path
        schema:
          type: integer
        required: true
        description: Vendor credit ID
        example: '1'
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-session-only: true
      operationId: get-api-vendor-credits-vendor-credit
    put:
      tags:
      - Vendor Credits
      summary: Update Vendor Credit
      description: 'Update an existing vendor credit. Accepts the same fields as Create.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::


        **Currency rules:**

        - `currency_id` (or `currency_code`) can be updated ONLY while the credit
        has no activity.

        - If the credit has any allocations (applied to bills) or payments, attempting
        to change the currency returns a 422 with a `currency_id` validation error.

        - If the credit is linked to a purchase order, the currency MUST match the
        PO''s currency — any mismatch returns a 422.


        **Line replacement semantics:** supplying `lines` replaces the existing line
        set (use with care). Closed or voided credits may be blocked from editing
        — check the manager.


        **Reference fields:**

        - `vendor_credit_number` (string, max 255, unique) — The supplier''s **credit
        memo number** as printed on their document (e.g. "Credit Memo 0001669"). This
        becomes the credit''s number in SKU. Leave blank/omit to auto-generate a local
        number (`VC-00001`, `VC-00002`, …). Supplying a number already used by another
        credit returns a 422 with a `vendor_credit_number` validation error.

        - `supplier_reference` (string, max 255) — Any **additional reference** on
        the supplier''s document, e.g. their internal order number ("Credit Order
        0010764"). The credit-memo OCR pipeline''s duplicate detection matches an
        extracted memo number against BOTH `supplier_reference` and `vendor_credit_number`.

        - `supplier_po_number` (string, max 255) — The **PO number printed on the
        supplier''s memo**, recorded as text for reference only. It does NOT link
        to a purchase order in SKU (use `purchase_order_id` for an actual link).

        - `purchase_order_id` (int) — Link the credit to an actual PO in SKU (return/damage
        credits). When linked, the credit''s currency must match the PO''s currency.


        This endpoint also accepts the PATCH method with identical behavior.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                supplier_id:
                  type: integer
                credit_type:
                  type: string
                refund_method:
                  type: string
                credit_date:
                  type: string
                supplier_reference:
                  type: string
                supplier_po_number:
                  type: string
                vendor_credit_note:
                  type: string
                lines:
                  type: array
                  items:
                    type: object
                    properties:
                      purchase_order_line_id:
                        type: integer
                      product_id:
                        type: integer
                      quantity:
                        type: integer
                      unit_cost:
                        type: number
                      amount:
                        type: integer
                      is_product:
                        type: boolean
                      restock_inventory:
                        type: boolean
              example:
                supplier_id: 1
                credit_type: restock
                refund_method: applied_to_bill
                credit_date: '2026-04-11'
                supplier_reference: Credit Order 0010764
                supplier_po_number: '001'
                vendor_credit_note: Updated note — replaced 2 lines with an adjusted
                  quantity.
                lines:
                - purchase_order_line_id: 101
                  product_id: 555
                  quantity: 4
                  unit_cost: 12.5
                  amount: 50
                  is_product: true
                  restock_inventory: true
      parameters:
      - name: vendor_credit
        in: path
        schema:
          type: integer
        required: true
        description: Vendor credit ID
        example: '1'
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-session-only: true
      operationId: put-api-vendor-credits-vendor-credit
    delete:
      tags:
      - Vendor Credits
      summary: Delete Vendor Credit
      description: 'Delete a vendor credit and cascade-delete its related lines, allocations,
        accounting transaction, and any inventory movements restored by the manager.
        Will fail for credits that are referenced by posted / synced accounting data
        if business rules prevent deletion.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::'
      parameters:
      - name: vendor_credit
        in: path
        schema:
          type: integer
        required: true
        description: Vendor credit ID
        example: '1'
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-session-only: true
      operationId: delete-api-vendor-credits-vendor-credit
  /api/vendor-credits/stats:
    get:
      tags:
      - Vendor Credits
      summary: Get Vendor Credit Stats
      description: 'Aggregate statistics for vendor credits: the number and remaining
        balance of open credits, the subset that is still fully unapplied, and the
        total amount ever allocated to purchase invoices.


        :::info[Required scope: `accounting:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Balances are summed in each credit''s original currency; currency_code is
        the tenant''s default currency and is intended for display formatting. On
        multi-currency tenants treat these totals as an indicator rather than an exact
        figure.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      open_count:
                        type: integer
                      open_balance:
                        type: number
                      unapplied_count:
                        type: integer
                      unapplied_balance:
                        type: number
                      total_allocated:
                        type: integer
                      currency_code:
                        type: string
                example:
                  data:
                    open_count: 4
                    open_balance: 1230.5
                    unapplied_count: 2
                    unapplied_balance: 730.5
                    total_allocated: 8250
                    currency_code: USD
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: accounting:read
      operationId: get-api-vendor-credits-stats
  /api/vendor-credits/for-supplier/{supplier}:
    get:
      tags:
      - Vendor Credits
      summary: List Open Vendor Credits for Supplier
      description: 'List open, non-archived vendor credits for a supplier that still
        have balance available to apply (payment status unapplied or partially applied),
        sorted by credit date descending. Useful for finding credits that can be allocated
        against the supplier''s outstanding bills.


        :::info[Required scope: `accounting:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: supplier
        in: path
        schema:
          type: integer
        required: true
        description: Supplier ID
        example: '7'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        vendor_credit_number:
                          type: string
                        supplier_reference:
                          type: string
                        supplier_po_number:
                          type: string
                        credit_date:
                          type: string
                        vendor_credit_note:
                          type: string
                        metadata:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                        updated_at:
                          type: string
                        archived_at:
                          type: string
                          nullable: true
                        fully_allocated_at:
                          type: string
                          nullable: true
                        fully_refunded_at:
                          type: string
                          nullable: true
                        is_settled:
                          type: boolean
                        settlement_breakdown:
                          type: object
                          properties:
                            allocated:
                              type: integer
                            refunded:
                              type: integer
                            remaining:
                              type: integer
                            total:
                              type: integer
                        credit_status:
                          type: string
                        credit_status_label:
                          type: string
                        payment_status:
                          type: string
                        payment_status_label:
                          type: string
                        is_for_overpayment:
                          type: boolean
                        supplier_id:
                          type: integer
                        supplier:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            email:
                              type: string
                        purchase_order_id:
                          type: integer
                        purchase_order:
                          type: object
                          properties:
                            id:
                              type: integer
                            purchase_order_number:
                              type: string
                        warehouse_id:
                          type: integer
                        warehouse:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        store_id:
                          type: string
                          nullable: true
                        store:
                          type: string
                          nullable: true
                        currency_id:
                          type: integer
                        currency_code:
                          type: string
                        currency_rate:
                          type: integer
                        is_tax_included:
                          type: boolean
                        tax_rate_id:
                          type: string
                          nullable: true
                        tax_rate:
                          type: string
                          nullable: true
                        tax_lines:
                          type: string
                          nullable: true
                        tax_total:
                          type: integer
                        tax_credit:
                          type: integer
                        product_total:
                          type: integer
                        total_credit:
                          type: integer
                        total:
                          type: integer
                        allocated_amount:
                          type: integer
                        planned_allocation_amount:
                          type: integer
                        available_to_allocate:
                          type: integer
                        refunded_amount:
                          type: integer
                        remaining_amount:
                          type: integer
                        lines:
                          type: array
                          items:
                            type: object
                            properties:
                              id:
                                type: integer
                              vendor_credit_id:
                                type: integer
                              purchase_order_line_id:
                                type: integer
                              financial_line_id:
                                type: string
                                nullable: true
                              product_id:
                                type: integer
                              quantity:
                                type: integer
                              amount:
                                type: integer
                              unit_cost:
                                type: integer
                              description:
                                type: string
                              tax_allocation:
                                type: integer
                              tax_rate_id:
                                type: string
                                nullable: true
                              tax_rate:
                                type: string
                                nullable: true
                              nominal_code_id:
                                type: string
                                nullable: true
                              nominal_code:
                                type: string
                                nullable: true
                              is_product:
                                type: boolean
                              restock_inventory:
                                type: boolean
                              proration:
                                type: string
                                nullable: true
                              subtotal:
                                type: integer
                              created_at:
                                type: string
                              updated_at:
                                type: string
                              product:
                                type: object
                                properties:
                                  id:
                                    type: integer
                                  sku:
                                    type: string
                                  name:
                                    type: string
                                  barcode:
                                    type: string
                                  image:
                                    type: string
                                    nullable: true
                                  is_lot_tracked:
                                    type: boolean
                                  lot_tracking_method:
                                    type: string
                                    nullable: true
                                  shelf_life_days:
                                    type: string
                                    nullable: true
                                  near_expiry_threshold_days:
                                    type: string
                                    nullable: true
                                  min_remaining_shelf_life_days:
                                    type: string
                                    nullable: true
                              purchase_order_line:
                                type: object
                                properties:
                                  id:
                                    type: integer
                                  purchase_order_id:
                                    type: integer
                                  product_id:
                                    type: integer
                                  quantity:
                                    type: integer
                                  unit_price:
                                    type: integer
                                  purchase_order_number:
                                    type: string
                        line_item_count:
                          type: integer
                        total_quantity:
                          type: integer
                        first_line_sku:
                          type: string
                        has_products:
                          type: boolean
                        allocations:
                          type: array
                        payments:
                          type: array
                        shipments_count:
                          type: integer
                        tags:
                          type: array
                          items:
                            type: string
                        inventory_movements:
                          type: array
                        link_reference:
                          type: string
                        link_type_label:
                          type: string
                        link_route:
                          type: string
                example:
                  data:
                  - id: 17
                    vendor_credit_number: VC-000017
                    supplier_reference: CM-88213
                    supplier_po_number: PO-000310
                    credit_date: '2026-06-20'
                    vendor_credit_note: Credit for damaged goods on PO-000310
                    metadata: null
                    created_at: '2026-06-20T10:15:00.000000Z'
                    updated_at: '2026-07-01T08:00:00.000000Z'
                    archived_at: null
                    fully_allocated_at: null
                    fully_refunded_at: null
                    is_settled: false
                    settlement_breakdown:
                      allocated: 0
                      refunded: 0
                      remaining: 250
                      total: 250
                    credit_status: open
                    credit_status_label: Open
                    payment_status: unapplied
                    payment_status_label: Unapplied
                    is_for_overpayment: false
                    supplier_id: 7
                    supplier:
                      id: 7
                      name: Acme Components Ltd
                      email: accounts@acme-components.com
                    purchase_order_id: 310
                    purchase_order:
                      id: 310
                      purchase_order_number: PO-000310
                    warehouse_id: 2
                    warehouse:
                      id: 2
                      name: Main Warehouse
                    store_id: null
                    store: null
                    currency_id: 1
                    currency_code: USD
                    currency_rate: 1
                    is_tax_included: false
                    tax_rate_id: null
                    tax_rate: null
                    tax_lines: null
                    tax_total: 0
                    tax_credit: 0
                    product_total: 250
                    total_credit: 250
                    total: 250
                    allocated_amount: 0
                    planned_allocation_amount: 0
                    available_to_allocate: 250
                    refunded_amount: 0
                    remaining_amount: 250
                    lines:
                    - id: 31
                      vendor_credit_id: 17
                      purchase_order_line_id: 771
                      financial_line_id: null
                      product_id: 55
                      quantity: 5
                      amount: 250
                      unit_cost: 50
                      description: Blue Widget (Medium)
                      tax_allocation: 0
                      tax_rate_id: null
                      tax_rate: null
                      nominal_code_id: null
                      nominal_code: null
                      is_product: true
                      restock_inventory: false
                      proration: null
                      subtotal: 250
                      created_at: '2026-06-20T10:15:00.000000Z'
                      updated_at: '2026-06-20T10:15:00.000000Z'
                      product:
                        id: 55
                        sku: WID-BLU-M
                        name: Blue Widget (Medium)
                        barcode: 0123456789012
                        image: null
                        is_lot_tracked: false
                        lot_tracking_method: null
                        shelf_life_days: null
                        near_expiry_threshold_days: null
                        min_remaining_shelf_life_days: null
                      purchase_order_line:
                        id: 771
                        purchase_order_id: 310
                        product_id: 55
                        quantity: 20
                        unit_price: 50
                        purchase_order_number: PO-000310
                    line_item_count: 1
                    total_quantity: 5
                    first_line_sku: WID-BLU-M
                    has_products: true
                    allocations: []
                    payments: []
                    shipments_count: 0
                    tags:
                    - damaged-goods
                    inventory_movements: []
                    link_reference: VC-000017
                    link_type_label: Vendor Credit
                    link_route: /purchases/vendor-credits/17
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: accounting:read
      operationId: get-api-vendor-credits-for-supplier-supplier
  /api/vendor-credits/for-invoice/{purchase_invoice}:
    get:
      tags:
      - Vendor Credits
      summary: List Applicable Vendor Credits for Invoice
      description: 'List open vendor credits that can be applied to a specific purchase
        invoice (bill): credits from the same supplier, in the same currency as the
        invoice, that are not archived and still have a remaining balance. Sorted
        by credit date descending.


        :::info[Required scope: `accounting:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: purchase_invoice
        in: path
        schema:
          type: integer
        required: true
        description: Purchase invoice (bill) ID
        example: '88'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        vendor_credit_number:
                          type: string
                        supplier_reference:
                          type: string
                        supplier_po_number:
                          type: string
                        credit_date:
                          type: string
                        vendor_credit_note:
                          type: string
                        metadata:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                        updated_at:
                          type: string
                        archived_at:
                          type: string
                          nullable: true
                        fully_allocated_at:
                          type: string
                          nullable: true
                        fully_refunded_at:
                          type: string
                          nullable: true
                        is_settled:
                          type: boolean
                        settlement_breakdown:
                          type: object
                          properties:
                            allocated:
                              type: integer
                            refunded:
                              type: integer
                            remaining:
                              type: integer
                            total:
                              type: integer
                        credit_status:
                          type: string
                        credit_status_label:
                          type: string
                        payment_status:
                          type: string
                        payment_status_label:
                          type: string
                        is_for_overpayment:
                          type: boolean
                        supplier_id:
                          type: integer
                        supplier:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            email:
                              type: string
                        purchase_order_id:
                          type: integer
                        purchase_order:
                          type: object
                          properties:
                            id:
                              type: integer
                            purchase_order_number:
                              type: string
                        warehouse_id:
                          type: integer
                        warehouse:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        store_id:
                          type: string
                          nullable: true
                        store:
                          type: string
                          nullable: true
                        currency_id:
                          type: integer
                        currency_code:
                          type: string
                        currency_rate:
                          type: integer
                        is_tax_included:
                          type: boolean
                        tax_rate_id:
                          type: string
                          nullable: true
                        tax_rate:
                          type: string
                          nullable: true
                        tax_lines:
                          type: string
                          nullable: true
                        tax_total:
                          type: integer
                        tax_credit:
                          type: integer
                        product_total:
                          type: integer
                        total_credit:
                          type: integer
                        total:
                          type: integer
                        allocated_amount:
                          type: integer
                        planned_allocation_amount:
                          type: integer
                        available_to_allocate:
                          type: integer
                        refunded_amount:
                          type: integer
                        remaining_amount:
                          type: integer
                        lines:
                          type: array
                          items:
                            type: object
                            properties:
                              id:
                                type: integer
                              vendor_credit_id:
                                type: integer
                              purchase_order_line_id:
                                type: integer
                              financial_line_id:
                                type: string
                                nullable: true
                              product_id:
                                type: integer
                              quantity:
                                type: integer
                              amount:
                                type: integer
                              unit_cost:
                                type: integer
                              description:
                                type: string
                              tax_allocation:
                                type: integer
                              tax_rate_id:
                                type: string
                                nullable: true
                              tax_rate:
                                type: string
                                nullable: true
                              nominal_code_id:
                                type: string
                                nullable: true
                              nominal_code:
                                type: string
                                nullable: true
                              is_product:
                                type: boolean
                              restock_inventory:
                                type: boolean
                              proration:
                                type: string
                                nullable: true
                              subtotal:
                                type: integer
                              created_at:
                                type: string
                              updated_at:
                                type: string
                              product:
                                type: object
                                properties:
                                  id:
                                    type: integer
                                  sku:
                                    type: string
                                  name:
                                    type: string
                                  barcode:
                                    type: string
                                  image:
                                    type: string
                                    nullable: true
                                  is_lot_tracked:
                                    type: boolean
                                  lot_tracking_method:
                                    type: string
                                    nullable: true
                                  shelf_life_days:
                                    type: string
                                    nullable: true
                                  near_expiry_threshold_days:
                                    type: string
                                    nullable: true
                                  min_remaining_shelf_life_days:
                                    type: string
                                    nullable: true
                              purchase_order_line:
                                type: object
                                properties:
                                  id:
                                    type: integer
                                  purchase_order_id:
                                    type: integer
                                  product_id:
                                    type: integer
                                  quantity:
                                    type: integer
                                  unit_price:
                                    type: integer
                                  purchase_order_number:
                                    type: string
                        line_item_count:
                          type: integer
                        total_quantity:
                          type: integer
                        first_line_sku:
                          type: string
                        has_products:
                          type: boolean
                        allocations:
                          type: array
                        payments:
                          type: array
                        shipments_count:
                          type: integer
                        tags:
                          type: array
                          items:
                            type: string
                        inventory_movements:
                          type: array
                        link_reference:
                          type: string
                        link_type_label:
                          type: string
                        link_route:
                          type: string
                example:
                  data:
                  - id: 17
                    vendor_credit_number: VC-000017
                    supplier_reference: CM-88213
                    supplier_po_number: PO-000310
                    credit_date: '2026-06-20'
                    vendor_credit_note: Credit for damaged goods on PO-000310
                    metadata: null
                    created_at: '2026-06-20T10:15:00.000000Z'
                    updated_at: '2026-07-01T08:00:00.000000Z'
                    archived_at: null
                    fully_allocated_at: null
                    fully_refunded_at: null
                    is_settled: false
                    settlement_breakdown:
                      allocated: 0
                      refunded: 0
                      remaining: 250
                      total: 250
                    credit_status: open
                    credit_status_label: Open
                    payment_status: unapplied
                    payment_status_label: Unapplied
                    is_for_overpayment: false
                    supplier_id: 7
                    supplier:
                      id: 7
                      name: Acme Components Ltd
                      email: accounts@acme-components.com
                    purchase_order_id: 310
                    purchase_order:
                      id: 310
                      purchase_order_number: PO-000310
                    warehouse_id: 2
                    warehouse:
                      id: 2
                      name: Main Warehouse
                    store_id: null
                    store: null
                    currency_id: 1
                    currency_code: USD
                    currency_rate: 1
                    is_tax_included: false
                    tax_rate_id: null
                    tax_rate: null
                    tax_lines: null
                    tax_total: 0
                    tax_credit: 0
                    product_total: 250
                    total_credit: 250
                    total: 250
                    allocated_amount: 0
                    planned_allocation_amount: 0
                    available_to_allocate: 250
                    refunded_amount: 0
                    remaining_amount: 250
                    lines:
                    - id: 31
                      vendor_credit_id: 17
                      purchase_order_line_id: 771
                      financial_line_id: null
                      product_id: 55
                      quantity: 5
                      amount: 250
                      unit_cost: 50
                      description: Blue Widget (Medium)
                      tax_allocation: 0
                      tax_rate_id: null
                      tax_rate: null
                      nominal_code_id: null
                      nominal_code: null
                      is_product: true
                      restock_inventory: false
                      proration: null
                      subtotal: 250
                      created_at: '2026-06-20T10:15:00.000000Z'
                      updated_at: '2026-06-20T10:15:00.000000Z'
                      product:
                        id: 55
                        sku: WID-BLU-M
                        name: Blue Widget (Medium)
                        barcode: 0123456789012
                        image: null
                        is_lot_tracked: false
                        lot_tracking_method: null
                        shelf_life_days: null
                        near_expiry_threshold_days: null
                        min_remaining_shelf_life_days: null
                      purchase_order_line:
                        id: 771
                        purchase_order_id: 310
                        product_id: 55
                        quantity: 20
                        unit_price: 50
                        purchase_order_number: PO-000310
                    line_item_count: 1
                    total_quantity: 5
                    first_line_sku: WID-BLU-M
                    has_products: true
                    allocations: []
                    payments: []
                    shipments_count: 0
                    tags:
                    - damaged-goods
                    inventory_movements: []
                    link_reference: VC-000017
                    link_type_label: Vendor Credit
                    link_route: /purchases/vendor-credits/17
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: accounting:read
      operationId: get-api-vendor-credits-for-invoice-purchase-invoice
  /api/vendor-credits/from-invoice/{purchase_invoice}:
    post:
      tags:
      - Vendor Credits
      summary: Create Vendor Credit from Invoice
      description: 'Create a vendor credit pre-populated from a purchase invoice (bill):
        the invoice''s lines are copied onto the credit, the credit is opened immediately,
        and its full balance is applied against the source invoice. No request body
        is required.


        :::info[Required scope: `accounting:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Returns 422 when a credit cannot be created from the invoice (e.g. the invoice
        has no outstanding balance).'
      requestBody:
        content: {}
      parameters:
      - name: purchase_invoice
        in: path
        schema:
          type: integer
        required: true
        description: Purchase invoice (bill) ID
        example: '88'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      vendor_credit_number:
                        type: string
                      supplier_reference:
                        type: string
                      supplier_po_number:
                        type: string
                      credit_date:
                        type: string
                      vendor_credit_note:
                        type: string
                      metadata:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                      fully_allocated_at:
                        type: string
                        nullable: true
                      fully_refunded_at:
                        type: string
                        nullable: true
                      is_settled:
                        type: boolean
                      settlement_breakdown:
                        type: object
                        properties:
                          allocated:
                            type: integer
                          refunded:
                            type: integer
                          remaining:
                            type: integer
                          total:
                            type: integer
                      credit_status:
                        type: string
                      credit_status_label:
                        type: string
                      payment_status:
                        type: string
                      payment_status_label:
                        type: string
                      is_for_overpayment:
                        type: boolean
                      supplier_id:
                        type: integer
                      supplier:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          email:
                            type: string
                      purchase_order_id:
                        type: integer
                      purchase_order:
                        type: object
                        properties:
                          id:
                            type: integer
                          purchase_order_number:
                            type: string
                      warehouse_id:
                        type: integer
                      warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      store_id:
                        type: string
                        nullable: true
                      store:
                        type: string
                        nullable: true
                      currency_id:
                        type: integer
                      currency_code:
                        type: string
                      currency_rate:
                        type: integer
                      is_tax_included:
                        type: boolean
                      tax_rate_id:
                        type: string
                        nullable: true
                      tax_rate:
                        type: string
                        nullable: true
                      tax_lines:
                        type: string
                        nullable: true
                      tax_total:
                        type: integer
                      tax_credit:
                        type: integer
                      product_total:
                        type: integer
                      total_credit:
                        type: integer
                      total:
                        type: integer
                      allocated_amount:
                        type: integer
                      planned_allocation_amount:
                        type: integer
                      available_to_allocate:
                        type: integer
                      refunded_amount:
                        type: integer
                      remaining_amount:
                        type: integer
                      lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            vendor_credit_id:
                              type: integer
                            purchase_order_line_id:
                              type: integer
                            financial_line_id:
                              type: string
                              nullable: true
                            product_id:
                              type: integer
                            quantity:
                              type: integer
                            amount:
                              type: integer
                            unit_cost:
                              type: integer
                            description:
                              type: string
                            tax_allocation:
                              type: integer
                            tax_rate_id:
                              type: string
                              nullable: true
                            tax_rate:
                              type: string
                              nullable: true
                            nominal_code_id:
                              type: string
                              nullable: true
                            nominal_code:
                              type: string
                              nullable: true
                            is_product:
                              type: boolean
                            restock_inventory:
                              type: boolean
                            proration:
                              type: string
                              nullable: true
                            subtotal:
                              type: integer
                            created_at:
                              type: string
                            updated_at:
                              type: string
                            product:
                              type: object
                              properties:
                                id:
                                  type: integer
                                sku:
                                  type: string
                                name:
                                  type: string
                                barcode:
                                  type: string
                                image:
                                  type: string
                                  nullable: true
                                is_lot_tracked:
                                  type: boolean
                                lot_tracking_method:
                                  type: string
                                  nullable: true
                                shelf_life_days:
                                  type: string
                                  nullable: true
                                near_expiry_threshold_days:
                                  type: string
                                  nullable: true
                                min_remaining_shelf_life_days:
                                  type: string
                                  nullable: true
                            purchase_order_line:
                              type: object
                              properties:
                                id:
                                  type: integer
                                purchase_order_id:
                                  type: integer
                                product_id:
                                  type: integer
                                quantity:
                                  type: integer
                                unit_price:
                                  type: integer
                                purchase_order_number:
                                  type: string
                      line_item_count:
                        type: integer
                      total_quantity:
                        type: integer
                      first_line_sku:
                        type: string
                      has_products:
                        type: boolean
                      allocations:
                        type: array
                      payments:
                        type: array
                      shipments_count:
                        type: integer
                      tags:
                        type: array
                        items:
                          type: string
                      inventory_movements:
                        type: array
                      link_reference:
                        type: string
                      link_type_label:
                        type: string
                      link_route:
                        type: string
                example:
                  message: Vendor credit created successfully.
                  data:
                    id: 17
                    vendor_credit_number: VC-000017
                    supplier_reference: CM-88213
                    supplier_po_number: PO-000310
                    credit_date: '2026-06-20'
                    vendor_credit_note: Credit for damaged goods on PO-000310
                    metadata: null
                    created_at: '2026-06-20T10:15:00.000000Z'
                    updated_at: '2026-07-01T08:00:00.000000Z'
                    archived_at: null
                    fully_allocated_at: null
                    fully_refunded_at: null
                    is_settled: false
                    settlement_breakdown:
                      allocated: 0
                      refunded: 0
                      remaining: 250
                      total: 250
                    credit_status: open
                    credit_status_label: Open
                    payment_status: fully_applied
                    payment_status_label: Fully Applied
                    is_for_overpayment: false
                    supplier_id: 7
                    supplier:
                      id: 7
                      name: Acme Components Ltd
                      email: accounts@acme-components.com
                    purchase_order_id: 310
                    purchase_order:
                      id: 310
                      purchase_order_number: PO-000310
                    warehouse_id: 2
                    warehouse:
                      id: 2
                      name: Main Warehouse
                    store_id: null
                    store: null
                    currency_id: 1
                    currency_code: USD
                    currency_rate: 1
                    is_tax_included: false
                    tax_rate_id: null
                    tax_rate: null
                    tax_lines: null
                    tax_total: 0
                    tax_credit: 0
                    product_total: 250
                    total_credit: 250
                    total: 250
                    allocated_amount: 250
                    planned_allocation_amount: 0
                    available_to_allocate: 0
                    refunded_amount: 0
                    remaining_amount: 0
                    lines:
                    - id: 31
                      vendor_credit_id: 17
                      purchase_order_line_id: 771
                      financial_line_id: null
                      product_id: 55
                      quantity: 5
                      amount: 250
                      unit_cost: 50
                      description: Blue Widget (Medium)
                      tax_allocation: 0
                      tax_rate_id: null
                      tax_rate: null
                      nominal_code_id: null
                      nominal_code: null
                      is_product: true
                      restock_inventory: false
                      proration: null
                      subtotal: 250
                      created_at: '2026-06-20T10:15:00.000000Z'
                      updated_at: '2026-06-20T10:15:00.000000Z'
                      product:
                        id: 55
                        sku: WID-BLU-M
                        name: Blue Widget (Medium)
                        barcode: 0123456789012
                        image: null
                        is_lot_tracked: false
                        lot_tracking_method: null
                        shelf_life_days: null
                        near_expiry_threshold_days: null
                        min_remaining_shelf_life_days: null
                      purchase_order_line:
                        id: 771
                        purchase_order_id: 310
                        product_id: 55
                        quantity: 20
                        unit_price: 50
                        purchase_order_number: PO-000310
                    line_item_count: 1
                    total_quantity: 5
                    first_line_sku: WID-BLU-M
                    has_products: true
                    allocations: []
                    payments: []
                    shipments_count: 0
                    tags:
                    - damaged-goods
                    inventory_movements: []
                    link_reference: VC-000017
                    link_type_label: Vendor Credit
                    link_route: /purchases/vendor-credits/17
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: object
                    properties:
                      purchase_invoice_id:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: object
                              properties:
                                id:
                                  type: integer
                example:
                  errors:
                    purchase_invoice_id:
                    - message: The invoice has no outstanding balance to credit.
                      code: VendorCredit422
                      data:
                        id: 88
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: accounting:write
      operationId: post-api-vendor-credits-from-invoice-purchase-invoice
  /api/vendor-credits/{vendor_credit}/tags:
    put:
      tags:
      - Vendor Credits
      summary: Update Vendor Credit Tags
      description: 'Replace the full set of tags on a vendor credit. The tags array
        is required (send an empty array to remove all tags); each tag is a string
        of up to 64 characters. Tags that do not exist yet are created automatically.


        :::info[Required scope: `accounting:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Returns the updated vendor credit.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                tags:
                  type: array
                  items:
                    type: string
              example:
                tags:
                - damaged-goods
                - q3-review
      parameters:
      - name: vendor_credit
        in: path
        schema:
          type: integer
        required: true
        description: Vendor credit ID
        example: '17'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      vendor_credit_number:
                        type: string
                      supplier_reference:
                        type: string
                      supplier_po_number:
                        type: string
                      credit_date:
                        type: string
                      vendor_credit_note:
                        type: string
                      metadata:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                      fully_allocated_at:
                        type: string
                        nullable: true
                      fully_refunded_at:
                        type: string
                        nullable: true
                      is_settled:
                        type: boolean
                      settlement_breakdown:
                        type: object
                        properties:
                          allocated:
                            type: integer
                          refunded:
                            type: integer
                          remaining:
                            type: integer
                          total:
                            type: integer
                      credit_status:
                        type: string
                      credit_status_label:
                        type: string
                      payment_status:
                        type: string
                      payment_status_label:
                        type: string
                      is_for_overpayment:
                        type: boolean
                      supplier_id:
                        type: integer
                      supplier:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          email:
                            type: string
                      purchase_order_id:
                        type: integer
                      purchase_order:
                        type: object
                        properties:
                          id:
                            type: integer
                          purchase_order_number:
                            type: string
                      warehouse_id:
                        type: integer
                      warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      store_id:
                        type: string
                        nullable: true
                      store:
                        type: string
                        nullable: true
                      currency_id:
                        type: integer
                      currency_code:
                        type: string
                      currency_rate:
                        type: integer
                      is_tax_included:
                        type: boolean
                      tax_rate_id:
                        type: string
                        nullable: true
                      tax_rate:
                        type: string
                        nullable: true
                      tax_lines:
                        type: string
                        nullable: true
                      tax_total:
                        type: integer
                      tax_credit:
                        type: integer
                      product_total:
                        type: integer
                      total_credit:
                        type: integer
                      total:
                        type: integer
                      allocated_amount:
                        type: integer
                      planned_allocation_amount:
                        type: integer
                      available_to_allocate:
                        type: integer
                      refunded_amount:
                        type: integer
                      remaining_amount:
                        type: integer
                      lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            vendor_credit_id:
                              type: integer
                            purchase_order_line_id:
                              type: integer
                            financial_line_id:
                              type: string
                              nullable: true
                            product_id:
                              type: integer
                            quantity:
                              type: integer
                            amount:
                              type: integer
                            unit_cost:
                              type: integer
                            description:
                              type: string
                            tax_allocation:
                              type: integer
                            tax_rate_id:
                              type: string
                              nullable: true
                            tax_rate:
                              type: string
                              nullable: true
                            nominal_code_id:
                              type: string
                              nullable: true
                            nominal_code:
                              type: string
                              nullable: true
                            is_product:
                              type: boolean
                            restock_inventory:
                              type: boolean
                            proration:
                              type: string
                              nullable: true
                            subtotal:
                              type: integer
                            created_at:
                              type: string
                            updated_at:
                              type: string
                            product:
                              type: object
                              properties:
                                id:
                                  type: integer
                                sku:
                                  type: string
                                name:
                                  type: string
                                barcode:
                                  type: string
                                image:
                                  type: string
                                  nullable: true
                                is_lot_tracked:
                                  type: boolean
                                lot_tracking_method:
                                  type: string
                                  nullable: true
                                shelf_life_days:
                                  type: string
                                  nullable: true
                                near_expiry_threshold_days:
                                  type: string
                                  nullable: true
                                min_remaining_shelf_life_days:
                                  type: string
                                  nullable: true
                            purchase_order_line:
                              type: object
                              properties:
                                id:
                                  type: integer
                                purchase_order_id:
                                  type: integer
                                product_id:
                                  type: integer
                                quantity:
                                  type: integer
                                unit_price:
                                  type: integer
                                purchase_order_number:
                                  type: string
                      line_item_count:
                        type: integer
                      total_quantity:
                        type: integer
                      first_line_sku:
                        type: string
                      has_products:
                        type: boolean
                      allocations:
                        type: array
                      payments:
                        type: array
                      shipments_count:
                        type: integer
                      tags:
                        type: array
                        items:
                          type: string
                      inventory_movements:
                        type: array
                      link_reference:
                        type: string
                      link_type_label:
                        type: string
                      link_route:
                        type: string
                example:
                  message: Vendor credit tags VC-000017 updated successfully.
                  data:
                    id: 17
                    vendor_credit_number: VC-000017
                    supplier_reference: CM-88213
                    supplier_po_number: PO-000310
                    credit_date: '2026-06-20'
                    vendor_credit_note: Credit for damaged goods on PO-000310
                    metadata: null
                    created_at: '2026-06-20T10:15:00.000000Z'
                    updated_at: '2026-07-01T08:00:00.000000Z'
                    archived_at: null
                    fully_allocated_at: null
                    fully_refunded_at: null
                    is_settled: false
                    settlement_breakdown:
                      allocated: 0
                      refunded: 0
                      remaining: 250
                      total: 250
                    credit_status: open
                    credit_status_label: Open
                    payment_status: unapplied
                    payment_status_label: Unapplied
                    is_for_overpayment: false
                    supplier_id: 7
                    supplier:
                      id: 7
                      name: Acme Components Ltd
                      email: accounts@acme-components.com
                    purchase_order_id: 310
                    purchase_order:
                      id: 310
                      purchase_order_number: PO-000310
                    warehouse_id: 2
                    warehouse:
                      id: 2
                      name: Main Warehouse
                    store_id: null
                    store: null
                    currency_id: 1
                    currency_code: USD
                    currency_rate: 1
                    is_tax_included: false
                    tax_rate_id: null
                    tax_rate: null
                    tax_lines: null
                    tax_total: 0
                    tax_credit: 0
                    product_total: 250
                    total_credit: 250
                    total: 250
                    allocated_amount: 0
                    planned_allocation_amount: 0
                    available_to_allocate: 250
                    refunded_amount: 0
                    remaining_amount: 250
                    lines:
                    - id: 31
                      vendor_credit_id: 17
                      purchase_order_line_id: 771
                      financial_line_id: null
                      product_id: 55
                      quantity: 5
                      amount: 250
                      unit_cost: 50
                      description: Blue Widget (Medium)
                      tax_allocation: 0
                      tax_rate_id: null
                      tax_rate: null
                      nominal_code_id: null
                      nominal_code: null
                      is_product: true
                      restock_inventory: false
                      proration: null
                      subtotal: 250
                      created_at: '2026-06-20T10:15:00.000000Z'
                      updated_at: '2026-06-20T10:15:00.000000Z'
                      product:
                        id: 55
                        sku: WID-BLU-M
                        name: Blue Widget (Medium)
                        barcode: 0123456789012
                        image: null
                        is_lot_tracked: false
                        lot_tracking_method: null
                        shelf_life_days: null
                        near_expiry_threshold_days: null
                        min_remaining_shelf_life_days: null
                      purchase_order_line:
                        id: 771
                        purchase_order_id: 310
                        product_id: 55
                        quantity: 20
                        unit_price: 50
                        purchase_order_number: PO-000310
                    line_item_count: 1
                    total_quantity: 5
                    first_line_sku: WID-BLU-M
                    has_products: true
                    allocations: []
                    payments: []
                    shipments_count: 0
                    tags:
                    - damaged-goods
                    - q3-review
                    inventory_movements: []
                    link_reference: VC-000017
                    link_type_label: Vendor Credit
                    link_route: /purchases/vendor-credits/17
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: accounting:write
      operationId: put-api-vendor-credits-vendor-credit-tags
  /api/vendor-credits/{vendor_credit}/archive:
    put:
      tags:
      - Vendor Credits
      summary: Archive Vendor Credit
      description: 'Archive (soft-hide) a vendor credit. Returns a warning if it is
        already archived.


        :::info[Required scope: `accounting:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters:
      - name: vendor_credit
        in: path
        schema:
          type: integer
        required: true
        description: Vendor credit ID
        example: '1'
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: accounting:write
      operationId: put-api-vendor-credits-vendor-credit-archive
  /api/vendor-credits/{vendor_credit}/unarchive:
    put:
      tags:
      - Vendor Credits
      summary: Unarchive Vendor Credit
      description: 'Unarchive a previously archived vendor credit. Returns a warning
        if it was not archived.


        :::info[Required scope: `accounting:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters:
      - name: vendor_credit
        in: path
        schema:
          type: integer
        required: true
        description: Vendor credit ID
        example: '1'
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: accounting:write
      operationId: put-api-vendor-credits-vendor-credit-unarchive
  /api/vendor-credits/{vendor_credit}/void:
    post:
      tags:
      - Vendor Credits
      summary: Void Vendor Credit
      description: 'Void a vendor credit. This reverses any inventory movements created
        by the credit (e.g. restock reversals) and reverses the linked accounting
        transaction. Idempotent: voiding an already-voided credit is a no-op.


        :::info[Required scope: `accounting:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters:
      - name: vendor_credit
        in: path
        schema:
          type: integer
        required: true
        description: Vendor credit ID
        example: '1'
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: accounting:write
      operationId: post-api-vendor-credits-vendor-credit-void
  /api/vendor-credits/{vendor_credit}/close:
    post:
      tags:
      - Vendor Credits
      summary: Close Vendor Credit
      description: 'Close a vendor credit — marks it as fully settled so no further
        allocations or edits are allowed. Typically called after the credit has been
        fully allocated or refunded.


        :::info[Required scope: `accounting:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters:
      - name: vendor_credit
        in: path
        schema:
          type: integer
        required: true
        description: Vendor credit ID
        example: '1'
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: accounting:write
      operationId: post-api-vendor-credits-vendor-credit-close
  /api/vendor-credits/{vendor_credit}/authorize:
    post:
      tags:
      - Vendor Credits
      summary: Authorize Vendor Credit
      description: 'Authorize a draft vendor credit, transitioning it to open. Authorization
        posts the credit''s accounting transaction, records the FIFO cost layers consumed
        by the credited quantities, and creates planned inventory allocations for
        lines marked for restock.


        :::info[Required scope: `accounting:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Returns 422 when the credit is not in a state that can be authorized.'
      requestBody:
        content: {}
      parameters:
      - name: vendor_credit
        in: path
        schema:
          type: integer
        required: true
        description: Vendor credit ID
        example: '17'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      vendor_credit_number:
                        type: string
                      supplier_reference:
                        type: string
                      supplier_po_number:
                        type: string
                      credit_date:
                        type: string
                      vendor_credit_note:
                        type: string
                      metadata:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                      fully_allocated_at:
                        type: string
                        nullable: true
                      fully_refunded_at:
                        type: string
                        nullable: true
                      is_settled:
                        type: boolean
                      settlement_breakdown:
                        type: object
                        properties:
                          allocated:
                            type: integer
                          refunded:
                            type: integer
                          remaining:
                            type: integer
                          total:
                            type: integer
                      credit_status:
                        type: string
                      credit_status_label:
                        type: string
                      payment_status:
                        type: string
                      payment_status_label:
                        type: string
                      is_for_overpayment:
                        type: boolean
                      supplier_id:
                        type: integer
                      supplier:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          email:
                            type: string
                      purchase_order_id:
                        type: integer
                      purchase_order:
                        type: object
                        properties:
                          id:
                            type: integer
                          purchase_order_number:
                            type: string
                      warehouse_id:
                        type: integer
                      warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      store_id:
                        type: string
                        nullable: true
                      store:
                        type: string
                        nullable: true
                      currency_id:
                        type: integer
                      currency_code:
                        type: string
                      currency_rate:
                        type: integer
                      is_tax_included:
                        type: boolean
                      tax_rate_id:
                        type: string
                        nullable: true
                      tax_rate:
                        type: string
                        nullable: true
                      tax_lines:
                        type: string
                        nullable: true
                      tax_total:
                        type: integer
                      tax_credit:
                        type: integer
                      product_total:
                        type: integer
                      total_credit:
                        type: integer
                      total:
                        type: integer
                      allocated_amount:
                        type: integer
                      planned_allocation_amount:
                        type: integer
                      available_to_allocate:
                        type: integer
                      refunded_amount:
                        type: integer
                      remaining_amount:
                        type: integer
                      lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            vendor_credit_id:
                              type: integer
                            purchase_order_line_id:
                              type: integer
                            financial_line_id:
                              type: string
                              nullable: true
                            product_id:
                              type: integer
                            quantity:
                              type: integer
                            amount:
                              type: integer
                            unit_cost:
                              type: integer
                            description:
                              type: string
                            tax_allocation:
                              type: integer
                            tax_rate_id:
                              type: string
                              nullable: true
                            tax_rate:
                              type: string
                              nullable: true
                            nominal_code_id:
                              type: string
                              nullable: true
                            nominal_code:
                              type: string
                              nullable: true
                            is_product:
                              type: boolean
                            restock_inventory:
                              type: boolean
                            proration:
                              type: string
                              nullable: true
                            subtotal:
                              type: integer
                            created_at:
                              type: string
                            updated_at:
                              type: string
                            product:
                              type: object
                              properties:
                                id:
                                  type: integer
                                sku:
                                  type: string
                                name:
                                  type: string
                                barcode:
                                  type: string
                                image:
                                  type: string
                                  nullable: true
                                is_lot_tracked:
                                  type: boolean
                                lot_tracking_method:
                                  type: string
                                  nullable: true
                                shelf_life_days:
                                  type: string
                                  nullable: true
                                near_expiry_threshold_days:
                                  type: string
                                  nullable: true
                                min_remaining_shelf_life_days:
                                  type: string
                                  nullable: true
                            purchase_order_line:
                              type: object
                              properties:
                                id:
                                  type: integer
                                purchase_order_id:
                                  type: integer
                                product_id:
                                  type: integer
                                quantity:
                                  type: integer
                                unit_price:
                                  type: integer
                                purchase_order_number:
                                  type: string
                      line_item_count:
                        type: integer
                      total_quantity:
                        type: integer
                      first_line_sku:
                        type: string
                      has_products:
                        type: boolean
                      allocations:
                        type: array
                      payments:
                        type: array
                      shipments_count:
                        type: integer
                      tags:
                        type: array
                        items:
                          type: string
                      inventory_movements:
                        type: array
                      link_reference:
                        type: string
                      link_type_label:
                        type: string
                      link_route:
                        type: string
                example:
                  message: Vendor credit VC-000017 updated successfully.
                  data:
                    id: 17
                    vendor_credit_number: VC-000017
                    supplier_reference: CM-88213
                    supplier_po_number: PO-000310
                    credit_date: '2026-06-20'
                    vendor_credit_note: Credit for damaged goods on PO-000310
                    metadata: null
                    created_at: '2026-06-20T10:15:00.000000Z'
                    updated_at: '2026-07-01T08:00:00.000000Z'
                    archived_at: null
                    fully_allocated_at: null
                    fully_refunded_at: null
                    is_settled: false
                    settlement_breakdown:
                      allocated: 0
                      refunded: 0
                      remaining: 250
                      total: 250
                    credit_status: open
                    credit_status_label: Open
                    payment_status: unapplied
                    payment_status_label: Unapplied
                    is_for_overpayment: false
                    supplier_id: 7
                    supplier:
                      id: 7
                      name: Acme Components Ltd
                      email: accounts@acme-components.com
                    purchase_order_id: 310
                    purchase_order:
                      id: 310
                      purchase_order_number: PO-000310
                    warehouse_id: 2
                    warehouse:
                      id: 2
                      name: Main Warehouse
                    store_id: null
                    store: null
                    currency_id: 1
                    currency_code: USD
                    currency_rate: 1
                    is_tax_included: false
                    tax_rate_id: null
                    tax_rate: null
                    tax_lines: null
                    tax_total: 0
                    tax_credit: 0
                    product_total: 250
                    total_credit: 250
                    total: 250
                    allocated_amount: 0
                    planned_allocation_amount: 0
                    available_to_allocate: 250
                    refunded_amount: 0
                    remaining_amount: 250
                    lines:
                    - id: 31
                      vendor_credit_id: 17
                      purchase_order_line_id: 771
                      financial_line_id: null
                      product_id: 55
                      quantity: 5
                      amount: 250
                      unit_cost: 50
                      description: Blue Widget (Medium)
                      tax_allocation: 0
                      tax_rate_id: null
                      tax_rate: null
                      nominal_code_id: null
                      nominal_code: null
                      is_product: true
                      restock_inventory: false
                      proration: null
                      subtotal: 250
                      created_at: '2026-06-20T10:15:00.000000Z'
                      updated_at: '2026-06-20T10:15:00.000000Z'
                      product:
                        id: 55
                        sku: WID-BLU-M
                        name: Blue Widget (Medium)
                        barcode: 0123456789012
                        image: null
                        is_lot_tracked: false
                        lot_tracking_method: null
                        shelf_life_days: null
                        near_expiry_threshold_days: null
                        min_remaining_shelf_life_days: null
                      purchase_order_line:
                        id: 771
                        purchase_order_id: 310
                        product_id: 55
                        quantity: 20
                        unit_price: 50
                        purchase_order_number: PO-000310
                    line_item_count: 1
                    total_quantity: 5
                    first_line_sku: WID-BLU-M
                    has_products: true
                    allocations: []
                    payments: []
                    shipments_count: 0
                    tags:
                    - damaged-goods
                    inventory_movements: []
                    link_reference: VC-000017
                    link_type_label: Vendor Credit
                    link_route: /purchases/vendor-credits/17
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: object
                    properties:
                      credit_status:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: object
                              properties:
                                id:
                                  type: integer
                example:
                  errors:
                    credit_status:
                    - message: Only draft credits can be authorized.
                      code: VendorCredit422
                      data:
                        id: 17
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: accounting:write
      operationId: post-api-vendor-credits-vendor-credit-authorize
  /api/vendor-credits/{vendor_credit}/unauthorize:
    post:
      tags:
      - Vendor Credits
      summary: Unauthorize Vendor Credit
      description: 'Revert an open vendor credit back to draft. This reverses everything
        authorization created: planned inventory allocations, write-off inventory
        movements, FIFO layer usages, and the accounting transaction.


        :::info[Required scope: `accounting:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Returns 422 when the credit cannot be reverted (e.g. it already has applied
        allocations, refund payments, or return shipments).'
      requestBody:
        content: {}
      parameters:
      - name: vendor_credit
        in: path
        schema:
          type: integer
        required: true
        description: Vendor credit ID
        example: '17'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      vendor_credit_number:
                        type: string
                      supplier_reference:
                        type: string
                      supplier_po_number:
                        type: string
                      credit_date:
                        type: string
                      vendor_credit_note:
                        type: string
                      metadata:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                      fully_allocated_at:
                        type: string
                        nullable: true
                      fully_refunded_at:
                        type: string
                        nullable: true
                      is_settled:
                        type: boolean
                      settlement_breakdown:
                        type: object
                        properties:
                          allocated:
                            type: integer
                          refunded:
                            type: integer
                          remaining:
                            type: integer
                          total:
                            type: integer
                      credit_status:
                        type: string
                      credit_status_label:
                        type: string
                      payment_status:
                        type: string
                      payment_status_label:
                        type: string
                      is_for_overpayment:
                        type: boolean
                      supplier_id:
                        type: integer
                      supplier:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          email:
                            type: string
                      purchase_order_id:
                        type: integer
                      purchase_order:
                        type: object
                        properties:
                          id:
                            type: integer
                          purchase_order_number:
                            type: string
                      warehouse_id:
                        type: integer
                      warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      store_id:
                        type: string
                        nullable: true
                      store:
                        type: string
                        nullable: true
                      currency_id:
                        type: integer
                      currency_code:
                        type: string
                      currency_rate:
                        type: integer
                      is_tax_included:
                        type: boolean
                      tax_rate_id:
                        type: string
                        nullable: true
                      tax_rate:
                        type: string
                        nullable: true
                      tax_lines:
                        type: string
                        nullable: true
                      tax_total:
                        type: integer
                      tax_credit:
                        type: integer
                      product_total:
                        type: integer
                      total_credit:
                        type: integer
                      total:
                        type: integer
                      allocated_amount:
                        type: integer
                      planned_allocation_amount:
                        type: integer
                      available_to_allocate:
                        type: integer
                      refunded_amount:
                        type: integer
                      remaining_amount:
                        type: integer
                      lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            vendor_credit_id:
                              type: integer
                            purchase_order_line_id:
                              type: integer
                            financial_line_id:
                              type: string
                              nullable: true
                            product_id:
                              type: integer
                            quantity:
                              type: integer
                            amount:
                              type: integer
                            unit_cost:
                              type: integer
                            description:
                              type: string
                            tax_allocation:
                              type: integer
                            tax_rate_id:
                              type: string
                              nullable: true
                            tax_rate:
                              type: string
                              nullable: true
                            nominal_code_id:
                              type: string
                              nullable: true
                            nominal_code:
                              type: string
                              nullable: true
                            is_product:
                              type: boolean
                            restock_inventory:
                              type: boolean
                            proration:
                              type: string
                              nullable: true
                            subtotal:
                              type: integer
                            created_at:
                              type: string
                            updated_at:
                              type: string
                            product:
                              type: object
                              properties:
                                id:
                                  type: integer
                                sku:
                                  type: string
                                name:
                                  type: string
                                barcode:
                                  type: string
                                image:
                                  type: string
                                  nullable: true
                                is_lot_tracked:
                                  type: boolean
                                lot_tracking_method:
                                  type: string
                                  nullable: true
                                shelf_life_days:
                                  type: string
                                  nullable: true
                                near_expiry_threshold_days:
                                  type: string
                                  nullable: true
                                min_remaining_shelf_life_days:
                                  type: string
                                  nullable: true
                            purchase_order_line:
                              type: object
                              properties:
                                id:
                                  type: integer
                                purchase_order_id:
                                  type: integer
                                product_id:
                                  type: integer
                                quantity:
                                  type: integer
                                unit_price:
                                  type: integer
                                purchase_order_number:
                                  type: string
                      line_item_count:
                        type: integer
                      total_quantity:
                        type: integer
                      first_line_sku:
                        type: string
                      has_products:
                        type: boolean
                      allocations:
                        type: array
                      payments:
                        type: array
                      shipments_count:
                        type: integer
                      tags:
                        type: array
                      inventory_movements:
                        type: array
                      link_reference:
                        type: string
                      link_type_label:
                        type: string
                      link_route:
                        type: string
                example:
                  message: Vendor credit VC-000017 updated successfully.
                  data:
                    id: 17
                    vendor_credit_number: VC-000017
                    supplier_reference: CM-88213
                    supplier_po_number: PO-000310
                    credit_date: '2026-06-20'
                    vendor_credit_note: Credit for damaged goods on PO-000310
                    metadata: null
                    created_at: '2026-06-20T10:15:00.000000Z'
                    updated_at: '2026-07-01T08:00:00.000000Z'
                    archived_at: null
                    fully_allocated_at: null
                    fully_refunded_at: null
                    is_settled: false
                    settlement_breakdown:
                      allocated: 0
                      refunded: 0
                      remaining: 250
                      total: 250
                    credit_status: draft
                    credit_status_label: Draft
                    payment_status: unapplied
                    payment_status_label: Unapplied
                    is_for_overpayment: false
                    supplier_id: 7
                    supplier:
                      id: 7
                      name: Acme Components Ltd
                      email: accounts@acme-components.com
                    purchase_order_id: 310
                    purchase_order:
                      id: 310
                      purchase_order_number: PO-000310
                    warehouse_id: 2
                    warehouse:
                      id: 2
                      name: Main Warehouse
                    store_id: null
                    store: null
                    currency_id: 1
                    currency_code: USD
                    currency_rate: 1
                    is_tax_included: false
                    tax_rate_id: null
                    tax_rate: null
                    tax_lines: null
                    tax_total: 0
                    tax_credit: 0
                    product_total: 250
                    total_credit: 250
                    total: 250
                    allocated_amount: 0
                    planned_allocation_amount: 0
                    available_to_allocate: 250
                    refunded_amount: 0
                    remaining_amount: 250
                    lines:
                    - id: 31
                      vendor_credit_id: 17
                      purchase_order_line_id: 771
                      financial_line_id: null
                      product_id: 55
                      quantity: 5
                      amount: 250
                      unit_cost: 50
                      description: Blue Widget (Medium)
                      tax_allocation: 0
                      tax_rate_id: null
                      tax_rate: null
                      nominal_code_id: null
                      nominal_code: null
                      is_product: true
                      restock_inventory: false
                      proration: null
                      subtotal: 250
                      created_at: '2026-06-20T10:15:00.000000Z'
                      updated_at: '2026-06-20T10:15:00.000000Z'
                      product:
                        id: 55
                        sku: WID-BLU-M
                        name: Blue Widget (Medium)
                        barcode: 0123456789012
                        image: null
                        is_lot_tracked: false
                        lot_tracking_method: null
                        shelf_life_days: null
                        near_expiry_threshold_days: null
                        min_remaining_shelf_life_days: null
                      purchase_order_line:
                        id: 771
                        purchase_order_id: 310
                        product_id: 55
                        quantity: 20
                        unit_price: 50
                        purchase_order_number: PO-000310
                    line_item_count: 1
                    total_quantity: 5
                    first_line_sku: WID-BLU-M
                    has_products: true
                    allocations: []
                    payments: []
                    shipments_count: 0
                    tags: []
                    inventory_movements: []
                    link_reference: VC-000017
                    link_type_label: Vendor Credit
                    link_route: /purchases/vendor-credits/17
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: object
                    properties:
                      credit_status:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: object
                              properties:
                                id:
                                  type: integer
                example:
                  errors:
                    credit_status:
                    - message: Credit has allocations and cannot be reverted to draft.
                      code: VendorCredit422
                      data:
                        id: 17
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: accounting:write
      operationId: post-api-vendor-credits-vendor-credit-unauthorize
  /api/vendor-credits/{vendor_credit}/reopen:
    post:
      tags:
      - Vendor Credits
      summary: Reopen Vendor Credit
      description: 'Reopen a closed vendor credit, making its remaining balance available
        to allocate or refund again. No request body is required.


        :::info[Required scope: `accounting:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Returns the updated vendor credit.'
      requestBody:
        content: {}
      parameters:
      - name: vendor_credit
        in: path
        schema:
          type: integer
        required: true
        description: Vendor credit ID
        example: '17'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      vendor_credit_number:
                        type: string
                      supplier_reference:
                        type: string
                      supplier_po_number:
                        type: string
                      credit_date:
                        type: string
                      vendor_credit_note:
                        type: string
                      metadata:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                      fully_allocated_at:
                        type: string
                        nullable: true
                      fully_refunded_at:
                        type: string
                        nullable: true
                      is_settled:
                        type: boolean
                      settlement_breakdown:
                        type: object
                        properties:
                          allocated:
                            type: integer
                          refunded:
                            type: integer
                          remaining:
                            type: integer
                          total:
                            type: integer
                      credit_status:
                        type: string
                      credit_status_label:
                        type: string
                      payment_status:
                        type: string
                      payment_status_label:
                        type: string
                      is_for_overpayment:
                        type: boolean
                      supplier_id:
                        type: integer
                      supplier:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          email:
                            type: string
                      purchase_order_id:
                        type: integer
                      purchase_order:
                        type: object
                        properties:
                          id:
                            type: integer
                          purchase_order_number:
                            type: string
                      warehouse_id:
                        type: integer
                      warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      store_id:
                        type: string
                        nullable: true
                      store:
                        type: string
                        nullable: true
                      currency_id:
                        type: integer
                      currency_code:
                        type: string
                      currency_rate:
                        type: integer
                      is_tax_included:
                        type: boolean
                      tax_rate_id:
                        type: string
                        nullable: true
                      tax_rate:
                        type: string
                        nullable: true
                      tax_lines:
                        type: string
                        nullable: true
                      tax_total:
                        type: integer
                      tax_credit:
                        type: integer
                      product_total:
                        type: integer
                      total_credit:
                        type: integer
                      total:
                        type: integer
                      allocated_amount:
                        type: integer
                      planned_allocation_amount:
                        type: integer
                      available_to_allocate:
                        type: integer
                      refunded_amount:
                        type: integer
                      remaining_amount:
                        type: integer
                      lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            vendor_credit_id:
                              type: integer
                            purchase_order_line_id:
                              type: integer
                            financial_line_id:
                              type: string
                              nullable: true
                            product_id:
                              type: integer
                            quantity:
                              type: integer
                            amount:
                              type: integer
                            unit_cost:
                              type: integer
                            description:
                              type: string
                            tax_allocation:
                              type: integer
                            tax_rate_id:
                              type: string
                              nullable: true
                            tax_rate:
                              type: string
                              nullable: true
                            nominal_code_id:
                              type: string
                              nullable: true
                            nominal_code:
                              type: string
                              nullable: true
                            is_product:
                              type: boolean
                            restock_inventory:
                              type: boolean
                            proration:
                              type: string
                              nullable: true
                            subtotal:
                              type: integer
                            created_at:
                              type: string
                            updated_at:
                              type: string
                            product:
                              type: object
                              properties:
                                id:
                                  type: integer
                                sku:
                                  type: string
                                name:
                                  type: string
                                barcode:
                                  type: string
                                image:
                                  type: string
                                  nullable: true
                                is_lot_tracked:
                                  type: boolean
                                lot_tracking_method:
                                  type: string
                                  nullable: true
                                shelf_life_days:
                                  type: string
                                  nullable: true
                                near_expiry_threshold_days:
                                  type: string
                                  nullable: true
                                min_remaining_shelf_life_days:
                                  type: string
                                  nullable: true
                            purchase_order_line:
                              type: object
                              properties:
                                id:
                                  type: integer
                                purchase_order_id:
                                  type: integer
                                product_id:
                                  type: integer
                                quantity:
                                  type: integer
                                unit_price:
                                  type: integer
                                purchase_order_number:
                                  type: string
                      line_item_count:
                        type: integer
                      total_quantity:
                        type: integer
                      first_line_sku:
                        type: string
                      has_products:
                        type: boolean
                      allocations:
                        type: array
                      payments:
                        type: array
                      shipments_count:
                        type: integer
                      tags:
                        type: array
                        items:
                          type: string
                      inventory_movements:
                        type: array
                      link_reference:
                        type: string
                      link_type_label:
                        type: string
                      link_route:
                        type: string
                example:
                  message: Vendor credit VC-000017 updated successfully.
                  data:
                    id: 17
                    vendor_credit_number: VC-000017
                    supplier_reference: CM-88213
                    supplier_po_number: PO-000310
                    credit_date: '2026-06-20'
                    vendor_credit_note: Credit for damaged goods on PO-000310
                    metadata: null
                    created_at: '2026-06-20T10:15:00.000000Z'
                    updated_at: '2026-07-01T08:00:00.000000Z'
                    archived_at: null
                    fully_allocated_at: null
                    fully_refunded_at: null
                    is_settled: false
                    settlement_breakdown:
                      allocated: 0
                      refunded: 0
                      remaining: 250
                      total: 250
                    credit_status: open
                    credit_status_label: Open
                    payment_status: unapplied
                    payment_status_label: Unapplied
                    is_for_overpayment: false
                    supplier_id: 7
                    supplier:
                      id: 7
                      name: Acme Components Ltd
                      email: accounts@acme-components.com
                    purchase_order_id: 310
                    purchase_order:
                      id: 310
                      purchase_order_number: PO-000310
                    warehouse_id: 2
                    warehouse:
                      id: 2
                      name: Main Warehouse
                    store_id: null
                    store: null
                    currency_id: 1
                    currency_code: USD
                    currency_rate: 1
                    is_tax_included: false
                    tax_rate_id: null
                    tax_rate: null
                    tax_lines: null
                    tax_total: 0
                    tax_credit: 0
                    product_total: 250
                    total_credit: 250
                    total: 250
                    allocated_amount: 0
                    planned_allocation_amount: 0
                    available_to_allocate: 250
                    refunded_amount: 0
                    remaining_amount: 250
                    lines:
                    - id: 31
                      vendor_credit_id: 17
                      purchase_order_line_id: 771
                      financial_line_id: null
                      product_id: 55
                      quantity: 5
                      amount: 250
                      unit_cost: 50
                      description: Blue Widget (Medium)
                      tax_allocation: 0
                      tax_rate_id: null
                      tax_rate: null
                      nominal_code_id: null
                      nominal_code: null
                      is_product: true
                      restock_inventory: false
                      proration: null
                      subtotal: 250
                      created_at: '2026-06-20T10:15:00.000000Z'
                      updated_at: '2026-06-20T10:15:00.000000Z'
                      product:
                        id: 55
                        sku: WID-BLU-M
                        name: Blue Widget (Medium)
                        barcode: 0123456789012
                        image: null
                        is_lot_tracked: false
                        lot_tracking_method: null
                        shelf_life_days: null
                        near_expiry_threshold_days: null
                        min_remaining_shelf_life_days: null
                      purchase_order_line:
                        id: 771
                        purchase_order_id: 310
                        product_id: 55
                        quantity: 20
                        unit_price: 50
                        purchase_order_number: PO-000310
                    line_item_count: 1
                    total_quantity: 5
                    first_line_sku: WID-BLU-M
                    has_products: true
                    allocations: []
                    payments: []
                    shipments_count: 0
                    tags:
                    - damaged-goods
                    inventory_movements: []
                    link_reference: VC-000017
                    link_type_label: Vendor Credit
                    link_route: /purchases/vendor-credits/17
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: accounting:write
      operationId: post-api-vendor-credits-vendor-credit-reopen
  /api/vendor-credits/{vendor_credit}/write-off-impact:
    get:
      tags:
      - Vendor Credits
      summary: Preview Vendor Credit Write-Off Impact
      description: 'Get a read-only preview of the order allocations that authorizing
        this vendor credit would consume when its write-off lines post their outbound
        decrement. Each row is one product whose stock the write-off would remove,
        split into free, soft-reserved and hard-allocated quantities, and lists the
        affected sales-order allocations highest-priority first so you can see which
        orders — and which printed shipping labels — would be demoted or voided before
        you authorize the credit.


        This endpoint makes no changes.


        Response fields:

        - `data[].product_id` / `product_sku` / `product_name` — the product the action
        would consume stock for.

        - `data[].shortfall_quantity` — how much more than the available quantity
        the action removes; stock goes negative when greater than 0.

        - `data[].unallocated_quantity` / `soft_allocated_quantity` / `hard_allocated_quantity`
        — the free / soft-reserved / hard-allocated (label-printed) split of the consumed
        quantity.

        - `data[].affected_allocations[]` — the order allocations that would be consumed,
        highest priority first. `allocation_type` is `soft` or `hard`. For hard rows,
        `fulfillment_id` and `carrier` identify the printed label and `carrier_void_supported`
        / `voidable_status` (`voidable` or otherwise) indicate whether the label can
        be voided through the API.


        Authentication: Requires Bearer token (PAT).'
      parameters:
      - name: vendor_credit
        in: path
        schema:
          type: integer
        required: true
        description: Vendor credit ID
        example: '17'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        product_id:
                          type: integer
                        product_sku:
                          type: string
                        product_name:
                          type: string
                        shortfall_quantity:
                          type: integer
                        unallocated_quantity:
                          type: integer
                        soft_allocated_quantity:
                          type: integer
                        hard_allocated_quantity:
                          type: integer
                        affected_allocations:
                          type: array
                          items:
                            type: object
                            properties:
                              allocation_id:
                                type: integer
                              allocation_type:
                                type: string
                              sales_order_id:
                                type: integer
                              order_number:
                                type: string
                              customer_name:
                                type: string
                              fulfillment_id:
                                type: string
                                nullable: true
                              carrier:
                                type: string
                                nullable: true
                              carrier_void_supported:
                                type: string
                                nullable: true
                              voidable_status:
                                type: string
                                nullable: true
                              voidable_detail:
                                type: string
                                nullable: true
                              quantity:
                                type: integer
                example:
                  data:
                  - product_id: 123
                    product_sku: WIDGET-001
                    product_name: Blue Widget 500ml
                    shortfall_quantity: 0
                    unallocated_quantity: 4
                    soft_allocated_quantity: 3
                    hard_allocated_quantity: 2
                    affected_allocations:
                    - allocation_id: 88213
                      allocation_type: soft
                      sales_order_id: 4521
                      order_number: SO-10442
                      customer_name: Acme Retail
                      fulfillment_id: null
                      carrier: null
                      carrier_void_supported: null
                      voidable_status: null
                      voidable_detail: null
                      quantity: 3
                    - allocation_id: 88240
                      allocation_type: hard
                      sales_order_id: 4530
                      order_number: SO-10450
                      customer_name: Beta Wholesale
                      fulfillment_id: 77120
                      carrier: ups
                      carrier_void_supported: true
                      voidable_status: voidable
                      voidable_detail: null
                      quantity: 2
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-vendor-credits-vendor-credit-write-off-impact
  /api/vendor-credits/{vendor_credit}/allocate:
    post:
      tags:
      - Vendor Credits
      summary: Allocate to Purchase Invoice
      description: 'Allocate part or all of the vendor credit''s remaining balance
        to a purchase invoice (bill).


        :::info[Required scope: `accounting:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        **Required fields:**

        - `purchase_invoice_id` (int) — Must exist.

        - `amount` (float, >= 0.01) — Amount to allocate. Cannot exceed the credit''s
        remaining balance or the bill''s outstanding balance.


        **Optional fields:**

        - `allocated_at` (date) — Defaults to now.

        - `notes` (string)


        The allocation is recorded on `vendor_credit_allocations` and reduces the
        bill''s outstanding amount. The response includes the new allocation with
        its purchase invoice and allocator user.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                purchase_invoice_id:
                  type: integer
                amount:
                  type: number
                allocated_at:
                  type: string
                notes:
                  type: string
              example:
                purchase_invoice_id: 17
                amount: 75.5
                allocated_at: '2026-04-11'
                notes: Applied against bill BILL-2026-0017
      parameters:
      - name: vendor_credit
        in: path
        schema:
          type: integer
        required: true
        description: Vendor credit ID
        example: '1'
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: accounting:write
      operationId: post-api-vendor-credits-vendor-credit-allocate
  /api/vendor-credits/allocate-batch:
    post:
      tags:
      - Vendor Credits
      summary: Batch Allocate to Purchase Invoice
      description: "Apply several vendor credits to a single purchase invoice (bill)\
        \ in one atomic batch. Powers the \"Credit this bill\" allocation flow, where\
        \ a buyer distributes multiple outstanding credits from the same supplier\
        \ against one bill at once. The whole batch is all-or-nothing: if any single\
        \ allocation fails validation or over-allocates, none of them are saved.\n\
        \n**Required fields:**\n- `purchase_invoice_id` (int) — The bill to credit.\
        \ Must exist.\n- `allocations` (array, min 1) — One entry per credit to apply.\n\
        \  - `allocations[].vendor_credit_id` (int) — Must exist and belong to the\
        \ same supplier and currency as the bill. Cannot be repeated within one request.\n\
        \  - `allocations[].amount` (float, >= 0.01) — Amount to allocate from that\
        \ credit. Cannot exceed the credit's remaining balance.\n\n**Optional fields:**\n\
        - `allocated_at` (date) — Applied to every allocation in the batch. Defaults\
        \ to now.\n- `notes` (string, max 1000) — Applied to every allocation in the\
        \ batch.\n\n**Validation:** the sum of all `amount` values cannot exceed the\
        \ bill's outstanding balance (gross total less cash paid, applied deposits,\
        \ and already-applied credits). A violation returns 422 with no allocations\
        \ saved."
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                purchase_invoice_id:
                  type: integer
                allocations:
                  type: array
                  items:
                    type: object
                    properties:
                      vendor_credit_id:
                        type: integer
                      amount:
                        type: integer
                allocated_at:
                  type: string
                notes:
                  type: string
              example:
                purchase_invoice_id: 17
                allocations:
                - vendor_credit_id: 1
                  amount: 600
                - vendor_credit_id: 2
                  amount: 150.5
                allocated_at: '2026-04-11'
                notes: Applied TecMATE credits against bill BILL-2026-0017
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        vendor_credit_id:
                          type: integer
                        purchase_invoice_id:
                          type: integer
                        amount:
                          type: integer
                        currency_rate:
                          type: integer
                        fx_gain_loss:
                          type: integer
                        allocated_at:
                          type: string
                        applied_at:
                          type: string
                        is_planned:
                          type: boolean
                        notes:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                        purchase_invoice:
                          type: object
                          properties:
                            id:
                              type: integer
                            supplier_invoice_number:
                              type: string
                            purchase_invoice_date:
                              type: string
                            purchase_order_id:
                              type: integer
                        allocated_by:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            email:
                              type: string
                example:
                  message: Applied 2 vendor credit(s) to the bill.
                  data:
                  - id: 41
                    vendor_credit_id: 1
                    purchase_invoice_id: 17
                    amount: 600
                    currency_rate: 1
                    fx_gain_loss: 0
                    allocated_at: '2026-04-11 00:00:00'
                    applied_at: '2026-04-11 14:22:07'
                    is_planned: false
                    notes: Applied TecMATE credits against bill BILL-2026-0017
                    created_at: '2026-04-11 14:22:07'
                    updated_at: '2026-04-11 14:22:07'
                    purchase_invoice:
                      id: 17
                      supplier_invoice_number: BILL-2026-0017
                      purchase_invoice_date: '2026-04-01'
                      purchase_order_id: 9
                    allocated_by:
                      id: 3
                      name: Jane Buyer
                      email: jane@acme.test
                  - id: 42
                    vendor_credit_id: 2
                    purchase_invoice_id: 17
                    amount: 150.5
                    currency_rate: 1
                    fx_gain_loss: 0
                    allocated_at: '2026-04-11 00:00:00'
                    applied_at: '2026-04-11 14:22:07'
                    is_planned: false
                    notes: Applied TecMATE credits against bill BILL-2026-0017
                    created_at: '2026-04-11 14:22:07'
                    updated_at: '2026-04-11 14:22:07'
                    purchase_invoice:
                      id: 17
                      supplier_invoice_number: BILL-2026-0017
                      purchase_invoice_date: '2026-04-01'
                      purchase_order_id: 9
                    allocated_by:
                      id: 3
                      name: Jane Buyer
                      email: jane@acme.test
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      allocations:
                        type: array
                        items:
                          type: string
                example:
                  message: Total amount to credit (900) exceeds the bill outstanding
                    balance (750.5).
                  errors:
                    allocations:
                    - Total amount to credit (900) exceeds the bill outstanding balance
                      (750.5).
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-vendor-credits-allocate-batch
  /api/vendor-credits/{vendor_credit}/allocations/{vendor_credit_allocation}:
    delete:
      tags:
      - Vendor Credits
      summary: Unallocate (Delete Allocation)
      description: 'Remove an allocation from a vendor credit. Returns 404-style error
        if the allocation does not belong to the specified vendor credit. Restores
        the vendor credit''s remaining balance and the purchase invoice''s outstanding
        amount.


        :::info[Required scope: `accounting:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: vendor_credit
        in: path
        schema:
          type: integer
        required: true
        description: Parent vendor credit ID
        example: '1'
      - name: vendor_credit_allocation
        in: path
        schema:
          type: integer
        required: true
        description: Allocation ID to remove
        example: '1'
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: accounting:write
      operationId: delete-api-vendor-credits-vendor-credit-allocations-vendor-credit-allocation
  /api/vendor-credits/{vendor_credit}/auto-apply:
    post:
      tags:
      - Vendor Credits
      summary: Auto-Apply Vendor Credit
      description: 'Automatically apply the credit''s remaining balance to the supplier''s
        oldest open purchase invoices (bills), oldest first, until the balance is
        exhausted or no eligible bills remain. No request body is required.


        :::info[Required scope: `accounting:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Returns the allocations that were created. Returns 422 when nothing can be
        applied (e.g. no remaining balance or no open bills for the supplier).'
      requestBody:
        content: {}
      parameters:
      - name: vendor_credit
        in: path
        schema:
          type: integer
        required: true
        description: Vendor credit ID
        example: '17'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        vendor_credit_id:
                          type: integer
                        purchase_invoice_id:
                          type: integer
                        amount:
                          type: integer
                        currency_rate:
                          type: integer
                        fx_gain_loss:
                          type: integer
                        allocated_at:
                          type: string
                        applied_at:
                          type: string
                        is_planned:
                          type: boolean
                        notes:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                        updated_at:
                          type: string
                        purchase_invoice:
                          type: object
                          properties:
                            id:
                              type: integer
                            supplier_invoice_number:
                              type: string
                            purchase_invoice_date:
                              type: string
                            purchase_order_id:
                              type: integer
                        allocated_by:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            email:
                              type: string
                example:
                  message: Applied credit to 1 invoice(s).
                  data:
                  - id: 61
                    vendor_credit_id: 17
                    purchase_invoice_id: 88
                    amount: 250
                    currency_rate: 1
                    fx_gain_loss: 0
                    allocated_at: '2026-07-07T09:00:00.000000Z'
                    applied_at: '2026-07-07T09:00:00.000000Z'
                    is_planned: false
                    notes: null
                    created_at: '2026-07-07T09:00:00.000000Z'
                    updated_at: '2026-07-07T09:00:00.000000Z'
                    purchase_invoice:
                      id: 88
                      supplier_invoice_number: INV-2026-0088
                      purchase_invoice_date: '2026-06-28'
                      purchase_order_id: 310
                    allocated_by:
                      id: 3
                      name: Jane Operator
                      email: jane@example.com
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: object
                    properties:
                      vendor_credit_id:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: object
                              properties:
                                id:
                                  type: integer
                example:
                  errors:
                    vendor_credit_id:
                    - message: No open invoices available to apply this credit to.
                      code: VendorCredit422
                      data:
                        id: 17
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: accounting:write
      operationId: post-api-vendor-credits-vendor-credit-auto-apply
  /api/vendor-credits/paid:
    post:
      tags:
      - Vendor Credits
      summary: Record Vendor Credit Refund Payment
      description: 'Record a refund payment against a vendor credit — money the supplier
        paid back instead of the credit being applied to bills.


        :::info[Required scope: `accounting:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Fields: vendor_credit_id, payment_type_id, and amount are required; payment_date,
        external_reference (max 255 characters), and currency_id are optional. The
        amount must be positive and cannot exceed the credit''s remaining balance;
        when currency_id is sent it must match the credit''s currency. Negative amounts
        are stored as their absolute value.


        Returns the updated vendor credit including its payments.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                vendor_credit_id:
                  type: integer
                payment_type_id:
                  type: integer
                amount:
                  type: integer
                payment_date:
                  type: string
                external_reference:
                  type: string
                currency_id:
                  type: integer
              example:
                vendor_credit_id: 17
                payment_type_id: 2
                amount: 100
                payment_date: '2026-07-07'
                external_reference: REF-20260707
                currency_id: 1
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      vendor_credit_number:
                        type: string
                      supplier_reference:
                        type: string
                      supplier_po_number:
                        type: string
                      credit_date:
                        type: string
                      vendor_credit_note:
                        type: string
                      metadata:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                      fully_allocated_at:
                        type: string
                        nullable: true
                      fully_refunded_at:
                        type: string
                        nullable: true
                      is_settled:
                        type: boolean
                      settlement_breakdown:
                        type: object
                        properties:
                          allocated:
                            type: integer
                          refunded:
                            type: integer
                          remaining:
                            type: integer
                          total:
                            type: integer
                      credit_status:
                        type: string
                      credit_status_label:
                        type: string
                      payment_status:
                        type: string
                      payment_status_label:
                        type: string
                      is_for_overpayment:
                        type: boolean
                      supplier_id:
                        type: integer
                      supplier:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          email:
                            type: string
                      purchase_order_id:
                        type: integer
                      purchase_order:
                        type: object
                        properties:
                          id:
                            type: integer
                          purchase_order_number:
                            type: string
                      warehouse_id:
                        type: integer
                      warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      store_id:
                        type: string
                        nullable: true
                      store:
                        type: string
                        nullable: true
                      currency_id:
                        type: integer
                      currency_code:
                        type: string
                      currency_rate:
                        type: integer
                      is_tax_included:
                        type: boolean
                      tax_rate_id:
                        type: string
                        nullable: true
                      tax_rate:
                        type: string
                        nullable: true
                      tax_lines:
                        type: string
                        nullable: true
                      tax_total:
                        type: integer
                      tax_credit:
                        type: integer
                      product_total:
                        type: integer
                      total_credit:
                        type: integer
                      total:
                        type: integer
                      allocated_amount:
                        type: integer
                      planned_allocation_amount:
                        type: integer
                      available_to_allocate:
                        type: integer
                      refunded_amount:
                        type: integer
                      remaining_amount:
                        type: integer
                      lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            vendor_credit_id:
                              type: integer
                            purchase_order_line_id:
                              type: integer
                            financial_line_id:
                              type: string
                              nullable: true
                            product_id:
                              type: integer
                            quantity:
                              type: integer
                            amount:
                              type: integer
                            unit_cost:
                              type: integer
                            description:
                              type: string
                            tax_allocation:
                              type: integer
                            tax_rate_id:
                              type: string
                              nullable: true
                            tax_rate:
                              type: string
                              nullable: true
                            nominal_code_id:
                              type: string
                              nullable: true
                            nominal_code:
                              type: string
                              nullable: true
                            is_product:
                              type: boolean
                            restock_inventory:
                              type: boolean
                            proration:
                              type: string
                              nullable: true
                            subtotal:
                              type: integer
                            created_at:
                              type: string
                            updated_at:
                              type: string
                            product:
                              type: object
                              properties:
                                id:
                                  type: integer
                                sku:
                                  type: string
                                name:
                                  type: string
                                barcode:
                                  type: string
                                image:
                                  type: string
                                  nullable: true
                                is_lot_tracked:
                                  type: boolean
                                lot_tracking_method:
                                  type: string
                                  nullable: true
                                shelf_life_days:
                                  type: string
                                  nullable: true
                                near_expiry_threshold_days:
                                  type: string
                                  nullable: true
                                min_remaining_shelf_life_days:
                                  type: string
                                  nullable: true
                            purchase_order_line:
                              type: object
                              properties:
                                id:
                                  type: integer
                                purchase_order_id:
                                  type: integer
                                product_id:
                                  type: integer
                                quantity:
                                  type: integer
                                unit_price:
                                  type: integer
                                purchase_order_number:
                                  type: string
                      line_item_count:
                        type: integer
                      total_quantity:
                        type: integer
                      first_line_sku:
                        type: string
                      has_products:
                        type: boolean
                      allocations:
                        type: array
                      payments:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            amount:
                              type: integer
                            cost:
                              type: string
                              nullable: true
                            payment_date:
                              type: string
                            payment_type:
                              type: object
                              properties:
                                id:
                                  type: integer
                                name:
                                  type: string
                            external_reference:
                              type: string
                            type:
                              type: string
                            currency_code:
                              type: string
                            sales_credit_allocation:
                              type: string
                              nullable: true
                      shipments_count:
                        type: integer
                      tags:
                        type: array
                        items:
                          type: string
                      inventory_movements:
                        type: array
                      link_reference:
                        type: string
                      link_type_label:
                        type: string
                      link_route:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 17
                    vendor_credit_number: VC-000017
                    supplier_reference: CM-88213
                    supplier_po_number: PO-000310
                    credit_date: '2026-06-20'
                    vendor_credit_note: Credit for damaged goods on PO-000310
                    metadata: null
                    created_at: '2026-06-20T10:15:00.000000Z'
                    updated_at: '2026-07-01T08:00:00.000000Z'
                    archived_at: null
                    fully_allocated_at: null
                    fully_refunded_at: null
                    is_settled: false
                    settlement_breakdown:
                      allocated: 0
                      refunded: 100
                      remaining: 150
                      total: 250
                    credit_status: open
                    credit_status_label: Open
                    payment_status: partially_applied
                    payment_status_label: Partially Applied
                    is_for_overpayment: false
                    supplier_id: 7
                    supplier:
                      id: 7
                      name: Acme Components Ltd
                      email: accounts@acme-components.com
                    purchase_order_id: 310
                    purchase_order:
                      id: 310
                      purchase_order_number: PO-000310
                    warehouse_id: 2
                    warehouse:
                      id: 2
                      name: Main Warehouse
                    store_id: null
                    store: null
                    currency_id: 1
                    currency_code: USD
                    currency_rate: 1
                    is_tax_included: false
                    tax_rate_id: null
                    tax_rate: null
                    tax_lines: null
                    tax_total: 0
                    tax_credit: 0
                    product_total: 250
                    total_credit: 250
                    total: 250
                    allocated_amount: 0
                    planned_allocation_amount: 0
                    available_to_allocate: 150
                    refunded_amount: 100
                    remaining_amount: 150
                    lines:
                    - id: 31
                      vendor_credit_id: 17
                      purchase_order_line_id: 771
                      financial_line_id: null
                      product_id: 55
                      quantity: 5
                      amount: 250
                      unit_cost: 50
                      description: Blue Widget (Medium)
                      tax_allocation: 0
                      tax_rate_id: null
                      tax_rate: null
                      nominal_code_id: null
                      nominal_code: null
                      is_product: true
                      restock_inventory: false
                      proration: null
                      subtotal: 250
                      created_at: '2026-06-20T10:15:00.000000Z'
                      updated_at: '2026-06-20T10:15:00.000000Z'
                      product:
                        id: 55
                        sku: WID-BLU-M
                        name: Blue Widget (Medium)
                        barcode: 0123456789012
                        image: null
                        is_lot_tracked: false
                        lot_tracking_method: null
                        shelf_life_days: null
                        near_expiry_threshold_days: null
                        min_remaining_shelf_life_days: null
                      purchase_order_line:
                        id: 771
                        purchase_order_id: 310
                        product_id: 55
                        quantity: 20
                        unit_price: 50
                        purchase_order_number: PO-000310
                    line_item_count: 1
                    total_quantity: 5
                    first_line_sku: WID-BLU-M
                    has_products: true
                    allocations: []
                    payments:
                    - id: 205
                      amount: 100
                      cost: null
                      payment_date: '2026-07-07'
                      payment_type:
                        id: 2
                        name: Wire Transfer
                      external_reference: REF-20260707
                      type: Payment
                      currency_code: USD
                      sales_credit_allocation: null
                    shipments_count: 0
                    tags:
                    - damaged-goods
                    inventory_movements: []
                    link_reference: VC-000017
                    link_type_label: Vendor Credit
                    link_route: /purchases/vendor-credits/17
                  message: Payment created successfully.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      amount:
                        type: array
                        items:
                          type: string
                example:
                  message: This vendor credit has been fully settled.
                  errors:
                    amount:
                    - This vendor credit has been fully settled.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: accounting:write
      operationId: post-api-vendor-credits-paid
  /api/vendor-credits/{vendor_credit}/payments/{payment}:
    put:
      tags:
      - Vendor Credits
      summary: Update Vendor Credit Refund Payment
      description: 'Update a refund payment previously recorded on a vendor credit.
        All fields are optional on update: payment_type_id, amount, payment_date,
        external_reference, currency_id. The updated amount cannot exceed the credit''s
        remaining balance (the current payment''s amount is excluded from that check),
        and currency_id must match the credit''s currency.


        :::info[Required scope: `accounting:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        The credit''s payment status is recalculated after the update. Returns an
        error when the payment does not belong to the vendor credit.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                amount:
                  type: integer
                payment_date:
                  type: string
                external_reference:
                  type: string
              example:
                amount: 150
                payment_date: '2026-07-08'
                external_reference: REF-20260708
      parameters:
      - name: vendor_credit
        in: path
        schema:
          type: integer
        required: true
        description: Vendor credit ID
        example: '17'
      - name: payment
        in: path
        schema:
          type: integer
        required: true
        description: Payment ID
        example: '205'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      vendor_credit_number:
                        type: string
                      supplier_reference:
                        type: string
                      supplier_po_number:
                        type: string
                      credit_date:
                        type: string
                      vendor_credit_note:
                        type: string
                      metadata:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                      fully_allocated_at:
                        type: string
                        nullable: true
                      fully_refunded_at:
                        type: string
                        nullable: true
                      is_settled:
                        type: boolean
                      settlement_breakdown:
                        type: object
                        properties:
                          allocated:
                            type: integer
                          refunded:
                            type: integer
                          remaining:
                            type: integer
                          total:
                            type: integer
                      credit_status:
                        type: string
                      credit_status_label:
                        type: string
                      payment_status:
                        type: string
                      payment_status_label:
                        type: string
                      is_for_overpayment:
                        type: boolean
                      supplier_id:
                        type: integer
                      supplier:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          email:
                            type: string
                      purchase_order_id:
                        type: integer
                      purchase_order:
                        type: object
                        properties:
                          id:
                            type: integer
                          purchase_order_number:
                            type: string
                      warehouse_id:
                        type: integer
                      warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      store_id:
                        type: string
                        nullable: true
                      store:
                        type: string
                        nullable: true
                      currency_id:
                        type: integer
                      currency_code:
                        type: string
                      currency_rate:
                        type: integer
                      is_tax_included:
                        type: boolean
                      tax_rate_id:
                        type: string
                        nullable: true
                      tax_rate:
                        type: string
                        nullable: true
                      tax_lines:
                        type: string
                        nullable: true
                      tax_total:
                        type: integer
                      tax_credit:
                        type: integer
                      product_total:
                        type: integer
                      total_credit:
                        type: integer
                      total:
                        type: integer
                      allocated_amount:
                        type: integer
                      planned_allocation_amount:
                        type: integer
                      available_to_allocate:
                        type: integer
                      refunded_amount:
                        type: integer
                      remaining_amount:
                        type: integer
                      lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            vendor_credit_id:
                              type: integer
                            purchase_order_line_id:
                              type: integer
                            financial_line_id:
                              type: string
                              nullable: true
                            product_id:
                              type: integer
                            quantity:
                              type: integer
                            amount:
                              type: integer
                            unit_cost:
                              type: integer
                            description:
                              type: string
                            tax_allocation:
                              type: integer
                            tax_rate_id:
                              type: string
                              nullable: true
                            tax_rate:
                              type: string
                              nullable: true
                            nominal_code_id:
                              type: string
                              nullable: true
                            nominal_code:
                              type: string
                              nullable: true
                            is_product:
                              type: boolean
                            restock_inventory:
                              type: boolean
                            proration:
                              type: string
                              nullable: true
                            subtotal:
                              type: integer
                            created_at:
                              type: string
                            updated_at:
                              type: string
                            product:
                              type: object
                              properties:
                                id:
                                  type: integer
                                sku:
                                  type: string
                                name:
                                  type: string
                                barcode:
                                  type: string
                                image:
                                  type: string
                                  nullable: true
                                is_lot_tracked:
                                  type: boolean
                                lot_tracking_method:
                                  type: string
                                  nullable: true
                                shelf_life_days:
                                  type: string
                                  nullable: true
                                near_expiry_threshold_days:
                                  type: string
                                  nullable: true
                                min_remaining_shelf_life_days:
                                  type: string
                                  nullable: true
                            purchase_order_line:
                              type: object
                              properties:
                                id:
                                  type: integer
                                purchase_order_id:
                                  type: integer
                                product_id:
                                  type: integer
                                quantity:
                                  type: integer
                                unit_price:
                                  type: integer
                                purchase_order_number:
                                  type: string
                      line_item_count:
                        type: integer
                      total_quantity:
                        type: integer
                      first_line_sku:
                        type: string
                      has_products:
                        type: boolean
                      allocations:
                        type: array
                      payments:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            amount:
                              type: integer
                            cost:
                              type: string
                              nullable: true
                            payment_date:
                              type: string
                            payment_type:
                              type: object
                              properties:
                                id:
                                  type: integer
                                name:
                                  type: string
                            external_reference:
                              type: string
                            type:
                              type: string
                            currency_code:
                              type: string
                            sales_credit_allocation:
                              type: string
                              nullable: true
                      shipments_count:
                        type: integer
                      tags:
                        type: array
                        items:
                          type: string
                      inventory_movements:
                        type: array
                      link_reference:
                        type: string
                      link_type_label:
                        type: string
                      link_route:
                        type: string
                example:
                  message: Payment updated successfully.
                  data:
                    id: 17
                    vendor_credit_number: VC-000017
                    supplier_reference: CM-88213
                    supplier_po_number: PO-000310
                    credit_date: '2026-06-20'
                    vendor_credit_note: Credit for damaged goods on PO-000310
                    metadata: null
                    created_at: '2026-06-20T10:15:00.000000Z'
                    updated_at: '2026-07-01T08:00:00.000000Z'
                    archived_at: null
                    fully_allocated_at: null
                    fully_refunded_at: null
                    is_settled: false
                    settlement_breakdown:
                      allocated: 0
                      refunded: 150
                      remaining: 100
                      total: 250
                    credit_status: open
                    credit_status_label: Open
                    payment_status: partially_applied
                    payment_status_label: Partially Applied
                    is_for_overpayment: false
                    supplier_id: 7
                    supplier:
                      id: 7
                      name: Acme Components Ltd
                      email: accounts@acme-components.com
                    purchase_order_id: 310
                    purchase_order:
                      id: 310
                      purchase_order_number: PO-000310
                    warehouse_id: 2
                    warehouse:
                      id: 2
                      name: Main Warehouse
                    store_id: null
                    store: null
                    currency_id: 1
                    currency_code: USD
                    currency_rate: 1
                    is_tax_included: false
                    tax_rate_id: null
                    tax_rate: null
                    tax_lines: null
                    tax_total: 0
                    tax_credit: 0
                    product_total: 250
                    total_credit: 250
                    total: 250
                    allocated_amount: 0
                    planned_allocation_amount: 0
                    available_to_allocate: 100
                    refunded_amount: 150
                    remaining_amount: 100
                    lines:
                    - id: 31
                      vendor_credit_id: 17
                      purchase_order_line_id: 771
                      financial_line_id: null
                      product_id: 55
                      quantity: 5
                      amount: 250
                      unit_cost: 50
                      description: Blue Widget (Medium)
                      tax_allocation: 0
                      tax_rate_id: null
                      tax_rate: null
                      nominal_code_id: null
                      nominal_code: null
                      is_product: true
                      restock_inventory: false
                      proration: null
                      subtotal: 250
                      created_at: '2026-06-20T10:15:00.000000Z'
                      updated_at: '2026-06-20T10:15:00.000000Z'
                      product:
                        id: 55
                        sku: WID-BLU-M
                        name: Blue Widget (Medium)
                        barcode: 0123456789012
                        image: null
                        is_lot_tracked: false
                        lot_tracking_method: null
                        shelf_life_days: null
                        near_expiry_threshold_days: null
                        min_remaining_shelf_life_days: null
                      purchase_order_line:
                        id: 771
                        purchase_order_id: 310
                        product_id: 55
                        quantity: 20
                        unit_price: 50
                        purchase_order_number: PO-000310
                    line_item_count: 1
                    total_quantity: 5
                    first_line_sku: WID-BLU-M
                    has_products: true
                    allocations: []
                    payments:
                    - id: 205
                      amount: 150
                      cost: null
                      payment_date: '2026-07-08'
                      payment_type:
                        id: 2
                        name: Wire Transfer
                      external_reference: REF-20260708
                      type: Payment
                      currency_code: USD
                      sales_credit_allocation: null
                    shipments_count: 0
                    tags:
                    - damaged-goods
                    inventory_movements: []
                    link_reference: VC-000017
                    link_type_label: Vendor Credit
                    link_route: /purchases/vendor-credits/17
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      amount:
                        type: array
                        items:
                          type: string
                example:
                  message: The amount may not be greater than 250.
                  errors:
                    amount:
                    - The amount may not be greater than 250.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: accounting:write
      operationId: put-api-vendor-credits-vendor-credit-payments-payment
    delete:
      tags:
      - Vendor Credits
      summary: Delete Vendor Credit Refund Payment
      description: 'Delete a refund payment from a vendor credit. The deleted amount
        becomes available on the credit again and the credit''s payment status is
        recalculated.


        :::info[Required scope: `accounting:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Returns the updated vendor credit. Returns an error when the payment does
        not belong to the vendor credit.'
      parameters:
      - name: vendor_credit
        in: path
        schema:
          type: integer
        required: true
        description: Vendor credit ID
        example: '17'
      - name: payment
        in: path
        schema:
          type: integer
        required: true
        description: Payment ID
        example: '205'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      vendor_credit_number:
                        type: string
                      supplier_reference:
                        type: string
                      supplier_po_number:
                        type: string
                      credit_date:
                        type: string
                      vendor_credit_note:
                        type: string
                      metadata:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      archived_at:
                        type: string
                        nullable: true
                      fully_allocated_at:
                        type: string
                        nullable: true
                      fully_refunded_at:
                        type: string
                        nullable: true
                      is_settled:
                        type: boolean
                      settlement_breakdown:
                        type: object
                        properties:
                          allocated:
                            type: integer
                          refunded:
                            type: integer
                          remaining:
                            type: integer
                          total:
                            type: integer
                      credit_status:
                        type: string
                      credit_status_label:
                        type: string
                      payment_status:
                        type: string
                      payment_status_label:
                        type: string
                      is_for_overpayment:
                        type: boolean
                      supplier_id:
                        type: integer
                      supplier:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          email:
                            type: string
                      purchase_order_id:
                        type: integer
                      purchase_order:
                        type: object
                        properties:
                          id:
                            type: integer
                          purchase_order_number:
                            type: string
                      warehouse_id:
                        type: integer
                      warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      store_id:
                        type: string
                        nullable: true
                      store:
                        type: string
                        nullable: true
                      currency_id:
                        type: integer
                      currency_code:
                        type: string
                      currency_rate:
                        type: integer
                      is_tax_included:
                        type: boolean
                      tax_rate_id:
                        type: string
                        nullable: true
                      tax_rate:
                        type: string
                        nullable: true
                      tax_lines:
                        type: string
                        nullable: true
                      tax_total:
                        type: integer
                      tax_credit:
                        type: integer
                      product_total:
                        type: integer
                      total_credit:
                        type: integer
                      total:
                        type: integer
                      allocated_amount:
                        type: integer
                      planned_allocation_amount:
                        type: integer
                      available_to_allocate:
                        type: integer
                      refunded_amount:
                        type: integer
                      remaining_amount:
                        type: integer
                      lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            vendor_credit_id:
                              type: integer
                            purchase_order_line_id:
                              type: integer
                            financial_line_id:
                              type: string
                              nullable: true
                            product_id:
                              type: integer
                            quantity:
                              type: integer
                            amount:
                              type: integer
                            unit_cost:
                              type: integer
                            description:
                              type: string
                            tax_allocation:
                              type: integer
                            tax_rate_id:
                              type: string
                              nullable: true
                            tax_rate:
                              type: string
                              nullable: true
                            nominal_code_id:
                              type: string
                              nullable: true
                            nominal_code:
                              type: string
                              nullable: true
                            is_product:
                              type: boolean
                            restock_inventory:
                              type: boolean
                            proration:
                              type: string
                              nullable: true
                            subtotal:
                              type: integer
                            created_at:
                              type: string
                            updated_at:
                              type: string
                            product:
                              type: object
                              properties:
                                id:
                                  type: integer
                                sku:
                                  type: string
                                name:
                                  type: string
                                barcode:
                                  type: string
                                image:
                                  type: string
                                  nullable: true
                                is_lot_tracked:
                                  type: boolean
                                lot_tracking_method:
                                  type: string
                                  nullable: true
                                shelf_life_days:
                                  type: string
                                  nullable: true
                                near_expiry_threshold_days:
                                  type: string
                                  nullable: true
                                min_remaining_shelf_life_days:
                                  type: string
                                  nullable: true
                            purchase_order_line:
                              type: object
                              properties:
                                id:
                                  type: integer
                                purchase_order_id:
                                  type: integer
                                product_id:
                                  type: integer
                                quantity:
                                  type: integer
                                unit_price:
                                  type: integer
                                purchase_order_number:
                                  type: string
                      line_item_count:
                        type: integer
                      total_quantity:
                        type: integer
                      first_line_sku:
                        type: string
                      has_products:
                        type: boolean
                      allocations:
                        type: array
                      payments:
                        type: array
                      shipments_count:
                        type: integer
                      tags:
                        type: array
                        items:
                          type: string
                      inventory_movements:
                        type: array
                      link_reference:
                        type: string
                      link_type_label:
                        type: string
                      link_route:
                        type: string
                example:
                  message: Payment 205 deleted successfully.
                  data:
                    id: 17
                    vendor_credit_number: VC-000017
                    supplier_reference: CM-88213
                    supplier_po_number: PO-000310
                    credit_date: '2026-06-20'
                    vendor_credit_note: Credit for damaged goods on PO-000310
                    metadata: null
                    created_at: '2026-06-20T10:15:00.000000Z'
                    updated_at: '2026-07-01T08:00:00.000000Z'
                    archived_at: null
                    fully_allocated_at: null
                    fully_refunded_at: null
                    is_settled: false
                    settlement_breakdown:
                      allocated: 0
                      refunded: 0
                      remaining: 250
                      total: 250
                    credit_status: open
                    credit_status_label: Open
                    payment_status: unapplied
                    payment_status_label: Unapplied
                    is_for_overpayment: false
                    supplier_id: 7
                    supplier:
                      id: 7
                      name: Acme Components Ltd
                      email: accounts@acme-components.com
                    purchase_order_id: 310
                    purchase_order:
                      id: 310
                      purchase_order_number: PO-000310
                    warehouse_id: 2
                    warehouse:
                      id: 2
                      name: Main Warehouse
                    store_id: null
                    store: null
                    currency_id: 1
                    currency_code: USD
                    currency_rate: 1
                    is_tax_included: false
                    tax_rate_id: null
                    tax_rate: null
                    tax_lines: null
                    tax_total: 0
                    tax_credit: 0
                    product_total: 250
                    total_credit: 250
                    total: 250
                    allocated_amount: 0
                    planned_allocation_amount: 0
                    available_to_allocate: 250
                    refunded_amount: 0
                    remaining_amount: 250
                    lines:
                    - id: 31
                      vendor_credit_id: 17
                      purchase_order_line_id: 771
                      financial_line_id: null
                      product_id: 55
                      quantity: 5
                      amount: 250
                      unit_cost: 50
                      description: Blue Widget (Medium)
                      tax_allocation: 0
                      tax_rate_id: null
                      tax_rate: null
                      nominal_code_id: null
                      nominal_code: null
                      is_product: true
                      restock_inventory: false
                      proration: null
                      subtotal: 250
                      created_at: '2026-06-20T10:15:00.000000Z'
                      updated_at: '2026-06-20T10:15:00.000000Z'
                      product:
                        id: 55
                        sku: WID-BLU-M
                        name: Blue Widget (Medium)
                        barcode: 0123456789012
                        image: null
                        is_lot_tracked: false
                        lot_tracking_method: null
                        shelf_life_days: null
                        near_expiry_threshold_days: null
                        min_remaining_shelf_life_days: null
                      purchase_order_line:
                        id: 771
                        purchase_order_id: 310
                        product_id: 55
                        quantity: 20
                        unit_price: 50
                        purchase_order_number: PO-000310
                    line_item_count: 1
                    total_quantity: 5
                    first_line_sku: WID-BLU-M
                    has_products: true
                    allocations: []
                    payments: []
                    shipments_count: 0
                    tags:
                    - damaged-goods
                    inventory_movements: []
                    link_reference: VC-000017
                    link_type_label: Vendor Credit
                    link_route: /purchases/vendor-credits/17
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: accounting:write
      operationId: delete-api-vendor-credits-vendor-credit-payments-payment
  /api/vendor-credits/{vendor_credit}/shipments:
    get:
      tags:
      - Vendor Credits
      summary: List Return Shipments
      description: 'List all return shipments for a vendor credit, with lines, product,
        warehouse location, shipping method and creator eager-loaded.


        Authentication: Requires Bearer token (PAT).


        :::info[Required scope: `accounting:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: vendor_credit
        in: path
        schema:
          type: integer
        required: true
        description: Vendor credit ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        vendor_credit_id:
                          type: integer
                        warehouse_id:
                          type: integer
                        shipment_date:
                          type: string
                        status:
                          type: string
                        status_label:
                          type: string
                        tracking_number:
                          type: string
                        shipping_method_id:
                          type: integer
                        custom_carrier:
                          type: string
                          nullable: true
                        expected_arrival_date:
                          type: string
                        vendor_rma_number:
                          type: string
                        notes:
                          type: string
                        created_by_user_id:
                          type: integer
                        created_at:
                          type: string
                        updated_at:
                          type: string
                        warehouse:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        shipping_method:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        created_by_user:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        lines:
                          type: array
                          items:
                            type: object
                            properties:
                              id:
                                type: integer
                              vendor_credit_shipment_id:
                                type: integer
                              vendor_credit_line_id:
                                type: integer
                              warehouse_location_id:
                                type: integer
                              quantity:
                                type: integer
                              notes:
                                type: string
                                nullable: true
                              created_at:
                                type: string
                              updated_at:
                                type: string
                              warehouse_location:
                                type: object
                                properties:
                                  id:
                                    type: integer
                                  name:
                                    type: string
                              vendor_credit_line:
                                type: object
                                properties:
                                  id:
                                    type: integer
                                  description:
                                    type: string
                                  quantity:
                                    type: integer
                                  unit_cost:
                                    type: number
                              product:
                                type: object
                                properties:
                                  id:
                                    type: integer
                                  sku:
                                    type: string
                                  name:
                                    type: string
                        total_quantity:
                          type: integer
                        link_reference:
                          type: string
                        link_type_label:
                          type: string
                        link_route:
                          type: string
                example:
                  data:
                  - id: 12
                    vendor_credit_id: 1
                    warehouse_id: 3
                    shipment_date: '2026-06-20'
                    status: shipped
                    status_label: Shipped
                    tracking_number: 1Z999AA10123456784
                    shipping_method_id: 2
                    custom_carrier: null
                    expected_arrival_date: '2026-06-27'
                    vendor_rma_number: RMA-44821
                    notes: Returning defective units to supplier.
                    created_by_user_id: 5
                    created_at: '2026-06-20T14:03:11.000000Z'
                    updated_at: '2026-06-20T14:03:11.000000Z'
                    warehouse:
                      id: 3
                      name: Main Warehouse
                    shipping_method:
                      id: 2
                      name: UPS Ground
                    created_by_user:
                      id: 5
                      name: Jane Doe
                    lines:
                    - id: 30
                      vendor_credit_shipment_id: 12
                      vendor_credit_line_id: 88
                      warehouse_location_id: 14
                      quantity: 10
                      notes: null
                      created_at: '2026-06-20T14:03:11.000000Z'
                      updated_at: '2026-06-20T14:03:11.000000Z'
                      warehouse_location:
                        id: 14
                        name: A-01-01
                      vendor_credit_line:
                        id: 88
                        description: Widget Blue
                        quantity: 10
                        unit_cost: 4.25
                      product:
                        id: 501
                        sku: WIDGET-BLUE
                        name: Widget Blue
                    total_quantity: 10
                    link_reference: VCS-12
                    link_type_label: Vendor Credit Shipment
                    link_route: /purchases/vendor-credits/1/shipments/12
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: accounting:read
      operationId: get-api-vendor-credits-vendor-credit-shipments
    post:
      tags:
      - Vendor Credits
      summary: Create Return Shipment
      description: "Create a return (RTV) shipment against an authorized vendor credit.\
        \ For each restock product line, posts the outbound inventory movement (negative\
        \ adjustment) and transitions the matching planned allocation to fulfilled.\n\
        \nAuthentication: Requires Bearer token (PAT).\n\nBody fields:\n- `warehouse_id`\
        \ (required, integer) — warehouse the goods ship out of.\n- `shipment_date`\
        \ (required, date).\n- `status` (optional, one of: pending, shipped, delivered,\
        \ cancelled — defaults to shipped).\n- `tracking_number` (optional, string,\
        \ max 191).\n- `shipping_method_id` (optional, integer — exists in shipping_methods).\n\
        - `custom_carrier` (optional, string, max 191).\n- `expected_arrival_date`\
        \ (optional, date).\n- `vendor_rma_number` (optional, string, max 191).\n\
        - `notes` (optional, string).\n- `lines` (required, array, min 1) — each line:\n\
        \    - `vendor_credit_line_id` (required, integer — exists in vendor_credit_lines).\n\
        \    - `quantity` (required, integer, min 1).\n    - `warehouse_location_id`\
        \ (optional, integer — exists in warehouse_locations).\n    - `notes` (optional,\
        \ string).\n    - `lot_allocation` (optional, array) — FEFO override for lot-tracked\
        \ products. When supplied, the named FIFO layers are consumed instead of automatic\
        \ FEFO. Each entry: `{ fifo_layer_id (required, exists in fifo_layers), quantity\
        \ (required, > 0) }`. The allocation must sum to the line quantity, every\
        \ layer must be an active layer of the line's product + the shipment warehouse\
        \ with enough available quantity, and the tenant's lot override policy is\
        \ enforced (under `enforce`, consuming expired stock or skipping the earliest-expiry\
        \ FEFO lot is rejected with 422). Omit to consume by automatic FEFO/FIFO.\n\
        \n:::info[Required scope: `accounting:write`]\nGrant this scope to your token\
        \ under [Settings → Developer → Personal Access Tokens](https://app.sku.io/settings/api).\n\
        :::"
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                warehouse_id:
                  type: integer
                shipment_date:
                  type: string
                status:
                  type: string
                tracking_number:
                  type: string
                shipping_method_id:
                  type: integer
                custom_carrier:
                  type: string
                  nullable: true
                expected_arrival_date:
                  type: string
                vendor_rma_number:
                  type: string
                notes:
                  type: string
                lines:
                  type: array
                  items:
                    type: object
                    properties:
                      vendor_credit_line_id:
                        type: integer
                      quantity:
                        type: integer
                      warehouse_location_id:
                        type: integer
                      notes:
                        type: string
                        nullable: true
                      lot_allocation:
                        type: array
                        items:
                          type: object
                          properties:
                            fifo_layer_id:
                              type: integer
                            quantity:
                              type: integer
              example:
                warehouse_id: 3
                shipment_date: '2026-06-20'
                status: shipped
                tracking_number: 1Z999AA10123456784
                shipping_method_id: 2
                custom_carrier: null
                expected_arrival_date: '2026-06-27'
                vendor_rma_number: RMA-44821
                notes: Returning defective units to supplier.
                lines:
                - vendor_credit_line_id: 88
                  quantity: 10
                  warehouse_location_id: 14
                  notes: null
                  lot_allocation:
                  - fifo_layer_id: 9001
                    quantity: 6
                  - fifo_layer_id: 9002
                    quantity: 4
      parameters:
      - name: vendor_credit
        in: path
        schema:
          type: integer
        required: true
        description: Vendor credit ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      vendor_credit_id:
                        type: integer
                      warehouse_id:
                        type: integer
                      shipment_date:
                        type: string
                      status:
                        type: string
                      status_label:
                        type: string
                      tracking_number:
                        type: string
                      shipping_method_id:
                        type: integer
                      custom_carrier:
                        type: string
                        nullable: true
                      expected_arrival_date:
                        type: string
                      vendor_rma_number:
                        type: string
                      notes:
                        type: string
                      created_by_user_id:
                        type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      shipping_method:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      created_by_user:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            vendor_credit_shipment_id:
                              type: integer
                            vendor_credit_line_id:
                              type: integer
                            warehouse_location_id:
                              type: integer
                            quantity:
                              type: integer
                            notes:
                              type: string
                              nullable: true
                            created_at:
                              type: string
                            updated_at:
                              type: string
                            warehouse_location:
                              type: object
                              properties:
                                id:
                                  type: integer
                                name:
                                  type: string
                            vendor_credit_line:
                              type: object
                              properties:
                                id:
                                  type: integer
                                description:
                                  type: string
                                quantity:
                                  type: integer
                                unit_cost:
                                  type: number
                            product:
                              type: object
                              properties:
                                id:
                                  type: integer
                                sku:
                                  type: string
                                name:
                                  type: string
                      total_quantity:
                        type: integer
                      link_reference:
                        type: string
                      link_type_label:
                        type: string
                      link_route:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 12
                    vendor_credit_id: 1
                    warehouse_id: 3
                    shipment_date: '2026-06-20'
                    status: shipped
                    status_label: Shipped
                    tracking_number: 1Z999AA10123456784
                    shipping_method_id: 2
                    custom_carrier: null
                    expected_arrival_date: '2026-06-27'
                    vendor_rma_number: RMA-44821
                    notes: Returning defective units to supplier.
                    created_by_user_id: 5
                    created_at: '2026-06-20T14:03:11.000000Z'
                    updated_at: '2026-06-20T14:03:11.000000Z'
                    warehouse:
                      id: 3
                      name: Main Warehouse
                    shipping_method:
                      id: 2
                      name: UPS Ground
                    created_by_user:
                      id: 5
                      name: Jane Doe
                    lines:
                    - id: 30
                      vendor_credit_shipment_id: 12
                      vendor_credit_line_id: 88
                      warehouse_location_id: 14
                      quantity: 10
                      notes: null
                      created_at: '2026-06-20T14:03:11.000000Z'
                      updated_at: '2026-06-20T14:03:11.000000Z'
                      warehouse_location:
                        id: 14
                        name: A-01-01
                      vendor_credit_line:
                        id: 88
                        description: Widget Blue
                        quantity: 10
                        unit_cost: 4.25
                      product:
                        id: 501
                        sku: WIDGET-BLUE
                        name: Widget Blue
                    total_quantity: 10
                    link_reference: VCS-12
                    link_type_label: Vendor Credit Shipment
                    link_route: /purchases/vendor-credits/1/shipments/12
                  message: Vendor credit shipment created successfully.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: object
                    properties:
                      lines.0.lot_allocation:
                        type: array
                        items:
                          type: string
                      lines.0.lot_allocation.0.fifo_layer_id:
                        type: array
                        items:
                          type: string
                  message:
                    type: string
                example:
                  errors:
                    lines.0.lot_allocation:
                    - The lot allocation must sum to the quantity (10).
                    lines.0.lot_allocation.0.fifo_layer_id:
                    - The selected lot is not an active layer for this product and
                      warehouse.
                  message: The given data was invalid.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: accounting:write
      operationId: post-api-vendor-credits-vendor-credit-shipments
  /api/vendor-credits/{vendor_credit}/shipments/{vendor_credit_shipment}:
    put:
      tags:
      - Vendor Credits
      summary: Update Return Shipment
      description: "Update an existing return (RTV) shipment. Reverses the prior movements/allocations,\
        \ then re-posts them from the new lines. For each restock product line, posts\
        \ the outbound inventory movement (negative adjustment) and transitions the\
        \ matching planned allocation to fulfilled.\n\nAuthentication: Requires Bearer\
        \ token (PAT).\n\nBody fields:\n- `warehouse_id` (required, integer) — warehouse\
        \ the goods ship out of.\n- `shipment_date` (required, date).\n- `status`\
        \ (optional, one of: pending, shipped, delivered, cancelled — defaults to\
        \ shipped).\n- `tracking_number` (optional, string, max 191).\n- `shipping_method_id`\
        \ (optional, integer — exists in shipping_methods).\n- `custom_carrier` (optional,\
        \ string, max 191).\n- `expected_arrival_date` (optional, date).\n- `vendor_rma_number`\
        \ (optional, string, max 191).\n- `notes` (optional, string).\n- `lines` (required,\
        \ array, min 1) — each line:\n    - `vendor_credit_line_id` (required, integer\
        \ — exists in vendor_credit_lines).\n    - `quantity` (required, integer,\
        \ min 1).\n    - `warehouse_location_id` (optional, integer — exists in warehouse_locations).\n\
        \    - `notes` (optional, string).\n    - `lot_allocation` (optional, array)\
        \ — FEFO override for lot-tracked products. When supplied, the named FIFO\
        \ layers are consumed instead of automatic FEFO. Each entry: `{ fifo_layer_id\
        \ (required, exists in fifo_layers), quantity (required, > 0) }`. The allocation\
        \ must sum to the line quantity, every layer must be an active layer of the\
        \ line's product + the shipment warehouse with enough available quantity,\
        \ and the tenant's lot override policy is enforced (under `enforce`, consuming\
        \ expired stock or skipping the earliest-expiry FEFO lot is rejected with\
        \ 422). Omit to consume by automatic FEFO/FIFO.\n\n:::info[Required scope:\
        \ `accounting:write`]\nGrant this scope to your token under [Settings → Developer\
        \ → Personal Access Tokens](https://app.sku.io/settings/api).\n:::"
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                warehouse_id:
                  type: integer
                shipment_date:
                  type: string
                status:
                  type: string
                tracking_number:
                  type: string
                shipping_method_id:
                  type: integer
                custom_carrier:
                  type: string
                  nullable: true
                expected_arrival_date:
                  type: string
                vendor_rma_number:
                  type: string
                notes:
                  type: string
                lines:
                  type: array
                  items:
                    type: object
                    properties:
                      vendor_credit_line_id:
                        type: integer
                      quantity:
                        type: integer
                      warehouse_location_id:
                        type: integer
                      notes:
                        type: string
                        nullable: true
                      lot_allocation:
                        type: array
                        items:
                          type: object
                          properties:
                            fifo_layer_id:
                              type: integer
                            quantity:
                              type: integer
              example:
                warehouse_id: 3
                shipment_date: '2026-06-20'
                status: shipped
                tracking_number: 1Z999AA10123456784
                shipping_method_id: 2
                custom_carrier: null
                expected_arrival_date: '2026-06-27'
                vendor_rma_number: RMA-44821
                notes: Returning defective units to supplier.
                lines:
                - vendor_credit_line_id: 88
                  quantity: 10
                  warehouse_location_id: 14
                  notes: null
                  lot_allocation:
                  - fifo_layer_id: 9001
                    quantity: 6
                  - fifo_layer_id: 9002
                    quantity: 4
      parameters:
      - name: vendor_credit
        in: path
        schema:
          type: integer
        required: true
        description: Vendor credit ID
        example: '1'
      - name: vendor_credit_shipment
        in: path
        schema:
          type: integer
        required: true
        description: Vendor credit shipment ID
        example: '12'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      vendor_credit_id:
                        type: integer
                      warehouse_id:
                        type: integer
                      shipment_date:
                        type: string
                      status:
                        type: string
                      status_label:
                        type: string
                      tracking_number:
                        type: string
                      shipping_method_id:
                        type: integer
                      custom_carrier:
                        type: string
                        nullable: true
                      expected_arrival_date:
                        type: string
                      vendor_rma_number:
                        type: string
                      notes:
                        type: string
                      created_by_user_id:
                        type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      shipping_method:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      created_by_user:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            vendor_credit_shipment_id:
                              type: integer
                            vendor_credit_line_id:
                              type: integer
                            warehouse_location_id:
                              type: integer
                            quantity:
                              type: integer
                            notes:
                              type: string
                              nullable: true
                            created_at:
                              type: string
                            updated_at:
                              type: string
                            warehouse_location:
                              type: object
                              properties:
                                id:
                                  type: integer
                                name:
                                  type: string
                            vendor_credit_line:
                              type: object
                              properties:
                                id:
                                  type: integer
                                description:
                                  type: string
                                quantity:
                                  type: integer
                                unit_cost:
                                  type: number
                            product:
                              type: object
                              properties:
                                id:
                                  type: integer
                                sku:
                                  type: string
                                name:
                                  type: string
                      total_quantity:
                        type: integer
                      link_reference:
                        type: string
                      link_type_label:
                        type: string
                      link_route:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 12
                    vendor_credit_id: 1
                    warehouse_id: 3
                    shipment_date: '2026-06-20'
                    status: shipped
                    status_label: Shipped
                    tracking_number: 1Z999AA10123456784
                    shipping_method_id: 2
                    custom_carrier: null
                    expected_arrival_date: '2026-06-27'
                    vendor_rma_number: RMA-44821
                    notes: Returning defective units to supplier.
                    created_by_user_id: 5
                    created_at: '2026-06-20T14:03:11.000000Z'
                    updated_at: '2026-06-20T14:03:11.000000Z'
                    warehouse:
                      id: 3
                      name: Main Warehouse
                    shipping_method:
                      id: 2
                      name: UPS Ground
                    created_by_user:
                      id: 5
                      name: Jane Doe
                    lines:
                    - id: 30
                      vendor_credit_shipment_id: 12
                      vendor_credit_line_id: 88
                      warehouse_location_id: 14
                      quantity: 10
                      notes: null
                      created_at: '2026-06-20T14:03:11.000000Z'
                      updated_at: '2026-06-20T14:03:11.000000Z'
                      warehouse_location:
                        id: 14
                        name: A-01-01
                      vendor_credit_line:
                        id: 88
                        description: Widget Blue
                        quantity: 10
                        unit_cost: 4.25
                      product:
                        id: 501
                        sku: WIDGET-BLUE
                        name: Widget Blue
                    total_quantity: 10
                    link_reference: VCS-12
                    link_type_label: Vendor Credit Shipment
                    link_route: /purchases/vendor-credits/1/shipments/12
                  message: Vendor credit shipment created successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: accounting:write
      operationId: put-api-vendor-credits-vendor-credit-shipments-vendor-credit-shipment
    delete:
      tags:
      - Vendor Credits
      summary: Delete Return Shipment
      description: 'Delete a return shipment. Reverses the posted inventory movements
        (returning stock to its FIFO layers) and reverts the matching fulfilled allocations
        back to allocated.


        Authentication: Requires Bearer token (PAT).


        :::info[Required scope: `accounting:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: vendor_credit
        in: path
        schema:
          type: integer
        required: true
        description: Vendor credit ID
        example: '1'
      - name: vendor_credit_shipment
        in: path
        schema:
          type: integer
        required: true
        description: Vendor credit shipment ID
        example: '12'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Vendor credit shipment VCS-12 deleted successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: accounting:write
      operationId: delete-api-vendor-credits-vendor-credit-shipments-vendor-credit-shipment
  /api/vendor-credits/{vendor_credit}/shipments/{vendor_credit_shipment}/status:
    patch:
      tags:
      - Vendor Credits
      summary: Update Return Shipment Status
      description: 'Update only the status of a return shipment. Lightweight — no
        inventory/allocation side effects.


        Body: `status` (required, one of: pending, shipped, delivered, cancelled).


        Authentication: Requires Bearer token (PAT).


        :::info[Required scope: `accounting:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                status:
                  type: string
              example:
                status: delivered
      parameters:
      - name: vendor_credit
        in: path
        schema:
          type: integer
        required: true
        description: Vendor credit ID
        example: '1'
      - name: vendor_credit_shipment
        in: path
        schema:
          type: integer
        required: true
        description: Vendor credit shipment ID
        example: '12'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      vendor_credit_id:
                        type: integer
                      warehouse_id:
                        type: integer
                      shipment_date:
                        type: string
                      status:
                        type: string
                      status_label:
                        type: string
                      tracking_number:
                        type: string
                      shipping_method_id:
                        type: integer
                      custom_carrier:
                        type: string
                        nullable: true
                      expected_arrival_date:
                        type: string
                      vendor_rma_number:
                        type: string
                      notes:
                        type: string
                      created_by_user_id:
                        type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      shipping_method:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      created_by_user:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            vendor_credit_shipment_id:
                              type: integer
                            vendor_credit_line_id:
                              type: integer
                            warehouse_location_id:
                              type: integer
                            quantity:
                              type: integer
                            notes:
                              type: string
                              nullable: true
                            created_at:
                              type: string
                            updated_at:
                              type: string
                            warehouse_location:
                              type: object
                              properties:
                                id:
                                  type: integer
                                name:
                                  type: string
                            vendor_credit_line:
                              type: object
                              properties:
                                id:
                                  type: integer
                                description:
                                  type: string
                                quantity:
                                  type: integer
                                unit_cost:
                                  type: number
                            product:
                              type: object
                              properties:
                                id:
                                  type: integer
                                sku:
                                  type: string
                                name:
                                  type: string
                      total_quantity:
                        type: integer
                      link_reference:
                        type: string
                      link_type_label:
                        type: string
                      link_route:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 12
                    vendor_credit_id: 1
                    warehouse_id: 3
                    shipment_date: '2026-06-20'
                    status: shipped
                    status_label: Shipped
                    tracking_number: 1Z999AA10123456784
                    shipping_method_id: 2
                    custom_carrier: null
                    expected_arrival_date: '2026-06-27'
                    vendor_rma_number: RMA-44821
                    notes: Returning defective units to supplier.
                    created_by_user_id: 5
                    created_at: '2026-06-20T14:03:11.000000Z'
                    updated_at: '2026-06-20T14:03:11.000000Z'
                    warehouse:
                      id: 3
                      name: Main Warehouse
                    shipping_method:
                      id: 2
                      name: UPS Ground
                    created_by_user:
                      id: 5
                      name: Jane Doe
                    lines:
                    - id: 30
                      vendor_credit_shipment_id: 12
                      vendor_credit_line_id: 88
                      warehouse_location_id: 14
                      quantity: 10
                      notes: null
                      created_at: '2026-06-20T14:03:11.000000Z'
                      updated_at: '2026-06-20T14:03:11.000000Z'
                      warehouse_location:
                        id: 14
                        name: A-01-01
                      vendor_credit_line:
                        id: 88
                        description: Widget Blue
                        quantity: 10
                        unit_cost: 4.25
                      product:
                        id: 501
                        sku: WIDGET-BLUE
                        name: Widget Blue
                    total_quantity: 10
                    link_reference: VCS-12
                    link_type_label: Vendor Credit Shipment
                    link_route: /purchases/vendor-credits/1/shipments/12
                  message: Vendor credit shipment created successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: accounting:write
      operationId: patch-api-vendor-credits-vendor-credit-shipments-vendor-credit-shipment-status
  /api/vendor-credits/shipments/{shipment}:
    get:
      tags:
      - Vendor Credits
      summary: Get Return Shipment
      description: 'Get a single return shipment (goods sent back to the supplier
        under a vendor credit) with its lines, warehouse, shipping method, and creator.
        The response also includes a summary of the parent vendor credit (number,
        status, and supplier) under the vendor_credit key.


        :::info[Required scope: `accounting:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: shipment
        in: path
        schema:
          type: integer
        required: true
        description: Vendor credit shipment ID
        example: '9'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      vendor_credit_id:
                        type: integer
                      warehouse_id:
                        type: integer
                      shipment_date:
                        type: string
                      status:
                        type: string
                      status_label:
                        type: string
                      tracking_number:
                        type: string
                      shipping_method_id:
                        type: integer
                      custom_carrier:
                        type: string
                        nullable: true
                      expected_arrival_date:
                        type: string
                      vendor_rma_number:
                        type: string
                      notes:
                        type: string
                        nullable: true
                      created_by_user_id:
                        type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      shipping_method:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      created_by_user:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            vendor_credit_shipment_id:
                              type: integer
                            vendor_credit_line_id:
                              type: integer
                            warehouse_location_id:
                              type: string
                              nullable: true
                            quantity:
                              type: integer
                            notes:
                              type: string
                              nullable: true
                            created_at:
                              type: string
                            updated_at:
                              type: string
                            warehouse_location:
                              type: string
                              nullable: true
                            vendor_credit_line:
                              type: object
                              properties:
                                id:
                                  type: integer
                                description:
                                  type: string
                                quantity:
                                  type: integer
                                unit_cost:
                                  type: integer
                            product:
                              type: object
                              properties:
                                id:
                                  type: integer
                                sku:
                                  type: string
                                name:
                                  type: string
                      total_quantity:
                        type: integer
                      link_reference:
                        type: string
                      link_type_label:
                        type: string
                      link_route:
                        type: string
                  vendor_credit:
                    type: object
                    properties:
                      id:
                        type: integer
                      vendor_credit_number:
                        type: string
                      credit_status:
                        type: string
                      supplier:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                example:
                  data:
                    id: 9
                    vendor_credit_id: 17
                    warehouse_id: 2
                    shipment_date: '2026-07-02'
                    status: shipped
                    status_label: Shipped
                    tracking_number: 1Z999AA10123456784
                    shipping_method_id: 4
                    custom_carrier: null
                    expected_arrival_date: '2026-07-09'
                    vendor_rma_number: RMA-5521
                    notes: null
                    created_by_user_id: 3
                    created_at: '2026-07-02T15:20:00.000000Z'
                    updated_at: '2026-07-02T15:20:00.000000Z'
                    warehouse:
                      id: 2
                      name: Main Warehouse
                    shipping_method:
                      id: 4
                      name: UPS Ground
                    created_by_user:
                      id: 3
                      name: Jane Operator
                    lines:
                    - id: 14
                      vendor_credit_shipment_id: 9
                      vendor_credit_line_id: 31
                      warehouse_location_id: null
                      quantity: 5
                      notes: null
                      created_at: '2026-07-02T15:20:00.000000Z'
                      updated_at: '2026-07-02T15:20:00.000000Z'
                      warehouse_location: null
                      vendor_credit_line:
                        id: 31
                        description: Blue Widget (Medium)
                        quantity: 5
                        unit_cost: 50
                      product:
                        id: 55
                        sku: WID-BLU-M
                        name: Blue Widget (Medium)
                    total_quantity: 5
                    link_reference: 1Z999AA10123456784
                    link_type_label: Vendor Credit Shipment
                    link_route: /purchases/vendor-credits/17/shipments/9
                  vendor_credit:
                    id: 17
                    vendor_credit_number: VC-000017
                    credit_status: open
                    supplier:
                      id: 7
                      name: Acme Components Ltd
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: accounting:read
      operationId: get-api-vendor-credits-shipments-shipment
  /api/vendor-credits/shipments/{shipment}/activity-log:
    get:
      tags:
      - Vendor Credits
      summary: Get Return Shipment Activity Log
      description: 'Paginated audit trail for a return shipment and its lines, newest
        first. Each entry records the event, the changed attributes, and who made
        the change.


        :::info[Required scope: `accounting:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Use filter[search] to match against the user''s name, the event, or the recorded
        change details.'
      parameters:
      - name: shipment
        in: path
        schema:
          type: integer
        required: true
        description: Vendor credit shipment ID
        example: '9'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        description:
                          type: string
                        event:
                          type: string
                        subject_type:
                          type: string
                        subject_id:
                          type: integer
                        properties:
                          type: object
                          properties:
                            attributes:
                              type: object
                              properties:
                                status:
                                  type: string
                            old:
                              type: object
                              properties:
                                status:
                                  type: string
                        causer_name:
                          type: string
                        created_at:
                          type: string
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                    items:
                      type: object
                      properties:
                        url:
                          type: string
                          nullable: true
                        label:
                          type: string
                        active:
                          type: boolean
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 3021
                    description: updated
                    event: updated
                    subject_type: VendorCreditShipment
                    subject_id: 9
                    properties:
                      attributes:
                        status: shipped
                      old:
                        status: pending
                    causer_name: Jane Operator
                    created_at: '2026-07-01T08:00:00.000000Z'
                  first_page_url: '{{protocol}}{{domain}}/api/vendor-credits/shipments/9/activity-log?page=1'
                  from: 1
                  last_page: 1
                  last_page_url: '{{protocol}}{{domain}}/api/vendor-credits/shipments/9/activity-log?page=1'
                  links:
                  - url: null
                    label: '&laquo; Previous'
                    active: false
                  - url: '{{protocol}}{{domain}}/api/vendor-credits/shipments/9/activity-log?page=1'
                    label: '1'
                    active: true
                  - url: null
                    label: Next &raquo;
                    active: false
                  next_page_url: null
                  path: '{{protocol}}{{domain}}/api/vendor-credits/shipments/9/activity-log'
                  per_page: 15
                  prev_page_url: null
                  to: 1
                  total: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: accounting:read
      operationId: get-api-vendor-credits-shipments-shipment-activity-log
  /api/vendor-credits/{vendor_credit}/ship-impact:
    get:
      tags:
      - Vendor Credits
      summary: Preview Vendor Credit Ship Impact
      description: 'Get a read-only preview of the order allocations that creating
        a return shipment for this vendor credit''s restock lines would consume. Each
        row is one product whose stock the shipment would remove, split into free,
        soft-reserved and hard-allocated quantities, and lists the affected sales-order
        allocations highest-priority first so you can see which orders — and which
        printed shipping labels — would be demoted or voided before you post the shipment.


        This endpoint makes no changes.


        Response fields:

        - `data[].product_id` / `product_sku` / `product_name` — the product the action
        would consume stock for.

        - `data[].shortfall_quantity` — how much more than the available quantity
        the action removes; stock goes negative when greater than 0.

        - `data[].unallocated_quantity` / `soft_allocated_quantity` / `hard_allocated_quantity`
        — the free / soft-reserved / hard-allocated (label-printed) split of the consumed
        quantity.

        - `data[].affected_allocations[]` — the order allocations that would be consumed,
        highest priority first. `allocation_type` is `soft` or `hard`. For hard rows,
        `fulfillment_id` and `carrier` identify the printed label and `carrier_void_supported`
        / `voidable_status` (`voidable` or otherwise) indicate whether the label can
        be voided through the API.


        Authentication: Requires Bearer token (PAT).'
      parameters:
      - name: vendor_credit
        in: path
        schema:
          type: integer
        required: true
        description: Vendor credit ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        product_id:
                          type: integer
                        product_sku:
                          type: string
                        product_name:
                          type: string
                        shortfall_quantity:
                          type: integer
                        unallocated_quantity:
                          type: integer
                        soft_allocated_quantity:
                          type: integer
                        hard_allocated_quantity:
                          type: integer
                        affected_allocations:
                          type: array
                          items:
                            type: object
                            properties:
                              allocation_id:
                                type: integer
                              allocation_type:
                                type: string
                              sales_order_id:
                                type: integer
                              order_number:
                                type: string
                              customer_name:
                                type: string
                              fulfillment_id:
                                type: string
                                nullable: true
                              carrier:
                                type: string
                                nullable: true
                              carrier_void_supported:
                                type: string
                                nullable: true
                              voidable_status:
                                type: string
                                nullable: true
                              voidable_detail:
                                type: string
                                nullable: true
                              quantity:
                                type: integer
                example:
                  data:
                  - product_id: 123
                    product_sku: WIDGET-001
                    product_name: Blue Widget 500ml
                    shortfall_quantity: 0
                    unallocated_quantity: 4
                    soft_allocated_quantity: 3
                    hard_allocated_quantity: 2
                    affected_allocations:
                    - allocation_id: 88213
                      allocation_type: soft
                      sales_order_id: 4521
                      order_number: SO-10442
                      customer_name: Acme Retail
                      fulfillment_id: null
                      carrier: null
                      carrier_void_supported: null
                      voidable_status: null
                      voidable_detail: null
                      quantity: 3
                    - allocation_id: 88240
                      allocation_type: hard
                      sales_order_id: 4530
                      order_number: SO-10450
                      customer_name: Beta Wholesale
                      fulfillment_id: 77120
                      carrier: ups
                      carrier_void_supported: true
                      voidable_status: voidable
                      voidable_detail: null
                      quantity: 2
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-vendor-credits-vendor-credit-ship-impact
  /api/vendor-credits/archive:
    put:
      tags:
      - Vendor Credits
      summary: Bulk Archive Vendor Credits
      description: 'Bulk archive vendor credits.


        :::info[Required scope: `accounting:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        **Body (either form):**

        ```json

        { "ids": [1, 2, 3] }

        ```

        or apply-to-all with filters:

        ```json

        { "apply_to_all": true, "filters": { "supplier_id": 5 } }

        ```'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1
                - 2
                - 3
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: accounting:write
      operationId: put-api-vendor-credits-archive
  /api/vendor-credits/unarchive:
    put:
      tags:
      - Vendor Credits
      summary: Bulk Unarchive Vendor Credits
      description: 'Bulk unarchive vendor credits. Same body shape as Bulk Archive.


        :::info[Required scope: `accounting:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1
                - 2
                - 3
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: accounting:write
      operationId: put-api-vendor-credits-unarchive
  /api/vendor-credits/bulk-void:
    post:
      tags:
      - Vendor Credits
      summary: Bulk Void Vendor Credits
      description: 'Void multiple vendor credits at once. Target credits either by
        an explicit ids array, or set apply_to_all to true with an optional filters
        object to void every credit matching the filter.


        :::info[Required scope: `accounting:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Voiding reverses each credit''s inventory movements and accounting transaction.
        Credits that cannot be voided (e.g. they have active allocations) are skipped
        and counted in the response message.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
                apply_to_all:
                  type: boolean
              example:
                ids:
                - 17
                - 18
                apply_to_all: false
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Voided 1 vendor credit(s). Skipped 1 (have active allocations).
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: accounting:write
      operationId: post-api-vendor-credits-bulk-void
  /api/vendor-credits/{vendorCredit}/notes:
    get:
      tags:
      - Vendor Credits
      summary: List Vendor Credit Notes
      description: 'Paginated list of notes on the vendor credit, ordered newest first.
        Each note includes its author (`user`) relation.


        :::info[Required scope: `accounting:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: vendorCredit
        in: path
        schema:
          type: integer
        required: true
        description: Vendor credit ID
        example: '1'
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: accounting:read
      operationId: get-api-vendor-credits-vendorcredit-notes
    post:
      tags:
      - Vendor Credits
      summary: Add Vendor Credit Note
      description: 'Add a note to the vendor credit. `note` is required.


        :::info[Required scope: `accounting:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                note:
                  type: string
              example:
                note: Called supplier, they confirmed the credit will be applied on
                  next bill.
      parameters:
      - name: vendorCredit
        in: path
        schema:
          type: integer
        required: true
        description: Vendor credit ID
        example: '1'
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: accounting:write
      operationId: post-api-vendor-credits-vendorcredit-notes
  /api/vendor-credits/{vendorCredit}/notes/{noteId}:
    delete:
      tags:
      - Vendor Credits
      summary: Delete Vendor Credit Note
      description: 'Delete a single note from a vendor credit. Idempotent: returns
        success even if the note does not exist.


        :::info[Required scope: `accounting:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: vendorCredit
        in: path
        schema:
          type: integer
        required: true
        description: Vendor credit ID
        example: '1'
      - name: noteId
        in: path
        schema:
          type: integer
        required: true
        description: Note ID
        example: '1'
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: accounting:write
      operationId: delete-api-vendor-credits-vendorcredit-notes-noteid
  /api/vendor-credits/{vendorCredit}/notes/{noteId}/toggle-pin:
    put:
      tags:
      - Vendor Credits
      summary: Toggle Vendor Credit Note Pin
      description: 'Toggle the pinned state of a note on a vendor credit. Pinned notes
        sort to the top of the note list. No request body is required.


        :::info[Required scope: `accounting:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Returns the updated note. Returns 404 when the note does not belong to the
        vendor credit.'
      requestBody:
        content: {}
      parameters:
      - name: vendorCredit
        in: path
        schema:
          type: integer
        required: true
        description: Vendor credit ID
        example: '17'
      - name: noteId
        in: path
        schema:
          type: integer
        required: true
        description: Note ID
        example: '12'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      note:
                        type: string
                      is_pinned:
                        type: boolean
                      user_id:
                        type: integer
                      notable_type:
                        type: string
                      notable_id:
                        type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      user:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          email:
                            type: string
                  message:
                    type: string
                example:
                  data:
                    id: 12
                    note: Called the supplier — replacement stock ships next week.
                    is_pinned: true
                    user_id: 3
                    notable_type: App\Models\VendorCredit
                    notable_id: 17
                    created_at: '2026-07-01T08:05:00.000000Z'
                    updated_at: '2026-07-07T09:40:00.000000Z'
                    user:
                      id: 3
                      name: Jane Operator
                      email: jane@example.com
                  message: Note pinned
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: accounting:write
      operationId: put-api-vendor-credits-vendorcredit-notes-noteid-toggle-pin
  /api/vendor-credits/{vendorCredit}/activity-log:
    get:
      tags:
      - Vendor Credits
      summary: Get Vendor Credit Activity Log
      description: 'Paginated audit trail for a vendor credit, newest first. Covers
        changes to the credit itself, its lines, and its return shipments and shipment
        lines. Each entry records the event, the changed attributes, and who made
        the change.


        :::info[Required scope: `accounting:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Use filter[search] to match against the user''s name, the event, or the recorded
        change details.'
      parameters:
      - name: vendorCredit
        in: path
        schema:
          type: integer
        required: true
        description: Vendor credit ID
        example: '17'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        description:
                          type: string
                        event:
                          type: string
                        subject_type:
                          type: string
                        subject_id:
                          type: integer
                        properties:
                          type: object
                          properties:
                            attributes:
                              type: object
                              properties:
                                credit_status:
                                  type: string
                            old:
                              type: object
                              properties:
                                credit_status:
                                  type: string
                        causer_name:
                          type: string
                        created_at:
                          type: string
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                    items:
                      type: object
                      properties:
                        url:
                          type: string
                          nullable: true
                        label:
                          type: string
                        active:
                          type: boolean
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 3021
                    description: updated
                    event: updated
                    subject_type: VendorCredit
                    subject_id: 17
                    properties:
                      attributes:
                        credit_status: open
                      old:
                        credit_status: draft
                    causer_name: Jane Operator
                    created_at: '2026-07-01T08:00:00.000000Z'
                  first_page_url: '{{protocol}}{{domain}}/api/vendor-credits/17/activity-log?page=1'
                  from: 1
                  last_page: 1
                  last_page_url: '{{protocol}}{{domain}}/api/vendor-credits/17/activity-log?page=1'
                  links:
                  - url: null
                    label: '&laquo; Previous'
                    active: false
                  - url: '{{protocol}}{{domain}}/api/vendor-credits/17/activity-log?page=1'
                    label: '1'
                    active: true
                  - url: null
                    label: Next &raquo;
                    active: false
                  next_page_url: null
                  path: '{{protocol}}{{domain}}/api/vendor-credits/17/activity-log'
                  per_page: 15
                  prev_page_url: null
                  to: 1
                  total: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: accounting:read
      operationId: get-api-vendor-credits-vendorcredit-activity-log
  /api/vendor-credits/{vendor_credit}/fifo-layer-usages:
    get:
      tags:
      - Vendor Credits
      summary: List Vendor Credit FIFO Layer Usages
      description: 'Read-only audit trail of the FIFO cost layers consumed or referenced
        when the vendor credit was authorized. Each usage records the credited quantity,
        the unit cost taken from the layer, whether the layer''s available quantity
        was actually decremented, and details of the layer, product, and credit line
        involved.


        :::info[Required scope: `accounting:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: vendor_credit
        in: path
        schema:
          type: integer
        required: true
        description: Vendor credit ID
        example: '17'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        vendor_credit_line_id:
                          type: integer
                        fifo_layer_id:
                          type: integer
                        quantity:
                          type: integer
                        unit_cost:
                          type: integer
                        line_total:
                          type: integer
                        decremented_layer:
                          type: boolean
                        created_at:
                          type: string
                        fifo_layer:
                          type: object
                          properties:
                            id:
                              type: integer
                            fifo_layer_date:
                              type: string
                            original_quantity:
                              type: integer
                            fulfilled_quantity:
                              type: integer
                            available_quantity:
                              type: integer
                            avg_cost:
                              type: integer
                            link_type:
                              type: string
                            link_id:
                              type: integer
                            link_reference:
                              type: string
                            warehouse:
                              type: object
                              properties:
                                id:
                                  type: integer
                                name:
                                  type: string
                        product:
                          type: object
                          properties:
                            id:
                              type: integer
                            sku:
                              type: string
                            name:
                              type: string
                        vendor_credit_line:
                          type: object
                          properties:
                            id:
                              type: integer
                            description:
                              type: string
                            quantity:
                              type: integer
                        link_reference:
                          type: string
                        link_type_label:
                          type: string
                        link_route:
                          type: string
                example:
                  data:
                  - id: 501
                    vendor_credit_line_id: 31
                    fifo_layer_id: 4410
                    quantity: 5
                    unit_cost: 50
                    line_total: 250
                    decremented_layer: true
                    created_at: '2026-06-20T10:20:00.000000Z'
                    fifo_layer:
                      id: 4410
                      fifo_layer_date: '2026-05-12'
                      original_quantity: 20
                      fulfilled_quantity: 8
                      available_quantity: 12
                      avg_cost: 50
                      link_type: App\Models\PurchaseOrderLine
                      link_id: 771
                      link_reference: PO-000310
                      warehouse:
                        id: 2
                        name: Main Warehouse
                    product:
                      id: 55
                      sku: WID-BLU-M
                      name: Blue Widget (Medium)
                    vendor_credit_line:
                      id: 31
                      description: Blue Widget (Medium)
                      quantity: 5
                    link_reference: PO-000310
                    link_type_label: FIFO Layer
                    link_route: /inventory/fifo-layers/4410
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: accounting:read
      operationId: get-api-vendor-credits-vendor-credit-fifo-layer-usages
  /api/vendor-credits/{vendor_credit}/inventory-movements:
    get:
      tags:
      - Vendor Credits
      summary: List Vendor Credit Inventory Movements
      description: 'Paginated inventory movements posted against a vendor credit:
        write-off movements on credit lines and outbound movements from return shipments.
        Each row includes the product, warehouse, quantity, and the FIFO layer and
        unit cost where known; unit_cost_provisional is true for rows whose cost is
        estimated from the product''s current unit cost because no layer was consumed.


        :::info[Required scope: `accounting:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Sortable by id, inventory_movement_date, type, inventory_status, quantity,
        reference, and created_at (default: -inventory_movement_date). Text filters
        on type, inventory_status, and reference support the advanced-filter operators
        (is / contains / starts_with / etc.); quantity supports numeric comparisons
        and inventory_movement_date / created_at support date comparisons.'
      parameters:
      - name: vendor_credit
        in: path
        schema:
          type: integer
        required: true
        description: Vendor credit ID
        example: '17'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        type:
                          type: string
                        inventory_status:
                          type: string
                        quantity:
                          type: integer
                        reference:
                          type: string
                        link_type:
                          type: string
                        link_id:
                          type: integer
                        parent_link_id:
                          type: integer
                        detail_link_id:
                          type: string
                          nullable: true
                        product_id:
                          type: integer
                        product_sku:
                          type: string
                        product_name:
                          type: string
                        warehouse_id:
                          type: integer
                        warehouse_name:
                          type: string
                        unit_cost:
                          type: integer
                        unit_cost_provisional:
                          type: boolean
                        layer:
                          type: object
                          properties:
                            name:
                              type: string
                            fifo_layer_id:
                              type: integer
                        inventory_movement_date:
                          type: string
                        created_at:
                          type: string
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                    items:
                      type: object
                      properties:
                        url:
                          type: string
                          nullable: true
                        label:
                          type: string
                        active:
                          type: boolean
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 7710
                    type: write_off
                    inventory_status: on_hand
                    quantity: -5
                    reference: VC-000017
                    link_type: App\Models\VendorCreditLine
                    link_id: 31
                    parent_link_id: 17
                    detail_link_id: null
                    product_id: 55
                    product_sku: WID-BLU-M
                    product_name: Blue Widget (Medium)
                    warehouse_id: 2
                    warehouse_name: Main Warehouse
                    unit_cost: 50
                    unit_cost_provisional: false
                    layer:
                      name: PO-000310
                      fifo_layer_id: 4410
                    inventory_movement_date: '2026-06-20T10:20:00.000000Z'
                    created_at: '2026-06-20T10:20:00.000000Z'
                  first_page_url: '{{protocol}}{{domain}}/api/vendor-credits/17/inventory-movements?page=1'
                  from: 1
                  last_page: 1
                  last_page_url: '{{protocol}}{{domain}}/api/vendor-credits/17/inventory-movements?page=1'
                  links:
                  - url: null
                    label: '&laquo; Previous'
                    active: false
                  - url: '{{protocol}}{{domain}}/api/vendor-credits/17/inventory-movements?page=1'
                    label: '1'
                    active: true
                  - url: null
                    label: Next &raquo;
                    active: false
                  next_page_url: null
                  path: '{{protocol}}{{domain}}/api/vendor-credits/17/inventory-movements'
                  per_page: 15
                  prev_page_url: null
                  to: 1
                  total: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: accounting:read
      operationId: get-api-vendor-credits-vendor-credit-inventory-movements
  /api/vendor-credits/{vendor_credit}/pdf:
    get:
      tags:
      - Vendor Credits
      summary: Get Vendor Credit PDF
      description: 'Render the vendor credit as a PDF using the configured Vendor
        Credit template. Returns a PDF file (Content-Type: application/pdf) displayed
        inline. Customize the template in Settings → PDF Templates → Vendor Credit.'
      parameters:
      - name: vendor_credit
        in: path
        schema:
          type: integer
        required: true
        description: Vendor credit ID
        example: '1'
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-vendor-credits-vendor-credit-pdf
  /api/vendor-credits/{vendor_credit}/generate-accounting-transaction:
    post:
      tags:
      - Vendor Credits
      summary: Generate Accounting Transaction
      description: 'Generate (or regenerate) the local accounting transaction for
        the vendor credit. Builds the transaction lines from the vendor credit and
        saves the accounting transaction. Returns an accounting transaction object
        with eager-loaded lines and nominal codes.


        :::info[Required scope: `accounting:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters:
      - name: vendor_credit
        in: path
        schema:
          type: integer
        required: true
        description: Vendor credit ID
        example: '1'
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: accounting:write
      operationId: post-api-vendor-credits-vendor-credit-generate-accounting-transaction
  /api/vendor-credits/{vendorCredit}/attachments:
    get:
      tags:
      - Vendor Credits
      summary: List Vendor Credit Attachments
      description: 'List all attachments for the given vendor credit, newest first.
        Each attachment includes the uploader (when loaded), a ready-to-use download_url,
        and OCR scan state (ocr_status: null, processing, pending_review, confirmed,
        failed, rejected, or duplicate_detected).


        :::info[Required scope: `accounting:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: vendorCredit
        in: path
        schema:
          type: integer
        required: true
        description: Vendor credit ID
        example: '12'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        file_name:
                          type: string
                        file_size:
                          type: integer
                        mime_type:
                          type: string
                        created_at:
                          type: string
                        uploaded_by:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        download_url:
                          type: string
                        ocr_status:
                          type: string
                        ocr_error_message:
                          type: string
                          nullable: true
                        ocr_processed_at:
                          type: string
                example:
                  data:
                  - id: 5
                    file_name: credit-memo-acme.pdf
                    file_size: 482133
                    mime_type: application/pdf
                    created_at: '2026-06-01T14:22:08.000000Z'
                    uploaded_by:
                      id: 3
                      name: Jane Doe
                    download_url: https://app.sku.io/api/vendor-credits/12/attachments/5/download
                    ocr_status: pending_review
                    ocr_error_message: null
                    ocr_processed_at: '2026-06-01T14:24:51.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: accounting:read
      operationId: get-api-vendor-credits-vendorcredit-attachments
    post:
      tags:
      - Vendor Credits
      summary: Upload Vendor Credit Attachment
      description: 'Upload a new attachment to the vendor credit. multipart/form-data
        with a single `file` field.


        :::info[Required scope: `accounting:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Validation:

        - file: required, max 20 MB (20480 KB), mimes: pdf, png, jpg, jpeg, webp

        - Empty (0-byte) files are rejected


        Returns 201 with the created attachment. Returns 422 if the vendor credit
        is archived or the file fails validation.'
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                file:
                  type: string
                  description: Required. PDF, PNG, JPG, JPEG, or WEBP file, max 20
                    MB.
                  format: binary
      parameters:
      - name: vendorCredit
        in: path
        schema:
          type: integer
        required: true
        description: Vendor credit ID
        example: '12'
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      file_name:
                        type: string
                      file_size:
                        type: integer
                      mime_type:
                        type: string
                      created_at:
                        type: string
                      uploaded_by:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      download_url:
                        type: string
                      ocr_status:
                        type: string
                        nullable: true
                      ocr_error_message:
                        type: string
                        nullable: true
                      ocr_processed_at:
                        type: string
                        nullable: true
                example:
                  data:
                    id: 5
                    file_name: credit-memo-acme.pdf
                    file_size: 482133
                    mime_type: application/pdf
                    created_at: '2026-06-01T14:22:08.000000Z'
                    uploaded_by:
                      id: 3
                      name: Jane Doe
                    download_url: https://app.sku.io/api/vendor-credits/12/attachments/5/download
                    ocr_status: null
                    ocr_error_message: null
                    ocr_processed_at: null
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 422 Archived Credit
                  value:
                    message: Cannot add attachments to an archived vendor credit.
                example-1:
                  summary: 422 Validation Error
                  value:
                    message: File exceeds the 20 MB limit.
                    errors:
                      file:
                      - File exceeds the 20 MB limit.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: accounting:write
      operationId: post-api-vendor-credits-vendorcredit-attachments
  /api/vendor-credits/{vendorCredit}/attachments/{attachment}:
    delete:
      tags:
      - Vendor Credits
      summary: Delete Vendor Credit Attachment
      description: 'Delete an attachment (removes the stored file and the record).
        Returns 404 if the attachment does not belong to the vendor credit, and 422
        if the vendor credit is archived.


        :::info[Required scope: `accounting:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Returns 422 if the credit is archived/voided or the attachment''s OCR scan
        is in progress.'
      parameters:
      - name: vendorCredit
        in: path
        schema:
          type: integer
        required: true
        description: Vendor credit ID
        example: '12'
      - name: attachment
        in: path
        schema:
          type: integer
        required: true
        description: Vendor credit attachment ID
        example: '5'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Attachment deleted.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 422 Archived Credit
                  value:
                    message: Cannot delete attachments from an archived vendor credit.
                example-1:
                  summary: 422 OCR In Progress
                  value:
                    message: Attachments cannot be deleted while OCR is in progress.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: accounting:write
      operationId: delete-api-vendor-credits-vendorcredit-attachments-attachment
  /api/vendor-credits/{vendorCredit}/attachments/{attachment}/download:
    get:
      tags:
      - Vendor Credits
      summary: Download Vendor Credit Attachment
      description: 'Stream the attachment file as a download (Content-Disposition:
        attachment). The response is the binary file content with the original file
        name and MIME type — not JSON. Returns 404 if the attachment does not belong
        to the vendor credit or the file is missing from storage.


        :::info[Required scope: `accounting:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: vendorCredit
        in: path
        schema:
          type: integer
        required: true
        description: Vendor credit ID
        example: '12'
      - name: attachment
        in: path
        schema:
          type: integer
        required: true
        description: Vendor credit attachment ID
        example: '5'
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: accounting:read
      operationId: get-api-vendor-credits-vendorcredit-attachments-attachment-download
  /api/vendor-credits/{vendorCredit}/attachments/{attachment}/view:
    get:
      tags:
      - Vendor Credits
      summary: View Attachment Inline
      description: 'Stream the attachment file inline (Content-Disposition: inline)
        for in-browser preview of PDFs and images. The response is the binary file
        content — not JSON. Returns 404 if the attachment does not belong to the vendor
        credit or the file is missing from storage.


        :::info[Required scope: `accounting:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: vendorCredit
        in: path
        schema:
          type: integer
        required: true
        description: Vendor credit ID
        example: '12'
      - name: attachment
        in: path
        schema:
          type: integer
        required: true
        description: Vendor credit attachment ID
        example: '5'
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: accounting:read
      operationId: get-api-vendor-credits-vendorcredit-attachments-attachment-view
  /api/vendor-credits/ocr/upload:
    post:
      tags:
      - Vendor Credits
      summary: Upload Credit Memo for OCR
      description: 'Upload a credit memo PDF to begin OCR extraction. multipart/form-data.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Validation:

        - file: required, PDF only (mimes: pdf), max 20 MB (20480 KB)

        - supplier_id: optional integer, must exist in suppliers

        - purchase_order_id: optional integer, must exist in purchase_orders. Pre-links
        the extraction to that PO; derives the supplier hint from the PO when supplier_id
        is omitted. A pre-linked PO wins over OCR''s own po_number match.


        Processing is asynchronous — the response includes a tracked_job_log_id for
        the tracked job log endpoints. Poll Get Extraction until status moves from
        processing to pending_review (or failed / duplicate_detected). Returns 422
        if Vendor Credit OCR is not enabled in Settings → Invoice OCR.'
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                file:
                  type: string
                  description: 'Vendor credit / credit memo file (required, max 20
                    MB). Accepts PDF and image scans: pdf, jpg, jpeg, png, tif, tiff,
                    bmp, webp.'
                  format: binary
                supplier_id:
                  type: integer
                  description: Optional. Supplier ID to pre-assign to the extraction.
                  example: '7'
                purchase_order_id:
                  type: integer
                  description: Optional. Pre-link the scan to a purchase order (e.g.
                    when launched from a PO page). The PO's supplier is used as the
                    supplier hint when supplier_id is omitted, and the pre-linked
                    PO takes precedence over OCR's own PO-number match.
                  example: '123'
      parameters: []
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      extraction_id:
                        type: integer
                      tracked_job_log_id:
                        type: integer
                      status:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    extraction_id: 12
                    tracked_job_log_id: 3301
                    status: processing
                  message: OCR processing started
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Vendor Credit OCR is not enabled. Please configure it in
                    Settings → Invoice OCR.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: orders:write
      operationId: post-api-vendor-credits-ocr-upload
  /api/vendor-credits/ocr/{extraction}:
    get:
      tags:
      - Vendor Credits
      summary: Get Vendor Credit Extraction
      description: 'Get a vendor credit OCR extraction record with extracted header
        fields, matched lines, and related records (supplier, purchase order, duplicate
        vendor credit, referenced purchase invoice, candidate purchase orders).


        :::info[Required scope: `orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Header fields: credit_number, credit_date, supplier_name, total, subtotal,
        tax_amount, currency_code, po_number, document_type, plus matched_supplier_id
        / matched_supplier_name / matched_purchase_order_id / matched_purchase_order_number.


        Line match_status values: exact, fuzzy, discount_confirmation, unmatched.


        **Classification fields:** `document_type` (`credit_memo` | `invoice` | `unknown`),
        `detection_signals` (array of raw classifier signals, e.g. `keyword:credit
        memo`, `doc_number:CM prefix`, `total:negative`; `null` when not classified)
        and `auto_routed` (`true` when the document arrived via the supplier-invoice
        intake and was automatically routed to the credit memo queue by the document
        type classifier).'
      parameters:
      - name: extraction
        in: path
        schema:
          type: integer
        required: true
        description: Vendor credit OCR extraction ID
        example: '12'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      status:
                        type: string
                      source:
                        type: string
                      file_url:
                        type: string
                      file_name:
                        type: string
                      page_count:
                        type: integer
                      header:
                        type: object
                        properties:
                          credit_number:
                            type: string
                          credit_date:
                            type: string
                          supplier_name:
                            type: string
                          total:
                            type: integer
                          subtotal:
                            type: integer
                          tax_amount:
                            type: integer
                          currency_code:
                            type: string
                          po_number:
                            type: string
                          document_type:
                            type: string
                          matched_supplier_id:
                            type: integer
                          matched_supplier_name:
                            type: string
                          matched_purchase_order_id:
                            type: integer
                          matched_purchase_order_number:
                            type: string
                      is_matched_supplier:
                        type: boolean
                      extracted_supplier_name:
                        type: string
                      lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: string
                            description:
                              type: string
                            qty:
                              type: integer
                            unit_price:
                              type: number
                            line_total:
                              type: integer
                            confidence:
                              type: number
                            raw_sku:
                              type: string
                            match_status:
                              type: string
                            matched_product_id:
                              type: integer
                            matched_product_name:
                              type: string
                            matched_product_sku:
                              type: string
                            saved_financial_line_type_id:
                              type: string
                              nullable: true
                            discount_variance:
                              type: string
                              nullable: true
                            po_expected_discount:
                              type: string
                              nullable: true
                      azure_cost_usd:
                        type: number
                      confidence_score:
                        type: number
                      error_message:
                        type: string
                        nullable: true
                      document_type:
                        type: string
                      detection_signals:
                        type: array
                        items:
                          type: string
                      auto_routed:
                        type: boolean
                      vendor_credit_id:
                        type: string
                        nullable: true
                      vendor_credit_attachment_id:
                        type: string
                        nullable: true
                      tracked_job_log_id:
                        type: integer
                      supplier:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      purchase_order:
                        type: object
                        properties:
                          id:
                            type: integer
                          purchase_order_number:
                            type: string
                          purchase_order_date:
                            type: string
                      duplicate_vendor_credit:
                        type: string
                        nullable: true
                      referenced_purchase_invoice:
                        type: string
                        nullable: true
                      candidate_purchase_orders:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            purchase_order_number:
                              type: string
                            purchase_order_date:
                              type: string
                            order_status:
                              type: string
                      created_at:
                        type: string
                example:
                  data:
                    id: 12
                    status: pending_review
                    source: upload
                    file_url: https://app.sku.io/api/vendor-credits/ocr/12/pdf
                    file_name: credit-memo-acme.pdf
                    page_count: 2
                    header:
                      credit_number: CM-10422
                      credit_date: '2026-05-28'
                      supplier_name: Acme Supply Co
                      total: 65
                      subtotal: 65
                      tax_amount: 0
                      currency_code: USD
                      po_number: PO-2026-0144
                      document_type: credit_memo
                      matched_supplier_id: 7
                      matched_supplier_name: Acme Supply Co
                      matched_purchase_order_id: 144
                      matched_purchase_order_number: PO-2026-0144
                    is_matched_supplier: true
                    extracted_supplier_name: Acme Supply Co
                    lines:
                    - id: f4f0c2ab-9a31-4a2e-8f0a-3d7e1f0b6c11
                      description: Blue Widget - damaged in transit
                      qty: 4
                      unit_price: 12.5
                      line_total: 50
                      confidence: 0.96
                      raw_sku: WIDGET-BLU
                      match_status: exact
                      matched_product_id: 555
                      matched_product_name: Blue Widget
                      matched_product_sku: WIDGET-BLU
                      saved_financial_line_type_id: null
                      discount_variance: null
                      po_expected_discount: null
                    - id: 0b2a6f7e-2c44-49d2-9a18-77c1f3a9e802
                      description: Freight rebate
                      qty: 1
                      unit_price: 15
                      line_total: 15
                      confidence: 0.91
                      raw_sku: null
                      match_status: unmatched
                      matched_product_id: null
                      matched_product_name: null
                      matched_product_sku: null
                      saved_financial_line_type_id: null
                      discount_variance: null
                      po_expected_discount: null
                    azure_cost_usd: 0.02
                    confidence_score: 0.94
                    error_message: null
                    document_type: credit_memo
                    detection_signals:
                    - keyword:credit memo
                    - total:negative
                    auto_routed: true
                    vendor_credit_id: null
                    vendor_credit_attachment_id: null
                    tracked_job_log_id: 3301
                    supplier:
                      id: 7
                      name: Acme Supply Co
                    purchase_order:
                      id: 144
                      purchase_order_number: PO-2026-0144
                      purchase_order_date: '2026-04-02'
                    duplicate_vendor_credit: null
                    referenced_purchase_invoice: null
                    candidate_purchase_orders:
                    - id: 144
                      purchase_order_number: PO-2026-0144
                      purchase_order_date: '2026-04-02'
                      order_status: received
                    created_at: '2026-06-01T14:22:08.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:read
      operationId: get-api-vendor-credits-ocr-extraction
    delete:
      tags:
      - Vendor Credits
      summary: Delete Vendor Credit Extraction
      description: 'Delete a vendor credit OCR extraction record and its associated
        stored file. Returns 204 No Content on success. Returns 422 if the extraction
        is confirmed (confirmed extractions cannot be deleted).


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Returns 422 if the extraction is confirmed or currently processing.'
      parameters:
      - name: extraction
        in: path
        schema:
          type: integer
        required: true
        description: Vendor credit OCR extraction ID
        example: '12'
      responses:
        '204':
          description: No Content
          content:
            text/plain:
              schema:
                type: string
                example: ''
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 422 Confirmed Extraction
                  value:
                    message: Confirmed extractions cannot be deleted.
                example-1:
                  summary: 422 Processing Extraction
                  value:
                    message: Extractions cannot be deleted while OCR is in progress.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:write
      operationId: delete-api-vendor-credits-ocr-extraction
  /api/vendor-credits/ocr/{extraction}/pdf:
    get:
      tags:
      - Vendor Credits
      summary: Stream Vendor Credit Extraction PDF
      description: 'Stream the original credit memo PDF through the backend (avoids
        CORS issues with direct storage URLs). The response is binary PDF content
        (Content-Type: application/pdf, Content-Disposition: inline) — not JSON. Returns
        404 if the file is no longer available in storage.


        :::info[Required scope: `orders:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: extraction
        in: path
        schema:
          type: integer
        required: true
        description: Vendor credit OCR extraction ID
        example: '12'
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:read
      operationId: get-api-vendor-credits-ocr-extraction-pdf
  /api/vendor-credits/ocr/{extraction}/rescan:
    post:
      tags:
      - Vendor Credits
      summary: Re-scan Vendor Credit Extraction
      description: 'Re-dispatch OCR processing for an existing extraction (e.g. after
        a failed scan or to pick up improved matching). Asynchronous — returns a new
        tracked_job_log_id. Returns 422 if the extraction is already confirmed or
        the original file is no longer available.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters:
      - name: extraction
        in: path
        schema:
          type: integer
        required: true
        description: Vendor credit OCR extraction ID
        example: '12'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      extraction_id:
                        type: integer
                      tracked_job_log_id:
                        type: integer
                      status:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    extraction_id: 12
                    tracked_job_log_id: 3305
                    status: processing
                  message: Re-scan started.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Confirmed extractions cannot be re-scanned.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:write
      operationId: post-api-vendor-credits-ocr-extraction-rescan
  /api/vendor-credits/ocr/{extraction}/create-credit:
    post:
      tags:
      - Vendor Credits
      summary: Create Vendor Credit from Extraction
      description: 'Create a draft vendor credit from a reviewed OCR extraction. The
        OCR''d PDF is automatically attached to the new credit and the extraction
        is marked confirmed.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Body fields (all top-level fields optional unless noted):

        - supplier_id: optional integer, must exist in suppliers

        - purchase_order_id: optional integer, must exist in purchase_orders

        - warehouse_id: optional integer, must exist in warehouses

        - currency_id: optional integer, must exist in currencies

        - credit_date: optional date

        - supplier_reference: optional string, max 255

        - vendor_credit_note: optional string

        - lines: REQUIRED array, min 1 element


        Line fields (per element of `lines`):

        - quantity: required, numeric, min 1

        - amount: required, numeric, must be less than 100000

        - purchase_order_line_id: optional integer (existing PO line)

        - product_id: optional integer (existing product)

        - description: optional string, max 255

        - unit_cost: optional numeric

        - nominal_code_id: optional integer (for non-product/financial lines)

        - is_product: optional boolean

        - restock_inventory: optional boolean


        Returns 201 with the new vendor_credit_id. Returns 422 with a message when
        the manager rejects the request (e.g. duplicate or invalid state).


        The created credit''s vendor_credit_number defaults to the supplier''s credit
        reference (extracted credit_number / supplier_reference) when that number
        is not already in use; otherwise the next local VC-#### number is generated.


        **Reference fields:**

        - `vendor_credit_number` (string, max 255) — The supplier''s credit memo number.
        On create it becomes the credit''s number (falls back to the OCR-detected
        `credit_number`, auto-generates `VC-xxxxx` if taken). On apply it renames
        the credit — skipped silently if another credit already uses that number.

        - `supplier_po_number` (string, max 255) — The PO number printed on the supplier''s
        memo, recorded as TEXT only (defaults from the OCR-detected `po_number` on
        create). It does not link a purchase order; use `purchase_order_id` for an
        actual link.

        - `supplier_reference` (string, max 255) — Any additional reference on the
        document (e.g. the vendor''s internal credit-order number). No longer auto-filled
        with the memo number.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                supplier_id:
                  type: integer
                purchase_order_id:
                  type: integer
                warehouse_id:
                  type: integer
                currency_id:
                  type: integer
                credit_date:
                  type: string
                supplier_reference:
                  type: string
                supplier_po_number:
                  type: string
                vendor_credit_number:
                  type: string
                vendor_credit_note:
                  type: string
                lines:
                  type: array
                  items:
                    type: object
                    properties:
                      purchase_order_line_id:
                        type: integer
                      product_id:
                        type: integer
                      description:
                        type: string
                      quantity:
                        type: integer
                      unit_cost:
                        type: number
                      amount:
                        type: integer
                      nominal_code_id:
                        type: string
                        nullable: true
                      is_product:
                        type: boolean
                      restock_inventory:
                        type: boolean
              example:
                supplier_id: 7
                purchase_order_id: 144
                warehouse_id: 2
                currency_id: 1
                credit_date: '2026-05-28'
                supplier_reference: CM-10422
                supplier_po_number: '001'
                vendor_credit_number: 0001669
                vendor_credit_note: Credit memo CM-10422 created from OCR upload.
                lines:
                - purchase_order_line_id: 101
                  product_id: 555
                  description: Blue Widget - damaged in transit
                  quantity: 4
                  unit_cost: 12.5
                  amount: 50
                  nominal_code_id: null
                  is_product: true
                  restock_inventory: false
                - purchase_order_line_id: null
                  product_id: null
                  description: Freight rebate
                  quantity: 1
                  unit_cost: 15
                  amount: 15
                  nominal_code_id: 27
                  is_product: false
                  restock_inventory: false
      parameters:
      - name: extraction
        in: path
        schema:
          type: integer
        required: true
        description: Vendor credit OCR extraction ID
        example: '12'
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      vendor_credit_id:
                        type: integer
                      extraction_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    vendor_credit_id: 311
                    extraction_id: 12
                  message: Vendor credit created from OCR extraction.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      lines:
                        type: array
                        items:
                          type: string
                example:
                  message: At least one line item is required to create a vendor credit.
                  errors:
                    lines:
                    - At least one line item is required to create a vendor credit.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:write
      operationId: post-api-vendor-credits-ocr-extraction-create-credit
  /api/vendor-credits/ocr/{extraction}/attach-to-credit:
    post:
      tags:
      - Vendor Credits
      summary: Attach Extraction to Existing Credit
      description: 'Attach the OCR''d PDF to an existing vendor credit that was created
        manually (instead of creating a new credit from the extraction).


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Body fields:

        - vendor_credit_id: required integer, must exist in vendor_credits


        Only extractions in pending_review or duplicate_detected status can be attached
        (422 otherwise). Returns 201 with the created attachment_id.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                vendor_credit_id:
                  type: integer
              example:
                vendor_credit_id: 311
      parameters:
      - name: extraction
        in: path
        schema:
          type: integer
        required: true
        description: Vendor credit OCR extraction ID
        example: '12'
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      vendor_credit_id:
                        type: integer
                      extraction_id:
                        type: integer
                      attachment_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    vendor_credit_id: 311
                    extraction_id: 12
                    attachment_id: 57
                  message: OCR document attached to existing vendor credit.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Only extractions pending review can be attached.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:write
      operationId: post-api-vendor-credits-ocr-extraction-attach-to-credit
  /api/vendor-credits/{vendorCredit}/ocr-apply:
    post:
      tags:
      - Vendor Credits
      summary: Apply OCR Results to Vendor Credit
      description: 'Apply reviewed OCR extraction results onto an existing vendor
        credit (header values and/or lines).


        :::info[Required scope: `accounting:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        IMPORTANT: the payload is FLAT — supplier_reference, credit_date, and vendor_credit_note
        are top-level fields. There is no header wrapper object.


        Body fields:

        - extraction_id: required integer, must exist in vendor_credit_ocr_extractions

        - line_mode: optional string, append or replace (how extracted lines are merged
        into the credit''s existing lines)

        - supplier_reference: optional (sometimes) nullable string, max 255

        - credit_date: optional (sometimes) nullable date

        - vendor_credit_note: optional (sometimes) nullable string

        - lines: optional array


        Line fields (per element of `lines`):

        - quantity: required, numeric, min 1

        - amount: required, numeric, must be less than 100000

        - purchase_order_line_id: optional integer (existing PO line)

        - product_id: optional integer (existing product)

        - description: optional string, max 255

        - unit_cost: optional numeric

        - nominal_code_id: optional integer (for non-product/financial lines)

        - is_product: optional boolean

        - restock_inventory: optional boolean


        Returns 200 on success. Returns 422 with a message when the manager rejects
        the apply (e.g. invalid state).


        **Reference fields:**

        - `vendor_credit_number` (string, max 255) — The supplier''s credit memo number.
        On create it becomes the credit''s number (falls back to the OCR-detected
        `credit_number`, auto-generates `VC-xxxxx` if taken). On apply it renames
        the credit — skipped silently if another credit already uses that number.

        - `supplier_po_number` (string, max 255) — The PO number printed on the supplier''s
        memo, recorded as TEXT only (defaults from the OCR-detected `po_number` on
        create). It does not link a purchase order; use `purchase_order_id` for an
        actual link.

        - `supplier_reference` (string, max 255) — Any additional reference on the
        document (e.g. the vendor''s internal credit-order number). No longer auto-filled
        with the memo number.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                extraction_id:
                  type: integer
                line_mode:
                  type: string
                supplier_reference:
                  type: string
                supplier_po_number:
                  type: string
                vendor_credit_number:
                  type: string
                credit_date:
                  type: string
                vendor_credit_note:
                  type: string
                lines:
                  type: array
                  items:
                    type: object
                    properties:
                      purchase_order_line_id:
                        type: integer
                      product_id:
                        type: integer
                      description:
                        type: string
                      quantity:
                        type: integer
                      unit_cost:
                        type: number
                      amount:
                        type: integer
                      nominal_code_id:
                        type: string
                        nullable: true
                      is_product:
                        type: boolean
                      restock_inventory:
                        type: boolean
              example:
                extraction_id: 12
                line_mode: replace
                supplier_reference: CM-10422
                supplier_po_number: '001'
                vendor_credit_number: 0001669
                credit_date: '2026-05-28'
                vendor_credit_note: Updated from OCR extraction CM-10422.
                lines:
                - purchase_order_line_id: 101
                  product_id: 555
                  description: Blue Widget - damaged in transit
                  quantity: 4
                  unit_cost: 12.5
                  amount: 50
                  nominal_code_id: null
                  is_product: true
                  restock_inventory: false
      parameters:
      - name: vendorCredit
        in: path
        schema:
          type: integer
        required: true
        description: Vendor credit ID
        example: '12'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      vendor_credit_id:
                        type: integer
                      extraction_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    vendor_credit_id: 311
                    extraction_id: 12
                  message: OCR results applied to vendor credit.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      extraction_id:
                        type: array
                        items:
                          type: string
                example:
                  message: An OCR extraction is required to apply results.
                  errors:
                    extraction_id:
                    - An OCR extraction is required to apply results.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: accounting:write
      operationId: post-api-vendor-credits-vendorcredit-ocr-apply
  /api/vendor-credits/ocr/{extraction}/reclassify-as-invoice:
    post:
      tags:
      - Vendor Credits
      summary: Reclassify as Supplier Invoice
      description: 'Reclassify a vendor credit extraction as a supplier invoice extraction
        — used when the scanned document turns out to be an invoice, not a credit
        memo. The vendor credit extraction is converted and a purchase invoice extraction
        is returned. No request body. Returns 422 if the extraction is already confirmed.


        :::info[Required scope: `orders:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Returns 422 if the extraction is confirmed or not in a reviewable status (pending
        review / duplicate detected).'
      requestBody:
        content: {}
      parameters:
      - name: extraction
        in: path
        schema:
          type: integer
        required: true
        description: Vendor credit OCR extraction ID
        example: '12'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      purchase_invoice_extraction_id:
                        type: integer
                example:
                  message: Reclassified as supplier invoice.
                  data:
                    purchase_invoice_extraction_id: 88
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 422 Confirmed Extraction
                  value:
                    message: Confirmed extractions cannot be reclassified.
                example-1:
                  summary: 422 Not Pending Review
                  value:
                    message: Only extractions pending review can be reclassified.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: orders:write
      operationId: post-api-vendor-credits-ocr-extraction-reclassify-as-invoice
  /api/vendor-credits/{vendorCredit}/attachments/{attachment}/ocr:
    post:
      tags:
      - Vendor Credits
      summary: Scan Attachment with OCR
      description: 'Trigger OCR processing for an existing vendor credit attachment.
        Only PDF attachments can be scanned (422 for other MIME types). Asynchronous
        — returns a tracked_job_log_id for the tracked job log endpoints. Returns
        404 if the attachment does not belong to the vendor credit, and 422 if Vendor
        Credit OCR is not enabled in Settings → Invoice OCR.


        :::info[Required scope: `accounting:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters:
      - name: vendorCredit
        in: path
        schema:
          type: integer
        required: true
        description: Vendor credit ID
        example: '12'
      - name: attachment
        in: path
        schema:
          type: integer
        required: true
        description: Vendor credit attachment ID
        example: '5'
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      extraction_id:
                        type: integer
                      tracked_job_log_id:
                        type: integer
                      attachment_id:
                        type: integer
                      status:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    extraction_id: 12
                    tracked_job_log_id: 3301
                    attachment_id: 5
                    status: processing
                  message: OCR processing started
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Only PDF files can be scanned.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: accounting:write
      operationId: post-api-vendor-credits-vendorcredit-attachments-attachment-ocr
    get:
      tags:
      - Vendor Credits
      summary: Get Latest Attachment Extraction
      description: 'Get the latest OCR extraction for a vendor credit attachment,
        including extracted header, matched lines, and related records. Returns data:
        null (200) when the attachment has never been scanned. Returns 404 if the
        attachment does not belong to the vendor credit.


        :::info[Required scope: `accounting:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        **Classification fields:** `document_type` (`credit_memo` | `invoice` | `unknown`),
        `detection_signals` (array of raw classifier signals, e.g. `keyword:credit
        memo`, `doc_number:CM prefix`, `total:negative`; `null` when not classified)
        and `auto_routed` (`true` when the document arrived via the supplier-invoice
        intake and was automatically routed to the credit memo queue by the document
        type classifier).'
      parameters:
      - name: vendorCredit
        in: path
        schema:
          type: integer
        required: true
        description: Vendor credit ID
        example: '12'
      - name: attachment
        in: path
        schema:
          type: integer
        required: true
        description: Vendor credit attachment ID
        example: '5'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 200 OK
                  value:
                    data:
                      id: 12
                      status: pending_review
                      source: upload
                      file_url: https://app.sku.io/api/vendor-credits/ocr/12/pdf
                      file_name: credit-memo-acme.pdf
                      page_count: 2
                      header:
                        credit_number: CM-10422
                        credit_date: '2026-05-28'
                        supplier_name: Acme Supply Co
                        total: 65
                        subtotal: 65
                        tax_amount: 0
                        currency_code: USD
                        po_number: PO-2026-0144
                        document_type: credit_memo
                        matched_supplier_id: 7
                        matched_supplier_name: Acme Supply Co
                        matched_purchase_order_id: 144
                        matched_purchase_order_number: PO-2026-0144
                      is_matched_supplier: true
                      extracted_supplier_name: Acme Supply Co
                      lines:
                      - id: f4f0c2ab-9a31-4a2e-8f0a-3d7e1f0b6c11
                        description: Blue Widget - damaged in transit
                        qty: 4
                        unit_price: 12.5
                        line_total: 50
                        confidence: 0.96
                        raw_sku: WIDGET-BLU
                        match_status: exact
                        matched_product_id: 555
                        matched_product_name: Blue Widget
                        matched_product_sku: WIDGET-BLU
                        saved_financial_line_type_id: null
                        discount_variance: null
                        po_expected_discount: null
                      - id: 0b2a6f7e-2c44-49d2-9a18-77c1f3a9e802
                        description: Freight rebate
                        qty: 1
                        unit_price: 15
                        line_total: 15
                        confidence: 0.91
                        raw_sku: null
                        match_status: unmatched
                        matched_product_id: null
                        matched_product_name: null
                        matched_product_sku: null
                        saved_financial_line_type_id: null
                        discount_variance: null
                        po_expected_discount: null
                      azure_cost_usd: 0.02
                      confidence_score: 0.94
                      error_message: null
                      document_type: credit_memo
                      detection_signals:
                      - keyword:credit memo
                      - total:negative
                      auto_routed: true
                      vendor_credit_id: null
                      vendor_credit_attachment_id: null
                      tracked_job_log_id: 3301
                      supplier:
                        id: 7
                        name: Acme Supply Co
                      purchase_order:
                        id: 144
                        purchase_order_number: PO-2026-0144
                        purchase_order_date: '2026-04-02'
                      duplicate_vendor_credit: null
                      referenced_purchase_invoice: null
                      candidate_purchase_orders:
                      - id: 144
                        purchase_order_number: PO-2026-0144
                        purchase_order_date: '2026-04-02'
                        order_status: received
                      created_at: '2026-06-01T14:22:08.000000Z'
                example-1:
                  summary: 200 OK (never scanned)
                  value:
                    data: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: accounting:read
      operationId: get-api-vendor-credits-vendorcredit-attachments-attachment-ocr
  /api/vendor-credits/list/export:
    get:
      tags:
      - Vendor Credits
      summary: Export Vendor Credits
      description: 'Download an Excel/CSV export of vendor credits.


        :::info[Required scope: `accounting:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Response: a binary file download (xlsx or csv), NOT JSON. Columns: ID, Credit
        #, Supplier Ref, Supplier, PO #, Credit Date, Status, Payment Status, Warehouse,
        Currency, Tax Total, Total Credit, Allocated, Refunded, Remaining, Settled,
        Note, Created At.


        Query params:

        - format: xlsx (default) or csv

        - scope: ''filtered'' (default — respects the same filters as the list endpoint)
        or ''selected''

        - ids: comma-separated IDs (only when scope=selected)'
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: accounting:read
      operationId: get-api-vendor-credits-list-export
  /api/vendor-credits/import/template:
    get:
      tags:
      - Vendor Credits
      summary: Download Vendor Credit Import Template
      description: 'Download a multi-sheet XLSX import template pre-filled with sample
        rows, a field guide, and reference data (stores, currencies, warehouses, tax
        rates, nominal codes, suppliers) from your account.


        :::info[Required scope: `accounting:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Response: a binary XLSX file download, NOT JSON. Use this template as the
        starting point for the import — fill the ''Import Here'' sheet, then upload
        it in the import wizard.'
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: accounting:read
      operationId: get-api-vendor-credits-import-template
  /api/vendor-credits/import/validate:
    post:
      tags:
      - Vendor Credits
      summary: Validate Vendor Credit Import
      description: 'Validate and preview mapped import rows BEFORE importing. No database
        writes occur — safe to call repeatedly.


        :::info[Required scope: `accounting:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Resolves supplier / purchase order / store / currency / warehouse / SKU /
        nominal code / tax rate names to IDs, groups flat rows into credits (by id,
        then vendor_credit_number, then purchase_order_number), and computes an upsert
        action per credit:

        - create: no existing credit matched

        - update: matched an existing DRAFT credit

        - blocked: matched a credit that cannot be updated (archived, voided, closed,
        refunded, allocated, or already authorized/open). The block_reason is returned
        for display.


        Each row accepts all template columns: id, vendor_credit_number, credit_date,
        purchase_order_number, supplier_name, supplier_email, supplier_id, warehouse_name,
        currency_code, store_name, supplier_reference, vendor_credit_note, sku, purchase_order_line_id,
        description, quantity, amount, unit_cost, nominal_code, tax_rate, is_product,
        restock_inventory.


        Max 50000 rows per call.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                rows:
                  type: array
                  items:
                    type: object
                    properties:
                      id:
                        type: string
                      vendor_credit_number:
                        type: string
                      credit_date:
                        type: string
                      purchase_order_number:
                        type: string
                      supplier_name:
                        type: string
                      supplier_email:
                        type: string
                      supplier_id:
                        type: string
                      warehouse_name:
                        type: string
                      currency_code:
                        type: string
                      store_name:
                        type: string
                      supplier_reference:
                        type: string
                      vendor_credit_note:
                        type: string
                      sku:
                        type: string
                      purchase_order_line_id:
                        type: string
                      description:
                        type: string
                      quantity:
                        type: string
                      amount:
                        type: string
                      unit_cost:
                        type: string
                      nominal_code:
                        type: string
                      tax_rate:
                        type: string
                      is_product:
                        type: string
                      restock_inventory:
                        type: string
              example:
                rows:
                - id: ''
                  vendor_credit_number: VC-001
                  credit_date: '2026-04-01'
                  purchase_order_number: ''
                  supplier_name: Acme Supplies
                  supplier_email: ''
                  supplier_id: ''
                  warehouse_name: Main Warehouse
                  currency_code: USD
                  store_name: ''
                  supplier_reference: CN-55321
                  vendor_credit_note: Damaged on arrival
                  sku: WIDGET-001
                  purchase_order_line_id: ''
                  description: Blue Widget - Large
                  quantity: '2'
                  amount: '19.99'
                  unit_cost: ''
                  nominal_code: ''
                  tax_rate: ''
                  is_product: 'true'
                  restock_inventory: 'false'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  vendor_credits:
                    type: array
                    items:
                      type: object
                      properties:
                        group_key:
                          type: string
                        id:
                          type: string
                          nullable: true
                        vendor_credit_number:
                          type: string
                        credit_date:
                          type: string
                        supplier_reference:
                          type: string
                        vendor_credit_note:
                          type: string
                        action:
                          type: string
                        match_reason:
                          type: string
                          nullable: true
                        block_reason:
                          type: string
                          nullable: true
                        existing_vendor_credit:
                          type: string
                          nullable: true
                        purchase_order:
                          type: string
                          nullable: true
                        supplier:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            email:
                              type: string
                        store:
                          type: string
                          nullable: true
                        currency:
                          type: object
                          properties:
                            id:
                              type: integer
                            code:
                              type: string
                        warehouse:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        errors:
                          type: array
                        lines:
                          type: array
                          items:
                            type: object
                            properties:
                              sku:
                                type: string
                              product_id:
                                type: integer
                              product_name:
                                type: string
                              purchase_order_line_id:
                                type: string
                                nullable: true
                              description:
                                type: string
                              quantity:
                                type: integer
                              amount:
                                type: number
                              unit_cost:
                                type: string
                                nullable: true
                              nominal_code_id:
                                type: string
                                nullable: true
                              tax_rate_id:
                                type: string
                                nullable: true
                              is_product:
                                type: boolean
                              restock_inventory:
                                type: boolean
                              line_total:
                                type: number
                              errors:
                                type: array
                        total_quantity:
                          type: integer
                        total_amount:
                          type: number
                  summary:
                    type: object
                    properties:
                      total_vendor_credits:
                        type: integer
                      total_line_items:
                        type: integer
                      total_errors:
                        type: integer
                      total_will_create:
                        type: integer
                      total_will_update:
                        type: integer
                      total_blocked:
                        type: integer
                example:
                  vendor_credits:
                  - group_key: vcn:vc-001
                    id: null
                    vendor_credit_number: VC-001
                    credit_date: '2026-04-01'
                    supplier_reference: CN-55321
                    vendor_credit_note: Damaged on arrival
                    action: create
                    match_reason: null
                    block_reason: null
                    existing_vendor_credit: null
                    purchase_order: null
                    supplier:
                      id: 12
                      name: Acme Supplies
                      email: orders@acme.com
                    store: null
                    currency:
                      id: 1
                      code: USD
                    warehouse:
                      id: 3
                      name: Main Warehouse
                    errors: []
                    lines:
                    - sku: WIDGET-001
                      product_id: 845
                      product_name: Blue Widget - Large
                      purchase_order_line_id: null
                      description: Blue Widget - Large
                      quantity: 2
                      amount: 19.99
                      unit_cost: null
                      nominal_code_id: null
                      tax_rate_id: null
                      is_product: true
                      restock_inventory: false
                      line_total: 39.98
                      errors: []
                    total_quantity: 2
                    total_amount: 39.98
                  summary:
                    total_vendor_credits: 1
                    total_line_items: 1
                    total_errors: 0
                    total_will_create: 1
                    total_will_update: 0
                    total_blocked: 0
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: accounting:write
      operationId: post-api-vendor-credits-import-validate
  /api/vendor-credits/import:
    post:
      tags:
      - Vendor Credits
      summary: Import Vendor Credits
      description: 'Execute the import — upsert vendor credits from validated data
        (typically the output of the Validate Import endpoint).


        :::info[Required scope: `accounting:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Authentication: Requires Bearer token.


        Upsert behavior:

        - Rows with no matched existing credit are CREATED in DRAFT status so you
        can review and authorize them.

        - Rows matching an existing DRAFT credit are UPDATED.

        - Rows with action=blocked are rejected (archived / voided / closed / refunded
        / allocated / already-authorized credits cannot be updated via import).


        continue_on_error (default false): when true, each credit is imported in its
        own transaction and failures are collected into ''skipped'' instead of aborting
        the whole import. When false, the entire import runs in one transaction and
        any failure rolls everything back.


        A per-user lock serializes concurrent imports.


        Returns 201 when any credit was created, otherwise 200.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                continue_on_error:
                  type: boolean
                vendor_credits:
                  type: array
                  items:
                    type: object
                    properties:
                      group_key:
                        type: string
                      id:
                        type: string
                        nullable: true
                      action:
                        type: string
                      match_reason:
                        type: string
                        nullable: true
                      block_reason:
                        type: string
                        nullable: true
                      existing_vendor_credit:
                        type: string
                        nullable: true
                      vendor_credit_number:
                        type: string
                      credit_date:
                        type: string
                      supplier_reference:
                        type: string
                      vendor_credit_note:
                        type: string
                      purchase_order:
                        type: string
                        nullable: true
                      supplier:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          email:
                            type: string
                      store:
                        type: string
                        nullable: true
                      currency:
                        type: object
                        properties:
                          id:
                            type: integer
                          code:
                            type: string
                      warehouse:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      lines:
                        type: array
                        items:
                          type: object
                          properties:
                            sku:
                              type: string
                            product_id:
                              type: integer
                            product_name:
                              type: string
                            purchase_order_line_id:
                              type: string
                              nullable: true
                            description:
                              type: string
                            quantity:
                              type: integer
                            amount:
                              type: number
                            unit_cost:
                              type: string
                              nullable: true
                            nominal_code_id:
                              type: string
                              nullable: true
                            tax_rate_id:
                              type: string
                              nullable: true
                            is_product:
                              type: boolean
                            restock_inventory:
                              type: boolean
              example:
                continue_on_error: false
                vendor_credits:
                - group_key: vcn:vc-001
                  id: null
                  action: create
                  match_reason: null
                  block_reason: null
                  existing_vendor_credit: null
                  vendor_credit_number: VC-001
                  credit_date: '2026-04-01'
                  supplier_reference: CN-55321
                  vendor_credit_note: Damaged on arrival
                  purchase_order: null
                  supplier:
                    id: 12
                    name: Acme Supplies
                    email: orders@acme.com
                  store: null
                  currency:
                    id: 1
                    code: USD
                  warehouse:
                    id: 3
                    name: Main Warehouse
                  lines:
                  - sku: WIDGET-001
                    product_id: 845
                    product_name: Blue Widget - Large
                    purchase_order_line_id: null
                    description: Blue Widget - Large
                    quantity: 2
                    amount: 19.99
                    unit_cost: null
                    nominal_code_id: null
                    tax_rate_id: null
                    is_product: true
                    restock_inventory: false
      parameters: []
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  created:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        vendor_credit_number:
                          type: string
                  updated:
                    type: array
                  skipped:
                    type: array
                  summary:
                    type: object
                    properties:
                      total:
                        type: integer
                      created:
                        type: integer
                      updated:
                        type: integer
                      skipped:
                        type: integer
                example:
                  created:
                  - id: 501
                    vendor_credit_number: VC-001
                  updated: []
                  skipped: []
                  summary:
                    total: 1
                    created: 1
                    updated: 0
                    skipped: 0
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 'Import failed: Vendor credit #VC-009 is voided and cannot
                    be updated via import.'
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: accounting:write
      operationId: post-api-vendor-credits-import
  /api/vendor-deposits:
    get:
      tags:
      - Vendor Deposits
      summary: List Vendor Deposits
      description: 'Paginated list of vendor deposits. Supports Spatie QueryBuilder
        filters and sorting.


        :::info[Required scope: `accounting:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        **Note:** bank details are omitted from list responses — `payee_bank_details`
        and `supplier.wire_instructions` are only returned by detail-type endpoints
        (show, action responses).


        Each deposit includes `attachments_count` (number of attached documents) and
        `attachment_filenames` (their file names). Sortable by `attachments_count`.
        Filter with `filter[attachments_count]` (e.g. `filter[attachments_count.is]=0`
        for deposits with no documents) or `filter[attachment_filename]` to match
        an attached document''s file name.'
      parameters:
      - name: page
        in: query
        schema:
          type: integer
        example: '1'
        description: Page number (default 1).
      - name: per_page
        in: query
        schema:
          type: integer
        example: '15'
        description: Results per page (default 10).
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: accounting:read
      operationId: get-api-vendor-deposits
    post:
      tags:
      - Vendor Deposits
      summary: Create Vendor Deposit
      description: 'Create a new vendor deposit. Validated by CreateVendorDepositRequest.
        Returns 201 with the created deposit.


        :::info[Required scope: `accounting:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        **Proforma invoice / payment request fields:**

        - `payee_bank_details` (string, nullable, max 2000) — payee bank block captured
        from the supplier''s proforma invoice. If it matches the supplier profile''s
        `wire_instructions` (case/whitespace-insensitive) it is normalized to `null`
        ("per supplier profile").

        - `bank_details_verified` (boolean, default false) — acknowledgment that details
        differing from the supplier profile were verified out-of-band. When true (and
        a differing snapshot is present), `bank_details_verified_at`/`bank_details_verified_by`
        are stamped. A deposit with an UNVERIFIED differing snapshot saves as draft
        but cannot be submitted for approval (422).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                supplier_id:
                  type: integer
                purchase_order_id:
                  type: string
                  nullable: true
                currency_id:
                  type: integer
                currency_rate:
                  type: integer
                currency_id_tenant_snapshot:
                  type: integer
                amount:
                  type: integer
                amount_in_tenant_currency:
                  type: integer
                deposit_date:
                  type: string
                due_date:
                  type: string
                external_reference:
                  type: string
                notes:
                  type: string
                tax_amount:
                  type: integer
                tax_amount_in_tenant_currency:
                  type: integer
                tax_lines:
                  type: array
                payee_bank_details:
                  type: string
                bank_details_verified:
                  type: boolean
              example:
                supplier_id: 1
                purchase_order_id: null
                currency_id: 1
                currency_rate: 1
                currency_id_tenant_snapshot: 1
                amount: 500
                amount_in_tenant_currency: 500
                deposit_date: '2026-04-12'
                due_date: '2026-05-12'
                external_reference: WIRE-2026-0001
                notes: 50% upfront deposit
                tax_amount: 0
                tax_amount_in_tenant_currency: 0
                tax_lines: []
                payee_bank_details: 'Bank of East Asia, Hong Kong

                  SWIFT: BEASHKHH

                  Account: 01551468050442

                  Beneficiary: Example Trading Co., Limited'
                bank_details_verified: true
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: accounting:write
      operationId: post-api-vendor-deposits
  /api/vendor-deposits/{vendorDepositId}:
    get:
      tags:
      - Vendor Deposits
      summary: Get Vendor Deposit
      description: 'Retrieve a single vendor deposit with its relations (supplier,
        purchase order, payments, applications, refunds).


        :::info[Required scope: `accounting:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: vendorDepositId
        in: path
        schema:
          type: string
        required: true
        description: The vendor deposit ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: accounting:read
      operationId: get-api-vendor-deposits-vendordepositid
    put:
      tags:
      - Vendor Deposits
      summary: Update Vendor Deposit
      description: 'Update a vendor deposit. All fields are optional (`sometimes`).


        :::info[Required scope: `accounting:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        **Editability by status:** draft and pending-approval deposits accept the
        full field set. Approved/paid/applied deposits accept only the descriptive
        fields — `deposit_date`, `due_date`, `external_reference`, `notes`; sending
        any other field returns 422 with the locked field(s) named. Terminal deposits
        (cancelled, void, refunded, written off) cannot be updated at all.


        **Bank details:** `payee_bank_details` may be updated on draft/pending deposits.
        Changing the snapshot without `bank_details_verified: true` clears the verification
        stamps — the deposit must then be re-verified before submit-for-approval succeeds.
        Details matching the supplier profile collapse to null.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                amount:
                  type: integer
                deposit_date:
                  type: string
                due_date:
                  type: string
                external_reference:
                  type: string
                notes:
                  type: string
                payee_bank_details:
                  type: string
                bank_details_verified:
                  type: boolean
              example:
                amount: 600
                deposit_date: '2026-04-12'
                due_date: '2026-05-30'
                external_reference: WIRE-2026-0001-REV
                notes: Revised deposit amount
                payee_bank_details: 'Bank: Different Bank

                  Account: 11112222'
                bank_details_verified: false
      parameters:
      - name: vendorDepositId
        in: path
        schema:
          type: string
        required: true
        description: The vendor deposit ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: accounting:write
      operationId: put-api-vendor-deposits-vendordepositid
    delete:
      tags:
      - Vendor Deposits
      summary: Delete Vendor Deposit
      description: 'Delete a vendor deposit. Returns 204 No Content.


        :::info[Required scope: `accounting:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: vendorDepositId
        in: path
        schema:
          type: string
        required: true
        description: The vendor deposit ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: accounting:write
      operationId: delete-api-vendor-deposits-vendordepositid
  /api/vendor-deposits/payment-request-routing:
    get:
      tags:
      - Vendor Deposits
      summary: Payment Request Routing Preview
      description: 'Preview where a payment request would route before submitting.
        Drives the "Payment request will be sent to …" indicator in the Record Proforma
        Invoice drawer and the draft-deposit hint.


        :::info[Required scope: `accounting:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        **Routing precedence:** matching approval levels → the site-wide default payer
        (AccountingSettings.vendor_deposit_default_payer_user_id, set in Accounting
        Settings) → the legacy amount threshold.


        **Response fields:**

        - `mode` — `approval_levels` | `payer` | `self_payer` | `threshold_approval`
        | `auto_approve`

        - `payer` — `{id, name, email}` of the resolved site-wide payer, or null

        - `payer_configured` — true when a payer id is configured even if unresolvable
        (admins are notified in that case)

        - `levels_count` — matching approval levels when mode=approval_levels


        `auto_approve` means nothing is configured: submitting will auto-approve without
        notifying anyone — the UI warns and links to Accounting Settings.


        `self_payer` means the acting user is themselves the configured payer: there
        is no one to send a request to, so submitting approves the deposit immediately
        and the payment can be recorded directly.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            text/plain:
              schema:
                type: string
              examples:
                example-0:
                  summary: 200 OK — routed to the configured payer
                  value:
                    mode: payer
                    payer:
                      id: 3
                      name: Kalvin M.
                      email: kalvin@example.com
                    payer_configured: true
                    levels_count: 0
                example-1:
                  summary: 200 OK — nothing configured (auto-approve warning)
                  value:
                    mode: auto_approve
                    payer: null
                    payer_configured: false
                    levels_count: 0
            application/json:
              schema:
                type: object
                properties:
                  mode:
                    type: string
                  payer:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      email:
                        type: string
                  payer_configured:
                    type: boolean
                  levels_count:
                    type: integer
                example:
                  mode: self_payer
                  payer:
                    id: 3
                    name: Kalvin M.
                    email: kalvin@example.com
                  payer_configured: true
                  levels_count: 0
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: accounting:read
      operationId: get-api-vendor-deposits-payment-request-routing
  /api/vendor-deposits/{vendorDepositId}/submit-for-approval:
    post:
      tags:
      - Vendor Deposits
      summary: Submit Vendor Deposit for Approval
      description: 'Submit a draft deposit for payment approval.


        :::info[Required scope: `accounting:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        **Routing precedence:** matching approval levels → the configured default
        payer → the amount threshold → auto-approve.


        - **Approval levels match** — the deposit enters the approval chain (status
        `pending_approval`).

        - **A default payer is configured** — the payment request is sent to that
        payer (status `pending_approval`).

        - **The acting user IS the configured payer** — there is no one to send a
        request to, so the deposit is approved immediately (status `approved`) and
        a payment can be recorded right away.

        - **Nothing configured** — submission auto-approves without notifying anyone.


        Deposits whose payee bank details differ from the supplier profile must have
        those details verified before submission.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties: {}
              example: {}
      parameters:
      - name: vendorDepositId
        in: path
        schema:
          type: string
        required: true
        description: The vendor deposit ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: accounting:write
      operationId: post-api-vendor-deposits-vendordepositid-submit-for-approval
  /api/vendor-deposits/{vendorDepositId}/approve:
    post:
      tags:
      - Vendor Deposits
      summary: Approve Vendor Deposit
      description: 'Approve a pending deposit.


        :::info[Required scope: `accounting:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties: {}
              example: {}
      parameters:
      - name: vendorDepositId
        in: path
        schema:
          type: string
        required: true
        description: The vendor deposit ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: accounting:write
      operationId: post-api-vendor-deposits-vendordepositid-approve
  /api/vendor-deposits/{vendorDepositId}/approve-only:
    post:
      tags:
      - Vendor Deposits
      summary: Approve Vendor Deposit (Without Payment)
      description: 'Approve a deposit without recording a payment. Status becomes
        APPROVED; amount_paid is unchanged. Use this when payment will be recorded
        later via /payments.


        :::info[Required scope: `accounting:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties: {}
              example: {}
      parameters:
      - name: vendorDepositId
        in: path
        schema:
          type: string
        required: true
        description: The vendor deposit ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: accounting:write
      operationId: post-api-vendor-deposits-vendordepositid-approve-only
  /api/vendor-deposits/{vendorDepositId}/reject:
    post:
      tags:
      - Vendor Deposits
      summary: Reject Vendor Deposit
      description: 'Reject a pending deposit with an optional reason.


        :::info[Required scope: `accounting:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                reason:
                  type: string
              example:
                reason: Incorrect supplier
      parameters:
      - name: vendorDepositId
        in: path
        schema:
          type: string
        required: true
        description: The vendor deposit ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: accounting:write
      operationId: post-api-vendor-deposits-vendordepositid-reject
  /api/vendor-deposits/{vendorDepositId}/cancel:
    post:
      tags:
      - Vendor Deposits
      summary: Cancel Vendor Deposit
      description: 'Cancel a vendor deposit.


        :::info[Required scope: `accounting:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties: {}
              example: {}
      parameters:
      - name: vendorDepositId
        in: path
        schema:
          type: string
        required: true
        description: The vendor deposit ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: accounting:write
      operationId: post-api-vendor-deposits-vendordepositid-cancel
  /api/vendor-deposits/{vendorDepositId}/write-off:
    post:
      tags:
      - Vendor Deposits
      summary: Write Off Vendor Deposit
      description: 'Write off the remaining balance of a deposit with an optional
        reason.


        :::info[Required scope: `accounting:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                reason:
                  type: string
              example:
                reason: Unrecoverable balance
      parameters:
      - name: vendorDepositId
        in: path
        schema:
          type: string
        required: true
        description: The vendor deposit ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: accounting:write
      operationId: post-api-vendor-deposits-vendordepositid-write-off
  /api/vendor-deposits/{vendorDepositId}/duplicate:
    post:
      tags:
      - Vendor Deposits
      summary: Duplicate Vendor Deposit
      description: 'Duplicate an existing deposit. Returns 201 with the new deposit.


        :::info[Required scope: `accounting:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties: {}
              example: {}
      parameters:
      - name: vendorDepositId
        in: path
        schema:
          type: string
        required: true
        description: The vendor deposit ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: accounting:write
      operationId: post-api-vendor-deposits-vendordepositid-duplicate
  /api/vendor-deposits/{vendorDepositId}/void:
    post:
      tags:
      - Vendor Deposits
      summary: Void Vendor Deposit
      description: 'Void a vendor deposit with an optional reason. Voiding reverses
        the deposit''s accounting impact and removes it from open-liability reporting.
        Deposits with applied or refunded amounts cannot be voided.


        :::info[Required scope: `accounting:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Returns the updated deposit.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                reason:
                  type: string
              example:
                reason: Duplicate entry created in error
      parameters:
      - name: vendorDepositId
        in: path
        schema:
          type: string
        required: true
        description: The vendor deposit ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: integer
                  deposit_number:
                    type: string
                  status:
                    type: string
                  status_label:
                    type: string
                  supplier_id:
                    type: integer
                  supplier:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      email:
                        type: string
                      wire_instructions:
                        type: string
                      link_route:
                        type: string
                  purchase_order_id:
                    type: integer
                  payment_term_schedule_line_index:
                    type: integer
                  inbound_shipment_id:
                    type: string
                    nullable: true
                  payment_term_schedule_snapshot:
                    type: object
                    properties:
                      label:
                        type: string
                      trigger_event:
                        type: string
                      percentage:
                        type: integer
                  is_ownership_transfer:
                    type: boolean
                  ownership_transferred_at:
                    type: string
                    nullable: true
                  purchase_order:
                    type: object
                    properties:
                      id:
                        type: integer
                      purchase_order_number:
                        type: string
                      link_route:
                        type: string
                      link_type:
                        type: string
                      link_type_label:
                        type: string
                      link_id:
                        type: integer
                      link_reference:
                        type: string
                  currency_id:
                    type: integer
                  currency:
                    type: object
                    properties:
                      id:
                        type: integer
                      code:
                        type: string
                      symbol:
                        type: string
                  currency_rate:
                    type: integer
                  currency_id_tenant_snapshot:
                    type: integer
                  tenant_currency:
                    type: object
                    properties:
                      id:
                        type: integer
                      code:
                        type: string
                      symbol:
                        type: string
                  amount:
                    type: integer
                  amount_in_tenant_currency:
                    type: integer
                  amount_paid:
                    type: integer
                  amount_paid_in_tenant_currency:
                    type: integer
                  amount_applied:
                    type: integer
                  amount_applied_in_tenant_currency:
                    type: integer
                  amount_refunded:
                    type: integer
                  amount_refunded_in_tenant_currency:
                    type: integer
                  amount_written_off:
                    type: integer
                  amount_written_off_in_tenant_currency:
                    type: integer
                  available_balance:
                    type: integer
                  available_balance_in_tenant_currency:
                    type: integer
                  tax_amount:
                    type: integer
                  tax_amount_in_tenant_currency:
                    type: integer
                  tax_lines:
                    type: string
                    nullable: true
                  deposit_date:
                    type: string
                  due_date:
                    type: string
                  paid_at:
                    type: string
                    nullable: true
                  external_reference:
                    type: string
                  payee_bank_details:
                    type: string
                    nullable: true
                  bank_details_verified_at:
                    type: string
                    nullable: true
                  bank_details_verified_by:
                    type: string
                    nullable: true
                  bank_details_verified_by_user:
                    type: string
                    nullable: true
                  payment_requested_at:
                    type: string
                    nullable: true
                  payment_requested_by:
                    type: string
                    nullable: true
                  payment_requested_by_user:
                    type: string
                    nullable: true
                  remittance_sent_at:
                    type: string
                    nullable: true
                  notes:
                    type: string
                  proportional_apply_enabled:
                    type: boolean
                  auto_apply_enabled:
                    type: string
                    nullable: true
                  auto_apply_effective:
                    type: boolean
                  approved_by:
                    type: string
                    nullable: true
                  approver:
                    type: string
                    nullable: true
                  approved_at:
                    type: string
                    nullable: true
                  approval_notes:
                    type: string
                    nullable: true
                  submit_action:
                    type: string
                    nullable: true
                  submit_action_label:
                    type: string
                    nullable: true
                  created_by:
                    type: integer
                  creator:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                  applications:
                    type: array
                  payments:
                    type: array
                  refunds:
                    type: array
                  created_at:
                    type: string
                  updated_at:
                    type: string
                  archived_at:
                    type: string
                    nullable: true
                example:
                  id: 42
                  deposit_number: DEP-000042
                  status: void
                  status_label: Void
                  supplier_id: 7
                  supplier:
                    id: 7
                    name: Acme Components Ltd
                    email: accounts@acme-components.com
                    wire_instructions: Routing 026009593, account 4426123456
                    link_route: /v2/crm/suppliers/7
                  purchase_order_id: 310
                  payment_term_schedule_line_index: 1
                  inbound_shipment_id: null
                  payment_term_schedule_snapshot:
                    label: 30% deposit on order
                    trigger_event: po_approved
                    percentage: 30
                  is_ownership_transfer: false
                  ownership_transferred_at: null
                  purchase_order:
                    id: 310
                    purchase_order_number: PO-000310
                    link_route: /v2/orders/purchase-orders/310
                    link_type: App\Models\PurchaseOrder
                    link_type_label: Purchase Order
                    link_id: 310
                    link_reference: PO-000310
                  currency_id: 1
                  currency:
                    id: 1
                    code: USD
                    symbol: $
                  currency_rate: 1
                  currency_id_tenant_snapshot: 1
                  tenant_currency:
                    id: 1
                    code: USD
                    symbol: $
                  amount: 1500
                  amount_in_tenant_currency: 1500
                  amount_paid: 0
                  amount_paid_in_tenant_currency: 0
                  amount_applied: 0
                  amount_applied_in_tenant_currency: 0
                  amount_refunded: 0
                  amount_refunded_in_tenant_currency: 0
                  amount_written_off: 0
                  amount_written_off_in_tenant_currency: 0
                  available_balance: 0
                  available_balance_in_tenant_currency: 0
                  tax_amount: 0
                  tax_amount_in_tenant_currency: 0
                  tax_lines: null
                  deposit_date: '2026-06-15'
                  due_date: '2026-07-20'
                  paid_at: null
                  external_reference: WIRE-20260615-042
                  payee_bank_details: null
                  bank_details_verified_at: null
                  bank_details_verified_by: null
                  bank_details_verified_by_user: null
                  payment_requested_at: null
                  payment_requested_by: null
                  payment_requested_by_user: null
                  remittance_sent_at: null
                  notes: 30% deposit for PO-000310
                  proportional_apply_enabled: false
                  auto_apply_enabled: null
                  auto_apply_effective: true
                  approved_by: null
                  approver: null
                  approved_at: null
                  approval_notes: null
                  submit_action: null
                  submit_action_label: null
                  created_by: 3
                  creator:
                    id: 3
                    name: Jane Operator
                  applications: []
                  payments: []
                  refunds: []
                  created_at: '2026-06-15T14:02:11+00:00'
                  updated_at: '2026-07-01T09:30:00+00:00'
                  archived_at: null
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: Deposit has applied amounts and cannot be voided.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: accounting:write
      operationId: post-api-vendor-deposits-vendordepositid-void
  /api/vendor-deposits/{vendorDepositId}/revert-to-draft:
    post:
      tags:
      - Vendor Deposits
      summary: Revert Vendor Deposit to Draft
      description: 'Revert a submitted or approved vendor deposit back to draft with
        an optional reason. Any pending approval chain is discarded so a resubmission
        rebuilds it from scratch.


        :::info[Required scope: `accounting:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Returns the updated deposit.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                reason:
                  type: string
              example:
                reason: Amount needs to be corrected before payment
      parameters:
      - name: vendorDepositId
        in: path
        schema:
          type: string
        required: true
        description: The vendor deposit ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: integer
                  deposit_number:
                    type: string
                  status:
                    type: string
                  status_label:
                    type: string
                  supplier_id:
                    type: integer
                  supplier:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      email:
                        type: string
                      wire_instructions:
                        type: string
                      link_route:
                        type: string
                  purchase_order_id:
                    type: integer
                  payment_term_schedule_line_index:
                    type: integer
                  inbound_shipment_id:
                    type: string
                    nullable: true
                  payment_term_schedule_snapshot:
                    type: object
                    properties:
                      label:
                        type: string
                      trigger_event:
                        type: string
                      percentage:
                        type: integer
                  is_ownership_transfer:
                    type: boolean
                  ownership_transferred_at:
                    type: string
                    nullable: true
                  purchase_order:
                    type: object
                    properties:
                      id:
                        type: integer
                      purchase_order_number:
                        type: string
                      link_route:
                        type: string
                      link_type:
                        type: string
                      link_type_label:
                        type: string
                      link_id:
                        type: integer
                      link_reference:
                        type: string
                  currency_id:
                    type: integer
                  currency:
                    type: object
                    properties:
                      id:
                        type: integer
                      code:
                        type: string
                      symbol:
                        type: string
                  currency_rate:
                    type: integer
                  currency_id_tenant_snapshot:
                    type: integer
                  tenant_currency:
                    type: object
                    properties:
                      id:
                        type: integer
                      code:
                        type: string
                      symbol:
                        type: string
                  amount:
                    type: integer
                  amount_in_tenant_currency:
                    type: integer
                  amount_paid:
                    type: integer
                  amount_paid_in_tenant_currency:
                    type: integer
                  amount_applied:
                    type: integer
                  amount_applied_in_tenant_currency:
                    type: integer
                  amount_refunded:
                    type: integer
                  amount_refunded_in_tenant_currency:
                    type: integer
                  amount_written_off:
                    type: integer
                  amount_written_off_in_tenant_currency:
                    type: integer
                  available_balance:
                    type: integer
                  available_balance_in_tenant_currency:
                    type: integer
                  tax_amount:
                    type: integer
                  tax_amount_in_tenant_currency:
                    type: integer
                  tax_lines:
                    type: string
                    nullable: true
                  deposit_date:
                    type: string
                  due_date:
                    type: string
                  paid_at:
                    type: string
                    nullable: true
                  external_reference:
                    type: string
                  payee_bank_details:
                    type: string
                    nullable: true
                  bank_details_verified_at:
                    type: string
                    nullable: true
                  bank_details_verified_by:
                    type: string
                    nullable: true
                  bank_details_verified_by_user:
                    type: string
                    nullable: true
                  payment_requested_at:
                    type: string
                    nullable: true
                  payment_requested_by:
                    type: string
                    nullable: true
                  payment_requested_by_user:
                    type: string
                    nullable: true
                  remittance_sent_at:
                    type: string
                    nullable: true
                  notes:
                    type: string
                  proportional_apply_enabled:
                    type: boolean
                  auto_apply_enabled:
                    type: string
                    nullable: true
                  auto_apply_effective:
                    type: boolean
                  approved_by:
                    type: string
                    nullable: true
                  approver:
                    type: string
                    nullable: true
                  approved_at:
                    type: string
                    nullable: true
                  approval_notes:
                    type: string
                    nullable: true
                  submit_action:
                    type: string
                  submit_action_label:
                    type: string
                  created_by:
                    type: integer
                  creator:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                  applications:
                    type: array
                  payments:
                    type: array
                  refunds:
                    type: array
                  created_at:
                    type: string
                  updated_at:
                    type: string
                  archived_at:
                    type: string
                    nullable: true
                example:
                  id: 42
                  deposit_number: DEP-000042
                  status: draft
                  status_label: Draft
                  supplier_id: 7
                  supplier:
                    id: 7
                    name: Acme Components Ltd
                    email: accounts@acme-components.com
                    wire_instructions: Routing 026009593, account 4426123456
                    link_route: /v2/crm/suppliers/7
                  purchase_order_id: 310
                  payment_term_schedule_line_index: 1
                  inbound_shipment_id: null
                  payment_term_schedule_snapshot:
                    label: 30% deposit on order
                    trigger_event: po_approved
                    percentage: 30
                  is_ownership_transfer: false
                  ownership_transferred_at: null
                  purchase_order:
                    id: 310
                    purchase_order_number: PO-000310
                    link_route: /v2/orders/purchase-orders/310
                    link_type: App\Models\PurchaseOrder
                    link_type_label: Purchase Order
                    link_id: 310
                    link_reference: PO-000310
                  currency_id: 1
                  currency:
                    id: 1
                    code: USD
                    symbol: $
                  currency_rate: 1
                  currency_id_tenant_snapshot: 1
                  tenant_currency:
                    id: 1
                    code: USD
                    symbol: $
                  amount: 1500
                  amount_in_tenant_currency: 1500
                  amount_paid: 0
                  amount_paid_in_tenant_currency: 0
                  amount_applied: 0
                  amount_applied_in_tenant_currency: 0
                  amount_refunded: 0
                  amount_refunded_in_tenant_currency: 0
                  amount_written_off: 0
                  amount_written_off_in_tenant_currency: 0
                  available_balance: 0
                  available_balance_in_tenant_currency: 0
                  tax_amount: 0
                  tax_amount_in_tenant_currency: 0
                  tax_lines: null
                  deposit_date: '2026-06-15'
                  due_date: '2026-07-20'
                  paid_at: null
                  external_reference: WIRE-20260615-042
                  payee_bank_details: null
                  bank_details_verified_at: null
                  bank_details_verified_by: null
                  bank_details_verified_by_user: null
                  payment_requested_at: null
                  payment_requested_by: null
                  payment_requested_by_user: null
                  remittance_sent_at: null
                  notes: 30% deposit for PO-000310
                  proportional_apply_enabled: false
                  auto_apply_enabled: null
                  auto_apply_effective: true
                  approved_by: null
                  approver: null
                  approved_at: null
                  approval_notes: null
                  submit_action: approve
                  submit_action_label: Approve Deposit
                  created_by: 3
                  creator:
                    id: 3
                    name: Jane Operator
                  applications: []
                  payments: []
                  refunds: []
                  created_at: '2026-06-15T14:02:11+00:00'
                  updated_at: '2026-07-01T09:30:00+00:00'
                  archived_at: null
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: Only submitted or approved deposits can be reverted to draft.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: accounting:write
      operationId: post-api-vendor-deposits-vendordepositid-revert-to-draft
  /api/vendor-deposits/{vendorDepositId}/purchase-order:
    put:
      tags:
      - Vendor Deposits
      summary: Link Vendor Deposit to Purchase Order
      description: 'Link a vendor deposit to a purchase order, or unlink it by passing
        null. The purchase order must belong to the same supplier as the deposit.


        :::info[Required scope: `accounting:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Returns the updated deposit.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                purchase_order_id:
                  type: integer
              example:
                purchase_order_id: 310
      parameters:
      - name: vendorDepositId
        in: path
        schema:
          type: string
        required: true
        description: The vendor deposit ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: integer
                  deposit_number:
                    type: string
                  status:
                    type: string
                  status_label:
                    type: string
                  supplier_id:
                    type: integer
                  supplier:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                      email:
                        type: string
                      wire_instructions:
                        type: string
                      link_route:
                        type: string
                  purchase_order_id:
                    type: integer
                  payment_term_schedule_line_index:
                    type: integer
                  inbound_shipment_id:
                    type: string
                    nullable: true
                  payment_term_schedule_snapshot:
                    type: object
                    properties:
                      label:
                        type: string
                      trigger_event:
                        type: string
                      percentage:
                        type: integer
                  is_ownership_transfer:
                    type: boolean
                  ownership_transferred_at:
                    type: string
                    nullable: true
                  purchase_order:
                    type: object
                    properties:
                      id:
                        type: integer
                      purchase_order_number:
                        type: string
                      link_route:
                        type: string
                      link_type:
                        type: string
                      link_type_label:
                        type: string
                      link_id:
                        type: integer
                      link_reference:
                        type: string
                  currency_id:
                    type: integer
                  currency:
                    type: object
                    properties:
                      id:
                        type: integer
                      code:
                        type: string
                      symbol:
                        type: string
                  currency_rate:
                    type: integer
                  currency_id_tenant_snapshot:
                    type: integer
                  tenant_currency:
                    type: object
                    properties:
                      id:
                        type: integer
                      code:
                        type: string
                      symbol:
                        type: string
                  amount:
                    type: integer
                  amount_in_tenant_currency:
                    type: integer
                  amount_paid:
                    type: integer
                  amount_paid_in_tenant_currency:
                    type: integer
                  amount_applied:
                    type: integer
                  amount_applied_in_tenant_currency:
                    type: integer
                  amount_refunded:
                    type: integer
                  amount_refunded_in_tenant_currency:
                    type: integer
                  amount_written_off:
                    type: integer
                  amount_written_off_in_tenant_currency:
                    type: integer
                  available_balance:
                    type: integer
                  available_balance_in_tenant_currency:
                    type: integer
                  tax_amount:
                    type: integer
                  tax_amount_in_tenant_currency:
                    type: integer
                  tax_lines:
                    type: string
                    nullable: true
                  deposit_date:
                    type: string
                  due_date:
                    type: string
                  paid_at:
                    type: string
                    nullable: true
                  external_reference:
                    type: string
                  payee_bank_details:
                    type: string
                    nullable: true
                  bank_details_verified_at:
                    type: string
                    nullable: true
                  bank_details_verified_by:
                    type: string
                    nullable: true
                  bank_details_verified_by_user:
                    type: string
                    nullable: true
                  payment_requested_at:
                    type: string
                    nullable: true
                  payment_requested_by:
                    type: string
                    nullable: true
                  payment_requested_by_user:
                    type: string
                    nullable: true
                  remittance_sent_at:
                    type: string
                    nullable: true
                  notes:
                    type: string
                  proportional_apply_enabled:
                    type: boolean
                  auto_apply_enabled:
                    type: string
                    nullable: true
                  auto_apply_effective:
                    type: boolean
                  approved_by:
                    type: string
                    nullable: true
                  approver:
                    type: string
                    nullable: true
                  approved_at:
                    type: string
                    nullable: true
                  approval_notes:
                    type: string
                    nullable: true
                  submit_action:
                    type: string
                  submit_action_label:
                    type: string
                  created_by:
                    type: integer
                  creator:
                    type: object
                    properties:
                      id:
                        type: integer
                      name:
                        type: string
                  applications:
                    type: array
                  payments:
                    type: array
                  refunds:
                    type: array
                  created_at:
                    type: string
                  updated_at:
                    type: string
                  archived_at:
                    type: string
                    nullable: true
                example:
                  id: 42
                  deposit_number: DEP-000042
                  status: draft
                  status_label: Draft
                  supplier_id: 7
                  supplier:
                    id: 7
                    name: Acme Components Ltd
                    email: accounts@acme-components.com
                    wire_instructions: Routing 026009593, account 4426123456
                    link_route: /v2/crm/suppliers/7
                  purchase_order_id: 310
                  payment_term_schedule_line_index: 1
                  inbound_shipment_id: null
                  payment_term_schedule_snapshot:
                    label: 30% deposit on order
                    trigger_event: po_approved
                    percentage: 30
                  is_ownership_transfer: false
                  ownership_transferred_at: null
                  purchase_order:
                    id: 310
                    purchase_order_number: PO-000310
                    link_route: /v2/orders/purchase-orders/310
                    link_type: App\Models\PurchaseOrder
                    link_type_label: Purchase Order
                    link_id: 310
                    link_reference: PO-000310
                  currency_id: 1
                  currency:
                    id: 1
                    code: USD
                    symbol: $
                  currency_rate: 1
                  currency_id_tenant_snapshot: 1
                  tenant_currency:
                    id: 1
                    code: USD
                    symbol: $
                  amount: 1500
                  amount_in_tenant_currency: 1500
                  amount_paid: 0
                  amount_paid_in_tenant_currency: 0
                  amount_applied: 0
                  amount_applied_in_tenant_currency: 0
                  amount_refunded: 0
                  amount_refunded_in_tenant_currency: 0
                  amount_written_off: 0
                  amount_written_off_in_tenant_currency: 0
                  available_balance: 0
                  available_balance_in_tenant_currency: 0
                  tax_amount: 0
                  tax_amount_in_tenant_currency: 0
                  tax_lines: null
                  deposit_date: '2026-06-15'
                  due_date: '2026-07-20'
                  paid_at: null
                  external_reference: WIRE-20260615-042
                  payee_bank_details: null
                  bank_details_verified_at: null
                  bank_details_verified_by: null
                  bank_details_verified_by_user: null
                  payment_requested_at: null
                  payment_requested_by: null
                  payment_requested_by_user: null
                  remittance_sent_at: null
                  notes: 30% deposit for PO-000310
                  proportional_apply_enabled: false
                  auto_apply_enabled: null
                  auto_apply_effective: true
                  approved_by: null
                  approver: null
                  approved_at: null
                  approval_notes: null
                  submit_action: approve
                  submit_action_label: Approve Deposit
                  created_by: 3
                  creator:
                    id: 3
                    name: Jane Operator
                  applications: []
                  payments: []
                  refunds: []
                  created_at: '2026-06-15T14:02:11+00:00'
                  updated_at: '2026-07-01T09:30:00+00:00'
                  archived_at: null
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      purchase_order_id:
                        type: array
                        items:
                          type: string
                example:
                  message: The selected purchase order must belong to the same supplier
                    as the vendor deposit.
                  errors:
                    purchase_order_id:
                    - The selected purchase order must belong to the same supplier
                      as the vendor deposit.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: accounting:write
      operationId: put-api-vendor-deposits-vendordepositid-purchase-order
  /api/vendor-deposits/{vendorDepositId}/approval-steps:
    get:
      tags:
      - Vendor Deposits
      summary: List Vendor Deposit Approval Steps
      description: 'List the approval chain for a vendor deposit, ordered by level.
        Each step records its approval level, assigned approver, status (pending,
        approved, or rejected), and who actioned it.


        :::info[Required scope: `accounting:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Steps are created when a deposit that crosses an approval-level threshold
        is submitted for approval.'
      parameters:
      - name: vendorDepositId
        in: path
        schema:
          type: string
        required: true
        description: The vendor deposit ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        vendor_deposit_id:
                          type: integer
                        approval_level_id:
                          type: integer
                        level_order:
                          type: integer
                        level_name:
                          type: string
                        status:
                          type: string
                        approver_user_id:
                          type: integer
                        approver_user:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            email:
                              type: string
                        actioned_by:
                          type: integer
                        actioned_by_user:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        actioned_at:
                          type: string
                        notes:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                example:
                  data:
                  - id: 11
                    vendor_deposit_id: 42
                    approval_level_id: 2
                    level_order: 1
                    level_name: Finance Review
                    status: approved
                    approver_user_id: 5
                    approver_user:
                      id: 5
                      name: Maya Finance
                      email: maya@example.com
                    actioned_by: 5
                    actioned_by_user:
                      id: 5
                      name: Maya Finance
                    actioned_at: '2026-07-07T10:12:00+00:00'
                    notes: Amount matches the PO schedule.
                    created_at: '2026-06-15T14:05:00+00:00'
                    updated_at: '2026-07-07T10:12:00+00:00'
                  - id: 12
                    vendor_deposit_id: 42
                    approval_level_id: 3
                    level_order: 2
                    level_name: CFO Sign-off
                    status: pending
                    approver_user_id: 6
                    approver_user:
                      id: 6
                      name: Sam Chief
                      email: sam@example.com
                    actioned_by: null
                    actioned_by_user: null
                    actioned_at: null
                    notes: null
                    created_at: '2026-06-15T14:05:00+00:00'
                    updated_at: '2026-06-15T14:05:00+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: accounting:read
      operationId: get-api-vendor-deposits-vendordepositid-approval-steps
  /api/vendor-deposits/{vendorDepositId}/approval-steps/approve:
    post:
      tags:
      - Vendor Deposits
      summary: Approve Vendor Deposit Approval Step
      description: 'Approve the next pending approval step on a vendor deposit, with
        optional notes (max 1000 characters). Only the step''s assigned approver may
        action it. When the final step is approved the deposit transitions to approved.


        :::info[Required scope: `accounting:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Fails when there are no pending steps, when the caller is not the assigned
        approver, or when the deposit''s bank details differ from the supplier profile
        and have not been verified.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                notes:
                  type: string
              example:
                notes: Amount matches the PO schedule.
      parameters:
      - name: vendorDepositId
        in: path
        schema:
          type: string
        required: true
        description: The vendor deposit ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      vendor_deposit_id:
                        type: integer
                      approval_level_id:
                        type: integer
                      level_order:
                        type: integer
                      level_name:
                        type: string
                      status:
                        type: string
                      approver_user_id:
                        type: integer
                      approver_user:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          email:
                            type: string
                      actioned_by:
                        type: integer
                      actioned_by_user:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      actioned_at:
                        type: string
                      notes:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 11
                    vendor_deposit_id: 42
                    approval_level_id: 2
                    level_order: 1
                    level_name: Finance Review
                    status: approved
                    approver_user_id: 5
                    approver_user:
                      id: 5
                      name: Maya Finance
                      email: maya@example.com
                    actioned_by: 5
                    actioned_by_user:
                      id: 5
                      name: Maya Finance
                    actioned_at: '2026-07-07T10:12:00+00:00'
                    notes: Amount matches the PO schedule.
                    created_at: '2026-06-15T14:05:00+00:00'
                    updated_at: '2026-07-07T10:12:00+00:00'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: No pending approval steps found for this deposit.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: accounting:write
      operationId: post-api-vendor-deposits-vendordepositid-approval-steps-approve
  /api/vendor-deposits/{vendorDepositId}/approval-steps/reject:
    post:
      tags:
      - Vendor Deposits
      summary: Reject Vendor Deposit Approval Step
      description: 'Reject the deposit at the next pending approval step, with optional
        notes (max 1000 characters). Only the step''s assigned approver may action
        it. Rejection transitions the deposit back to draft.


        :::info[Required scope: `accounting:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                notes:
                  type: string
              example:
                notes: Deposit percentage does not match the agreed terms.
      parameters:
      - name: vendorDepositId
        in: path
        schema:
          type: string
        required: true
        description: The vendor deposit ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      vendor_deposit_id:
                        type: integer
                      approval_level_id:
                        type: integer
                      level_order:
                        type: integer
                      level_name:
                        type: string
                      status:
                        type: string
                      approver_user_id:
                        type: integer
                      approver_user:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          email:
                            type: string
                      actioned_by:
                        type: integer
                      actioned_by_user:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                      actioned_at:
                        type: string
                      notes:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 11
                    vendor_deposit_id: 42
                    approval_level_id: 2
                    level_order: 1
                    level_name: Finance Review
                    status: rejected
                    approver_user_id: 5
                    approver_user:
                      id: 5
                      name: Maya Finance
                      email: maya@example.com
                    actioned_by: 5
                    actioned_by_user:
                      id: 5
                      name: Maya Finance
                    actioned_at: '2026-07-07T10:12:00+00:00'
                    notes: Deposit percentage does not match the agreed terms.
                    created_at: '2026-06-15T14:05:00+00:00'
                    updated_at: '2026-06-15T14:05:00+00:00'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: No pending approval steps found for this deposit.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: accounting:write
      operationId: post-api-vendor-deposits-vendordepositid-approval-steps-reject
  /api/vendor-deposits/{vendorDepositId}/payments:
    post:
      tags:
      - Vendor Deposits
      summary: Record Payment
      description: 'Record a payment against a vendor deposit (full or partial), with
        the payment date, currency rate, and optional reference.


        :::info[Required scope: `accounting:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Payments can also be recorded on a **draft** deposit — useful for capturing
        a payment that was already made in the past. The deposit then moves directly
        to Partially Paid / Paid without a payment request or approval step.


        The payment amount cannot exceed the deposit''s outstanding balance (deposit
        amount minus payments already recorded). Deposits whose payee bank details
        differ from the supplier profile must have those details verified before payments
        can be recorded. Payments cannot be recorded against cancelled, void, refunded,
        or written-off deposits.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                amount_in_deposit_currency:
                  type: integer
                currency_rate:
                  type: integer
                payment_date:
                  type: string
                payment_method_id:
                  type: integer
                external_reference:
                  type: string
                bank_account_id:
                  type: string
                  nullable: true
                paid_externally:
                  type: boolean
              example:
                amount_in_deposit_currency: 250
                currency_rate: 1
                payment_date: '2026-04-12'
                payment_method_id: 1
                external_reference: WIRE-REF-001
                bank_account_id: null
                paid_externally: false
      parameters:
      - name: vendorDepositId
        in: path
        schema:
          type: string
        required: true
        description: The vendor deposit ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: accounting:write
      operationId: post-api-vendor-deposits-vendordepositid-payments
  /api/vendor-deposits/{vendorDepositId}/refunds:
    post:
      tags:
      - Vendor Deposits
      summary: Refund Deposit
      description: 'Refund an amount from a vendor deposit. Validated by RefundVendorDepositRequest.


        :::info[Required scope: `accounting:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                amount_in_deposit_currency:
                  type: integer
                currency_rate:
                  type: integer
                refund_date:
                  type: string
                reason:
                  type: string
                external_reference:
                  type: string
                notes:
                  type: string
              example:
                amount_in_deposit_currency: 100
                currency_rate: 1
                refund_date: '2026-04-12'
                reason: Partial refund — PO cancelled
                external_reference: RFD-0001
                notes: Returned via bank transfer
      parameters:
      - name: vendorDepositId
        in: path
        schema:
          type: string
        required: true
        description: The vendor deposit ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: accounting:write
      operationId: post-api-vendor-deposits-vendordepositid-refunds
  /api/vendor-deposits/{vendorDepositId}/send-remittance:
    post:
      tags:
      - Vendor Deposits
      summary: Send Remittance Advice
      description: 'Email a remittance advice for a paid vendor deposit to the supplier.


        :::info[Required scope: `accounting:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Sends a supplier-facing email containing the deposit reference, PO number,
        supplier reference (PI #), amount paid, payment date and payment reference
        — bank/account numbers are never included. Selected deposit attachments (e.g.
        the wire confirmation uploaded with category `payment_proof`) are attached
        to the email. Stamps `remittance_sent_at` on the deposit and returns the full
        updated deposit resource.


        **Validation (SendVendorDepositRemittanceRequest):**

        - `to` (required, email) — recipient, usually the supplier''s email

        - `cc` (optional, array of emails)

        - `subject` (required, string, max 255)

        - `note` (optional, string, max 2000) — included in the email body

        - `attachment_ids` (optional, array of integers) — must belong to this deposit,
        else 422


        **Errors (422):** deposit not yet paid (allowed statuses: partially_paid,
        paid, partially_applied, fully_applied); attachment ids not belonging to the
        deposit; validation failures.

        - attachment file missing from storage → 422 before anything is sent.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                to:
                  type: string
                cc:
                  type: array
                  items:
                    type: string
                subject:
                  type: string
                note:
                  type: string
                attachment_ids:
                  type: array
                  items:
                    type: integer
              example:
                to: accounts@supplier.example.com
                cc:
                - finance@yourcompany.example.com
                subject: Remittance Advice — VD-00012 / PO-0660
                note: Wire sent today via SWIFT; please confirm receipt.
                attachment_ids:
                - 3
      parameters:
      - name: vendorDepositId
        in: path
        schema:
          type: string
        required: true
        description: The vendor deposit ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: integer
                  deposit_number:
                    type: string
                  status:
                    type: string
                  status_label:
                    type: string
                  supplier_id:
                    type: integer
                  purchase_order_id:
                    type: integer
                  amount:
                    type: number
                  amount_paid:
                    type: number
                  external_reference:
                    type: string
                  payee_bank_details:
                    type: string
                  bank_details_verified_at:
                    type: string
                  bank_details_verified_by:
                    type: integer
                  payment_requested_at:
                    type: string
                  payment_requested_by:
                    type: integer
                  remittance_sent_at:
                    type: string
                  paid_at:
                    type: string
                example:
                  id: 12
                  deposit_number: VD-00012
                  status: paid
                  status_label: Paid
                  supplier_id: 1
                  purchase_order_id: 7
                  amount: 28147.71
                  amount_paid: 28147.71
                  external_reference: PI-2026-0630-199
                  payee_bank_details: 'Bank of East Asia, Hong Kong

                    SWIFT: BEASHKHH

                    Account: 01551468050442'
                  bank_details_verified_at: '2026-07-02T18:10:00+00:00'
                  bank_details_verified_by: 2
                  payment_requested_at: '2026-07-01T09:20:00+00:00'
                  payment_requested_by: 3
                  remittance_sent_at: '2026-07-02T19:45:12+00:00'
                  paid_at: '2026-07-02T00:00:00+00:00'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: Remittance advice can only be sent after a payment has been
                    recorded on the deposit.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: accounting:write
      operationId: post-api-vendor-deposits-vendordepositid-send-remittance
  /api/vendor-deposits/{vendorDepositId}/scan-proof:
    post:
      tags:
      - Vendor Deposits
      summary: Scan Payment Proof (OCR)
      description: 'OCR a payment-proof image/PDF (a wire confirmation or receipt)
        and return the extracted payment fields for the payer to review before recording
        the payment.


        :::info[Required scope: `accounting:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Runs the shared OCR stack — Azure Document Intelligence layout OCR + a small
        LLM extraction — and returns the fields WITHOUT persisting anything. The file
        is only stored (as a payment_proof attachment) when the payment itself is
        recorded. The Record Payment / Approve & Mark Paid dialogs use this to pre-fill
        Reference, Amount, and Date.


        **Gating & metering:** requires the tenant''s OCR setting to be enabled (Settings
        → Accounting → Invoice OCR) and Azure DI credentials configured; each scan
        is metered in the shared OCR usage log. Throttled to 20/min.


        **Body (multipart/form-data):** `file` — required image/PDF, max 10MB.


        **Errors (422):** OCR not enabled; Azure not configured; no readable text
        found; file validation.'
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                file:
                  type: string
                  description: 'The payment proof image or PDF (wire confirmation
                    / receipt). mimes: pdf,jpg,jpeg,png,gif,webp,tiff,bmp; max 10MB.'
                  format: binary
      parameters:
      - name: vendorDepositId
        in: path
        schema:
          type: string
        required: true
        description: The vendor deposit ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      reference:
                        type: string
                      amount:
                        type: number
                      currency_code:
                        type: string
                      value_date:
                        type: string
                      payee_name:
                        type: string
                example:
                  data:
                    reference: FT26183999888
                    amount: 28147.71
                    currency_code: USD
                    value_date: '2026-07-02'
                    payee_name: Pacific Rim Trading Co.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: OCR is not enabled for this account. Enable it in Settings
                    → Accounting → Invoice OCR to scan payment proofs.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: accounting:write
      operationId: post-api-vendor-deposits-vendordepositid-scan-proof
  /api/vendor-deposits/{vendorDepositId}/applications:
    post:
      tags:
      - Vendor Deposits
      summary: Apply To Purchase Invoices
      description: 'Apply deposit balance to one or more purchase invoices. Validated
        by ApplyVendorDepositRequest.


        :::info[Required scope: `accounting:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                applications:
                  type: array
                  items:
                    type: object
                    properties:
                      purchase_invoice_id:
                        type: integer
                      amount_in_deposit_currency:
                        type: integer
              example:
                applications:
                - purchase_invoice_id: 1
                  amount_in_deposit_currency: 150
                - purchase_invoice_id: 2
                  amount_in_deposit_currency: 75.5
      parameters:
      - name: vendorDepositId
        in: path
        schema:
          type: string
        required: true
        description: The vendor deposit ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: accounting:write
      operationId: post-api-vendor-deposits-vendordepositid-applications
  /api/vendor-deposit-applications/{applicationId}:
    delete:
      tags:
      - Vendor Deposits
      summary: Unapply Deposit Application
      description: 'Unapply (reverse) a previously applied deposit application. Returns
        204 No Content.


        :::warning[Not yet available to API tokens]

        This endpoint currently requires session authentication; Personal Access Token
        scope support is in progress.

        :::'
      parameters:
      - name: applicationId
        in: path
        schema:
          type: string
        required: true
        description: The application ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-session-only: true
      operationId: delete-api-vendor-deposit-applications-applicationid
  /api/vendor-deposits/{vendorDepositId}/applications/preview:
    post:
      tags:
      - Vendor Deposits
      summary: Preview Vendor Deposit Application
      description: 'Preview the effect of applying a deposit amount to a purchase
        invoice (bill) without committing anything. Returns the before/after balances
        on both the deposit and the bill, the tenant-currency amount, and any FX gain/loss
        that would be posted when the deposit and bill currencies differ.


        :::info[Required scope: `accounting:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Validation problems (deposit not applicable, supplier mismatch, amount exceeding
        the unapplied balance) are returned in the errors and warnings arrays rather
        than as an HTTP error.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                purchase_invoice_id:
                  type: integer
                amount_in_deposit_currency:
                  type: integer
              example:
                purchase_invoice_id: 88
                amount_in_deposit_currency: 500
      parameters:
      - name: vendorDepositId
        in: path
        schema:
          type: string
        required: true
        description: The vendor deposit ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      deposit_id:
                        type: integer
                      purchase_invoice_id:
                        type: integer
                      amount_in_deposit_currency:
                        type: integer
                      amount_in_tenant_currency:
                        type: integer
                      amount_at_bill_rate:
                        type: integer
                      fx_gain_loss:
                        type: integer
                      deposit_balance_before:
                        type: object
                        properties:
                          available:
                            type: integer
                          applied:
                            type: integer
                      deposit_balance_after:
                        type: object
                        properties:
                          available:
                            type: integer
                          applied:
                            type: integer
                      bill_balance_before:
                        type: object
                        properties:
                          outstanding:
                            type: integer
                          total:
                            type: integer
                          total_deposits_applied:
                            type: integer
                      bill_balance_after:
                        type: object
                        properties:
                          outstanding:
                            type: integer
                          total:
                            type: integer
                          total_deposits_applied:
                            type: integer
                      warnings:
                        type: array
                      errors:
                        type: array
                example:
                  data:
                    deposit_id: 42
                    purchase_invoice_id: 88
                    amount_in_deposit_currency: 500
                    amount_in_tenant_currency: 500
                    amount_at_bill_rate: 500
                    fx_gain_loss: 0
                    deposit_balance_before:
                      available: 1500
                      applied: 0
                    deposit_balance_after:
                      available: 1000
                      applied: 500
                    bill_balance_before:
                      outstanding: 5000
                      total: 5000
                      total_deposits_applied: 0
                    bill_balance_after:
                      outstanding: 4500
                      total: 5000
                      total_deposits_applied: 500
                    warnings: []
                    errors: []
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: accounting:write
      operationId: post-api-vendor-deposits-vendordepositid-applications-preview
  /api/vendor-deposits/{vendorDepositId}/applicable-bills:
    get:
      tags:
      - Vendor Deposits
      summary: List Applicable Bills for Vendor Deposit
      description: 'List open purchase invoices (bills) from the deposit''s supplier
        that the deposit can be applied to, including each bill''s outstanding balance
        after payments and previously applied deposits. Returns up to 100 bills.


        :::info[Required scope: `accounting:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: vendorDepositId
        in: path
        schema:
          type: string
        required: true
        description: The vendor deposit ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        purchase_invoice_number:
                          type: string
                        purchase_order_id:
                          type: integer
                        purchase_order_number:
                          type: string
                        supplier_id:
                          type: integer
                        supplier_name:
                          type: string
                        currency_code:
                          type: string
                        total:
                          type: integer
                        total_paid:
                          type: integer
                        total_deposits_applied:
                          type: integer
                        outstanding_balance:
                          type: integer
                        invoice_date:
                          type: string
                        due_date:
                          type: string
                        status:
                          type: string
                example:
                  data:
                  - id: 88
                    purchase_invoice_number: INV-2026-0088
                    purchase_order_id: 310
                    purchase_order_number: PO-000310
                    supplier_id: 7
                    supplier_name: Acme Components Ltd
                    currency_code: USD
                    total: 5000
                    total_paid: 0
                    total_deposits_applied: 1500
                    outstanding_balance: 3500
                    invoice_date: '2026-06-28'
                    due_date: '2026-07-28'
                    status: approved
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: accounting:read
      operationId: get-api-vendor-deposits-vendordepositid-applicable-bills
  /api/vendor-deposits/{vendorDepositId}/accounting:
    get:
      tags:
      - Vendor Deposits
      summary: Get Vendor Deposit Accounting Transactions
      description: 'Get the accounting transactions posted for a vendor deposit. The
        primary vendor-deposit-paid transaction is returned in data (null when none
        exists yet); application, refund, and write-off transactions are returned
        in related_transactions.


        :::info[Required scope: `accounting:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        The eligibility object indicates whether an accounting transaction can currently
        be generated for this deposit and, when it cannot, why (e.g. the Prepaid Vendor
        Deposits nominal code is not configured, or the deposit has no payments, applications,
        refunds, or write-offs to post).'
      parameters:
      - name: vendorDepositId
        in: path
        schema:
          type: string
        required: true
        description: The vendor deposit ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      transaction_date:
                        type: string
                      type:
                        type: object
                        properties:
                          name:
                            type: string
                          link_type:
                            type: string
                          link_id:
                            type: integer
                          link_type_label:
                            type: string
                          link_route:
                            type: string
                      integration_invoice_number_override:
                        type: string
                        nullable: true
                      name:
                        type: string
                      is_tax_included:
                        type: boolean
                      total:
                        type: integer
                      reference:
                        type: string
                      last_sync_error:
                        type: string
                        nullable: true
                      is_sync_enabled:
                        type: boolean
                      is_type_sync_enabled:
                        type: boolean
                      lines:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            type:
                              type: string
                            nominal_code:
                              type: object
                              properties:
                                id:
                                  type: integer
                                code:
                                  type: string
                                name:
                                  type: string
                            description:
                              type: string
                            quantity:
                              type: integer
                            amount:
                              type: integer
                            subtotal:
                              type: integer
                            tax_amount:
                              type: integer
                            created_at:
                              type: string
                            updated_at:
                              type: string
                      status:
                        type: string
                      is_locked:
                        type: boolean
                      is_batchable:
                        type: boolean
                      updated_at:
                        type: string
                      created_at:
                        type: string
                  related_transactions:
                    type: array
                  eligibility:
                    type: object
                    properties:
                      eligible:
                        type: boolean
                      reason:
                        type: string
                        nullable: true
                      settings_route:
                        type: string
                        nullable: true
                      settings_label:
                        type: string
                        nullable: true
                example:
                  data:
                    id: 501
                    transaction_date: '2026-06-15'
                    type:
                      name: vendor_deposit_paid
                      link_type: App\Models\VendorDeposit
                      link_id: 42
                      link_type_label: Vendor Deposit Paid
                      link_route: /orders/vendor-deposits/42
                    integration_invoice_number_override: null
                    name: Vendor Deposit Paid
                    is_tax_included: false
                    total: 1500
                    reference: DEP-000042
                    last_sync_error: null
                    is_sync_enabled: true
                    is_type_sync_enabled: true
                    lines:
                    - id: 9001
                      type: debit
                      nominal_code:
                        id: 21
                        code: '1350'
                        name: Prepaid Vendor Deposits
                      description: Deposit paid to Acme Components Ltd
                      quantity: 1
                      amount: 1500
                      subtotal: 1500
                      tax_amount: 0
                      created_at: '2026-06-15T14:10:00.000000Z'
                      updated_at: '2026-06-15T14:10:00.000000Z'
                    - id: 9002
                      type: credit
                      nominal_code:
                        id: 5
                        code: '1200'
                        name: Bank Account
                      description: Deposit paid to Acme Components Ltd
                      quantity: 1
                      amount: -1500
                      subtotal: -1500
                      tax_amount: 0
                      created_at: '2026-06-15T14:10:00.000000Z'
                      updated_at: '2026-06-15T14:10:00.000000Z'
                    status: approved
                    is_locked: false
                    is_batchable: true
                    updated_at: '2026-06-15T14:10:00.000000Z'
                    created_at: '2026-06-15T14:10:00.000000Z'
                  related_transactions: []
                  eligibility:
                    eligible: true
                    reason: null
                    settings_route: null
                    settings_label: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: accounting:read
      operationId: get-api-vendor-deposits-vendordepositid-accounting
  /api/vendor-deposits/{vendorDepositId}/generate-accounting-transaction:
    post:
      tags:
      - Vendor Deposits
      summary: Generate Vendor Deposit Accounting Transaction
      description: 'Generate (or regenerate) the accounting transactions for a vendor
        deposit from its current payments, applications, refunds, and write-offs.
        No request body is required.


        :::info[Required scope: `accounting:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters:
      - name: vendorDepositId
        in: path
        schema:
          type: string
        required: true
        description: The vendor deposit ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: Generated
                  value:
                    message: Ledger entry generated successfully.
                    data: null
                example-1:
                  summary: Ledger Disabled
                  value:
                    message: Ledger generation is disabled for this tenant.
                    data: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: accounting:write
      operationId: post-api-vendor-deposits-vendordepositid-generate-accounting-transaction
  /api/vendor-deposits/{vendorDepositId}/push-to-qbo:
    post:
      tags:
      - Vendor Deposits
      summary: Push Vendor Deposit to QuickBooks Online
      description: 'Queue a push of the vendor deposit''s accounting transactions
        to QuickBooks Online. The push runs asynchronously — a 200 response confirms
        the sync was queued, not that it has completed. Requires a connected QuickBooks
        Online integration.


        :::info[Required scope: `accounting:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Returns 422 when the deposit cannot be pushed (e.g. no accounting transaction
        exists or no QuickBooks Online connection is configured).'
      requestBody:
        content: {}
      parameters:
      - name: vendorDepositId
        in: path
        schema:
          type: string
        required: true
        description: The vendor deposit ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      vendor_deposit_id:
                        type: integer
                example:
                  message: Vendor deposit push to QuickBooks Online queued.
                  data:
                    vendor_deposit_id: 42
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: No QuickBooks Online integration is connected.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: accounting:write
      operationId: post-api-vendor-deposits-vendordepositid-push-to-qbo
  /api/vendor-deposits/{vendorDepositId}/push-to-xero:
    post:
      tags:
      - Vendor Deposits
      summary: Push Vendor Deposit to Xero
      description: 'Queue a push of the vendor deposit''s accounting transactions
        to Xero. The push runs asynchronously — a 200 response confirms the sync was
        queued, not that it has completed. Requires a connected Xero integration.


        :::info[Required scope: `accounting:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Returns 422 when the deposit cannot be pushed (e.g. no accounting transaction
        exists or no Xero connection is configured).'
      requestBody:
        content: {}
      parameters:
      - name: vendorDepositId
        in: path
        schema:
          type: string
        required: true
        description: The vendor deposit ID.
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      vendor_deposit_id:
                        type: integer
                example:
                  message: Vendor deposit push to Xero queued.
                  data:
                    vendor_deposit_id: 42
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: No Xero integration is connected.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: accounting:write
      operationId: post-api-vendor-deposits-vendordepositid-push-to-xero
  /api/vendor-deposits/{vendorDepositId}/attachments:
    get:
      tags:
      - Vendor Deposits
      summary: List Vendor Deposit Attachments
      description: 'List all attachments on a vendor deposit.


        :::info[Required scope: `accounting:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: vendorDepositId
        in: path
        schema:
          type: string
        required: true
        description: The vendor deposit ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: accounting:read
      operationId: get-api-vendor-deposits-vendordepositid-attachments
    post:
      tags:
      - Vendor Deposits
      summary: Upload Vendor Deposit Attachment
      description: 'Upload an attachment (multipart/form-data). Max size 10 MB. Optional
        description (<=500 chars).


        :::info[Required scope: `accounting:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        **Category:** optional `category` field — `proforma_invoice`, `payment_proof`,
        or `other` (default). Categories drive UI chips and remittance-advice attachment
        pre-selection.'
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                file:
                  type: string
                  format: binary
                description:
                  type: string
                  example: Wire receipt
                category:
                  type: string
                  description: 'Optional. One of: proforma_invoice, payment_proof,
                    other (default: other).'
                  example: proforma_invoice
      parameters:
      - name: vendorDepositId
        in: path
        schema:
          type: string
        required: true
        description: The vendor deposit ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      x-required-scope: accounting:write
      operationId: post-api-vendor-deposits-vendordepositid-attachments
  /api/vendor-deposits/{vendorDepositId}/attachments/{attachmentId}:
    get:
      tags:
      - Vendor Deposits
      summary: Download Vendor Deposit Attachment
      description: 'Download the original attachment file.


        :::info[Required scope: `accounting:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: vendorDepositId
        in: path
        schema:
          type: string
        required: true
        description: The vendor deposit ID.
      - name: attachmentId
        in: path
        schema:
          type: string
        required: true
        description: The attachment ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: accounting:read
      operationId: get-api-vendor-deposits-vendordepositid-attachments-attachmentid
    delete:
      tags:
      - Vendor Deposits
      summary: Delete Vendor Deposit Attachment
      description: 'Delete an attachment. Returns 204 No Content.


        :::info[Required scope: `accounting:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: vendorDepositId
        in: path
        schema:
          type: string
        required: true
        description: The vendor deposit ID.
      - name: attachmentId
        in: path
        schema:
          type: string
        required: true
        description: The attachment ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: accounting:write
      operationId: delete-api-vendor-deposits-vendordepositid-attachments-attachmentid
  /api/vendor-deposits/aging-report:
    get:
      tags:
      - Vendor Deposits
      summary: Get Vendor Deposit Aging Report
      description: 'Aging report bucketed by current / 1-30 / 31-60 / 61-90 / over_90
        days. Returns totals and deposit details per bucket.


        :::info[Required scope: `accounting:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: supplier_id
        in: query
        schema:
          type: integer
        description: Optional — filter by supplier
        example: '1'
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: accounting:read
      operationId: get-api-vendor-deposits-aging-report
  /api/vendor-deposits/summary-stats:
    get:
      tags:
      - Vendor Deposits
      summary: Get Vendor Deposit Summary Stats
      description: 'Aggregate KPI stats across all deposits (totals by status, available
        balance, etc.).


        :::info[Required scope: `accounting:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: accounting:read
      operationId: get-api-vendor-deposits-summary-stats
  /api/vendor-deposits/supplier-statement/{supplierId}:
    get:
      tags:
      - Vendor Deposits
      summary: Supplier Statement
      description: 'All deposits for a specific supplier with totals (amount, paid,
        applied, refunded, available).


        :::info[Required scope: `accounting:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: supplierId
        in: path
        schema:
          type: string
        required: true
        description: The supplier ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: accounting:read
      operationId: get-api-vendor-deposits-supplier-statement-supplierid
  /api/vendor-deposits/{vendorDepositId}/activity-log:
    get:
      tags:
      - Vendor Deposits
      summary: Get Vendor Deposit Activity Log
      description: 'Paginated activity log (Spatie Activitylog) for a vendor deposit.


        :::info[Required scope: `accounting:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: per_page
        in: query
        schema:
          type: integer
        example: '15'
        description: Results per page (default 10).
      - name: vendorDepositId
        in: path
        schema:
          type: string
        required: true
        description: The vendor deposit ID.
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: accounting:read
      operationId: get-api-vendor-deposits-vendordepositid-activity-log
  /api/vendor-deposits/write-off-report:
    get:
      tags:
      - Vendor Deposits
      summary: Get Vendor Deposit Write-Off Report
      description: 'Report of written-off vendor deposits, with per-deposit rows,
        totals, and a per-supplier breakdown sorted by written-off amount.


        :::info[Required scope: `accounting:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Optionally filter by written-off date range and supplier.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      rows:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            deposit_number:
                              type: string
                            supplier_id:
                              type: integer
                            supplier_name:
                              type: string
                            deposit_date:
                              type: string
                            due_date:
                              type: string
                            written_off_at:
                              type: string
                            write_off_reason:
                              type: string
                            written_off_by:
                              type: string
                            currency_code:
                              type: string
                            amount:
                              type: integer
                            amount_written_off:
                              type: integer
                            amount_written_off_in_tenant_currency:
                              type: integer
                      count:
                        type: integer
                      total_written_off:
                        type: integer
                      total_written_off_in_tenant_currency:
                        type: integer
                      by_supplier:
                        type: array
                        items:
                          type: object
                          properties:
                            supplier_id:
                              type: integer
                            supplier_name:
                              type: string
                            count:
                              type: integer
                            total_written_off_in_tenant_currency:
                              type: integer
                example:
                  data:
                    rows:
                    - id: 42
                      deposit_number: DEP-000042
                      supplier_id: 7
                      supplier_name: Acme Components Ltd
                      deposit_date: '2026-03-02'
                      due_date: '2026-04-01'
                      written_off_at: '2026-06-20'
                      write_off_reason: Supplier ceased trading
                      written_off_by: Jane Operator
                      currency_code: USD
                      amount: 750
                      amount_written_off: 750
                      amount_written_off_in_tenant_currency: 750
                    count: 1
                    total_written_off: 750
                    total_written_off_in_tenant_currency: 750
                    by_supplier:
                    - supplier_id: 7
                      supplier_name: Acme Components Ltd
                      count: 1
                      total_written_off_in_tenant_currency: 750
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: accounting:read
      operationId: get-api-vendor-deposits-write-off-report
  /api/vendor-deposits/cash-due-schedule:
    get:
      tags:
      - Vendor Deposits
      summary: Get Cash Due Schedule
      description: 'Cash due schedule for deposit obligations, combining existing
        deposits and projected payment-term milestones on open purchase orders. Rows
        are grouped into sections: due_now (triggered and due or overdue), due_within_30_days,
        upcoming_by_trigger (dated but trigger not yet reached), undated, late_shipments,
        and shortfalls.


        :::info[Required scope: `accounting:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Each section row describes the obligation: source_type (deposit or installment),
        deposit/PO references, milestone label, trigger event, due date, amounts in
        the deposit currency and the tenant currency, and flags (has_triggered, is_ready_to_pay,
        is_overdue).'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      summary:
                        type: object
                        properties:
                          due_now_count:
                            type: integer
                          due_now_in_tenant_currency:
                            type: integer
                          due_within_30_days_count:
                            type: integer
                          due_within_30_days_in_tenant_currency:
                            type: integer
                          upcoming_by_trigger_count:
                            type: integer
                          upcoming_by_trigger_in_tenant_currency:
                            type: integer
                          undated_count:
                            type: integer
                          undated_in_tenant_currency:
                            type: integer
                          late_shipment_count:
                            type: integer
                          late_shipment_in_tenant_currency:
                            type: integer
                          shortfall_count:
                            type: integer
                          shortfall_in_tenant_currency:
                            type: integer
                      sections:
                        type: object
                        properties:
                          due_now:
                            type: array
                            items:
                              type: object
                              properties:
                                source_type:
                                  type: string
                                row_key:
                                  type: string
                                vendor_deposit_id:
                                  type: integer
                                vendor_deposit_number:
                                  type: string
                                deposit_status:
                                  type: string
                                deposit_status_label:
                                  type: string
                                supplier_id:
                                  type: integer
                                supplier_name:
                                  type: string
                                purchase_order_id:
                                  type: integer
                                purchase_order_number:
                                  type: string
                                payment_term_schedule_line_index:
                                  type: integer
                                inbound_shipment_id:
                                  type: string
                                  nullable: true
                                milestone_label:
                                  type: string
                                currency_code:
                                  type: string
                                settlement_type:
                                  type: string
                                settlement_type_label:
                                  type: string
                                trigger_event:
                                  type: string
                                trigger_event_label:
                                  type: string
                                due_date:
                                  type: string
                                amount:
                                  type: integer
                                amount_paid:
                                  type: integer
                                remaining_amount:
                                  type: integer
                                amount_in_tenant_currency:
                                  type: integer
                                amount_paid_in_tenant_currency:
                                  type: integer
                                remaining_amount_in_tenant_currency:
                                  type: integer
                                has_triggered:
                                  type: boolean
                                is_ready_to_pay:
                                  type: boolean
                                forecast_source:
                                  type: string
                                forecast_source_label:
                                  type: string
                                is_overdue:
                                  type: boolean
                          due_within_30_days:
                            type: array
                          upcoming_by_trigger:
                            type: array
                          undated:
                            type: array
                          late_shipments:
                            type: array
                          shortfalls:
                            type: array
                      shortfall_summary:
                        type: object
                        properties:
                          count:
                            type: integer
                          shortfall_count:
                            type: integer
                          undercoverage_count:
                            type: integer
                          overage_count:
                            type: integer
                          overdue_count:
                            type: integer
                          shortfall_in_tenant_currency:
                            type: integer
                          overage_in_tenant_currency:
                            type: integer
                          overdue_in_tenant_currency:
                            type: integer
                example:
                  data:
                    summary:
                      due_now_count: 1
                      due_now_in_tenant_currency: 1500
                      due_within_30_days_count: 0
                      due_within_30_days_in_tenant_currency: 0
                      upcoming_by_trigger_count: 0
                      upcoming_by_trigger_in_tenant_currency: 0
                      undated_count: 0
                      undated_in_tenant_currency: 0
                      late_shipment_count: 0
                      late_shipment_in_tenant_currency: 0
                      shortfall_count: 0
                      shortfall_in_tenant_currency: 0
                    sections:
                      due_now:
                      - source_type: deposit
                        row_key: '42'
                        vendor_deposit_id: 42
                        vendor_deposit_number: DEP-000042
                        deposit_status: approved
                        deposit_status_label: Approved
                        supplier_id: 7
                        supplier_name: Acme Components Ltd
                        purchase_order_id: 310
                        purchase_order_number: PO-000310
                        payment_term_schedule_line_index: 1
                        inbound_shipment_id: null
                        milestone_label: 30% deposit on order
                        currency_code: USD
                        settlement_type: vendor_deposit
                        settlement_type_label: Vendor Deposit
                        trigger_event: po_approved
                        trigger_event_label: PO Approved
                        due_date: '2026-07-20'
                        amount: 1500
                        amount_paid: 0
                        remaining_amount: 1500
                        amount_in_tenant_currency: 1500
                        amount_paid_in_tenant_currency: 0
                        remaining_amount_in_tenant_currency: 1500
                        has_triggered: true
                        is_ready_to_pay: true
                        forecast_source: deposit_due_date
                        forecast_source_label: Deposit due date
                        is_overdue: false
                      due_within_30_days: []
                      upcoming_by_trigger: []
                      undated: []
                      late_shipments: []
                      shortfalls: []
                    shortfall_summary:
                      count: 0
                      shortfall_count: 0
                      undercoverage_count: 0
                      overage_count: 0
                      overdue_count: 0
                      shortfall_in_tenant_currency: 0
                      overage_in_tenant_currency: 0
                      overdue_in_tenant_currency: 0
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: accounting:read
      operationId: get-api-vendor-deposits-cash-due-schedule
  /api/vendor-deposits/cash-flow-forecast:
    get:
      tags:
      - Vendor Deposits
      summary: Get Cash Flow Forecast
      description: 'Forecast of upcoming cash outflows from unpaid deposit obligations,
        bucketed by day, week, or month. Buckets include existing deposits and projected
        payment-term milestones on open purchase orders, keyed by due date.


        :::info[Required scope: `accounting:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Defaults: date_from = today, date_to = six months out, granularity = month.
        Undated obligations (no due date yet) are listed separately in undated_rows;
        coverage shortfalls appear in shortfall_rows.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      granularity:
                        type: string
                      date_from:
                        type: string
                      date_to:
                        type: string
                      settlement_scope:
                        type: string
                      buckets:
                        type: array
                        items:
                          type: object
                          properties:
                            period_start:
                              type: string
                            period_label:
                              type: string
                            obligation_count:
                              type: integer
                            deposit_count:
                              type: integer
                            total_outstanding:
                              type: integer
                            total_outstanding_in_tenant_currency:
                              type: integer
                            rows:
                              type: array
                              items:
                                type: object
                                properties:
                                  source_type:
                                    type: string
                                  row_key:
                                    type: string
                                  vendor_deposit_id:
                                    type: integer
                                  vendor_deposit_number:
                                    type: string
                                  deposit_status:
                                    type: string
                                  deposit_status_label:
                                    type: string
                                  supplier_id:
                                    type: integer
                                  supplier_name:
                                    type: string
                                  purchase_order_id:
                                    type: integer
                                  purchase_order_number:
                                    type: string
                                  payment_term_schedule_line_index:
                                    type: integer
                                  inbound_shipment_id:
                                    type: string
                                    nullable: true
                                  milestone_label:
                                    type: string
                                  currency_code:
                                    type: string
                                  settlement_type:
                                    type: string
                                  settlement_type_label:
                                    type: string
                                  trigger_event:
                                    type: string
                                  trigger_event_label:
                                    type: string
                                  due_date:
                                    type: string
                                  amount:
                                    type: integer
                                  amount_paid:
                                    type: integer
                                  remaining_amount:
                                    type: integer
                                  amount_in_tenant_currency:
                                    type: integer
                                  amount_paid_in_tenant_currency:
                                    type: integer
                                  remaining_amount_in_tenant_currency:
                                    type: integer
                                  has_triggered:
                                    type: boolean
                                  is_ready_to_pay:
                                    type: boolean
                                  forecast_source:
                                    type: string
                                  forecast_source_label:
                                    type: string
                                  is_overdue:
                                    type: boolean
                      total_outstanding_in_tenant_currency:
                        type: integer
                      obligation_count:
                        type: integer
                      deposit_count:
                        type: integer
                      undated_rows:
                        type: array
                      undated_count:
                        type: integer
                      undated_outstanding_in_tenant_currency:
                        type: integer
                      shortfall_rows:
                        type: array
                      shortfall_count:
                        type: integer
                      shortfall_in_tenant_currency:
                        type: integer
                      shortfall_overdue_in_tenant_currency:
                        type: integer
                example:
                  data:
                    granularity: month
                    date_from: '2026-07-07'
                    date_to: '2027-01-07'
                    settlement_scope: all
                    buckets:
                    - period_start: '2026-07-01'
                      period_label: Jul 2026
                      obligation_count: 1
                      deposit_count: 1
                      total_outstanding: 1500
                      total_outstanding_in_tenant_currency: 1500
                      rows:
                      - source_type: deposit
                        row_key: '42'
                        vendor_deposit_id: 42
                        vendor_deposit_number: DEP-000042
                        deposit_status: approved
                        deposit_status_label: Approved
                        supplier_id: 7
                        supplier_name: Acme Components Ltd
                        purchase_order_id: 310
                        purchase_order_number: PO-000310
                        payment_term_schedule_line_index: 1
                        inbound_shipment_id: null
                        milestone_label: 30% deposit on order
                        currency_code: USD
                        settlement_type: vendor_deposit
                        settlement_type_label: Vendor Deposit
                        trigger_event: po_approved
                        trigger_event_label: PO Approved
                        due_date: '2026-07-20'
                        amount: 1500
                        amount_paid: 0
                        remaining_amount: 1500
                        amount_in_tenant_currency: 1500
                        amount_paid_in_tenant_currency: 0
                        remaining_amount_in_tenant_currency: 1500
                        has_triggered: true
                        is_ready_to_pay: true
                        forecast_source: deposit_due_date
                        forecast_source_label: Deposit due date
                        is_overdue: false
                    total_outstanding_in_tenant_currency: 1500
                    obligation_count: 1
                    deposit_count: 1
                    undated_rows: []
                    undated_count: 0
                    undated_outstanding_in_tenant_currency: 0
                    shortfall_rows: []
                    shortfall_count: 0
                    shortfall_in_tenant_currency: 0
                    shortfall_overdue_in_tenant_currency: 0
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: accounting:read
      operationId: get-api-vendor-deposits-cash-flow-forecast
  /api/vendor-deposits/upcoming-liability:
    get:
      tags:
      - Vendor Deposits
      summary: Get Upcoming Liability Report
      description: 'Upcoming deposit liabilities: every outstanding deposit obligation
        (existing deposits plus projected payment-term milestones on open purchase
        orders), sorted with overdue and ready-to-pay rows first. Rows with no due
        date are returned separately in undated_rows.


        :::info[Required scope: `accounting:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        The summary aggregates the tenant-currency exposure: total outstanding, overdue,
        due in the next 7 and 30 days, ready to pay, and blocked (trigger event not
        yet reached).'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      rows:
                        type: array
                        items:
                          type: object
                          properties:
                            source_type:
                              type: string
                            row_key:
                              type: string
                            vendor_deposit_id:
                              type: integer
                            vendor_deposit_number:
                              type: string
                            deposit_status:
                              type: string
                            deposit_status_label:
                              type: string
                            supplier_id:
                              type: integer
                            supplier_name:
                              type: string
                            purchase_order_id:
                              type: integer
                            purchase_order_number:
                              type: string
                            payment_term_schedule_line_index:
                              type: integer
                            inbound_shipment_id:
                              type: string
                              nullable: true
                            milestone_label:
                              type: string
                            currency_code:
                              type: string
                            settlement_type:
                              type: string
                            settlement_type_label:
                              type: string
                            trigger_event:
                              type: string
                            trigger_event_label:
                              type: string
                            due_date:
                              type: string
                            amount:
                              type: integer
                            amount_paid:
                              type: integer
                            remaining_amount:
                              type: integer
                            amount_in_tenant_currency:
                              type: integer
                            amount_paid_in_tenant_currency:
                              type: integer
                            remaining_amount_in_tenant_currency:
                              type: integer
                            has_triggered:
                              type: boolean
                            is_ready_to_pay:
                              type: boolean
                            forecast_source:
                              type: string
                            forecast_source_label:
                              type: string
                            is_overdue:
                              type: boolean
                      summary:
                        type: object
                        properties:
                          row_count:
                            type: integer
                          outstanding_in_tenant_currency:
                            type: integer
                          overdue_count:
                            type: integer
                          overdue_in_tenant_currency:
                            type: integer
                          due_in_7_days_count:
                            type: integer
                          due_in_7_days_in_tenant_currency:
                            type: integer
                          due_in_30_days_count:
                            type: integer
                          due_in_30_days_in_tenant_currency:
                            type: integer
                          ready_to_pay_count:
                            type: integer
                          ready_to_pay_in_tenant_currency:
                            type: integer
                          blocked_count:
                            type: integer
                          blocked_in_tenant_currency:
                            type: integer
                      undated_rows:
                        type: array
                      undated_count:
                        type: integer
                      undated_total:
                        type: integer
                      shortfall_rows:
                        type: array
                      shortfall_summary:
                        type: object
                        properties:
                          count:
                            type: integer
                          shortfall_count:
                            type: integer
                          undercoverage_count:
                            type: integer
                          overage_count:
                            type: integer
                          overdue_count:
                            type: integer
                          shortfall_in_tenant_currency:
                            type: integer
                          overage_in_tenant_currency:
                            type: integer
                          overdue_in_tenant_currency:
                            type: integer
                example:
                  data:
                    rows:
                    - source_type: deposit
                      row_key: '42'
                      vendor_deposit_id: 42
                      vendor_deposit_number: DEP-000042
                      deposit_status: approved
                      deposit_status_label: Approved
                      supplier_id: 7
                      supplier_name: Acme Components Ltd
                      purchase_order_id: 310
                      purchase_order_number: PO-000310
                      payment_term_schedule_line_index: 1
                      inbound_shipment_id: null
                      milestone_label: 30% deposit on order
                      currency_code: USD
                      settlement_type: vendor_deposit
                      settlement_type_label: Vendor Deposit
                      trigger_event: po_approved
                      trigger_event_label: PO Approved
                      due_date: '2026-07-20'
                      amount: 1500
                      amount_paid: 0
                      remaining_amount: 1500
                      amount_in_tenant_currency: 1500
                      amount_paid_in_tenant_currency: 0
                      remaining_amount_in_tenant_currency: 1500
                      has_triggered: true
                      is_ready_to_pay: true
                      forecast_source: deposit_due_date
                      forecast_source_label: Deposit due date
                      is_overdue: false
                    summary:
                      row_count: 1
                      outstanding_in_tenant_currency: 1500
                      overdue_count: 0
                      overdue_in_tenant_currency: 0
                      due_in_7_days_count: 0
                      due_in_7_days_in_tenant_currency: 0
                      due_in_30_days_count: 1
                      due_in_30_days_in_tenant_currency: 1500
                      ready_to_pay_count: 1
                      ready_to_pay_in_tenant_currency: 1500
                      blocked_count: 0
                      blocked_in_tenant_currency: 0
                    undated_rows: []
                    undated_count: 0
                    undated_total: 0
                    shortfall_rows: []
                    shortfall_summary:
                      count: 0
                      shortfall_count: 0
                      undercoverage_count: 0
                      overage_count: 0
                      overdue_count: 0
                      shortfall_in_tenant_currency: 0
                      overage_in_tenant_currency: 0
                      overdue_in_tenant_currency: 0
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: accounting:read
      operationId: get-api-vendor-deposits-upcoming-liability
  /api/vendor-deposits/supplier-exposure:
    get:
      tags:
      - Vendor Deposits
      summary: Get Supplier Exposure Report
      description: 'Deposit exposure grouped by supplier, sorted by outstanding amount.
        Each supplier row aggregates its outstanding obligations (existing deposits
        plus projected milestones), overdue and near-term amounts, unapplied paid
        balances, pending approvals, and coverage shortfalls/overages, and includes
        the underlying obligation_rows, shortfall_rows, and a per-purchase-order breakdown.


        :::info[Required scope: `accounting:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      rows:
                        type: array
                        items:
                          type: object
                          properties:
                            supplier_id:
                              type: integer
                            supplier_name:
                              type: string
                            deposit_count:
                              type: integer
                            obligation_count:
                              type: integer
                            po_count:
                              type: integer
                            outstanding_in_tenant_currency:
                              type: integer
                            overdue_in_tenant_currency:
                              type: integer
                            due_in_7_days_in_tenant_currency:
                              type: integer
                            due_in_30_days_in_tenant_currency:
                              type: integer
                            blocked_in_tenant_currency:
                              type: integer
                            unapplied_balance_in_tenant_currency:
                              type: integer
                            pending_approval_count:
                              type: integer
                            shortfall_count:
                              type: integer
                            shortfall_in_tenant_currency:
                              type: integer
                            shortfall_overdue_in_tenant_currency:
                              type: integer
                            overage_count:
                              type: integer
                            overage_in_tenant_currency:
                              type: integer
                            obligation_rows:
                              type: array
                              items:
                                type: object
                                properties:
                                  source_type:
                                    type: string
                                  row_key:
                                    type: string
                                  vendor_deposit_id:
                                    type: integer
                                  vendor_deposit_number:
                                    type: string
                                  deposit_status:
                                    type: string
                                  deposit_status_label:
                                    type: string
                                  supplier_id:
                                    type: integer
                                  supplier_name:
                                    type: string
                                  purchase_order_id:
                                    type: integer
                                  purchase_order_number:
                                    type: string
                                  payment_term_schedule_line_index:
                                    type: integer
                                  inbound_shipment_id:
                                    type: string
                                    nullable: true
                                  milestone_label:
                                    type: string
                                  currency_code:
                                    type: string
                                  settlement_type:
                                    type: string
                                  settlement_type_label:
                                    type: string
                                  trigger_event:
                                    type: string
                                  trigger_event_label:
                                    type: string
                                  due_date:
                                    type: string
                                  amount:
                                    type: integer
                                  amount_paid:
                                    type: integer
                                  remaining_amount:
                                    type: integer
                                  amount_in_tenant_currency:
                                    type: integer
                                  amount_paid_in_tenant_currency:
                                    type: integer
                                  remaining_amount_in_tenant_currency:
                                    type: integer
                                  has_triggered:
                                    type: boolean
                                  is_ready_to_pay:
                                    type: boolean
                                  forecast_source:
                                    type: string
                                  forecast_source_label:
                                    type: string
                                  is_overdue:
                                    type: boolean
                            shortfall_rows:
                              type: array
                            purchase_orders:
                              type: array
                              items:
                                type: object
                                properties:
                                  purchase_order_id:
                                    type: integer
                                  purchase_order_number:
                                    type: string
                                  order_status:
                                    type: string
                                  order_status_label:
                                    type: string
                                  shipment_status:
                                    type: string
                                  shipment_status_label:
                                    type: string
                                  obligation_count:
                                    type: integer
                                  outstanding_in_tenant_currency:
                                    type: integer
                                  due_in_7_days_in_tenant_currency:
                                    type: integer
                                  awaiting_trigger_in_tenant_currency:
                                    type: integer
                      summary:
                        type: object
                        properties:
                          supplier_count:
                            type: integer
                          outstanding_in_tenant_currency:
                            type: integer
                          overdue_in_tenant_currency:
                            type: integer
                          due_in_7_days_in_tenant_currency:
                            type: integer
                          due_in_30_days_in_tenant_currency:
                            type: integer
                          blocked_in_tenant_currency:
                            type: integer
                          unapplied_balance_in_tenant_currency:
                            type: integer
                          shortfall_count:
                            type: integer
                          shortfall_in_tenant_currency:
                            type: integer
                          shortfall_overdue_in_tenant_currency:
                            type: integer
                          overage_count:
                            type: integer
                          overage_in_tenant_currency:
                            type: integer
                example:
                  data:
                    rows:
                    - supplier_id: 7
                      supplier_name: Acme Components Ltd
                      deposit_count: 2
                      obligation_count: 1
                      po_count: 1
                      outstanding_in_tenant_currency: 1500
                      overdue_in_tenant_currency: 0
                      due_in_7_days_in_tenant_currency: 0
                      due_in_30_days_in_tenant_currency: 1500
                      blocked_in_tenant_currency: 0
                      unapplied_balance_in_tenant_currency: 250
                      pending_approval_count: 0
                      shortfall_count: 0
                      shortfall_in_tenant_currency: 0
                      shortfall_overdue_in_tenant_currency: 0
                      overage_count: 0
                      overage_in_tenant_currency: 0
                      obligation_rows:
                      - source_type: deposit
                        row_key: '42'
                        vendor_deposit_id: 42
                        vendor_deposit_number: DEP-000042
                        deposit_status: approved
                        deposit_status_label: Approved
                        supplier_id: 7
                        supplier_name: Acme Components Ltd
                        purchase_order_id: 310
                        purchase_order_number: PO-000310
                        payment_term_schedule_line_index: 1
                        inbound_shipment_id: null
                        milestone_label: 30% deposit on order
                        currency_code: USD
                        settlement_type: vendor_deposit
                        settlement_type_label: Vendor Deposit
                        trigger_event: po_approved
                        trigger_event_label: PO Approved
                        due_date: '2026-07-20'
                        amount: 1500
                        amount_paid: 0
                        remaining_amount: 1500
                        amount_in_tenant_currency: 1500
                        amount_paid_in_tenant_currency: 0
                        remaining_amount_in_tenant_currency: 1500
                        has_triggered: true
                        is_ready_to_pay: true
                        forecast_source: deposit_due_date
                        forecast_source_label: Deposit due date
                        is_overdue: false
                      shortfall_rows: []
                      purchase_orders:
                      - purchase_order_id: 310
                        purchase_order_number: PO-000310
                        order_status: open
                        order_status_label: Open
                        shipment_status: not_shipped
                        shipment_status_label: Not Shipped
                        obligation_count: 1
                        outstanding_in_tenant_currency: 1500
                        due_in_7_days_in_tenant_currency: 0
                        awaiting_trigger_in_tenant_currency: 0
                    summary:
                      supplier_count: 1
                      outstanding_in_tenant_currency: 1500
                      overdue_in_tenant_currency: 0
                      due_in_7_days_in_tenant_currency: 0
                      due_in_30_days_in_tenant_currency: 1500
                      blocked_in_tenant_currency: 0
                      unapplied_balance_in_tenant_currency: 250
                      shortfall_count: 0
                      shortfall_in_tenant_currency: 0
                      shortfall_overdue_in_tenant_currency: 0
                      overage_count: 0
                      overage_in_tenant_currency: 0
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: accounting:read
      operationId: get-api-vendor-deposits-supplier-exposure
  /api/vendor-deposits/exceptions-queue:
    get:
      tags:
      - Vendor Deposits
      summary: Get Exceptions Queue
      description: 'Deposit obligations that need attention, grouped into sections:
        overdue, due_soon (next 7 days), blocked (trigger event not yet reached),
        pending_approval, unapplied_after_bill (paid deposits still unapplied after
        a supplier bill has arrived), late_shipments, and shortfalls. The summary
        aggregates counts and tenant-currency amounts per section.


        :::info[Required scope: `accounting:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      summary:
                        type: object
                        properties:
                          overdue_count:
                            type: integer
                          overdue_in_tenant_currency:
                            type: integer
                          due_soon_count:
                            type: integer
                          due_soon_in_tenant_currency:
                            type: integer
                          blocked_count:
                            type: integer
                          blocked_in_tenant_currency:
                            type: integer
                          pending_approval_count:
                            type: integer
                          pending_approval_in_tenant_currency:
                            type: integer
                          unapplied_after_bill_count:
                            type: integer
                          unapplied_after_bill_in_tenant_currency:
                            type: integer
                          late_shipment_count:
                            type: integer
                          shortfall_count:
                            type: integer
                          shortfall_in_tenant_currency:
                            type: integer
                      sections:
                        type: object
                        properties:
                          overdue:
                            type: array
                          due_soon:
                            type: array
                            items:
                              type: object
                              properties:
                                source_type:
                                  type: string
                                row_key:
                                  type: string
                                vendor_deposit_id:
                                  type: integer
                                vendor_deposit_number:
                                  type: string
                                deposit_status:
                                  type: string
                                deposit_status_label:
                                  type: string
                                supplier_id:
                                  type: integer
                                supplier_name:
                                  type: string
                                purchase_order_id:
                                  type: integer
                                purchase_order_number:
                                  type: string
                                payment_term_schedule_line_index:
                                  type: integer
                                inbound_shipment_id:
                                  type: string
                                  nullable: true
                                milestone_label:
                                  type: string
                                currency_code:
                                  type: string
                                settlement_type:
                                  type: string
                                settlement_type_label:
                                  type: string
                                trigger_event:
                                  type: string
                                trigger_event_label:
                                  type: string
                                due_date:
                                  type: string
                                amount:
                                  type: integer
                                amount_paid:
                                  type: integer
                                remaining_amount:
                                  type: integer
                                amount_in_tenant_currency:
                                  type: integer
                                amount_paid_in_tenant_currency:
                                  type: integer
                                remaining_amount_in_tenant_currency:
                                  type: integer
                                has_triggered:
                                  type: boolean
                                is_ready_to_pay:
                                  type: boolean
                                forecast_source:
                                  type: string
                                forecast_source_label:
                                  type: string
                                is_overdue:
                                  type: boolean
                          blocked:
                            type: array
                          pending_approval:
                            type: array
                            items:
                              type: object
                              properties:
                                vendor_deposit_id:
                                  type: integer
                                vendor_deposit_number:
                                  type: string
                                supplier_id:
                                  type: integer
                                supplier_name:
                                  type: string
                                purchase_order_id:
                                  type: integer
                                purchase_order_number:
                                  type: string
                                deposit_date:
                                  type: string
                                due_date:
                                  type: string
                                remaining_amount_in_tenant_currency:
                                  type: integer
                          unapplied_after_bill:
                            type: array
                          late_shipments:
                            type: array
                          shortfalls:
                            type: array
                      shortfall_summary:
                        type: object
                        properties:
                          count:
                            type: integer
                          shortfall_count:
                            type: integer
                          undercoverage_count:
                            type: integer
                          overage_count:
                            type: integer
                          overdue_count:
                            type: integer
                          shortfall_in_tenant_currency:
                            type: integer
                          overage_in_tenant_currency:
                            type: integer
                          overdue_in_tenant_currency:
                            type: integer
                example:
                  data:
                    summary:
                      overdue_count: 0
                      overdue_in_tenant_currency: 0
                      due_soon_count: 1
                      due_soon_in_tenant_currency: 1500
                      blocked_count: 0
                      blocked_in_tenant_currency: 0
                      pending_approval_count: 1
                      pending_approval_in_tenant_currency: 1500
                      unapplied_after_bill_count: 0
                      unapplied_after_bill_in_tenant_currency: 0
                      late_shipment_count: 0
                      shortfall_count: 0
                      shortfall_in_tenant_currency: 0
                    sections:
                      overdue: []
                      due_soon:
                      - source_type: deposit
                        row_key: '42'
                        vendor_deposit_id: 42
                        vendor_deposit_number: DEP-000042
                        deposit_status: approved
                        deposit_status_label: Approved
                        supplier_id: 7
                        supplier_name: Acme Components Ltd
                        purchase_order_id: 310
                        purchase_order_number: PO-000310
                        payment_term_schedule_line_index: 1
                        inbound_shipment_id: null
                        milestone_label: 30% deposit on order
                        currency_code: USD
                        settlement_type: vendor_deposit
                        settlement_type_label: Vendor Deposit
                        trigger_event: po_approved
                        trigger_event_label: PO Approved
                        due_date: '2026-07-20'
                        amount: 1500
                        amount_paid: 0
                        remaining_amount: 1500
                        amount_in_tenant_currency: 1500
                        amount_paid_in_tenant_currency: 0
                        remaining_amount_in_tenant_currency: 1500
                        has_triggered: true
                        is_ready_to_pay: true
                        forecast_source: deposit_due_date
                        forecast_source_label: Deposit due date
                        is_overdue: false
                      blocked: []
                      pending_approval:
                      - vendor_deposit_id: 42
                        vendor_deposit_number: DEP-000042
                        supplier_id: 7
                        supplier_name: Acme Components Ltd
                        purchase_order_id: 310
                        purchase_order_number: PO-000310
                        deposit_date: '2026-06-15'
                        due_date: '2026-07-20'
                        remaining_amount_in_tenant_currency: 1500
                      unapplied_after_bill: []
                      late_shipments: []
                      shortfalls: []
                    shortfall_summary:
                      count: 0
                      shortfall_count: 0
                      undercoverage_count: 0
                      overage_count: 0
                      overdue_count: 0
                      shortfall_in_tenant_currency: 0
                      overage_in_tenant_currency: 0
                      overdue_in_tenant_currency: 0
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: accounting:read
      operationId: get-api-vendor-deposits-exceptions-queue
  /api/vendor-deposits/po-by-shipping-stage:
    get:
      tags:
      - Vendor Deposits
      summary: Get Purchase Orders by Shipping Stage
      description: 'Open purchase orders with deposit schedules, grouped by their
        farthest-reached installment trigger stage (e.g. PO approved, shipped, received).
        Each stage lists its purchase orders with the outstanding deposit amount still
        owed, so you can see how much cash is committed at each stage of the inbound
        pipeline.


        :::info[Required scope: `accounting:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      stages:
                        type: array
                        items:
                          type: object
                          properties:
                            stage:
                              type: string
                            stage_label:
                              type: string
                            stage_ordering:
                              type: integer
                            po_count:
                              type: integer
                            outstanding_in_tenant_currency:
                              type: integer
                            purchase_orders:
                              type: array
                      total_po_count:
                        type: integer
                      total_outstanding_in_tenant_currency:
                        type: integer
                example:
                  data:
                    stages:
                    - stage: manual
                      stage_label: Not Yet Triggered
                      stage_ordering: 0
                      po_count: 0
                      outstanding_in_tenant_currency: 0
                      purchase_orders: []
                    - stage: po_approved
                      stage_label: PO Approved
                      stage_ordering: 1
                      po_count: 1
                      outstanding_in_tenant_currency: 3500
                      purchase_orders:
                      - purchase_order_id: 310
                        purchase_order_number: PO-000310
                        supplier_id: 7
                        supplier_name: Acme Components Ltd
                        order_status: open
                        order_status_label: Open
                        shipment_status: not_shipped
                        shipment_status_label: Not Shipped
                        outstanding_in_tenant_currency: 3500
                    total_po_count: 1
                    total_outstanding_in_tenant_currency: 3500
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: accounting:read
      operationId: get-api-vendor-deposits-po-by-shipping-stage
  /api/vendor-deposits/expected-milestones:
    get:
      tags:
      - Vendor Deposits
      summary: List Expected Deposit Milestones
      description: 'List expected deposit milestones derived from the payment-term
        schedules of draft and open purchase orders. Each milestone describes an installment:
        its trigger event, expected amount, due date, and lifecycle status — expected
        (trigger not reached), ready_to_create (trigger reached, no deposit yet),
        created (linked to a deposit), or out_of_sync (linked deposit no longer matches
        the schedule).


        :::info[Required scope: `accounting:read`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Use unlinked_only=1 to list only milestones that should create a deposit but
        have none linked yet.'
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      summary:
                        type: object
                        properties:
                          row_count:
                            type: integer
                          expected_count:
                            type: integer
                          ready_to_create_count:
                            type: integer
                          created_count:
                            type: integer
                          out_of_sync_count:
                            type: integer
                          expected_amount_in_tenant_currency:
                            type: integer
                      rows:
                        type: array
                        items:
                          type: object
                          properties:
                            key:
                              type: string
                            status:
                              type: string
                            status_label:
                              type: string
                            status_reason:
                              type: string
                              nullable: true
                            status_reasons:
                              type: array
                            purchase_order_id:
                              type: integer
                            purchase_order_number:
                              type: string
                            supplier_id:
                              type: integer
                            supplier_name:
                              type: string
                            currency_id:
                              type: integer
                            currency_code:
                              type: string
                            line_index:
                              type: integer
                            shipment_id:
                              type: string
                              nullable: true
                            shipment_reference:
                              type: string
                              nullable: true
                            label:
                              type: string
                            amount_mode:
                              type: string
                            fixed_amount:
                              type: string
                              nullable: true
                            percentage:
                              type: integer
                            is_ownership_transfer:
                              type: boolean
                            settlement_type:
                              type: string
                            settlement_type_label:
                              type: string
                            creates_vendor_deposit:
                              type: boolean
                            trigger_event:
                              type: string
                            trigger_event_label:
                              type: string
                            offset_days:
                              type: integer
                            per_shipment:
                              type: boolean
                            shipment_date_basis:
                              type: string
                              nullable: true
                            forecast_source:
                              type: string
                            forecast_source_label:
                              type: string
                            is_synthesized:
                              type: boolean
                            expected_amount:
                              type: integer
                            expected_amount_in_tenant_currency:
                              type: integer
                            basis_date:
                              type: string
                            due_date:
                              type: string
                            is_trigger_reached:
                              type: boolean
                            is_ready_to_create:
                              type: boolean
                            linked_vendor_deposit_id:
                              type: string
                              nullable: true
                            linked_vendor_deposit_number:
                              type: string
                              nullable: true
                            linked_vendor_deposit_status:
                              type: string
                              nullable: true
                            linked_vendor_deposit_status_label:
                              type: string
                              nullable: true
                            schedule_snapshot:
                              type: object
                              properties:
                                label:
                                  type: string
                                trigger_event:
                                  type: string
                                percentage:
                                  type: integer
                            placeholder_reason:
                              type: string
                              nullable: true
                example:
                  data:
                    summary:
                      row_count: 1
                      expected_count: 0
                      ready_to_create_count: 1
                      created_count: 0
                      out_of_sync_count: 0
                      expected_amount_in_tenant_currency: 1500
                    rows:
                    - key: po-310-line-1
                      status: ready_to_create
                      status_label: Ready to Create
                      status_reason: null
                      status_reasons: []
                      purchase_order_id: 310
                      purchase_order_number: PO-000310
                      supplier_id: 7
                      supplier_name: Acme Components Ltd
                      currency_id: 1
                      currency_code: USD
                      line_index: 1
                      shipment_id: null
                      shipment_reference: null
                      label: 30% deposit on order
                      amount_mode: percent
                      fixed_amount: null
                      percentage: 30
                      is_ownership_transfer: false
                      settlement_type: vendor_deposit
                      settlement_type_label: Vendor Deposit
                      creates_vendor_deposit: true
                      trigger_event: po_approved
                      trigger_event_label: PO Approved
                      offset_days: 0
                      per_shipment: false
                      shipment_date_basis: null
                      forecast_source: po_approved_at
                      forecast_source_label: PO approval date
                      is_synthesized: false
                      expected_amount: 1500
                      expected_amount_in_tenant_currency: 1500
                      basis_date: '2026-06-10'
                      due_date: '2026-07-20'
                      is_trigger_reached: true
                      is_ready_to_create: true
                      linked_vendor_deposit_id: null
                      linked_vendor_deposit_number: null
                      linked_vendor_deposit_status: null
                      linked_vendor_deposit_status_label: null
                      schedule_snapshot:
                        label: 30% deposit on order
                        trigger_event: po_approved
                        percentage: 30
                      placeholder_reason: null
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: accounting:read
      operationId: get-api-vendor-deposits-expected-milestones
  /api/vendor-deposits/bulk-archive:
    post:
      tags:
      - Vendor Deposits
      summary: Bulk Archive Vendor Deposits
      description: 'Archive multiple deposits by id.


        :::info[Required scope: `accounting:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1
                - 2
                - 3
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: accounting:write
      operationId: post-api-vendor-deposits-bulk-archive
  /api/vendor-deposits/bulk-unarchive:
    post:
      tags:
      - Vendor Deposits
      summary: Bulk Unarchive Vendor Deposits
      description: 'Unarchive multiple deposits by id.


        :::info[Required scope: `accounting:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1
                - 2
                - 3
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: accounting:write
      operationId: post-api-vendor-deposits-bulk-unarchive
  /api/vendor-deposits/bulk-delete:
    post:
      tags:
      - Vendor Deposits
      summary: Bulk Delete Vendor Deposits
      description: 'Hard-delete multiple deposits by id. Returns a message with the
        delete count.


        :::info[Required scope: `accounting:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 1
                - 2
                - 3
      parameters: []
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: accounting:write
      operationId: post-api-vendor-deposits-bulk-delete
  /api/vendor-deposits/bulk-create:
    post:
      tags:
      - Vendor Deposits
      summary: Bulk Create Vendor Deposits
      description: 'Create multiple vendor deposits in one call — one per item, each
        linked to a purchase order. Shared header fields (deposit_date, due_date,
        external_reference, notes, proportional_apply_enabled) apply to every deposit
        created.


        :::info[Required scope: `accounting:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Item fields: purchase_order_id (required), currency_id, currency_rate, currency_id_tenant_snapshot,
        amount, and amount_in_tenant_currency are required; supplier_id, tax_amount,
        tax_amount_in_tenant_currency, tax_lines, payment_term_schedule_line_index,
        inbound_shipment_id, payment_term_schedule_snapshot, and is_ownership_transfer
        are optional.


        Returns 201 with the created deposits.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                deposit_date:
                  type: string
                due_date:
                  type: string
                external_reference:
                  type: string
                notes:
                  type: string
                proportional_apply_enabled:
                  type: boolean
                items:
                  type: array
                  items:
                    type: object
                    properties:
                      purchase_order_id:
                        type: integer
                      supplier_id:
                        type: integer
                      currency_id:
                        type: integer
                      currency_rate:
                        type: integer
                      currency_id_tenant_snapshot:
                        type: integer
                      amount:
                        type: integer
                      amount_in_tenant_currency:
                        type: integer
                      tax_amount:
                        type: integer
                      tax_amount_in_tenant_currency:
                        type: integer
                      payment_term_schedule_line_index:
                        type: integer
                      inbound_shipment_id:
                        type: string
                        nullable: true
                      is_ownership_transfer:
                        type: boolean
              example:
                deposit_date: '2026-07-07'
                due_date: '2026-08-01'
                external_reference: WIRE-20260707-001
                notes: Deposits for July purchase orders
                proportional_apply_enabled: false
                items:
                - purchase_order_id: 310
                  supplier_id: 7
                  currency_id: 1
                  currency_rate: 1
                  currency_id_tenant_snapshot: 1
                  amount: 1500
                  amount_in_tenant_currency: 1500
                  tax_amount: 0
                  tax_amount_in_tenant_currency: 0
                  payment_term_schedule_line_index: 1
                  inbound_shipment_id: null
                  is_ownership_transfer: false
      parameters: []
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        deposit_number:
                          type: string
                        status:
                          type: string
                        status_label:
                          type: string
                        supplier_id:
                          type: integer
                        supplier:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                            email:
                              type: string
                            wire_instructions:
                              type: string
                            link_route:
                              type: string
                        purchase_order_id:
                          type: integer
                        payment_term_schedule_line_index:
                          type: integer
                        inbound_shipment_id:
                          type: string
                          nullable: true
                        payment_term_schedule_snapshot:
                          type: object
                          properties:
                            label:
                              type: string
                            trigger_event:
                              type: string
                            percentage:
                              type: integer
                        is_ownership_transfer:
                          type: boolean
                        ownership_transferred_at:
                          type: string
                          nullable: true
                        purchase_order:
                          type: object
                          properties:
                            id:
                              type: integer
                            purchase_order_number:
                              type: string
                            link_route:
                              type: string
                            link_type:
                              type: string
                            link_type_label:
                              type: string
                            link_id:
                              type: integer
                            link_reference:
                              type: string
                        currency_id:
                          type: integer
                        currency:
                          type: object
                          properties:
                            id:
                              type: integer
                            code:
                              type: string
                            symbol:
                              type: string
                        currency_rate:
                          type: integer
                        currency_id_tenant_snapshot:
                          type: integer
                        tenant_currency:
                          type: object
                          properties:
                            id:
                              type: integer
                            code:
                              type: string
                            symbol:
                              type: string
                        amount:
                          type: integer
                        amount_in_tenant_currency:
                          type: integer
                        amount_paid:
                          type: integer
                        amount_paid_in_tenant_currency:
                          type: integer
                        amount_applied:
                          type: integer
                        amount_applied_in_tenant_currency:
                          type: integer
                        amount_refunded:
                          type: integer
                        amount_refunded_in_tenant_currency:
                          type: integer
                        amount_written_off:
                          type: integer
                        amount_written_off_in_tenant_currency:
                          type: integer
                        available_balance:
                          type: integer
                        available_balance_in_tenant_currency:
                          type: integer
                        tax_amount:
                          type: integer
                        tax_amount_in_tenant_currency:
                          type: integer
                        tax_lines:
                          type: string
                          nullable: true
                        deposit_date:
                          type: string
                        due_date:
                          type: string
                        paid_at:
                          type: string
                          nullable: true
                        external_reference:
                          type: string
                        payee_bank_details:
                          type: string
                          nullable: true
                        bank_details_verified_at:
                          type: string
                          nullable: true
                        bank_details_verified_by:
                          type: string
                          nullable: true
                        bank_details_verified_by_user:
                          type: string
                          nullable: true
                        payment_requested_at:
                          type: string
                          nullable: true
                        payment_requested_by:
                          type: string
                          nullable: true
                        payment_requested_by_user:
                          type: string
                          nullable: true
                        remittance_sent_at:
                          type: string
                          nullable: true
                        notes:
                          type: string
                        proportional_apply_enabled:
                          type: boolean
                        auto_apply_enabled:
                          type: string
                          nullable: true
                        auto_apply_effective:
                          type: boolean
                        approved_by:
                          type: string
                          nullable: true
                        approver:
                          type: string
                          nullable: true
                        approved_at:
                          type: string
                          nullable: true
                        approval_notes:
                          type: string
                          nullable: true
                        submit_action:
                          type: string
                        submit_action_label:
                          type: string
                        created_by:
                          type: integer
                        creator:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        applications:
                          type: array
                        payments:
                          type: array
                        refunds:
                          type: array
                        created_at:
                          type: string
                        updated_at:
                          type: string
                        archived_at:
                          type: string
                          nullable: true
                  message:
                    type: string
                example:
                  data:
                  - id: 42
                    deposit_number: DEP-000042
                    status: draft
                    status_label: Draft
                    supplier_id: 7
                    supplier:
                      id: 7
                      name: Acme Components Ltd
                      email: accounts@acme-components.com
                      wire_instructions: Routing 026009593, account 4426123456
                      link_route: /v2/crm/suppliers/7
                    purchase_order_id: 310
                    payment_term_schedule_line_index: 1
                    inbound_shipment_id: null
                    payment_term_schedule_snapshot:
                      label: 30% deposit on order
                      trigger_event: po_approved
                      percentage: 30
                    is_ownership_transfer: false
                    ownership_transferred_at: null
                    purchase_order:
                      id: 310
                      purchase_order_number: PO-000310
                      link_route: /v2/orders/purchase-orders/310
                      link_type: App\Models\PurchaseOrder
                      link_type_label: Purchase Order
                      link_id: 310
                      link_reference: PO-000310
                    currency_id: 1
                    currency:
                      id: 1
                      code: USD
                      symbol: $
                    currency_rate: 1
                    currency_id_tenant_snapshot: 1
                    tenant_currency:
                      id: 1
                      code: USD
                      symbol: $
                    amount: 1500
                    amount_in_tenant_currency: 1500
                    amount_paid: 0
                    amount_paid_in_tenant_currency: 0
                    amount_applied: 0
                    amount_applied_in_tenant_currency: 0
                    amount_refunded: 0
                    amount_refunded_in_tenant_currency: 0
                    amount_written_off: 0
                    amount_written_off_in_tenant_currency: 0
                    available_balance: 0
                    available_balance_in_tenant_currency: 0
                    tax_amount: 0
                    tax_amount_in_tenant_currency: 0
                    tax_lines: null
                    deposit_date: '2026-06-15'
                    due_date: '2026-07-20'
                    paid_at: null
                    external_reference: WIRE-20260615-042
                    payee_bank_details: null
                    bank_details_verified_at: null
                    bank_details_verified_by: null
                    bank_details_verified_by_user: null
                    payment_requested_at: null
                    payment_requested_by: null
                    payment_requested_by_user: null
                    remittance_sent_at: null
                    notes: 30% deposit for PO-000310
                    proportional_apply_enabled: false
                    auto_apply_enabled: null
                    auto_apply_effective: true
                    approved_by: null
                    approver: null
                    approved_at: null
                    approval_notes: null
                    submit_action: approve
                    submit_action_label: Approve Deposit
                    created_by: 3
                    creator:
                      id: 3
                      name: Jane Operator
                    applications: []
                    payments: []
                    refunds: []
                    created_at: '2026-06-15T14:02:11+00:00'
                    updated_at: '2026-07-01T09:30:00+00:00'
                    archived_at: null
                  message: Deposits created.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: Deposit amount exceeds the remaining schedule amount for
                    this purchase order.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: accounting:write
      operationId: post-api-vendor-deposits-bulk-create
  /api/vendor-deposits/bulk-apply:
    post:
      tags:
      - Vendor Deposits
      summary: Bulk Apply Vendor Deposits
      description: 'Apply multiple deposits to purchase invoices (bills) in one operation.
        Each item names a deposit, a bill, and the amount to apply in the deposit''s
        currency.


        :::info[Required scope: `accounting:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        The applications are processed asynchronously in the background — the endpoint
        returns 202 Accepted immediately with a tracked_job_log_id you can use to
        follow progress.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                items:
                  type: array
                  items:
                    type: object
                    properties:
                      vendor_deposit_id:
                        type: integer
                      purchase_invoice_id:
                        type: integer
                      amount_in_deposit_currency:
                        type: integer
              example:
                items:
                - vendor_deposit_id: 42
                  purchase_invoice_id: 88
                  amount_in_deposit_currency: 500
                - vendor_deposit_id: 43
                  purchase_invoice_id: 91
                  amount_in_deposit_currency: 1200
      parameters: []
      responses:
        '202':
          description: Accepted
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 8231
                  message: Bulk apply started — track progress in the job tray.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: accounting:write
      operationId: post-api-vendor-deposits-bulk-apply
  /api/vendor-deposits/bulk-approve:
    post:
      tags:
      - Vendor Deposits
      summary: Bulk Approve Vendor Deposits
      description: 'Approve multiple vendor deposits in one operation. Deposit IDs
        must be unique and refer to existing deposits.


        :::info[Required scope: `accounting:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        The approvals are processed asynchronously in the background — the endpoint
        returns 202 Accepted immediately with a tracked_job_log_id you can use to
        follow progress.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                vendor_deposit_ids:
                  type: array
                  items:
                    type: integer
              example:
                vendor_deposit_ids:
                - 42
                - 43
                - 44
      parameters: []
      responses:
        '202':
          description: Accepted
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 8232
                  message: Bulk approve started — track progress in the job tray.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: accounting:write
      operationId: post-api-vendor-deposits-bulk-approve
  /api/vendor-deposits/import/preview:
    post:
      tags:
      - Vendor Deposits
      summary: Preview Vendor Deposit Import
      description: 'Preview a CSV import of vendor deposits before running it. References
        a previously uploaded CSV file by its stored name and returns the parsed records,
        the detected file headers, the list of importable fields, and any unmapped
        (difference) or missing required (required_difference) fields so the column
        mapping can be corrected before importing.


        :::info[Required scope: `accounting:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Body fields: original_name and stored_name are required; mapping (array of
        {file_field, expected_field} pairs), separator, escape, meta, and task_id
        are optional.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                original_name:
                  type: string
                stored_name:
                  type: string
                separator:
                  type: string
                mapping:
                  type: array
                  items:
                    type: object
                    properties:
                      file_field:
                        type: string
                      expected_field:
                        type: string
              example:
                original_name: vendor-deposits.csv
                stored_name: imports/2026/07/vendor-deposits-9f1c2a34.csv
                separator: ','
                mapping:
                - file_field: Deposit Number
                  expected_field: deposit_number
                - file_field: Supplier
                  expected_field: supplier
                - file_field: Amount
                  expected_field: amount
                - file_field: Deposit Date
                  expected_field: deposit_date
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      records:
                        type: array
                        items:
                          type: object
                          properties:
                            Deposit Number:
                              type: string
                            Supplier:
                              type: string
                            Amount:
                              type: string
                            Deposit Date:
                              type: string
                      file_headers:
                        type: array
                        items:
                          type: string
                      importable_fields:
                        type: array
                        items:
                          type: string
                      difference:
                        type: array
                      required_difference:
                        type: array
                      not_importable:
                        type: array
                      task_id:
                        type: string
                example:
                  data:
                    records:
                    - Deposit Number: DEP-000101
                      Supplier: Acme Components Ltd
                      Amount: '1500.00'
                      Deposit Date: 07/01/2026
                    file_headers:
                    - Deposit Number
                    - Supplier
                    - Amount
                    - Deposit Date
                    importable_fields:
                    - deposit_number
                    - supplier
                    - amount
                    - deposit_date
                    - due_date
                    - external_reference
                    - notes
                    difference: []
                    required_difference: []
                    not_importable: []
                    task_id: 9f1c2a34-77aa-4f0e-9a3d-1b2c3d4e5f60
        '400':
          description: Bad Request
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: object
                    properties:
                      ImportData:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: array
                example:
                  errors:
                    ImportData:
                    - message: 'CSV Import has invalid syntax: Unclosed quote on line
                        3.'
                      code: IsUnacceptable
                      data: []
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: accounting:write
      operationId: post-api-vendor-deposits-import-preview
  /api/vendor-deposits/import:
    post:
      tags:
      - Vendor Deposits
      summary: Import Vendor Deposits
      description: 'Import vendor deposits from a previously uploaded CSV file using
        the supplied column mapping. If required fields are missing from the mapping,
        the endpoint returns the same preview payload as the preview endpoint instead
        of importing.


        :::info[Required scope: `accounting:write`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Large files are imported asynchronously in the background — in that case the
        response data reads "The data will be imported shortly." Row-level validation
        failures return 500 with the per-row errors.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                original_name:
                  type: string
                stored_name:
                  type: string
                separator:
                  type: string
                mapping:
                  type: array
                  items:
                    type: object
                    properties:
                      file_field:
                        type: string
                      expected_field:
                        type: string
              example:
                original_name: vendor-deposits.csv
                stored_name: imports/2026/07/vendor-deposits-9f1c2a34.csv
                separator: ','
                mapping:
                - file_field: Deposit Number
                  expected_field: deposit_number
                - file_field: Supplier
                  expected_field: supplier
                - file_field: Amount
                  expected_field: amount
                - file_field: Deposit Date
                  expected_field: deposit_date
      parameters: []
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: string
                example:
                  data: Data import was successful.
        '500':
          description: Internal Server Error
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  errors:
                    type: object
                    properties:
                      ImportData:
                        type: array
                        items:
                          type: object
                          properties:
                            message:
                              type: string
                            code:
                              type: string
                            data:
                              type: object
                              properties:
                                '2':
                                  type: object
                                  properties:
                                    amount:
                                      type: array
                                      items:
                                        type: string
                example:
                  errors:
                    ImportData:
                    - message: Data import failed for some records
                      code: IsUnacceptable
                      data:
                        '2':
                          amount:
                          - The amount field is required.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: accounting:write
      operationId: post-api-vendor-deposits-import
  /api/walmart/{integrationInstance}/activity-log:
    get:
      tags:
      - Walmart
      summary: List Walmart Integration Activity Log
      description: 'Get a paginated activity history for a Walmart integration instance.
        Covers every Walmart entity tied to the instance — orders, catalog items,
        fulfillment locations, returns, and the integration settings themselves —
        newest first.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Each entry includes the event type (created, updated, deleted), the affected
        entity type and id, the changed attributes (with old values where available),
        the acting user''s name (null for system/background changes), and a timestamp.
        Returns a paginated result.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        log_name:
                          type: string
                        description:
                          type: string
                        event:
                          type: string
                        subject_type:
                          type: string
                        subject_id:
                          type: integer
                        properties:
                          type: object
                          properties:
                            attributes:
                              type: object
                              properties:
                                publishedStatus:
                                  type: string
                            old:
                              type: object
                              properties:
                                publishedStatus:
                                  type: string
                        causer_name:
                          type: string
                        created_at:
                          type: string
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 10231
                    log_name: default
                    description: updated
                    event: updated
                    subject_type: WalmartProduct
                    subject_id: 87
                    properties:
                      attributes:
                        publishedStatus: PUBLISHED
                      old:
                        publishedStatus: UNPUBLISHED
                    causer_name: Jane Operator
                    created_at: '2026-06-30T09:12:45.000000Z'
                  - id: 9812
                    description: updated
                    event: updated
                    subject_type: WalmartOrder
                    subject_id: 412
                    properties:
                      attributes:
                        status: Shipped
                      old:
                        status: Acknowledged
                    causer_name: Jane Operator
                    created_at: '2026-06-28T14:03:22.000000Z'
                  first_page_url: https://your-instance.test/api/walmart/1/activity-log?page=1
                  from: 1
                  last_page: 1
                  last_page_url: https://your-instance.test/api/walmart/1/activity-log?page=1
                  next_page_url: null
                  path: https://your-instance.test/api/walmart/1/activity-log
                  per_page: 15
                  prev_page_url: null
                  to: 2
                  total: 2
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-walmart-integrationinstance-activity-log
  /api/walmart/{integrationInstance}/supported-carriers:
    get:
      tags:
      - Walmart
      summary: List Walmart Supported Carriers
      description: 'Get the shipping carriers Walmart accepts on shipment confirmations
        (UPS, USPS, FedEx, DHL, OnTrac, and many more), together with the current
        mapping of each Walmart carrier to a shipping method in SKU.io.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Use this to discover valid carrier values before submitting fulfillments,
        and to review which internal shipping methods will be reported to Walmart
        for each carrier. `shipping_methods` lists all shipping methods available
        for mapping. Returns 404 if the integration instance has no linked sales channel.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      carriers:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            sales_channel_method:
                              type: string
                            shipping_method_id:
                              type: integer
                            shipping_method_name:
                              type: string
                      shipping_methods:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            full_name:
                              type: string
                example:
                  data:
                    carriers:
                    - id: 3
                      sales_channel_method: UPS
                      shipping_method_id: 12
                      shipping_method_name: UPS Ground
                    - id: null
                      sales_channel_method: USPS
                      shipping_method_id: null
                      shipping_method_name: null
                    - id: null
                      sales_channel_method: FedEx
                      shipping_method_id: null
                      shipping_method_name: null
                    shipping_methods:
                    - id: 12
                      full_name: UPS Ground
                    - id: 17
                      full_name: USPS Ground Advantage
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Sales channel not found for this integration instance.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-walmart-integrationinstance-supported-carriers
  /api/walmart/{integrationInstance}/locations/refresh-tracked:
    post:
      tags:
      - Walmart
      summary: Start Tracked Walmart Location Refresh
      description: 'Refresh the list of Walmart fulfillment locations (ship nodes)
        for this integration instance from the Walmart Marketplace API. This queues
        an asynchronous background job and returns immediately. Poll progress using
        the returned tracked_job_log_id.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 1234
                  message: Location refresh job has been queued
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-walmart-integrationinstance-locations-refresh-tracked
  /api/walmart/{integrationInstance}/orders/refresh-tracked:
    post:
      tags:
      - Walmart
      summary: Start Tracked Walmart Order Refresh
      description: 'Pull orders from the Walmart Marketplace API into SKU.io. This
        queues an asynchronous background job and returns immediately. Poll progress
        using the returned tracked_job_log_id.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Request body (all fields optional):

        - mode — which orders to pull: `latest` (default; orders modified since the
        most recent local order), `from_start_date` (orders modified since the integration''s
        configured start date), `date_range` (orders modified since `date_from`),
        or `all`.

        - date_from — start of the modification window (date). Used with mode `date_range`.

        - date_to — end of the window (date). Accepted for validation but the pull
        is open-ended from `date_from`.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                mode:
                  type: string
                date_from:
                  type: string
                date_to:
                  type: string
              example:
                mode: latest
                date_from: '2026-06-01'
                date_to: '2026-06-30'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 1234
                  message: Order refresh job has been queued
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      mode:
                        type: array
                        items:
                          type: string
                example:
                  message: The selected mode is invalid.
                  errors:
                    mode:
                    - The selected mode is invalid.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-walmart-integrationinstance-orders-refresh-tracked
  /api/walmart/{integrationInstance}/orders/latest-sync-info:
    get:
      tags:
      - Walmart
      summary: Get Walmart Orders Latest Sync Info
      description: 'Get a snapshot of the order sync state for this integration instance:
        the most recent Walmart order on record (id, order date, status), the total
        number of synced Walmart orders, and how many are (or are not yet) linked
        to a SKU.io sales order. Useful for deciding which refresh mode to run.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      latest_order_id:
                        type: string
                      latest_order_date:
                        type: string
                      latest_order_status:
                        type: string
                      total_orders:
                        type: integer
                      with_sku_order:
                        type: integer
                      without_sku_order:
                        type: integer
                example:
                  data:
                    latest_order_id: '1796277083022'
                    latest_order_date: '2026-06-27T00:00:00.000000Z'
                    latest_order_status: Shipped
                    total_orders: 1250
                    with_sku_order: 1198
                    without_sku_order: 52
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-walmart-integrationinstance-orders-latest-sync-info
  /api/walmart/{integrationInstance}/orders/archive:
    put:
      tags:
      - Walmart
      summary: Bulk Archive Walmart Orders
      description: 'Archive multiple Walmart orders in one call. Archived orders are
        hidden from active listings but remain available with their history. Only
        currently-active orders belonging to the integration instance are affected;
        already-archived orders are skipped.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Request body:

        - ids (required, array of integers) — the Walmart order ids (SKU.io internal
        ids) to archive.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 412
                - 413
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  archived_count:
                    type: integer
                example:
                  message: 2 orders archived successfully
                  archived_count: 2
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-walmart-integrationinstance-orders-archive
  /api/walmart/{integrationInstance}/orders/unarchive:
    put:
      tags:
      - Walmart
      summary: Bulk Unarchive Walmart Orders
      description: 'Restore multiple archived Walmart orders in one call. Only currently-archived
        orders belonging to the integration instance are affected.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Request body:

        - ids (required, array of integers) — the Walmart order ids (SKU.io internal
        ids) to unarchive.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 412
                - 413
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  unarchived_count:
                    type: integer
                example:
                  message: 2 orders unarchived successfully
                  unarchived_count: 2
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-walmart-integrationinstance-orders-unarchive
  /api/walmart/{integrationInstance}/orders/{order}/activity-log:
    get:
      tags:
      - Walmart
      summary: List Walmart Order Activity Log
      description: 'Get the paginated activity history for a single Walmart order,
        newest first. Each entry includes the event type, changed attributes with
        old values, the acting user''s name (null for system/background changes),
        and a timestamp.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      - name: order
        in: path
        schema:
          type: integer
        required: true
        description: Walmart order ID (SKU.io internal id)
        example: '412'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        description:
                          type: string
                        event:
                          type: string
                        subject_type:
                          type: string
                        subject_id:
                          type: integer
                        properties:
                          type: object
                          properties:
                            attributes:
                              type: object
                              properties:
                                status:
                                  type: string
                            old:
                              type: object
                              properties:
                                status:
                                  type: string
                        causer_name:
                          type: string
                        created_at:
                          type: string
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 9812
                    description: updated
                    event: updated
                    subject_type: WalmartOrder
                    subject_id: 412
                    properties:
                      attributes:
                        status: Shipped
                      old:
                        status: Acknowledged
                    causer_name: Jane Operator
                    created_at: '2026-06-28T14:03:22.000000Z'
                  first_page_url: https://your-instance.test/api/walmart/1/orders/412/activity-log?page=1
                  from: 1
                  last_page: 1
                  last_page_url: https://your-instance.test/api/walmart/1/orders/412/activity-log?page=1
                  next_page_url: null
                  path: https://your-instance.test/api/walmart/1/orders/412/activity-log
                  per_page: 15
                  prev_page_url: null
                  to: 1
                  total: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-walmart-integrationinstance-orders-order-activity-log
  /api/walmart/{integrationInstance}/orders/{order}/raw:
    get:
      tags:
      - Walmart
      summary: Get Raw Walmart Order
      description: 'Fetch the order directly from the Walmart Marketplace API and
        return Walmart''s raw purchase-order payload without any transformation. Useful
        for troubleshooting sync discrepancies — this is the live payload as Walmart
        returns it today, not the locally stored copy.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Returns 403 if the order does not belong to the integration instance, and
        500 if Walmart cannot be reached or rejects the request.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      - name: order
        in: path
        schema:
          type: integer
        required: true
        description: Walmart order ID (SKU.io internal id)
        example: '412'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      order:
                        type: object
                        properties:
                          purchaseOrderId:
                            type: string
                          customerOrderId:
                            type: string
                          customerEmailId:
                            type: string
                          orderDate:
                            type: integer
                          shippingInfo:
                            type: object
                            properties:
                              phone:
                                type: string
                              estimatedDeliveryTime:
                                type: integer
                              estimatedShipTime:
                                type: integer
                              methodCode:
                                type: string
                              postalAddress:
                                type: object
                                properties:
                                  name:
                                    type: string
                                  address1:
                                    type: string
                                  address2:
                                    type: string
                                  city:
                                    type: string
                                  state:
                                    type: string
                                  postalCode:
                                    type: string
                                  country:
                                    type: string
                                  addressType:
                                    type: string
                          orderLines:
                            type: object
                            properties:
                              orderLine:
                                type: array
                                items:
                                  type: object
                                  properties:
                                    lineNumber:
                                      type: string
                                    item:
                                      type: object
                                      properties:
                                        productName:
                                          type: string
                                        sku:
                                          type: string
                                    charges:
                                      type: object
                                      properties:
                                        charge:
                                          type: array
                                          items:
                                            type: object
                                            properties:
                                              chargeType:
                                                type: string
                                              chargeName:
                                                type: string
                                              chargeAmount:
                                                type: object
                                                properties:
                                                  currency:
                                                    type: string
                                                  amount:
                                                    type: number
                                              tax:
                                                type: object
                                                properties:
                                                  taxName:
                                                    type: string
                                                  taxAmount:
                                                    type: object
                                                    properties:
                                                      currency:
                                                        type: string
                                                      amount:
                                                        type: number
                                    orderLineQuantity:
                                      type: object
                                      properties:
                                        unitOfMeasurement:
                                          type: string
                                        amount:
                                          type: string
                                    statusDate:
                                      type: integer
                                    orderLineStatuses:
                                      type: object
                                      properties:
                                        orderLineStatus:
                                          type: array
                                          items:
                                            type: object
                                            properties:
                                              status:
                                                type: string
                                              statusQuantity:
                                                type: object
                                                properties:
                                                  unitOfMeasurement:
                                                    type: string
                                                  amount:
                                                    type: string
                                              trackingInfo:
                                                type: object
                                                properties:
                                                  shipDateTime:
                                                    type: integer
                                                  carrierName:
                                                    type: object
                                                    properties:
                                                      carrier:
                                                        type: string
                                                  methodCode:
                                                    type: string
                                                  trackingNumber:
                                                    type: string
                example:
                  data:
                    order:
                      purchaseOrderId: '1796277083022'
                      customerOrderId: '200010536482277'
                      customerEmailId: 0A31D21A44D449D9@relay.walmart.com
                      orderDate: 1750982400000
                      shippingInfo:
                        phone: '5555550123'
                        estimatedDeliveryTime: 1751673600000
                        estimatedShipTime: 1751068800000
                        methodCode: Value
                        postalAddress:
                          name: Jane Smith
                          address1: 123 Main St
                          address2: Apt 4B
                          city: Dallas
                          state: TX
                          postalCode: '75201'
                          country: USA
                          addressType: RESIDENTIAL
                      orderLines:
                        orderLine:
                        - lineNumber: '1'
                          item:
                            productName: Stainless Steel Water Bottle 32 oz
                            sku: WB-32-SS
                          charges:
                            charge:
                            - chargeType: PRODUCT
                              chargeName: ItemPrice
                              chargeAmount:
                                currency: USD
                                amount: 24.99
                              tax:
                                taxName: Tax1
                                taxAmount:
                                  currency: USD
                                  amount: 2.06
                          orderLineQuantity:
                            unitOfMeasurement: EACH
                            amount: '1'
                          statusDate: 1751155200000
                          orderLineStatuses:
                            orderLineStatus:
                            - status: Shipped
                              statusQuantity:
                                unitOfMeasurement: EACH
                                amount: '1'
                              trackingInfo:
                                shipDateTime: 1751155200000
                                carrierName:
                                  carrier: UPS
                                methodCode: Value
                                trackingNumber: 1Z999AA10123456784
        '403':
          description: Forbidden
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: Order does not belong to this integration instance
        '500':
          description: Internal Server Error
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                  message:
                    type: string
                example:
                  error: Failed to fetch raw order data from Walmart
                  message: Request timed out after 30 seconds
        '429': *id001
        '401': *id002
        '404': *id004
      operationId: get-api-walmart-integrationinstance-orders-order-raw
  /api/walmart/{integrationInstance}/orders/{order}/archive:
    put:
      tags:
      - Walmart
      summary: Archive Walmart Order
      description: 'Archive a single Walmart order. Archived orders are hidden from
        active listings but remain available with their history. Returns whether the
        order was actually archived (`archived` is false when it was already archived).
        Returns 403 if the order does not belong to the integration instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      - name: order
        in: path
        schema:
          type: integer
        required: true
        description: Walmart order ID (SKU.io internal id)
        example: '412'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  archived:
                    type: boolean
                example:
                  message: Order archived successfully
                  archived: true
        '403':
          description: Forbidden
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: Order does not belong to this integration instance
        '429': *id001
        '401': *id002
        '404': *id004
        '422': *id005
      operationId: put-api-walmart-integrationinstance-orders-order-archive
  /api/walmart/{integrationInstance}/orders/{order}/unarchive:
    put:
      tags:
      - Walmart
      summary: Unarchive Walmart Order
      description: 'Restore a single archived Walmart order. Returns whether the order
        was actually restored (`unarchived` is false when it was already active).
        Returns 403 if the order does not belong to the integration instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      - name: order
        in: path
        schema:
          type: integer
        required: true
        description: Walmart order ID (SKU.io internal id)
        example: '412'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  unarchived:
                    type: boolean
                example:
                  message: Order unarchived successfully
                  unarchived: true
        '403':
          description: Forbidden
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: Order does not belong to this integration instance
        '429': *id001
        '401': *id002
        '404': *id004
        '422': *id005
      operationId: put-api-walmart-integrationinstance-orders-order-unarchive
  /api/walmart/{integrationInstance}/pre-start-date-orders:
    get:
      tags:
      - Walmart
      summary: List Pre-Start-Date Walmart Orders
      description: 'Query the Walmart Marketplace API live for orders created before
        the account''s inventory start date, within a chosen creation-date window.
        Returns lightweight order summaries with an eligibility assessment for import:
        cancelled orders are marked ineligible, and orders that already exist in SKU.io
        are flagged `already_imported`.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Up to 2,000 matching orders are returned per query (Walmart pagination is
        followed for at most 10 pages). The inventory start date must be configured;
        both window bounds must fall before it (422 otherwise). Returns 500 if Walmart
        cannot be reached.'
      parameters:
      - name: created_at_min
        in: query
        schema:
          type: string
        description: Required. Start of the order-creation window (date). Must be
          before the inventory start date.
        example: '2025-10-01'
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        purchase_order_id:
                          type: string
                        customer_order_id:
                          type: string
                        name:
                          type: string
                        email:
                          type: string
                        created_at:
                          type: string
                        order_status:
                          type: string
                        total_price:
                          type: number
                        currency:
                          type: string
                        line_items:
                          type: array
                          items:
                            type: object
                            properties:
                              title:
                                type: string
                              sku:
                                type: string
                              quantity:
                                type: integer
                              current_quantity:
                                type: integer
                              price:
                                type: number
                              variant_title:
                                type: string
                                nullable: true
                        eligible:
                          type: boolean
                        eligibility_reason:
                          type: string
                          nullable: true
                        already_imported:
                          type: boolean
                  inventory_start_date:
                    type: string
                  meta:
                    type: object
                    properties:
                      total_queried:
                        type: integer
                      eligible_count:
                        type: integer
                      already_imported_count:
                        type: integer
                example:
                  data:
                  - purchase_order_id: '1796277083022'
                    customer_order_id: '200010536482277'
                    name: Jane Smith
                    email: 0A31D21A44D449D9@relay.walmart.com
                    created_at: '2025-11-14T18:20:00Z'
                    order_status: Delivered
                    total_price: 49.98
                    currency: USD
                    line_items:
                    - title: Stainless Steel Water Bottle 32 oz
                      sku: WB-32-SS
                      quantity: 2
                      current_quantity: 2
                      price: 24.99
                      variant_title: null
                    eligible: true
                    eligibility_reason: null
                    already_imported: false
                  inventory_start_date: '2026-01-01'
                  meta:
                    total_queried: 1
                    eligible_count: 1
                    already_imported_count: 0
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      created_at_min:
                        type: array
                        items:
                          type: string
                example:
                  message: Created at min must be before the inventory start date.
                  errors:
                    created_at_min:
                    - Created at min must be before the inventory start date.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-walmart-integrationinstance-pre-start-date-orders
  /api/walmart/{integrationInstance}/pre-start-date-orders/search:
    get:
      tags:
      - Walmart
      summary: Search Pre-Start-Date Walmart Orders
      description: 'Search the Walmart Marketplace API live for specific orders created
        before the inventory start date. `purchase_order_id` performs a direct order
        lookup; `customer_order_id` and `order_number` scan up to two years of pre-start-date
        orders and match on the given value.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Results use the same summary shape and eligibility flags as the pre-start-date
        listing. The inventory start date must be configured (422 otherwise). Returns
        500 if Walmart cannot be reached.'
      parameters:
      - name: search_by
        in: query
        schema:
          type: string
        description: 'Required. Field to search on: purchase_order_id (direct lookup),
          customer_order_id, or order_number.'
        example: purchase_order_id
      - name: search_term
        in: query
        schema:
          type: integer
        description: Required. The value to search for (1-255 characters).
        example: '1796277083022'
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        purchase_order_id:
                          type: string
                        customer_order_id:
                          type: string
                        name:
                          type: string
                        email:
                          type: string
                        created_at:
                          type: string
                        order_status:
                          type: string
                        total_price:
                          type: number
                        currency:
                          type: string
                        line_items:
                          type: array
                          items:
                            type: object
                            properties:
                              title:
                                type: string
                              sku:
                                type: string
                              quantity:
                                type: integer
                              current_quantity:
                                type: integer
                              price:
                                type: number
                              variant_title:
                                type: string
                                nullable: true
                        eligible:
                          type: boolean
                        eligibility_reason:
                          type: string
                          nullable: true
                        already_imported:
                          type: boolean
                  inventory_start_date:
                    type: string
                  meta:
                    type: object
                    properties:
                      total_queried:
                        type: integer
                      eligible_count:
                        type: integer
                      already_imported_count:
                        type: integer
                example:
                  data:
                  - purchase_order_id: '1796277083022'
                    customer_order_id: '200010536482277'
                    name: Jane Smith
                    email: 0A31D21A44D449D9@relay.walmart.com
                    created_at: '2025-11-14T18:20:00Z'
                    order_status: Delivered
                    total_price: 49.98
                    currency: USD
                    line_items:
                    - title: Stainless Steel Water Bottle 32 oz
                      sku: WB-32-SS
                      quantity: 2
                      current_quantity: 2
                      price: 24.99
                      variant_title: null
                    eligible: true
                    eligibility_reason: null
                    already_imported: false
                  inventory_start_date: '2026-01-01'
                  meta:
                    total_queried: 1
                    eligible_count: 1
                    already_imported_count: 0
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      search_by:
                        type: array
                        items:
                          type: string
                example:
                  message: The selected search by is invalid.
                  errors:
                    search_by:
                    - The selected search by is invalid.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-walmart-integrationinstance-pre-start-date-orders-search
  /api/walmart/{integrationInstance}/pre-start-date-orders/import:
    post:
      tags:
      - Walmart
      summary: Import Pre-Start-Date Walmart Orders
      description: 'Import selected pre-start-date orders from Walmart. For each purchase
        order id, the full order is downloaded from the Walmart Marketplace API, saved
        through the standard order pipeline, and flagged as a pre-start-date import
        (so it does not affect inventory).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Because each order requires its own throttled Walmart Marketplace API call,
        the import runs asynchronously as a queued background job. The request returns
        immediately with a tracked job log id that can be polled to follow the import''s
        progress.


        **Requires the inventory start date to be set** — returns 422 otherwise.


        **Path Parameters:**

        - `integrationInstance` - The Walmart integration instance ID


        **Request Body:**

        - `purchase_order_ids` (required, array of strings, 1-10,000 entries) — Walmart
        purchase order ids to import.


        **Behavior:**

        - Runs as a background import — the request returns right away with a tracked
        job log id; the orders are fetched and stored asynchronously

        - Orders that already exist locally are flagged as pre-start-date imports
        instead of being re-imported

        - Cancelled or not-found orders are skipped


        **Response:**

        - `data.tracked_job_log_id` - id of the tracked job log; poll it to follow
        import progress

        - `message` - human-readable confirmation of how many orders are being imported'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                purchase_order_ids:
                  type: array
                  items:
                    type: string
              example:
                purchase_order_ids:
                - '1796277083022'
                - '1796277083055'
                - '1796277083060'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 4821
                  message: Importing 2 pre-start-date orders.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: Inventory start date must be set before importing pre-start-date
                    orders.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-walmart-integrationinstance-pre-start-date-orders-import
  /api/walmart/{integrationInstance}/products/refresh-tracked:
    post:
      tags:
      - Walmart
      summary: Start Tracked Walmart Product Refresh
      description: 'Pull the Walmart item catalog for this integration instance from
        the Walmart Marketplace API into SKU.io. This queues an asynchronous background
        job and returns immediately. Poll progress using the returned tracked_job_log_id.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 1234
                  message: Product refresh job has been queued
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-walmart-integrationinstance-products-refresh-tracked
  /api/walmart/{integrationInstance}/products/latest-sync-info:
    get:
      tags:
      - Walmart
      summary: Get Walmart Products Latest Sync Info
      description: 'Get a snapshot of the catalog sync state for this integration
        instance: the most recently updated Walmart item (title and update time),
        total synced items, and how many are mapped (or not yet mapped) to SKU.io
        products.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      latest_product_title:
                        type: string
                      latest_product_date:
                        type: string
                      total_products:
                        type: integer
                      mapped_products:
                        type: integer
                      unmapped_products:
                        type: integer
                      last_synced_at:
                        type: string
                example:
                  data:
                    latest_product_title: Stainless Steel Water Bottle 32 oz
                    latest_product_date: '2026-06-29T21:15:03+00:00'
                    total_products: 340
                    mapped_products: 312
                    unmapped_products: 28
                    last_synced_at: '2026-06-29T21:15:03+00:00'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-walmart-integrationinstance-products-latest-sync-info
  /api/walmart/{integrationInstance}/products/{product}/orders:
    get:
      tags:
      - Walmart
      summary: List Orders for Walmart Product
      description: 'Get a paginated list of Walmart orders that contain this Walmart
        item, matched by the item''s SKU across the instance''s order lines. Orders
        are returned newest first as stored order records, including Walmart identifiers,
        status, totals, and the stored raw payload (`json_object`).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Returns 403 if the product does not belong to the integration instance.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: Walmart product ID (SKU.io internal id)
        example: '87'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        customerOrderId:
                          type: string
                        purchaseOrderId:
                          type: string
                        customerEmailId:
                          type: string
                        customerName:
                          type: string
                        estimatedDeliveryDate:
                          type: string
                        estimatedShipDate:
                          type: string
                        shipNodeType:
                          type: string
                        status:
                          type: string
                        orderDate:
                          type: string
                        currency:
                          type: string
                        total:
                          type: string
                        syncStatus:
                          type: string
                        pre_start_date_import:
                          type: boolean
                        json_object:
                          type: object
                          properties:
                            purchaseOrderId:
                              type: string
                            customerOrderId:
                              type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                        archived_at:
                          type: string
                          nullable: true
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 412
                    integration_instance_id: 1
                    customerOrderId: '200010536482277'
                    purchaseOrderId: '1796277083022'
                    customerEmailId: 0A31D21A44D449D9@relay.walmart.com
                    customerName: Jane Smith
                    estimatedDeliveryDate: '2026-07-05 00:00:00'
                    estimatedShipDate: '2026-06-28 00:00:00'
                    shipNodeType: SellerFulfilled
                    status: Shipped
                    orderDate: '2026-06-27T00:00:00.000000Z'
                    currency: USD
                    total: '27.05'
                    syncStatus: synced
                    pre_start_date_import: false
                    json_object:
                      purchaseOrderId: '1796277083022'
                      customerOrderId: '200010536482277'
                    created_at: '2026-06-27T02:14:55.000000Z'
                    updated_at: '2026-06-28T11:40:19.000000Z'
                    archived_at: null
                  first_page_url: https://your-instance.test/api/walmart/1/products/87/orders?page=1
                  from: 1
                  last_page: 1
                  last_page_url: https://your-instance.test/api/walmart/1/products/87/orders?page=1
                  next_page_url: null
                  path: https://your-instance.test/api/walmart/1/products/87/orders
                  per_page: 10
                  prev_page_url: null
                  to: 1
                  total: 1
        '403':
          description: Forbidden
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: Product does not belong to this integration instance
        '429': *id001
        '401': *id002
        '404': *id004
      operationId: get-api-walmart-integrationinstance-products-product-orders
  /api/walmart/{integrationInstance}/products/{product}/sync:
    post:
      tags:
      - Walmart
      summary: Sync Walmart Product
      description: 'Re-fetch a single item from the Walmart Marketplace API and update
        the local record with the latest data (title, price, identifiers, publish
        status). Runs synchronously and returns the refreshed item, including any
        mapped SKU.io product. If the item can no longer be found on Walmart, a message
        is returned and the local record is left unchanged.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: Walmart product ID (SKU.io internal id)
        example: '87'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: Success
                  value:
                    data:
                      id: 87
                      integration_instance_id: 1
                      mart: WALMART_US
                      sku: WB-32-SS
                      condition: New
                      wpid: 0RCPILAXM0C1
                      upc: '884912129123'
                      gtin: 00884912129123
                      productName: Stainless Steel Water Bottle 32 oz
                      shelf: '["Home","Kitchen & Dining","Drinkware"]'
                      productType: Water Bottles
                      priceCurrency: USD
                      priceAmount: 24.99
                      publishedStatus: PUBLISHED
                      lifecycleStatus: ACTIVE
                      fulfillment_type: seller_fulfilled
                      product_listing_id: 902
                      product:
                        id: 45
                        name: Stainless Steel Water Bottle 32 oz
                        sku: WB-32-SS
                        default_financial_line_type_id: 2
                        default_financial_line_type:
                          id: 2
                          name: Product Sales
                          classification: revenue
                        listing_id: 902
                      subscription_offering: null
                      mapped_at: '2026-03-15T09:30:00.000000Z'
                      mapped_sku: WB-32-SS
                      json_object:
                        sku: WB-32-SS
                        wpid: 0RCPILAXM0C1
                      created_at: '2026-03-14T10:02:31.000000Z'
                      updated_at: '2026-06-30T08:12:44.000000Z'
                example-1:
                  summary: Not found on Walmart
                  value:
                    message: Product not found in Walmart or sync failed.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-walmart-integrationinstance-products-product-sync
  /api/walmart/{integrationInstance}/products/deleteable:
    put:
      tags:
      - Walmart
      summary: Check Walmart Products Deleteable
      description: 'Check whether the given Walmart items can be deleted from SKU.io,
        before running a bulk delete. Returns one entry per item with a `deleteable`
        flag and a `reason` when deletion is blocked.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Request body — one of:

        - ids (array of integers) — explicit Walmart product ids (must belong to the
        integration instance).

        - mode — set to "all" to check every Walmart item on the instance instead
        of passing ids.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 87
                - 88
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        deleteable:
                          type: boolean
                        reason:
                          type: boolean
                example:
                  data:
                  - id: 87
                    deleteable: true
                    reason: false
                  - id: 88
                    deleteable: true
                    reason: false
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-walmart-integrationinstance-products-deleteable
  /api/walmart/{integrationInstance}/mappings:
    get:
      tags:
      - Walmart
      summary: Get Walmart Field Mappings
      description: 'Get the field-mapping configuration for a Walmart integration
        instance: which Walmart item fields (title, price, identifiers, and so on)
        populate which SKU.io product fields during catalog sync.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        The response includes the built-in default mappings, any custom overrides
        configured for this instance, and the effective mappings actually applied
        (defaults merged with overrides). `available_walmart_fields` and `available_sku_fields`
        describe every field that can be used on each side, grouped and typed.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      integration_instance_id:
                        type: integer
                      integration_name:
                        type: string
                      mappings:
                        type: array
                        items:
                          type: object
                          properties:
                            listing_field:
                              type: string
                            sku_field:
                              type: string
                            parsers:
                              type: array
                            is_default:
                              type: boolean
                      available_walmart_fields:
                        type: object
                        properties:
                          sku:
                            type: object
                            properties:
                              name:
                                type: string
                              label:
                                type: string
                              type:
                                type: string
                              description:
                                type: string
                              group:
                                type: string
                          productName:
                            type: object
                            properties:
                              name:
                                type: string
                              label:
                                type: string
                              type:
                                type: string
                              description:
                                type: string
                              group:
                                type: string
                          upc:
                            type: object
                            properties:
                              name:
                                type: string
                              label:
                                type: string
                              type:
                                type: string
                              description:
                                type: string
                              group:
                                type: string
                      available_sku_fields:
                        type: object
                        properties:
                          sku:
                            type: object
                            properties:
                              name:
                                type: string
                              label:
                                type: string
                              type:
                                type: string
                              description:
                                type: string
                              group:
                                type: string
                          name:
                            type: object
                            properties:
                              name:
                                type: string
                              label:
                                type: string
                              type:
                                type: string
                              description:
                                type: string
                              group:
                                type: string
                          price:
                            type: object
                            properties:
                              name:
                                type: string
                              label:
                                type: string
                              type:
                                type: string
                              description:
                                type: string
                              group:
                                type: string
                      default_mappings:
                        type: array
                        items:
                          type: object
                          properties:
                            listing_field:
                              type: string
                            sku_field:
                              type: string
                            parsers:
                              type: array
                            is_default:
                              type: boolean
                      custom_mappings:
                        type: array
                      effective_mappings:
                        type: array
                        items:
                          type: object
                          properties:
                            listing_field:
                              type: string
                            sku_field:
                              type: string
                            parsers:
                              type: array
                            is_default:
                              type: boolean
                example:
                  data:
                    integration_instance_id: 1
                    integration_name: Walmart US Store
                    mappings:
                    - listing_field: productName
                      sku_field: name
                      parsers: []
                      is_default: true
                    - listing_field: priceAmount
                      sku_field: price
                      parsers: []
                      is_default: true
                    available_walmart_fields:
                      sku:
                        name: sku
                        label: SKU
                        type: string
                        description: Walmart product SKU
                        group: Identifiers
                      productName:
                        name: productName
                        label: Product Name
                        type: string
                        description: Walmart item title
                        group: Details
                      upc:
                        name: upc
                        label: UPC
                        type: string
                        description: Universal Product Code
                        group: Identifiers
                    available_sku_fields:
                      sku:
                        name: sku
                        label: SKU
                        type: string
                        description: Product SKU
                        group: Identifiers
                      name:
                        name: name
                        label: Name
                        type: string
                        description: Product name
                        group: Details
                      price:
                        name: price
                        label: Price
                        type: number
                        description: Selling price
                        group: Pricing
                    default_mappings:
                    - listing_field: productName
                      sku_field: name
                      parsers: []
                      is_default: true
                    - listing_field: priceAmount
                      sku_field: price
                      parsers: []
                      is_default: true
                    custom_mappings: []
                    effective_mappings:
                    - listing_field: productName
                      sku_field: name
                      parsers: []
                      is_default: true
                    - listing_field: priceAmount
                      sku_field: price
                      parsers: []
                      is_default: true
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-walmart-integrationinstance-mappings
    put:
      tags:
      - Walmart
      summary: Update Walmart Field Mappings
      description: 'Replace the custom field-mapping overrides for a Walmart integration
        instance. The submitted mappings are stored as instance-specific overrides
        on top of the built-in defaults; the response returns the resulting effective
        mappings.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Request body:

        - mappings (required, array) — each entry: { listing_field (required string,
        a Walmart field name), sku_field (required string, a SKU.io product field
        name), parsers (optional array of value-transformation steps) }.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                mappings:
                  type: array
                  items:
                    type: object
                    properties:
                      listing_field:
                        type: string
                      sku_field:
                        type: string
                      parsers:
                        type: array
              example:
                mappings:
                - listing_field: productName
                  sku_field: name
                  parsers: []
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      integration_instance_id:
                        type: integer
                      integration_name:
                        type: string
                      mappings:
                        type: array
                        items:
                          type: object
                          properties:
                            listing_field:
                              type: string
                            sku_field:
                              type: string
                            parsers:
                              type: array
                            is_default:
                              type: boolean
                      effective_mappings:
                        type: array
                        items:
                          type: object
                          properties:
                            listing_field:
                              type: string
                            sku_field:
                              type: string
                            parsers:
                              type: array
                            is_default:
                              type: boolean
                  message:
                    type: string
                example:
                  data:
                    integration_instance_id: 1
                    integration_name: Walmart US Store
                    mappings:
                    - listing_field: productName
                      sku_field: name
                      parsers: []
                      is_default: false
                    effective_mappings:
                    - listing_field: productName
                      sku_field: name
                      parsers: []
                      is_default: false
                  message: Field mappings updated successfully
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      mappings:
                        type: array
                        items:
                          type: string
                example:
                  message: The mappings field is required.
                  errors:
                    mappings:
                    - The mappings field is required.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: put-api-walmart-integrationinstance-mappings
  /api/walmart/{integrationInstance}/fulfillments:
    get:
      tags:
      - Walmart
      summary: List Walmart Fulfillments
      description: 'Get a paginated list of completed fulfillments for sales orders
        that originated from this Walmart integration instance — both those already
        submitted to Walmart and those still pending. Each entry includes tracking
        details, carrier and shipping method, the linked sales order and Walmart order
        identifiers, the fulfilling warehouse, and a `sync_status` of submitted or
        pending.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        fulfillment_number:
                          type: string
                        fulfillment_type:
                          type: string
                        status:
                          type: string
                        tracking_number:
                          type: string
                        cost:
                          type: number
                        fulfilled_at:
                          type: string
                        submitted_to_sales_channel_at:
                          type: string
                        created_at:
                          type: string
                        carrier:
                          type: string
                        shipping_method_display:
                          type: string
                        sales_order:
                          type: object
                          properties:
                            id:
                              type: integer
                            sales_order_number:
                              type: string
                        walmart_order:
                          type: object
                          properties:
                            id:
                              type: integer
                            purchaseOrderId:
                              type: string
                            customerOrderId:
                              type: string
                        warehouse:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        shipping_method:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        sync_status:
                          type: string
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  next_page_url:
                    type: string
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 55
                    fulfillment_number: F-1042
                    fulfillment_type: shipping
                    status: fulfilled
                    tracking_number: 1Z999AA10123456784
                    cost: 8.45
                    fulfilled_at: '2026-06-27T18:22:10+00:00'
                    submitted_to_sales_channel_at: '2026-06-27T18:30:02+00:00'
                    created_at: '2026-06-27T18:22:11+00:00'
                    carrier: UPS
                    shipping_method_display: UPS Ground
                    sales_order:
                      id: 3120
                      sales_order_number: SO-3120
                    walmart_order:
                      id: 412
                      purchaseOrderId: '1796277083022'
                      customerOrderId: '200010536482277'
                    warehouse:
                      id: 5
                      name: Main Warehouse
                    shipping_method:
                      id: 12
                      name: UPS Ground
                    sync_status: submitted
                  - id: 61
                    fulfillment_number: F-1057
                    fulfillment_type: shipping
                    status: fulfilled
                    tracking_number: '9400111899220123456781'
                    cost: 8.45
                    fulfilled_at: '2026-06-27T18:22:10+00:00'
                    submitted_to_sales_channel_at: null
                    created_at: '2026-06-27T18:22:11+00:00'
                    carrier: USPS
                    shipping_method_display: USPS Ground Advantage
                    sales_order:
                      id: 3120
                      sales_order_number: SO-3120
                    walmart_order:
                      id: 412
                      purchaseOrderId: '1796277083022'
                      customerOrderId: '200010536482277'
                    warehouse:
                      id: 5
                      name: Main Warehouse
                    shipping_method:
                      id: 17
                      name: USPS Ground Advantage
                    sync_status: pending
                  first_page_url: https://your-instance.test/api/walmart/1/fulfillments?page=1
                  from: 1
                  last_page: 5
                  last_page_url: https://your-instance.test/api/walmart/1/fulfillments?page=5
                  next_page_url: https://your-instance.test/api/walmart/1/fulfillments?page=2
                  path: https://your-instance.test/api/walmart/1/fulfillments
                  per_page: 10
                  prev_page_url: null
                  to: 2
                  total: 42
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-walmart-integrationinstance-fulfillments
  /api/walmart/{integrationInstance}/fulfillments/pending:
    get:
      tags:
      - Walmart
      summary: List Pending Walmart Fulfillments
      description: 'Get a paginated list of completed fulfillments that have not yet
        been submitted to Walmart. Pickup fulfillments and fulfillments on cancelled
        orders are excluded. Results are ordered newest first. These are the fulfillments
        that the automatic sync (every 10 minutes) or a manual submit call will send
        to Walmart.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        fulfillment_number:
                          type: string
                        fulfillment_type:
                          type: string
                        status:
                          type: string
                        tracking_number:
                          type: string
                        cost:
                          type: number
                        fulfilled_at:
                          type: string
                        submitted_to_sales_channel_at:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                        carrier:
                          type: string
                        shipping_method_display:
                          type: string
                        sales_order:
                          type: object
                          properties:
                            id:
                              type: integer
                            sales_order_number:
                              type: string
                        walmart_order:
                          type: object
                          properties:
                            id:
                              type: integer
                            purchaseOrderId:
                              type: string
                            customerOrderId:
                              type: string
                        warehouse:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        shipping_method:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        sync_status:
                          type: string
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 61
                    fulfillment_number: F-1057
                    fulfillment_type: shipping
                    status: fulfilled
                    tracking_number: '9400111899220123456781'
                    cost: 8.45
                    fulfilled_at: '2026-06-27T18:22:10+00:00'
                    submitted_to_sales_channel_at: null
                    created_at: '2026-06-27T18:22:11+00:00'
                    carrier: USPS
                    shipping_method_display: USPS Ground Advantage
                    sales_order:
                      id: 3120
                      sales_order_number: SO-3120
                    walmart_order:
                      id: 412
                      purchaseOrderId: '1796277083022'
                      customerOrderId: '200010536482277'
                    warehouse:
                      id: 5
                      name: Main Warehouse
                    shipping_method:
                      id: 17
                      name: USPS Ground Advantage
                    sync_status: pending
                  first_page_url: https://your-instance.test/api/walmart/1/fulfillments/pending?page=1
                  from: 1
                  last_page: 1
                  last_page_url: https://your-instance.test/api/walmart/1/fulfillments/pending?page=1
                  next_page_url: null
                  path: https://your-instance.test/api/walmart/1/fulfillments/pending
                  per_page: 10
                  prev_page_url: null
                  to: 1
                  total: 3
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-walmart-integrationinstance-fulfillments-pending
  /api/walmart/{integrationInstance}/fulfillments/stats:
    get:
      tags:
      - Walmart
      summary: Get Walmart Fulfillment Stats
      description: 'Get summary figures for fulfillment syncing on this integration
        instance: how many completed fulfillments are still waiting to be submitted
        to Walmart, and the automatic sync schedule.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      pending_sync_count:
                        type: integer
                      sync_schedule:
                        type: object
                        properties:
                          interval:
                            type: integer
                          unit:
                            type: string
                          description:
                            type: string
                example:
                  data:
                    pending_sync_count: 3
                    sync_schedule:
                      interval: 10
                      unit: minutes
                      description: Fulfillments are automatically synced every 10
                        minutes
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-walmart-integrationinstance-fulfillments-stats
  /api/walmart/{integrationInstance}/fulfillments/{salesOrderFulfillment}/submit:
    post:
      tags:
      - Walmart
      summary: Submit Walmart Fulfillment
      description: 'Submit a single completed fulfillment''s shipment confirmation
        (carrier, tracking number, shipped lines) to Walmart. Only fulfillments that
        are completed, not yet submitted, not pickup-type, and linked to a non-cancelled
        Walmart order of this instance are accepted. On success the fulfillment is
        marked as submitted; on failure a 422 is returned with the reason.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      - name: salesOrderFulfillment
        in: path
        schema:
          type: integer
        required: true
        description: Sales order fulfillment ID
        example: '61'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                example:
                  success: true
                  message: 'Fulfillment #F-1057 submitted successfully'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                example:
                  success: false
                  message: Fulfillment submission failed
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-walmart-integrationinstance-fulfillments-salesorderfulfillment-submit
  /api/walmart/{integrationInstance}/fulfillments/submit-bulk:
    post:
      tags:
      - Walmart
      summary: Bulk Submit Walmart Fulfillments
      description: 'Submit multiple fulfillments'' shipment confirmations to Walmart
        in one call. Each fulfillment is processed independently; the response reports
        how many were submitted and how many failed, with per-fulfillment error messages.
        Fulfillments that are already submitted, pickup-type, or on cancelled orders
        are ignored.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Request body:

        - ids (required, array of integers) — sales order fulfillment ids to submit.
        Each id must exist.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 61
                - 62
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      submitted:
                        type: integer
                      failed:
                        type: integer
                  errors:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        message:
                          type: string
                  message:
                    type: string
                example:
                  success: false
                  data:
                    submitted: 1
                    failed: 1
                  errors:
                  - id: 62
                    message: Sales order is not linked to a Walmart order
                  message: 1 fulfillment(s) submitted, 1 failed
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-walmart-integrationinstance-fulfillments-submit-bulk
  /api/walmart/{integrationInstance}/fulfillments/submit-all:
    post:
      tags:
      - Walmart
      summary: Submit All Pending Walmart Fulfillments
      description: 'Submit every pending fulfillment for this integration instance
        to Walmart in one call — the same set returned by the pending listing. Each
        fulfillment is processed independently; the response reports totals plus per-fulfillment
        errors. Returns zeros when nothing is pending.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      submitted:
                        type: integer
                      failed:
                        type: integer
                  errors:
                    type: array
                  message:
                    type: string
                example:
                  success: true
                  data:
                    submitted: 3
                    failed: 0
                  errors: []
                  message: 3 fulfillment(s) submitted, 0 failed
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-walmart-integrationinstance-fulfillments-submit-all
  /api/walmart/{integrationInstance}/inventory:
    get:
      tags:
      - Walmart
      summary: List Walmart Inventory Comparison
      description: 'Get a paginated inventory comparison for this Walmart integration
        instance — one row per SKU per Walmart fulfillment location — showing the
        SKU.io quantity next to the quantity Walmart currently has, the variance,
        and a per-row sync status (synced, variance, or needs_recalc).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Rows cover every listed item across the instance''s fulfillment locations.
        When the instance is configured to clamp negative inventory to zero, negative
        SKU.io quantities count as synced while Walmart shows 0. Returns an empty
        result when the instance has no fulfillment locations yet.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        product_listing_id:
                          type: integer
                        document_id:
                          type: integer
                        listing_sku:
                          type: string
                        title:
                          type: string
                        product:
                          type: object
                          properties:
                            id:
                              type: integer
                            sku:
                              type: string
                            name:
                              type: string
                        subscription_offering:
                          type: string
                          nullable: true
                        location_id:
                          type: string
                        location_name:
                          type: string
                        location_is_active:
                          type: boolean
                        sku_quantity:
                          type: integer
                        sales_channel_quantity:
                          type: integer
                        variance:
                          type: integer
                        status:
                          type: string
                        is_sku_recalculation_needed:
                          type: boolean
                        sku_quantity_updated_at:
                          type: string
                        sales_channel_quantity_updated_at:
                          type: string
                        sales_channel_quantity_synced_at:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  next_page_url:
                    type: string
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 3311
                    product_listing_id: 902
                    document_id: 87
                    listing_sku: WB-32-SS
                    title: Stainless Steel Water Bottle 32 oz
                    product:
                      id: 45
                      sku: WB-32-SS
                      name: Stainless Steel Water Bottle 32 oz
                    subscription_offering: null
                    location_id: '10001096717'
                    location_name: Main Warehouse
                    location_is_active: true
                    sku_quantity: 142
                    sales_channel_quantity: 138
                    variance: 4
                    status: variance
                    is_sku_recalculation_needed: false
                    sku_quantity_updated_at: '2026-06-30T06:00:12+00:00'
                    sales_channel_quantity_updated_at: '2026-06-30T05:45:01+00:00'
                    sales_channel_quantity_synced_at: '2026-06-29T22:10:44+00:00'
                    created_at: '2026-03-14T10:02:31+00:00'
                    updated_at: '2026-06-30T06:00:12+00:00'
                  first_page_url: https://your-instance.test/api/walmart/1/inventory?page=1
                  from: 1
                  last_page: 42
                  last_page_url: https://your-instance.test/api/walmart/1/inventory?page=42
                  next_page_url: https://your-instance.test/api/walmart/1/inventory?page=2
                  path: https://your-instance.test/api/walmart/1/inventory
                  per_page: 10
                  prev_page_url: null
                  to: 1
                  total: 420
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-walmart-integrationinstance-inventory
  /api/walmart/{integrationInstance}/inventory/summary:
    get:
      tags:
      - Walmart
      summary: Get Walmart Inventory Summary
      description: 'Get aggregate inventory-comparison statistics for this integration
        instance, counting SKU/location combinations: totals in sync, with variance,
        and needing recalculation, plus when Walmart quantities were last fetched
        and when SKU.io last pushed quantities to Walmart.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      total_items:
                        type: integer
                      in_sync:
                        type: integer
                      with_variance:
                        type: integer
                      needs_recalculation:
                        type: integer
                      last_fetch_at:
                        type: string
                      last_sync_at:
                        type: string
                example:
                  data:
                    total_items: 420
                    in_sync: 391
                    with_variance: 24
                    needs_recalculation: 5
                    last_fetch_at: '2026-06-30 05:45:01'
                    last_sync_at: '2026-06-29 22:10:44'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-walmart-integrationinstance-inventory-summary
  /api/walmart/{integrationInstance}/inventory/locations:
    get:
      tags:
      - Walmart
      summary: List Walmart Inventory Locations
      description: 'Get every Walmart fulfillment location (ship node) known for this
        integration instance, with its display name and whether it is currently active
        on Walmart. Use the returned ids as `filter[location_id]` values on the inventory
        comparison listing.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: string
                        name:
                          type: string
                        is_active:
                          type: boolean
                example:
                  data:
                  - id: '10001096717'
                    name: Main Warehouse
                    is_active: true
                  - id: '10001096718'
                    name: East Coast DC
                    is_active: false
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-walmart-integrationinstance-inventory-locations
  /api/walmart/{integrationInstance}/inventory/recache:
    post:
      tags:
      - Walmart
      summary: Start Walmart Inventory Recache
      description: 'Recalculate SKU.io''s sellable quantities for every Walmart listing/location
        on this integration instance and refresh the comparison cache. Run this when
        SKU.io quantities look stale or rows show needs_recalc. This queues an asynchronous
        background job and returns immediately. Poll progress using the returned tracked_job_log_id.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                example:
                  message: Inventory recache job has been queued
                  data:
                    tracked_job_log_id: 1234
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-walmart-integrationinstance-inventory-recache
  /api/walmart/{integrationInstance}/inventory/recache-progress/{trackedJobLogId}:
    get:
      tags:
      - Walmart
      summary: Get Walmart Inventory Recache Progress
      description: 'Poll the progress of a previously started inventory recache. Returns
        the job''s status (queued, processing, completed, failed), item counts, and
        a progress percentage. Returns 404 for an unknown job id.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      - name: trackedJobLogId
        in: path
        schema:
          type: integer
        required: true
        description: Job id returned when the recache was started
        example: '1234'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      job_type:
                        type: string
                      queue:
                        type: string
                      job_name:
                        type: string
                      status:
                        type: string
                      related_model:
                        type: object
                        properties:
                          id:
                            type: integer
                          type:
                            type: string
                          reference:
                            type: string
                      related_model_reference:
                        type: string
                      messages:
                        type: array
                      attempted_at:
                        type: string
                      completed_at:
                        type: string
                        nullable: true
                      duration:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      results:
                        type: string
                        nullable: true
                      total_items:
                        type: integer
                      processed_items:
                        type: integer
                      progress_percentage:
                        type: number
                      progress_mode:
                        type: string
                      stages:
                        type: string
                        nullable: true
                example:
                  data:
                    id: 1234
                    job_type: walmart_inventory
                    queue: default
                    job_name: Walmart Inventory Recache
                    status: processing
                    related_model:
                      id: 1
                      type: integration_instance
                      reference: Walmart US Store
                    related_model_reference: Walmart US Store
                    messages: []
                    attempted_at: '2026-06-30T06:00:01.000000Z'
                    completed_at: null
                    duration: null
                    created_at: '2026-06-30T06:00:00.000000Z'
                    updated_at: '2026-06-30T06:00:15.000000Z'
                    results: null
                    total_items: 420
                    processed_items: 180
                    progress_percentage: 42.86
                    progress_mode: items
                    stages: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-walmart-integrationinstance-inventory-recache-progress-trackedjoblogid
  /api/walmart/{integrationInstance}/inventory/sync:
    post:
      tags:
      - Walmart
      summary: Start Walmart Inventory Sync
      description: 'Push SKU.io quantities to Walmart for every listing/location with
        a variance on this integration instance, updating Walmart''s available-to-sell
        figures. This queues an asynchronous background job and returns immediately.
        Poll progress using the returned tracked_job_log_id.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                example:
                  message: Inventory sync job has been queued
                  data:
                    tracked_job_log_id: 1235
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-walmart-integrationinstance-inventory-sync
  /api/walmart/{integrationInstance}/inventory/sync-progress/{trackedJobLogId}:
    get:
      tags:
      - Walmart
      summary: Get Walmart Inventory Sync Progress
      description: 'Poll the progress of a previously started inventory sync to Walmart.
        Returns the job''s status (queued, processing, completed, failed), item counts,
        and a progress percentage. Returns 404 for an unknown job id.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      - name: trackedJobLogId
        in: path
        schema:
          type: integer
        required: true
        description: Job id returned when the sync was started
        example: '1235'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      job_type:
                        type: string
                      queue:
                        type: string
                      job_name:
                        type: string
                      status:
                        type: string
                      related_model:
                        type: object
                        properties:
                          id:
                            type: integer
                          type:
                            type: string
                          reference:
                            type: string
                      related_model_reference:
                        type: string
                      messages:
                        type: array
                      attempted_at:
                        type: string
                      completed_at:
                        type: string
                        nullable: true
                      duration:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      results:
                        type: string
                        nullable: true
                      total_items:
                        type: integer
                      processed_items:
                        type: integer
                      progress_percentage:
                        type: number
                      progress_mode:
                        type: string
                      stages:
                        type: string
                        nullable: true
                example:
                  data:
                    id: 1234
                    job_type: walmart_inventory
                    queue: default
                    job_name: Walmart Inventory Sync
                    status: processing
                    related_model:
                      id: 1
                      type: integration_instance
                      reference: Walmart US Store
                    related_model_reference: Walmart US Store
                    messages: []
                    attempted_at: '2026-06-30T06:00:01.000000Z'
                    completed_at: null
                    duration: null
                    created_at: '2026-06-30T06:00:00.000000Z'
                    updated_at: '2026-06-30T06:00:15.000000Z'
                    results: null
                    total_items: 420
                    processed_items: 180
                    progress_percentage: 42.86
                    progress_mode: items
                    stages: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-walmart-integrationinstance-inventory-sync-progress-trackedjoblogid
  /api/walmart/{integrationInstance}/inventory/fetch-live:
    post:
      tags:
      - Walmart
      summary: Start Walmart Live Inventory Fetch
      description: 'Fetch current on-hand quantities from the Walmart Marketplace
        API for every listing/location on this integration instance and store them
        on the comparison rows (`sales_channel_quantity`). This queues an asynchronous
        background job and returns immediately. Poll progress using the returned tracked_job_log_id.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                example:
                  message: Fetch live inventory job has been queued
                  data:
                    tracked_job_log_id: 1236
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-walmart-integrationinstance-inventory-fetch-live
  /api/walmart/{integrationInstance}/inventory/fetch-live-progress/{trackedJobLogId}:
    get:
      tags:
      - Walmart
      summary: Get Walmart Live Inventory Fetch Progress
      description: 'Poll the progress of a previously started live inventory fetch
        from Walmart. Returns the job''s status (queued, processing, completed, failed),
        item counts, and a progress percentage. Returns 404 for an unknown job id.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      - name: trackedJobLogId
        in: path
        schema:
          type: integer
        required: true
        description: Job id returned when the live fetch was started
        example: '1236'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      job_type:
                        type: string
                      queue:
                        type: string
                      job_name:
                        type: string
                      status:
                        type: string
                      related_model:
                        type: object
                        properties:
                          id:
                            type: integer
                          type:
                            type: string
                          reference:
                            type: string
                      related_model_reference:
                        type: string
                      messages:
                        type: array
                      attempted_at:
                        type: string
                      completed_at:
                        type: string
                        nullable: true
                      duration:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      results:
                        type: string
                        nullable: true
                      total_items:
                        type: integer
                      processed_items:
                        type: integer
                      progress_percentage:
                        type: number
                      progress_mode:
                        type: string
                      stages:
                        type: string
                        nullable: true
                example:
                  data:
                    id: 1234
                    job_type: walmart_inventory
                    queue: default
                    job_name: Walmart Live Inventory Fetch
                    status: processing
                    related_model:
                      id: 1
                      type: integration_instance
                      reference: Walmart US Store
                    related_model_reference: Walmart US Store
                    messages: []
                    attempted_at: '2026-06-30T06:00:01.000000Z'
                    completed_at: null
                    duration: null
                    created_at: '2026-06-30T06:00:00.000000Z'
                    updated_at: '2026-06-30T06:00:15.000000Z'
                    results: null
                    total_items: 420
                    processed_items: 180
                    progress_percentage: 42.86
                    progress_mode: items
                    stages: null
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-walmart-integrationinstance-inventory-fetch-live-progress-trackedjoblogid
  /api/walmart/{id}/returns:
    get:
      tags:
      - Walmart
      summary: List Walmart Returns
      description: 'Get a paginated list of Walmart customer returns for a specific
        integration instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Walmart returns are synced from the Walmart Marketplace API and represent
        customer-initiated return requests.


        Each return includes:

        - return_order_id: Walmart''s return order identifier

        - return_date: Date the return was initiated

        - status: Current return status (INITIATED, RECEIVED, CANCELLED)

        - refund_status: Current refund processing status

        - return_type: Type of return (REPLACEMENT, REFUND, EXCHANGE)

        - line_items: Individual SKUs and quantities being returned


        Route name: walmart.returns.index (via salesChannel macro)'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      - name: filter[search]
        in: query
        schema:
          type: string
        description: Optional. Search by return ID or order number.
      - name: filter[status]
        in: query
        schema:
          type: string
        description: Optional. Filter by return status (e.g. INITIATED, RECEIVED,
          CANCELLED).
      - name: filter[refund_status]
        in: query
        schema:
          type: string
        description: Optional. Filter by refund status (e.g. REFUND_INITIATED, REFUND_PROCESSED,
          REFUND_DECLINED).
      - name: sort
        in: query
        schema:
          type: string
        description: 'Optional. Sort field. Prefix with - for descending. Available:
          id, created_at, updated_at.'
        example: -created_at
      - name: page
        in: query
        schema:
          type: integer
        description: Page number for pagination.
        example: '1'
      - name: per_page
        in: query
        schema:
          type: integer
        description: Number of results per page (default 10).
        example: '10'
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-walmart-id-returns
  /api/walmart/{integrationInstance}/returns/refresh-tracked:
    post:
      tags:
      - Walmart
      summary: Refresh Walmart Returns
      description: 'Queue a tracked job that pulls the latest returns from the Walmart
        Marketplace Returns API (seller- and WFS-fulfilled). Read-only against Walmart.
        Track progress via the returned tracked_job_log_id via the tracked job log
        endpoints.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 1234
                  message: Walmart returns refresh started
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-walmart-integrationinstance-returns-refresh-tracked
  /api/walmart/{integrationInstance}/returns/{return}/refund:
    post:
      tags:
      - Walmart
      summary: Refund Walmart Return
      description: 'Issue a refund against a Walmart Marketplace return order. Without
        a request body, every returned line is refunded at its full quantity. To refund
        only specific line(s) or quantities, send an optional `lines` array — each
        item has `returnOrderLineNumber` (integer, required) and `quantity` (integer
        ≥ 1, required). Reflects the refund status locally.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        WFS-fulfilled returns are settled by Walmart and cannot be refunded here;
        attempting to refund one (or any Walmart-side failure) returns a 422 with
        the failure reason. The return must belong to the integration instance in
        the path (404 otherwise).


        Requires a Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                lines:
                  type: array
                  items:
                    type: object
                    properties:
                      returnOrderLineNumber:
                        type: integer
                      quantity:
                        type: integer
              example:
                lines:
                - returnOrderLineNumber: 1
                  quantity: 1
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      - name: return
        in: path
        schema:
          type: integer
        required: true
        description: Local Walmart return ID (numeric)
        example: '7'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Refund issued
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: 422 Refund Failed
                  value:
                    message: 'Failed to issue refund: This return is fulfilled by
                      WFS and is refunded by Walmart — it cannot be refunded here.'
                example-1:
                  summary: 422 Validation Error
                  value:
                    message: Each refund line needs a quantity.
                    errors:
                      lines.0.quantity:
                      - Each refund line needs a quantity.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-walmart-integrationinstance-returns-return-refund
  /api/walmart/{id}/wfs/settings:
    get:
      tags:
      - Walmart
      summary: Get WFS Settings
      description: 'Get the WFS settings (enabled flag, sync cadence, default source
        warehouse, MCF flag, MCF order channel id) for an integration instance, plus
        the per-instance `webhook_url` the seller registers with Walmart so WFS inbound/inventory/return
        status changes are pushed in real time. Returns defaults when WFS is not yet
        configured. Requires a Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      enabled:
                        type: boolean
                      default_source_warehouse_id:
                        type: string
                        nullable: true
                      mcf_enabled:
                        type: boolean
                      mcf_order_channel_id:
                        type: string
                        nullable: true
                  webhook_url:
                    type: string
                example:
                  data:
                    enabled: true
                    default_source_warehouse_id: null
                    mcf_enabled: false
                    mcf_order_channel_id: null
                  webhook_url: https://app.sku.io/webhooks/walmart/wh_aB3xY7zKqLmN0pQrStUvWxYz12345678
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-walmart-id-wfs-settings
    put:
      tags:
      - Walmart
      summary: Update WFS Settings
      description: 'Update WFS settings. Toggling `enabled` creates (true) or archives
        (false) the dedicated WFS warehouse. Disabling while the WFS warehouse holds
        stock or inbound shipments are in flight returns 409 requires_confirmation;
        resend with `force: true` to proceed. Requires a Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                enabled:
                  type: boolean
                force:
                  type: boolean
              example:
                enabled: false
                force: true
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      enabled:
                        type: boolean
                      default_source_warehouse_id:
                        type: string
                        nullable: true
                      mcf_enabled:
                        type: boolean
                      mcf_order_channel_id:
                        type: string
                        nullable: true
                  message:
                    type: string
                example:
                  data:
                    enabled: true
                    default_source_warehouse_id: null
                    mcf_enabled: false
                    mcf_order_channel_id: null
                  message: WFS settings saved
        '409':
          description: Conflict
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  requires_confirmation:
                    type: boolean
                example:
                  message: There are 2 open WFS inbound shipment(s) in flight. Confirm
                    to proceed.
                  requires_confirmation: true
        '422':
          description: Unprocessable Content
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties: {}
                example:
                  message: The WFS inventory sync interval must be at least 5 minutes.
                  errors: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: put-api-walmart-id-wfs-settings
  /api/walmart/{id}/wfs/inventory:
    get:
      tags:
      - Walmart
      summary: List WFS Inventory
      description: 'Paginated WFS inventory snapshot for a Walmart integration instance.
        Quantities are pulled from Walmart per SKU + ship node and are read-only (Walmart
        owns the stock). Requires a Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        sku:
                          type: string
                        product_id:
                          type: integer
                        ship_node:
                          type: string
                        available_quantity:
                          type: integer
                        reserved_quantity:
                          type: integer
                        inbound_quantity:
                          type: integer
                        unfulfillable_quantity:
                          type: integer
                        total_quantity:
                          type: integer
                        last_synced_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 41
                    sku: ABC-001
                    product_id: 1
                    ship_node: '10002506668'
                    available_quantity: 320
                    reserved_quantity: 12
                    inbound_quantity: 100
                    unfulfillable_quantity: 2
                    total_quantity: 320
                    last_synced_at: '2026-06-17T14:32:00.000000Z'
                  current_page: 1
                  last_page: 1
                  per_page: 10
                  total: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-walmart-id-wfs-inventory
  /api/walmart/{id}/wfs/inventory/refresh-tracked:
    post:
      tags:
      - Walmart
      summary: Refresh WFS Inventory
      description: 'Queue a tracked job that re-syncs WFS inventory from Walmart for
        every WFS SKU (listings flagged WFS plus SKUs with existing WFS snapshots).
        Returns the tracked job log id. Requires a Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 12346
                  message: WFS inventory refresh started
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-walmart-id-wfs-inventory-refresh-tracked
  /api/walmart/{id}/wfs/replenishment/settings:
    get:
      tags:
      - Walmart
      summary: Get WFS Replenishment Settings
      description: 'Instance-default WFS replenishment tunables (target days of supply,
        buffer, lead time, case pack, velocity window). Returns defaults when not
        configured. Requires a Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      target_days_of_supply:
                        type: integer
                      buffer_days:
                        type: integer
                      lead_time_days:
                        type: integer
                      case_pack_qty:
                        type: integer
                      velocity_window_days:
                        type: integer
                      candidate_min_units:
                        type: integer
                example:
                  data:
                    target_days_of_supply: 30
                    buffer_days: 7
                    lead_time_days: 14
                    case_pack_qty: 1
                    velocity_window_days: 30
                    candidate_min_units: 30
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-walmart-id-wfs-replenishment-settings
    put:
      tags:
      - Walmart
      summary: Update WFS Replenishment Settings
      description: 'Update instance-default replenishment tunables. All fields required;
        target_days_of_supply 1-365, buffer 0-180, lead_time 0-365, case_pack >=1,
        velocity_window 7-365. Requires a Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                target_days_of_supply:
                  type: integer
                buffer_days:
                  type: integer
                lead_time_days:
                  type: integer
                case_pack_qty:
                  type: integer
                velocity_window_days:
                  type: integer
              example:
                target_days_of_supply: 45
                buffer_days: 10
                lead_time_days: 21
                case_pack_qty: 24
                velocity_window_days: 60
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      target_days_of_supply:
                        type: integer
                      buffer_days:
                        type: integer
                      lead_time_days:
                        type: integer
                      case_pack_qty:
                        type: integer
                      velocity_window_days:
                        type: integer
                      candidate_min_units:
                        type: integer
                example:
                  data:
                    target_days_of_supply: 30
                    buffer_days: 7
                    lead_time_days: 14
                    case_pack_qty: 1
                    velocity_window_days: 30
                    candidate_min_units: 30
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-walmart-id-wfs-replenishment-settings
  /api/walmart/{id}/wfs/replenishment:
    get:
      tags:
      - Walmart
      summary: List WFS Replenishment Suggestions
      description: 'Replenishment grid as a full-featured, server-side list view:
        one row per WFS SKU with its WFS position (available/inbound summed across
        ship nodes), demand velocity (units/day from matched-product sales over the
        velocity window), and the suggested quantity to send (velocity x coverage
        horizon - net WFS position, case-pack rounded). Supports search, advanced
        filter_groups, sorting, and pagination — all applied server-side over the
        computed columns. Returns a Laravel LengthAwarePaginator. Requires a Bearer
        token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        sku:
                          type: string
                        product_id:
                          type: integer
                        wfs_available:
                          type: integer
                        wfs_inbound:
                          type: integer
                        velocity_per_day:
                          type: integer
                        target_days_of_supply:
                          type: integer
                        suggested_quantity:
                          type: integer
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                  first_page_url:
                    type: string
                  last_page_url:
                    type: string
                  next_page_url:
                    type: string
                    nullable: true
                  prev_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                example:
                  data:
                  - sku: WFS-ABC-001
                    product_id: 1
                    wfs_available: 10
                    wfs_inbound: 0
                    velocity_per_day: 2
                    target_days_of_supply: 30
                    suggested_quantity: 92
                  current_page: 1
                  last_page: 1
                  per_page: 25
                  total: 1
                  from: 1
                  to: 1
                  first_page_url: '{{base_url}}/api/walmart/1/wfs/replenishment?page=1'
                  last_page_url: '{{base_url}}/api/walmart/1/wfs/replenishment?page=1'
                  next_page_url: null
                  prev_page_url: null
                  path: '{{base_url}}/api/walmart/1/wfs/replenishment'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-walmart-id-wfs-replenishment
  /api/walmart/{integrationInstance}/wfs/replenishment/candidates:
    get:
      tags:
      - Walmart
      summary: List WFS Replenishment Candidates
      description: 'WFS candidate intelligence as a full-featured, server-side list
        view: seller-fulfilled Walmart listings NOT yet in WFS that sell enough on
        the Walmart channel (>= candidate_min_units in the velocity window) to warrant
        sending into WFS. Ranked by Walmart-channel volume by default, with a suggested
        initial ship quantity (velocity x coverage, nothing on hand yet). Supports
        search, advanced filter_groups, sorting, and pagination — all applied server-side
        over the computed columns. Returns a Laravel LengthAwarePaginator. Empty when
        the instance has no linked sales channel. Requires a Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        sku:
                          type: string
                        product_id:
                          type: integer
                        product_name:
                          type: string
                        units_in_window:
                          type: integer
                        velocity_per_day:
                          type: integer
                        window_days:
                          type: integer
                        suggested_initial_quantity:
                          type: integer
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                  first_page_url:
                    type: string
                  last_page_url:
                    type: string
                  next_page_url:
                    type: string
                    nullable: true
                  prev_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                example:
                  data:
                  - sku: SELL-HOTTER
                    product_id: 42
                    product_name: Aurora LED Strip 5m
                    units_in_window: 300
                    velocity_per_day: 10
                    window_days: 30
                    suggested_initial_quantity: 510
                  current_page: 1
                  last_page: 1
                  per_page: 25
                  total: 1
                  from: 1
                  to: 1
                  first_page_url: '{{base_url}}/api/walmart/1/wfs/replenishment/candidates?page=1'
                  last_page_url: '{{base_url}}/api/walmart/1/wfs/replenishment/candidates?page=1'
                  next_page_url: null
                  prev_page_url: null
                  path: '{{base_url}}/api/walmart/1/wfs/replenishment/candidates'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-walmart-integrationinstance-wfs-replenishment-candidates
  /api/walmart/{integrationInstance}/wfs/inbound-products/recommendations:
    get:
      tags:
      - Walmart
      summary: WFS Recommended Items
      description: 'Walmart''s WFS restock recommendations for the inbound builder''s
        "Recommended items" modal — items running low at WFS with days of supply,
        stock status, and Walmart''s suggested send quantities, joined to the local
        product (product_id) so a recommendation can be added straight to the cart.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Proxies Walmart''s GET /v3/wfs/recommendation/restock with showInsights=true
        (no caching). Returns an empty data array when Walmart has no recommendations.
        A Walmart API failure returns 422 with a message.


        Response fields per item: sku, gtin, item_name, brand, stock_status (e.g.
        ''At Risk''), days_of_supply, suggested_units, forecasted_sales_lift, customer_favorite,
        product_id (local product id or null).


        Requires a Bearer token.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        sku:
                          type: string
                        gtin:
                          type: string
                        item_name:
                          type: string
                        brand:
                          type: string
                        stock_status:
                          type: string
                        days_of_supply:
                          type: integer
                        suggested_units:
                          type: integer
                        forecasted_sales_lift:
                          type: number
                        customer_favorite:
                          type: boolean
                        product_id:
                          type: integer
                example:
                  data:
                  - sku: ABC-001
                    gtin: 00894147009695
                    item_name: Charlie Banana Baby Washable Diaper
                    brand: Charlie Banana
                    stock_status: At Risk
                    days_of_supply: 9
                    suggested_units: 40
                    forecasted_sales_lift: 120.5
                    customer_favorite: true
                    product_id: 512
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 'Failed to load recommended items: Walmart WFS restock
                    recommendations fetch failed (HTTP 500)'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-walmart-integrationinstance-wfs-inbound-products-recommendations
  /api/walmart/{integrationInstance}/wfs/inbound-shipments/fulfillment-portal/{token}/unit-mix.csv:
    get:
      tags:
      - Walmart
      summary: Portal — Download WFS Unit-Mix Spreadsheet (CSV, public)
      description: 'PUBLIC. Downloads the unit-mix spreadsheet (CSV) for the WFS inbound
        shipment so the 3PL / supplier can reconcile what to pack. Columns: SKU, Product,
        GTIN/UPC, Qty, Packing, Units per case, Unit weight, Unit dimensions, Prep
        services — plus a Kitting Work Order section when the shipment contains kits.
        Streamed as text/csv with filename wfs-unit-mix-&lt;shipmentId>.csv. Returns
        404 if the portal token is invalid or has been revoked.'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      - name: token
        in: path
        schema:
          type: string
        required: true
        description: The packet's revocable portal token
        example: <portal-token>
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-walmart-integrationinstance-wfs-inbound-shipments-fulfillment-portal-token-unit-mix-csv
  /api/walmart/{integrationInstance}/wfs/inbound-shipments/fulfillment-portal/{token}/box-contents:
    post:
      tags:
      - Walmart
      summary: Portal — Submit WFS Box Contents (public)
      description: 'PUBLIC. The 3PL/supplier reports what they packed in each box.
        Body: boxes[] each { box_number (int), lines[] of { sku, quantity } }. Moves
        the packet to In Progress and unlocks the ready-to-ship acknowledgement.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                boxes:
                  type: array
                  items:
                    type: object
                    properties:
                      box_number:
                        type: integer
                      lines:
                        type: array
                        items:
                          type: object
                          properties:
                            sku:
                              type: string
                            quantity:
                              type: integer
              example:
                boxes:
                - box_number: 1
                  lines:
                  - sku: ABC-001
                    quantity: 5
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      - name: token
        in: path
        schema:
          type: string
        required: true
        description: The packet's revocable portal token
        example: <portal-token>
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      reference:
                        type: string
                      inbound_order_id:
                        type: string
                      source_name:
                        type: string
                      source_type:
                        type: string
                      destination_fc:
                        type: string
                      status:
                        type: string
                      build_required:
                        type: boolean
                      kit_build_manifest:
                        type: array
                      instructions:
                        type: string
                      line_items:
                        type: array
                        items:
                          type: object
                          properties:
                            sku:
                              type: string
                            name:
                              type: string
                            quantity:
                              type: integer
                      documents:
                        type: array
                        items:
                          type: object
                          properties:
                            id:
                              type: integer
                            type:
                              type: string
                            type_label:
                              type: string
                            stage:
                              type: string
                            status:
                              type: string
                      box_contents_submission:
                        type: array
                        items:
                          type: object
                          properties:
                            box_number:
                              type: integer
                            lines:
                              type: array
                              items:
                                type: object
                                properties:
                                  sku:
                                    type: string
                                  quantity:
                                    type: integer
                      can_confirm:
                        type: boolean
                      confirm_blocked_reason:
                        type: string
                        nullable: true
                      acknowledged_at:
                        type: string
                        nullable: true
                  message:
                    type: string
                example:
                  data:
                    reference: 8973354WFA
                    inbound_order_id: 01KVV71P30GJ95KMT429EY76AK
                    source_name: 3PL East
                    source_type: 3pl
                    destination_fc: KY1
                    status: in_progress
                    build_required: false
                    kit_build_manifest: []
                    instructions: 'WALMART WFS INBOUND — PREP INSTRUCTIONS

                      ...'
                    line_items:
                    - sku: ABC-001
                      name: Blue Jeans
                      quantity: 12
                    documents:
                    - id: 2
                      type: instructions
                      type_label: Prep Instructions
                      stage: initial
                      status: ready
                    box_contents_submission:
                    - box_number: 1
                      lines:
                      - sku: ABC-001
                        quantity: 5
                    can_confirm: true
                    confirm_blocked_reason: null
                    acknowledged_at: null
                  message: Box contents submitted.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-walmart-integrationinstance-wfs-inbound-shipments-fulfillment-portal-token-box-contents
  /api/walmart/{integrationInstance}/wfs/inbound-shipments/{shipment}/item-labels:
    post:
      tags:
      - Walmart
      summary: Print WFS GTIN Item Labels (shipment)
      description: 'Render printable GTIN item labels (PDF) for a WFS inbound shipment''s
        lines — the detail page''s "Item labels" print-all. Defaults to ONE LABEL
        PER UNIT of every intent line when the body is empty; pass items to override
        per-SKU label counts (per-row printing).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Request body (all optional):

        - items (array, 1–500) — each: { sku (required string), quantity (required
        integer 1–3000) }. Omit to print every line at its full quantity.

        - format: ''letter_30'' (default) or ''thermal_2_25x1_25''.


        404 when the shipment belongs to another integration instance; 422 when the
        shipment has no lines (e.g. synced from Walmart without local intent lines)
        or a SKU lacks a GTIN/UPC. Response is the raw PDF (application/pdf). See
        the ad-hoc variant for label/symbology details. Requires a Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                items:
                  type: array
                  items:
                    type: object
                    properties:
                      sku:
                        type: string
                      quantity:
                        type: integer
                format:
                  type: string
              example:
                items:
                - sku: ABC-001
                  quantity: 12
                format: thermal_2_25x1_25
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      - name: shipment
        in: path
        schema:
          type: integer
        required: true
        description: SKU.io WFS inbound shipment ID
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/pdf
            Content-Disposition:
              schema:
                type: string
                example: attachment; filename="wfs-item-labels-0066618GDM.pdf"
          content:
            text/plain:
              schema:
                type: string
                example: '%PDF-1.4 … (binary PDF stream — the generated GTIN label
                  sheet)'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: This shipment has no lines to print labels for.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-walmart-integrationinstance-wfs-inbound-shipments-shipment-item-labels
  /api/walmart/{integrationInstance}/wfs/item-labels:
    post:
      tags:
      - Walmart
      summary: Print WFS GTIN Item Labels (ad-hoc)
      description: 'Render printable GTIN item labels (PDF) for arbitrary WFS-bound
        SKUs — the inbound builder''s per-row "Print GTIN label". Walmart exposes
        NO item-label API (Seller Center only), but WFS item labels are plain GTIN-14
        / UPC-12 barcodes (no FNSKU-style Walmart identifier), so SKU.io renders the
        PDF locally from the listing''s GTIN/UPC (fallback UPC → product barcode),
        mirroring the Amazon FBA item-label UX.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Request body:

        - items (required, array, 1–500) — each: { sku (required string), quantity
        (required integer 1–3000) — number of labels to print for that SKU }.

        - format (optional): ''letter_30'' (default — Avery-5160-style letter sheet,
        30 labels of 2⅝" × 1") or ''thermal_2_25x1_25'' (one 2¼" × 1¼" label per page).


        Hard cap 3,000 labels per render. Barcode symbology is chosen by code length
        (12 → UPC-A, 13 → EAN-13, 14 → ITF-14, else Code 128). Each label shows product
        name, barcode, the numeric GTIN/UPC, and the SKU.


        Response is the raw PDF (Content-Type: application/pdf, attachment). A SKU
        without a GTIN/UPC returns 422 before any rendering. Requires a Bearer token.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                items:
                  type: array
                  items:
                    type: object
                    properties:
                      sku:
                        type: string
                      quantity:
                        type: integer
                format:
                  type: string
              example:
                items:
                - sku: ABC-001
                  quantity: 24
                format: letter_30
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/pdf
            Content-Disposition:
              schema:
                type: string
                example: attachment; filename="wfs-item-labels.pdf"
          content:
            text/plain:
              schema:
                type: string
                example: '%PDF-1.4 … (binary PDF stream — the generated GTIN label
                  sheet)'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 'Failed to generate GTIN labels: SKU NO-GTIN has no GTIN/UPC
                    on its Walmart listing or product record, so a GTIN label can''t
                    be printed.'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-walmart-integrationinstance-wfs-item-labels
  /api/walmart/{integrationInstance}/wfs/inbound-shipments/fulfillment-portal/{token}/item-labels:
    post:
      tags:
      - Walmart
      summary: Portal — Print WFS GTIN Item Labels (public)
      description: 'Self-service GTIN item labels from the PUBLIC fulfillment portal
        — the 3PL/supplier prints the barcode label sheet (PDF) straight from the
        portal, no login. Mirrors the authenticated "Print WFS GTIN Item Labels (shipment)"
        download. Defaults to ONE LABEL PER UNIT of every shipment line when the body
        is empty; pass items to override per-SKU label counts (per-row printing).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Walmart has no item-label API — SKU.io renders the GTIN/UPC barcode PDF locally,
        so the response is the raw PDF (application/pdf), not JSON. Each label encodes
        the product''s GTIN, falling back to UPC, then the product barcode.


        Request body (all optional):

        - items (array, 1–500) — each: { sku (required string, max 255), quantity
        (required integer 1–3000) }.

        - format: ''letter_30'' (default) or ''thermal_2_25x1_25''.


        Public, token-gated endpoint — NO bearer auth. The :token gates packet access;
        tenant is resolved by request host. 404 when the token is invalid/expired;
        422 when the shipment has no lines or a SKU lacks a GTIN/UPC/barcode.'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                items:
                  type: array
                  items:
                    type: object
                    properties:
                      sku:
                        type: string
                      quantity:
                        type: integer
                format:
                  type: string
              example:
                items:
                - sku: WIDGET-BLUE-500
                  quantity: 12
                format: thermal_2_25x1_25
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      - name: token
        in: path
        schema:
          type: string
        required: true
        description: Portal access token that gates this packet (revocable, expiring)
        example: a1b2c3d4e5
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/pdf
            Content-Disposition:
              schema:
                type: string
                example: attachment; filename="wfs-item-labels-0066618GDM.pdf"
          content:
            text/plain:
              schema:
                type: string
                example: '%PDF-1.4 … (binary PDF stream — the generated GTIN label
                  sheet)'
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: text/plain; charset=UTF-8
          content:
            text/plain:
              schema:
                type: string
                example: This portal link is no longer valid.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: text/plain; charset=UTF-8
          content:
            text/plain:
              schema:
                type: string
                example: This shipment has no lines to print labels for.
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: post-api-walmart-integrationinstance-wfs-inbound-shipments-fulfillment-portal-token-item-labels
  /api/walmart/{integrationInstance}/wfs/inventory/log:
    get:
      tags:
      - Walmart
      summary: List WFS Inventory Log Entries
      description: 'The WFS inventory transaction log for a single SKU (resolved to
        its GTIN), pulled live from Walmart and capped at 50 rows. `sku` is required;
        `transaction_type` optionally narrows to one transaction type. A missing/unresolvable
        SKU or Walmart-side failure returns a 422. Requires a Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: sku
        in: query
        schema:
          type: string
        description: Required. Seller SKU; resolved to its GTIN before querying Walmart.
        example: ABC-001
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        transaction_type:
                          type: string
                        quantity:
                          type: integer
                        reason:
                          type: string
                        ship_node:
                          type: string
                        event_time:
                          type: string
                example:
                  data:
                  - transaction_type: Inbound
                    quantity: 100
                    reason: Inbound receipt
                    ship_node: NJ3
                    event_time: '2026-06-15T14:32:00.000000Z'
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      sku:
                        type: array
                        items:
                          type: string
                example:
                  message: The sku field is required.
                  errors:
                    sku:
                    - The sku field is required.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-walmart-integrationinstance-wfs-inventory-log
  /api/walmart/{integrationInstance}/wfs/inventory/health-report:
    get:
      tags:
      - Walmart
      summary: Get WFS Inventory Health Report
      description: 'Download the WFS Inventory Health report (aged / long-term-storage
        exposure) Walmart generates. Returns the raw file as a download (Content-Disposition
        attachment) — CSV when Walmart returns CSV, or ZIP when Walmart returns a
        zipped report (filename wfs-inventory-health.csv or .zip accordingly). Not
        a JSON envelope. Requires a Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: text/csv
            Content-Disposition:
              schema:
                type: string
                example: attachment; filename="wfs-inventory-health.csv"
          content:
            text/plain:
              schema:
                type: string
                example: 'sku,gtin,available_qty,aged_90_plus,long_term_storage_fee

                  ABC-001,00689107230963,320,40,12.50'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-walmart-integrationinstance-wfs-inventory-health-report
  /api/walmart/{integrationInstance}/wfs/inventory/compliance-holds:
    get:
      tags:
      - Walmart
      summary: List WFS Compliance Holds
      description: 'Search items on a WFS compliance hold (WERCS / hazmat) so they
        can be excluded from replenishment, pulled live from Walmart. `search` is
        optional and matched against `field` (sku or gtin, default sku). A Walmart-side
        failure returns a 422. Requires a Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        sku:
                          type: string
                        gtin:
                          type: string
                        hold_type:
                          type: string
                        reason:
                          type: string
                example:
                  data:
                  - sku: ABC-001
                    gtin: 00689107230963
                    hold_type: WERCS
                    reason: Awaiting hazmat classification.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 'Failed to search compliance holds: Walmart returned an
                    error for the compliance-hold query.'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-walmart-integrationinstance-wfs-inventory-compliance-holds
  /api/walmart/{integrationInstance}/wfs/mcf-orders:
    get:
      tags:
      - Walmart
      summary: List MCF Orders
      description: 'Paginated WFS MCF orders for an integration instance. Supports
        free-text search (filter[search] spans customer_order_no + customer_order_id),
        advanced filters via filter_groups (columns: customer_order_no, customer_order_id,
        status, created_at), and sorting (allowed: id, customer_order_no, customer_order_id,
        status, created_at, updated_at; default -created_at). `can_cancel` is true
        while the order still has items and is not yet CANCELLED/SHIPPED/DELIVERED.
        Returns a Laravel LengthAwarePaginator. Requires a Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        customer_order_no:
                          type: string
                        customer_order_id:
                          type: string
                        request_id:
                          type: string
                        status:
                          type: string
                        can_cancel:
                          type: boolean
                        item_count:
                          type: integer
                        destination_address:
                          type: object
                          properties:
                            name:
                              type: string
                            address1:
                              type: string
                            city:
                              type: string
                            state:
                              type: string
                            postal_code:
                              type: string
                            country:
                              type: string
                        fulfillment_order_id:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                example:
                  data:
                  - id: 5
                    customer_order_no: CO-1001
                    customer_order_id: '118123456789012'
                    request_id: req-abc-123
                    status: CREATED
                    can_cancel: true
                    item_count: 2
                    destination_address:
                      name: Jane Doe
                      address1: 1 Market St
                      city: Newark
                      state: NJ
                      postal_code: '07102'
                      country: US
                    fulfillment_order_id: FO-77001
                    created_at: '2026-06-18T19:05:00.000000Z'
                    updated_at: '2026-06-18T19:05:00.000000Z'
                  current_page: 1
                  last_page: 1
                  per_page: 10
                  total: 1
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-walmart-integrationinstance-wfs-mcf-orders
  /api/walmart/{integrationInstance}/wfs/mcf-orders/{mcfOrder}:
    get:
      tags:
      - Walmart
      summary: Get MCF Order
      description: 'Fetch a single WFS MCF order by id, scoped to the integration
        instance (404 if it belongs to another instance). Requires a Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      - name: mcfOrder
        in: path
        schema:
          type: integer
        required: true
        description: Local WFS MCF order ID (numeric)
        example: '5'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      customer_order_no:
                        type: string
                      customer_order_id:
                        type: string
                      request_id:
                        type: string
                      status:
                        type: string
                      can_cancel:
                        type: boolean
                      cancel_blocked_reason:
                        type: string
                      item_count:
                        type: integer
                      destination_address:
                        type: object
                        properties:
                          name:
                            type: string
                          address1:
                            type: string
                          city:
                            type: string
                          state:
                            type: string
                          postal_code:
                            type: string
                          country:
                            type: string
                      fulfillment_order_id:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 5
                    customer_order_no: CO-1001
                    customer_order_id: '118123456789012'
                    request_id: req-abc-123
                    status: SHIPPED
                    can_cancel: false
                    cancel_blocked_reason: This shipment can no longer be cancelled.
                    item_count: 2
                    destination_address:
                      name: Jane Doe
                      address1: 1 Market St
                      city: Newark
                      state: NJ
                      postal_code: '07102'
                      country: US
                    fulfillment_order_id: FO-77001
                    created_at: '2026-06-18T19:05:00.000000Z'
                    updated_at: '2026-06-19T09:12:00.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-walmart-integrationinstance-wfs-mcf-orders-mcforder
  /api/walmart/{integrationInstance}/wfs/mcf-orders/{mcfOrder}/cancel:
    post:
      tags:
      - Walmart
      summary: Cancel MCF Order
      description: 'Cancel an MCF order on Walmart and reflect the cancellation locally.
        No request body. Scoped to the integration instance (404 if it belongs to
        another instance). Walmart rejects the cancel once the order has shipped/delivered/already-cancelled
        — that returns a 422. Returns the updated order resource. Requires a Bearer
        token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      - name: mcfOrder
        in: path
        schema:
          type: integer
        required: true
        description: Local WFS MCF order ID (numeric)
        example: '5'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      customer_order_no:
                        type: string
                      customer_order_id:
                        type: string
                      request_id:
                        type: string
                      status:
                        type: string
                      can_cancel:
                        type: boolean
                      cancel_blocked_reason:
                        type: string
                      item_count:
                        type: integer
                      destination_address:
                        type: string
                        nullable: true
                      fulfillment_order_id:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 5
                    customer_order_no: CO-1001
                    customer_order_id: '118123456789012'
                    request_id: req-abc-123
                    status: CANCELLED
                    can_cancel: false
                    cancel_blocked_reason: This shipment can no longer be cancelled.
                    item_count: 2
                    destination_address: null
                    fulfillment_order_id: FO-77001
                    created_at: '2026-06-18T19:05:00.000000Z'
                    updated_at: '2026-06-20T08:00:00.000000Z'
                  message: MCF order cancelled
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 'Failed to cancel MCF order: This order has already shipped
                    and can no longer be cancelled.'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-walmart-integrationinstance-wfs-mcf-orders-mcforder-cancel
  /api/walmart/{integrationInstance}/wfs/mcf-orders/{mcfOrder}/sync-status:
    post:
      tags:
      - Walmart
      summary: Sync MCF Order Status
      description: 'Pull the latest status for an MCF order from Walmart and update
        the local record. No request body. Scoped to the integration instance (404
        if it belongs to another instance). A Walmart-side failure returns a 422.
        Returns the updated order resource. Requires a Bearer token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      - name: mcfOrder
        in: path
        schema:
          type: integer
        required: true
        description: Local WFS MCF order ID (numeric)
        example: '5'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      customer_order_no:
                        type: string
                      customer_order_id:
                        type: string
                      request_id:
                        type: string
                      status:
                        type: string
                      can_cancel:
                        type: boolean
                      cancel_blocked_reason:
                        type: string
                      item_count:
                        type: integer
                      destination_address:
                        type: string
                        nullable: true
                      fulfillment_order_id:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 5
                    customer_order_no: CO-1001
                    customer_order_id: '118123456789012'
                    request_id: req-abc-123
                    status: DELIVERED
                    can_cancel: false
                    cancel_blocked_reason: This shipment can no longer be cancelled.
                    item_count: 2
                    destination_address: null
                    fulfillment_order_id: FO-77001
                    created_at: '2026-06-18T19:05:00.000000Z'
                    updated_at: '2026-06-21T11:30:00.000000Z'
                  message: MCF order status synced
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 'Failed to sync MCF order status: Walmart could not locate
                    fulfillment order FO-77001.'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-walmart-integrationinstance-wfs-mcf-orders-mcforder-sync-status
  /api/walmart/{integrationInstance}/wfs/mcf-orders/{mcfOrder}/promise-options:
    post:
      tags:
      - Walmart
      summary: Fetch MCF Order Promise Options
      description: 'Re-check Walmart''s delivery-promise / fulfillability options
        for an MCF order (which shipping speeds Walmart can still honour from WFS
        stock). No request body. Scoped to the integration instance (404 if it belongs
        to another instance). A Walmart-side failure returns a 422. Requires a Bearer
        token.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: Walmart integration instance ID
        example: '1'
      - name: mcfOrder
        in: path
        schema:
          type: integer
        required: true
        description: Local WFS MCF order ID (numeric)
        example: '5'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        shipping_speed:
                          type: string
                        available:
                          type: boolean
                        promised_delivery_date:
                          type: string
                example:
                  data:
                  - shipping_speed: STANDARD
                    available: true
                    promised_delivery_date: '2026-06-26'
                  - shipping_speed: EXPEDITED
                    available: false
                    promised_delivery_date: null
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 'Failed to fetch promise options: Walmart could not compute
                    promise options for this order.'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-walmart-integrationinstance-wfs-mcf-orders-mcforder-promise-options
  /webhooks/walmart/{webhook_token}:
    post:
      tags:
      - Walmart
      summary: Receive Walmart Webhook
      description: Receive a Walmart WFS webhook delivery. No Bearer auth — the secret
        path token is the credential. The body shape is whatever Walmart sends; the
        receiver classifies the delivery into a coarse bucket (inbound / inventory
        / return / order / unknown) by keyword-matching the `eventType` (or `topic`/`type`)
        field, persists it, and dispatches a resync. An unrecognised event type triggers
        a full WFS resync so nothing is missed. Always acks 2xx on success so Walmart
        does not retry; unknown tokens return 404.
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                eventType:
                  type: string
                shipmentId:
                  type: string
                status:
                  type: string
              example:
                eventType: WFS_INBOUND_SHIPMENT_STATUS
                shipmentId: IB-123456
                status: RECEIVED
      parameters:
      - name: webhook_token
        in: path
        schema:
          type: string
        required: true
        description: Opaque per-instance secret token (format wh_[A-Za-z0-9]+) from
          Get WFS Settings → webhook_url. Unknown tokens 404.
        example: wh_aB3xY7zKqLmN0pQrStUvWxYz12345678
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  received:
                    type: boolean
                example:
                  received: true
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: Could not resolve a Walmart integration instance for this
                    webhook.
        '429': *id001
        '422': *id005
      security: []
      operationId: post-webhooks-walmart-webhook-token
  /api/walmart/dashboard:
    get:
      tags:
      - Walmart
      summary: Get Walmart Dashboard Metrics
      description: 'Get aggregated dashboard metrics across all Walmart integration
        instances.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Returns order counts, revenue metrics, and sync status per instance.


        Period validation: Must be one of today, 7d, or 30d. Invalid values return
        a 422 error.


        Sync summary: the response includes sync_summary.auto_sync.schedules with
        one entry per sync type — orders (300s interval), products (86400s), and inventory
        (900s) — each carrying interval_seconds and seconds_until_next, which the
        frontend uses to render the "Next auto-sync in ..." countdown. Orders/products
        countdowns derive from the sync cursor''s last completion; inventory runs
        on a splayed every-15-minutes cron (ScheduleSplay::offset(''walmart'') minutes
        past each quarter-hour, currently :04/:19/:34/:49), so its countdown targets
        those offset boundaries.


        Route name: walmart.dashboard'
      parameters:
      - name: integration_instance_ids
        in: query
        schema:
          type: string
        description: Optional. Comma-separated list of integration instance IDs to
          filter by. Omit for all instances.
        example: 1,2
      - name: period
        in: query
        schema:
          type: string
        description: 'Optional. Time period filter. Valid values: today, 7d, 30d.
          Returns 422 for invalid values.'
        example: 7d
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-walmart-dashboard
  /api/webhook-events:
    get:
      tags:
      - Webhooks
      summary: List Outbound Webhook Event Types
      description: 'Returns the full catalog of subscribable events. Each entry includes
        the wire `event` name, human `label`/`description`, UI `group`, the `required_scope`
        needed to subscribe and view samples, and a one-record `sample_payload` shaped
        exactly like the live webhook payload. Requires the `webhooks:manage` scope.


        :::info[Required scope: `webhooks:manage`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: X-Tenant-Id
        in: header
        schema:
          type: string
        description: Tenant to scope the request to. Required on multi-tenant hosts.
        example: your-tenant-id
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        event:
                          type: string
                        label:
                          type: string
                        description:
                          type: string
                        group:
                          type: string
                        required_scope:
                          type: string
                        sample_payload:
                          type: array
                          items:
                            type: object
                            properties:
                              event:
                                type: string
                              occurred_at:
                                type: string
                              data:
                                type: object
                                properties:
                                  id:
                                    type: integer
                                  order_number:
                                    type: string
                                  status:
                                    type: string
                                  fulfillment_status:
                                    type: string
                                  currency:
                                    type: string
                                  subtotal:
                                    type: string
                                  tax_total:
                                    type: string
                                  total:
                                    type: string
                                  line_count:
                                    type: integer
                                  customer_name:
                                    type: string
                                  customer_email:
                                    type: string
                                  lines:
                                    type: array
                                    items:
                                      type: object
                                      properties:
                                        id:
                                          type: integer
                                        sku:
                                          type: string
                                        name:
                                          type: string
                                        quantity:
                                          type: integer
                                        unit_price:
                                          type: string
                                        total:
                                          type: string
                example:
                  data:
                  - event: sales_order.created
                    label: New Sales Order
                    description: Fires when a new sales order is created (any channel
                      or manual).
                    group: Sales Orders
                    required_scope: orders:read
                    sample_payload:
                    - event: sales_order.created
                      occurred_at: '2026-06-15T14:03:11+00:00'
                      data:
                        id: 4821
                        order_number: SO-10293
                        status: open
                        fulfillment_status: unfulfilled
                        currency: USD
                        subtotal: '129.90'
                        tax_total: '10.39'
                        total: '140.29'
                        line_count: 2
                        customer_name: Jane Doe
                        customer_email: jane@example.com
                        lines:
                        - id: 88231
                          sku: WIDGET-BLK
                          name: Black Widget
                          quantity: 2
                          unit_price: '49.95'
                          total: '99.90'
                  - event: inventory.adjusted
                    label: Inventory Adjusted
                    description: Fires when on-hand inventory is adjusted.
                    group: Inventory
                    required_scope: inventory:read
                    sample_payload: []
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: webhooks:manage
      operationId: get-api-webhook-events
  /api/webhook-events/{event}/sample:
    get:
      tags:
      - Webhooks
      summary: Get Outbound Event Sample Payload
      description: 'Returns up to 3 most-recent real records for the named event,
        each shaped exactly like the live webhook payload. Backs sample-record discovery
        for connected apps. Returns an empty `data` array if the tenant has no matching
        records yet.


        :::info[Required scope: `webhooks:manage`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        Requires `webhooks:manage` AND the event''s own READ scope (e.g. `orders:read`
        for sales_order.* events) — a token with only `webhooks:manage` receives 403.'
      parameters:
      - name: X-Tenant-Id
        in: header
        schema:
          type: string
        description: Tenant to scope the request to. Required on multi-tenant hosts.
        example: your-tenant-id
      - name: event
        in: path
        schema:
          type: string
        required: true
        description: 'Required. Wire event name. One of: sales_order.created, sales_order.shipped,
          sales_order.cancelled, purchase_order.created, purchase_order.approved,
          purchase_order.submitted, purchase_order.received, inventory.adjusted, product.created,
          customer.created.'
        example: sales_order.created
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        event:
                          type: string
                        occurred_at:
                          type: string
                        data:
                          type: object
                          properties:
                            id:
                              type: integer
                            order_number:
                              type: string
                            customer_po_number:
                              type: string
                            status:
                              type: string
                            fulfillment_status:
                              type: string
                            currency:
                              type: string
                            subtotal:
                              type: string
                            tax_total:
                              type: string
                            total:
                              type: string
                            line_count:
                              type: integer
                            customer_id:
                              type: integer
                            customer_name:
                              type: string
                            customer_email:
                              type: string
                            customer_company:
                              type: string
                            shipping_name:
                              type: string
                            shipping_city:
                              type: string
                            shipping_province:
                              type: string
                            shipping_zip:
                              type: string
                            shipping_country:
                              type: string
                            store_id:
                              type: integer
                            store_name:
                              type: string
                            warehouse_id:
                              type: integer
                            warehouse_name:
                              type: string
                            order_date:
                              type: string
                            ship_by_date:
                              type: string
                            fulfilled_at:
                              type: string
                              nullable: true
                            canceled_at:
                              type: string
                              nullable: true
                            created_at:
                              type: string
                            updated_at:
                              type: string
                            lines:
                              type: array
                              items:
                                type: object
                                properties:
                                  id:
                                    type: integer
                                  sku:
                                    type: string
                                  name:
                                    type: string
                                  quantity:
                                    type: integer
                                  unit_price:
                                    type: string
                                  total:
                                    type: string
                example:
                  data:
                  - event: sales_order.created
                    occurred_at: '2026-06-15T14:03:11+00:00'
                    data:
                      id: 4821
                      order_number: SO-10293
                      customer_po_number: PO-55821
                      status: open
                      fulfillment_status: unfulfilled
                      currency: USD
                      subtotal: '129.90'
                      tax_total: '10.39'
                      total: '140.29'
                      line_count: 2
                      customer_id: 312
                      customer_name: Jane Doe
                      customer_email: jane@example.com
                      customer_company: Acme Co
                      shipping_name: Jane Doe
                      shipping_city: San Francisco
                      shipping_province: CA
                      shipping_zip: '94103'
                      shipping_country: US
                      store_id: 7
                      store_name: Shopify US
                      warehouse_id: 2
                      warehouse_name: Main Warehouse
                      order_date: '2026-06-15T14:03:11+00:00'
                      ship_by_date: '2026-06-18T00:00:00+00:00'
                      fulfilled_at: null
                      canceled_at: null
                      created_at: '2026-06-15T14:03:11+00:00'
                      updated_at: '2026-06-15T14:03:11+00:00'
                      lines:
                      - id: 88231
                        sku: WIDGET-BLK
                        name: Black Widget
                        quantity: 2
                        unit_price: '49.95'
                        total: '99.90'
                      - id: 88232
                        sku: GADGET-SM
                        name: Small Gadget
                        quantity: 1
                        unit_price: '30.00'
                        total: '30.00'
        '403':
          description: Forbidden
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: 'Token is missing required scope: orders:read'
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Unknown event.
        '429': *id001
        '401': *id002
      x-required-scope: webhooks:manage
      operationId: get-api-webhook-events-event-sample
  /api/webhook-subscriptions:
    get:
      tags:
      - Webhooks
      summary: List Webhook Subscriptions
      description: 'Paginated list of every webhook subscription on the tenant. The
        signing `secret` is never included here — it is shown only once in the create
        response. Requires the `webhooks:manage` scope.


        :::info[Required scope: `webhooks:manage`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: X-Tenant-Id
        in: header
        schema:
          type: string
        description: Tenant to scope the request to. Required on multi-tenant hosts.
        example: your-tenant-id
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        event:
                          type: string
                        target_url:
                          type: string
                        source:
                          type: string
                        is_active:
                          type: boolean
                        failure_count:
                          type: integer
                        disabled_reason:
                          type: string
                          nullable: true
                        last_delivery_at:
                          type: string
                        last_delivery_status:
                          type: integer
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - id: 42
                    event: sales_order.created
                    target_url: https://hooks.example.com/standard/123456/abcdef
                    source: api
                    is_active: true
                    failure_count: 0
                    disabled_reason: null
                    last_delivery_at: '2026-06-15T14:05:00+00:00'
                    last_delivery_status: 200
                    created_at: '2026-06-15T13:00:00+00:00'
                    updated_at: '2026-06-15T14:05:00+00:00'
                  current_page: 1
                  last_page: 1
                  per_page: 10
                  total: 1
                  from: 1
                  to: 1
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: webhooks:manage
      operationId: get-api-webhook-subscriptions
    post:
      tags:
      - Webhooks
      summary: Create Webhook Subscription
      description: 'Create a subscription. Body fields:


        :::info[Required scope: `webhooks:manage`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::


        - `event` (required, string) — wire event name; must be one of the catalog
        events (see List Events). The token must also hold that event''s READ scope.

        - `target_url` (required, string, max 2048, valid URL) — HTTPS endpoint to
        receive deliveries. Must pass the SSRF guard (public host only).


        The signing `secret` is returned in the response exactly once and is never
        retrievable again — store it immediately.


        Idempotent on (event, target_url): a duplicate POST returns the existing subscription
        with HTTP 200 (and no `secret`) instead of creating a new one (HTTP 201).'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                event:
                  type: string
                target_url:
                  type: string
              example:
                event: sales_order.created
                target_url: https://hooks.example.com/standard/123456/abcdef
      parameters:
      - name: X-Tenant-Id
        in: header
        schema:
          type: string
        description: Tenant to scope the request to. Required on multi-tenant hosts.
        example: your-tenant-id
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      event:
                        type: string
                      target_url:
                        type: string
                      source:
                        type: string
                      is_active:
                        type: boolean
                      failure_count:
                        type: integer
                      disabled_reason:
                        type: string
                        nullable: true
                      last_delivery_at:
                        type: string
                      last_delivery_status:
                        type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 42
                    event: sales_order.created
                    target_url: https://hooks.example.com/standard/123456/abcdef
                    source: api
                    is_active: true
                    failure_count: 0
                    disabled_reason: null
                    last_delivery_at: '2026-06-15T14:05:00+00:00'
                    last_delivery_status: 200
                    created_at: '2026-06-15T13:00:00+00:00'
                    updated_at: '2026-06-15T14:05:00+00:00'
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      event:
                        type: string
                      target_url:
                        type: string
                      source:
                        type: string
                      is_active:
                        type: boolean
                      failure_count:
                        type: integer
                      disabled_reason:
                        type: string
                        nullable: true
                      last_delivery_at:
                        type: string
                        nullable: true
                      last_delivery_status:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      secret:
                        type: string
                example:
                  data:
                    id: 42
                    event: sales_order.created
                    target_url: https://hooks.example.com/standard/123456/abcdef
                    source: api
                    is_active: true
                    failure_count: 0
                    disabled_reason: null
                    last_delivery_at: null
                    last_delivery_status: null
                    created_at: '2026-06-15T13:00:00+00:00'
                    updated_at: '2026-06-15T13:00:00+00:00'
                    secret: whsec_3f9a1c0b8e2d4f6a7c1e9b0d2a4c6e8f
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      event:
                        type: array
                        items:
                          type: string
                      target_url:
                        type: array
                        items:
                          type: string
                example:
                  message: The selected event is not a supported webhook event. (and
                    1 more error)
                  errors:
                    event:
                    - The selected event is not a supported webhook event.
                    target_url:
                    - Target URL must be a valid URL.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: webhooks:manage
      operationId: post-api-webhook-subscriptions
  /api/webhook-subscriptions/{id}:
    get:
      tags:
      - Webhooks
      summary: Get Webhook Subscription
      description: 'Returns a single subscription owned by the authenticated user/tenant.
        Never includes the signing `secret`. Requires the `webhooks:manage` scope.


        :::info[Required scope: `webhooks:manage`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: X-Tenant-Id
        in: header
        schema:
          type: string
        description: Tenant to scope the request to. Required on multi-tenant hosts.
        example: your-tenant-id
      - name: id
        in: path
        schema:
          type: integer
        required: true
        description: Required. Numeric subscription id.
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      event:
                        type: string
                      target_url:
                        type: string
                      source:
                        type: string
                      is_active:
                        type: boolean
                      failure_count:
                        type: integer
                      disabled_reason:
                        type: string
                        nullable: true
                      last_delivery_at:
                        type: string
                      last_delivery_status:
                        type: integer
                      created_at:
                        type: string
                      updated_at:
                        type: string
                example:
                  data:
                    id: 42
                    event: sales_order.created
                    target_url: https://hooks.example.com/standard/123456/abcdef
                    source: api
                    is_active: true
                    failure_count: 0
                    disabled_reason: null
                    last_delivery_at: '2026-06-15T14:05:00+00:00'
                    last_delivery_status: 200
                    created_at: '2026-06-15T13:00:00+00:00'
                    updated_at: '2026-06-15T14:05:00+00:00'
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Webhook subscription not found.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: webhooks:manage
      operationId: get-api-webhook-subscriptions-id
    delete:
      tags:
      - Webhooks
      summary: Delete Webhook Subscription
      description: 'Delete (unsubscribe) a subscription. Idempotent — always returns
        204, even if no matching row existed (clients may retry unsubscribe calls).
        Requires the `webhooks:manage` scope.


        :::info[Required scope: `webhooks:manage`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: X-Tenant-Id
        in: header
        schema:
          type: string
        description: Tenant to scope the request to. Required on multi-tenant hosts.
        example: your-tenant-id
      - name: id
        in: path
        schema:
          type: integer
        required: true
        description: Required. Numeric subscription id.
        example: '42'
      responses:
        '204':
          description: No Content
          content:
            text/plain:
              schema:
                type: string
                example: ''
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      x-required-scope: webhooks:manage
      operationId: delete-api-webhook-subscriptions-id
  /api/webhook-subscriptions/{id}/deliveries:
    get:
      tags:
      - Webhooks
      summary: List Deliveries
      description: 'Paginated delivery log for one subscription, newest first. Each
        row captures one delivery attempt: HTTP `response_status`/`response_body`,
        `duration_ms`, `attempt` number, whether it `succeeded`, and whether it was
        `throttled` (dropped before dispatch because the tenant''s per-minute outbound
        rate cap was hit — `succeeded: false`, `attempt: 0`, `response_status: null`).
        The full signed `payload` that was (or would have been) sent is included.
        Requires the `webhooks:manage` scope.


        :::info[Required scope: `webhooks:manage`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: X-Tenant-Id
        in: header
        schema:
          type: string
        description: Tenant to scope the request to. Required on multi-tenant hosts.
        example: your-tenant-id
      - name: id
        in: path
        schema:
          type: integer
        required: true
        description: Required. Numeric subscription id.
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        delivery_id:
                          type: string
                        event:
                          type: string
                        attempt:
                          type: integer
                        response_status:
                          type: integer
                        response_body:
                          type: string
                        duration_ms:
                          type: integer
                        succeeded:
                          type: boolean
                        throttled:
                          type: boolean
                        payload:
                          type: object
                          properties:
                            event:
                              type: string
                            delivery_id:
                              type: string
                            occurred_at:
                              type: string
                            data:
                              type: object
                              properties:
                                id:
                                  type: integer
                                order_number:
                                  type: string
                                status:
                                  type: string
                        created_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - id: 9001
                    delivery_id: f1e2d3c4-5a6b-7c8d-9e0f-1a2b3c4d5e6f
                    event: sales_order.created
                    attempt: 1
                    response_status: 200
                    response_body: OK
                    duration_ms: 142
                    succeeded: true
                    throttled: false
                    payload:
                      event: sales_order.created
                      delivery_id: f1e2d3c4-5a6b-7c8d-9e0f-1a2b3c4d5e6f
                      occurred_at: '2026-06-15T14:05:00+00:00'
                      data:
                        id: 4821
                        order_number: SO-10293
                        status: open
                    created_at: '2026-06-15T14:05:00+00:00'
                  - id: 9002
                    delivery_id: a9b8c7d6-1234-5678-90ab-cdef01234567
                    event: sales_order.created
                    attempt: 0
                    response_status: null
                    response_body: 'Dropped: tenant outbound webhook rate limit exceeded.'
                    duration_ms: 0
                    succeeded: false
                    throttled: true
                    payload:
                      event: sales_order.created
                      delivery_id: a9b8c7d6-1234-5678-90ab-cdef01234567
                      occurred_at: '2026-06-15T14:05:01+00:00'
                      data:
                        id: 4822
                        order_number: SO-10294
                        status: open
                    created_at: '2026-06-15T14:05:01+00:00'
                  current_page: 1
                  last_page: 1
                  per_page: 10
                  total: 2
                  from: 1
                  to: 2
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Webhook subscription not found.
        '429': *id001
        '401': *id002
        '403': *id003
      x-required-scope: webhooks:manage
      operationId: get-api-webhook-subscriptions-id-deliveries
  /api/webhook-subscriptions/{id}/test:
    post:
      tags:
      - Webhooks
      summary: Send Test Delivery
      description: 'Send a synchronous test delivery to the subscription''s target
        URL with a signed `{ "_test": true }` payload. Runs inline (not queued) so
        the UI can show the result immediately, and records a row in the delivery
        log regardless of outcome. Always returns 200 with the generated `delivery_id`
        even if the target responds with an error (inspect the delivery log for the
        captured status). Requires the `webhooks:manage` scope.


        :::info[Required scope: `webhooks:manage`]

        Grant this scope to your token under [Settings → Developer → Personal Access
        Tokens](https://app.sku.io/settings/api).

        :::'
      requestBody:
        content: {}
      parameters:
      - name: X-Tenant-Id
        in: header
        schema:
          type: string
        description: Tenant to scope the request to. Required on multi-tenant hosts.
        example: your-tenant-id
      - name: id
        in: path
        schema:
          type: integer
        required: true
        description: Required. Numeric subscription id.
        example: '42'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  delivery_id:
                    type: string
                example:
                  message: Test delivery sent.
                  delivery_id: f1e2d3c4-5a6b-7c8d-9e0f-1a2b3c4d5e6f
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Webhook subscription not found.
        '429': *id001
        '401': *id002
        '403': *id003
        '422': *id005
      x-required-scope: webhooks:manage
      operationId: post-api-webhook-subscriptions-id-test
  /api/woo-commerce/{integrationInstance}/activity-log:
    get:
      tags:
      - WooCommerce
      summary: Get Integration Activity Log
      description: 'Get the paginated activity history recorded against the orders
        synced for a WooCommerce integration instance - status changes, sync events,
        and edits, with the user who caused each change.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Route name: woo-commerce.activity-log'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: WooCommerce integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        description:
                          type: string
                        event:
                          type: string
                        subject_type:
                          type: string
                        subject_id:
                          type: integer
                        properties:
                          type: object
                          properties:
                            attributes:
                              type: object
                              properties:
                                status:
                                  type: string
                            old:
                              type: object
                              properties:
                                status:
                                  type: string
                        causer_name:
                          type: string
                        created_at:
                          type: string
                        batch_uuid:
                          type: string
                          nullable: true
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                    items:
                      type: object
                      properties:
                        url:
                          type: string
                          nullable: true
                        label:
                          type: string
                        active:
                          type: boolean
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 88213
                    description: updated
                    event: updated
                    subject_type: WooCommerceOrder
                    subject_id: 4512
                    properties:
                      attributes:
                        status: completed
                      old:
                        status: processing
                    causer_name: Jane Smith
                    created_at: '2026-06-18T14:25:00.000000Z'
                    batch_uuid: null
                  first_page_url: '{{base_url}}/api/woo-commerce/1/activity-log?page=1'
                  from: 1
                  last_page: 3
                  last_page_url: '{{base_url}}/api/woo-commerce/1/activity-log?page=3'
                  links:
                  - url: null
                    label: '&laquo; Previous'
                    active: false
                  - url: '{{base_url}}/api/woo-commerce/1/activity-log?page=1'
                    label: '1'
                    active: true
                  - url: null
                    label: Next &raquo;
                    active: false
                  next_page_url: null
                  path: '{{base_url}}/api/woo-commerce/1/activity-log'
                  per_page: 15
                  prev_page_url: null
                  to: 1
                  total: 42
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-woo-commerce-integrationinstance-activity-log
  /api/woo-commerce/{id}/reports:
    get:
      tags:
      - WooCommerce
      summary: Get Cached Reports
      description: 'Get the most recently cached WooCommerce reports for a specific
        integration instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Returns null data if no reports have been fetched yet. Trigger a refresh to
        fetch reports from WooCommerce.'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-woo-commerce-id-reports
  /api/woo-commerce/{id}/reports/refresh:
    post:
      tags:
      - WooCommerce
      summary: Refresh Reports
      description: 'Dispatch a background job to re-fetch WooCommerce reports for
        the integration instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        The job runs asynchronously on the salesOrderProcessing queue. Call GET /reports
        to retrieve results after the job completes.'
      requestBody:
        content: {}
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-woo-commerce-id-reports-refresh
  /api/woo-commerce/{id}/refunds:
    get:
      tags:
      - WooCommerce
      summary: List WooCommerce Refunds
      description: 'Get a paginated list of WooCommerce order refunds for a specific
        integration instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      - name: page
        in: query
        schema:
          type: integer
        description: Page number for pagination.
        example: '1'
      - name: per_page
        in: query
        schema:
          type: integer
        description: Number of results per page (default 10).
        example: '10'
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-woo-commerce-id-refunds
  /api/woo-commerce/{id}/refunds/refresh:
    post:
      tags:
      - WooCommerce
      summary: Refresh WooCommerce Refunds
      description: 'Dispatch a tracked background job to re-fetch all order refunds
        from WooCommerce.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Returns a tracked_job_log_id that can be used to monitor job progress via
        the tracked job log endpoints.'
      requestBody:
        content: {}
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-woo-commerce-id-refunds-refresh
  /api/woo-commerce/{integrationInstance}/orders/refresh-tracked:
    post:
      tags:
      - WooCommerce
      summary: Refresh Orders from WooCommerce
      description: 'Start a background refresh that downloads orders from WooCommerce
        into SKU.io.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        The `mode` field controls which orders are fetched:

        - `latest` (default) - orders modified since the most recent local order

        - `from_start_date` - orders created since the integration''s configured start
        date

        - `date_range` - orders created on or after `date_from` (`date_to` is accepted
        but not currently applied)

        - `all` - every order in the store


        The job runs asynchronously. The response includes a `tracked_job_log_id`
        you can use to poll job progress.


        Route name: woo-commerce.orders.refresh-tracked'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                mode:
                  type: string
                date_from:
                  type: string
                date_to:
                  type: string
              example:
                mode: date_range
                date_from: '2026-01-01'
                date_to: '2026-01-31'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: WooCommerce integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                  status:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 5120
                  message: Order refresh job has been queued
                  status: Success
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      mode:
                        type: array
                        items:
                          type: string
                example:
                  message: The selected mode is invalid.
                  errors:
                    mode:
                    - The selected mode is invalid.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-woo-commerce-integrationinstance-orders-refresh-tracked
  /api/woo-commerce/{integrationInstance}/orders/latest-sync-info:
    get:
      tags:
      - WooCommerce
      summary: Get Latest Order Sync Info
      description: 'Get a summary of the most recently synced WooCommerce order plus
        counts of how many local WooCommerce orders exist and how many are linked
        to SKU.io sales orders. Useful for deciding whether a refresh is needed.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Route name: woo-commerce.orders.latest-sync-info'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: WooCommerce integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      latest_order_id:
                        type: string
                      latest_order_date:
                        type: string
                      latest_order_status:
                        type: string
                      total_orders:
                        type: integer
                      with_sku_order:
                        type: integer
                      without_sku_order:
                        type: integer
                example:
                  data:
                    latest_order_id: '1189'
                    latest_order_date: '2026-06-14T09:21:33.000000Z'
                    latest_order_status: processing
                    total_orders: 1240
                    with_sku_order: 1180
                    without_sku_order: 60
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-woo-commerce-integrationinstance-orders-latest-sync-info
  /api/woo-commerce/{integrationInstance}/orders/archive:
    put:
      tags:
      - WooCommerce
      summary: Bulk Archive Orders
      description: 'Archive multiple WooCommerce orders by their local IDs. Orders
        that are already archived are skipped.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Route name: woo-commerce.orders.bulk-archive'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 4512
                - 4513
                - 4514
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: WooCommerce integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  archived_count:
                    type: integer
                example:
                  message: 3 orders archived successfully
                  archived_count: 3
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      ids:
                        type: array
                        items:
                          type: string
                example:
                  message: The ids field is required.
                  errors:
                    ids:
                    - The ids field is required.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: put-api-woo-commerce-integrationinstance-orders-archive
  /api/woo-commerce/{integrationInstance}/orders/unarchive:
    put:
      tags:
      - WooCommerce
      summary: Bulk Unarchive Orders
      description: 'Restore multiple archived WooCommerce orders by their local IDs.
        Orders that are already active are skipped.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Route name: woo-commerce.orders.bulk-unarchive'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 4512
                - 4513
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: WooCommerce integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  unarchived_count:
                    type: integer
                example:
                  message: 2 orders unarchived successfully
                  unarchived_count: 2
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-woo-commerce-integrationinstance-orders-unarchive
  /api/woo-commerce/{integrationInstance}/orders/{order}/archive:
    put:
      tags:
      - WooCommerce
      summary: Archive Order
      description: 'Archive a single WooCommerce order. Archived orders are hidden
        from active listings but remain stored and can be restored later.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Route name: woo-commerce.orders.archive'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties: {}
              example: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: WooCommerce integration instance ID
        example: '1'
      - name: order
        in: path
        schema:
          type: integer
        required: true
        description: Local WooCommerce order ID
        example: '4512'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  archived:
                    type: boolean
                example:
                  message: Order archived successfully
                  archived: true
        '403':
          description: Forbidden
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: Order does not belong to this integration instance
        '429': *id001
        '401': *id002
        '404': *id004
        '422': *id005
      operationId: put-api-woo-commerce-integrationinstance-orders-order-archive
  /api/woo-commerce/{integrationInstance}/orders/{order}/unarchive:
    put:
      tags:
      - WooCommerce
      summary: Unarchive Order
      description: 'Restore a single archived WooCommerce order to the active list.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Route name: woo-commerce.orders.unarchive'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties: {}
              example: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: WooCommerce integration instance ID
        example: '1'
      - name: order
        in: path
        schema:
          type: integer
        required: true
        description: Local WooCommerce order ID
        example: '4512'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  unarchived:
                    type: boolean
                example:
                  message: Order unarchived successfully
                  unarchived: true
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: put-api-woo-commerce-integrationinstance-orders-order-unarchive
  /api/woo-commerce/{integrationInstance}/orders/{order}/activity-log:
    get:
      tags:
      - WooCommerce
      summary: Get Order Activity Log
      description: 'Get the paginated activity history for a single WooCommerce order
        - status changes, sync events, and edits, with the user who caused each change.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Route name: woo-commerce.orders.activity-log'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: WooCommerce integration instance ID
        example: '1'
      - name: order
        in: path
        schema:
          type: integer
        required: true
        description: Local WooCommerce order ID
        example: '4512'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        description:
                          type: string
                        event:
                          type: string
                        subject_type:
                          type: string
                        subject_id:
                          type: integer
                        properties:
                          type: object
                          properties:
                            attributes:
                              type: object
                              properties:
                                status:
                                  type: string
                            old:
                              type: object
                              properties:
                                status:
                                  type: string
                        causer_name:
                          type: string
                        created_at:
                          type: string
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                    items:
                      type: object
                      properties:
                        url:
                          type: string
                          nullable: true
                        label:
                          type: string
                        active:
                          type: boolean
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 88213
                    description: updated
                    event: updated
                    subject_type: WooCommerceOrder
                    subject_id: 4512
                    properties:
                      attributes:
                        status: completed
                      old:
                        status: processing
                    causer_name: Jane Smith
                    created_at: '2026-06-18T14:25:00.000000Z'
                  first_page_url: '{{base_url}}/api/woo-commerce/1/orders/4512/activity-log?page=1'
                  from: 1
                  last_page: 1
                  last_page_url: '{{base_url}}/api/woo-commerce/1/orders/4512/activity-log?page=1'
                  links:
                  - url: null
                    label: '&laquo; Previous'
                    active: false
                  - url: '{{base_url}}/api/woo-commerce/1/orders/4512/activity-log?page=1'
                    label: '1'
                    active: true
                  - url: null
                    label: Next &raquo;
                    active: false
                  next_page_url: null
                  path: '{{base_url}}/api/woo-commerce/1/orders/4512/activity-log'
                  per_page: 15
                  prev_page_url: null
                  to: 1
                  total: 6
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-woo-commerce-integrationinstance-orders-order-activity-log
  /api/woo-commerce/{integrationInstance}/orders/{order}/notes:
    get:
      tags:
      - WooCommerce
      summary: Get Order Notes
      description: 'Fetch the notes for a single order live from the WooCommerce store
        - both system status notes and customer-facing notes. The response is the
        raw WooCommerce order notes payload.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Route name: woo-commerce.orders.notes'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: WooCommerce integration instance ID
        example: '1'
      - name: order
        in: path
        schema:
          type: integer
        required: true
        description: Local WooCommerce order ID
        example: '4512'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        author:
                          type: string
                        date_created:
                          type: string
                        date_created_gmt:
                          type: string
                        note:
                          type: string
                        customer_note:
                          type: boolean
                example:
                  data:
                  - id: 281
                    author: system
                    date_created: '2026-06-14T09:21:35'
                    date_created_gmt: '2026-06-14T09:21:35'
                    note: Order status changed from Pending payment to Processing.
                    customer_note: false
                  - id: 282
                    author: store-admin
                    date_created: '2026-06-15T08:00:12'
                    date_created_gmt: '2026-06-15T08:00:12'
                    note: Shipped via UPS Ground, tracking emailed to customer.
                    customer_note: true
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                  data:
                    type: array
                example:
                  error: 'Failed to fetch order notes: cURL error 28: Operation timed
                    out'
                  data: []
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-woo-commerce-integrationinstance-orders-order-notes
  /api/woo-commerce/{integrationInstance}/orders/{order}/raw:
    get:
      tags:
      - WooCommerce
      summary: Get Raw Order
      description: 'Fetch the raw order payload for a single order directly from the
        WooCommerce REST API (live request, not the locally cached copy).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Route name: woo-commerce.orders.raw'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: WooCommerce integration instance ID
        example: '1'
      - name: order
        in: path
        schema:
          type: integer
        required: true
        description: Local WooCommerce order ID
        example: '4512'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      order:
                        type: object
                        properties:
                          id:
                            type: integer
                          number:
                            type: string
                          status:
                            type: string
                          currency:
                            type: string
                          total:
                            type: string
                          total_tax:
                            type: string
                          date_created_gmt:
                            type: string
                          date_modified_gmt:
                            type: string
                          billing:
                            type: object
                            properties:
                              first_name:
                                type: string
                              last_name:
                                type: string
                              email:
                                type: string
                          line_items:
                            type: array
                            items:
                              type: object
                              properties:
                                id:
                                  type: integer
                                name:
                                  type: string
                                product_id:
                                  type: integer
                                sku:
                                  type: string
                                quantity:
                                  type: integer
                                price:
                                  type: number
                                total:
                                  type: string
                example:
                  data:
                    order:
                      id: 1189
                      number: '1189'
                      status: processing
                      currency: USD
                      total: '49.98'
                      total_tax: '4.12'
                      date_created_gmt: '2026-06-14T09:21:33'
                      date_modified_gmt: '2026-06-15T10:02:11'
                      billing:
                        first_name: Jane
                        last_name: Smith
                        email: jane@example.com
                      line_items:
                      - id: 77
                        name: Stainless Water Bottle 750ml
                        product_id: 42
                        sku: WB-750-SS
                        quantity: 2
                        price: 24.99
                        total: '49.98'
        '403':
          description: Forbidden
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: Order does not belong to this integration instance
        '500':
          description: Internal Server Error
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                  message:
                    type: string
                example:
                  error: Failed to fetch raw order data from WooCommerce
                  message: 'cURL error 28: Operation timed out'
        '429': *id001
        '401': *id002
        '404': *id004
      operationId: get-api-woo-commerce-integrationinstance-orders-order-raw
  /api/woo-commerce/{integrationInstance}/orders/{order}/sku-order:
    delete:
      tags:
      - WooCommerce
      summary: Delete Linked SKU.io Order
      description: 'Delete the SKU.io sales order linked to a WooCommerce order, keeping
        the WooCommerce order record intact. Pass `archive_order=true` to also archive
        the WooCommerce order afterwards.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Route name: woo-commerce.orders.delete-sku-order'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: WooCommerce integration instance ID
        example: '1'
      - name: order
        in: path
        schema:
          type: integer
        required: true
        description: Local WooCommerce order ID
        example: '4512'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  archived_order:
                    type: boolean
                example:
                  message: SKU order deleted successfully and WooCommerce order archived
                  archived_order: true
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: No SKU order linked to this WooCommerce order
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: delete-api-woo-commerce-integrationinstance-orders-order-sku-order
  /api/woo-commerce/{integrationInstance}/orders/bulk-delete-sku-orders:
    post:
      tags:
      - WooCommerce
      summary: Bulk Delete Linked SKU.io Orders
      description: 'Delete the SKU.io sales orders linked to the given WooCommerce
        orders, keeping the WooCommerce order records intact. Set `archive_orders`
        to true to also archive the WooCommerce orders after their linked sales orders
        are removed.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Route name: woo-commerce.orders.bulk-delete-sku-orders'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
                archive_orders:
                  type: boolean
              example:
                ids:
                - 4512
                - 4513
                archive_orders: true
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: WooCommerce integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
              examples:
                example-0:
                  summary: Success
                  value:
                    message: 2 SKU order(s) deleted successfully and WooCommerce orders
                      archived
                    deleted_count: 2
                example-1:
                  summary: No Linked Orders
                  value:
                    message: No orders with linked SKU orders found
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-woo-commerce-integrationinstance-orders-bulk-delete-sku-orders
  /api/woo-commerce/{integrationInstance}/orders/bulk-delete:
    post:
      tags:
      - WooCommerce
      summary: Bulk Delete Orders
      description: 'Permanently delete multiple local WooCommerce order records by
        their local IDs. This removes the local copies only - orders in the WooCommerce
        store are not affected. Linked SKU.io sales orders are not deleted.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Route name: woo-commerce.orders.bulk-delete'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 4512
                - 4513
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: WooCommerce integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  deleted_count:
                    type: integer
                example:
                  message: 2 order(s) deleted successfully
                  deleted_count: 2
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-woo-commerce-integrationinstance-orders-bulk-delete
  /api/woo-commerce/{integrationInstance}/pre-start-date-orders:
    get:
      tags:
      - WooCommerce
      summary: List Pre-Start-Date Orders
      description: 'Query the WooCommerce store live for orders created before your
        SKU.io inventory start date, so historical orders can be selectively imported
        without affecting inventory.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Each returned order carries an `eligible` flag with an `eligibility_reason`
        (cancelled, refunded, failed, and trashed orders are not eligible) and an
        `already_imported` flag for orders that already exist locally.


        Both dates must be before the inventory start date. Returns up to 1,000 matching
        orders per query.


        Route name: woo-commerce.pre-start-date-orders.query'
      parameters:
      - name: created_at_min
        in: query
        schema:
          type: string
        description: Required. Earliest order creation date (must be before the inventory
          start date).
        example: '2025-10-01'
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: WooCommerce integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        woo_commerce_order_id:
                          type: integer
                        name:
                          type: string
                        email:
                          type: string
                        created_at:
                          type: string
                        status:
                          type: string
                        total_price:
                          type: string
                        currency:
                          type: string
                        line_items:
                          type: array
                          items:
                            type: object
                            properties:
                              title:
                                type: string
                              sku:
                                type: string
                              quantity:
                                type: integer
                              current_quantity:
                                type: integer
                              price:
                                type: string
                              variant_title:
                                type: string
                                nullable: true
                        eligible:
                          type: boolean
                        eligibility_reason:
                          type: string
                          nullable: true
                        already_imported:
                          type: boolean
                  inventory_start_date:
                    type: string
                  meta:
                    type: object
                    properties:
                      total_queried:
                        type: integer
                      eligible_count:
                        type: integer
                      already_imported_count:
                        type: integer
                example:
                  data:
                  - woo_commerce_order_id: 1189
                    name: '#1189'
                    email: jane@example.com
                    created_at: '2025-11-03T15:22:10'
                    status: completed
                    total_price: '49.98'
                    currency: USD
                    line_items:
                    - title: Stainless Water Bottle 750ml
                      sku: WB-750-SS
                      quantity: 2
                      current_quantity: 2
                      price: '24.99'
                      variant_title: null
                    eligible: true
                    eligibility_reason: null
                    already_imported: false
                  inventory_start_date: '2026-01-01'
                  meta:
                    total_queried: 1
                    eligible_count: 1
                    already_imported_count: 0
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      created_at_min:
                        type: array
                        items:
                          type: string
                example:
                  message: Created at min must be before the inventory start date.
                  errors:
                    created_at_min:
                    - Created at min must be before the inventory start date.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-woo-commerce-integrationinstance-pre-start-date-orders
  /api/woo-commerce/{integrationInstance}/pre-start-date-orders/search:
    get:
      tags:
      - WooCommerce
      summary: Search Pre-Start-Date Orders
      description: 'Search the WooCommerce store for specific pre-start-date orders
        by order number, order ID, or customer email. Returns the same response format
        as the list endpoint, including eligibility and already-imported flags.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Route name: woo-commerce.pre-start-date-orders.search'
      parameters:
      - name: search_by
        in: query
        schema:
          type: string
        description: 'Required. Field to search by: order_number, order_id, or email.'
        example: order_number
      - name: search_term
        in: query
        schema:
          type: integer
        description: Required. Value to search for (max 255 characters).
        example: '1189'
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: WooCommerce integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        woo_commerce_order_id:
                          type: integer
                        name:
                          type: string
                        email:
                          type: string
                        created_at:
                          type: string
                        status:
                          type: string
                        total_price:
                          type: string
                        currency:
                          type: string
                        line_items:
                          type: array
                          items:
                            type: object
                            properties:
                              title:
                                type: string
                              sku:
                                type: string
                              quantity:
                                type: integer
                              current_quantity:
                                type: integer
                              price:
                                type: string
                              variant_title:
                                type: string
                                nullable: true
                        eligible:
                          type: boolean
                        eligibility_reason:
                          type: string
                          nullable: true
                        already_imported:
                          type: boolean
                  inventory_start_date:
                    type: string
                  meta:
                    type: object
                    properties:
                      total_queried:
                        type: integer
                      eligible_count:
                        type: integer
                      already_imported_count:
                        type: integer
                example:
                  data:
                  - woo_commerce_order_id: 1189
                    name: '#1189'
                    email: jane@example.com
                    created_at: '2025-11-03T15:22:10'
                    status: completed
                    total_price: '49.98'
                    currency: USD
                    line_items:
                    - title: Stainless Water Bottle 750ml
                      sku: WB-750-SS
                      quantity: 2
                      current_quantity: 2
                      price: '24.99'
                      variant_title: null
                    eligible: true
                    eligibility_reason: null
                    already_imported: false
                  inventory_start_date: '2026-01-01'
                  meta:
                    total_queried: 1
                    eligible_count: 1
                    already_imported_count: 0
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-woo-commerce-integrationinstance-pre-start-date-orders-search
  /api/woo-commerce/{integrationInstance}/pre-start-date-orders/import:
    post:
      tags:
      - WooCommerce
      summary: Import Pre-Start-Date Orders
      description: 'Import selected pre-start-date orders from WooCommerce by their
        WooCommerce order IDs. Full order data is downloaded and stored flagged as
        a pre-start-date import so it does not affect inventory. Orders that already
        exist locally are marked instead of duplicated, and cancelled orders are skipped.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Because each order is fetched individually from WooCommerce, the import runs
        asynchronously as a queued background job. The request returns immediately
        with a tracked job log id that can be polled to follow the import''s progress.


        **Requires the inventory start date to be set** — returns 422 otherwise.


        **Path Parameters:**

        - `integrationInstance` - The WooCommerce integration instance ID


        **Request Body:**

        - `woo_commerce_order_ids` (required, array of integers, 1-10,000 entries)
        — WooCommerce order IDs to import.


        **Response:**

        - `data.tracked_job_log_id` - id of the tracked job log; poll it to follow
        import progress

        - `message` - human-readable confirmation of how many orders are being imported


        Route name: woo-commerce.pre-start-date-orders.import'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                woo_commerce_order_ids:
                  type: array
                  items:
                    type: integer
              example:
                woo_commerce_order_ids:
                - 1189
                - 1190
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: WooCommerce integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                  message:
                    type: string
                example:
                  data:
                    tracked_job_log_id: 4821
                  message: Importing 2 pre-start-date orders.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: Inventory start date must be set before importing pre-start-date
                    orders.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-woo-commerce-integrationinstance-pre-start-date-orders-import
  /api/woo-commerce/{id}/products/search-woocommerce:
    post:
      tags:
      - WooCommerce
      summary: Search WooCommerce Products
      description: 'Search products on the remote WooCommerce store. Used by the Refresh
        modal''s Search Specific Product tab to locate a product and offer a one-click
        download.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Body fields:

        - search_by (string, required): One of sku, title, product_id.

        - query (string, required): Search term, max 255 chars.


        Route name: woo-commerce.products.search-woocommerce'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                search_by:
                  type: string
                query:
                  type: string
              example:
                search_by: sku
                query: ACME-001
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: string
                        productId:
                          type: string
                        title:
                          type: string
                        sku:
                          type: string
                        status:
                          type: string
                        existsInDatabase:
                          type: boolean
                        databaseId:
                          type: integer
                        variantCount:
                          type: integer
                example:
                  data:
                  - id: '42'
                    productId: '42'
                    title: Acme Widget
                    sku: ACME-001
                    status: publish
                    existsInDatabase: true
                    databaseId: 17
                    variantCount: 3
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-woo-commerce-id-products-search-woocommerce
  /api/woo-commerce/{id}/products/refresh-product:
    post:
      tags:
      - WooCommerce
      summary: Refresh Single Product
      description: 'Fetch a single product (and its variations) from WooCommerce and
        persist it locally. Used by the Refresh modal''s Search Specific Product tab
        download button.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Body fields:

        - product_id (string, required): WooCommerce parent product ID.


        Route name: woo-commerce.products.refresh-product'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                product_id:
                  type: string
              example:
                product_id: '42'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Product refreshed successfully.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-woo-commerce-id-products-refresh-product
  /api/woo-commerce/{id}/products/latest-sync-info:
    get:
      tags:
      - WooCommerce
      summary: Get WooCommerce Products Latest Sync Info
      description: 'Return summary information about the locally-cached WooCommerce
        products for a single integration instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Used by the Refresh Products modal on the application UI listings page to
        display the latest synced product title, last sync date, and mapping counts.


        Route name: woo-commerce.products.latest-sync-info'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      latest_product_title:
                        type: string
                      latest_product_date:
                        type: string
                      total_products:
                        type: integer
                      mapped_products:
                        type: integer
                      unmapped_products:
                        type: integer
                example:
                  data:
                    latest_product_title: Acme Widget - Blue
                    latest_product_date: '2026-05-24T14:32:11.000000Z'
                    total_products: 1245
                    mapped_products: 1100
                    unmapped_products: 145
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-woo-commerce-id-products-latest-sync-info
  /api/woo-commerce/{integrationInstance}/products/{product}/map:
    post:
      tags:
      - WooCommerce
      summary: Map Product
      description: 'Map a WooCommerce product to an existing SKU.io product by creating
        (or updating) its product listing.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        After mapping, a background job is dispatched to link any unmapped sales order
        lines that match the new listing.


        Route name: woo-commerce.products.map-single'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                product_id:
                  type: integer
              example:
                product_id: 55
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: WooCommerce integration instance ID
        example: '1'
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: Local WooCommerce product ID
        example: '231'
      responses:
        '201':
          description: Created
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      woo_commerce_parent_product_id:
                        type: integer
                      woo_commerce_product_id:
                        type: integer
                      woo_commerce_variation_id:
                        type: integer
                      woo_commerce_unique_id:
                        type: integer
                      parent_product_name:
                        type: string
                      parent_sku:
                        type: string
                      variation_name:
                        type: string
                        nullable: true
                      unified_title:
                        type: string
                      sku:
                        type: string
                      price:
                        type: number
                      regular_price:
                        type: number
                      sale_price:
                        type: string
                        nullable: true
                      manage_stock:
                        type: boolean
                      stock_quantity:
                        type: integer
                      stock_status:
                        type: string
                      product_type:
                        type: string
                      status:
                        type: string
                      image_url:
                        type: string
                      product_listing_id:
                        type: integer
                      product:
                        type: object
                        properties:
                          id:
                            type: integer
                          name:
                            type: string
                          sku:
                            type: string
                          default_financial_line_type_id:
                            type: integer
                          default_financial_line_type:
                            type: object
                            properties:
                              id:
                                type: integer
                              name:
                                type: string
                              classification:
                                type: string
                          listing_id:
                            type: integer
                      subscription_offering:
                        type: string
                        nullable: true
                      mapped_at:
                        type: string
                      mapped_sku:
                        type: string
                      created_at:
                        type: string
                      updated_at:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 231
                    integration_instance_id: 1
                    woo_commerce_parent_product_id: 42
                    woo_commerce_product_id: 42
                    woo_commerce_variation_id: 0
                    woo_commerce_unique_id: 42
                    parent_product_name: Stainless Water Bottle
                    parent_sku: WB-750
                    variation_name: null
                    unified_title: Stainless Water Bottle 750ml
                    sku: WB-750-SS
                    price: 24.95
                    regular_price: 24.95
                    sale_price: null
                    manage_stock: true
                    stock_quantity: 132
                    stock_status: instock
                    product_type: simple
                    status: publish
                    image_url: https://store.example.com/wp-content/uploads/wb-750.jpg
                    product_listing_id: 977
                    product:
                      id: 55
                      name: Stainless Water Bottle 750ml
                      sku: WB-750-SS
                      default_financial_line_type_id: 3
                      default_financial_line_type:
                        id: 3
                        name: Product Sales
                        classification: revenue
                      listing_id: 977
                    subscription_offering: null
                    mapped_at: '2026-07-01T09:00:00.000000Z'
                    mapped_sku: WB-750-SS
                    created_at: '2026-02-11T08:30:00.000000Z'
                    updated_at: '2026-07-01T09:00:00.000000Z'
                  message: Product mapped successfully.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      product_id:
                        type: array
                        items:
                          type: string
                example:
                  message: The product id field is required.
                  errors:
                    product_id:
                    - The product id field is required.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-woo-commerce-integrationinstance-products-product-map
    delete:
      tags:
      - WooCommerce
      summary: Unmap Product
      description: 'Remove the mapping between a WooCommerce product and its SKU.io
        product by deleting the product listing. The WooCommerce product and the SKU.io
        product both remain.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Route name: woo-commerce.products.unmap-single'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: WooCommerce integration instance ID
        example: '1'
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: Local WooCommerce product ID
        example: '231'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      integration_instance_id:
                        type: integer
                      woo_commerce_parent_product_id:
                        type: integer
                      woo_commerce_product_id:
                        type: integer
                      woo_commerce_variation_id:
                        type: integer
                      woo_commerce_unique_id:
                        type: integer
                      parent_product_name:
                        type: string
                      parent_sku:
                        type: string
                      variation_name:
                        type: string
                        nullable: true
                      unified_title:
                        type: string
                      sku:
                        type: string
                      price:
                        type: number
                      regular_price:
                        type: number
                      sale_price:
                        type: string
                        nullable: true
                      manage_stock:
                        type: boolean
                      stock_quantity:
                        type: integer
                      stock_status:
                        type: string
                      product_type:
                        type: string
                      status:
                        type: string
                      image_url:
                        type: string
                      product_listing_id:
                        type: string
                        nullable: true
                      product:
                        type: string
                        nullable: true
                      subscription_offering:
                        type: string
                        nullable: true
                      mapped_at:
                        type: string
                        nullable: true
                      mapped_sku:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                  message:
                    type: string
                example:
                  data:
                    id: 231
                    integration_instance_id: 1
                    woo_commerce_parent_product_id: 42
                    woo_commerce_product_id: 42
                    woo_commerce_variation_id: 0
                    woo_commerce_unique_id: 42
                    parent_product_name: Stainless Water Bottle
                    parent_sku: WB-750
                    variation_name: null
                    unified_title: Stainless Water Bottle 750ml
                    sku: WB-750-SS
                    price: 24.95
                    regular_price: 24.95
                    sale_price: null
                    manage_stock: true
                    stock_quantity: 132
                    stock_status: instock
                    product_type: simple
                    status: publish
                    image_url: https://store.example.com/wp-content/uploads/wb-750.jpg
                    product_listing_id: null
                    product: null
                    subscription_offering: null
                    mapped_at: null
                    mapped_sku: null
                    created_at: '2026-02-11T08:30:00.000000Z'
                    updated_at: '2026-07-01T09:00:00.000000Z'
                  message: Product unmapped successfully.
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: Product is not mapped.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: delete-api-woo-commerce-integrationinstance-products-product-map
  /api/woo-commerce/{integrationInstance}/products/{product}/orders:
    get:
      tags:
      - WooCommerce
      summary: List Orders for Product
      description: 'Get a paginated list of WooCommerce orders that contain a given
        product, newest first.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Route name: woo-commerce.products.orders'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: WooCommerce integration instance ID
        example: '1'
      - name: product
        in: path
        schema:
          type: integer
        required: true
        description: Local WooCommerce product ID
        example: '231'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        integration_instance_id:
                          type: integer
                        woo_commerce_id:
                          type: string
                        number:
                          type: string
                        status:
                          type: string
                        currency:
                          type: string
                        total:
                          type: string
                        total_tax:
                          type: string
                        date_created_gmt:
                          type: string
                        date_modified_gmt:
                          type: string
                        date_completed_gmt:
                          type: string
                          nullable: true
                        pre_start_date_import:
                          type: boolean
                        archived_at:
                          type: string
                          nullable: true
                        sku_sales_order:
                          type: object
                          properties:
                            id:
                              type: integer
                            number:
                              type: string
                            order_status:
                              type: string
                            fulfillment_status:
                              type: string
                            payment_status:
                              type: string
                        last_synced_at:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  current_page:
                    type: integer
                  last_page:
                    type: integer
                  per_page:
                    type: integer
                  total:
                    type: integer
                  from:
                    type: integer
                  to:
                    type: integer
                example:
                  data:
                  - id: 4512
                    integration_instance_id: 1
                    woo_commerce_id: '1189'
                    number: '1189'
                    status: processing
                    currency: USD
                    total: '49.98'
                    total_tax: '4.12'
                    date_created_gmt: '2026-06-14T09:21:33.000000Z'
                    date_modified_gmt: '2026-06-15T10:02:11.000000Z'
                    date_completed_gmt: null
                    pre_start_date_import: false
                    archived_at: null
                    sku_sales_order:
                      id: 887
                      number: SO-1042
                      order_status: PROCESSING
                      fulfillment_status: UNFULFILLED
                      payment_status: PAID
                    last_synced_at: '2026-06-15T10:02:11+00:00'
                    created_at: '2026-06-14T09:22:00.000000Z'
                    updated_at: '2026-06-15T10:02:11.000000Z'
                  current_page: 1
                  last_page: 2
                  per_page: 10
                  total: 14
                  from: 1
                  to: 10
        '403':
          description: Forbidden
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                example:
                  error: Product does not belong to this integration instance
        '429': *id001
        '401': *id002
        '404': *id004
      operationId: get-api-woo-commerce-integrationinstance-products-product-orders
  /api/woo-commerce/{integrationInstance}/mappings:
    get:
      tags:
      - WooCommerce
      summary: Get Field Mappings
      description: 'Get the product field mappings for a WooCommerce integration instance
        - which WooCommerce product fields populate which SKU.io product fields when
        products are created or updated from listings.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        The response includes the default mappings, any custom overrides, the effective
        (merged) mappings, and the catalog of available fields on both sides.


        Route name: woo-commerce.mappings.show'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: WooCommerce integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      integration_instance_id:
                        type: integer
                      integration_name:
                        type: string
                      mappings:
                        type: array
                        items:
                          type: object
                          properties:
                            listing_field:
                              type: string
                            sku_field:
                              type: string
                            source:
                              type: string
                            description:
                              type: string
                      available_woocommerce_fields:
                        type: object
                        properties:
                          sku:
                            type: object
                            properties:
                              name:
                                type: string
                              label:
                                type: string
                              type:
                                type: string
                              description:
                                type: string
                              group:
                                type: string
                          name:
                            type: object
                            properties:
                              name:
                                type: string
                              label:
                                type: string
                              type:
                                type: string
                              description:
                                type: string
                              group:
                                type: string
                          weight:
                            type: object
                            properties:
                              name:
                                type: string
                              label:
                                type: string
                              type:
                                type: string
                              description:
                                type: string
                              group:
                                type: string
                      available_sku_fields:
                        type: object
                        properties:
                          sku:
                            type: object
                            properties:
                              name:
                                type: string
                              label:
                                type: string
                              type:
                                type: string
                          name:
                            type: object
                            properties:
                              name:
                                type: string
                              label:
                                type: string
                              type:
                                type: string
                          weight:
                            type: object
                            properties:
                              name:
                                type: string
                              label:
                                type: string
                              type:
                                type: string
                      default_mappings:
                        type: array
                        items:
                          type: object
                          properties:
                            listing_field:
                              type: string
                            sku_field:
                              type: string
                            source:
                              type: string
                            description:
                              type: string
                      custom_mappings:
                        type: array
                        items:
                          type: object
                          properties:
                            listing_field:
                              type: string
                            sku_field:
                              type: string
                            parsers:
                              type: array
                            source:
                              type: string
                            description:
                              type: string
                      effective_mappings:
                        type: array
                        items:
                          type: object
                          properties:
                            listing_field:
                              type: string
                            sku_field:
                              type: string
                            source:
                              type: string
                            description:
                              type: string
                example:
                  data:
                    integration_instance_id: 1
                    integration_name: My WooCommerce Store
                    mappings:
                    - listing_field: name
                      sku_field: name
                      source: default
                      description: Maps name to name
                    - listing_field: weight
                      sku_field: weight
                      parsers: []
                      source: custom
                      description: 'Custom mapping: weight to weight'
                    available_woocommerce_fields:
                      sku:
                        name: sku
                        label: SKU
                        type: string
                        description: Stock Keeping Unit
                        group: Identifiers
                      name:
                        name: name
                        label: Product Name
                        type: string
                        description: Product name/title
                        group: Product Info
                      weight:
                        name: weight
                        label: Weight
                        type: string
                        description: Product weight
                        group: Shipping
                    available_sku_fields:
                      sku:
                        name: sku
                        label: SKU
                        type: string
                      name:
                        name: name
                        label: Name
                        type: string
                      weight:
                        name: weight
                        label: Weight
                        type: number
                    default_mappings:
                    - listing_field: name
                      sku_field: name
                      source: default
                      description: Maps name to name
                    custom_mappings:
                    - listing_field: weight
                      sku_field: weight
                      parsers: []
                      source: custom
                      description: 'Custom mapping: weight to weight'
                    effective_mappings:
                    - listing_field: name
                      sku_field: name
                      source: default
                      description: Maps name to name
                    - listing_field: weight
                      sku_field: weight
                      parsers: []
                      source: custom
                      description: 'Custom mapping: weight to weight'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-woo-commerce-integrationinstance-mappings
    put:
      tags:
      - WooCommerce
      summary: Update Field Mappings
      description: 'Replace the custom product field mappings for a WooCommerce integration
        instance. Each mapping pairs a WooCommerce `listing_field` with a SKU.io `sku_field`,
        with optional `parsers` applied to transform the value. Custom mappings override
        the defaults for the same field.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Route name: woo-commerce.mappings.update'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                mappings:
                  type: array
                  items:
                    type: object
                    properties:
                      listing_field:
                        type: string
                      sku_field:
                        type: string
                      parsers:
                        type: array
              example:
                mappings:
                - listing_field: weight
                  sku_field: weight
                  parsers: []
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: WooCommerce integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      integration_instance_id:
                        type: integer
                      integration_name:
                        type: string
                      mappings:
                        type: array
                        items:
                          type: object
                          properties:
                            listing_field:
                              type: string
                            sku_field:
                              type: string
                            source:
                              type: string
                            description:
                              type: string
                      effective_mappings:
                        type: array
                        items:
                          type: object
                          properties:
                            listing_field:
                              type: string
                            sku_field:
                              type: string
                            source:
                              type: string
                            description:
                              type: string
                  message:
                    type: string
                example:
                  data:
                    integration_instance_id: 1
                    integration_name: My WooCommerce Store
                    mappings:
                    - listing_field: name
                      sku_field: name
                      source: default
                      description: Maps name to name
                    - listing_field: weight
                      sku_field: weight
                      parsers: []
                      source: custom
                      description: 'Custom mapping: weight to weight'
                    effective_mappings:
                    - listing_field: name
                      sku_field: name
                      source: default
                      description: Maps name to name
                    - listing_field: weight
                      sku_field: weight
                      parsers: []
                      source: custom
                      description: 'Custom mapping: weight to weight'
                  message: Field mappings updated successfully
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      mappings.0.sku_field:
                        type: array
                        items:
                          type: string
                example:
                  message: The mappings.0.sku_field field is required.
                  errors:
                    mappings.0.sku_field:
                    - The mappings.0.sku_field field is required.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: put-api-woo-commerce-integrationinstance-mappings
  /api/woo-commerce/{id}/customers:
    get:
      tags:
      - WooCommerce
      summary: List WooCommerce Customers
      description: 'Get a paginated list of WooCommerce customers for a specific integration
        instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      - name: filter[search]
        in: query
        schema:
          type: string
        description: Optional. Search by customer name or email.
        example: john
      - name: page
        in: query
        schema:
          type: integer
        description: Page number for pagination.
        example: '1'
      - name: per_page
        in: query
        schema:
          type: integer
        description: Number of results per page.
        example: '10'
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-woo-commerce-id-customers
  /api/woo-commerce/{id}/customers/sync:
    post:
      tags:
      - WooCommerce
      summary: Sync WooCommerce Customers
      description: 'Sync customers from WooCommerce for the integration instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Returns the count of synced customers and pages fetched.'
      requestBody:
        content: {}
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-woo-commerce-id-customers-sync
  /api/woo-commerce/{integrationInstance}/fulfillments:
    get:
      tags:
      - WooCommerce
      summary: List Fulfillments
      description: 'Get a paginated list of fulfilled shipments for sales orders that
        originated from this WooCommerce store. Each item shows whether it has been
        submitted to WooCommerce (`sync_status` of submitted or pending).


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Text and date filters accept operator suffixes, e.g. `filter[tracking_number.contains]=1Z9`
        or `filter[fulfilled_at.between]=2026-06-01,2026-06-30`. Text operators: contains,
        does_not_contain, is, is_not, is_one_of, is_not_one_of, starts_with, does_not_start_with,
        ends_with, does_not_end_with, is_empty, is_not_empty.


        Allowed sorts: id, fulfilled_at, created_at, submitted_to_sales_channel_at
        (default -id).


        Route name: woo-commerce.fulfillments.index'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: WooCommerce integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        fulfillment_number:
                          type: string
                        fulfillment_type:
                          type: string
                        status:
                          type: string
                        tracking_number:
                          type: string
                        cost:
                          type: string
                        fulfilled_at:
                          type: string
                        submitted_to_sales_channel_at:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                        carrier:
                          type: string
                        shipping_method_display:
                          type: string
                        sales_order:
                          type: object
                          properties:
                            id:
                              type: integer
                            sales_order_number:
                              type: string
                        woocommerce_order:
                          type: object
                          properties:
                            id:
                              type: integer
                            woo_commerce_id:
                              type: string
                        warehouse:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        shipping_method:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        sync_status:
                          type: string
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                    items:
                      type: object
                      properties:
                        url:
                          type: string
                          nullable: true
                        label:
                          type: string
                        active:
                          type: boolean
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 3120
                    fulfillment_number: F-3120
                    fulfillment_type: shipment
                    status: FULFILLED
                    tracking_number: 1Z999AA10123456784
                    cost: '8.45'
                    fulfilled_at: '2026-06-18T14:22:05+00:00'
                    submitted_to_sales_channel_at: null
                    created_at: '2026-06-18T14:22:06+00:00'
                    carrier: UPS
                    shipping_method_display: UPS Ground
                    sales_order:
                      id: 887
                      sales_order_number: SO-1042
                    woocommerce_order:
                      id: 4512
                      woo_commerce_id: '1189'
                    warehouse:
                      id: 2
                      name: Main Warehouse
                    shipping_method:
                      id: 14
                      name: UPS Ground
                    sync_status: pending
                  first_page_url: '{{base_url}}/api/woo-commerce/1/fulfillments?page=1'
                  from: 1
                  last_page: 5
                  last_page_url: '{{base_url}}/api/woo-commerce/1/fulfillments?page=5'
                  links:
                  - url: null
                    label: '&laquo; Previous'
                    active: false
                  - url: '{{base_url}}/api/woo-commerce/1/fulfillments?page=1'
                    label: '1'
                    active: true
                  - url: null
                    label: Next &raquo;
                    active: false
                  next_page_url: null
                  path: '{{base_url}}/api/woo-commerce/1/fulfillments'
                  per_page: 10
                  prev_page_url: null
                  to: 1
                  total: 48
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-woo-commerce-integrationinstance-fulfillments
  /api/woo-commerce/{integrationInstance}/fulfillments/pending:
    get:
      tags:
      - WooCommerce
      summary: List Pending Fulfillments
      description: 'Get a paginated list of fulfilled shipments that have not yet
        been submitted to WooCommerce. Pickup fulfillments and fulfillments on cancelled
        orders are excluded.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Text and date filters accept operator suffixes, e.g. `filter[tracking_number.contains]=1Z9`.


        Allowed sorts: id, fulfilled_at, created_at, tracking_number (default -created_at).


        Route name: woo-commerce.fulfillments.pending'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: WooCommerce integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        fulfillment_number:
                          type: string
                        fulfillment_type:
                          type: string
                        status:
                          type: string
                        tracking_number:
                          type: string
                        cost:
                          type: string
                        fulfilled_at:
                          type: string
                        submitted_to_sales_channel_at:
                          type: string
                          nullable: true
                        created_at:
                          type: string
                        carrier:
                          type: string
                        shipping_method_display:
                          type: string
                        sales_order:
                          type: object
                          properties:
                            id:
                              type: integer
                            sales_order_number:
                              type: string
                        woocommerce_order:
                          type: object
                          properties:
                            id:
                              type: integer
                            woo_commerce_id:
                              type: string
                        warehouse:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        shipping_method:
                          type: object
                          properties:
                            id:
                              type: integer
                            name:
                              type: string
                        sync_status:
                          type: string
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                    items:
                      type: object
                      properties:
                        url:
                          type: string
                          nullable: true
                        label:
                          type: string
                        active:
                          type: boolean
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 3120
                    fulfillment_number: F-3120
                    fulfillment_type: shipment
                    status: FULFILLED
                    tracking_number: 1Z999AA10123456784
                    cost: '8.45'
                    fulfilled_at: '2026-06-18T14:22:05+00:00'
                    submitted_to_sales_channel_at: null
                    created_at: '2026-06-18T14:22:06+00:00'
                    carrier: UPS
                    shipping_method_display: UPS Ground
                    sales_order:
                      id: 887
                      sales_order_number: SO-1042
                    woocommerce_order:
                      id: 4512
                      woo_commerce_id: '1189'
                    warehouse:
                      id: 2
                      name: Main Warehouse
                    shipping_method:
                      id: 14
                      name: UPS Ground
                    sync_status: pending
                  first_page_url: '{{base_url}}/api/woo-commerce/1/fulfillments/pending?page=1'
                  from: 1
                  last_page: 1
                  last_page_url: '{{base_url}}/api/woo-commerce/1/fulfillments/pending?page=1'
                  links:
                  - url: null
                    label: '&laquo; Previous'
                    active: false
                  - url: '{{base_url}}/api/woo-commerce/1/fulfillments/pending?page=1'
                    label: '1'
                    active: true
                  - url: null
                    label: Next &raquo;
                    active: false
                  next_page_url: null
                  path: '{{base_url}}/api/woo-commerce/1/fulfillments/pending'
                  per_page: 10
                  prev_page_url: null
                  to: 1
                  total: 3
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-woo-commerce-integrationinstance-fulfillments-pending
  /api/woo-commerce/{integrationInstance}/fulfillments/stats:
    get:
      tags:
      - WooCommerce
      summary: Get Fulfillment Stats
      description: 'Get the count of fulfillments waiting to be submitted to WooCommerce,
        plus the automatic sync schedule. Pending fulfillments are submitted automatically
        every 10 minutes.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Route name: woo-commerce.fulfillments.stats'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: WooCommerce integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      pending_sync_count:
                        type: integer
                      sync_schedule:
                        type: object
                        properties:
                          interval:
                            type: integer
                          unit:
                            type: string
                          description:
                            type: string
                example:
                  data:
                    pending_sync_count: 3
                    sync_schedule:
                      interval: 10
                      unit: minutes
                      description: Fulfillments are automatically synced every 10
                        minutes
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-woo-commerce-integrationinstance-fulfillments-stats
  /api/woo-commerce/{integrationInstance}/fulfillments/{salesOrderFulfillment}/submit:
    post:
      tags:
      - WooCommerce
      summary: Submit Fulfillment
      description: 'Submit a single fulfillment to WooCommerce, recording the shipment
        and its tracking details on the WooCommerce order and marking the order completed
        according to the store''s settings.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Route name: woo-commerce.fulfillments.submit-single'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties: {}
              example: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: WooCommerce integration instance ID
        example: '1'
      - name: salesOrderFulfillment
        in: path
        schema:
          type: integer
        required: true
        description: Sales order fulfillment ID
        example: '3120'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                example:
                  success: true
                  message: The fulfillment submitted successfully
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                example:
                  success: false
                  message: Fulfillment submission failed
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-woo-commerce-integrationinstance-fulfillments-salesorderfulfillment-submit
  /api/woo-commerce/{integrationInstance}/fulfillments/submit-bulk:
    post:
      tags:
      - WooCommerce
      summary: Bulk Submit Fulfillments
      description: 'Submit multiple fulfillments to WooCommerce by their IDs. The
        response reports how many were submitted and how many failed, with per-fulfillment
        error details.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Route name: woo-commerce.fulfillments.submit-bulk'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                ids:
                  type: array
                  items:
                    type: integer
              example:
                ids:
                - 3120
                - 3121
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: WooCommerce integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      submitted:
                        type: integer
                      failed:
                        type: integer
                  errors:
                    type: array
                  message:
                    type: string
                example:
                  success: true
                  data:
                    submitted: 2
                    failed: 0
                  errors: []
                  message: 2 fulfillment(s) submitted, 0 failed
        '422':
          description: Unprocessable Entity
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: object
                    properties:
                      ids.0:
                        type: array
                        items:
                          type: string
                example:
                  message: The selected ids.0 is invalid.
                  errors:
                    ids.0:
                    - The selected ids.0 is invalid.
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: post-api-woo-commerce-integrationinstance-fulfillments-submit-bulk
  /api/woo-commerce/{integrationInstance}/fulfillments/submit-all:
    post:
      tags:
      - WooCommerce
      summary: Submit All Pending Fulfillments
      description: 'Submit every pending fulfillment for the integration instance
        to WooCommerce in one call. The response reports how many were submitted and
        how many failed, with per-fulfillment error details.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Route name: woo-commerce.fulfillments.submit-all'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties: {}
              example: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: WooCommerce integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  data:
                    type: object
                    properties:
                      submitted:
                        type: integer
                      failed:
                        type: integer
                  errors:
                    type: array
                  message:
                    type: string
                example:
                  success: true
                  data:
                    submitted: 3
                    failed: 0
                  errors: []
                  message: 3 fulfillment(s) submitted, 0 failed
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-woo-commerce-integrationinstance-fulfillments-submit-all
  /api/woo-commerce/{integrationInstance}/inventory:
    get:
      tags:
      - WooCommerce
      summary: List Inventory Comparison
      description: 'Get a paginated side-by-side comparison of SKU.io quantities vs
        WooCommerce quantities, one row per mapped product listing. Each row includes
        the variance and a status of synced, variance, or needs_recalc.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        WooCommerce has no multi-location concept - every row belongs to a single
        synthetic "WooCommerce Store" location whose ID equals the integration instance
        ID.


        Text, numeric, and date filters accept operator suffixes, e.g. `filter[sku_quantity.greater_than]=0`,
        `filter[listing_sku.contains]=WB`, `filter[updated_at.between]=2026-06-01,2026-06-30`.


        Allowed sorts: id, sku_quantity, sales_channel_quantity, created_at, updated_at
        (default -id).


        Route name: woo-commerce.inventory.index'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: WooCommerce integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  current_page:
                    type: integer
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        product_listing_id:
                          type: integer
                        document_id:
                          type: integer
                        listing_sku:
                          type: string
                        title:
                          type: string
                        product:
                          type: object
                          properties:
                            id:
                              type: integer
                            sku:
                              type: string
                            name:
                              type: string
                        subscription_offering:
                          type: string
                          nullable: true
                        location_id:
                          type: string
                        location_name:
                          type: string
                        location_is_active:
                          type: boolean
                        sku_quantity:
                          type: integer
                        sales_channel_quantity:
                          type: integer
                        variance:
                          type: integer
                        status:
                          type: string
                        is_sku_recalculation_needed:
                          type: boolean
                        sku_quantity_updated_at:
                          type: string
                        sales_channel_quantity_updated_at:
                          type: string
                        sales_channel_quantity_synced_at:
                          type: string
                        created_at:
                          type: string
                        updated_at:
                          type: string
                  first_page_url:
                    type: string
                  from:
                    type: integer
                  last_page:
                    type: integer
                  last_page_url:
                    type: string
                  links:
                    type: array
                    items:
                      type: object
                      properties:
                        url:
                          type: string
                          nullable: true
                        label:
                          type: string
                        active:
                          type: boolean
                  next_page_url:
                    type: string
                    nullable: true
                  path:
                    type: string
                  per_page:
                    type: integer
                  prev_page_url:
                    type: string
                    nullable: true
                  to:
                    type: integer
                  total:
                    type: integer
                example:
                  current_page: 1
                  data:
                  - id: 9021
                    product_listing_id: 977
                    document_id: 231
                    listing_sku: WB-750-SS
                    title: Stainless Water Bottle 750ml
                    product:
                      id: 55
                      sku: WB-750-SS
                      name: Stainless Water Bottle 750ml
                    subscription_offering: null
                    location_id: '1'
                    location_name: WooCommerce Store
                    location_is_active: true
                    sku_quantity: 132
                    sales_channel_quantity: 128
                    variance: 4
                    status: variance
                    is_sku_recalculation_needed: false
                    sku_quantity_updated_at: '2026-06-20T04:05:31+00:00'
                    sales_channel_quantity_updated_at: '2026-06-20T04:05:32+00:00'
                    sales_channel_quantity_synced_at: '2026-06-19T04:05:30+00:00'
                    created_at: '2026-02-11T08:30:00+00:00'
                    updated_at: '2026-06-20T04:05:32+00:00'
                  first_page_url: '{{base_url}}/api/woo-commerce/1/inventory?page=1'
                  from: 1
                  last_page: 48
                  last_page_url: '{{base_url}}/api/woo-commerce/1/inventory?page=48'
                  links:
                  - url: null
                    label: '&laquo; Previous'
                    active: false
                  - url: '{{base_url}}/api/woo-commerce/1/inventory?page=1'
                    label: '1'
                    active: true
                  - url: null
                    label: Next &raquo;
                    active: false
                  next_page_url: null
                  path: '{{base_url}}/api/woo-commerce/1/inventory'
                  per_page: 10
                  prev_page_url: null
                  to: 1
                  total: 480
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-woo-commerce-integrationinstance-inventory
  /api/woo-commerce/{integrationInstance}/inventory/summary:
    get:
      tags:
      - WooCommerce
      summary: Get Inventory Summary
      description: 'Get aggregate inventory sync statistics for the integration instance:
        total product rows, how many are in sync, how many have a variance, how many
        need recalculation, and the timestamps of the last fetch from WooCommerce
        and last sync to WooCommerce.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Route name: woo-commerce.inventory.summary'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: WooCommerce integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      total_items:
                        type: integer
                      in_sync:
                        type: integer
                      with_variance:
                        type: integer
                      needs_recalculation:
                        type: integer
                      last_fetch_at:
                        type: string
                      last_sync_at:
                        type: string
                example:
                  data:
                    total_items: 480
                    in_sync: 440
                    with_variance: 32
                    needs_recalculation: 8
                    last_fetch_at: '2026-06-20T04:05:32.000000Z'
                    last_sync_at: '2026-06-19T04:05:30.000000Z'
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-woo-commerce-integrationinstance-inventory-summary
  /api/woo-commerce/{integrationInstance}/inventory/locations:
    get:
      tags:
      - WooCommerce
      summary: List Inventory Locations
      description: 'Get the inventory locations for the integration instance. WooCommerce
        has no native location concept, so a single synthetic "WooCommerce Store"
        location is returned whose ID equals the integration instance ID. It is always
        active.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Route name: woo-commerce.inventory.locations'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: WooCommerce integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        id:
                          type: integer
                        name:
                          type: string
                        is_active:
                          type: boolean
                example:
                  data:
                  - id: 1
                    name: WooCommerce Store
                    is_active: true
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-woo-commerce-integrationinstance-inventory-locations
  /api/woo-commerce/{integrationInstance}/inventory/recache:
    post:
      tags:
      - WooCommerce
      summary: Recache Inventory Quantities
      description: 'Start a background job that recalculates SKU.io inventory quantities
        for every product listing mapped to this WooCommerce store. Run this when
        the comparison shows rows needing recalculation.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        The job runs asynchronously. Use the returned `tracked_job_log_id` with the
        recache progress endpoint to poll for completion.


        Route name: woo-commerce.inventory.recache'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties: {}
              example: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: WooCommerce integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                example:
                  message: Inventory recache job has been queued
                  data:
                    tracked_job_log_id: 5120
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-woo-commerce-integrationinstance-inventory-recache
  /api/woo-commerce/{integrationInstance}/inventory/recache-progress/{trackedJobLogId}:
    get:
      tags:
      - WooCommerce
      summary: Get Recache Progress
      description: 'Poll the progress of an inventory recache job using the `tracked_job_log_id`
        returned when the job was queued. The response includes the job status, item
        counts, and completion percentage.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Route name: woo-commerce.inventory.recache-progress'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: WooCommerce integration instance ID
        example: '1'
      - name: trackedJobLogId
        in: path
        schema:
          type: integer
        required: true
        description: Tracked job log ID returned when the job was queued
        example: '5120'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      job_type:
                        type: string
                      queue:
                        type: string
                      job_name:
                        type: string
                      status:
                        type: string
                      related_model:
                        type: object
                        properties:
                          id:
                            type: integer
                          type:
                            type: string
                            nullable: true
                          reference:
                            type: string
                            nullable: true
                      related_model_reference:
                        type: string
                        nullable: true
                      messages:
                        type: array
                      attempted_at:
                        type: string
                      completed_at:
                        type: string
                        nullable: true
                      duration:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      results:
                        type: string
                        nullable: true
                      total_items:
                        type: integer
                      processed_items:
                        type: integer
                      progress_percentage:
                        type: integer
                      progress_mode:
                        type: string
                      stages:
                        type: string
                        nullable: true
                example:
                  data:
                    id: 5120
                    job_type: integration
                    queue: serial
                    job_name: WooCommerce Inventory Recache
                    status: in_progress
                    related_model:
                      id: 1
                      type: null
                      reference: null
                    related_model_reference: null
                    messages: []
                    attempted_at: '2026-06-20T04:00:01.000000Z'
                    completed_at: null
                    duration: null
                    created_at: '2026-06-20T04:00:00.000000Z'
                    updated_at: '2026-06-20T04:01:12.000000Z'
                    results: null
                    total_items: 480
                    processed_items: 120
                    progress_percentage: 25
                    progress_mode: batch
                    stages: null
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Record not found
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-woo-commerce-integrationinstance-inventory-recache-progress-trackedjoblogid
  /api/woo-commerce/{integrationInstance}/inventory/sync:
    post:
      tags:
      - WooCommerce
      summary: Sync Inventory to WooCommerce
      description: 'Start a background job that pushes SKU.io inventory quantities
        to the WooCommerce store, updating stock levels on the mapped products.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        The job runs asynchronously. Use the returned `tracked_job_log_id` with the
        sync progress endpoint to poll for completion.


        Route name: woo-commerce.inventory.sync'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties: {}
              example: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: WooCommerce integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                example:
                  message: Inventory sync job has been queued
                  data:
                    tracked_job_log_id: 5121
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-woo-commerce-integrationinstance-inventory-sync
  /api/woo-commerce/{integrationInstance}/inventory/sync-progress/{trackedJobLogId}:
    get:
      tags:
      - WooCommerce
      summary: Get Inventory Sync Progress
      description: 'Poll the progress of an inventory sync job using the `tracked_job_log_id`
        returned when the job was queued. The response includes the job status, item
        counts, and completion percentage.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Route name: woo-commerce.inventory.sync-progress'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: WooCommerce integration instance ID
        example: '1'
      - name: trackedJobLogId
        in: path
        schema:
          type: integer
        required: true
        description: Tracked job log ID returned when the job was queued
        example: '5120'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      job_type:
                        type: string
                      queue:
                        type: string
                      job_name:
                        type: string
                      status:
                        type: string
                      related_model:
                        type: object
                        properties:
                          id:
                            type: integer
                          type:
                            type: string
                            nullable: true
                          reference:
                            type: string
                            nullable: true
                      related_model_reference:
                        type: string
                        nullable: true
                      messages:
                        type: array
                      attempted_at:
                        type: string
                      completed_at:
                        type: string
                        nullable: true
                      duration:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      results:
                        type: string
                        nullable: true
                      total_items:
                        type: integer
                      processed_items:
                        type: integer
                      progress_percentage:
                        type: integer
                      progress_mode:
                        type: string
                      stages:
                        type: string
                        nullable: true
                example:
                  data:
                    id: 5120
                    job_type: integration
                    queue: serial
                    job_name: WooCommerce Inventory Sync
                    status: in_progress
                    related_model:
                      id: 1
                      type: null
                      reference: null
                    related_model_reference: null
                    messages: []
                    attempted_at: '2026-06-20T04:00:01.000000Z'
                    completed_at: null
                    duration: null
                    created_at: '2026-06-20T04:00:00.000000Z'
                    updated_at: '2026-06-20T04:01:12.000000Z'
                    results: null
                    total_items: 480
                    processed_items: 120
                    progress_percentage: 25
                    progress_mode: batch
                    stages: null
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Record not found
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-woo-commerce-integrationinstance-inventory-sync-progress-trackedjoblogid
  /api/woo-commerce/{integrationInstance}/inventory/fetch-live:
    post:
      tags:
      - WooCommerce
      summary: Fetch Live Inventory
      description: 'Start a background job that downloads the current stock quantities
        from the WooCommerce store into the local comparison cache, so the comparison
        reflects the latest store-side values.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        The job runs asynchronously. Use the returned `tracked_job_log_id` with the
        live-fetch progress endpoint to poll for completion.


        Route name: woo-commerce.inventory.fetch-live'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties: {}
              example: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: WooCommerce integration instance ID
        example: '1'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  data:
                    type: object
                    properties:
                      tracked_job_log_id:
                        type: integer
                example:
                  message: Fetch live inventory job has been queued
                  data:
                    tracked_job_log_id: 5122
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-woo-commerce-integrationinstance-inventory-fetch-live
  /api/woo-commerce/{integrationInstance}/inventory/fetch-live-progress/{trackedJobLogId}:
    get:
      tags:
      - WooCommerce
      summary: Get Live Inventory Fetch Progress
      description: 'Poll the progress of a live inventory fetch job using the `tracked_job_log_id`
        returned when the job was queued. The response includes the job status, item
        counts, and completion percentage.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Route name: woo-commerce.inventory.fetch-live-progress'
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: WooCommerce integration instance ID
        example: '1'
      - name: trackedJobLogId
        in: path
        schema:
          type: integer
        required: true
        description: Tracked job log ID returned when the job was queued
        example: '5120'
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      id:
                        type: integer
                      job_type:
                        type: string
                      queue:
                        type: string
                      job_name:
                        type: string
                      status:
                        type: string
                      related_model:
                        type: object
                        properties:
                          id:
                            type: integer
                          type:
                            type: string
                            nullable: true
                          reference:
                            type: string
                            nullable: true
                      related_model_reference:
                        type: string
                        nullable: true
                      messages:
                        type: array
                      attempted_at:
                        type: string
                      completed_at:
                        type: string
                        nullable: true
                      duration:
                        type: string
                        nullable: true
                      created_at:
                        type: string
                      updated_at:
                        type: string
                      results:
                        type: string
                        nullable: true
                      total_items:
                        type: integer
                      processed_items:
                        type: integer
                      progress_percentage:
                        type: integer
                      progress_mode:
                        type: string
                      stages:
                        type: string
                        nullable: true
                example:
                  data:
                    id: 5120
                    job_type: integration
                    queue: serial
                    job_name: WooCommerce Live Inventory Fetch
                    status: in_progress
                    related_model:
                      id: 1
                      type: null
                      reference: null
                    related_model_reference: null
                    messages: []
                    attempted_at: '2026-06-20T04:00:01.000000Z'
                    completed_at: null
                    duration: null
                    created_at: '2026-06-20T04:00:00.000000Z'
                    updated_at: '2026-06-20T04:01:12.000000Z'
                    results: null
                    total_items: 480
                    processed_items: 120
                    progress_percentage: 25
                    progress_mode: batch
                    stages: null
        '404':
          description: Not Found
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                example:
                  message: Record not found
        '429': *id001
        '401': *id002
        '403': *id003
      operationId: get-api-woo-commerce-integrationinstance-inventory-fetch-live-progress-trackedjoblogid
  /api/woo-commerce/{id}/webhooks/configurations:
    get:
      tags:
      - WooCommerce
      summary: Get Webhook Configurations
      description: 'Get all webhook configurations for the integration instance.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        Returns the registration status (enabled/disabled) for each WooCommerce webhook
        topic.'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
      operationId: get-api-woo-commerce-id-webhooks-configurations
  /api/woo-commerce/{integrationInstance}/webhooks/configurations/{topic}/enable:
    post:
      tags:
      - WooCommerce
      summary: Enable Webhook
      description: 'Enable a webhook for a specific WooCommerce topic. The webhook
        is registered on the WooCommerce store so the store notifies SKU.io when the
        topic fires. Enabling a webhook never deletes or resets existing synced data.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        The topic in the URL uses triple-dashes (---) in place of dots to be URL-safe.

        Examples:

        - order.created -> order---created

        - order.updated -> order---updated

        - product.created -> product---created

        - product.updated -> product---updated


        Route name: woo-commerce.webhooks.configurations.enable'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: WooCommerce integration instance ID
        example: '1'
      - name: topic
        in: path
        schema:
          type: string
        required: true
        description: 'Webhook topic with dots encoded as triple dashes: order.created
          -> order---created, order.updated -> order---updated, product.created ->
          product---created, product.updated -> product---updated.'
        example: order---created
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      success:
                        type: boolean
                      message:
                        type: string
                      topic:
                        type: string
                      wc_webhook_id:
                        type: string
                  message:
                    type: string
                  status:
                    type: string
                example:
                  data:
                    success: true
                    message: Webhook enabled successfully
                    topic: order.created
                    wc_webhook_id: '812'
                  message: Webhook enabled successfully
                  status: Success
        '500':
          description: Internal Server Error
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                  message:
                    type: string
                example:
                  success: false
                  message: WooCommerce did not return a webhook ID
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-woo-commerce-integrationinstance-webhooks-configurations-topic-enable
  /api/woo-commerce/{integrationInstance}/webhooks/configurations/{topic}/disable:
    post:
      tags:
      - WooCommerce
      summary: Disable Webhook
      description: 'Disable a webhook for a specific WooCommerce topic. The webhook
        is deleted from the WooCommerce store, so the store stops notifying SKU.io
        for that topic. Previously synced data is unaffected.


        :::info[Authorization]

        Any valid API token can call this endpoint — no specific scope required. [Manage
        tokens](https://app.sku.io/settings/api).

        :::


        The topic in the URL uses triple-dashes (---) in place of dots. See Enable
        Webhook for the encoding pattern.


        Route name: woo-commerce.webhooks.configurations.disable'
      requestBody:
        content: {}
      parameters:
      - name: integrationInstance
        in: path
        schema:
          type: integer
        required: true
        description: WooCommerce integration instance ID
        example: '1'
      - name: topic
        in: path
        schema:
          type: string
        required: true
        description: 'Webhook topic with dots encoded as triple dashes: order.created
          -> order---created, order.updated -> order---updated, product.created ->
          product---created, product.updated -> product---updated.'
        example: order---created
      responses:
        '200':
          description: OK
          headers:
            Content-Type:
              schema:
                type: string
                example: application/json
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      success:
                        type: boolean
                      message:
                        type: string
                      topic:
                        type: string
                  message:
                    type: string
                  status:
                    type: string
                example:
                  data:
                    success: true
                    message: Webhook disabled successfully
                    topic: order.created
                  message: Webhook disabled successfully
                  status: Success
        '429': *id001
        '401': *id002
        '403': *id003
        '404': *id004
        '422': *id005
      operationId: post-api-woo-commerce-integrationinstance-webhooks-configurations-topic-disable
  /api/webhooks/wc-webhook/{id}/order.created:
    post:
      tags:
      - WooCommerce
      summary: Order Created Webhook
      description: 'Inbound webhook endpoint called by WooCommerce when a new order
        is created.


        Requires WooCommerce webhook signature verification (VerifyWooCommerceWebhook
        middleware).

        Dispatches a background job for async processing.


        Route name: woocommerce.order_created'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                id:
                  type: integer
                status:
                  type: string
                total:
                  type: string
                currency:
                  type: string
                line_items:
                  type: array
                  items:
                    type: object
                    properties:
                      id:
                        type: integer
                      product_id:
                        type: integer
                      quantity:
                        type: integer
                      price:
                        type: string
                billing:
                  type: object
                  properties:
                    first_name:
                      type: string
                    last_name:
                      type: string
                    email:
                      type: string
              example:
                id: 1234
                status: processing
                total: '49.99'
                currency: USD
                line_items:
                - id: 1
                  product_id: 500
                  quantity: 2
                  price: '24.99'
                billing:
                  first_name: John
                  last_name: Doe
                  email: john.doe@example.com
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      - name: X-WC-Webhook-Signature
        in: header
        schema:
          type: string
        description: WooCommerce HMAC-SHA256 webhook signature for payload verification.
        example: '{{wc_webhook_signature}}'
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '404': *id004
        '422': *id005
      security: []
      operationId: post-api-webhooks-wc-webhook-id-order-created
  /api/webhooks/wc-webhook/{id}/order.updated:
    post:
      tags:
      - WooCommerce
      summary: Order Updated Webhook
      description: 'Inbound webhook endpoint called by WooCommerce when an order is
        updated.


        Route name: woocommerce.order_updated'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                id:
                  type: integer
                status:
                  type: string
                total:
                  type: string
              example:
                id: 1234
                status: completed
                total: '49.99'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      - name: X-WC-Webhook-Signature
        in: header
        schema:
          type: string
        example: '{{wc_webhook_signature}}'
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '404': *id004
        '422': *id005
      security: []
      operationId: post-api-webhooks-wc-webhook-id-order-updated
  /api/webhooks/wc-webhook/{id}/order.deleted:
    post:
      tags:
      - WooCommerce
      summary: Order Deleted Webhook
      description: 'Inbound webhook endpoint called by WooCommerce when an order is
        deleted.


        Route name: woocommerce.order_deleted'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                id:
                  type: integer
                status:
                  type: string
              example:
                id: 1234
                status: trash
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      - name: X-WC-Webhook-Signature
        in: header
        schema:
          type: string
        example: '{{wc_webhook_signature}}'
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '404': *id004
        '422': *id005
      security: []
      operationId: post-api-webhooks-wc-webhook-id-order-deleted
  /api/webhooks/wc-webhook/{id}/product.created:
    post:
      tags:
      - WooCommerce
      summary: Product Created Webhook
      description: 'Inbound webhook endpoint called by WooCommerce when a product
        is created.


        Route name: woocommerce.product_created'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                id:
                  type: integer
                name:
                  type: string
                sku:
                  type: string
                status:
                  type: string
                type:
                  type: string
                price:
                  type: string
              example:
                id: 500
                name: Sample Product
                sku: SKU-001
                status: publish
                type: simple
                price: '29.99'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      - name: X-WC-Webhook-Signature
        in: header
        schema:
          type: string
        example: '{{wc_webhook_signature}}'
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '404': *id004
        '422': *id005
      security: []
      operationId: post-api-webhooks-wc-webhook-id-product-created
  /api/webhooks/wc-webhook/{id}/product.updated:
    post:
      tags:
      - WooCommerce
      summary: Product Updated Webhook
      description: 'Inbound webhook endpoint called by WooCommerce when a product
        is updated.


        Route name: woocommerce.product_updated'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                id:
                  type: integer
                name:
                  type: string
                sku:
                  type: string
                price:
                  type: string
              example:
                id: 500
                name: Updated Product
                sku: SKU-001
                price: '34.99'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      - name: X-WC-Webhook-Signature
        in: header
        schema:
          type: string
        example: '{{wc_webhook_signature}}'
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '404': *id004
        '422': *id005
      security: []
      operationId: post-api-webhooks-wc-webhook-id-product-updated
  /api/webhooks/wc-webhook/{id}/product.deleted:
    post:
      tags:
      - WooCommerce
      summary: Product Deleted Webhook
      description: 'Inbound webhook endpoint called by WooCommerce when a product
        is deleted.


        Route name: woocommerce.product_deleted'
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                id:
                  type: integer
                name:
                  type: string
                sku:
                  type: string
                status:
                  type: string
              example:
                id: 500
                name: Deleted Product
                sku: SKU-001
                status: trash
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
        description: The id identifier
      - name: X-WC-Webhook-Signature
        in: header
        schema:
          type: string
        example: '{{wc_webhook_signature}}'
      responses:
        '200':
          description: Successful response
          content:
            application/json: {}
        '429': *id001
        '404': *id004
        '422': *id005
      security: []
      operationId: post-api-webhooks-wc-webhook-id-product-deleted
x-tagGroups:
- name: Core API
  tags:
  - Accounting
  - Financials
  - Bills
  - Amortization Schedules
  - Financial Line Types
  - Cost Categories
  - Payment Terms
  - Ledger (Accounting v2)
  - Configuration
  - FIFO Layers
  - Customers
  - Suppliers
  - Warehouses
  - Inventory Adjustments
  - Inventory Movements
  - Listings
  - Sales Credits
  - Reporting
  - Product Listings (V2)
  - PDF Templates
  - Card on File
  - Channel Partners
  - Sales Channel Listing Profiles
  - Sub Sales Channels
  - Sales Reps
  - Custom Report Builder
  - Gift Cards
  - House Accounts
  - Export
  - Data Feeds
  - Inventory Intelligence
  - Inventory Expiry & Shelf-Life
  - Odoo 3PL
  - Google Sheets
  - Airtable
  - Products
  - Organization
  - Pricing
  - Custom Fields
  - CSV Templates
  - Product Listings
  - Inventory
  - Adjustments & Transfers
  - Stock Takes
  - Assemblies
  - Initial Inventory
  - Costing
  - Product Pro Forma
  - Merchandise Planning
  - Serial Numbers
  - Landed Cost Breakdown
  - Loyalty
  - OAuth
  - Connection
  - Transactions
  - Orders
  - Shipments
  - Inventory Sources (MSI)
  - Warehouse Mappings
  - Shipping Method Mappings
  - Payment Method Mappings
  - BOMs
  - Manufacturing Orders
  - MO Operations
  - Outsourced Production
  - Simple Assembly
  - Work Centers
  - Contractors
  - Units of Measure
  - Scheduler
  - Demand Suggestions
  - Lots
  - Lot Genealogy
  - MRP Planning
  - Sales Orders
  - Sales Order Lines
  - Fulfillments
  - Merged Shipments
  - Channel Refunds
  - Returns & RMAs
  - Discount Codes
  - Purchase Orders
  - Purchase Invoices
  - Vendor Returns
  - Purchase Receipts
  - Purchase Order Shipments
  - Inbound Shipments
  - Sales Order OCR
  - Purchase Invoice OCR
  - Landed Cost Invoice OCR
  - Document Inbox
  - Documents
  - Fulfillment Orders
  - Line Decorations
  - Decoration Orders
  - Artwork
  - Decoration Cost Rules
  - Decoration Methods
  - Decoration Placements
  - Quotes
  - POS / Register
  - Pick Lists
  - Movement Composer
  - Product Import
  - Vendor Credits
  - Vendor Deposits
- name: Integrations
  tags:
  - 17TRACK
  - BigCommerce
  - Stores
  - Sales Channels
  - Store Email Templates
  - Sales Channel Product Templates
  - eBay
  - Faire
  - Amazon
  - Shopify
  - WooCommerce
  - Walmart
  - Magento
  - TikTok Shop
  - Temu
  - Square
  - Magento 1
  - Shipfusion
  - ShipHero
  - ShipStation
  - Veracore
  - 3PL
  - Trackstar
  - Starshipit
  - API Shipping Provider
  - Shippit
  - QuickBooks Online
  - Xero
  - Stripe
  - Google Calendar
- name: Platform
  tags:
  - Authentication
  - Users
  - Roles & Permissions
  - Feature Flags
  - Alerts
  - Jobs & Logs
  - Integration Instances
  - Misc
  - Data Imports
  - Settings
  - Tracked Job Logs
  - Reference Data (Read-Only)
  - Dashboard
  - Tags
  - Subscriptions
  - UI Utilities
  - Horizon
  - Workflows
  - Workflow Actions
  - Workflow Executions
  - Workflow Node Types
  - Workflow Templates
  - Workflow Credentials
  - Report Templates
  - Webhooks
